@ -0,0 +1,129 @@ | |||
const htmlmin = require('html-minifier'); | |||
const dateFns = require('date-fns'); | |||
const lazyImagesPlugin = require('eleventy-plugin-lazyimages'); | |||
const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight'); | |||
const i18n = require('eleventy-plugin-i18n'); | |||
const translations = require('./src/_data/i18n'); | |||
module.exports = function (eleventyConfig) { | |||
// PLUGINS ************************************************************** | |||
eleventyConfig.addPlugin(syntaxHighlight); | |||
// does not work with background images | |||
eleventyConfig.addPlugin(lazyImagesPlugin, { | |||
transformImgPath: (imgPath) => { | |||
if (imgPath.startsWith('http://') || imgPath.startsWith('https://')) { | |||
// Handle remote file | |||
return imgPath; | |||
} else { | |||
return `./src/${imgPath}`; | |||
} | |||
}, | |||
}); | |||
eleventyConfig.addPlugin(i18n, { | |||
translations, | |||
fallbackLocales: { | |||
'*': 'en-US', | |||
}, | |||
}); | |||
eleventyConfig.setEjsOptions({ | |||
rmWhitespace: true, | |||
context: { | |||
dateFns, | |||
}, | |||
}); | |||
eleventyConfig.setBrowserSyncConfig({ | |||
files: './_site/assets/styles/main.css', | |||
}); | |||
// use this to redirect to en-US | |||
// eleventyConfig.setBrowserSyncConfig({ | |||
// files: './_site/assets/styles/main.css', | |||
// callbacks: { | |||
// ready: function (err, bs) { | |||
// bs.addMiddleware('*', (req, res) => { | |||
// if (req.url === '/') { | |||
// res.writeHead(302, { | |||
// location: '/en-US/' | |||
// }); | |||
// res.end(); | |||
// } | |||
// }); | |||
// } | |||
// } | |||
// }); | |||
eleventyConfig.addPassthroughCopy('styles/fonts'); | |||
eleventyConfig.addPassthroughCopy('src/assets/images/**/*.png'); | |||
eleventyConfig.addPassthroughCopy('src/assets/images/**/*.svg'); | |||
eleventyConfig.addPassthroughCopy('src/assets/images/**/*.jpg'); | |||
eleventyConfig.addPassthroughCopy('node_modules/@glidejs/glide/dist'); | |||
eleventyConfig.addPassthroughCopy('node_modules/blueimp-md5/js'); | |||
eleventyConfig.addTransform('htmlmin', (content, outputPath) => { | |||
if (outputPath.endsWith('.html')) { | |||
const minified = htmlmin.minify(content, { | |||
useShortDoctype: true, | |||
removeComments: true, | |||
collapseWhitespace: true, | |||
minifyJS: true, | |||
}); | |||
return minified; | |||
} | |||
return content; | |||
}); | |||
// Import fast-glob package | |||
const fg = require('fast-glob'); | |||
// Run search for images in /screenshots | |||
const galleryThumbnails = fg.sync(['**/images/screenshots/*resized*', '!**/_site']); | |||
const galleryImagesAll = fg.sync(['**/images/screenshots/*', '!**/_site']); | |||
//Create collection of screenshots | |||
eleventyConfig.addCollection('screenshotThumbnails', function (collection) { | |||
return galleryThumbnails.map((url) => { | |||
return url.replace('src/', ''); | |||
}); | |||
}); | |||
//Create collection of screenshots | |||
eleventyConfig.addCollection('screenshotHires', function (collection) { | |||
return galleryImagesAll | |||
.filter((url) => !url.includes('resized')) | |||
.map((url) => { | |||
return url.replace('src/', ''); | |||
}); | |||
}); | |||
return { | |||
passthroughFileCopy: true, | |||
dir: { input: 'src', output: '_site', data: '_data' }, | |||
}; | |||
// return { | |||
// templateFormats: ['md', 'njk', 'html', 'liquid'], | |||
// // If your site lives in a different subdirectory, change this. | |||
// // Leading or trailing slashes are all normalized away, so don’t worry about it. | |||
// // If you don’t have a subdirectory, use "" or "/" (they do the same thing) | |||
// // This is only used for URLs (it does not affect your file structure) | |||
// pathPrefix: '/', | |||
// markdownTemplateEngine: 'liquid', | |||
// htmlTemplateEngine: 'njk', | |||
// dataTemplateEngine: 'njk', | |||
// passthroughFileCopy: true, | |||
// dir: { | |||
// input: '.', | |||
// includes: '_includes', | |||
// data: '_data', | |||
// output: 'docs', | |||
// }, | |||
// }; | |||
}; |
@ -0,0 +1,2 @@ | |||
node_modules | |||
_site |
@ -0,0 +1,3 @@ | |||
{ | |||
"extends": ["airbnb-base"] | |||
} |
@ -0,0 +1 @@ | |||
custom: ['https://creativedesignsguru.com/category/eleventy/', 'https://www.buymeacoffee.com/ixartz'] |
@ -0,0 +1,17 @@ | |||
# Dependencies | |||
/node_modules | |||
# Output directories | |||
/_site | |||
# Generated file | |||
/src/_includes/layouts/webpack.ejs | |||
.lazyimages.json | |||
# Misc | |||
.DS_Store | |||
Thumbs.db | |||
npm-debug.log* | |||
yarn-debug.log* | |||
yarn-error.log* | |||
*.zip |
@ -0,0 +1,2 @@ | |||
node_modules | |||
_site |
@ -0,0 +1,4 @@ | |||
{ | |||
"printWidth": 100, | |||
"singleQuote": true | |||
} |
@ -0,0 +1,21 @@ | |||
MIT License | |||
Copyright (c) 2020 Rem W. | |||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||
of this software and associated documentation files (the "Software"), to deal | |||
in the Software without restriction, including without limitation the rights | |||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
copies of the Software, and to permit persons to whom the Software is | |||
furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all | |||
copies or substantial portions of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
SOFTWARE. |
@ -0,0 +1,149 @@ | |||
# Eleventy Starter Boilerplate | |||
<p align="center"> | |||
<a href="https://creativedesignsguru.com/demo/Eleventy-Starter-Boilerplate/eleventy-starter-boilerplate-presentation/"><img src="public/assets/images/eleventy-js-starter-boilerplate.png?raw=true" alt="Eleventy starter banner"></a> | |||
</p> | |||
🚀 Eleventy Starter Boilerplate is production-ready with SEO-friendly for quickly starting a blog. ⚡️ Built with [Eleventy](https://www.11ty.dev), [ESLint](https://eslint.org), [Prettier](https://prettier.io), [Webpack](https://webpack.js.org), [PostCSS](https://postcss.org), [Tailwind CSS](https://tailwindcss.com) and [Netlify CMS](https://www.netlifycms.org) (optional). | |||
Clone this project and use it to create your own [Eleventy](https://www.11ty.dev) blog. You can check a [Eleventy templates demo](https://creativedesignsguru.com/demo/Eleventy-Starter-Boilerplate/eleventy-starter-boilerplate-presentation/). | |||
### Features | |||
Production-ready in mind: | |||
- 🔥 [11ty](https://www.11ty.dev) for Static Site Generator | |||
- 🎨 Integrate with [Tailwind CSS](https://tailwindcss.com) (with [PurgeCSS](https://purgecss.com), remove unused CSS) | |||
- 💅 [PostCSS](https://postcss.org) for processing [Tailwind CSS](https://tailwindcss.com) | |||
- ⚡️ Lazy load images with [lazysizes](https://github.com/aFarkas/lazysizes) | |||
- ✨ Compress image with [Imagemin](https://github.com/imagemin/imagemin) | |||
- 🎈 Syntax Highlighting with [Prism.js](https://prismjs.com) | |||
- ☕ Minify HTML & CSS with [HTMLMinifier](https://www.npmjs.com/package/html-minifier) and [cssnano](https://cssnano.co) | |||
- ✏️ Linter with [ESLint](https://eslint.org) | |||
- 🛠 Code Formatter with [Prettier](https://prettier.io) | |||
- 💨 Live reload | |||
- 📦 Module Bundler with [Webpack](https://webpack.js.org) | |||
- 🦊 Templating with [EJS](https://ejs.co) | |||
- 🤖 SEO metadata and [Open Graph](https://ogp.me/) tags | |||
- ⚙️ [JSON-LD](https://developers.google.com/search/docs/guides/intro-structured-data) for richer indexing | |||
- 🗺 Sitemap.xml | |||
- ⚠️ 404 page | |||
- 📖 Pagination | |||
- ✅ Cache busting | |||
- 💯 Maximize lighthouse score | |||
- 🌈 Include a FREE minimalist blog theme | |||
- 🗒 Netlify CMS (optional) | |||
### Philosophy | |||
- Minimal code (HTML, CSS & JS). Add what you need | |||
- SEO-friendly | |||
- 🚀 Production-ready | |||
### Requirements | |||
- Node.js and npm | |||
### Premium Themes ([Eleventy Themes](https://creativedesignsguru.com/category/eleventy/)) | |||
| [Blue Dark Eleventy Theme](https://creativedesignsguru.com/blue-dark-eleventy-theme/) | [Blue Eclatant Eleventy Theme](https://creativedesignsguru.com/blue-eclatant-eleventy-theme/) | | |||
| --- | --- | | |||
| [![Blue Dark Eleventy Theme premium](https://creativedesignsguru.com/assets/images/themes/blue-dark-mode-eleventy-theme-homepage-xs.png)](https://creativedesignsguru.com/blue-dark-eleventy-theme/) | [![Blue Eclatant Eleventy Theme premium](https://creativedesignsguru.com/assets/images/themes/eclatant-blue-eleventy-theme-homepage-xs.png)](https://creativedesignsguru.com/blue-eclatant-eleventy-theme/) | | |||
| [Blue Modern Eleventy Theme](https://creativedesignsguru.com/blue-modern-eleventy-theme/) | [Blue Minimalist Eleventy Theme](https://creativedesignsguru.com/blue-minimalist-eleventy-theme/) | | |||
| --- | --- | | |||
| [![Blue Modern Eleventy Theme premium](https://creativedesignsguru.com/assets/images/themes/modern-blue-eleventy-theme-homepage-xs.png)](https://creativedesignsguru.com/blue-modern-eleventy-theme/) | [![Blue Minimalist Eleventy Theme premium](https://creativedesignsguru.com/assets/images/themes/minimalist-blue-eleventy-theme-homepage-xs.png)](https://creativedesignsguru.com/blue-minimalist-eleventy-theme/) | | |||
### Getting started | |||
Run the following command on your local environment: | |||
``` | |||
git clone --depth=1 https://github.com/ixartz/Eleventy-Starter-Boilerplate.git my-project-name | |||
cd my-project-name | |||
npm install | |||
``` | |||
Then, you can run locally in development mode with live reload: | |||
``` | |||
npm run dev | |||
``` | |||
Open http://localhost:8080 with your favorite browser to see your blog. | |||
### Project structure | |||
``` | |||
. | |||
├── public # Static files | |||
│ └── assets | |||
│ └── images # Images not needed by Webpack | |||
└── src | |||
├── _data # Eleventy data folder | |||
├── _includes | |||
│ └── layouts # HTML layout files | |||
├── assets # Assets folder that needs to be processed by Webpack | |||
│ ├── images | |||
│ │ └── posts # Images used in your blog posts (will be compressed by Webpack) | |||
│ └── styles # Your blog CSS files | |||
└── posts # Your blog posts | |||
``` | |||
### Customization | |||
You can easily configure Eleventy Starter Boilerplate. Please change the following file: | |||
- `public/assets/images/logo.png`: your blog logo | |||
- `public/apple-touch-icon.png`, `public/favicon.ico`, `public/favicon-16x16.png` and `public/favicon-32x32.png`: your blog favicon, you can generate from https://favicon.io/favicon-converter/ | |||
- `src/_data/site.json`: your blog configuration | |||
- `src/_includes/layouts`: your blog HTML layout | |||
- `src/assets/styles/main.css`: your blog CSS file using Tailwind CSS | |||
### Deploy to production | |||
You can see the results locally in production mode with: | |||
``` | |||
npm run serve | |||
``` | |||
The generated HTML and CSS files are minified. It will also removed unused CSS from [Tailwind CSS](https://tailwindcss.com). | |||
You can create an optimized production build with: | |||
``` | |||
npm run build | |||
``` | |||
Now, your blog is ready to be deployed. All generated files are located at `_site` folder, which you can deploy with any hosting service. | |||
### Deploy to Netlify | |||
Clone this repository on own GitHub account and deploy to Netlify: | |||
[![Netlify Deploy button](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/ixartz/Eleventy-Starter-Boilerplate&stack=cms) | |||
### Remove Netlify files and Netlify CMS | |||
If you don't use Netlify, you can easily remove all Netlify related files: | |||
- `public/admin`, the entier folder | |||
- `src/_includes/layouts/base.ejs`, the loaded script `netlify-identity-widget.js` and the inline script `if (window.netlifyIdentity) { ...` | |||
- `netlify.toml`, the entire file | |||
### Contributions | |||
Everyone is welcome to contribute to this project. Feel free to open an issue if you have question or found a bug. | |||
### License | |||
Licensed under the MIT License, Copyright © 2020 | |||
See [LICENSE](LICENSE) for more information. | |||
--- | |||
Made with ♥ by [CreativeDesignsGuru](https://creativedesignsguru.com) | |||
[![Sponsor Next JS Boilerplate](https://cdn.buymeacoffee.com/buttons/default-red.png)](https://www.buymeacoffee.com/ixartz) |
@ -0,0 +1,3 @@ | |||
[build] | |||
publish = "_site" | |||
command = "npm run build" |
@ -0,0 +1,75 @@ | |||
{ | |||
"name": "graphicvizion", | |||
"version": "1.0.0", | |||
"description": "Visual Anatomy 3D", | |||
"scripts": { | |||
"build-dev:webpack": "webpack", | |||
"watch:webpack": "webpack --watch", | |||
"watch:eleventy": "cross-env ELEVENTY_ENV=development eleventy --serve", | |||
"dev": "npm-run-all clean build-dev:webpack --parallel watch:*", | |||
"build:webpack": "cross-env NODE_ENV=production webpack --mode production", | |||
"build:eleventy": "cross-env ELEVENTY_ENV=production eleventy", | |||
"build": "run-s clean build:*", | |||
"serve:local": "serve _site", | |||
"serve": "run-s build serve:local", | |||
"clean": "rimraf _site", | |||
"format:js": "prettier '**/*.js' --write && eslint '**/*.js' --fix", | |||
"format:json": "prettier '**/*.json' --write", | |||
"format": "run-s format:*", | |||
"lint": "eslint --ext .js ." | |||
}, | |||
"license": "ISC", | |||
"devDependencies": { | |||
"@11ty/eleventy": "^0.12.1", | |||
"@11ty/eleventy-plugin-syntaxhighlight": "^3.1.1", | |||
"autoprefixer": "^10.2.6", | |||
"copy-webpack-plugin": "^9.0.0", | |||
"cross-env": "^7.0.3", | |||
"css-loader": "^5.2.6", | |||
"cssnano": "^5.0.4", | |||
"date-fns": "^2.21.3", | |||
"eleventy-plugin-lazyimages": "^2.1.0", | |||
"eslint": "^7.27.0", | |||
"eslint-config-airbnb-base": "^14.2.1", | |||
"eslint-plugin-import": "^2.23.3", | |||
"file-loader": "^6.2.0", | |||
"glob": "^7.1.7", | |||
"html-minifier": "^4.0.0", | |||
"html-webpack-plugin": "^5.3.1", | |||
"husky": "^4.3.8", | |||
"image-webpack-loader": "^7.0.1", | |||
"lint-staged": "^11.0.0", | |||
"mini-css-extract-plugin": "^1.6.0", | |||
"npm-run-all": "^4.1.5", | |||
"postcss-loader": "^5.3.0", | |||
"prettier": "^2.3.0", | |||
"rimraf": "^3.0.2", | |||
"serve": "^11.3.2", | |||
"svg-url-loader": "^7.1.1", | |||
"tailwindcss": "^2.1.2", | |||
"url-loader": "^4.1.1", | |||
"webpack": "^5.37.1", | |||
"webpack-cli": "^4.7.0" | |||
}, | |||
"husky": { | |||
"hooks": { | |||
"pre-commit": "lint-staged" | |||
} | |||
}, | |||
"lint-staged": { | |||
"*.js": [ | |||
"prettier --write", | |||
"eslint --fix", | |||
"eslint" | |||
], | |||
"*.json": [ | |||
"prettier --write" | |||
] | |||
}, | |||
"dependencies": { | |||
"@glidejs/glide": "^3.4.1", | |||
"blueimp-md5": "^2.19.0", | |||
"eleventy-plugin-i18n": "^0.1.3", | |||
"fast-glob": "^3.2.7" | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
/* eslint-disable import/no-extraneous-dependencies, global-require */ | |||
const plugins = [require('tailwindcss'), require('autoprefixer')]; | |||
if (process.env.NODE_ENV === 'production') { | |||
plugins.push( | |||
require('cssnano')({ | |||
preset: [ | |||
'default', | |||
{ | |||
discardComments: { | |||
removeAll: true, | |||
}, | |||
}, | |||
], | |||
}), | |||
); | |||
} | |||
module.exports = { plugins }; |
@ -0,0 +1,39 @@ | |||
backend: | |||
name: git-gateway | |||
branch: master | |||
# publish_mode: editorial_workflow | |||
media_folder: 'src/assets/images' # Media files will be stored in the repo under src/assets/images/posts | |||
public_folder: '/assets/images' # The src attribute for uploaded media will begin with assets/images/posts | |||
# media_folder: 'src/assets/images/posts' # Media files will be stored in the repo under src/assets/images/posts | |||
# public_folder: '/assets/images/posts' # The src attribute for uploaded media will begin with assets/images/posts | |||
collections: | |||
- name: "blog" # Used in routes, e.g., /admin/collections/blog | |||
label: "Blog" # Used in the UI | |||
folder: "src/posts" # The path to the folder where the documents are stored | |||
create: true # Allow users to create new documents in this collection | |||
slug: "{{year}}-{{month}}-{{day}}-{{slug}}" # Filename template, e.g., YYYY-MM-DD-title.md | |||
editor: | |||
preview: false # Disable the editor preview and use instead 'preview links' | |||
fields: # The fields for each document, usually in front matter | |||
- { name: "title", label: "Title" } | |||
- { name: "description", label: "Description" } | |||
- { name: "date", label: "Date", widget: "datetime" } | |||
- { name: "body", label: "Body", widget: "markdown" } | |||
- name: "config" | |||
label: "Configuration" | |||
editor: | |||
preview: false | |||
files: | |||
- name: "global" | |||
label: "Global" | |||
file: "src/_data/site.json" | |||
fields: | |||
- { name: "site_name", label: "Site name" } | |||
- { name: "title", label: "Site title" } | |||
- { name: "description", label: "Site description" } | |||
- { name: "url", label: "Site url" } | |||
- { name: "locale", label: "Language" } | |||
- { name: "author", label: "Author" } |
@ -0,0 +1,14 @@ | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta charset="utf-8" /> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
<title>Content Manager</title> | |||
</head> | |||
<body> | |||
<!-- Include the script that builds the page and powers Netlify CMS --> | |||
<script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script> | |||
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script> | |||
</body> | |||
</html> |
@ -0,0 +1,10 @@ | |||
--- | |||
title: 404 - Page not found | |||
description: Page not found | |||
permalink: 404.html | |||
eleventyExcludeFromCollections: true | |||
--- | |||
# 404 | |||
Page not found |
@ -0,0 +1,21 @@ | |||
const packageJson = require('../../package.json'); | |||
module.exports = () => { | |||
const now = new Date(); | |||
const { timeZone } = Intl.DateTimeFormat().resolvedOptions(); | |||
const buildDate = Intl.DateTimeFormat('fr-CA', { | |||
year: 'numeric', | |||
month: '2-digit', | |||
day: '2-digit', | |||
}).format(now); | |||
const buildTime = Intl.DateTimeFormat('nl-NL', { hour: '2-digit', minute: '2-digit' }).format( | |||
now, | |||
); | |||
return { | |||
version: packageJson.version, | |||
time: { | |||
raw: now.toISOString(), | |||
formatted: `${buildDate} ${buildTime} ${timeZone}`, | |||
}, | |||
}; | |||
}; |
@ -0,0 +1,6 @@ | |||
module.exports = { | |||
hello: { | |||
'en-US': 'Hello', | |||
'es-NL': 'Hola' | |||
} | |||
}; |
@ -0,0 +1,4 @@ | |||
// Set default layout | |||
// https://github.com/11ty/eleventy/issues/380#issuecomment-568033456 | |||
module.exports = 'layouts/base.ejs'; |
@ -0,0 +1,23 @@ | |||
module.exports = [ | |||
{ | |||
name: 'Andre Taris', | |||
quote: 'I am a designer and researcher and as part of TU Delft’s medical design major you get to do a surgical level anatomy class at Erasmus hospital. A world first and leader in this type of collab this involved full dissection training of us medical designers and common procedure run throughs. Laparoscopic training and this is more thorough than most doctors gets hands on. This app aids at that level', | |||
stars: 5, | |||
site: 'App Store', | |||
link: '' | |||
}, | |||
{ | |||
name: 'Anthony Horsley', | |||
quote: 'I\'m homeschooled and this is awesome!', | |||
stars: 5, | |||
site: 'App Store', | |||
link: '' | |||
}, | |||
{ | |||
name: 'Tom van Vugt', | |||
quote: 'As a physical therapist this is one of the better apps out there for learning human anatomy, I tried multiple, but this one is easy to use and runs smoothly with lots of options.', | |||
stars: 5, | |||
site: 'App Store', | |||
link: '' | |||
} | |||
] |
@ -0,0 +1,11 @@ | |||
module.exports = [ | |||
//{ slug: 'home', name: 'Home' }, | |||
{ slug: 'info', name: 'Info' }, | |||
{ slug: 'screenshots', name: 'Screenshots' }, | |||
{ slug: 'systems', name: 'Systems' }, | |||
{ slug: 'pricing', name: 'Pricing' }, | |||
{ slug: 'download', name: 'Download' }, | |||
{ slug: 'reviews', name: 'Reviews' }, | |||
{ slug: 'contact', name: 'Contact' } | |||
] |
@ -0,0 +1,8 @@ | |||
{ | |||
"site_name": "Visual Anatomy 3D", | |||
"title": "Visual Anatomy 3D", | |||
"description": "Learn human anatomy quickly and easily by zooming, panning, hiding layers and interacting in real time.", | |||
"url": "https://visualanatomy3d.app/", | |||
"locale": "en", | |||
"author": "Spencer Flagg" | |||
} |
@ -0,0 +1,13 @@ | |||
module.exports = [ | |||
{ slug: 'skeletal', name: 'Skeletal', status: 'free', order: 1 }, | |||
{ slug: 'ligamentous', name: 'Ligamentous', status: 'free', order: 2 }, | |||
{ slug: 'muscular', name: 'Muscular', status: 'pro', order: 3 }, | |||
{ slug: 'digestive', name: 'Digestive', status: 'pro', order: 4 }, | |||
{ slug: 'respiratory', name: 'Respiratory', status: 'pro', order: 5 }, | |||
{ slug: 'urogenital', name: 'Urogenital', status: 'pro', order: 6 }, | |||
{ slug: 'endocrine', name: 'Endocrine', status: 'pro', order: 7 }, | |||
{ slug: 'circulatory', name: 'Circulatory', status: 'soon', order: 8 }, | |||
{ slug: 'nervous', name: 'Nervous', status: 'soon', order: 9 }, | |||
{ slug: 'lymphatic', name: 'Lymphatic', status: 'soon', order: 10 }, | |||
{ slug: 'integumentary', name: 'Integumentary', status: 'soon', order: 11 } | |||
] |
@ -0,0 +1,43 @@ | |||
<article class="blurb__wrapper"> | |||
<section> | |||
<p> | |||
<em>Complete</em> and <em>easy-to-use</em> virtual guide for learning, understanding, and visualizing the complexities of human anatomy in 3D. | |||
Includes information and images for each anatomical system and part, multiple options to interact with the <em>3D anatomy</em> models (hiding, fading, etc), and much more. | |||
</p> | |||
<p class="hide-on-mobile"> | |||
The <%= site.site_name %> app can be downloaded and tested for free, which contains the skeleton and ligaments, other anatomical systems can be purchased separately. | |||
The anatomy app is available on <em>most platforms</em> (android, iOS, windows and mac) and can be used on your phone, tablet or desktop pc. | |||
</p> | |||
</section> | |||
<section> | |||
<div class="before-and-after"> | |||
<div class='img background-img'></div> | |||
<div class='img foreground-img'></div> | |||
<input type="range" min="1" max="100" value="59" class="slider" name='slider' id="before-and-after__slider"> | |||
<div class='slider-button'></div> | |||
</div> | |||
</section> | |||
</article> | |||
<script> | |||
document.querySelector('#before-and-after__slider').addEventListener('input', (e) => { | |||
const sliderPos = e.target.value; | |||
// Update the width of the foreground image | |||
document.querySelector('.foreground-img').style.width = `${sliderPos}%`; | |||
// Update the position of the slider button | |||
document.querySelector('.slider-button').style.left = `calc(${sliderPos}% - 18px)`; | |||
}); | |||
</script> | |||
<style> | |||
.before-and-after .background-img { | |||
background-image: url('./assets/images/slider-1.png'); | |||
background-position-x: -1px; | |||
} | |||
.before-and-after .foreground-img { | |||
background-image: url('./assets/images/slider-2.png'); | |||
background-position-x: -1px; | |||
width: 59%; | |||
} | |||
</style> |
@ -0,0 +1,24 @@ | |||
<article class="contact__wrapper"> | |||
<header> | |||
<h1 id="contact">Contact Us</h1> | |||
</header> | |||
<section> | |||
<div class="form"> | |||
<input type="text" placeholder="your email address goes here" id="fromEmail"> | |||
<span class="alert form-alert" id="emailError">your email address isn't valid</span> | |||
<textarea placeholder="your message goes here" id="message"> | |||
</textarea> | |||
<button class="btn btn--contact" type="submit" id="contactSubmit">send <svg | |||
xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-send" width="32" height="32" | |||
viewBox="0 0 24 24" stroke-width="2" stroke="#ffffff" fill="none" stroke-linecap="round" | |||
stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> | |||
<line x1="10" y1="14" x2="21" y2="3" /> | |||
<path d="M21 3l-6.5 18a0.55 .55 0 0 1 -1 0l-3.5 -7l-7 -3.5a0.55 .55 0 0 1 0 -1l18 -6.5" /> | |||
</svg> | |||
</button> | |||
<span class="alert form-alert alert--failure" id="otherError">Something went wrong. Try us on <a href="https://twitter.com/graphicvizion" target="_blank" style="font-weight: 600; color: #eee; text-decoration: underline;">Twitter</a> instead.</span> | |||
<span class="alert form-alert alert--success" id="success">Thanks! We'll contact you shortly.</span> | |||
</div> | |||
</section> | |||
</article> |
@ -0,0 +1,45 @@ | |||
<article class="download__wrapper max-w-screen-lg"> | |||
<header> | |||
<h1 id="download"> | |||
download now | |||
</h1> | |||
</header> | |||
<section class="download__content"> | |||
<a class="platform__wrapper" href="https://apps.apple.com/il/app/visual-anatomy-3d-human/id1148048602" target="_blank"> | |||
<% include /store-icons/ios.svg %> | |||
<h2> | |||
iOS | |||
</h2> | |||
<div class="btn btn--store"> | |||
go to store | |||
</div> | |||
</a> | |||
<a class="platform__wrapper" href="https://play.google.com/store/apps/details?id=com.graphicvizion.visualAnatomyHumanFr" target="_blank"> | |||
<% include /store-icons/android.svg %> | |||
<h2> | |||
Android | |||
</h2> | |||
<div class="btn btn--store"> | |||
go to store | |||
</div> | |||
</a> | |||
<a class="platform__wrapper" href="https://apps.apple.com/il/app/visual-anatomy-3d-human/id1148048602" target="_blank"> | |||
<% include /store-icons/macos.svg %> | |||
<h2> | |||
macOS | |||
</h2> | |||
<div class="btn btn--store"> | |||
go to store | |||
</div> | |||
</a> | |||
<a class="platform__wrapper" href="https://www.microsoft.com/en-us/p/visual-anatomy-human-body/9nblggh4qg21" target="_blank"> | |||
<% include /store-icons/windows.svg %> | |||
<h2> | |||
Windows | |||
</h2> | |||
<div class="btn btn--store"> | |||
go to store | |||
</div> | |||
</a> | |||
</section> | |||
</article> |
@ -0,0 +1,133 @@ | |||
<footer class="text-center"> | |||
<section> | |||
<h3> | |||
<a href="https://www.graphicvizion.com/" target="_blank">GraphicViZion</a> | |||
</h3> | |||
<div class="copywrite"> | |||
<p>© <%= new Date().getFullYear() %> by GraphicViZion</p> | |||
<p class="build">v <%= buildInfo.version %> @ <time datetime="<%= buildInfo.time.raw %>"> | |||
<%= buildInfo.time.formatted %> | |||
</time></p> | |||
</div> | |||
<div class="credit"> | |||
this site was hand-crafted by <a href="https://spencerflagg.com" target="_blank">Spencer Flagg</a> | |||
</div> | |||
</section> | |||
<section> | |||
<ul> | |||
<li> | |||
<a href="https://www.instagram.com/graphic_vizion/" target="_blank"> | |||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-instagram" width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |||
<rect x="4" y="4" width="16" height="16" rx="4" /> | |||
<circle cx="12" cy="12" r="3" /> | |||
<line x1="16.5" y1="7.5" x2="16.5" y2="7.501" /> | |||
</svg> | |||
@graphic_vizion | |||
</a> | |||
</li> | |||
<li> | |||
<a href="https://twitter.com/graphicvizion" target="_blank"> | |||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-twitter" | |||
width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" | |||
stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> | |||
<path | |||
d="M22 4.01c-1 .49 -1.98 .689 -3 .99c-1.121 -1.265 -2.783 -1.335 -4.38 -.737s-2.643 2.06 -2.62 3.737v1c-3.245 .083 -6.135 -1.395 -8 -4c0 0 -4.182 7.433 4 11c-1.872 1.247 -3.739 2.088 -6 2c3.308 1.803 6.913 2.423 10.034 1.517c3.58 -1.04 6.522 -3.723 7.651 -7.742a13.84 13.84 0 0 0 .497 -3.753c-.002 -.249 1.51 -2.772 1.818 -4.013z" /> | |||
</svg> | |||
@graphicvizion | |||
</a> | |||
</li> | |||
<li> | |||
<a href="https://www.facebook.com/GraphicViZion/" target="_blank"> | |||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-facebook" width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |||
<path d="M7 10v4h3v7h4v-7h3l1 -4h-4v-2a1 1 0 0 1 1 -1h3v-4h-3a5 5 0 0 0 -5 5v2h-3" /> | |||
</svg> | |||
</a> | |||
</li> | |||
<li> | |||
<a href="https://www.linkedin.com/company/graphicvizion/" target="_blank"> | |||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-linkedin" width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |||
<rect x="4" y="4" width="16" height="16" rx="2" /> | |||
<line x1="8" y1="11" x2="8" y2="16" /> | |||
<line x1="8" y1="8" x2="8" y2="8.01" /> | |||
<line x1="12" y1="16" x2="12" y2="11" /> | |||
<path d="M16 16v-3a2 2 0 0 0 -4 0" /> | |||
</svg> | |||
</a> | |||
</li> | |||
<li> | |||
<a href="https://www.youtube.com/user/GraphicVizion" target="_blank"> | |||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-youtube" | |||
width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" | |||
stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> | |||
<rect x="3" y="5" width="18" height="14" rx="4" /> | |||
<path d="M10 9l5 3l-5 3z" /> | |||
</svg> | |||
YouTube | |||
</a> | |||
</li> | |||
<li> | |||
<a href="https://itunes.apple.com/us/artist/graphicvizion/id492668041" target="_blank"> | |||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-apple" width="32" | |||
height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" | |||
stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> | |||
<path | |||
d="M9 7c-3 0 -4 3 -4 5.5c0 3 2 7.5 4 7.5c1.088 -.046 1.679 -.5 3 -.5c1.312 0 1.5 .5 3 .5s4 -3 4 -5c-.028 -.01 -2.472 -.403 -2.5 -3c-.019 -2.17 2.416 -2.954 2.5 -3c-1.023 -1.492 -2.951 -1.963 -3.5 -2c-1.433 -.111 -2.83 1 -3.5 1c-.68 0 -1.9 -1 -3 -1z" /> | |||
<path d="M12 4a2 2 0 0 0 2 -2a2 2 0 0 0 -2 2" /> | |||
</svg> | |||
App Store | |||
</a> | |||
</li> | |||
<li> | |||
<a href="https://play.google.com/store/apps/developer?id=Graphic-ViZion" target="_blank"> | |||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-google-play" | |||
width="32" height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" | |||
stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> | |||
<path | |||
d="M4 3.71v16.58a0.7 .7 0 0 0 1.05 .606l14.622 -8.42a0.55 .55 0 0 0 0 -.953l-14.622 -8.419a0.7 .7 0 0 0 -1.05 .607z" /> | |||
<line x1="15" y1="9" x2="4.5" y2="20.5" /> | |||
<line x1="4.5" y1="3.5" x2="15" y2="15" /> | |||
</svg> | |||
Play Store | |||
</a> | |||
</li> | |||
<li><a href="<%= site.url %>app/policies/privacypolicy.html" target="_blank"> | |||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-eye-off" width="32" | |||
height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" | |||
stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> | |||
<line x1="3" y1="3" x2="21" y2="21" /> | |||
<path d="M10.584 10.587a2 2 0 0 0 2.828 2.83" /> | |||
<path | |||
d="M9.363 5.365a9.466 9.466 0 0 1 2.637 -.365c4 0 7.333 2.333 10 7c-.778 1.361 -1.612 2.524 -2.503 3.488m-2.14 1.861c-1.631 1.1 -3.415 1.651 -5.357 1.651c-4 0 -7.333 -2.333 -10 -7c1.369 -2.395 2.913 -4.175 4.632 -5.341" /> | |||
</svg> | |||
Privacy Policy</a></li> | |||
<li><a href="<%= site.url %>app/policies/termsofuse.html" target="_blank"><svg | |||
xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-news" width="32" | |||
height="32" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ffffff" fill="none" | |||
stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> | |||
<path | |||
d="M16 6h3a1 1 0 0 1 1 1v11a2 2 0 0 1 -4 0v-13a1 1 0 0 0 -1 -1h-10a1 1 0 0 0 -1 1v12a3 3 0 0 0 3 3h11" /> | |||
<line x1="8" y1="8" x2="12" y2="8" /> | |||
<line x1="8" y1="12" x2="12" y2="12" /> | |||
<line x1="8" y1="16" x2="12" y2="16" /> | |||
</svg>Terms of Use</a></li> | |||
<% sections.forEach((link)=> { %> | |||
<li class="menu-item"> | |||
<a href="#<%= link.slug %>"> | |||
<%= link.name %> | |||
</a> | |||
</li> | |||
<% }) %> | |||
</ul> | |||
</section> | |||
</footer> |
@ -0,0 +1,30 @@ | |||
<article class="hero__wrapper"> | |||
<% include /nav %> | |||
<!-- whatever video you put here will be (effectively) cropped to fit container size; make sure you're okay with it shrinking to the top left corner of the video at your specified minimum dimensions --> | |||
<!-- <video autoplay loop muted class="hero__video"> | |||
<source src="https://zippy.gfycat.com/FearfulSoggyFox.webm" type="video/webm" alt="HTML5 background video"> | |||
</video> --> | |||
<img src="./assets/images/hero.png" class="hero__video"> | |||
<div class="hero__info"> | |||
<a class="btn btn--hero" href="#download"> | |||
download now | |||
</a> | |||
<div class="platform-list"> | |||
<% include /store-icons/ios.svg %> | |||
<% include /store-icons/android.svg %> | |||
<% include /store-icons/macos.svg %> | |||
<% include /store-icons/windows.svg %> | |||
</div> | |||
</div> | |||
<div class="hero__banner"> | |||
<svg class="banner-edge-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"> | |||
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.116947" | |||
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" /> | |||
</svg> | |||
<svg class="banner-edge-right" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"> | |||
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0.116947" | |||
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" /> | |||
</svg> | |||
<h1 class="h1--hero">Interactive human anatomy in real-time 3D</h1> | |||
</div> | |||
</article> |
@ -0,0 +1,41 @@ | |||
<article class="info__wrapper max-w-screen-lg"> | |||
<section id="info"> | |||
<h1> | |||
Designed for anatomy students | |||
</h1> | |||
<p> | |||
We believe that learning by interaction is the best and easiest way to study human anatomy. | |||
</p> | |||
<h1> | |||
Perfect for professionals | |||
</h1> | |||
<p> | |||
When discussing anatomy with a patient it can help as an visual aid. | |||
</p> | |||
</section> | |||
<section> | |||
<ul> | |||
<li> | |||
over 1200 body parts! | |||
</li> | |||
<li> | |||
highly detailed | |||
</li> | |||
<li> | |||
fully searchable | |||
</li> | |||
<li> | |||
zoom, pan, and rotate in real time | |||
</li> | |||
<li> | |||
show and hide layers | |||
</li> | |||
<li> | |||
see details for each body part | |||
</li> | |||
<li class="hide-on-mobile"> | |||
add custom notes | |||
</li> | |||
</ul> | |||
</section> | |||
</article> |
@ -0,0 +1,338 @@ | |||
<!DOCTYPE html> | |||
<html lang="en" dir="ltr" style="--scrollbarWidth: 0px; --viewportWidth: calc(100vw - var(--scrollbarWidth));"> | |||
<head> | |||
<meta charset="UTF-8" /> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" /> | |||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" /> | |||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" /> | |||
<link rel="icon" href="/favicon.ico" /> | |||
<!-- <link rel="preconnect" href="https://fonts.googleapis.com"> | |||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |||
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Nunito&family=DM+Serif+Display:ital@0;1&display=swap" rel="stylesheet"> --> | |||
<link rel="preconnect" href="https://api.fonts.coollabs.io" crossorigin> | |||
<link href="https://api.fonts.coollabs.io/css2?family=Bebas+Neue&family=Nunito&family=DM+Serif+Display&display=swap" rel="stylesheet"> | |||
<!-- Required Core Stylesheet --> | |||
<!-- <link rel="stylesheet" href="/node_modules/@glidejs/glide/dist/css/glide.core.css"> --> | |||
<!-- Optional Theme Stylesheet --> | |||
<!-- <link rel="stylesheet" href="/node_modules/@glidejs/glide/dist/css/glide.theme.css"> --> | |||
<script> | |||
window.onload = setScrollbarVariable; | |||
document.onload = setScrollbarVariable; | |||
window.onresize = setScrollbarVariable; | |||
function setScrollbarVariable() { | |||
//alert(window.innerWidth + " - " + document.body.clientWidth); | |||
//const scrollbarWidth = window.innerWidth - document.body.clientWidth; | |||
const viewportDependantWidth = (typeof window.orientation !== "undefined") ? screen.width : window.innerWidth; | |||
//console.log(screen.width + " " + window.innerWidth); | |||
const scrollbarWidth = viewportDependantWidth - document.body.clientWidth; | |||
document.documentElement.style.setProperty("--scrollbarWidth", `${scrollbarWidth}px`); | |||
} | |||
</script> | |||
<style> | |||
:root{ | |||
--viewportWidth: calc(100vw - var(--scrollbarWidth)); | |||
} | |||
</style> | |||
<title> | |||
<%= site.title %> | |||
</title> | |||
<meta name="description" content="<%= (!!locals.description) ? description : site.description %>" /> | |||
<meta name="author" content="<%= site.author %>" /> | |||
<meta property="og:title" content="<%= site.title %>" /> | |||
<meta property="og:description" content="<%= (!!locals.description) ? description : site.description %>" /> | |||
<meta property="og:locale" content="<%= site.locale %>" /> | |||
<meta property="og:site_name" content="<%= site.site_name %>" /> | |||
<% if (locals.tags=="posts" ) { %> | |||
<meta property="og:type" content="article" /> | |||
<meta property="article:published_time" content="<%= date.toISOString() %>" /> | |||
<script type="application/ld+json"> | |||
{ | |||
"description": "<%= (!!locals.description) ? description : site.description %>", | |||
"author": { "@type": "Person", "name": "<%= site.author %>" }, | |||
"@type": "BlogPosting", | |||
"url": "<%= `${site.url}${page.url}` %>", | |||
"publisher": { | |||
"@type": "Organization", | |||
"logo": { | |||
"@type": "ImageObject", | |||
"url": "<%= `${site.url}/assets/images/logo.png` %>" | |||
}, | |||
"name": "<%= site.author %>" | |||
}, | |||
"headline": "<%= site.title %>", | |||
"datePublished": "<%= date.toISOString() %>", | |||
"mainEntityOfPage": { | |||
"@type": "WebPage", | |||
"@id": "<%= `${site.url}${page.url}` %>" | |||
}, | |||
"@context": "http://schema.org" | |||
} | |||
</script> | |||
<% } %> | |||
<%- include('webpack.ejs') %> | |||
<% if (page.url=="/" ) { %> | |||
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script> | |||
<script> | |||
if (window.netlifyIdentity) { | |||
window.netlifyIdentity.on('init', (user) => { | |||
if (!user) { | |||
window.netlifyIdentity.on('login', () => { | |||
document.location.href = '/admin/'; | |||
}); | |||
} | |||
}); | |||
} | |||
</script> | |||
<% } %> | |||
</head> | |||
<body class=""> | |||
<div id="page" class="max-w-screen-lg mx-auto"> | |||
<header class="site-header "> | |||
<img class="site-logo" src="<%= `./assets/images/logo.png` %>" alt=""> | |||
<h1 class="site-title font-semibold text-3xl text-gray-800"> | |||
<%= site.title %> | |||
</h1> | |||
<!-- <div class="text-xl"><%= site.description %></div> --> | |||
</header> | |||
<main class="page-content"> | |||
<%- content %> | |||
</main> | |||
<% include /footer %> | |||
</div> | |||
<!-- <script src="https://unpkg.com/@glidejs/glide@3.3.0/dist/glide.js"></script> --> | |||
<!-- <script src="/node_modules/@glidejs/glide/dist/glide.modular.esm.js"></script> --> | |||
<!-- <script src="/js/eleventy.js" type="module" async></script> --> | |||
<!-- this below were the last ones that i used --> | |||
<!-- <script src="./node_modules/@glidejs/glide/dist/glide.min.js"></script> --> | |||
<script src="/node_modules/blueimp-md5/js/md5.min.js"></script> | |||
<script> | |||
// new Glide('.glide').mount({ | |||
// type: 'carousel', | |||
// startAt: 0, | |||
// perView: 1, | |||
// autoplay: 1000, | |||
// bound: true, | |||
// rewind: false | |||
// }) | |||
// new Glide('.glide').mount() | |||
</script> | |||
<script> | |||
var siteUrl = "<%= site.url %>"; | |||
console.log(siteUrl); | |||
document.getElementById('fromEmail').addEventListener('input', function () { | |||
const fromEmail = document.getElementById('fromEmail'); | |||
const message = document.getElementById('message'); | |||
const emailError = document.getElementById('emailError'); | |||
const otherError = document.getElementById('otherError'); | |||
const success = document.getElementById('success'); | |||
const contactSubmit = document.getElementById('contactSubmit'); | |||
// if (/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/.test(fromEmail.value)) { | |||
// contactSubmit.disabled = false; | |||
// alert.classList.remove('form-alert--visible'); | |||
// } else { | |||
// contactSubmit.disabled = true; | |||
// alert.classList.add('form-alert--visible'); | |||
// } | |||
emailError.classList.remove('form-alert--visible'); | |||
otherError.classList.remove('form-alert--visible'); | |||
success.classList.remove('form-alert--visible'); | |||
}); | |||
document.getElementById('contactSubmit').addEventListener('click', function () { | |||
const fromEmail = document.getElementById('fromEmail'); | |||
const message = document.getElementById('message'); | |||
const emailError = document.getElementById('emailError'); | |||
const otherError = document.getElementById('otherError'); | |||
const success = document.getElementById('success'); | |||
if (/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/.test(fromEmail.value)) { | |||
/* succeeded */ | |||
emailError.classList.remove('form-alert--visible'); | |||
var details = { | |||
'hash': md5(fromEmail.value + 'erkbn234987kjs'), | |||
'fromEmail': fromEmail.value, | |||
'message': message.value, | |||
'title': 'Support - Visual Anatomy 3D (site)' | |||
}; | |||
var formBody = []; | |||
for (var property in details) { | |||
var encodedKey = encodeURIComponent(property); | |||
var encodedValue = encodeURIComponent(details[property]); | |||
formBody.push(encodedKey + "=" + encodedValue); | |||
} | |||
formBody = formBody.join("&"); | |||
try { | |||
fetch(siteUrl + 'app/php/email/v1/SendSupportMail.php', { | |||
method: 'POST', | |||
//mode: 'no-cors', | |||
headers: { | |||
'Content-Type': 'application/x-www-form-urlencoded', | |||
}, | |||
body: formBody, | |||
}) | |||
.then(response => { | |||
//console.log("response.status: " + response.status); | |||
if(response.status === 200){ | |||
return response.text(); | |||
} else { | |||
otherError.classList.add('form-alert--visible'); | |||
} | |||
}) | |||
.then(data => { | |||
//console.log("data:"); | |||
//console.log(data); | |||
switch (data) { | |||
case "succesSendingSupportEmail": | |||
success.classList.add('form-alert--visible'); | |||
emailError.classList.remove('form-alert--visible'); | |||
otherError.classList.remove('form-alert--visible'); | |||
fromEmail.value = ''; | |||
message.value = ''; | |||
break; | |||
case "invalidEmailAdres": | |||
emailError.classList.add('form-alert--visible'); | |||
break; | |||
case "failedSendingSupportEmail": | |||
case "failedHash": | |||
otherError.classList.add('form-alert--visible'); | |||
break; | |||
default: | |||
break; | |||
} | |||
//console.log(data) | |||
}); | |||
} catch (error) { | |||
otherError.classList.add('form-alert--visible'); | |||
} | |||
} else { | |||
/* failed */ | |||
emailError.classList.add('form-alert--visible'); | |||
} | |||
}); | |||
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/flexgap.js | |||
function checkFlexGap() { | |||
// create flex container with row-gap set | |||
var flex = document.createElement("div"); | |||
flex.style.display = "flex"; | |||
flex.style.flexDirection = "column"; | |||
flex.style.rowGap = "1px"; | |||
// create two, elements inside it | |||
flex.appendChild(document.createElement("div")); | |||
flex.appendChild(document.createElement("div")); | |||
// append to the DOM (needed to obtain scrollHeight) | |||
document.body.appendChild(flex); | |||
var isSupported = flex.scrollHeight === 1; // flex container should be 1px high from the row-gap | |||
//flex.parentNode.removeChild(flex); | |||
return isSupported; | |||
} | |||
console.log(checkFlexGap()); | |||
if (checkFlexGap()) { | |||
document.documentElement.classList.add("flexbox-gap"); | |||
} else { | |||
document.documentElement.classList.add("no-flexbox-gap"); | |||
} | |||
</script> | |||
</body> | |||
</html> | |||
<!-- <style> | |||
.site-logo { | |||
height: 5rem; | |||
width: 5rem; | |||
transform: rotateZ(0deg) translateY(0.4rem); | |||
transition: 0.2s all; | |||
border: 3px solid var(--c-1); | |||
border-radius: 1rem; | |||
} | |||
.site-logo:hover { | |||
transform: rotateZ(4deg) translateY(0.4rem) scale(1.1); | |||
} | |||
.site-header { | |||
display: flex; | |||
justify-content: center; | |||
align-items: baseline; | |||
gap: 1rem; | |||
} | |||
.no-flexbox-gap .site-header>*:not(:last-child) { | |||
margin-right: 1rem; | |||
} | |||
.site-title { | |||
font-family: Bebas Neue; | |||
font-style: normal; | |||
font-weight: normal; | |||
font-size: 3rem; | |||
line-height: 1; | |||
letter-spacing: 0.24em; | |||
text-transform: uppercase; | |||
width: auto; | |||
margin: 3rem 0 0 0; | |||
} | |||
#page { | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
} | |||
.page-content { | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
} | |||
</style> --> |
@ -0,0 +1,30 @@ | |||
--- | |||
layout: layouts/base.ejs | |||
--- | |||
<span>asdf</span> | |||
<%= 'hello' | i18n %> | |||
<% include /hero %> | |||
<% include /blurb %> | |||
<div class="inset"> | |||
<% include /info %> | |||
</div> | |||
<% include /screenshots %> | |||
<% include /systems %> | |||
<div class="inset"> | |||
<% include /pricing %> | |||
<% include /download %> | |||
</div> | |||
<% include /reviews %> |
@ -0,0 +1,14 @@ | |||
--- | |||
layout: layouts/base.ejs | |||
--- | |||
<article> | |||
<header> | |||
<h1 class="text-center font-bold text-3xl text-gray-800"><%= site.title %></h1> | |||
<div class="text-center text-sm mb-8"> | |||
<%= this.dateFns.format(new Date(date), 'LLLL d, yyyy') %> | |||
</div> | |||
</header> | |||
<section class="content"><%- content %></section> | |||
</article> |
@ -0,0 +1,21 @@ | |||
<div class="nav__wrapper"> | |||
<nav> | |||
<ul> | |||
<% sections.forEach((link)=> { %> | |||
<li class=""> | |||
<a class="nav-link" href="#<%= link.slug %>"> | |||
<%= link.name %> | |||
</a> | |||
</li> | |||
<% }) %> | |||
</ul> | |||
</nav> | |||
<svg class="nav-edge-left" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"> | |||
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0" | |||
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" /> | |||
</svg> | |||
<svg class="nav-edge-right" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"> | |||
<path id="rect22" style="fill:#ffffff;fill-rule:evenodd;stroke-width:0" | |||
d="M 9.9999058,0 A 10,10 0 0 1 0,10.000422 h 9.9999058 z" /> | |||
</svg> | |||
</div> |
@ -0,0 +1,212 @@ | |||
<article class="pricing__wrapper max-w-screen-lg"> | |||
<header> | |||
<h1 id="pricing"> | |||
flexible pricing options | |||
</h1> | |||
</header> | |||
<section class="pricing__content"> | |||
<div class="level__wrapper level-wrapper--heading"> | |||
<header> | |||
<h2> | |||
<span> | |||
</span> | |||
</h2> | |||
</header> | |||
<div class="level__content"> | |||
<div class="level__price-wrapper"> | |||
<h2 class="level__price"> | |||
</h2> | |||
<span> | |||
</span> | |||
</div> | |||
<ul> | |||
<% systems.forEach((system)=> { %> | |||
<li class=""> | |||
<%= system.name %> | |||
</li> | |||
<% }) %> | |||
</ul> | |||
</div> | |||
<div></div> | |||
</div> | |||
<div class="level__wrapper level-wrapper--trial"> | |||
<header> | |||
<h2> | |||
starter | |||
<span> | |||
limited | |||
</span> | |||
</h2> | |||
</header> | |||
<div class="level__content"> | |||
<div class="level__price-wrapper"> | |||
<h2 class="level__price" style="align-items: center;"> | |||
free | |||
<span> | |||
with paid add-ons | |||
</span> | |||
</h2> | |||
</div> | |||
<ul> | |||
<!-- <li>2 systems included</li> | |||
<li>purchase advanced systems separately</li> --> | |||
<% systems.forEach((system)=> { %> | |||
<% if (system.status==='free' ) { %> | |||
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#00C2FF" fill="none" stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |||
<path d="M5 12l5 5l10 -10" /> | |||
</svg></li> | |||
<% } else if (system.status==='pro' ) { %> | |||
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-x" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#000000" fill="none" stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |||
<line x1="18" y1="6" x2="6" y2="18" /> | |||
<line x1="6" y1="6" x2="18" y2="18" /> | |||
</svg><span>(in-app purchase)</span></li> | |||
<% } else if (system.status==='soon' ) { %> | |||
<li><span>(coming soon)</span></li> | |||
<% } %> | |||
<% }) %> | |||
</ul> | |||
</div> | |||
<a class="btn btn--level" href="#download"> | |||
download | |||
</a> | |||
</div> | |||
<div class="level__wrapper level__wrapper--monthly level__wrapper--disabled"> | |||
<header> | |||
<h2> | |||
monthly | |||
<span> | |||
subscription | |||
</span> | |||
</h2> | |||
</header> | |||
<div class="level__content"> | |||
<div class="level__price-wrapper"> | |||
<h2 class="level__price"> | |||
$9.95 | |||
<span> | |||
paid monthly | |||
</span> | |||
</h2> | |||
</div> | |||
<ul> | |||
<% systems.forEach((system)=> { %> | |||
<% if (system.status==='pro' || system.status==='free' ) { %> | |||
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#00C2FF" fill="none" stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |||
<path d="M5 12l5 5l10 -10" /> | |||
</svg> | |||
</li> | |||
<% } else if (system.status==='soon' ) { %> | |||
<li><span>(coming soon)</span></li> | |||
<% } %> | |||
<% }) %> | |||
</ul> | |||
</div> | |||
<a class="btn btn--level btn--disabled"> | |||
coming soon | |||
</a> | |||
</div> | |||
<div class="level__wrapper level__wrapper--yearly level__wrapper--disabled"> | |||
<header> | |||
<h2> | |||
yearly | |||
<span> | |||
subscription | |||
</span> | |||
</h2> | |||
</header> | |||
<div class="level__content"> | |||
<div class="level__price-wrapper"> | |||
<h2 class="level__price"> | |||
$3.95 | |||
<span> | |||
paid monthly | |||
</span> | |||
</h2> | |||
</div> | |||
<ul> | |||
<% systems.forEach((system)=> { %> | |||
<% if (system.status==='pro' || system.status==='free' ) { %> | |||
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#00C2FF" fill="none" stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |||
<path d="M5 12l5 5l10 -10" /> | |||
</svg></li> | |||
<% } else if (system.status==='soon' ) { %> | |||
<li><span class="">(coming soon)</span></li> | |||
<% } %> | |||
<% }) %> | |||
</ul> | |||
</div> | |||
<a class="btn btn--level btn--disabled"> | |||
coming soon | |||
</a> | |||
</div> | |||
<div class="level__wrapper level__wrapper--lifetime"> | |||
<header> | |||
<h2> | |||
lifetime | |||
<span> | |||
full version | |||
</span> | |||
</h2> | |||
</header> | |||
<div class="level__content"> | |||
<div class="level__price-wrapper"> | |||
<h2 class="level__price"> | |||
$24.95 | |||
<span> | |||
one time fee | |||
</span> | |||
</h2> | |||
</div> | |||
<ul> | |||
<% systems.forEach((system)=> { %> | |||
<% if (system.status==='pro' || system.status==='free' ) { %> | |||
<li><svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-check" width="32" height="32" viewBox="0 0 24 24" stroke-width="3" stroke="#00C2FF" fill="none" stroke-linecap="round" stroke-linejoin="round"> | |||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/> | |||
<path d="M5 12l5 5l10 -10" /> | |||
</svg></li> | |||
<% } else if (system.status==='soon' ) { %> | |||
<li><span>(coming soon)</span></li> | |||
<% } %> | |||
<% }) %> | |||
</ul> | |||
</div> | |||
<a class="btn btn--level" href="#download"> | |||
download | |||
</a> | |||
</div> | |||
</section> | |||
</article> |
@ -0,0 +1,36 @@ | |||
<article class="reviews-wrapper"> | |||
<header> | |||
<h1 id="reviews"> | |||
Glowing reviews | |||
</h1> | |||
</header> | |||
<section> | |||
<ul class="reviews"> | |||
<% reviews.forEach((review)=> { %> | |||
<li class="review"> | |||
<div class="rating-wrapper"> | |||
<div class="rating"> | |||
<% for (let step=0; step <=review.stars * 10; step +=5) { %> | |||
<% if (step> 0) { %> | |||
<label class="<%= (step % 2 == 0) ? 'full' : 'half' %> <%= step %>"></label> | |||
<% } %> | |||
<% } %> | |||
<% if (review.stars * 10 % 2 !==0) { %> | |||
<label class="full" style="color: transparent"></label> | |||
<% } %> | |||
</div> | |||
<a href="<%= review.link %>"> | |||
<%= review.site %> | |||
</a> | |||
</div> | |||
<blockquote> | |||
<%= review.quote %> | |||
</blockquote> | |||
<label class="review__name"> | |||
<%= review.name %> | |||
</label> | |||
</li> | |||
<% }) %> | |||
</ul> | |||
</section> | |||
</article> |
@ -0,0 +1,65 @@ | |||
<article class="screenshots__wrapper"> | |||
<header> | |||
<h1 id="screenshots"> | |||
Hi-res imagery everywhere you need it | |||
</h1> | |||
<aside> | |||
The <%= site.site_name %> app is currently available for iOS and Android, with desktop support added later. | |||
The app supports portrait mode, text-scaling, and it includes 3 color themes. | |||
</aside> | |||
</header> | |||
<section> | |||
<div class="glide"> | |||
<div data-glide-el="track" class="glide__track"> | |||
<ul class="glide__slides"> | |||
<% collections.screenshotThumbnails.forEach((screenshot, index)=> { %> | |||
<% if (screenshot.includes('--en')) { %> | |||
<li class="glide__slide"> | |||
<img src="<%= screenshot %>" alt="" onclick="zoomScreenshot('<%= screenshot %>')" /> | |||
</li> | |||
<% } %> | |||
<% }) %> | |||
</ul> | |||
</div> | |||
</div> | |||
<div class="hires"> | |||
<% collections.screenshotHires.forEach((screenshot, index)=> { %> | |||
<% if (screenshot.includes('--en')) { %> | |||
<div class="hires-details" data="<%= screenshot %>" onclick="clearScreenshotSelection()"> | |||
<img src="<%= screenshot %>" alt="" /> | |||
<caption></caption> | |||
</div> | |||
<% } %> | |||
<% }) %> | |||
</div> | |||
</section> | |||
</article> | |||
<script> | |||
function zoomScreenshot(slug) { | |||
let thisImage = document.querySelector('[data="' + slug.replace('resized.','') + '"]'); | |||
thisImage.classList.add('hires-details--selected'); | |||
let allIconImages = document.querySelectorAll('.hires-details'); | |||
for (let elem of allIconImages) { | |||
if (elem !== thisImage) { | |||
elem.classList.remove('hires-details--selected') | |||
} | |||
} | |||
} | |||
function clearScreenshotSelection() { | |||
let allIconImages = document.querySelectorAll('.hires-details'); | |||
for (let elem of allIconImages) { | |||
elem.classList.remove('hires-details--selected') | |||
} | |||
} | |||
</script> |
@ -0,0 +1,3 @@ | |||
<svg width="88" height="97" viewBox="0 0 88 97" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
<path d="M47.9932 46.3913L63.8426 30.4439L12.6495 1.49383C9.25667 -0.350607 6.07821 -0.609474 3.29102 1.40754L47.9932 46.3913ZM66.544 65.0621L83.0206 55.7375C86.2366 53.9254 88 51.3583 88 48.5108C88 45.6686 86.2366 43.0961 83.0259 41.284L68.1092 32.8546L51.3164 49.7458L66.544 65.0621ZM0.535997 5.32831C0.192958 6.39075 0 7.57723 0 8.87696V88.1823C0 90.2371 0.450238 92.006 1.26495 93.4136L44.6646 49.7404L0.535997 5.32831ZM47.9932 53.0841L4.83469 96.5146C5.66013 96.8328 6.54988 97 7.48788 97C9.16019 97 10.9022 96.5038 12.6763 95.5115L62.2829 67.4836L47.9932 53.0841Z" fill="var(--c-3)"/> | |||
</svg> |
@ -0,0 +1,3 @@ | |||
<svg width="109" height="108" viewBox="0 0 109 108" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
<path d="M54.5 0C84.6003 0 109 24.1758 109 54C109 83.8242 84.6003 108 54.5 108C24.3997 108 0 83.8242 0 54C0 24.1758 24.3997 0 54.5 0ZM37.1853 72.0522C35.0326 69.4764 32.3566 68.5584 29.1248 69.3036L28.3073 69.525L25.0918 75.0114C24.4854 75.9896 24.2845 77.1624 24.5313 78.284C24.7781 79.4057 25.4533 80.3892 26.4156 81.0286C27.3779 81.668 28.5526 81.9136 29.6936 81.714C30.8346 81.5144 31.8534 80.885 32.5365 79.9578L32.8744 79.4556L37.1799 72.0522H37.1853ZM61.0945 35.964C58.4349 38.1456 55.7535 44.5878 59.514 51.0138L76.082 79.4502C76.6557 80.4163 77.5763 81.1322 78.6597 81.4548C79.7431 81.7775 80.9095 81.6832 81.9257 81.1906C82.9419 80.6981 83.7331 79.8437 84.1411 78.7982C84.549 77.7527 84.5437 76.5932 84.1262 75.5514L83.8591 75.0114L79.4882 67.4946H85.9737C86.5629 67.496 87.1466 67.382 87.6911 67.1591C88.2356 66.9362 88.7303 66.6088 89.1467 66.1958C89.563 65.7827 89.8928 65.2922 90.1171 64.7524C90.3414 64.2126 90.4558 63.6342 90.4536 63.0504C90.4565 61.9676 90.0588 60.9212 89.3357 60.1093C88.6126 59.2973 87.6144 58.7761 86.5296 58.644L85.9683 58.6116H74.3053L62.348 38.1078L61.0945 35.9694V35.964ZM62.6096 19.5264C61.6684 18.9908 60.5635 18.8105 59.4987 19.0189C58.4339 19.2274 57.4811 19.8104 56.8162 20.6604L56.4783 21.1572L54.4782 24.5754L52.5216 21.1572C51.9479 20.1911 51.0273 19.4752 49.9439 19.1526C48.8605 18.8299 47.6941 18.9243 46.6779 19.4168C45.6617 19.9093 44.8705 20.7637 44.4626 21.8092C44.0546 22.8547 44.0599 24.0142 44.4775 25.056L44.7445 25.596L49.3116 33.4638L34.6783 58.59H23.2497C22.661 58.5886 22.0778 58.7024 21.5336 58.925C20.9894 59.1476 20.495 59.4745 20.0787 59.8869C19.6624 60.2994 19.3325 60.7893 19.1079 61.3285C18.8833 61.8676 18.7684 62.4455 18.7698 63.0288C18.7698 65.3022 20.4702 67.1652 22.6884 67.4406L23.2497 67.473H64.0157C65.8687 64.017 63.6887 59.1084 59.6012 58.6278L58.9417 58.59H45.0279L64.2555 25.596C64.8495 24.5749 65.0099 23.3617 64.7012 22.2235C64.3925 21.0852 63.6402 20.115 62.6096 19.5264Z" fill="var(--c-3)"/> | |||
</svg> |
@ -0,0 +1,3 @@ | |||
<svg width="100" height="116" viewBox="0 0 100 116" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
<path d="M100 85.1098C97.2652 91.1454 95.9573 93.8441 92.4451 99.1777C87.5381 106.627 80.6098 115.922 72.0443 115.985C64.4254 116.049 62.4589 111.03 52.119 111.112C41.7791 111.162 39.6251 116.077 31.9971 115.999C23.4316 115.922 16.8737 107.547 11.9621 100.112C-1.77107 79.2565 -3.22076 54.8131 5.26702 41.8073C11.2716 32.5851 20.7746 27.1695 29.6968 27.1695C38.7837 27.1695 44.4956 32.1475 52.0093 32.1475C59.2989 32.1475 63.7394 27.1558 74.2485 27.1558C82.1967 27.1558 90.6021 31.4728 96.6067 38.9216C76.9604 49.6527 80.1525 77.6245 100 85.1098ZM66.2729 18.8317C70.0961 13.9403 72.9955 7.03854 71.9436 0C65.7059 0.423953 58.4117 4.39453 54.1495 9.53667C50.2898 14.2184 47.0885 21.1749 48.337 27.9034C55.1419 28.1222 62.1845 24.0787 66.2729 18.8317Z" fill="var(--c-3)"/> | |||
</svg> |
@ -0,0 +1,3 @@ | |||
<svg width="104" height="104" viewBox="0 0 104 104" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
<path d="M42.5745 8.93049L0 14.5291V49.9263H42.5745V8.93049ZM0 89.5972L42.5745 95.6569V53.9921H0V89.5972ZM47.2704 54.5247L47.4392 95.9492L103.919 103.918V54.5247H47.2704ZM103.919 0L47.6081 8.07966V49.738H103.919V0Z" fill="var(--c-3)"/> | |||
</svg> |
@ -0,0 +1,69 @@ | |||
<article class="system__wrapper"> | |||
<header> | |||
<h1 id="systems"> | |||
<%= systems.filter(system => system.status !== 'soon').length %> detailed body systems | |||
</h1> | |||
<aside> | |||
The <%= site.site_name %> app includes <strong><%= systems.filter(system => system.status !== 'soon').length %></strong> body systems, which can be hidden or shown (in layers) and colored to easily distinguish the individual anatomical parts. | |||
All body systems can be viewed individually or in customizable combinations. | |||
</aside> | |||
</header> | |||
<section> | |||
<ul class="system__list"> | |||
<% systems.forEach((system, index)=> { %> | |||
<li onclick="zoom('<%= system.slug %>')" | |||
class="system system--<%= system.slug %> system--<%= system.status %> <%= index === 0 ? 'system--selected' : '' %>"> | |||
<%- include('/system-icons/'+system.slug+'.svg') %> | |||
<span> | |||
<%= system.name %> | |||
</span> | |||
</li> | |||
<% }) %> | |||
</ul> | |||
<div class="system__zoom-wrapper"> | |||
<img class="zoom__image--bkg %>" | |||
src="./assets/images/systems/layers/bkg.png" alt="background"> | |||
<% systems.filter(system => system.status !== 'soon').forEach((system, index)=> { %> | |||
<img class="zoom__image zoom__image--<%= system.slug %> <%= index === 0 ? 'zoom__image--visible' : '' %>" | |||
src="./assets/images/systems/layers/<%= system.slug %>.png" alt="<%= system.name %>" | |||
title="<%= system.name %>"> | |||
<% }) %> | |||
</div> | |||
</section> | |||
</article> | |||
<script> | |||
function zoom(slug) { | |||
const thisIconClass = 'system--' + slug; | |||
let thisIconImage = document.querySelector('.' + thisIconClass); | |||
thisIconImage.classList.add('system--selected') | |||
let allIconImages = document.querySelectorAll('.system'); | |||
for (let elem of allIconImages) { | |||
if (!elem.classList.contains(thisIconClass)) { | |||
elem.classList.remove('system--selected') | |||
} | |||
} | |||
const thisZoomClass = 'zoom__image--' + slug; | |||
let thisZoomImage = document.querySelector('.' + thisZoomClass); | |||
thisZoomImage.classList.add('zoom__image--visible') | |||
let allZoomImages = document.querySelectorAll('.zoom__image'); | |||
for (let elem of allZoomImages) { | |||
if (!elem.classList.contains(thisZoomClass)) { | |||
elem.classList.remove('zoom__image--visible') | |||
} | |||
} | |||
} | |||
</script> |
@ -0,0 +1,10 @@ | |||
<svg width="28" height="29" viewBox="0 0 28 29" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
<g clip-path="url(#clip0_51:52)"> | |||
<path d="M28.0029 14.3048C28.0029 18.0987 26.5278 21.7372 23.902 24.4198C21.2762 27.1025 17.7149 28.6096 14.0014 28.6096C10.288 28.6096 6.72671 27.1025 4.10093 24.4198C1.47515 21.7372 0 18.0987 0 14.3048C0 10.5109 1.47515 6.87245 4.10093 4.18978C6.72671 1.50711 10.288 0 14.0014 0C17.7149 0 21.2762 1.50711 23.902 4.18978C26.5278 6.87245 28.0029 10.5109 28.0029 14.3048V14.3048ZM21.0547 8.88686C20.9297 8.75958 20.7808 8.65937 20.617 8.59221C20.4532 8.52505 20.2779 8.49233 20.1014 8.49601C19.9249 8.49968 19.751 8.53967 19.59 8.61358C19.4291 8.6875 19.2843 8.79383 19.1645 8.9262L13.0861 16.8385L9.42298 13.0943C9.17414 12.8574 8.84503 12.7284 8.50497 12.7345C8.1649 12.7407 7.84045 12.8814 7.59995 13.1271C7.35945 13.3728 7.22169 13.7043 7.21569 14.0518C7.20969 14.3992 7.33592 14.7354 7.56778 14.9897L12.1988 19.7228C12.3235 19.85 12.4721 19.9502 12.6356 20.0175C12.7991 20.0848 12.9742 20.1178 13.1504 20.1145C13.3267 20.1111 13.5004 20.0715 13.6614 19.9981C13.8223 19.9247 13.9672 19.8189 14.0872 19.687L21.0739 10.7644C21.3121 10.5114 21.4437 10.173 21.4404 9.82196C21.4372 9.47093 21.2993 9.1352 21.0564 8.88686H21.0547Z" fill="#00C2FF"/> | |||
</g> | |||
<defs> | |||
<clipPath id="clip0_51:52"> | |||
<rect width="28" height="29" fill="white"/> | |||
</clipPath> | |||
</defs> | |||
</svg> |