diff --git a/nfp_is/.npmrc b/nfp_is/.npmrc
new file mode 100644
index 0000000..9cf9495
--- /dev/null
+++ b/nfp_is/.npmrc
@@ -0,0 +1 @@
+package-lock=false
\ No newline at end of file
diff --git a/nfp_is/api/serve.mjs b/nfp_is/api/serve.mjs
new file mode 100644
index 0000000..8a1da35
--- /dev/null
+++ b/nfp_is/api/serve.mjs
@@ -0,0 +1,20 @@
+import path from 'path'
+import Parent from '../base/serve.mjs'
+import fs from 'fs/promises'
+import config from '../base/config.mjs'
+
+export default class ServeHandler extends Parent {
+ loadTemplate(indexFile) {
+ this.template = indexFile.toString()
+ }
+
+ async serveIndex(ctx) {
+ if (config.get('NODE_ENV') === 'development') {
+ let indexFile = await fs.readFile(path.join(this.root, 'index.html'))
+ this.loadTemplate(indexFile)
+ }
+
+ ctx.body = this.template
+ ctx.type = 'text/html; charset=utf-8'
+ }
+}
diff --git a/nfp_is/api/server.mjs b/nfp_is/api/server.mjs
new file mode 100644
index 0000000..2ee249d
--- /dev/null
+++ b/nfp_is/api/server.mjs
@@ -0,0 +1,27 @@
+import config from '../base/config.mjs'
+import Parent from '../base/server.mjs'
+import StaticRoutes from '../base/static_routes.mjs'
+import ServeHandler from './serve.mjs'
+
+export default class Server extends Parent {
+ init() {
+ super.init()
+ let localUtil = new this.core.sc.Util(import.meta.url)
+
+ delete this.flaskaOptions.appendHeaders['Content-Security-Policy']
+ this.flaskaOptions.nonce = []
+
+ this.routes = {
+ static: new StaticRoutes(),
+ }
+ this.routes.serve = new ServeHandler({
+ root: localUtil.getPathFromRoot('../public'),
+ version: this.core.app.running,
+ frontend: config.get('frontend:url'),
+ })
+ }
+
+ runCreateDatabase() {
+ return {}
+ }
+}
diff --git a/nfp_is/app/footer.js b/nfp_is/app/footer.js
new file mode 100644
index 0000000..9d00427
--- /dev/null
+++ b/nfp_is/app/footer.js
@@ -0,0 +1,51 @@
+var m = require('mithril')
+var Helper = require('./helper')
+
+var Footer = {
+ oninit: function(vnode) {
+ vnode.state.scrollListenerWaiting = []
+ },
+
+ view: function(vnode) {
+ return [
+ m('div.outerbox', [
+ m('div.innerbox', [
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/contact.svg',
+ })
+ },
+ }),
+ m('aside', [
+ m('h3', 'Hafðu samband'),
+ m('p', `
+ Sendu okkur tölvupóst og lýstu þínum þörfum. Við munum setja okkur
+ inn í málin og finna lausnir. Við bjóðum persónulega og
+ metnaðarfulla þjónustu fyrir alla okkar viðskiptavini.
+ `),
+ m('h5', 'nfp@nfp.is'),
+ ]),
+ ]),
+ m('div.meta', [
+ m('span', 'Nordic Freelance Partners ehf.'),
+ m('span', 'nfp@nfp.is'),
+ m('span', 'kt. 420623-0110'),
+ m('span', [
+ 'Bakgrunnsmyndir frá ',
+ m('a', { href: 'https://www.freepik.com/pikisuperstar' }, 'pikisuperstar úr freepik.com'),
+ ]),
+ ]),
+ ]),
+ ]
+ },
+}
+
+/*
+ Background vector created by pikisuperstar - www.freepik.com
+*/
+
+module.exports = Footer
diff --git a/nfp_is/app/front/front.styl b/nfp_is/app/front/front.styl
new file mode 100644
index 0000000..55658fc
--- /dev/null
+++ b/nfp_is/app/front/front.styl
@@ -0,0 +1,138 @@
+article {
+ &.solution {
+ box-shadow: 0 5px 50px #0005;
+ background: #e9e9e9;
+ margin: 0 0 5vh;
+ height: 800px;
+
+ h3 {
+ font-size: 5vh;
+ padding: 5vh 20px;
+ font-weight: bold;
+ text-align: center;
+ position: relative;
+ align-self: center;
+
+ .left, .right {
+ position: absolute;
+ top: 50%;
+ margin-top: 0px;
+ border-bottom: 2px solid #29688c;
+ }
+
+ .left {
+ right: 100%;
+ left: -9999px;
+ }
+
+ .right {
+ left: 100%;
+ right: -9999px;
+ }
+ }
+ }
+
+ &.hosting {
+ height: 600px;
+ }
+
+ &.programming {
+ background: #29688c;
+ background: linear-gradient(150deg, #020024 15%, #29688c 100%);
+ color: white;
+ position: relative;
+ min-height: auto;
+ height: 70vw;
+ max-height: 80vh;
+ min-height: 600px;
+
+ section {
+ }
+
+ aside {
+ align-self: flex-start;
+ position: relative;
+ z-index: 2;
+ margin-top: 5vh;
+ flex: 1 1 auto;
+ width: 90%;
+ max-width: 1440px;
+
+ .item {
+ width: 50%;
+ min-width: 500px;
+ text-align: left;
+ }
+ }
+
+ h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+ }
+
+ a {
+ border-color: white;
+ color: white;
+ align-self: flex-start;
+ }
+
+ .image {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ width: 87%;
+ height: 90%;
+ max-width: none;
+ background-position: right bottom;
+ background-size: contain;
+ }
+ }
+
+ &.video {
+ min-height: 70vh;
+ }
+}
+
+@media only screen and (max-width: 810px) {
+ article.solution h3 {
+ font-size: 2em;
+ }
+}
+
+@media only screen and (max-width: 800px) {
+ article.programming {
+ max-height: none;
+ min-height: auto;
+ padding: 0 40px 300px;
+
+ section {
+ }
+
+ aside {
+ margin-top: 10px;
+ width: 100%;
+
+ .item {
+ width: 100%;
+ min-width: auto;
+ }
+ }
+
+ h3 {
+ align-self: center;
+ }
+
+ .image {
+ width: 100%;
+ height: 300px;
+ max-width: none;
+ background-position: right bottom;
+ background-size: contain;
+ transform: translate(50%, 0);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+}
diff --git a/nfp_is/app/front/index.js b/nfp_is/app/front/index.js
new file mode 100644
index 0000000..c83848a
--- /dev/null
+++ b/nfp_is/app/front/index.js
@@ -0,0 +1,239 @@
+var m = require('mithril')
+var Helper = require('../helper')
+
+var Front = {
+ oninit: function(vnode) {
+ Helper.init(vnode, 'frontpage', {
+ ratio: 0.91,
+ })
+ },
+
+ view: function(vnode) {
+ return [
+ m('header', {
+ oncreate: function(subnode) {
+ vnode.state.domContainer = subnode.dom
+ Helper.checkCreated(vnode)
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ })
+ },
+ }, m('div.container', [
+ !vnode.state.isMobile ? m('video', {
+ oncreate: function(subnode) {
+ vnode.state.domVideo = subnode.dom
+ Helper.checkCreated(vnode)
+ },
+ preload: 'none',
+ loop: true,
+ muted: true,
+ playsinline: true,
+ }, [
+ m('source', {
+ src: vnode.state.videoUrl,
+ type: 'video/mp4',
+ }),
+ m('source', {
+ src: '/assets/cover/frontpage.webm',
+ type: 'video/webm',
+ }),
+ ]
+ ) : m('div', {
+ oncreate: function(subnode) {
+ vnode.state.domVideo = subnode.dom
+ Helper.checkCreated(vnode)
+ },
+ }),
+ m('div',
+ m('img', {
+ oncreate: function(subnode) {
+ vnode.state.domImg = subnode.dom
+ Helper.lazyLoadImage(vnode, 'domImg', '/assets/cover/frontpage.jpg')
+ Helper.checkCreated(vnode)
+ },
+ src: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAQCAwMDAgQDAwMEBAQEBQkGBQUFBQsICAYJDQsNDQ0LDAwOEBQRDg8TDwwMEhgSExUWFxcXDhEZGxkWGhQWFxb/2wBDAQQEBAUFBQoGBgoWDwwPFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhb/wgARCABaAKADASIAAhEBAxEB/8QAGgAAAwEBAQEAAAAAAAAAAAAAAgMEAQAFB//EABkBAQEBAQEBAAAAAAAAAAAAAAECAAMEBf/aAAwDAQACEAMQAAAB+fctH2/iXeVbCXGuni5OaBWbztuNz9PnjWrPE2zT5h18PkJrjOnsFG6uRzkootzKNxwotobs1ezjvBwuphfgk1rSNdy5uN01MW4+RUEUZZ9QZaL5pZlDkIulMruzVrU6b0VTBh0uKnox8JcbYpeKfDwtfKy4vf5xdOd8yNRnGSJ49ypbUzSsII6Bhr8/TCAlPu657eYHFXLcBobWoYjail8FNS6SpOJV0jHTz9DfJ6TPrriILonHqhG1CDx25jnYvaHWSX1znHGUFndU/wD/xAAhEAADAAICAwADAQAAAAAAAAAAAQIQEQMgEiExEyJBQv/aAAgBAQABBQKnomi/nMhoazsQkeLGsSxo8B8Xq51jleyH7q/XI8NDRo0SiEPQ9D0cSR4IekO1rmYxVi2POjQlhMqjZsm9H5CmbGNCoVlMQxCHljyiUeA4ND0KiWJbNaGySPZaxJQ8MRLFfqqLY2SShVpclmxUcfIO9n9lFIrrsbHRs4hsqjeUyWQzzHRWNZYx4iiqN9EJio2eRskZo0Uhjwhvuuks2JiKkpDRrDwukSeH63mTYmcbGx9dCgc4Qq0fl9N7ymbJJ+VWIKWYJOT4+iH04/v+f6/kjP/EABwRAAIDAQEBAQAAAAAAAAAAAAABAhARIBIhQf/aAAgBAwEBPwFISNNN4TEZ2zRSJU4jTVK1EURx+nkwaHE82rfGGDQhOpPBPTDKwkYfp//EABwRAAMBAAIDAAAAAAAAAAAAAAABERAgIQISMP/aAAgBAgEBPwG5ONHl+ME8TLxpTxfR7FExMuseJ6mUpcaKJUfRRMpRMuf/xAAUEAEAAAAAAAAAAAAAAAAAAABw/9oACAEBAAY/AnD/xAAbEAEBAQEBAQEBAAAAAAAAAAABABEQISAxQf/aAAgBAQABPyF1bwG+ndzIb1wzwS9mkYTJN0kMx4G8e9hhxlt58hqUyJxeJCspGCwlsc9TfWDDpb4ZQ0nZUVl5+NuXq8XqPnOw63gn78Nr2cUnxQ8QOKsCzn9hyIhxmxT1vDmdnijSeXBgEGzxhztY4PO8wEYcWrb8SAI0lrBMzpdYcGb9I3wXLYnqDhh5wGIJi23LwZO/KXlevJumQ2/srbbNtGDPDbEvJ6DzmSWWwxqSUgyRlov4cyw3jM9Mc1JtrDYt4X7j5Cfvj1+oj4L2P1f/2gAMAwEAAgADAAAAEJfK1cHvJurU1ZyigO6xZhbQ1tS7V0hPtb08C1iCrD9IB0dS0jX6/HNHdekp0f/EABgRAQEBAQEAAAAAAAAAAAAAAAEAERAh/9oACAEDAQE/ENSYhkBkFvHCSazlg8ktnWCyxB4AIFZElJZRJt6WVtAHG/HxLjbyR6+wsZScWY7bGSccljCDJLDLOw9ywcf/xAAbEQEBAQADAQEAAAAAAAAAAAABABEQITFRMP/aAAgBAgEBPxBxbs6syBlS2+ODdre4bLznJJjSwka4SeHE/kVp0tQwvpaStlEIT20vUUOpeStq3NCh0v/EAB4QAQEBAQEBAQEBAQEAAAAAAAEAESExEEFRYbEg/9oACAEBAAE/EOyheLb6MeWjwlPy0pSYKt4hOHkL8jDZMJvpI+MreSMJZMI5B3YeNib2yuxZ5dvPgu3hyINJjOFrvkqGxy2PJL+WnxI8u1wVkzdkHvznOy7xv8LP4CrI2fc2dPWF/YvjY/bvbL/Znbd5AdGBxsftdrhPV6p4xiSHKM625YW3ELWAb38gf5J/ZWItFEubFsMFi0tcS+wUzJB7Dfhw2V8E3ht9bNvs6hAtln8ujGXfZj9mDv0dHexEFy3sjJhT9gY2Y7sqZto2TWxZIvtt+yMMlH2Vw2A6sZm3uYeDKy3ESwmS9TIM2RPZF9+NllYfs2Zs/wBreZts9n6RxyReQw8kyTYXMhqy5FDfiO2iFsY2W2LG8t71iU2Nhd2Knkfy8sCkT4uSNQoQ7B1zyI4T3IYCBvti8ZXOxc7IPYlkHs/7+GmT4RXlo7A9R6Fp6WxdmGeIm77NElszIzjGNYHE+Xu8Is8Ihc/Pu2F33/xniPbyn/i/7wM8nnnz/9k=',
+ })
+ ),
+ m('nav', [
+ m(m.route.Link, { class: 'title', href: '/' }, m('span', 'NFP')),
+ m('div.filler'),
+ m(m.route.Link, { href: '/hosting-solutions' }, [ 'Hýsingarlausnir', m('div') ]),
+ m(m.route.Link, { href: '/programming-solutions' }, [ 'Forritunarlausnir', m('div') ]),
+ m(m.route.Link, { href: '/video-solutions' }, [ 'Videólausnir', m('div') ]),
+ ]),
+ m('div.content', [
+ m('h1', 'Nýjir tímar kalla á nýjar lausnir'),
+ m('h2', '...og við erum með þær'),
+ ]),
+ ])
+ ),
+ m('main', [
+ // Solutions
+ m('article.solution', [
+ m('h3', [
+ 'Hvað getum við gert fyrir þig?',
+ m('div.left'),
+ m('div.right'),
+ ]),
+ m('section', [
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h5', 'Þínar þarfir'),
+ m('p', `
+ Þarfir fólks og fyrirtækja eru margvíslegar og krefjast
+ oft sérstæðrar nálgunar. Starfslið okkar hefur víðtæka
+ reynslu í þarfagreiningu og útfærslum á ýmsum sviðum
+ hins stafræna nútíma.
+ `),
+ ]),
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h5', 'Okkar lausnir'),
+ m('p', `
+ Hvort sem þú ert að leitast eftir hýsingu, hugbúnaðargerð,
+ vefhönnun, streymi- eða upptökulausnum, þá erum við með
+ þekkinguna og reynsluna. Við erum alltaf tilbúnir til
+ leiks og elskum að taka að okkur krefjandi verkefni.
+ `),
+ ]),
+ ]),
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/solutions.svg',
+ })
+ },
+ }),
+ ]),
+ ]),
+ // Solutions
+ m('article.hosting', [
+ m('section', [
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Hýsingarlausnir'),
+ m('p', `
+ Hvort heldur sem þig vantar vefhýsingu, sýndarvélar eða
+ geymslu og meðhöndlun gagna þá getum við fundið lausn sem
+ hentar þér.
+ `),
+ m(m.route.Link, { class: 'next', href: '/hosting-solutions' }, 'Lesa meira'),
+ ]),
+ ]),
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/hosting.svg',
+ })
+ },
+ }),
+ ]),
+ ]),
+ // Programming
+ m('article.programming', [
+ m('section', [
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Forritunarlausnir'),
+ m('p', `
+ Ef þig vantar sérlausn eða aðstoð með þín verkefni að þá
+ getum við hjálpað þér. Við höfum yfir 20 ára reynslu í
+ forritun og hugbúnaðargerð.
+ `),
+ m(m.route.Link, { class: 'next', href: '/programming-solutions' }, 'Lesa meira'),
+ ]),
+ ]),
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/programming.svg',
+ })
+ },
+ }),
+ ]),
+ ]),
+ // Programming
+ m('article.video', [
+ m('section', [
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Streymi- og upptökulausnir'),
+ m('p', `
+ Hvort sem er að ræða fundi eða ráðstefnur þá tökum við að
+ okkur upptökur og streymingu á þeim. Við höfum margra ára
+ reynslu og getum unnið í hvaða sal sem er.
+ `),
+ m(m.route.Link, { class: 'next', href: '/video-solutions' }, 'Lesa meira'),
+ ]),
+ ]),
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/video.svg',
+ })
+ },
+ }),
+ ]),
+ ]),
+ ]),
+ ]
+ },
+}
+
+/*
+Background vector created by macrovector - www.freepik.com
+*/
+
+module.exports = Front
diff --git a/nfp_is/app/helper.js b/nfp_is/app/helper.js
new file mode 100644
index 0000000..62a9393
--- /dev/null
+++ b/nfp_is/app/helper.js
@@ -0,0 +1,249 @@
+var Helper = {
+ init: function(vnode, filename, options) {
+ vnode.state.domImg = null
+ vnode.state.domVideo = null
+ vnode.state.domContainer = null
+ vnode.state.isMobile = Helper.isMobile()
+
+ vnode.state.videoShow = false
+ vnode.state.videoFilename = filename
+ vnode.state.resizePauseTimeout = null
+ vnode.state.resizeTimeout = null
+ vnode.state.videoResizeThrottler = Helper.resizeThrottler.bind(vnode.state, vnode)
+ vnode.state.scrollListener = null
+ vnode.state.scrollListenerWaiting = []
+ vnode.state.videoVisibilityHidden = ''
+ vnode.state.videoVisibilityEvent = null
+ vnode.state.videoVisibilityChanged = null
+ vnode.state.videoResizeRatio = options && options.ratio || 1
+ vnode.state.videoUrl = screen.width > 1280
+ ? '/assets/cover/' + filename + '_1080.mp4'
+ : '/assets/cover/' + filename + '_720.mp4'
+ },
+
+ isMobile: function() {
+ var check = false;
+ (function(a) {
+ if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true
+ })(navigator.userAgent || navigator.vendor || window.opera);
+ return check
+ },
+
+ clear: function(vnode) {
+ vnode.state.scrollListenerWaiting.splice(0, vnode.state.scrollListenerWaiting.length)
+ window.removeEventListener('resize', vnode.state.videoResizeThrottler)
+ window.removeEventListener('scroll', vnode.state.scrollListener, false)
+ window.removeEventListener(vnode.state.videoVisibilityEvent, vnode.state.videoVisibilityChanged)
+ },
+
+ scrollListener: function(vnode) {
+ if (!vnode.state.scrollListenerWaiting.length) return
+
+ var scrollTop = window.pageYOffset
+ var height = window.innerHeight
+
+ for (var i = 0; i < vnode.state.scrollListenerWaiting.length; i++) {
+ Helper.scrollItemIsVisible(vnode, vnode.state.scrollListenerWaiting[i], scrollTop, height)
+ }
+ },
+
+ scrollCheckEmpty: function(vnode) {
+ if (vnode.state.scrollListenerWaiting.length) return
+
+ vnode.state.scrollListener = null
+ window.removeEventListener('scroll', vnode.state.scrollListener, false)
+ },
+
+ scrollAddItem: function(vnode, options) {
+ var bound = options.dom.getBoundingClientRect()
+ var scrollTop = window.pageYOffset
+
+ var item = {
+ dom: options.dom,
+ threshold: options.threshold || 100,
+ top: Math.round(bound.top) + Math.round(scrollTop),
+ bottom: Math.round(bound.bottom) + Math.round(scrollTop),
+ className: ' ' + options.className,
+ img: options.img || null,
+ ticking: false,
+ }
+
+ vnode.state.scrollListenerWaiting.push(item)
+
+ if (!vnode.state.scrollListener) {
+ vnode.state.scrollListener = Helper.scrollListener.bind(vnode.state, vnode)
+ window.addEventListener('scroll', vnode.state.scrollListener, false)
+ }
+ Helper.scrollItemIsVisible(vnode, item, window.pageYOffset, window.innerHeight)
+ },
+
+ scrollResetBound: function(vnode) {
+ var scrollTop = window.pageYOffset
+
+ vnode.state.scrollListenerWaiting.forEach(function (item) {
+ var bound = item.dom.getBoundingClientRect()
+ item.top = Math.round(bound.top) + Math.round(scrollTop)
+ })
+ },
+
+ scrollItemIsVisible: function(vnode, item, scrollTop, height) {
+ if (item.ticking) return
+
+ if (item.top - item.threshold < scrollTop + height) {
+ item.ticking = true
+
+ if (item.img) {
+ Helper.lazyLoadImage(vnode, null, item.img, function() {
+ item.dom.style.backgroundImage = 'url("' + item.img + '")'
+
+ requestAnimationFrame(function() {
+ item.dom.className += item.className
+ var index = vnode.state.scrollListenerWaiting.indexOf(item)
+
+ if (index >= 0) {
+ vnode.state.scrollListenerWaiting.splice(index, 1)
+ }
+ Helper.scrollCheckEmpty(vnode)
+ })
+ })
+ } else {
+ requestAnimationFrame(function() {
+ item.dom.className += item.className
+ var index = vnode.state.scrollListenerWaiting.indexOf(item)
+
+ if (index >= 0) {
+ vnode.state.scrollListenerWaiting.splice(index, 1)
+ }
+ Helper.scrollCheckEmpty(vnode)
+ })
+ }
+ }
+ },
+
+ checkCreated: function(vnode) {
+ if (!vnode.state.domImg || !vnode.state.domVideo || !vnode.state.domContainer) return
+
+ vnode.state.videoShow = Boolean(vnode.state.domVideo.play)
+
+ window.addEventListener('resize', vnode.state.videoResizeThrottler, false)
+
+ Helper.resizeHandler(vnode)
+ if (vnode.state.videoShow) {
+ vnode.state.domVideo.play()
+
+ if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
+ vnode.state.videoVisibilityHidden = 'hidden'
+ vnode.state.videoVisibilityEvent = 'visibilitychange'
+ } else if (typeof document.msHidden !== 'undefined') {
+ vnode.state.videoVisibilityHidden = 'msHidden'
+ vnode.state.videoVisibilityEvent = 'msvisibilitychange'
+ } else if (typeof document.webkitHidden !== 'undefined') {
+ vnode.state.videoVisibilityHidden = 'webkitHidden'
+ vnode.state.videoVisibilityEvent = 'webkitvisibilitychange'
+ }
+
+ if (vnode.state.videoVisibilityHidden && vnode.state.videoVisibilityEvent) {
+ vnode.state.videoVisibilityChanged = Helper.visibilityChanged.bind(this, vnode)
+
+ document.addEventListener(vnode.state.videoVisibilityEvent, vnode.state.videoVisibilityChanged, false)
+ }
+ }
+ },
+
+ visibilityChanged: function(vnode) {
+ if (document[vnode.state.videoVisibilityHidden]) {
+ vnode.state.domVideo.pause()
+ } else {
+ vnode.state.domVideo.play()
+ }
+ },
+
+ resizeThrottler: function(vnode) {
+ if (vnode.state.videoShow) {
+ if (!vnode.state.resizePauseTimeout) {
+ vnode.state.domVideo.pause()
+ }
+ clearTimeout(vnode.state.resizePauseTimeout)
+ vnode.state.resizePauseTimeout = setTimeout(function () {
+ vnode.state.resizePauseTimeout = null
+
+ requestAnimationFrame(function() {
+ Helper.scrollResetBound(vnode)
+ vnode.state.domVideo.play()
+ })
+ }, 250)
+ }
+
+ if (!vnode.state.resizeTimeout) {
+ vnode.state.resizeTimeout = setTimeout(function () {
+ vnode.state.resizeTimeout = null
+ Helper.resizeHandler(vnode)
+ }, 66)
+ }
+ },
+
+ resizeHandler: function(vnode) {
+ var height = Helper.getHeight(vnode)
+ var width = document.documentElement.clientWidth
+
+ Helper.scaleContainer(vnode, height)
+ Helper.scaleContainerContent(vnode, 'domImg', true, width, height)
+ Helper.scaleContainerContent(vnode, 'domVideo', false, width, height)
+ },
+
+ lazyLoadImage: function(vnode, name, url, cb) {
+ if (!vnode.state[name] && !cb) return
+
+ var img = document.createElement('img')
+ img.onload = function() {
+ if (cb) {
+ cb()
+ } else {
+ vnode.state[name].src = url
+ }
+ }
+ img.src = url
+ },
+
+ scaleContainer: function(vnode, height) {
+ if (!vnode.state.domContainer) return
+ vnode.state.domContainer.setAttribute('style', 'height: ' + height + 'px;')
+ },
+
+ scaleContainerContent: function(vnode, name, forceHeight, width, height) {
+ if (!vnode.state[name]) return
+
+ var videoRatio = 0.5625
+ var windowRatio = height / width
+
+ if (windowRatio > videoRatio) {
+ var videoWidth = height / videoRatio
+ var marginFromLeft = -(videoWidth - width) / 2 + 'px'
+ vnode.state[name].setAttribute('style',
+ 'margin-top: 0; margin-left: ' + marginFromLeft + ';' +
+ 'width: ' + videoWidth + 'px; height: ' + height + 'px')
+ } else {
+ if (forceHeight) {
+ vnode.state[name].setAttribute('style',
+ 'width: ' + width + 'px; height: ' + height + 'px')
+ } else {
+ vnode.state[name].setAttribute('style',
+ 'width: ' + width + 'px;')
+ }
+ }
+ },
+
+ getHeight: function(vnode) {
+ var height = document.documentElement.clientHeight + 5
+ if (height < 485) {
+ height = 485
+ } else {
+ height = height * vnode.state.videoResizeRatio
+ }
+ return height
+ },
+}
+
+window.helper = Helper
+
+module.exports = Helper
diff --git a/nfp_is/app/hosting/hosting.styl b/nfp_is/app/hosting/hosting.styl
new file mode 100644
index 0000000..41f867d
--- /dev/null
+++ b/nfp_is/app/hosting/hosting.styl
@@ -0,0 +1,202 @@
+header.hosting {
+ h1 {
+ font-size: 4.3vw;
+ margin-bottom: 10px;
+ }
+ h2 {
+ font-size: 2.5vw;
+ }
+}
+
+article {
+ &.hostintro {
+ .image {
+ transform: translate(-50%, 0px);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+
+ &.hoststorage {
+ background: #29688c;
+ background: linear-gradient(150deg, #020024 15%, #29688c 100%);
+ color: white;
+ position: relative;
+ height: 80vh;
+ min-height: 600px;
+
+ section {
+ justify-content: flex-end;
+ }
+
+ aside {
+ align-items: center;
+ max-width: none;
+
+ .item {
+ width: 100%;
+ max-width: 600px;
+ text-align: left;
+ }
+ }
+
+ h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+ }
+
+ .image {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 50%;
+ height: 90%;
+ max-width: none;
+ background-position: left center;
+ background-size: contain;
+ transform: translate(-50%, 0px);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+
+ &.hostmanaged {
+ position: relative;
+ height: 80vh;
+ min-height: 600px;
+
+ section {
+ justify-content: flex-end;
+ }
+
+ aside {
+ align-items: center;
+ max-width: none;
+
+ .item {
+ padding-left: 20px;
+ width: 100%;
+ max-width: 600px;
+ text-align: left;
+ }
+ }
+
+ h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+ }
+
+ .image {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 50%;
+ height: 90%;
+ max-width: none;
+ background-position: left center;
+ background-size: contain;
+ transform: translate(-50%, 0px);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+}
+
+@media only screen and (max-width: 800px) {
+ header.hosting {
+ h1 {
+ font-size: 2.3em;
+ }
+ h2 {
+ font-size: 1.5em;
+ }
+ }
+
+ article {
+ &.hostintro {
+ h3 {
+ padding: 30px 0 30px;
+ }
+
+ .image {
+ transform: translate(0, 50%);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+
+ &.hoststorage {
+ min-height: auto;
+ padding: 0;
+
+ section {
+ justify-content: flex-start;
+ padding-bottom: 0;
+ }
+
+ aside {
+ order: 1;
+ padding: 0 50px;
+ }
+
+ .image {
+ width: 100%;
+ height: auto;
+ background-position: center;
+ padding-top: 66%;
+ position: relative;
+ order: 2;
+ }
+ }
+
+ &.hostmanaged {
+ min-height: auto;
+ padding: 0;
+
+ section {
+ justify-content: flex-start;
+ padding-bottom: 0;
+ }
+
+ aside {
+ order: 1;
+ padding: 0 50px;
+ }
+
+ aside .item {
+ padding-left: 0;
+ }
+ .image {
+ position: relative;
+ width: 100%;
+ padding-top: 68%;
+ height: auto;
+ order: 2;
+ }
+ }
+ }
+}
+
+@media only screen and (max-width: 500px) {
+ article {
+ &.hoststorage {
+ aside {
+ padding: 0 10px;
+ }
+ }
+
+ &.hostmanaged {
+ aside {
+ padding: 0 10px;
+ }
+ }
+ }
+}
diff --git a/nfp_is/app/hosting/index.js b/nfp_is/app/hosting/index.js
new file mode 100644
index 0000000..7cbb882
--- /dev/null
+++ b/nfp_is/app/hosting/index.js
@@ -0,0 +1,207 @@
+var m = require('mithril')
+var Helper = require('../helper')
+
+var Hosting = {
+ oninit: function(vnode) {
+ Helper.init(vnode, 'hosting')
+ },
+
+ onremove: function(vnode) {
+ Helper.clear(vnode)
+ },
+
+ view: function(vnode) {
+ return [
+ m('header.hosting', {
+ oncreate: function(subnode) {
+ vnode.state.domContainer = subnode.dom
+ Helper.checkCreated(vnode)
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ })
+ },
+ }, m('div.container', [
+ !vnode.state.isMobile ? m('video', {
+ oncreate: function(subnode) {
+ vnode.state.domVideo = subnode.dom
+ Helper.checkCreated(vnode)
+ },
+ preload: 'none',
+ loop: true,
+ muted: true,
+ playsinline: true,
+ }, [
+ m('source', {
+ src: vnode.state.videoUrl,
+ type: 'video/mp4',
+ }),
+ m('source', {
+ src: '/assets/cover/hosting.webm',
+ type: 'video/webm',
+ }),
+ ]
+ ) : m('div', {
+ oncreate: function(subnode) {
+ vnode.state.domVideo = subnode.dom
+ Helper.checkCreated(vnode)
+ },
+ }),
+ m('div',
+ m('img', {
+ oncreate: function(subnode) {
+ vnode.state.domImg = subnode.dom
+ Helper.lazyLoadImage(vnode, 'domImg', '/assets/cover/hosting.jpg')
+ Helper.checkCreated(vnode)
+ },
+ src: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCABaAKADASIAAhEBAxEB/8QAGgAAAwEBAQEAAAAAAAAAAAAAAQIDAAQFBv/EABcBAQEBAQAAAAAAAAAAAAAAAAEAAgP/2gAMAwEAAhADEAAAAfisu652ITFMJkZ5vRZXzRl0L0OdOmc8y1nmutJtHFctzBsVtFkoYmgpWfSeLxpsnSIyaFhWOXqRxm5g0mLo2HEGARqGAr0GiylNNKqobSZB6TNtE+e8am2cUJKJmBDbZexpmih2gBhU0pOqmTZRNptWibplyoihkIrIIVzPc+l25h1x0rz5qxyCzyfDkKJQA406jIQ5WIZSttiy5NTBcRQoT0lUlV0D/8QAHRAAAgMBAQEBAQAAAAAAAAAAAAEQESACMRJBMP/aAAgBAQABBQKy82fvPh0VLEIYznbF7z4OKGhwhjFNlyzn3mHhn6joYi4ssuV7zDw45GP+PPqhllw45GMZe16oeuRsYxZss5FD0hwxFFFFFFCFtilizRQ82WNjFLiyyyz6PoubLLwpYoQ5YtWXCliwoYpelLP/xAAaEQACAwEBAAAAAAAAAAAAAAABEQAQIDBA/9oACAEDAQE/AbVv0vTyjAC6Ii7f/8QAHREAAwEBAQADAQAAAAAAAAAAAAEREBICEyAhMf/aAAgBAgEBPwH8JnWIhBeof3KzoueVRqDYspS6nBu4oMXg+M4H5mcnJzkLDo6G1MXo6LlyE+lLv//EABQQAQAAAAAAAAAAAAAAAAAAAHD/2gAIAQEABj8CcP/EABsQAQEBAQEBAQEAAAAAAAAAAAEAERAhIDFB/9oACAEBAAE/ISepLObM3qExJ4HsPPjb8bxfNMngMft+PibD02ez8d7bL2/PT9cb8BZeS8hnxnn+347jjHwSy+Sj8tnHBZX9l53/AFwNpbx7Py2dtsstsuC4UsMsMxi9l5bK22WeOU8ifMRhGMOMvLZ9sskk4cs8HOBZtlixDGGGG0kSODlb1vHq89memG2Zq1bLPG2ylLLrOP1HG23hiy+R+Dx+o+z83//aAAwDAQACAAMAAAAQQxMUBpQhhWsZvsfymwhtADDvcnRC6d2P9ahJ5zPOwQHzNBJeJ9ae+/zQ637l/8QAGhEAAwEBAQEAAAAAAAAAAAAAAAERECEgMf/aAAgBAwEBPxDpfBuCFIfBKeWLolrqKyl2Y8bxUJrKirVOtHYNglWNbylkyeYTf//EABoRAQEBAQEBAQAAAAAAAAAAAAEAESEQMUH/2gAIAQIBAT8Q24/J58lfPAJO5zJxMBiBXT43BI8bjl1JkcQMsWnn4Jfpvt27YXkqbfEqTwJtygg1tl2wbG5sCd4yPDuzHwdY6nEngypUtrf/xAAbEAEBAQEBAQEBAAAAAAAAAAABABEhEDFBIP/aAAgBAQABPxBCQOwrGJ5ckX7ATl8JLXxU8jw5ehWcjL8nZWy8uU9N8I+2ZDF44+79w0uGcfviqOLOyM8PmfMPZz150mZ46od8KDYyTuMEdXG0L53D6pjcSly2vnz8eDu3l3ZeS74JNJyx50J147ep0Q43EAwn2W+WM7CbIycy5nBF2j+AkbcbhC2d8E/JNllk2TLS8keI9Byu3K4Slbvg3bM8V2fJuvgIIO363Hjp66JdMsHwCM5bCEHG4XSH9uXqQQ+TxL4CzhjC6TF5kp+w74eEPJjfg5zxPl4XazOy1jUlQ8ly2VmTPo+19JIXx4Pfz7PiPD6+h6//2Q==',
+ })
+ ),
+ m('nav', [
+ m(m.route.Link, { class: 'title', href: '/' }, m('span', 'NFP')),
+ m('div.filler'),
+ m(m.route.Link, { class: 'active', href: '/hosting-solutions' }, [ 'Hýsingarlausnir', m('div') ]),
+ m(m.route.Link, { href: '/programming-solutions' }, [ 'Forritunarlausnir', m('div') ]),
+ m(m.route.Link, { href: '/video-solutions' }, [ 'Videólausnir', m('div') ]),
+ ]),
+ m('div.content', [
+ m('h1', 'Hýsingarlausnir sem þú getur treyst'),
+ m('h2', 'SÝNDARVÉLAR, WORDPRESS, GEYMSLUHÝSING, OG HVAÐ EINA!'),
+ ]),
+ ])
+ ),
+ m('main', [
+ // Solutions
+ m('article.hostintro', [
+ m('section', [
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/hostintro.svg',
+ })
+ },
+ }),
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Vefhýsing'),
+ m('p', `
+ Við getum boðið okkar viðskiptavinum upp á margskonar
+ lausnir þegar kemur að hýsa þeirra vefi. Meðal þess sem
+ við höfum reynslu af er að setja upp sýndarvélar sem þú
+ getur haft fulla umsjá með og gert hvað svo sem þig lystir
+ með en einnig sérhæfum okkur í að bjóða upp á
+ alsherjarlausnir þar sem við sjáum um alla uppsetningu og
+ umsjón svo að þú getir haft athyglina á öðrum þáttum
+ reksturs þíns.
+ `),
+ m('p', `
+ Ef þig vantar Wordpress/PHP uppsetningu eða hefur sérhæfða
+ síðu og vilt nota docker eða node þá munar okkur ekki um
+ það. Okkar kerfi geta séð um að mæta þínum þörfum hverjar
+ sem þær eru.
+ `),
+ ]),
+ ]),
+ ]),
+ ]),
+ m('article.hoststorage', [
+ m('section', [
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/hostfile.svg',
+ })
+ },
+ }),
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Gagnageymslur og skölun myndefnis'),
+ m('p', `
+ Örugg geymsla gagna er sífellt mikilvægari þáttur fyrir
+ fyrirtæki. NFP hefur boðið upp á gagnageymslu fyrir
+ fyrirtæki til að geyma sín afrit eða vinnslugögn sem
+ starfsmenn geta haft aðgang að og unnið með hvar sem
+ þeir eru staddir í heiminum.
+ `),
+ m('p', `
+ Við getum einnig séð um hvers kyns meðhöndlun myndgagna
+ svo sem endurkóðun upptökuefnis til að lágmarka rýmisþörf
+ með bestu mögulegu gæðum eða skölun á myndum fyrir
+ vefsíðubirtingar. Lausnir okkar eru skilvirkar og
+ afkastamiklar.
+ `),
+ ]),
+ ]),
+ ]),
+ ]),
+ m('article.hostmanaged', [
+ m('section', [
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/hostmanaged.svg',
+ })
+ },
+ }),
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Láttu okkur sjá um viðhaldið'),
+ m('p', `
+ Það getur verið kúnst að viðhalda sýndarvélum og
+ heimasíðum og Það er ekki á allra hendi að framkvæma
+ Wordpress uppfærslur eða prófanir á öryggisafritum.
+ `),
+ m('p', `
+ Þú átt að geta einbeitt þér að þínu sérsviði. Þess vegna
+ bjóðum við upp á að sjá um allt sem kemur að viðhaldi og
+ gæðaeftirliti. Við fylgjumst vel með þróuninni, gerum
+ reglulegar uppfærslur og tryggjum að allt virki sem
+ skildi.
+ `),
+ ]),
+ ]),
+ ]),
+ ]),
+ ]),
+ ]
+ },
+}
+
+/*
+Background vector created by macrovector - www.freepik.com
+*/
+
+module.exports = Hosting
diff --git a/nfp_is/app/index.js b/nfp_is/app/index.js
new file mode 100644
index 0000000..fb27ac8
--- /dev/null
+++ b/nfp_is/app/index.js
@@ -0,0 +1,42 @@
+/**
+ * @license
+ * NFP
+ * Copyright 2018 Jonatan Nilsson
+ *
+ * Available under WTFPL License (http://www.wtfpl.net/txt/copying/)
+*/
+
+'use strict'
+
+//Add debug components to window. Allows us to play with controls
+//in the console.
+window.components = {}
+
+var m = require('mithril')
+
+m.route.setOrig = m.route.set
+m.route.set = function(path, data, options){
+ m.route.setOrig(path, data, options)
+ window.scrollTo(0, 0)
+}
+
+m.route.linkOrig = m.route.link
+m.route.link = function(vnode){
+ m.route.linkOrig(vnode)
+ window.scrollTo(0, 0)
+}
+
+var Front = require('./front')
+var Hosting = require('./hosting')
+var Programming = require('./programming')
+var Streaming = require('./streaming')
+var Footer = require('./footer')
+
+m.route.prefix = ''
+m.route(document.getElementById('container'), '/', {
+ '/': Front,
+ '/hosting-solutions': Hosting,
+ '/programming-solutions': Programming,
+ '/video-solutions': Streaming,
+})
+m.mount(document.getElementById('footer'), Footer)
diff --git a/nfp_is/app/programming/index.js b/nfp_is/app/programming/index.js
new file mode 100644
index 0000000..117792f
--- /dev/null
+++ b/nfp_is/app/programming/index.js
@@ -0,0 +1,205 @@
+var m = require('mithril')
+var Helper = require('../helper')
+
+var Programming = {
+ oninit: function(vnode) {
+ Helper.init(vnode, 'programming')
+ },
+
+ onremove: function(vnode) {
+ Helper.clear(vnode)
+ },
+
+ view: function(vnode) {
+ return [
+ m('header.programming', {
+ oncreate: function(subnode) {
+ vnode.state.domContainer = subnode.dom
+ Helper.checkCreated(vnode)
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ })
+ },
+ }, m('div.container', [
+ !vnode.state.isMobile ? m('video', {
+ oncreate: function(subnode) {
+ vnode.state.domVideo = subnode.dom
+ Helper.checkCreated(vnode)
+ },
+ preload: 'none',
+ loop: true,
+ muted: true,
+ playsinline: true,
+ }, [
+ m('source', {
+ src: vnode.state.videoUrl,
+ type: 'video/mp4',
+ }),
+ m('source', {
+ src: '/assets/cover/programming.webm',
+ type: 'video/webm',
+ }),
+ ]
+ ) : m('div', {
+ oncreate: function(subnode) {
+ vnode.state.domVideo = subnode.dom
+ Helper.checkCreated(vnode)
+ },
+ }),
+ m('div',
+ m('img', {
+ oncreate: function(subnode) {
+ vnode.state.domImg = subnode.dom
+ Helper.lazyLoadImage(vnode, 'domImg', '/assets/cover/programming.jpg')
+ Helper.checkCreated(vnode)
+ },
+ src: ' data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAA0JCgsKCA0LCgsODg0PEyAVExISEyccHhcgLikxMC4pLSwzOko+MzZGNywtQFdBRkxOUlNSMj5aYVpQYEpRUk//2wBDAQ4ODhMREyYVFSZPNS01T09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0//wgARCABaAKADASIAAhEBAxEB/8QAGQAAAwEBAQAAAAAAAAAAAAAAAQIDAAQF/8QAFwEBAQEBAAAAAAAAAAAAAAAAAQACA//aAAwDAQACEAMQAAAB8adF6cJioGIqprZ2RWdHICE0FoBe/PXXNpOqQleOO3YCmuZyGXA0F50gqyICGNYOsEgpObzztZUnnp1HDfPBhSYqaLzeHDFyuc0qNKnE0NUmozsqcPVhPfOw58NxHTXSNdTSOudMi00gpoqQaG2HY6qCra5846lnnFgMxUUrYVRAKzK7bNnKFtShsVWiUrkKKApqtefocvLoVxzC6G5CoGaXgKhBno4XT//EABsQAAMBAQEBAQAAAAAAAAAAAAABERAgMBIC/9oACAEBAAEFAnkITqlHixof5GvN8TaUfcITiE4ePKPaUomXwePxXVPo+hsvknkyD8aUvCFtGy+DKUpcQtflCEIQmXqEIQhMhCE2HzyvC9JHyP8AJCEJtKUvaPzr5fP/xAAaEQADAAMBAAAAAAAAAAAAAAAAAREQEiAC/9oACAEDAQE/AUUpS4oxU88PlC4eKI1EsQ1NSEIJcU2KXLKXEz6EylEQh//EABkRAAIDAQAAAAAAAAAAAAAAAAARASAwEP/aAAgBAgEBPwG8cnKcGPrGO6EIWUUkYz//xAAUEAEAAAAAAAAAAAAAAAAAAABw/9oACAEBAAY/AnD/xAAcEAEBAQEBAQADAAAAAAAAAAABABEQICEwMUH/2gAIAQEAAT8hWyeFkFkFudvqD7OPAKT4SyILISQWcBDnLXLZPMsmEJk2RwyDrZTwrbeWnKxeDxifdnHgemz5CXxlknN8DODJZPneuLS+Xzwb0M2fLLyGyl8t4pss9Jw+cZkQbZeB6AwNjm1mWX3asT8LZY4GZ4ZFI4PN4JLnnDhx8H8np4/rl8f/2gAMAwEAAgADAAAAEBr/AJK106M1iZzHPUQsF7qTyBHmplEJPpqBT2lWE8Kfxs8s7ywQsqGwhiTaN5D/xAAbEQEBAQEBAAMAAAAAAAAAAAABABEQITFRYf/aAAgBAwEBPxBZCiMNWHB+rCSxtljajZ2Gb4djEHoDAYSI1yR8zDUJAW23mKX92jAStWoXjPYIZJDhT1g2L//EABkRAQEBAQEBAAAAAAAAAAAAAAEAERAhIP/aAAgBAgEBPxBsLIJL2zhyBNt5GT8PwY5krKlcXPibbLPfU9nssWFhIW2y8IWWXi1av//EAB0QAQEBAQEBAAMBAAAAAAAAAAEAERAhMSBBUWH/2gAIAQEAAT8QSas1/wATi1suQt4mEid8MoBey14Z2LIttJx4Pq+YmBl/OXeDfqQZxObQtb25ARjYgpBBycQkrwfEHYJAJk8S96BWyMdEGC0t9ivEvDOHkJyzMXjIkhlm3rBJ+Q+yeRoxk9jgE3eXK8YHbUqaVIZaQaRC4sfk0q2TtlllggFjktKpiNkZacOIYJq28sssmWPyVatWrcu8R7l4NbTKkbIGxsySG8XrPM6SE6z5tbdtJ4vqDln8FDrhhxvLS+SH6hk7YsD15YXgWCHJhYIWZZvLaVIPkH8hP1A35CRiTJ1aJq5bJl5edl+EFnvOQn2/i//Z',
+ })
+ ),
+ m('nav', [
+ m(m.route.Link, { class: 'title', href: '/' }, m('span', 'NFP')),
+ m('div.filler'),
+ m(m.route.Link, { href: '/hosting-solutions' }, [ 'Hýsingarlausnir', m('div') ]),
+ m(m.route.Link, { class: 'active', href: '/programming-solutions' }, [ 'Forritunarlausnir', m('div') ]),
+ m(m.route.Link, { href: '/video-solutions' }, [ 'Videólausnir', m('div') ]),
+ ]),
+ m('div.content', [
+ m('h1', 'Sérfræðingar í forritun'),
+ m('h2', 'Meira en 20 ára reynsla!'),
+ ]),
+ ])
+ ),
+ m('main', [
+ // Solutions
+ m('article.programmingintro', [
+ m('section', [
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/programmingintro.svg',
+ })
+ },
+ }),
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Vefsíðuforritun'),
+ m('p', `
+ Með margra ára reynslu í forritun og yfirgripsmikla
+ þekkingu þegar kemur að vefsíðugerð, er ekkert sem stoppar
+ okkur í að leysa krefjandi verkefni. Hvort heldur sem um
+ er að ræða útfærslu á hönnun og innleiðing hennar í
+ HTML/CSS eða uppsetningu greiðslugátta og áskriftaleiða
+ hjá mismunandi aðilum að þá erum við sérfræðingar á því
+ sviði.
+ `),
+ m('p', `
+ Við getum unnið með hvaða forritunartungumál sem er.
+ Hvaða tækni sem þú notar, node, python, C# eða hvað
+ annað tungumál, þá látum við ekkert stoppa okkur.
+ `),
+ ]),
+ ]),
+ ]),
+ ]),
+ m('article.programmingstore', [
+ m('section', [
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/programmingstore.svg',
+ })
+ },
+ }),
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Sölukerfi og vefverslun'),
+ m('p', `
+ Við höfum hannað og þróað sölukerfi frá grunni í síðuformi.
+ Það er byggt til að vera einfalt í notkun og henta fyrir
+ lítil og meðalstór fyrirtæki. Sölukerfið býður upp á
+ pantanakerfi, verkbókhald og birgðakerfi sem og
+ vefverslunarframenda og tengingu við posa.
+ `),
+ m('p', `
+ Við getum aðlagað vefverslunarframendanum til að passa
+ fyrir hvert fyrirtæki og þeirra vöruframboði. Við vinnum
+ náið með hverjum og einum viðskiptavini og skilum af okkur
+ lausn sem uppfyllir þarfir þeirra.
+ `),
+ ]),
+ ]),
+ ]),
+ ]),
+ m('article.programmingcontracting', [
+ m('section', [
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/programmingcontractor.svg',
+ })
+ },
+ }),
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Verktakavinna'),
+ m('p', `
+ Ef það er tímapressa hjá þér, að þá getum við komið beint
+ til ykkar og unnið verktakavinnu á ykkar vinnustað. Við
+ getum unnið náið með ykkar fólki og aðlagast hvaða
+ vinnureglum sem er.
+ `),
+ m('p', `
+ Okkar fólki hefur verið vel tekið hvert sem við förum og
+ við höfum ætíð kappkostað að skila frá okkur góðu verki.
+ Hverjar svo sem sem vandamálin kunna að liggja að þá
+ geturðu treyst því að við munum finna lausn á þeim
+ saman og redda málunum.
+ `),
+ ]),
+ ]),
+ ]),
+ ]),
+ ]),
+ ]
+ },
+}
+
+/*
+Background vector created by macrovector - www.freepik.com
+*/
+
+module.exports = Programming
diff --git a/nfp_is/app/programming/programming.styl b/nfp_is/app/programming/programming.styl
new file mode 100644
index 0000000..1c83a9b
--- /dev/null
+++ b/nfp_is/app/programming/programming.styl
@@ -0,0 +1,185 @@
+header.programming {
+ text-shadow: 0 0 30px black;
+
+ nav a {
+ background-color: #0003;
+ border-radius: 20px;
+ box-shadow: 0 0 80px black;
+ text-shadow: 0 0 80px black;
+ opacity: 1;
+ color: #999;
+ transition: opacity 0.5 color 0.5s;
+
+ &.title {
+ color: white;
+ opacity: 0.6;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+
+ &:hover {
+ color: white;
+ }
+
+ &.active {
+ color: white;
+ }
+ }
+
+ h1 {
+ font-size: 5.8vw;
+ margin-bottom: 10px;
+ }
+ h2 {
+ font-size: 3.5vw;
+ }
+
+ h1, h2 {
+ }
+}
+
+article {
+ &.programmingintro {
+ .image {
+ transform: translate(-50%, 0px);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+
+ &.programmingstore {
+ background: #29688c;
+ background: linear-gradient(30deg, #020024 15%, #29688c 100%);
+ color: white;
+ position: relative;
+ height: 80vh;
+ min-height: 600px;
+
+ section {
+ justify-content: flex-start;
+ }
+
+ aside {
+ align-items: center;
+ max-width: none;
+
+ .item {
+ width: 100%;
+ max-width: 600px;
+ text-align: left;
+ }
+ }
+
+ h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+ }
+
+ .image {
+ position: absolute;
+ right: 0;
+ top: 5%;
+ width: 50%;
+ height: 90%;
+ max-width: none;
+ background-position: center;
+ background-size: contain;
+ transform: translate(50%, 0px);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+
+ &.programmingcontracting {
+ .image {
+ transform: translate(-50%, 0px);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+}
+
+@media only screen and (max-width: 800px) {
+ header.programming {
+ nav a {
+ &.title {
+ background-position: calc(50% - 60px) center;
+ }
+ }
+
+ h1 {
+ font-size: 5.8vw;
+ margin-bottom: 10px;
+ }
+ h2 {
+ font-size: 3.5vw;
+ }
+
+ h1, h2 {
+ }
+ }
+
+ article {
+ &.programmingintro {
+ .image {
+ transform: translate(0, 50%);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+
+ h3 {
+ padding: 30px 0 30px;
+ }
+ }
+
+ &.programmingstore {
+ aside {
+ order: 1;
+ flex: 0 1 auto;
+ }
+
+ h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+ }
+
+ .image {
+ position: relative;
+ order: 2;
+ width: 100%;
+ padding-top: 430px;
+ height: auto;
+ background-size: auto 100%;
+ background-position: center -17px;
+ transform: translate(0, 50%);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+
+ &.programmingcontracting {
+ h3 {
+ padding: 30px 0 30px;
+ }
+ .image {
+ transform: translate(0, 50%);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+ }
+}
diff --git a/nfp_is/app/streaming/index.js b/nfp_is/app/streaming/index.js
new file mode 100644
index 0000000..5ef0926
--- /dev/null
+++ b/nfp_is/app/streaming/index.js
@@ -0,0 +1,124 @@
+var m = require('mithril')
+var Helper = require('../helper')
+
+var Streaming = {
+ oninit: function(vnode) {
+ Helper.init(vnode, 'streaming')
+ },
+
+ onremove: function(vnode) {
+ Helper.clear(vnode)
+ },
+
+ view: function(vnode) {
+ return [
+ m('header.streaming', {
+ oncreate: function(subnode) {
+ vnode.state.domContainer = subnode.dom
+ Helper.checkCreated(vnode)
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ })
+ },
+ }, m('div.container', [
+ !vnode.state.isMobile ? m('video', {
+ oncreate: function(subnode) {
+ vnode.state.domVideo = subnode.dom
+ Helper.checkCreated(vnode)
+ },
+ preload: 'none',
+ loop: true,
+ muted: true,
+ playsinline: true,
+ }, [
+ m('source', {
+ src: vnode.state.videoUrl,
+ type: 'video/mp4',
+ }),
+ m('source', {
+ src: '/assets/cover/streaming.webm',
+ type: 'video/webm',
+ }),
+ ]
+ ) : m('div', {
+ oncreate: function(subnode) {
+ vnode.state.domVideo = subnode.dom
+ Helper.checkCreated(vnode)
+ },
+ }),
+ m('div',
+ m('img', {
+ oncreate: function(subnode) {
+ vnode.state.domImg = subnode.dom
+ Helper.lazyLoadImage(vnode, 'domImg', '/assets/cover/streaming.jpg')
+ Helper.checkCreated(vnode)
+ },
+ src: ' data:image/jpeg;base64,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',
+ })
+ ),
+ m('nav', [
+ m(m.route.Link, { class: 'title', href: '/' }, m('span', 'NFP')),
+ m('div.filler'),
+ m(m.route.Link, { href: '/hosting-solutions' }, [ 'Hýsingarlausnir', m('div') ]),
+ m(m.route.Link, { href: '/programming-solutions' }, [ 'Forritunarlausnir', m('div') ]),
+ m(m.route.Link, { class: 'active', href: '/video-solutions' }, [ 'Videólausnir', m('div') ]),
+ ]),
+ m('div.content', [
+ m('h1', 'Streymi- og upptökulausnir'),
+ m('h2', 'Fyrir ráðstefnur og fundi á tækniöld'),
+ ]),
+ ])
+ ),
+ m('main', [
+ // Solutions
+ m('article.streamintro', [
+ m('section', [
+ m('div.image', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ img: '/assets/images/videoconference.svg',
+ })
+ },
+ }),
+ m('aside', [
+ m('div.item', {
+ oncreate: function(subnode) {
+ Helper.scrollAddItem(vnode, {
+ dom: subnode.dom,
+ className: 'visible',
+ threshold: -100,
+ })
+ },
+ }, [
+ m('h3', 'Ekki missa af neinu!'),
+ m('p', `
+ Aðstæður fólks eru æði ólíkar og ekki geta allir komist á
+ alla viðburði, hvort sem er vegna fjarlægðar, fötlunar eða
+ tímaleysis. Við bjóðum upp á upptöku og streymiþjónustu
+ fyrir hvers kyns viðburði til að færa þá nær fólki í tíma
+ og rúmi.
+ `),
+ m('p', `
+ Innifalið í þjónustunni er streymigluggi, upptaka og
+ úrvinnsla myndefnis með sundurgreiningu eftir ræðumanni
+ eða umræðuefni, tilbúið til birtingar á netinu og/eða
+ í varðveislu á stafrænu formi.
+ `),
+ ]),
+ ]),
+ ]),
+ ]),
+ ]),
+ ]
+ },
+}
+
+/*
+Background vector created by macrovector - www.freepik.com
+*/
+
+module.exports = Streaming
diff --git a/nfp_is/app/streaming/streaming.styl b/nfp_is/app/streaming/streaming.styl
new file mode 100644
index 0000000..1b597f9
--- /dev/null
+++ b/nfp_is/app/streaming/streaming.styl
@@ -0,0 +1,39 @@
+header.streaming {
+ text-shadow: 0 0 40px black;
+
+ h1 {
+ font-size: 5.7vw;
+ margin-bottom: 10px;
+ }
+ h2 {
+ font-size: 3vw;
+ }
+}
+
+article.streamintro {
+ .image {
+ transform: translate(-50%, 0px);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+}
+
+@media only screen and (max-width: 800px) {
+ article {
+ &.streamintro {
+ h3 {
+ padding: 30px 0 30px;
+ }
+
+ .image {
+ transform: translate(0, 50%);
+ }
+
+ .visible.image {
+ transform: translate(0px, 0px);
+ }
+ }
+ }
+}
diff --git a/nfp_is/base b/nfp_is/base
new file mode 120000
index 0000000..24312d1
--- /dev/null
+++ b/nfp_is/base
@@ -0,0 +1 @@
+../base
\ No newline at end of file
diff --git a/nfp_is/build-package.json b/nfp_is/build-package.json
new file mode 100644
index 0000000..155e640
--- /dev/null
+++ b/nfp_is/build-package.json
@@ -0,0 +1,10 @@
+{
+ "scripts": {
+ "build": "asbundle app/index.js public/assets/app.js"
+ },
+ "dependencies": {
+ "asbundle": "^2.6.1",
+ "mithril": "^2.2.2",
+ "service-core": "^3.0.0-beta.17"
+ }
+}
diff --git a/nfp_is/index.mjs b/nfp_is/index.mjs
new file mode 100644
index 0000000..24c1394
--- /dev/null
+++ b/nfp_is/index.mjs
@@ -0,0 +1,38 @@
+import fs from 'fs'
+import { pathToFileURL } from 'url'
+import config from './base/config.mjs'
+
+export function start(http, port, ctx) {
+ config.sources[1].store = ctx.config
+
+ return import('./api/server.mjs')
+ .then(function(module) {
+ let server = new module.default(http, port, ctx)
+ return server.run()
+ })
+}
+
+if (import.meta.url === pathToFileURL(process.argv[1]).href) {
+ import('service-core').then(core => {
+ const port = 4210
+
+ var core = new core.ServiceCore('nfp_is', import.meta.url, port, '')
+
+ let config = {
+ frontend: {
+ url: 'http://localhost:' + port
+ }
+ }
+
+ try {
+ config = JSON.parse(fs.readFileSync('./config.json'))
+ } catch {}
+
+ config.port = port
+
+ core.setConfig(config)
+ core.init({ start }).then(function() {
+ return core.run()
+ })
+ })
+}
diff --git a/nfp_is/package.json b/nfp_is/package.json
new file mode 100644
index 0000000..cc36c6e
--- /dev/null
+++ b/nfp_is/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "nfp_is",
+ "version": "1.0.0",
+ "port": 4210,
+ "description": "nfp.is website",
+ "main": "index.mjs",
+ "directories": {
+ "test": "test"
+ },
+ "scripts": {
+ "start": "node index.mjs",
+ "build": "asbundle app/index.js public/assets/app.js",
+ "dev:build": "npm-watch build",
+ "dev:server": "node index.mjs | bunyan",
+ "dev": "npm-watch dev:server"
+ },
+ "watch": {
+ "dev:server": {
+ "patterns": [
+ "api/*",
+ "base/*",
+ "../base/*"
+ ],
+ "extensions": "js,mjs",
+ "quiet": true,
+ "inherit": true
+ }
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.nfp.is/nfp/nfp_sites.git"
+ },
+ "author": "Jonatan Nilsson",
+ "license": "WTFPL",
+ "bugs": {
+ "url": "https://git.nfp.is/nfp/nfp_sites/issues"
+ },
+ "homepage": "https://git.nfp.is/nfp/nfp_sites",
+ "dependencies": {
+ "flaska": "^1.3.4",
+ "nconf-lite": "^2.0.0"
+ },
+ "devDependencies": {
+ "asbundle": "^2.6.1",
+ "mithril": "^2.2.3",
+ "service-core": "^3.0.0-beta.17"
+ }
+}
diff --git a/nfp_is/public/android-chrome-192x192.png b/nfp_is/public/android-chrome-192x192.png
new file mode 100644
index 0000000..799e519
Binary files /dev/null and b/nfp_is/public/android-chrome-192x192.png differ
diff --git a/nfp_is/public/android-chrome-512x512.png b/nfp_is/public/android-chrome-512x512.png
new file mode 100644
index 0000000..fc11f16
Binary files /dev/null and b/nfp_is/public/android-chrome-512x512.png differ
diff --git a/nfp_is/public/apple-touch-icon.png b/nfp_is/public/apple-touch-icon.png
new file mode 100644
index 0000000..fe26095
Binary files /dev/null and b/nfp_is/public/apple-touch-icon.png differ
diff --git a/nfp_is/public/assets/app.css b/nfp_is/public/assets/app.css
new file mode 100644
index 0000000..aecdc79
--- /dev/null
+++ b/nfp_is/public/assets/app.css
@@ -0,0 +1,852 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+*/
+html, body, div, span, h1, h2, h3, h4, h5, h6, p, a, img, form, label, input {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+div, span, h1, h2, h3, h4, h5, h6, p, a, img, form, label, input, header, nav, main, article, section {
+ box-sizing: border-box;
+}
+body {
+ line-height: 1;
+ font-family: Tahoma, sans-serif;
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ color: #000;
+ background: #fff;
+}
+#container {
+ flex-grow: 2;
+ display: flex;
+ flex-direction: column;
+}
+header {
+ background: #444;
+ position: relative;
+ text-shadow: 0 0 10px #000;
+}
+header .container {
+ position: relative;
+ bottom: 0%;
+ left: 0%;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ background: #000;
+ min-height: 485px;
+}
+header .container video {
+ width: 100%;
+ position: absolute;
+ z-index: 1;
+ bottom: 0;
+}
+header .container img {
+ width: 100%;
+ bottom: 0;
+ position: absolute;
+ z-index: 0;
+ min-height: 485px;
+}
+header nav {
+ display: flex;
+ z-index: 6;
+ position: absolute;
+ align-items: center;
+ top: 0%;
+ left: 0%;
+ width: 100%;
+ padding: 10px;
+}
+header nav .filler {
+ flex: 2 1 auto;
+}
+header nav .title {
+ margin: 0 20px 0 50px;
+ height: 70px;
+ display: flex;
+ align-items: center;
+ padding-left: 90px;
+ background-repeat: no-repeat;
+ background-color: transparent;
+ background-image: url("data:image/svg+xml;utf8,");
+ background-position: left center;
+ background-size: auto 70px;
+ font-size: 1.6em;
+ color: #fff;
+ opacity: 0.6;
+}
+header nav a {
+ font-size: 1.2em;
+ color: #fff;
+ text-shadow: 0 0 20px #000;
+ padding: 10px 20px;
+ text-decoration: none;
+ opacity: 0.6;
+ transition: opacity 0.5s;
+ position: relative;
+}
+header nav a div {
+ position: absolute;
+ bottom: 0;
+ left: 20px;
+ right: 20px;
+ border-bottom: 2px solid #fff;
+ transition: transform 0.3s;
+ transform: scaleX(0);
+}
+header nav a:hover {
+ opacity: 1;
+}
+header nav a:hover div {
+ transition: transform 0.7s;
+ transform: scaleX(1);
+}
+header nav a.active {
+ opacity: 1;
+}
+header nav a.active div {
+ transform: scaleX(1);
+}
+header .content {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ z-index: 5;
+ position: absolute;
+ top: 0px;
+ left: 0%;
+ height: 100%;
+ width: 100%;
+ min-height: 485px;
+ color: #fff;
+ text-transform: uppercase;
+}
+header .content h1 {
+ padding-left: 15px;
+ padding-right: 15px;
+ text-align: center;
+ font-size: 4.6vw;
+ font-weight: bold;
+ padding: 10px;
+ transition: opacity 1s, transform 1s;
+ opacity: 0;
+ transform: translateY(30px);
+ margin-bottom: 10px;
+}
+header .content h2 {
+ padding-left: 15px;
+ padding-right: 15px;
+ text-align: center;
+ font-size: 3vw;
+ transition: opacity 1.2s, transform 1.2s;
+ opacity: 0;
+ transform: translateY(50px);
+}
+header.visible h1,
+header.visible h2 {
+ opacity: 1;
+ transform: translateY(0px);
+}
+main {
+ display: flex;
+ flex-direction: column;
+ flex-grow: 2;
+ color: #333;
+}
+article {
+ display: flex;
+ padding: 0 50px;
+ flex-direction: column;
+ min-height: 82vh;
+ height: 600px;
+ overflow: hidden;
+}
+article h3 {
+ font-size: 2em;
+ padding: 10px 20px 40px;
+ font-weight: bold;
+ text-align: center;
+ position: relative;
+ align-self: center;
+}
+article section {
+ display: flex;
+ flex: 2 1 auto;
+ justify-content: center;
+}
+article section aside {
+ flex: 0 1 50%;
+ max-width: 600px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+article section aside .item {
+ display: flex;
+ flex-direction: column;
+}
+article section aside p {
+ font-size: 1.2em;
+ line-height: 1.4em;
+ margin-bottom: 50px;
+}
+article section aside h5 {
+ text-align: center;
+ margin: 20px 10px;
+ font-size: 1.2em;
+ line-height: 1.4em;
+ font-weight: bold;
+ border-bottom: 2px solid #29688c;
+ padding: 10px 50px;
+ align-self: center;
+}
+article section aside a {
+ text-decoration: none;
+ border: 2px solid #29688c;
+ align-self: center;
+ border-radius: 10px;
+ padding: 10px 30px 12px;
+ color: #29688c;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+article section aside p,
+article section aside h5,
+article section aside a,
+article section aside h3 {
+ transition: opacity 1.2s, transform 1.2s;
+ opacity: 0;
+ transform: translate(0px, 50px);
+}
+article section .image {
+ flex: 0 1 50%;
+ max-width: 600px;
+ background-position: center;
+ background-size: 90% auto;
+ background-repeat: no-repeat;
+ transition: opacity 1.2s, transform 1.2s;
+ opacity: 0;
+ transform: translate(50%, 0px);
+}
+article .visible p,
+article .visible a,
+article .visible .image,
+article .visible h5,
+article .visible h3,
+article .visible.image {
+ opacity: 1;
+ transform: translate(0px, 0px);
+}
+footer {
+ background: #29688c;
+ padding: 100px;
+}
+footer .outerbox {
+ display: flex;
+ flex-direction: column;
+ min-height: 50vh;
+ background: #fff;
+ box-shadow: 0 0 10px #020024;
+}
+footer .innerbox {
+ padding: 50px;
+ display: flex;
+ justify-content: center;
+ height: 500px;
+}
+footer .innerbox aside {
+ flex: 0 1 50%;
+ max-width: 600px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+footer .innerbox aside h3 {
+ font-size: 2em;
+ padding: 10px 20px 40px;
+ font-weight: bold;
+ text-align: center;
+ position: relative;
+ align-self: center;
+}
+footer .innerbox aside p {
+ font-size: 1.2em;
+ line-height: 1.4em;
+ margin-bottom: 50px;
+}
+footer .innerbox aside h5 {
+ text-align: center;
+ margin: 20px 10px;
+ font-size: 1.2em;
+ line-height: 1.4em;
+ font-weight: bold;
+ border-bottom: 2px solid #29688c;
+ padding: 10px 50px;
+ align-self: center;
+}
+footer .innerbox aside a {
+ text-decoration: none;
+ border: 2px solid #29688c;
+ align-self: center;
+ border-radius: 10px;
+ padding: 10px 30px 12px;
+ color: #29688c;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+footer .innerbox .image {
+ flex: 0 1 50%;
+ max-width: 600px;
+ background-position: center;
+ background-size: 90% auto;
+ background-repeat: no-repeat;
+ transition: opacity 1.2s, transform 1.2s;
+ opacity: 0;
+ transform: translate(0px, 50%);
+}
+footer .innerbox .image.visible {
+ transform: translate(0px, 0px);
+ opacity: 1;
+}
+footer .meta {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ padding: 40px 0 10px;
+ color: #777;
+ line-height: 1.6em;
+}
+footer .meta span {
+ margin: 0 10px;
+}
+footer .meta a {
+ color: #29688c;
+ text-decoration: none;
+}
+@media only screen and (max-width: 1000px) {
+ article {
+ font-size: 0.9em;
+ }
+ footer {
+ font-size: 0.9em;
+ }
+ footer .innerbox {
+ flex-direction: column;
+ align-items: center;
+ height: auto;
+ }
+ footer .innerbox aside h3 {
+ padding: 30px 20px 20px;
+ }
+ footer .innerbox .image {
+ width: 100%;
+ max-width: 600px;
+ height: 300px;
+ flex: 0 0 300px;
+ background-size: contain;
+ }
+ footer .meta {
+ padding: 0px 0 30px;
+ }
+}
+@media only screen and (max-width: 800px) {
+ header .container nav {
+ flex-wrap: wrap;
+ justify-content: center;
+ }
+ header .container nav a.title {
+ width: 100%;
+ flex: 2 0 100%;
+ justify-content: center;
+ background-position: calc(50% - 60px) center;
+ padding-left: 100px;
+ margin-left: 0;
+ margin-right: 0;
+ margin-bottom: 15px;
+ }
+ header .container nav .filler {
+ flex: 0 0 0;
+ }
+ header .content h1 {
+ font-size: 2.3em;
+ }
+ header .content h2 {
+ font-size: 1.5em;
+ }
+ article {
+ height: auto !important;
+ }
+ article section {
+ flex-direction: column;
+ align-items: center;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ }
+ article section aside {
+ order: 2;
+ }
+ article section .image {
+ order: 1;
+ width: 100%;
+ background-size: contain;
+ flex: 0 0 300px;
+ transform: translate(0, 50%);
+ }
+}
+@media only screen and (max-width: 680px) {
+ footer {
+ padding: 100px 20px;
+ }
+}
+@media only screen and (max-width: 500px) {
+ header .content {
+ top: 60px;
+ }
+ article {
+ padding-left: 10px;
+ padding-right: 10px;
+ font-size: 0.8em;
+ }
+ footer {
+ padding: 100px 20px;
+ font-size: 0.8em;
+ }
+ footer .innerbox {
+ padding: 50px 15px;
+ }
+}
+article.solution {
+ box-shadow: 0 5px 50px rgba(0,0,0,0.333);
+ background: #e9e9e9;
+ margin: 0 0 5vh;
+ height: 800px;
+}
+article.solution h3 {
+ font-size: 5vh;
+ padding: 5vh 20px;
+ font-weight: bold;
+ text-align: center;
+ position: relative;
+ align-self: center;
+}
+article.solution h3 .left,
+article.solution h3 .right {
+ position: absolute;
+ top: 50%;
+ margin-top: 0px;
+ border-bottom: 2px solid #29688c;
+}
+article.solution h3 .left {
+ right: 100%;
+ left: -9999px;
+}
+article.solution h3 .right {
+ left: 100%;
+ right: -9999px;
+}
+article.hosting {
+ height: 600px;
+}
+article.programming {
+ background: #29688c;
+ background: linear-gradient(150deg, #020024 15%, #29688c 100%);
+ color: #fff;
+ position: relative;
+ min-height: auto;
+ height: 70vw;
+ max-height: 80vh;
+ min-height: 600px;
+}
+article.programming aside {
+ align-self: flex-start;
+ position: relative;
+ z-index: 2;
+ margin-top: 5vh;
+ flex: 1 1 auto;
+ width: 90%;
+ max-width: 1440px;
+}
+article.programming aside .item {
+ width: 50%;
+ min-width: 500px;
+ text-align: left;
+}
+article.programming h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+}
+article.programming a {
+ border-color: #fff;
+ color: #fff;
+ align-self: flex-start;
+}
+article.programming .image {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ width: 87%;
+ height: 90%;
+ max-width: none;
+ background-position: right bottom;
+ background-size: contain;
+}
+article.video {
+ min-height: 70vh;
+}
+@media only screen and (max-width: 810px) {
+ article.solution h3 {
+ font-size: 2em;
+ }
+}
+@media only screen and (max-width: 800px) {
+ article.programming {
+ max-height: none;
+ min-height: auto;
+ padding: 0 40px 300px;
+ }
+ article.programming aside {
+ margin-top: 10px;
+ width: 100%;
+ }
+ article.programming aside .item {
+ width: 100%;
+ min-width: auto;
+ }
+ article.programming h3 {
+ align-self: center;
+ }
+ article.programming .image {
+ width: 100%;
+ height: 300px;
+ max-width: none;
+ background-position: right bottom;
+ background-size: contain;
+ transform: translate(50%, 0);
+ }
+ article.programming .visible.image {
+ transform: translate(0px, 0px);
+ }
+}
+header.hosting h1 {
+ font-size: 4.3vw;
+ margin-bottom: 10px;
+}
+header.hosting h2 {
+ font-size: 2.5vw;
+}
+article.hostintro .image {
+ transform: translate(-50%, 0px);
+}
+article.hostintro .visible.image {
+ transform: translate(0px, 0px);
+}
+article.hoststorage {
+ background: #29688c;
+ background: linear-gradient(150deg, #020024 15%, #29688c 100%);
+ color: #fff;
+ position: relative;
+ height: 80vh;
+ min-height: 600px;
+}
+article.hoststorage section {
+ justify-content: flex-end;
+}
+article.hoststorage aside {
+ align-items: center;
+ max-width: none;
+}
+article.hoststorage aside .item {
+ width: 100%;
+ max-width: 600px;
+ text-align: left;
+}
+article.hoststorage h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+}
+article.hoststorage .image {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 50%;
+ height: 90%;
+ max-width: none;
+ background-position: left center;
+ background-size: contain;
+ transform: translate(-50%, 0px);
+}
+article.hoststorage .visible.image {
+ transform: translate(0px, 0px);
+}
+article.hostmanaged {
+ position: relative;
+ height: 80vh;
+ min-height: 600px;
+}
+article.hostmanaged section {
+ justify-content: flex-end;
+}
+article.hostmanaged aside {
+ align-items: center;
+ max-width: none;
+}
+article.hostmanaged aside .item {
+ padding-left: 20px;
+ width: 100%;
+ max-width: 600px;
+ text-align: left;
+}
+article.hostmanaged h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+}
+article.hostmanaged .image {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ width: 50%;
+ height: 90%;
+ max-width: none;
+ background-position: left center;
+ background-size: contain;
+ transform: translate(-50%, 0px);
+}
+article.hostmanaged .visible.image {
+ transform: translate(0px, 0px);
+}
+@media only screen and (max-width: 800px) {
+ header.hosting h1 {
+ font-size: 2.3em;
+ }
+ header.hosting h2 {
+ font-size: 1.5em;
+ }
+ article.hostintro h3 {
+ padding: 30px 0 30px;
+ }
+ article.hostintro .image {
+ transform: translate(0, 50%);
+ }
+ article.hostintro .visible.image {
+ transform: translate(0px, 0px);
+ }
+ article.hoststorage {
+ min-height: auto;
+ padding: 0;
+ }
+ article.hoststorage section {
+ justify-content: flex-start;
+ padding-bottom: 0;
+ }
+ article.hoststorage aside {
+ order: 1;
+ padding: 0 50px;
+ }
+ article.hoststorage .image {
+ width: 100%;
+ height: auto;
+ background-position: center;
+ padding-top: 66%;
+ position: relative;
+ order: 2;
+ }
+ article.hostmanaged {
+ min-height: auto;
+ padding: 0;
+ }
+ article.hostmanaged section {
+ justify-content: flex-start;
+ padding-bottom: 0;
+ }
+ article.hostmanaged aside {
+ order: 1;
+ padding: 0 50px;
+ }
+ article.hostmanaged aside .item {
+ padding-left: 0;
+ }
+ article.hostmanaged .image {
+ position: relative;
+ width: 100%;
+ padding-top: 68%;
+ height: auto;
+ order: 2;
+ }
+}
+@media only screen and (max-width: 500px) {
+ article.hoststorage aside {
+ padding: 0 10px;
+ }
+ article.hostmanaged aside {
+ padding: 0 10px;
+ }
+}
+header.programming {
+ text-shadow: 0 0 30px #000;
+}
+header.programming nav a {
+ background-color: rgba(0,0,0,0.2);
+ border-radius: 20px;
+ box-shadow: 0 0 80px #000;
+ text-shadow: 0 0 80px #000;
+ opacity: 1;
+ color: #999;
+ transition: opacity 0.5 color 0.5s;
+}
+header.programming nav a.title {
+ color: #fff;
+ opacity: 0.6;
+}
+header.programming nav a.title:hover {
+ opacity: 1;
+}
+header.programming nav a:hover {
+ color: #fff;
+}
+header.programming nav a.active {
+ color: #fff;
+}
+header.programming h1 {
+ font-size: 5.8vw;
+ margin-bottom: 10px;
+}
+header.programming h2 {
+ font-size: 3.5vw;
+}
+article.programmingintro .image {
+ transform: translate(-50%, 0px);
+}
+article.programmingintro .visible.image {
+ transform: translate(0px, 0px);
+}
+article.programmingstore {
+ background: #29688c;
+ background: linear-gradient(30deg, #020024 15%, #29688c 100%);
+ color: #fff;
+ position: relative;
+ height: 80vh;
+ min-height: 600px;
+}
+article.programmingstore section {
+ justify-content: flex-start;
+}
+article.programmingstore aside {
+ align-items: center;
+ max-width: none;
+}
+article.programmingstore aside .item {
+ width: 100%;
+ max-width: 600px;
+ text-align: left;
+}
+article.programmingstore h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+}
+article.programmingstore .image {
+ position: absolute;
+ right: 0;
+ top: 5%;
+ width: 50%;
+ height: 90%;
+ max-width: none;
+ background-position: center;
+ background-size: contain;
+ transform: translate(50%, 0px);
+}
+article.programmingstore .visible.image {
+ transform: translate(0px, 0px);
+}
+article.programmingcontracting .image {
+ transform: translate(-50%, 0px);
+}
+article.programmingcontracting .visible.image {
+ transform: translate(0px, 0px);
+}
+@media only screen and (max-width: 800px) {
+ header.programming nav a.title {
+ background-position: calc(50% - 60px) center;
+ }
+ header.programming h1 {
+ font-size: 5.8vw;
+ margin-bottom: 10px;
+ }
+ header.programming h2 {
+ font-size: 3.5vw;
+ }
+ article.programmingintro .image {
+ transform: translate(0, 50%);
+ }
+ article.programmingintro .visible.image {
+ transform: translate(0px, 0px);
+ }
+ article.programmingintro h3 {
+ padding: 30px 0 30px;
+ }
+ article.programmingstore aside {
+ order: 1;
+ flex: 0 1 auto;
+ }
+ article.programmingstore h3 {
+ align-self: flex-start;
+ padding: 10px 0 40px;
+ }
+ article.programmingstore .image {
+ position: relative;
+ order: 2;
+ width: 100%;
+ padding-top: 430px;
+ height: auto;
+ background-size: auto 100%;
+ background-position: center -17px;
+ transform: translate(0, 50%);
+ }
+ article.programmingstore .visible.image {
+ transform: translate(0px, 0px);
+ }
+ article.programmingcontracting h3 {
+ padding: 30px 0 30px;
+ }
+ article.programmingcontracting .image {
+ transform: translate(0, 50%);
+ }
+ article.programmingcontracting .visible.image {
+ transform: translate(0px, 0px);
+ }
+}
+header.streaming {
+ text-shadow: 0 0 40px #000;
+}
+header.streaming h1 {
+ font-size: 5.7vw;
+ margin-bottom: 10px;
+}
+header.streaming h2 {
+ font-size: 3vw;
+}
+article.streamintro .image {
+ transform: translate(-50%, 0px);
+}
+article.streamintro .visible.image {
+ transform: translate(0px, 0px);
+}
+@media only screen and (max-width: 800px) {
+ article.streamintro h3 {
+ padding: 30px 0 30px;
+ }
+ article.streamintro .image {
+ transform: translate(0, 50%);
+ }
+ article.streamintro .visible.image {
+ transform: translate(0px, 0px);
+ }
+}
diff --git a/nfp_is/public/assets/aranja.svg b/nfp_is/public/assets/aranja.svg
new file mode 100644
index 0000000..e864774
--- /dev/null
+++ b/nfp_is/public/assets/aranja.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/cover/frontpage.jpg b/nfp_is/public/assets/cover/frontpage.jpg
new file mode 100644
index 0000000..68dc407
Binary files /dev/null and b/nfp_is/public/assets/cover/frontpage.jpg differ
diff --git a/nfp_is/public/assets/cover/frontpage.webm b/nfp_is/public/assets/cover/frontpage.webm
new file mode 100644
index 0000000..4fffc48
Binary files /dev/null and b/nfp_is/public/assets/cover/frontpage.webm differ
diff --git a/nfp_is/public/assets/cover/frontpage_1080.mp4 b/nfp_is/public/assets/cover/frontpage_1080.mp4
new file mode 100644
index 0000000..0ef3fef
Binary files /dev/null and b/nfp_is/public/assets/cover/frontpage_1080.mp4 differ
diff --git a/nfp_is/public/assets/cover/frontpage_720.mp4 b/nfp_is/public/assets/cover/frontpage_720.mp4
new file mode 100644
index 0000000..a4c9e46
Binary files /dev/null and b/nfp_is/public/assets/cover/frontpage_720.mp4 differ
diff --git a/nfp_is/public/assets/cover/hosting.jpg b/nfp_is/public/assets/cover/hosting.jpg
new file mode 100644
index 0000000..188ab46
Binary files /dev/null and b/nfp_is/public/assets/cover/hosting.jpg differ
diff --git a/nfp_is/public/assets/cover/hosting.png b/nfp_is/public/assets/cover/hosting.png
new file mode 100644
index 0000000..8dbb4d2
Binary files /dev/null and b/nfp_is/public/assets/cover/hosting.png differ
diff --git a/nfp_is/public/assets/cover/hosting.webm b/nfp_is/public/assets/cover/hosting.webm
new file mode 100644
index 0000000..92905f6
Binary files /dev/null and b/nfp_is/public/assets/cover/hosting.webm differ
diff --git a/nfp_is/public/assets/cover/hosting_1080.mp4 b/nfp_is/public/assets/cover/hosting_1080.mp4
new file mode 100644
index 0000000..6356ddb
Binary files /dev/null and b/nfp_is/public/assets/cover/hosting_1080.mp4 differ
diff --git a/nfp_is/public/assets/cover/hosting_720.mp4 b/nfp_is/public/assets/cover/hosting_720.mp4
new file mode 100644
index 0000000..2859218
Binary files /dev/null and b/nfp_is/public/assets/cover/hosting_720.mp4 differ
diff --git a/nfp_is/public/assets/cover/hosting_tiny.jpg b/nfp_is/public/assets/cover/hosting_tiny.jpg
new file mode 100644
index 0000000..fdf1d24
Binary files /dev/null and b/nfp_is/public/assets/cover/hosting_tiny.jpg differ
diff --git a/nfp_is/public/assets/cover/programming.jpg b/nfp_is/public/assets/cover/programming.jpg
new file mode 100644
index 0000000..7760eb1
Binary files /dev/null and b/nfp_is/public/assets/cover/programming.jpg differ
diff --git a/nfp_is/public/assets/cover/programming.png b/nfp_is/public/assets/cover/programming.png
new file mode 100644
index 0000000..eada7a8
Binary files /dev/null and b/nfp_is/public/assets/cover/programming.png differ
diff --git a/nfp_is/public/assets/cover/programming.webm b/nfp_is/public/assets/cover/programming.webm
new file mode 100644
index 0000000..c5dd7fa
Binary files /dev/null and b/nfp_is/public/assets/cover/programming.webm differ
diff --git a/nfp_is/public/assets/cover/programming_1080.mp4 b/nfp_is/public/assets/cover/programming_1080.mp4
new file mode 100644
index 0000000..475a0f5
Binary files /dev/null and b/nfp_is/public/assets/cover/programming_1080.mp4 differ
diff --git a/nfp_is/public/assets/cover/programming_720.mp4 b/nfp_is/public/assets/cover/programming_720.mp4
new file mode 100644
index 0000000..ddd3ef6
Binary files /dev/null and b/nfp_is/public/assets/cover/programming_720.mp4 differ
diff --git a/nfp_is/public/assets/cover/programming_tiny.jpg b/nfp_is/public/assets/cover/programming_tiny.jpg
new file mode 100644
index 0000000..bf02fcb
Binary files /dev/null and b/nfp_is/public/assets/cover/programming_tiny.jpg differ
diff --git a/nfp_is/public/assets/cover/streaming.jpg b/nfp_is/public/assets/cover/streaming.jpg
new file mode 100644
index 0000000..f7b8d44
Binary files /dev/null and b/nfp_is/public/assets/cover/streaming.jpg differ
diff --git a/nfp_is/public/assets/cover/streaming.png b/nfp_is/public/assets/cover/streaming.png
new file mode 100644
index 0000000..f6b83f8
Binary files /dev/null and b/nfp_is/public/assets/cover/streaming.png differ
diff --git a/nfp_is/public/assets/cover/streaming.webm b/nfp_is/public/assets/cover/streaming.webm
new file mode 100644
index 0000000..33c527d
Binary files /dev/null and b/nfp_is/public/assets/cover/streaming.webm differ
diff --git a/nfp_is/public/assets/cover/streaming_1080.mp4 b/nfp_is/public/assets/cover/streaming_1080.mp4
new file mode 100644
index 0000000..9b686df
Binary files /dev/null and b/nfp_is/public/assets/cover/streaming_1080.mp4 differ
diff --git a/nfp_is/public/assets/cover/streaming_720.mp4 b/nfp_is/public/assets/cover/streaming_720.mp4
new file mode 100644
index 0000000..0b55a48
Binary files /dev/null and b/nfp_is/public/assets/cover/streaming_720.mp4 differ
diff --git a/nfp_is/public/assets/cover/streaming_tiny.jpg b/nfp_is/public/assets/cover/streaming_tiny.jpg
new file mode 100644
index 0000000..4d95ee3
Binary files /dev/null and b/nfp_is/public/assets/cover/streaming_tiny.jpg differ
diff --git a/nfp_is/public/assets/filadelfia.png b/nfp_is/public/assets/filadelfia.png
new file mode 100644
index 0000000..2c53cb0
Binary files /dev/null and b/nfp_is/public/assets/filadelfia.png differ
diff --git a/nfp_is/public/assets/images/contact.svg b/nfp_is/public/assets/images/contact.svg
new file mode 100644
index 0000000..65b3b89
--- /dev/null
+++ b/nfp_is/public/assets/images/contact.svg
@@ -0,0 +1,766 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/hostfile.svg b/nfp_is/public/assets/images/hostfile.svg
new file mode 100644
index 0000000..328a971
--- /dev/null
+++ b/nfp_is/public/assets/images/hostfile.svg
@@ -0,0 +1,2661 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/hosting.svg b/nfp_is/public/assets/images/hosting.svg
new file mode 100644
index 0000000..d5a2d61
--- /dev/null
+++ b/nfp_is/public/assets/images/hosting.svg
@@ -0,0 +1,15456 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/hostintro.svg b/nfp_is/public/assets/images/hostintro.svg
new file mode 100644
index 0000000..a609a16
--- /dev/null
+++ b/nfp_is/public/assets/images/hostintro.svg
@@ -0,0 +1,1110 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/hostmanaged.svg b/nfp_is/public/assets/images/hostmanaged.svg
new file mode 100644
index 0000000..7667b62
--- /dev/null
+++ b/nfp_is/public/assets/images/hostmanaged.svg
@@ -0,0 +1,5117 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/programming.svg b/nfp_is/public/assets/images/programming.svg
new file mode 100644
index 0000000..0b892db
--- /dev/null
+++ b/nfp_is/public/assets/images/programming.svg
@@ -0,0 +1,2875 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/programmingcontractor.svg b/nfp_is/public/assets/images/programmingcontractor.svg
new file mode 100644
index 0000000..9c78899
--- /dev/null
+++ b/nfp_is/public/assets/images/programmingcontractor.svg
@@ -0,0 +1,5559 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/programmingintro.svg b/nfp_is/public/assets/images/programmingintro.svg
new file mode 100644
index 0000000..8a480e7
--- /dev/null
+++ b/nfp_is/public/assets/images/programmingintro.svg
@@ -0,0 +1,2530 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/programmingstore.svg b/nfp_is/public/assets/images/programmingstore.svg
new file mode 100644
index 0000000..1c197be
--- /dev/null
+++ b/nfp_is/public/assets/images/programmingstore.svg
@@ -0,0 +1,2295 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/solutions.svg b/nfp_is/public/assets/images/solutions.svg
new file mode 100644
index 0000000..9137712
--- /dev/null
+++ b/nfp_is/public/assets/images/solutions.svg
@@ -0,0 +1,1335 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/video.svg b/nfp_is/public/assets/images/video.svg
new file mode 100644
index 0000000..6a487dd
--- /dev/null
+++ b/nfp_is/public/assets/images/video.svg
@@ -0,0 +1,1328 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/images/videoconference.svg b/nfp_is/public/assets/images/videoconference.svg
new file mode 100644
index 0000000..9b49212
--- /dev/null
+++ b/nfp_is/public/assets/images/videoconference.svg
@@ -0,0 +1,884 @@
+
+
+
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/jokula.png b/nfp_is/public/assets/jokula.png
new file mode 100644
index 0000000..a1694ef
Binary files /dev/null and b/nfp_is/public/assets/jokula.png differ
diff --git a/nfp_is/public/assets/logo.svg b/nfp_is/public/assets/logo.svg
new file mode 100644
index 0000000..87ed05d
--- /dev/null
+++ b/nfp_is/public/assets/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/logo_only.svg b/nfp_is/public/assets/logo_only.svg
new file mode 100644
index 0000000..3fac2f5
--- /dev/null
+++ b/nfp_is/public/assets/logo_only.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/nfp_is/public/assets/stjornarradid.svg b/nfp_is/public/assets/stjornarradid.svg
new file mode 100644
index 0000000..4e38ed5
--- /dev/null
+++ b/nfp_is/public/assets/stjornarradid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/nfp_is/public/browserconfig.xml b/nfp_is/public/browserconfig.xml
new file mode 100644
index 0000000..b431274
--- /dev/null
+++ b/nfp_is/public/browserconfig.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ #3e0a1e
+
+
+
diff --git a/nfp_is/public/favicon-16x16.png b/nfp_is/public/favicon-16x16.png
new file mode 100644
index 0000000..53e9fbf
Binary files /dev/null and b/nfp_is/public/favicon-16x16.png differ
diff --git a/nfp_is/public/favicon-32x32.png b/nfp_is/public/favicon-32x32.png
new file mode 100644
index 0000000..03dbdf1
Binary files /dev/null and b/nfp_is/public/favicon-32x32.png differ
diff --git a/nfp_is/public/favicon.ico b/nfp_is/public/favicon.ico
new file mode 100644
index 0000000..ce8f62e
Binary files /dev/null and b/nfp_is/public/favicon.ico differ
diff --git a/nfp_is/public/index.html b/nfp_is/public/index.html
new file mode 100644
index 0000000..9358339
--- /dev/null
+++ b/nfp_is/public/index.html
@@ -0,0 +1,28 @@
+
+
+
+
+ NFP ehf. - Programming, Video, Live & Operations Contractors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nfp_is/public/mstile-150x150.png b/nfp_is/public/mstile-150x150.png
new file mode 100644
index 0000000..7a40a54
Binary files /dev/null and b/nfp_is/public/mstile-150x150.png differ
diff --git a/nfp_is/public/safari-pinned-tab.svg b/nfp_is/public/safari-pinned-tab.svg
new file mode 100644
index 0000000..31daeed
--- /dev/null
+++ b/nfp_is/public/safari-pinned-tab.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/nfp_is/public/site.webmanifest b/nfp_is/public/site.webmanifest
new file mode 100644
index 0000000..65d3258
--- /dev/null
+++ b/nfp_is/public/site.webmanifest
@@ -0,0 +1,20 @@
+{
+ "name": "NFP ehf.",
+ "short_name": "NFP ehf.",
+ "icons": [
+ {
+ "src": "/android-chrome-192x192.png?v=2",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/android-chrome-512x512.png?v=2",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#3e0a1e",
+ "background_color": "#3e0a1e",
+ "start_url": "https://nfp.is",
+ "display": "standalone"
+}