diff --git a/404.html b/404.html new file mode 100644 index 0000000..b45039d --- /dev/null +++ b/404.html @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + Michael Kennedy + + + + + + + + + + +
+
+
+

HTTP 404

+

+ It seems you are looking for something that I don't have. +

+ +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

+ + + + + Home + +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..e36caac --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +https://www.michaelkennedy.dev diff --git a/assets/michaelkennedy_contact.vcf b/assets/michaelkennedy_contact.vcf new file mode 100644 index 0000000..9a7b1fc --- /dev/null +++ b/assets/michaelkennedy_contact.vcf @@ -0,0 +1,18 @@ +BEGIN:VCARD +VERSION:3.0 +FN:Michael Kennedy -- Software Engineer +N:Kennedy;Michael;;; +EMAIL;TYPE=INTERNET;TYPE=WORK:michael@michaelkennedy.dev +TEL;TYPE=WORK:831-917-9737 +item1.TITLE:That one software developer from Linux Fest NW +item1.X-ABLabel:work +item2.URL:https\://linkedin.com/in/mw-Kennedy +item2.X-ABLabel:homePage +item3.URL:https\://github.com/xns5 +item3.X-ABLabel:homePage +item4.URL:https\://michaelkennedy.dev +item4.X-ABLabel:homePage +PHOTO:https://lh3.googleusercontent.com/contacts/AG6tpzGgAO1SgjFsD28sU8gGRD + 1_LTzfTGBsYvntvOh78zXr1NJoFqbO +CATEGORIES:myContacts +END:VCARD diff --git a/ats-resume/index.html b/ats-resume/index.html new file mode 100644 index 0000000..4e5ec11 --- /dev/null +++ b/ats-resume/index.html @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Resume + + + + + + + + + + + + + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/blog/1-07-24/index.html b/blog/1-07-24/index.html new file mode 100644 index 0000000..7e254ca --- /dev/null +++ b/blog/1-07-24/index.html @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Laid off - Day 1 (ish) + + + + + + + + + + +
+
+
+
+
+

+ Laid off - Day 1 (ish) + +

+ +

I'm trying to stay sane

+ +
+
+ + + Published on + + +
+
+
+
+

So I got laid off...

+

I got laid off on Thursday, January 4th. To say that this wasn't the note I wanted to start off 2024 with is a major understatement. This news was so unplanned +that I had just gotten out of a meeting discussing new year goals with one of the senior developers. I didn't have a chance to say goodbye to my coworkers who I've become friends with in the year and a half I've worked at Heritage, I didn't have a chance to hand off my notes, I had less than 30 minutes before my account would get locked out. You'd think that even having worked for a year, I'd at least get one last day.

+

In addition to...all of that, it's going to bug me for a while that I wasn't able to complete my outstanding tasks/tickets. I had a really neat idea for PDF tracking that I was on the verge of completing before I got the good news. I like to pride myself in seeing work through to the end, and being forced to not complete work that I had assigned to me or that I created for myself is tough to swallow. I realize the irony in that considering my Github is loaded up with half-baked projects, but those projects don't pay the bills.

+

I'm a good software developer. I have a lot of good ideas, and I have the drive to research, document, and implement my ideas. I know that these layoffs supposedly don't have anything to do with me and my work, but some consideration had to be made to pick me specifically. I can't help but wonder what I could have done differently.

+

I have a plan, I have a support system, and I have a professional network. I'm going to be okay. I just need some time to lick my wounds.

+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/blog/1-15-24/index.html b/blog/1-15-24/index.html new file mode 100644 index 0000000..1664c1b --- /dev/null +++ b/blog/1-15-24/index.html @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Laid off - Day 9 (ish) + + + + + + + + + + +
+
+
+
+
+

+ Laid off - Day 9 (ish) + +

+ +

I'm trying to stay sane -- but DNS is *really* testing me

+ +
+
+ + + Published on + + +
+
+
+
+

Why proxies?

+

I can remember IP addresses just fine, but if I'm hosting multiple services on a single VM (which therefore will have the same IP address, but will utilize different ports) it's going to be more challenging -- especially considering there are over a thousand available ports available to use on a given client. That's where the reverse proxy comes in. In most cases that I've seen, in the context of self hosting, reverse proxies are used to connect the internet to services on one's home network. The tutorials require purchasing a domain, setting up a dynamic DNS, opening up ports on my firewall to the big bad internet, blah blah blah. I don't want any of that. All of the stuff on my network is going to stay nice and cozy behind my firewall.

+

Nginx Proxy Manager (NPM) vs Traefik

+

I ended up using Nginx Proxy Manager after trying Traefik. While the latter has good reviews, changing configurations is a bit...clunky. I like that NPM because it's an all-in-one interface. I can add, modify, and test things at will without having to restart the service or the VM. With Traefik, I have to go into a dedicated dynamic route configuration file and make tweaks. I don't really have a problem with that, however if one thing was misconfigured it would throw off all of the routes. On top of that, it isn't super verbose when something goes wonky.

+

The Solution

+

The solution was simple, but figuring out where the reverse proxy goes in my network setup wasn't the easiest to figure out. If the client makes a request, does it go to the router, DNS server, then the reverse proxy? Or would it go direct to the reverse proxy from the router?

+

All I needed to do was create DNS records, add a few CNAME records, but the step I was missing was flushing my DNS cache on my computer. I wasn't able to hit the URLs I had built out, and that's because I forgot one aspect of DNS that I learned about in college: Time To Live, or TTL. I was setting records correctly, my computer simply wasn't picking them up before I got frustrated and changed the records again. This just reminds me that even if it isn't DNS, it's still DNS.

+

Next up, monitoring!

+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/blog/index.html b/blog/index.html new file mode 100644 index 0000000..7122057 --- /dev/null +++ b/blog/index.html @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Blog + + + + + + + + + + +
+
+
+

Blog

+

A collection of 'Blog' posts about anything that's on my mind

+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/blog/page/1/index.html b/blog/page/1/index.html new file mode 100644 index 0000000..85e07e5 --- /dev/null +++ b/blog/page/1/index.html @@ -0,0 +1,6 @@ + + + + +Redirect +

Click here to be redirected.

diff --git a/contact-me/index.html b/contact-me/index.html new file mode 100644 index 0000000..3608091 --- /dev/null +++ b/contact-me/index.html @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Resume + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + diff --git a/css/fontawesome-all.min.css b/css/fontawesome-all.min.css new file mode 100644 index 0000000..b7d052b --- /dev/null +++ b/css/fontawesome-all.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.9.0 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{animation:fa-spin 2s infinite linear}.fa-pulse{animation:fa-spin 1s infinite steps(8)}@keyframes fa-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scaleX(-1)}.fa-flip-vertical{transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adobe:before{content:"\f778"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-handshake:before{content:"\f2b5"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-wizard:before{content:"\f6e8"}.fa-haykal:before{content:"\f666"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:normal;font-display:auto;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands"}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:400;font-display:auto;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-weight:400}@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:auto;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.far,.fas{font-family:"Font Awesome 5 Free"}.fa,.fas{font-weight:900} \ No newline at end of file diff --git a/css/noscript.css b/css/noscript.css new file mode 100644 index 0000000..2832087 --- /dev/null +++ b/css/noscript.css @@ -0,0 +1,27 @@ +/* + Photon by HTML5 UP + html5up.net | @ajlkn + Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) +*/ + +/* Header */ + + body.is-preload #header .inner { + -moz-transform: none; + -webkit-transform: none; + -ms-transform: none; + transform: none; + opacity: 1; + } + + body.is-preload #header .inner .actions { + -moz-transform: none; + -webkit-transform: none; + -ms-transform: none; + transform: none; + opacity: 1; + } + + body.is-preload #header:after { + opacity: 0; + } \ No newline at end of file diff --git a/icons/android-chrome-192x192.png b/icons/android-chrome-192x192.png new file mode 100644 index 0000000..aea97b9 Binary files /dev/null and b/icons/android-chrome-192x192.png differ diff --git a/icons/android-chrome-384x384.png b/icons/android-chrome-384x384.png new file mode 100644 index 0000000..3d37c74 Binary files /dev/null and b/icons/android-chrome-384x384.png differ diff --git a/icons/apple-touch-icon.png b/icons/apple-touch-icon.png new file mode 100644 index 0000000..87f4544 Binary files /dev/null and b/icons/apple-touch-icon.png differ diff --git a/icons/arrow.png b/icons/arrow.png new file mode 100644 index 0000000..9290203 Binary files /dev/null and b/icons/arrow.png differ diff --git a/icons/browserconfig.xml b/icons/browserconfig.xml new file mode 100644 index 0000000..74bb89a --- /dev/null +++ b/icons/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #da532c + + + diff --git a/icons/code-black.ico b/icons/code-black.ico new file mode 100644 index 0000000..38be3f6 Binary files /dev/null and b/icons/code-black.ico differ diff --git a/icons/code-white.ico b/icons/code-white.ico new file mode 100644 index 0000000..39e3c5c Binary files /dev/null and b/icons/code-white.ico differ diff --git a/icons/favicon-16x16.png b/icons/favicon-16x16.png new file mode 100644 index 0000000..3480bc7 Binary files /dev/null and b/icons/favicon-16x16.png differ diff --git a/icons/favicon-32x32.png b/icons/favicon-32x32.png new file mode 100644 index 0000000..605b4ab Binary files /dev/null and b/icons/favicon-32x32.png differ diff --git a/icons/favicon.ico b/icons/favicon.ico new file mode 100644 index 0000000..77b9683 Binary files /dev/null and b/icons/favicon.ico differ diff --git a/icons/icons8-menu-24.png b/icons/icons8-menu-24.png new file mode 100644 index 0000000..6dbd7c2 Binary files /dev/null and b/icons/icons8-menu-24.png differ diff --git a/icons/icons8-menu-48.png b/icons/icons8-menu-48.png new file mode 100644 index 0000000..31f956a Binary files /dev/null and b/icons/icons8-menu-48.png differ diff --git a/icons/icons8-menu-96.png b/icons/icons8-menu-96.png new file mode 100644 index 0000000..9f8a0f9 Binary files /dev/null and b/icons/icons8-menu-96.png differ diff --git a/icons/mstile-150x150.png b/icons/mstile-150x150.png new file mode 100644 index 0000000..ecacbb4 Binary files /dev/null and b/icons/mstile-150x150.png differ diff --git a/icons/safari-pinned-tab.svg b/icons/safari-pinned-tab.svg new file mode 100644 index 0000000..9e473c4 --- /dev/null +++ b/icons/safari-pinned-tab.svg @@ -0,0 +1,15 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + diff --git a/icons/site.webmanifest b/icons/site.webmanifest new file mode 100644 index 0000000..161c642 --- /dev/null +++ b/icons/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-384x384.png", + "sizes": "384x384", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/images/accessibility.png b/images/accessibility.png new file mode 100644 index 0000000..e585258 Binary files /dev/null and b/images/accessibility.png differ diff --git a/images/captcha.png b/images/captcha.png new file mode 100644 index 0000000..ae22a57 Binary files /dev/null and b/images/captcha.png differ diff --git a/images/deadwood.jpg b/images/deadwood.jpg new file mode 100644 index 0000000..8b38a8e Binary files /dev/null and b/images/deadwood.jpg differ diff --git a/images/deadwood_move.png b/images/deadwood_move.png new file mode 100644 index 0000000..88242ee Binary files /dev/null and b/images/deadwood_move.png differ diff --git a/images/deadwood_start.png b/images/deadwood_start.png new file mode 100644 index 0000000..c121c7c Binary files /dev/null and b/images/deadwood_start.png differ diff --git a/images/header.jpg b/images/header.jpg new file mode 100644 index 0000000..e84417a Binary files /dev/null and b/images/header.jpg differ diff --git a/images/hero_image.jpg b/images/hero_image.jpg new file mode 100644 index 0000000..dec545d Binary files /dev/null and b/images/hero_image.jpg differ diff --git a/images/img036.jpg b/images/img036.jpg new file mode 100644 index 0000000..91350b3 Binary files /dev/null and b/images/img036.jpg differ diff --git a/images/overlay1.png b/images/overlay1.png new file mode 100644 index 0000000..7aa8031 Binary files /dev/null and b/images/overlay1.png differ diff --git a/images/overlay2.png b/images/overlay2.png new file mode 100644 index 0000000..1d1e8f5 Binary files /dev/null and b/images/overlay2.png differ diff --git a/images/overlay3.svg b/images/overlay3.svg new file mode 100644 index 0000000..1dc020c --- /dev/null +++ b/images/overlay3.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/images/overlay4.svg b/images/overlay4.svg new file mode 100644 index 0000000..fb0be90 --- /dev/null +++ b/images/overlay4.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/images/pic01.jpg b/images/pic01.jpg new file mode 100644 index 0000000..afbdfe4 Binary files /dev/null and b/images/pic01.jpg differ diff --git a/images/pic02.jpg b/images/pic02.jpg new file mode 100644 index 0000000..6741495 Binary files /dev/null and b/images/pic02.jpg differ diff --git a/images/pic03.jpg b/images/pic03.jpg new file mode 100644 index 0000000..5b4de55 Binary files /dev/null and b/images/pic03.jpg differ diff --git a/images/pic04.jpg b/images/pic04.jpg new file mode 100644 index 0000000..1f6eb1c Binary files /dev/null and b/images/pic04.jpg differ diff --git a/images/pic05.jpg b/images/pic05.jpg new file mode 100644 index 0000000..077a610 Binary files /dev/null and b/images/pic05.jpg differ diff --git a/images/pic06.jpg b/images/pic06.jpg new file mode 100644 index 0000000..a4c22e1 Binary files /dev/null and b/images/pic06.jpg differ diff --git a/images/profile_picture.png b/images/profile_picture.png new file mode 100644 index 0000000..5b8253d Binary files /dev/null and b/images/profile_picture.png differ diff --git a/images/python-file-symbol.png b/images/python-file-symbol.png new file mode 100644 index 0000000..fbfd27c Binary files /dev/null and b/images/python-file-symbol.png differ diff --git a/images/releave.png b/images/releave.png new file mode 100644 index 0000000..63a7d2c Binary files /dev/null and b/images/releave.png differ diff --git a/images/releave_badges.jpg b/images/releave_badges.jpg new file mode 100644 index 0000000..722f5c8 Binary files /dev/null and b/images/releave_badges.jpg differ diff --git a/images/releave_consumption_tracker.jpg b/images/releave_consumption_tracker.jpg new file mode 100644 index 0000000..3e7b27f Binary files /dev/null and b/images/releave_consumption_tracker.jpg differ diff --git a/images/releave_custom_goals.jpg b/images/releave_custom_goals.jpg new file mode 100644 index 0000000..7b92ea6 Binary files /dev/null and b/images/releave_custom_goals.jpg differ diff --git a/images/releave_home.jpg b/images/releave_home.jpg new file mode 100644 index 0000000..35b27f9 Binary files /dev/null and b/images/releave_home.jpg differ diff --git a/images/releave_journal.jpg b/images/releave_journal.jpg new file mode 100644 index 0000000..1d68d2c Binary files /dev/null and b/images/releave_journal.jpg differ diff --git a/images/releave_leaves.jpg b/images/releave_leaves.jpg new file mode 100644 index 0000000..e0a53d1 Binary files /dev/null and b/images/releave_leaves.jpg differ diff --git a/images/releave_prev_journal.jpg b/images/releave_prev_journal.jpg new file mode 100644 index 0000000..398ebea Binary files /dev/null and b/images/releave_prev_journal.jpg differ diff --git a/images/releave_rating.jpg b/images/releave_rating.jpg new file mode 100644 index 0000000..b65d407 Binary files /dev/null and b/images/releave_rating.jpg differ diff --git a/images/uml.png b/images/uml.png new file mode 100644 index 0000000..039f2e6 Binary files /dev/null and b/images/uml.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..312a835 --- /dev/null +++ b/index.html @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + + + + + Michael Kennedy + + + + + + + + + + + + + + +
+
+
+
+ A picture of me wearing red sunglasses and a hat, smiling at the camera. +
+
+

Hi, I'm Michael

+

I am a graduate of Western Washington University's Computer Science program with a Communication Studies minor. I'm an inquisitive, tenacious, and detail oriented individual who enjoys any opportunity to further his knowledge and abilities. Through my education, I've been fortunate to have worked on all types of projects — mobile, video games, web development, and systems development. I am currently open to work, and any opportunities which allow me to grow as a professional and my skills as a software developer.

+

In my free time, I enjoy exploring Washington, playing classical guitar, photography, and making things with my hands. Photography allows me to shut off that part of my brain that wants to be analytical and allows me to enjoy the natural beauty of my surroundings. I've been playing guitar for most of my life, and I enjoy the elegance of classical music.

+

+ +
+
+
+
+ + +
+ +
+
+
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
+
+
+
+

Languages I've Used

+
+

So far in my educational and professional career, I've had the opportunity to use Java, C#, C, Flutter (Dart), Javascript + HTML/CSS, and Python.

+

At my previous position with Heritage Bank NW, I worked full-stack on their Java back-end server as well as their React.js front-end application. The majority of my education involved algorithms, data structures, and less on UX/UI to the point where I've developed a preference for more back-end technologies.

+

The easiest language I've worked with thus far is Flutter. The structure of the code is hierarchical, and it's very easy to throw together a functioning application in a short amount of time. For example, I developed ReLeave in a matter of months with a team of students who had never interacted with the language before. Flutter has a lot of potential with a ton of community support, and it's incredibly easy for new software developers to see their application ideas become reality.

+
+
+
+
+
+ + +
+ +
+
+

My Projects

+
+

While I have worked on a number of projects during my schooling, these are the ones that I am the most proud of.

+ +
+
+ + +
+
+
+

Want to get in touch?

+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/js/breakpoints.min.js b/js/breakpoints.min.js new file mode 100644 index 0000000..32419cc --- /dev/null +++ b/js/breakpoints.min.js @@ -0,0 +1,2 @@ +/* breakpoints.js v1.0 | @ajlkn | MIT licensed */ +var breakpoints=function(){"use strict";function e(e){t.init(e)}var t={list:null,media:{},events:[],init:function(e){t.list=e,window.addEventListener("resize",t.poll),window.addEventListener("orientationchange",t.poll),window.addEventListener("load",t.poll),window.addEventListener("fullscreenchange",t.poll)},active:function(e){var n,a,s,i,r,d,c;if(!(e in t.media)){if(">="==e.substr(0,2)?(a="gte",n=e.substr(2)):"<="==e.substr(0,2)?(a="lte",n=e.substr(2)):">"==e.substr(0,1)?(a="gt",n=e.substr(1)):"<"==e.substr(0,1)?(a="lt",n=e.substr(1)):"!"==e.substr(0,1)?(a="not",n=e.substr(1)):(a="eq",n=e),n&&n in t.list)if(i=t.list[n],Array.isArray(i)){if(r=parseInt(i[0]),d=parseInt(i[1]),isNaN(r)){if(isNaN(d))return;c=i[1].substr(String(d).length)}else c=i[0].substr(String(r).length);if(isNaN(r))switch(a){case"gte":s="screen";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: -1px)";break;case"not":s="screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (max-width: "+d+c+")"}else if(isNaN(d))switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen";break;case"gt":s="screen and (max-width: -1px)";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+")";break;default:s="screen and (min-width: "+r+c+")"}else switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+"), screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (min-width: "+r+c+") and (max-width: "+d+c+")"}}else s="("==i.charAt(0)?"screen and "+i:i;t.media[e]=!!s&&s}return t.media[e]!==!1&&window.matchMedia(t.media[e]).matches},on:function(e,n){t.events.push({query:e,handler:n,state:!1}),t.active(e)&&n()},poll:function(){var e,n;for(e=0;e0:!!("ontouchstart"in window),e.mobile="wp"==e.os||"android"==e.os||"ios"==e.os||"bb"==e.os}};return e.init(),e}();!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?module.exports=n():e.browser=n()}(this,function(){return browser}); diff --git a/js/jquery.min.js b/js/jquery.min.js new file mode 100644 index 0000000..a1c07fd --- /dev/null +++ b/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 01){for(o=0;o img.setAttribute("theme", "dark")); + document.querySelectorAll(".vimeo, .youtube, .chart").forEach(video => video.setAttribute("theme", "dark")); + document.getElementById("dark-mode").setAttribute("title", "Switch to light theme"); + } + + document.querySelector(".navbar-burger").addEventListener("click", () => { + document.querySelector(".navbar-burger").classList.toggle("is-active"); + document.querySelector(".navbar-menu").classList.toggle("is-active"); + }); + + document.querySelectorAll("div.navbar-end > .navbar-item").forEach((el) => { + if (location.href.includes(el.getAttribute("href"))) { + document.querySelectorAll("a.navbar-item.is-active").forEach(itm => itm.classList.remove("is-active")); + el.classList.add("is-active"); + } + }) + + if (typeof renderMathInElement !== "undefined") { + renderMathInElement(document.body, { + delimiters: [ + { left: '$$', right: '$$', display: true }, + { left: '$', right: '$', display: false }, + { left: '\\(', right: '\\)', display: false }, + { left: '\\[', right: '\\]', display: true } + ] + }); + } +} + +if (document.readyState === 'loading') { // Loading hasn't finished yet + document.addEventListener('DOMContentLoaded', documentReadyCallback); +} else { // `DOMContentLoaded` has already fired + documentReadyCallback(); +} diff --git a/js/util.js b/js/util.js new file mode 100644 index 0000000..dc014b3 --- /dev/null +++ b/js/util.js @@ -0,0 +1,596 @@ +(function($) { + + /** + * Generate an indented list of links from a nav. Meant for use with panel(). + * @return {jQuery} jQuery object. + */ + $.fn.navList = function() { + + var $this = $(this); + $a = $this.find('a'), + b = []; + + $a.each(function() { + + var $this = $(this), + indent = Math.max(0, $this.parents('li').length - 1), + href = $this.attr('href'), + target = $this.attr('target'); + + b.push( + '' + + '' + + $this.text() + + '' + ); + + }); + + return b.join(''); + + }; + + /** + * Panel-ify an element. + * @param {object} userConfig User config. + * @return {jQuery} jQuery object. + */ + $.fn.panel = function(userConfig) { + + // No elements? + if (this.length == 0) + return $this; + + // Multiple elements? + if (this.length > 1) { + + for (var i=0; i < this.length; i++) + $(this[i]).panel(userConfig); + + return $this; + + } + + // Vars. + var $this = $(this), + $body = $('body'), + $window = $(window), + id = $this.attr('id'), + config; + + // Config. + config = $.extend({ + + // Delay. + delay: 0, + + // Hide panel on link click. + hideOnClick: false, + + // Hide panel on escape keypress. + hideOnEscape: false, + + // Hide panel on swipe. + hideOnSwipe: false, + + // Reset scroll position on hide. + resetScroll: false, + + // Reset forms on hide. + resetForms: false, + + // Side of viewport the panel will appear. + side: null, + + // Target element for "class". + target: $this, + + // Class to toggle. + visibleClass: 'visible' + + }, userConfig); + + // Expand "target" if it's not a jQuery object already. + if (typeof config.target != 'jQuery') + config.target = $(config.target); + + // Panel. + + // Methods. + $this._hide = function(event) { + + // Already hidden? Bail. + if (!config.target.hasClass(config.visibleClass)) + return; + + // If an event was provided, cancel it. + if (event) { + + event.preventDefault(); + event.stopPropagation(); + + } + + // Hide. + config.target.removeClass(config.visibleClass); + + // Post-hide stuff. + window.setTimeout(function() { + + // Reset scroll position. + if (config.resetScroll) + $this.scrollTop(0); + + // Reset forms. + if (config.resetForms) + $this.find('form').each(function() { + this.reset(); + }); + + }, config.delay); + + }; + + // Vendor fixes. + $this + .css('-ms-overflow-style', '-ms-autohiding-scrollbar') + .css('-webkit-overflow-scrolling', 'touch'); + + // Hide on click. + if (config.hideOnClick) { + + $this.find('a') + .css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)'); + + $this + .on('click', 'a', function(event) { + + var $a = $(this), + href = $a.attr('href'), + target = $a.attr('target'); + + if (!href || href == '#' || href == '' || href == '#' + id) + return; + + // Cancel original event. + event.preventDefault(); + event.stopPropagation(); + + // Hide panel. + $this._hide(); + + // Redirect to href. + window.setTimeout(function() { + + if (target == '_blank') + window.open(href); + else + window.location.href = href; + + }, config.delay + 10); + + }); + + } + + // Event: Touch stuff. + $this.on('touchstart', function(event) { + + $this.touchPosX = event.originalEvent.touches[0].pageX; + $this.touchPosY = event.originalEvent.touches[0].pageY; + + }) + + $this.on('touchmove', function(event) { + + if ($this.touchPosX === null + || $this.touchPosY === null) + return; + + var diffX = $this.touchPosX - event.originalEvent.touches[0].pageX, + diffY = $this.touchPosY - event.originalEvent.touches[0].pageY, + th = $this.outerHeight(), + ts = ($this.get(0).scrollHeight - $this.scrollTop()); + + // Hide on swipe? + if (config.hideOnSwipe) { + + var result = false, + boundary = 20, + delta = 50; + + switch (config.side) { + + case 'left': + result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta); + break; + + case 'right': + result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta)); + break; + + case 'top': + result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY > delta); + break; + + case 'bottom': + result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY < (-1 * delta)); + break; + + default: + break; + + } + + if (result) { + + $this.touchPosX = null; + $this.touchPosY = null; + $this._hide(); + + return false; + + } + + } + + // Prevent vertical scrolling past the top or bottom. + if (($this.scrollTop() < 0 && diffY < 0) + || (ts > (th - 2) && ts < (th + 2) && diffY > 0)) { + + event.preventDefault(); + event.stopPropagation(); + + } + + }); + + // Event: Prevent certain events inside the panel from bubbling. + $this.on('click touchend touchstart touchmove', function(event) { + event.stopPropagation(); + }); + + // Event: Hide panel if a child anchor tag pointing to its ID is clicked. + $this.on('click', 'a[href="#' + id + '"]', function(event) { + + event.preventDefault(); + event.stopPropagation(); + + config.target.removeClass(config.visibleClass); + + }); + + // Body. + + // Event: Hide panel on body click/tap. + $body.on('click touchend', function(event) { + $this._hide(event); + }); + + // Event: Toggle. + $body.on('click', 'a[href="#' + id + '"]', function(event) { + + event.preventDefault(); + event.stopPropagation(); + + config.target.toggleClass(config.visibleClass); + + }); + + // Window. + + // Event: Hide on ESC. + if (config.hideOnEscape) + $window.on('keydown', function(event) { + + if (event.keyCode == 27) + $this._hide(event); + + }); + + return $this; + + }; + + /** + * Apply "placeholder" attribute polyfill to one or more forms. + * @return {jQuery} jQuery object. + */ + $.fn.placeholder = function() { + + // Browser natively supports placeholders? Bail. + if (typeof (document.createElement('input')).placeholder != 'undefined') + return $(this); + + // No elements? + if (this.length == 0) + return $this; + + // Multiple elements? + if (this.length > 1) { + + for (var i=0; i < this.length; i++) + $(this[i]).placeholder(); + + return $this; + + } + + // Vars. + var $this = $(this); + + // Text, TextArea. + $this.find('input[type=text],textarea') + .each(function() { + + var i = $(this); + + if (i.val() == '' + || i.val() == i.attr('placeholder')) + i + .addClass('polyfill-placeholder') + .val(i.attr('placeholder')); + + }) + .on('blur', function() { + + var i = $(this); + + if (i.attr('name').match(/-polyfill-field$/)) + return; + + if (i.val() == '') + i + .addClass('polyfill-placeholder') + .val(i.attr('placeholder')); + + }) + .on('focus', function() { + + var i = $(this); + + if (i.attr('name').match(/-polyfill-field$/)) + return; + + if (i.val() == i.attr('placeholder')) + i + .removeClass('polyfill-placeholder') + .val(''); + + }); + + // Password. + $this.find('input[type=password]') + .each(function() { + + var i = $(this); + var x = $( + $('
') + .append(i.clone()) + .remove() + .html() + .replace(/type="password"/i, 'type="text"') + .replace(/type=password/i, 'type=text') + ); + + if (i.attr('id') != '') + x.attr('id', i.attr('id') + '-polyfill-field'); + + if (i.attr('name') != '') + x.attr('name', i.attr('name') + '-polyfill-field'); + + x.addClass('polyfill-placeholder') + .val(x.attr('placeholder')).insertAfter(i); + + if (i.val() == '') + i.hide(); + else + x.hide(); + + i + .on('blur', function(event) { + + event.preventDefault(); + + var x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]'); + + if (i.val() == '') { + + i.hide(); + x.show(); + + } + + }); + + x + .on('focus', function(event) { + + event.preventDefault(); + + var i = x.parent().find('input[name=' + x.attr('name').replace('-polyfill-field', '') + ']'); + + x.hide(); + + i + .show() + .focus(); + + }) + .on('keypress', function(event) { + + event.preventDefault(); + x.val(''); + + }); + + }); + + // Events. + $this + .on('submit', function() { + + $this.find('input[type=text],input[type=password],textarea') + .each(function(event) { + + var i = $(this); + + if (i.attr('name').match(/-polyfill-field$/)) + i.attr('name', ''); + + if (i.val() == i.attr('placeholder')) { + + i.removeClass('polyfill-placeholder'); + i.val(''); + + } + + }); + + }) + .on('reset', function(event) { + + event.preventDefault(); + + $this.find('select') + .val($('option:first').val()); + + $this.find('input,textarea') + .each(function() { + + var i = $(this), + x; + + i.removeClass('polyfill-placeholder'); + + switch (this.type) { + + case 'submit': + case 'reset': + break; + + case 'password': + i.val(i.attr('defaultValue')); + + x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]'); + + if (i.val() == '') { + i.hide(); + x.show(); + } + else { + i.show(); + x.hide(); + } + + break; + + case 'checkbox': + case 'radio': + i.attr('checked', i.attr('defaultValue')); + break; + + case 'text': + case 'textarea': + i.val(i.attr('defaultValue')); + + if (i.val() == '') { + i.addClass('polyfill-placeholder'); + i.val(i.attr('placeholder')); + } + + break; + + default: + i.val(i.attr('defaultValue')); + break; + + } + }); + + }); + + return $this; + + }; + + /** + * Moves elements to/from the first positions of their respective parents. + * @param {jQuery} $elements Elements (or selector) to move. + * @param {bool} condition If true, moves elements to the top. Otherwise, moves elements back to their original locations. + */ + $.prioritize = function($elements, condition) { + + var key = '__prioritize'; + + // Expand $elements if it's not already a jQuery object. + if (typeof $elements != 'jQuery') + $elements = $($elements); + + // Step through elements. + $elements.each(function() { + + var $e = $(this), $p, + $parent = $e.parent(); + + // No parent? Bail. + if ($parent.length == 0) + return; + + // Not moved? Move it. + if (!$e.data(key)) { + + // Condition is false? Bail. + if (!condition) + return; + + // Get placeholder (which will serve as our point of reference for when this element needs to move back). + $p = $e.prev(); + + // Couldn't find anything? Means this element's already at the top, so bail. + if ($p.length == 0) + return; + + // Move element to top of parent. + $e.prependTo($parent); + + // Mark element as moved. + $e.data(key, $p); + + } + + // Moved already? + else { + + // Condition is true? Bail. + if (condition) + return; + + $p = $e.data(key); + + // Move element back to its original location (using our placeholder). + $e.insertAfter($p); + + // Unmark element as moved. + $e.removeData(key); + + } + + }); + + }; + +})(jQuery); + +function toggleNav() { + var navbar = document.getElementById("topnav"); + if (navbar.className === "topnav") { + navbar.className += " responsive"; + } else { + navbar.className = "topnav"; + } +} \ No newline at end of file diff --git a/main.css b/main.css new file mode 100644 index 0000000..5aa6213 --- /dev/null +++ b/main.css @@ -0,0 +1,4353 @@ +@import url("css/fontawesome-all.min.css"); +@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300italic,400,400italic"); + +html, body, div, span, applet, object, +iframe, h1, h2, h3, h4, h5, h6, p, blockquote, +pre, a, abbr, acronym, address, big, cite, +code, del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, b, +u, i, center, dl, dt, dd, ol, ul, li, fieldset, +form, label, legend, table, caption, tbody, +tfoot, thead, tr, th, td, article, aside, +canvas, details, embed, figure, figcaption, +footer, header, hgroup, menu, nav, output, ruby, +section, summary, time, mark, audio, video, title { + margin: 0; + padding: 0; + border: 0; + font: inherit; + vertical-align: baseline; +} + +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +article{ + margin: 1.5em; +} + +body { + line-height: 1; +} + +ol, ul { + list-style: none; +} + +blockquote, q { + quotes: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +body { + -webkit-text-size-adjust: none; +} + +p{ + color: black; +} + +a:hover{ + color: #004F99; +} + +mark { + background-color: transparent; + color: inherit; +} + +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +select, textarea { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; +} + +/* Basic */ + + html { + box-sizing: border-box; + } + + *, *:before, *:after { + box-sizing: inherit; + } + + body { + background: #fff; + } + + #intro{ + font-size: 3em; + } + + #tech-content > *{ + color: white; + } + + body.is-preload *, body.is-preload *:before, body.is-preload *:after { + -moz-animation: none !important; + -webkit-animation: none !important; + animation: none !important; + -moz-transition: none !important; + -webkit-transition: none !important; + transition: none !important; + } + + body, input, select, textarea { + color: #666; + font-family: "Source Sans Pro", Helvetica, sans-serif; + font-size: 16pt; + font-weight: 300; + line-height: 1.65em; + } + + a { + -moz-transition: color 0.2s ease-in-out, border-color 0.2s ease-in-out; + -webkit-transition: color 0.2s ease-in-out, border-color 0.2s ease-in-out; + transition: color 0.2s ease-in-out, border-color 0.2s ease-in-out; + color: inherit; + text-decoration: none; + font-weight: 500; + /*font-size: 20px;*/ + } + + a:hover { + color: #004F99; + } + + strong, b { + font-weight: 800; + } + + em, i { + font-style: italic; + } + + p { + margin: 0 0 0.5em 0; + font-size: 18pt; + } + + h1, h2, h3, h4, h5, h6 { + color: #555; + line-height: 1em; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + color: inherit; + text-decoration: none; + } + + h1 { + font-size: 34pt; + line-height: 1.35em; + color: black; + font-weight: bold; + } + + h2 { + font-size: 28pt; + } + + h3 { + font-size: 24pt; + line-height: 1.5em; + } + + h4 { + font-size: 1.25em; + line-height: 1.5em; + font-style: italic; + } + + h5 { + font-size: 0.8em; + line-height: 1.5em; + } + + h6 { + font-size: 0.6em; + line-height: 1.5em; + } + + sub { + font-size: 0.8em; + position: relative; + top: 0.5em; + } + + sup { + font-size: 0.8em; + position: relative; + top: -0.5em; + } + + hr { + border: 0; + border-bottom: solid 1px rgba(144, 144, 144, 0.5); + margin: 2em 0; + } + + hr.major { + margin: 3em 0; + } + + blockquote { + border-left: solid 4px rgba(144, 144, 144, 0.5); + font-style: italic; + margin: 0 0 2em 0; + padding: 0.5em 0 0.5em 2em; + } + + code { + background: rgba(144, 144, 144, 0.075); + border-radius: 2px; + border: solid 1px rgba(144, 144, 144, 0.5); + font-family: "Courier New", monospace; + font-size: 0.9em; + padding: 0.01em 0.325em; + } + + pre { + -webkit-overflow-scrolling: touch; + font-family: "Courier New", monospace; + font-size: 0.9em; + margin: 0 0 2em 0; + } + + pre code { + display: block; + line-height: 1.75em; + padding: 1em 1.5em; + overflow-x: auto; + } + + .align-left { + text-align: left; + } + + .align-center { + text-align: center; + } + + .align-right { + text-align: right; + } + + .project-logo{ + width: 10%; + height: fit-content; + } + + .project-logo-home{ + width: 15%; + height: fit-content; + } + + .project_screenshot_mobile_right{ + width: 25%; + float: right; + margin: 1em; + padding: 1em 1em 1em 1em; + } + + .project_screenshot_mobile_left{ + width: 25%; + float: left; + margin: 1em; + padding: 1em 1em 1em 1em; + } + + .project_demo_video_embed{ + padding: 1em; + } + + .project_demo_desktop { + width: 85%; + margin: 1em 1em 1em 1em; + } + + .page_timestamp { + font-size: 15px; + } + +/* Container */ + .container { + margin: 0 auto; + max-width: calc(100% - 4em); + width: 80em; + } + + .article-list{ + margin: 0 1em 0 1em; + } + + .container.xsmall { + width: 15em; + } + + .container.small { + width: 30em; + } + + .container.medium { + width: 45em; + } + + .container.large { + width: 75em; + } + + .container.xlarge { + width: 90em; + } + + .container.max { + width: 100%; + } + + @media screen and (max-width: 980px) { + + .container { + max-width: 100% !important; + width: 100% !important; + } + + } + + @media screen and (max-width: 480px) { + + .container { + max-width: calc(100% - 3em); + } + + } + +/* Row */ + .row { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: stretch; + } + + .row > * { + box-sizing: border-box; + } + + .row.gtr-uniform > * > :last-child { + margin-bottom: 0; + } + + .row.aln-left { + justify-content: flex-start; + } + + .row.aln-center { + justify-content: center; + } + + .row.aln-right { + justify-content: flex-end; + } + + .row.aln-top { + align-items: flex-start; + } + + .row.aln-middle { + align-items: center; + } + + .row.aln-bottom { + align-items: flex-end; + } + + .row > .imp { + order: -1; + } + + .row > .col-1 { + width: 8.33333%; + } + + .row > .off-1 { + margin-left: 8.33333%; + } + + .row > .col-2 { + width: 16.66667%; + } + + .row > .off-2 { + margin-left: 16.66667%; + } + + .row > .col-3 { + width: 25%; + } + + .row > .off-3 { + margin-left: 25%; + } + + .row > .col-4 { + width: 33.33333%; + } + + .row > .off-4 { + margin-left: 33.33333%; + } + + .row > .col-5 { + width: 41.66667%; + } + + .row > .off-5 { + margin-left: 41.66667%; + } + + .row > .col-6 { + width: 50%; + } + + .row > .off-6 { + margin-left: 50%; + } + + .row > .col-7 { + width: 58.33333%; + } + + .row > .off-7 { + margin-left: 58.33333%; + } + + .row > .col-8 { + width: 66.66667%; + } + + .row > .off-8 { + margin-left: 66.66667%; + } + + .row > .col-9 { + width: 75%; + } + + .row > .off-9 { + margin-left: 75%; + } + + .row > .col-10 { + width: 83.33333%; + } + + .row > .off-10 { + margin-left: 83.33333%; + } + + .row > .col-11 { + width: 91.66667%; + } + + .row > .off-11 { + margin-left: 91.66667%; + } + + .row > .col-12 { + width: 100%; + } + + .row > .off-12 { + margin-left: 100%; + } + + .row.gtr-0 { + margin-top: 0; + margin-left: 0; + } + + .row.gtr-0 > * { + padding: 0 0 0 0; + } + + .row.gtr-0.gtr-uniform { + margin-top:0; + } + + .row.gtr-0.gtr-uniform > * { + padding-top:0; + } + + .row.gtr-25 { + margin-top: 0; + margin-left: -0.5em; + } + + .row.gtr-25 > * { + padding: 0 0 0 0.5em; + } + + .row.gtr-25.gtr-uniform { + margin-top: -0.5em; + } + + .row.gtr-25.gtr-uniform > * { + padding-top: 0.5em; + } + + .row.gtr-50 { + margin-top: 0; + margin-left: -1em; + } + + .row.gtr-50 > * { + padding: 0 0 0 1em; + } + + .row.gtr-50.gtr-uniform { + margin-top: -1em; + } + + .row.gtr-50.gtr-uniform > * { + padding-top: 1em; + } + + .row { + margin-top: 0; + margin-left: -2em; + } + + .row > * { + padding: 0 0 0 2em; + } + + .row.gtr-uniform { + margin-top: -2em; + } + + .row.gtr-uniform > * { + padding-top: 2em; + } + + .row.gtr-150 { + margin-top: 0; + } + + .row.gtr-150 > * { + padding: 0 3em 0 3em; + } + + .row.gtr-150.gtr-uniform { + margin-top: -3em; + } + + .row.gtr-150.gtr-uniform > * { + padding-top: 3em; + } + + .row.gtr-200 { + margin-top: 0; + margin-left: -4em; + } + + .row.gtr-200 > * { + padding: 0 0 0 4em; + } + + .row.gtr-200.gtr-uniform { + margin-top: -4em; + } + + .row.gtr-200.gtr-uniform > * { + padding-top: 4em; + } + + @media screen and (max-width: 1680px) { + + .row { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: stretch; + } + + .row > * { + box-sizing: border-box; + } + + .row.gtr-uniform > * > :last-child { + margin-bottom: 0; + } + + .row.aln-left { + justify-content: flex-start; + } + + .row.aln-center { + justify-content: center; + } + + .row.aln-right { + justify-content: flex-end; + } + + .row.aln-top { + align-items: flex-start; + } + + .row.aln-middle { + align-items: center; + } + + .row.aln-bottom { + align-items: flex-end; + } + + .row > .imp-xlarge { + order: -1; + } + + .row > .col-1-xlarge { + width: 8.33333%; + } + + .row > .off-1-xlarge { + margin-left: 8.33333%; + } + + .row > .col-2-xlarge { + width: 16.66667%; + } + + .row > .off-2-xlarge { + margin-left: 16.66667%; + } + + .row > .col-3-xlarge { + width: 25%; + } + + .row > .off-3-xlarge { + margin-left: 25%; + } + + .row > .col-4-xlarge { + width: 33.33333%; + } + + .row > .off-4-xlarge { + margin-left: 33.33333%; + } + + .row > .col-5-xlarge { + width: 41.66667%; + } + + .row > .off-5-xlarge { + margin-left: 41.66667%; + } + + .row > .col-6-xlarge { + width: 50%; + } + + .row > .off-6-xlarge { + margin-left: 50%; + } + + .row > .col-7-xlarge { + width: 58.33333%; + } + + .row > .off-7-xlarge { + margin-left: 58.33333%; + } + + .row > .col-8-xlarge { + width: 66.66667%; + } + + .row > .off-8-xlarge { + margin-left: 66.66667%; + } + + .row > .col-9-xlarge { + width: 75%; + } + + .row > .off-9-xlarge { + margin-left: 75%; + } + + .row > .col-10-xlarge { + width: 83.33333%; + } + + .row > .off-10-xlarge { + margin-left: 83.33333%; + } + + .row > .col-11-xlarge { + width: 91.66667%; + } + + .row > .off-11-xlarge { + margin-left: 91.66667%; + } + + .row > .col-12-xlarge { + width: 100%; + } + + .row > .off-12-xlarge { + margin-left: 100%; + } + + .row.gtr-0 { + margin-top: 0; + margin-left:0; + } + + .row.gtr-0 > * { + padding: 0 0 0 0; + } + + .row.gtr-0.gtr-uniform { + margin-top:0; + } + + .row.gtr-0.gtr-uniform > * { + padding-top:0; + } + + .row.gtr-25 { + margin-top: 0; + margin-left: -0.5em; + } + + .row.gtr-25 > * { + padding: 0 0 0 0.5em; + } + + .row.gtr-25.gtr-uniform { + margin-top: -0.5em; + } + + .row.gtr-25.gtr-uniform > * { + padding-top: 0.5em; + } + + .row.gtr-50 { + margin-top: 0; + margin-left: -1em; + } + + .row.gtr-50 > * { + padding: 0 0 0 1em; + } + + .row.gtr-50.gtr-uniform { + margin-top: -1em; + } + + .row.gtr-50.gtr-uniform > * { + padding-top: 1em; + } + + .row { + margin-top: 0; + margin-left: -2em; + } + + .row > * { + padding: 0 0 0 2em; + } + + .row.gtr-uniform { + margin-top: -2em; + } + + .row.gtr-uniform > * { + padding-top: 2em; + } + + .row.gtr-150 { + margin-top: 0; + margin-left: -3em; + } + + .row.gtr-150 > * { + padding: 0 0 0 3em; + } + + .row.gtr-150.gtr-uniform { + margin-top: -3em; + } + + .row.gtr-150.gtr-uniform > * { + padding-top: 3em; + } + + .row.gtr-200 { + margin-top: 0; + margin-left: -4em; + } + + .row.gtr-200 > * { + padding: 0 0 0 4em; + } + + .row.gtr-200.gtr-uniform { + margin-top: -4em; + } + + .row.gtr-200.gtr-uniform > * { + padding-top: 4em; + } + + } + + @media screen and (max-width: 1140px) { + + .row { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: stretch; + } + + .row > * { + box-sizing: border-box; + } + + .row.gtr-uniform > * > :last-child { + margin-bottom: 0; + } + + .row.aln-left { + justify-content: flex-start; + } + + .row.aln-center { + justify-content: center; + } + + .row.aln-right { + justify-content: flex-end; + } + + .row.aln-top { + align-items: flex-start; + } + + .row.aln-middle { + align-items: center; + } + + .row.aln-bottom { + align-items: flex-end; + } + + .row > .imp-large { + order: -1; + } + + .row > .col-1-large { + width: 8.33333%; + } + + .row > .off-1-large { + margin-left: 8.33333%; + } + + .row > .col-2-large { + width: 16.66667%; + } + + .row > .off-2-large { + margin-left: 16.66667%; + } + + .row > .col-3-large { + width: 25%; + } + + .row > .off-3-large { + margin-left: 25%; + } + + .row > .col-4-large { + width: 33.33333%; + } + + .row > .off-4-large { + margin-left: 33.33333%; + } + + .row > .col-5-large { + width: 41.66667%; + } + + .row > .off-5-large { + margin-left: 41.66667%; + } + + .row > .col-6-large { + width: 50%; + } + + .row > .off-6-large { + margin-left: 50%; + } + + .row > .col-7-large { + width: 58.33333%; + } + + .row > .off-7-large { + margin-left: 58.33333%; + } + + .row > .col-8-large { + width: 66.66667%; + } + + .row > .off-8-large { + margin-left: 66.66667%; + } + + .row > .col-9-large { + width: 75%; + } + + .row > .off-9-large { + margin-left: 75%; + } + + .row > .col-10-large { + width: 83.33333%; + } + + .row > .off-10-large { + margin-left: 83.33333%; + } + + .row > .col-11-large { + width: 91.66667%; + } + + .row > .off-11-large { + margin-left: 91.66667%; + } + + .row > .col-12-large { + width: 100%; + } + + .row > .off-12-large { + margin-left: 100%; + } + + .row.gtr-0 { + margin-top: 0; + margin-left:0; + } + + .row.gtr-0 > * { + padding: 0 0 0 0; + } + + .row.gtr-0.gtr-uniform { + margin-top:0; + } + + .row.gtr-0.gtr-uniform > * { + padding-top:0; + } + + .row.gtr-25 { + margin-top: 0; + margin-left: -0.5em; + } + + .row.gtr-25 > * { + padding: 0 0 0 0.5em; + } + + .row.gtr-25.gtr-uniform { + margin-top: -0.5em; + } + + .row.gtr-25.gtr-uniform > * { + padding-top: 0.5em; + } + + .row.gtr-50 { + margin-top: 0; + margin-left: -1em; + } + + .row.gtr-50 > * { + padding: 0 0 0 1em; + } + + .row.gtr-50.gtr-uniform { + margin-top: -1em; + } + + .row.gtr-50.gtr-uniform > * { + padding-top: 1em; + } + + .row { + margin-top: 0; + margin-left: -2em; + } + + .row > * { + padding: 0 0 0 2em; + } + + .row.gtr-uniform { + margin-top: -2em; + } + + .row.gtr-uniform > * { + padding-top: 2em; + } + + .row.gtr-150 { + margin-top: 0; + margin-left: -3em; + } + + .row.gtr-150 > * { + padding: 0 0 0 3em; + } + + .row.gtr-150.gtr-uniform { + margin-top: -3em; + } + + .row.gtr-150.gtr-uniform > * { + padding-top: 3em; + } + + .row.gtr-200 { + margin-top: 0; + margin-left: -4em; + } + + .row.gtr-200 > * { + padding: 0 0 0 4em; + } + + .row.gtr-200.gtr-uniform { + margin-top: -4em; + } + + .row.gtr-200.gtr-uniform > * { + padding-top: 4em; + } + + } + + @media screen and (max-width: 980px) { + + .row { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: stretch; + } + + .row > * { + box-sizing: border-box; + } + + .row.gtr-uniform > * > :last-child { + margin-bottom: 0; + } + + .row.aln-left { + justify-content: flex-start; + } + + .row.aln-center { + justify-content: center; + } + + .row.aln-right { + justify-content: flex-end; + } + + .row.aln-top { + align-items: flex-start; + } + + .row.aln-middle { + align-items: center; + } + + .row.aln-bottom { + align-items: flex-end; + } + + .row > .imp-medium { + order: -1; + } + + .row > .col-1-medium { + width: 8.33333%; + } + + .row > .off-1-medium { + margin-left: 8.33333%; + } + + .row > .col-2-medium { + width: 16.66667%; + } + + .row > .off-2-medium { + margin-left: 16.66667%; + } + + .row > .col-3-medium { + width: 25%; + } + + .row > .off-3-medium { + margin-left: 25%; + } + + .row > .col-4-medium { + width: 33.33333%; + } + + .row > .off-4-medium { + margin-left: 33.33333%; + } + + .row > .col-5-medium { + width: 41.66667%; + } + + .row > .off-5-medium { + margin-left: 41.66667%; + } + + .row > .col-6-medium { + width: 50%; + } + + .row > .off-6-medium { + margin-left: 50%; + } + + .row > .col-7-medium { + width: 58.33333%; + } + + .row > .off-7-medium { + margin-left: 58.33333%; + } + + .row > .col-8-medium { + width: 66.66667%; + } + + .row > .off-8-medium { + margin-left: 66.66667%; + } + + .row > .col-9-medium { + width: 75%; + } + + .row > .off-9-medium { + margin-left: 75%; + } + + .row > .col-10-medium { + width: 83.33333%; + } + + .row > .off-10-medium { + margin-left: 83.33333%; + } + + .row > .col-11-medium { + width: 91.66667%; + } + + .row > .off-11-medium { + margin-left: 91.66667%; + } + + .row > .col-12-medium { + width: 100%; + } + + .row > .off-12-medium { + margin-left: 100%; + } + + .row.gtr-0 { + margin-top: 0; + margin-left:0; + } + + .row.gtr-0 > * { + padding: 0 0 0 0; + } + + .row.gtr-0.gtr-uniform { + margin-top:0; + } + + .row.gtr-0.gtr-uniform > * { + padding-top:0; + } + + .row.gtr-25 { + margin-top: 0; + margin-left: -0.5em; + } + + .row.gtr-25 > * { + padding: 0 0 0 0.5em; + } + + .row.gtr-25.gtr-uniform { + margin-top: -0.5em; + } + + .row.gtr-25.gtr-uniform > * { + padding-top: 0.5em; + } + + .row.gtr-50 { + margin-top: 0; + margin-left: -1em; + } + + .row.gtr-50 > * { + padding: 0 0 0 1em; + } + + .row.gtr-50.gtr-uniform { + margin-top: -1em; + } + + .row.gtr-50.gtr-uniform > * { + padding-top: 1em; + } + + .row { + margin-top: 0; + margin-left: -2em; + } + + .row > * { + padding: 0 0 0 2em; + } + + .row.gtr-uniform { + margin-top: -2em; + } + + .row.gtr-uniform > * { + padding-top: 2em; + } + + .row.gtr-150 { + margin-top: 0; + margin-left: -3em; + } + + .row.gtr-150 > * { + padding: 0 0 0 3em; + } + + .row.gtr-150.gtr-uniform { + margin-top: -3em; + } + + .row.gtr-150.gtr-uniform > * { + padding-top: 3em; + } + + .row.gtr-200 { + margin-top: 0; + margin-left: -4em; + } + + .row.gtr-200 > * { + padding: 0 0 0 4em; + } + + .row.gtr-200.gtr-uniform { + margin-top: -4em; + } + + .row.gtr-200.gtr-uniform > * { + padding-top: 4em; + } + + } + + @media screen and (max-width: 736px) { + + .row { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: stretch; + } + + .row > * { + box-sizing: border-box; + } + + .row.gtr-uniform > * > :last-child { + margin-bottom: 0; + } + + .row.aln-left { + justify-content: flex-start; + } + + .row.aln-center { + justify-content: center; + } + + .row.aln-right { + justify-content: flex-end; + } + + .row.aln-top { + align-items: flex-start; + } + + .row.aln-middle { + align-items: center; + } + + .row.aln-bottom { + align-items: flex-end; + } + + .row > .imp-small { + order: -1; + } + + .row > .col-1-small { + width: 8.33333%; + } + + .row > .off-1-small { + margin-left: 8.33333%; + } + + .row > .col-2-small { + width: 16.66667%; + } + + .row > .off-2-small { + margin-left: 16.66667%; + } + + .row > .col-3-small { + width: 25%; + } + + .row > .off-3-small { + margin-left: 25%; + } + + .row > .col-4-small { + width: 33.33333%; + } + + .row > .off-4-small { + margin-left: 33.33333%; + } + + .row > .col-5-small { + width: 41.66667%; + } + + .row > .off-5-small { + margin-left: 41.66667%; + } + + .row > .col-6-small { + width: 50%; + } + + .row > .off-6-small { + margin-left: 50%; + } + + .row > .col-7-small { + width: 58.33333%; + } + + .row > .off-7-small { + margin-left: 58.33333%; + } + + .row > .col-8-small { + width: 66.66667%; + } + + .row > .off-8-small { + margin-left: 66.66667%; + } + + .row > .col-9-small { + width: 75%; + } + + .row > .off-9-small { + margin-left: 75%; + } + + .row > .col-10-small { + width: 83.33333%; + } + + .row > .off-10-small { + margin-left: 83.33333%; + } + + .row > .col-11-small { + width: 91.66667%; + } + + .row > .off-11-small { + margin-left: 91.66667%; + } + + .row > .col-12-small { + width: 100%; + } + + .row > .off-12-small { + margin-left: 100%; + } + + .row.gtr-0 { + margin-top: 0; + margin-left:0; + } + + .row.gtr-0 > * { + padding: 0 0 0 0; + } + + .row.gtr-0.gtr-uniform { + margin-top:0; + } + + .row.gtr-0.gtr-uniform > * { + padding-top:0; + } + + .row.gtr-25 { + margin-top: 0; + margin-left: -0.5em; + } + + .row.gtr-25 > * { + padding: 0 0 0 0.5em; + } + + .row.gtr-25.gtr-uniform { + margin-top: -0.5em; + } + + .row.gtr-25.gtr-uniform > * { + padding-top: 0.5em; + } + + .row.gtr-50 { + margin-top: 0; + margin-left: -1em; + } + + .row.gtr-50 > * { + padding: 0 0 0 1em; + } + + .row.gtr-50.gtr-uniform { + margin-top: -1em; + } + + .row.gtr-50.gtr-uniform > * { + padding-top: 1em; + } + + .row { + margin-top: 0; + margin-left: -2em; + } + + .row > * { + padding: 0 0 0 2em; + } + + .row.gtr-uniform { + margin-top: -2em; + } + + .row.gtr-uniform > * { + padding-top: 2em; + } + + .row.gtr-150 { + margin-top: 0; + margin-left: -3em; + } + + .row.gtr-150 > * { + padding: 0 0 0 3em; + } + + .row.gtr-150.gtr-uniform { + margin-top: -3em; + } + + .row.gtr-150.gtr-uniform > * { + padding-top: 3em; + } + + .row.gtr-200 { + margin-top: 0; + margin-left: -4em; + } + + .row.gtr-200 > * { + padding: 0 0 0 4em; + } + + .row.gtr-200.gtr-uniform { + margin-top: -4em; + } + + .row.gtr-200.gtr-uniform > * { + padding-top: 4em; + } + + } + + @media screen and (max-width: 480px) { + + .row { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: stretch; + } + + .row > * { + box-sizing: border-box; + } + + .row.gtr-uniform > * > :last-child { + margin-bottom: 0; + } + + .row.aln-left { + justify-content: flex-start; + } + + .row.aln-center { + justify-content: center; + } + + .row.aln-right { + justify-content: flex-end; + } + + .row.aln-top { + align-items: flex-start; + } + + .row.aln-middle { + align-items: center; + } + + .row.aln-bottom { + align-items: flex-end; + } + + .row > .imp-xsmall { + order: -1; + } + + .row > .col-1-xsmall { + width: 8.33333%; + } + + .row > .off-1-xsmall { + margin-left: 8.33333%; + } + + .row > .col-2-xsmall { + width: 16.66667%; + } + + .row > .off-2-xsmall { + margin-left: 16.66667%; + } + + .row > .col-3-xsmall { + width: 25%; + } + + .row > .off-3-xsmall { + margin-left: 25%; + } + + .row > .col-4-xsmall { + width: 33.33333%; + } + + .row > .off-4-xsmall { + margin-left: 33.33333%; + } + + .row > .col-5-xsmall { + width: 41.66667%; + } + + .row > .off-5-xsmall { + margin-left: 41.66667%; + } + + .row > .col-6-xsmall { + width: 50%; + } + + .row > .off-6-xsmall { + margin-left: 50%; + } + + .row > .col-7-xsmall { + width: 58.33333%; + } + + .row > .off-7-xsmall { + margin-left: 58.33333%; + } + + .row > .col-8-xsmall { + width: 66.66667%; + } + + .row > .off-8-xsmall { + margin-left: 66.66667%; + } + + .row > .col-9-xsmall { + width: 75%; + } + + .row > .off-9-xsmall { + margin-left: 75%; + } + + .row > .col-10-xsmall { + width: 83.33333%; + } + + .row > .off-10-xsmall { + margin-left: 83.33333%; + } + + .row > .col-11-xsmall { + width: 91.66667%; + } + + .row > .off-11-xsmall { + margin-left: 91.66667%; + } + + .row > .col-12-xsmall { + width: 100%; + } + + .row > .off-12-xsmall { + margin-left: 100%; + } + + .row.gtr-0 { + margin-top: 0; + margin-left:0; + } + + .row.gtr-0 > * { + padding: 0 0 0 0; + } + + .row.gtr-0.gtr-uniform { + margin-top:0; + } + + .row.gtr-0.gtr-uniform > * { + padding-top:0; + } + + .row.gtr-25 { + margin-top: 0; + margin-left: -0.5em; + } + + .row.gtr-25 > * { + padding: 0 0 0 0.5em; + } + + .row.gtr-25.gtr-uniform { + margin-top: -0.5em; + } + + .row.gtr-25.gtr-uniform > * { + padding-top: 0.5em; + } + + .row.gtr-50 { + margin-top: 0; + margin-left: -1em; + } + + .row.gtr-50 > * { + padding: 0 0 0 1em; + } + + .row.gtr-50.gtr-uniform { + margin-top: -1em; + } + + .row.gtr-50.gtr-uniform > * { + padding-top: 1em; + } + + .row { + margin-top: 0; + margin-left: -2em; + } + + .row > * { + padding: 0 0 0 2em; + } + + .row.gtr-uniform { + margin-top: -2em; + } + + .row.gtr-uniform > * { + padding-top: 2em; + } + + .row.gtr-150 { + margin-top: 0; + margin-left: -3em; + } + + .row.gtr-150 > * { + padding: 0 0 0 3em; + } + + .row.gtr-150.gtr-uniform { + margin-top: -3em; + } + + .row.gtr-150.gtr-uniform > * { + padding-top: 3em; + } + + .row.gtr-200 { + margin-top: 0; + margin-left: -4em; + } + + .row.gtr-200 > * { + padding: 0 0 0 4em; + } + + .row.gtr-200.gtr-uniform { + margin-top: -4em; + } + + .row.gtr-200.gtr-uniform > * { + padding-top: 4em; + } + + } + + @media screen and (max-width: 320px) { + + .row { + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: stretch; + } + + .row > * { + box-sizing: border-box; + } + + .row.gtr-uniform > * > :last-child { + margin-bottom: 0; + } + + .row.aln-left { + justify-content: flex-start; + } + + .row.aln-center { + justify-content: center; + } + + .row.aln-right { + justify-content: flex-end; + } + + .row.aln-top { + align-items: flex-start; + } + + .row.aln-middle { + align-items: center; + } + + .row.aln-bottom { + align-items: flex-end; + } + + .row > .imp-xxsmall { + order: -1; + } + + .row > .col-1-xxsmall { + width: 8.33333%; + } + + .row > .off-1-xxsmall { + margin-left: 8.33333%; + } + + .row > .col-2-xxsmall { + width: 16.66667%; + } + + .row > .off-2-xxsmall { + margin-left: 16.66667%; + } + + .row > .col-3-xxsmall { + width: 25%; + } + + .row > .off-3-xxsmall { + margin-left: 25%; + } + + .row > .col-4-xxsmall { + width: 33.33333%; + } + + .row > .off-4-xxsmall { + margin-left: 33.33333%; + } + + .row > .col-5-xxsmall { + width: 41.66667%; + } + + .row > .off-5-xxsmall { + margin-left: 41.66667%; + } + + .row > .col-6-xxsmall { + width: 50%; + } + + .row > .off-6-xxsmall { + margin-left: 50%; + } + + .row > .col-7-xxsmall { + width: 58.33333%; + } + + .row > .off-7-xxsmall { + margin-left: 58.33333%; + } + + .row > .col-8-xxsmall { + width: 66.66667%; + } + + .row > .off-8-xxsmall { + margin-left: 66.66667%; + } + + .row > .col-9-xxsmall { + width: 75%; + } + + .row > .off-9-xxsmall { + margin-left: 75%; + } + + .row > .col-10-xxsmall { + width: 83.33333%; + } + + .row > .off-10-xxsmall { + margin-left: 83.33333%; + } + + .row > .col-11-xxsmall { + width: 91.66667%; + } + + .row > .off-11-xxsmall { + margin-left: 91.66667%; + } + + .row > .col-12-xxsmall { + width: 100%; + } + + .row > .off-12-xxsmall { + margin-left: 100%; + } + + .row.gtr-0 { + margin-top: 0; + margin-left:0; + } + + .row.gtr-0 > * { + padding: 0 0 0 0; + } + + .row.gtr-0.gtr-uniform { + margin-top:0; + } + + .row.gtr-0.gtr-uniform > * { + padding-top:0; + } + + .row.gtr-25 { + margin-top: 0; + margin-left: -0.5em; + } + + .row.gtr-25 > * { + padding: 0 0 0 0.5em; + } + + .row.gtr-25.gtr-uniform { + margin-top: -0.5em; + } + + .row.gtr-25.gtr-uniform > * { + padding-top: 0.5em; + } + + .row.gtr-50 { + margin-top: 0; + margin-left: -1em; + } + + .row.gtr-50 > * { + padding: 0 0 0 1em; + } + + .row.gtr-50.gtr-uniform { + margin-top: -1em; + } + + .row.gtr-50.gtr-uniform > * { + padding-top: 1em; + } + + .row { + margin-top: 0; + margin-left: -2em; + } + + .row > * { + padding: 0 0 0 2em; + } + + .row.gtr-uniform { + margin-top: -2em; + } + + .row.gtr-uniform > * { + padding-top: 2em; + } + + .row.gtr-150 { + margin-top: 0; + margin-left: -3em; + } + + .row.gtr-150 > * { + padding: 0 0 0 3em; + } + + .row.gtr-150.gtr-uniform { + margin-top: -3em; + } + + .row.gtr-150.gtr-uniform > * { + padding-top: 3em; + } + + .row.gtr-200 { + margin-top: 0; + margin-left: -4em; + } + + .row.gtr-200 > * { + padding: 0 0 0 4em; + } + + .row.gtr-200.gtr-uniform { + margin-top: -4em; + } + + .row.gtr-200.gtr-uniform > * { + padding-top: 4em; + } + + } + +/* Section/Article */ + section.special, article.special { + text-align: center; + } + + article > h2.title:after { + background: rgba(144, 144, 144, 0.5); + content: ''; + display: inherit; + height: 1px; + width: 6em; + margin: 1em 0; + } + + article > h2 > p.tech{ + margin: 0 !important; + } + + article.major:after { + background: rgba(144, 144, 144, 0.5); + content: ''; + display: inline-block; + height: 1px; + margin-top: 1.5em; + width: 6em; +} + + header p { + color: #999; + margin: 0 0 1.5em 0; + position: relative; + } + + header h2 + p { + font-size: 1.25em; + line-height: 1.5em; + margin-top: -1em; + } + + header h3 + p { + font-size: 1.1em; + line-height: 1.5em; + margin-top: -0.8em; + } + + header h4 + p, + header h5 + p, + header h6 + p { + font-size: 0.9em; + line-height: 1.5em; + margin-top: -0.6em; + } + + header.major { + margin: 0 0 1em 0; + } + + header.major:after { + background: rgba(144, 144, 144, 0.5); + content: ''; + display: flex; + height: 1px; + margin-top: 1.5em; + width: 6em; + margin: 1em auto; + } + + header.major h2, header.major h3, header.major h4, header.major h5, header.major h6 { + margin: 0; + } + + header.major p { + margin: 0.7em 0 0 0; + } + + header.special { + text-align: center; + } + +/* Form */ + + form { + margin: 0 0 2em 0; + } + + label { + color: #555; + display: block; + font-size: 0.9em; + font-weight: 400; + margin: 0 0 1em 0; + } + + input[type="text"], + input[type="password"], + input[type="email"], + select, + textarea { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + background: rgba(144, 144, 144, 0.075); + border-radius: 4px; + color: inherit; + display: block; + outline: 0; + padding: 0 1em; + text-decoration: none; + width: 100%; + border: 1px solid #ccc; /* Gray border */ + box-sizing: border-box; /* Make sure that padding and width stays in place */ + margin-top: 10px; /* Add a top margin */ + margin-bottom: 1em; /* Bottom margin */ + resize: vertical /* Allow the user to vertically resize the textarea (not horizontally) */ + } + + input[type="text"]:invalid, + input[type="password"]:invalid, + input[type="email"]:invalid, + select:invalid, + textarea:invalid { + box-shadow: none; + } + + input[type="text"]:focus, + input[type="password"]:focus, + input[type="email"]:focus, + select:focus, + textarea:focus { + border-color: #6bd4c8; + } + + select { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' preserveAspectRatio='none' viewBox='0 0 40 40'%3E%3Cpath d='M9.4,12.3l10.4,10.4l10.4-10.4c0.2-0.2,0.5-0.4,0.9-0.4c0.3,0,0.6,0.1,0.9,0.4l3.3,3.3c0.2,0.2,0.4,0.5,0.4,0.9 c0,0.4-0.1,0.6-0.4,0.9L20.7,31.9c-0.2,0.2-0.5,0.4-0.9,0.4c-0.3,0-0.6-0.1-0.9-0.4L4.3,17.3c-0.2-0.2-0.4-0.5-0.4-0.9 c0-0.4,0.1-0.6,0.4-0.9l3.3-3.3c0.2-0.2,0.5-0.4,0.9-0.4S9.1,12.1,9.4,12.3z' fill='rgba(144, 144, 144, 0.5)' /%3E%3C/svg%3E"); + background-size: 1.25rem; + background-repeat: no-repeat; + background-position: calc(100% - 1rem) center; + height: 2.75em; + padding-right: 2.75em; + text-overflow: ellipsis; + } + + select option { + color: #555; + background: #fff; + } + + input[type="text"], + input[type="password"], + input[type="email"], + select { + height: 1.75em; + padding: 1em; + } + + textarea { + padding: 0.75em 1em; + } + + input[type="checkbox"] + label, + input[type="radio"] + label { + text-decoration: none; + color: #666; + cursor: pointer; + display: inline-block; + font-size: 1em; + font-weight: 300; + padding-left: 2.4em; + padding-right: 0.75em; + position: relative; + } + + input[type="checkbox"] + label:before, + input[type="radio"] + label:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; + text-transform: none !important; + font-family: 'Font Awesome 5 Free', sans-serif; + font-weight: 900; + } + + input[type="checkbox"] + label:before, + input[type="radio"] + label:before { + background: rgba(144, 144, 144, 0.075); + border-radius: 4px; + border: solid 1px rgba(144, 144, 144, 0.5); + content: ''; + display: inline-block; + font-size: 0.8em; + height: 2.0625em; + left: 0; + line-height: 2.0625em; + position: absolute; + text-align: center; + top: 0; + width: 2.0625em; + } + + input[type="checkbox"]:checked + label:before, + input[type="radio"]:checked + label:before { + background: #666666; + border-color: #666666; + color: #ffffff; + content: '\f00c'; + } + + input[type="checkbox"]:focus + label:before, + input[type="radio"]:focus + label:before { + border-color: #6bd4c8; + } + + input[type="checkbox"] + label:before { + border-radius: 4px; + } + + input[type="radio"] + label:before { + border-radius: 100%; + } + + ::-webkit-input-placeholder { + color: #999 !important; + opacity: 1.0; + } + + :-moz-placeholder { + color: #999 !important; + opacity: 1.0; + } + + ::-moz-placeholder { + color: #999 !important; + opacity: 1.0; + } + +/* Box */ + + .box-list, + .box { + margin: 5px; + padding: 1.5em; + border-radius: 4px; + border: solid 2px #949494; + } + + .box.alt { + border: 0; + border-radius: 0; + padding: 0; + } + + .box-list:hover{ + border-radius: 4px; + border: solid 2px rgb(67, 67, 67); + } + + a.project-title-container:hover{ + color: #004F99 !important; + } + +/* Icon */ + + .icon { + text-decoration: none; + border-bottom: none; + position: relative; + } + + .icon:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; + text-transform: none !important; + font-family: 'Font Awesome 5 Free', sans-serif; + font-weight: 400; + } + + .icon > .label { + display: none; + } + + .icon:before { + line-height: inherit; + } + + .icon.solid:before { + font-weight: 900 !important; + } + + .icon.brands:before { + font-family: 'Font Awesome 5 Brands', sans-serif; + } + + .icon.style1:before { + color: #c3e895; + } + + .icon.style2:before { + color: #8addaa; + } + + .icon.style3:before { + color: #6bd4c8; + } + + .icon.style4:before { + color: #57aed3; + } + + .icon.style5:before { + color: #4a87d3; + } + + .icon.style6:before { + color: #6b88e6; + } + + .icon.major { + text-decoration: none; + color: #555; + cursor: default; + display: inline-block; + margin: 0 0 1.5em 0; + } + + .icon.major:before { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; + text-transform: none !important; + font-family: 'Font Awesome 5 Free', sans-serif; + font-weight: 400; + } + + .icon.major:before { + font-size: 4em; + line-height: 1em; + } + +/* Image */ + + .image { + border-radius: 4px; + border: 0; + display: inline-block; + position: relative; + } + + .image img { + margin-top: 2em; + display: block; + } + + .image.left { + float: left; + padding: 0 1.5em 1em 0; + top: 0.25em; + } + + .image.right { + float: right; + padding: 0 0 1em 1.5em; + top: 0.25em; + } + + .image.left, .image.right { + max-width: 40%; + } + + .image.left img, .image.right img { + width: 100%; + } + + .image.fit { + display: block; + margin: 0 0 2em 0; + width: 100% !important; + } + + .image.fit img { + width: 100%; + } + +/* List */ + + ol { + list-style: decimal; + margin: 0 0 2em 0; + padding-left: 1.25em; + } + + ol li { + padding-left: 0.25em; + font-size: 1.5rem; + } + + ul { + list-style: disc; + margin: 0 0 2em 0; + padding-left: 1em; + font-size: 18pt; + } + + ul li { + padding-left: 0.25em; + color: black; + } + + ul.alt { + list-style: none; + padding-left: 0; + } + + ul.alt li { + border-top: solid 1px rgba(144, 144, 144, 0.5); + padding: 0.5em 0; + } + + ul.alt li:first-child { + border-top: 0; + padding-top: 0; + } + + dl { + margin: 0 0 2em 0; + } + +/* Actions */ + + ul.actions { + display: -moz-flex; + display: -webkit-flex; + display: -ms-flex; + display: flex; + cursor: default; + list-style: none; + margin-left: -1em; + padding-left: 0; + } + + ul.actions li { + padding: 0 0 0 1em; + vertical-align: middle; + } + + ul.actions.special { + -webkit-justify-content: center; + justify-content: center; + width: 100%; + margin-left: 0; + } + + ul.actions.special li:first-child { + padding-left: 0; + } + + ul.actions.stacked { + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + margin-left: 0; + } + + ul.actions.stacked li { + padding: 1.3em 0 0 0; + } + + ul.actions.stacked li:first-child { + padding-top: 0; + } + + ul.actions.fit { + width: calc(100% + 1em); + } + + ul.actions.fit li { + -webkit-flex-grow: 1; + flex-grow: 1; + -webkit-flex-shrink: 1; + flex-shrink: 1; + width: 100%; + } + + ul.actions.fit li > * { + width: 100%; + } + + ul.actions.fit.stacked { + width: 100%; + } + + @media screen and (max-width: 480px) { + + ul.actions:not(.fixed) { + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + margin-left: 0; + width: 100% !important; + } + + ul.actions:not(.fixed) li { + -webkit-flex-grow: 1; + flex-grow: 1; + -webkit-flex-shrink: 1; + flex-shrink: 1; + padding: 1em 0 0 0; + text-align: center; + width: 100%; + } + + ul.actions:not(.fixed) li > * { + width: 100%; + } + + ul.actions:not(.fixed) li:first-child { + padding-top: 0; + } + + ul.actions:not(.fixed) li input[type="submit"], + ul.actions:not(.fixed) li input[type="reset"], + ul.actions:not(.fixed) li input[type="button"], + ul.actions:not(.fixed) li button, + ul.actions:not(.fixed) li .button { + width: 100%; + } + + ul.actions:not(.fixed) li input[type="submit"].icon:before, + ul.actions:not(.fixed) li input[type="reset"].icon:before, + ul.actions:not(.fixed) li input[type="button"].icon:before, + ul.actions:not(.fixed) li button.icon:before, + ul.actions:not(.fixed) li .button.icon:before { + margin-left: -0.5em; + } + + } + +/* Icons */ + + ul.icons { + cursor: default; + list-style: none; + padding-left: 0; + } + + ul.icons li { + display: inline-block; + padding: 0 1.25em 0 0; + } + + ul.icons li:last-child { + padding-right: 0; + } + + ul.icons li .icon:before { + font-size: 1.5em; + } + +/* Major Icons */ + + ul.major-icons { + list-style: none; + padding-left: 0; + font-size: inherit; + } + + ul.major-icons li { + display: inline-block; + padding: 2.5em; + text-align: center; + } + + ul.major-icons li .icon { + -moz-transform: rotate(45deg); + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + border-radius: 4px; + border: solid 1px rgba(144, 144, 144, 0.5); + display: inline-block; + height: 8em; + line-height: 8em; + margin: 0; + text-align: center; + width: 8em; + } + + ul.major-icons li .icon:before { + -moz-transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg); + display: inline-block; + line-height: inherit; + } + +/* Table */ + .table-wrapper { + -webkit-overflow-scrolling: touch; + overflow-x: auto; + } + + table { + margin: 0 0 2em 0; + width: 100%; + } + + table tbody tr { + border-left: 0; + border-right: 0; + } + + table tbody tr:nth-child(2n + 1) { + background-color: rgba(144, 144, 144, 0.075); + } + + table td { + padding: 0.75em 0.75em; + } + + table th { + color: #555; + font-size: 0.9em; + font-weight: 400; + padding: 0 0.75em 0.75em 0.75em; + text-align: left; + } + + table thead { + border-bottom: solid 1px rgba(144, 144, 144, 0.5); + } + + table tfoot { + border-top: solid 1px rgba(144, 144, 144, 0.5); + } + + table.alt { + border-collapse: separate; + } + + table.alt tbody tr td { + border: solid 1px rgba(144, 144, 144, 0.5); + border-left-width: 0; + border-top-width: 0; + } + + table.alt tbody tr td:first-child { + border-left-width: 1px; + } + + table.alt tbody tr:first-child td { + border-top-width: 1px; + } + + table.alt thead { + border-bottom: 0; + } + + table.alt tfoot { + border-top: 0; + } + +/* Button */ + input[type="submit"], + input[type="reset"], + input[type="button"], + button, + .button { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + -moz-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; + -webkit-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; + transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out; + background-color: transparent; + border-radius: 4px; + border: 1px solid black; + color: black; + justify-content: space-between; + cursor: pointer; + display: inline-block; + font-size: 0.9em; + font-weight: 400; + height: 2.75em; + letter-spacing: 0.125em; + line-height: 2.75em; + padding: 0 2em; + text-align: center; + text-decoration: none; + text-indent: 0.125em; + text-transform: uppercase; + white-space: nowrap; + } + + input[type="submit"]:hover, + input[type="reset"]:hover, + input[type="button"]:hover, + button:hover, + .button:hover { + background-color: #D7DDE9; + border-radius: 5px; + } + + input[type="submit"]:active, + input[type="reset"]:active, + input[type="button"]:active, + button:active, + .button:active { + background-color: rgba(144, 144, 144, 0.2); + } + + input[type="submit"].icon:before, + input[type="reset"].icon:before, + input[type="button"].icon:before, + button.icon:before, + .button.icon:before { + margin-right: 0.5em; + } + + input[type="submit"].fit, + input[type="reset"].fit, + input[type="button"].fit, + button.fit, + .button.fit { + width: 100%; + } + + input[type="submit"].small, + input[type="reset"].small, + input[type="button"].small, + button.small, + .button.small { + font-size: 0.7em; + } + + input[type="submit"].large, + input[type="reset"].large, + input[type="button"].large, + button.large, + .button.large { + font-size: 1.25em; + } + + input[type="submit"].wide, + input[type="reset"].wide, + input[type="button"].wide, + button.wide, + .button.wide { + min-width: 12em; + color: #ffffff; + } + + input[type="submit"].primary, + input[type="reset"].primary, + input[type="button"].primary, + button.primary, + .button.primary { + background-color: #555; + box-shadow: none !important; + color: #fff !important; + } + + input[type="submit"].primary:hover, + input[type="reset"].primary:hover, + input[type="button"].primary:hover, + button.primary:hover, + .button.primary:hover { + background-color: #626262; + } + + input[type="submit"].primary:active, + input[type="reset"].primary:active, + input[type="button"].primary:active, + button.primary:active, + .button.primary:active { + background-color: #484848; + } + + input[type="submit"].disabled, input[type="submit"]:disabled, + input[type="reset"].disabled, + input[type="reset"]:disabled, + input[type="button"].disabled, + input[type="button"]:disabled, + button.disabled, + button:disabled, + .button.disabled, + .button:disabled { + cursor: default; + opacity: 0.25; + } + +/* Main */ + .main { + padding: 6em 0 4em 0 ; + flex-grow: 5; + } + + .main.style1 { + background: #fff; + } + + .main.style2 { + color: rgba(255, 255, 255, 255); + background-attachment: scroll; + background-image: linear-gradient(rgba(0, 0, 0,0.3), rgba( 0,0,0,1)), url("images/img036.jpg"); + background-size: cover; + } + + .main.style2 a { + border-bottom-color: rgba(255, 255, 255, 0.5); + } + + .main.style2 a:hover { + color: #ffffff; + } + + .main.style2 h1, .main.style2 h2, .main.style2 h3, .main.style2 h4, .main.style2 h5, .main.style2 h6, .main.style2 strong, .main.style2 b { + color: #ffffff; + } + + .main.style2 header p { + color: #ffffff; + } + + .main.style2 header.major:after { + background: #ffffff; + } + + .main.style2 input[type="submit"], + .main.style2 input[type="reset"], + .main.style2 input[type="button"], + .main.style2 button, + .main.style2 .button { + box-shadow: inset 0 0 0 2px #ffffff; + color: #ffffff !important; + font-weight: bold; + } + + .main.style2 input[type="submit"]:hover, + .main.style2 input[type="reset"]:hover, + .main.style2 input[type="button"]:hover, + .main.style2 button:hover, + .main.style2 .button:hover { + background-color: rgba(255, 255, 255, 0.125); + } + + .main.style2 input[type="submit"]:active, + .main.style2 input[type="reset"]:active, + .main.style2 input[type="button"]:active, + .main.style2 button:active, + .main.style2 .button:active { + background-color: rgba(255, 255, 255, 0.25); + } + + .main.style2 input[type="submit"].primary, + .main.style2 input[type="reset"].primary, + .main.style2 input[type="button"].primary, + .main.style2 button.primary, + .main.style2 .button.primary { + background-color: #ffffff; + box-shadow: inset 0 0 0 2px #ffffff !important; + color: #333 !important; + } + + .main.style2 input[type="submit"].primary:hover, + .main.style2 input[type="reset"].primary:hover, + .main.style2 input[type="button"].primary:hover, + .main.style2 button.primary:hover, + .main.style2 .button.primary:hover { + background-color: rgba(255, 255, 255, 0.125) !important; + color: #ffffff !important; + } + + .main.style2 input[type="submit"].primary:active, + .main.style2 input[type="reset"].primary:active, + .main.style2 input[type="button"].primary:active, + .main.style2 button.primary:active, + .main.style2 .button.primary:active { + background-color: rgba(255, 255, 255, 0.25) !important; + } + + .main.style2 ul.major-icons li .icon { + border-color: #ffffff; + } + + .main.style2 .icon.major { + color: #ffffff; + } + +/* Header */ + + #header { + padding: 10em 0 10em 0 ; + background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 1)), url("/images/hero_image.jpg"); + background-position: 50% 30%; + background-size: cover; + overflow: hidden; + position: relative; + text-align: center; + } + + #header a { + border-bottom-color: rgba(255, 255, 255, 0.5); + } + + #header a:hover { + color: #ffffff; + } + + #header h1, #header h2, #header h3, #header h4, #header h5, #header h6, #header strong, #header b { + color: #ffffff; + } + + #header header p { + color: #ffffff; + } + + #header header.major:after { + background: #ffffff; + } + + #header input[type="submit"], + #header input[type="reset"], + #header input[type="button"], + #header button, + #header .button { + box-shadow: inset 0 0 0 1px #ffffff; + color: #ffffff !important; + } + + #header input[type="submit"]:hover, + #header input[type="reset"]:hover, + #header input[type="button"]:hover, + #header button:hover, + #header .button:hover { + background-color: rgba(255, 255, 255, 0.125); + } + + #header input[type="submit"]:active, + #header input[type="reset"]:active, + #header input[type="button"]:active, + #header button:active, + #header .button:active { + background-color: rgba(255, 255, 255, 0.25); + } + + #header input[type="submit"].primary, + #header input[type="reset"].primary, + #header input[type="button"].primary, + #header button.primary, + #header .button.primary { + background-color: #ffffff; + box-shadow: inset 0 0 0 1px #ffffff !important; + color: #4686a0 !important; + } + + #header input[type="submit"].primary:hover, + #header input[type="reset"].primary:hover, + #header input[type="button"].primary:hover, + #header button.primary:hover, + #header .button.primary:hover { + background-color: rgba(255, 255, 255, 0.125) !important; + color: #ffffff !important; + } + + #header input[type="submit"].primary:active, + #header input[type="reset"].primary:active, + #header input[type="button"].primary:active, + #header button.primary:active, + #header .button.primary:active { + background-color: rgba(255, 255, 255, 0.25) !important; + } + + #header ul.major-icons li .icon { + border-color: #ffffff; + } + + #header .icon.major { + color: #ffffff; + } + + #header h1 { + margin: 0; + } + + #header p { + margin: 1em 0 0 0; + } + + #header .actions { + -webkit-justify-content: center; + justify-content: center; + margin-top: 2.5em; + margin-left: 0; + position: relative; + } + + #header .actions li:first-child { + padding-left: 0; + } + + #header .actions:after { + background: #ffffff; + content: ''; + height: 100vh; + left: 50%; + position: absolute; + top: 100%; + width: 1px; + } + + #header .inner { + -moz-transition: -moz-transform 1s ease, opacity 2s ease; + -webkit-transition: -webkit-transform 1s ease, opacity 2s ease; + transition: transform 1.5s ease, opacity 2s ease; + -moz-transition-delay: 0.25s; + -webkit-transition-delay: 0.25s; + transition-delay: 0.25s; + -moz-transform: scale(1); + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + opacity: 1; + position: relative; + z-index: 1; + } + + #header .inner .actions { + -moz-transition: -moz-transform 1.25s ease; + -webkit-transition: -webkit-transform 1.25s ease; + transition: transform 1.25s ease; + -moz-transition-delay: 1s; + -webkit-transition-delay: 1s; + transition-delay: 1s; + -moz-transform: translateY(0); + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + opacity: 1; + } + + #header:after { + + -moz-transition: opacity 1s ease; + -webkit-transition: opacity 1s ease; + transition: opacity 1s ease; + content: ''; + height: 100%; + left: 0; + opacity: 0; + position: absolute; + top: 0; + width: 100%; + } + + body.is-preload #header .inner { + -moz-transform: scale(1.05); + -webkit-transform: scale(1.05); + -ms-transform: scale(1.05); + transform: scale(1.05); + opacity: 0; + } + + body.is-preload #header .inner .actions { + -moz-transform: translateY(30em); + -webkit-transform: translateY(30em); + -ms-transform: translateY(30em); + transform: translateY(30em); + opacity: 0; + } + + body.is-preload #header:after { + opacity: 1; + } + +/* Navbar */ +.navbar { + background-color: #333333; + min-height: 3.25rem; + position:relative; + display: flex; + font: inherit; + font-size: 30px; +} + +.navbar-brand .navbar-link::after { + border-color:#0a0a0a +} + +@media screen and (min-width:1024px) { + .navbar.is-primary .navbar-end .navbar-link, + .navbar.is-primary .navbar-end>.navbar-item, + .navbar.is-primary .navbar-start .navbar-link, + .navbar.is-primary .navbar-start>.navbar-item { + color:#fff + } + .navbar.is-primary .navbar-end .navbar-link.is-active, + .navbar.is-primary .navbar-end .navbar-link:focus, + .navbar.is-primary .navbar-end .navbar-link:hover, + .navbar.is-primary .navbar-end>a.navbar-item.is-active, + .navbar.is-primary .navbar-end>a.navbar-item:focus, + .navbar.is-primary .navbar-end>a.navbar-item:hover, + .navbar.is-primary .navbar-start .navbar-link.is-active, + .navbar.is-primary .navbar-start .navbar-link:focus, + .navbar.is-primary .navbar-start .navbar-link:hover, + .navbar.is-primary .navbar-start>a.navbar-item.is-active, + .navbar.is-primary .navbar-start>a.navbar-item:focus, + .navbar.is-primary .navbar-start>a.navbar-item:hover { + background-color:#00b89c; + color:#fff + } + .navbar.is-primary .navbar-end .navbar-link::after, + .navbar.is-primary .navbar-start .navbar-link::after { + border-color:#fff + } + .navbar.is-primary .navbar-item.has-dropdown.is-active .navbar-link, + .navbar.is-primary .navbar-item.has-dropdown:focus .navbar-link, + .navbar.is-primary .navbar-item.has-dropdown:hover .navbar-link { + background-color:#00b89c; + color:#fff + } + .navbar.is-primary .navbar-dropdown a.navbar-item.is-active { + background-color:#00d1b2; + color:#fff + } + + article > h2.title::after { + background: rgba(144, 144, 144, 0.5); + content: ''; + display: inherit; + height: 1px; + width: 6em; + margin: 0.5em 0; + } +} +.navbar.is-link { + background-color:#485fc7; + color:#fff +} + +.navbar>.container { + align-items:stretch; + display:flex; + min-height:3.25rem; + width:100% +} +.navbar.has-shadow { + box-shadow:0 2px 0 0 #f5f5f5 +} + +.navbar.is-fixed-bottom, +.navbar.is-fixed-top { + left:0; + position:fixed; + right:0; + z-index:30 +} +.navbar.is-fixed-bottom { + bottom:0 +} +.navbar.is-fixed-bottom.has-shadow { + box-shadow:0 -2px 0 0 #f5f5f5 +} +.navbar.is-fixed-top { + top:0 +} +body.has-navbar-fixed-top, +html.has-navbar-fixed-top { + padding-top:3.25rem +} +body.has-navbar-fixed-bottom, +html.has-navbar-fixed-bottom { + padding-bottom:3.25rem +} +.navbar-brand, +.navbar-tabs { + align-items:stretch; + display:flex; + flex-shrink:0; + min-height:3.25rem +} +.navbar-brand a.navbar-item:focus, +.navbar-brand a.navbar-item:hover { + background-color:transparent +} +.navbar-tabs { + -webkit-overflow-scrolling:touch; + max-width:100vw; + overflow-x:auto; + overflow-y:hidden +} +.navbar-burger { + color:white; + -moz-appearance:none; + -webkit-appearance:none; + appearance:none; + background:0 0; + border:none; + cursor:pointer; + display:block; + height:3.25rem; + position:relative; + width:3.25rem; + margin-left:auto +} +.navbar-burger span { + background-color:currentColor; + display:block; + height:2px; + left:calc(50% - 8px); + position:absolute; + transform-origin:center; + transition-duration:86ms; + transition-property:background-color,opacity,transform; + transition-timing-function:ease-out; + width:20px +} +.navbar-burger span:first-child { + top:calc(50% - 6px) +} +.navbar-burger span:nth-child(2) { + top:calc(50% - 1px) +} +.navbar-burger span:nth-child(3) { + top:calc(50% + 4px) +} +.navbar-burger:hover { + background-color:white; +} +.navbar-burger.is-active span:first-child { + transform:translateY(5px) rotate(45deg) +} +.navbar-burger.is-active span:nth-child(2) { + opacity:0 +} +.navbar-burger.is-active span:nth-child(3) { + transform:translateY(-5px) rotate(-45deg) +} +.navbar-menu { + display:none +} +.navbar-item, +.navbar-link { + color:#ffffff; + line-height:1.5; + padding:.5rem .75rem; + position:relative; + display: block; +} +.navbar-item .icon:only-child, +.navbar-link .icon:only-child { + margin-left:-.25rem; + margin-right:-.25rem +} +.navbar-link, +a.navbar-item { + cursor:pointer; + font-size: 25px; +} + +.navbar-link:focus, +.navbar-link:focus-within, +.navbar-link:hover, +a.navbar-item.is-active, +a.navbar-item:focus, +.navbar-link.is-active, +a.navbar-item:hover, +a.navbar-item:focus-within{ + background-color: #D7DDE9; + color: black; +} + +.navbar-item { + flex-grow:0; + flex-shrink:0 +} +.navbar-item img { + max-height:1.75rem +} +.navbar-item.has-dropdown { + padding:0 +} +.navbar-item.is-expanded { + flex-grow:1; + flex-shrink:1 +} +.navbar-item.is-tab { + border-bottom:1px solid transparent; + min-height:3.25rem; + padding-bottom:calc(.5rem - 1px) +} +.navbar-item.is-tab:focus, +.navbar-item.is-tab:hover { + background-color:transparent; + border-bottom-color:#485fc7 +} +.navbar-item.is-tab.is-active { + background-color:transparent; + border-bottom-color:#485fc7; + border-bottom-style:solid; + border-bottom-width:3px; + color:#485fc7; + padding-bottom:calc(.5rem - 3px) +} +.navbar-content { + flex-grow:1; + flex-shrink:1 +} +.navbar-link:not(.is-arrowless) { + padding-right:2.5em +} +.navbar-link:not(.is-arrowless)::after { + border-color:#485fc7; + margin-top:-.375em; + right:1.125em +} +.navbar-dropdown { + font-size:.875rem; + padding-bottom:.5rem; + padding-top:.5rem +} +.navbar-dropdown .navbar-item { + padding-left:1.5rem; + padding-right:1.5rem +} +.navbar-divider { + background-color:#f5f5f5; + border:none; + display:none; + height:2px; + margin:.5rem 0 +} + +.is-centered{ + justify-content: center; +} + +/* Paginator */ +.pagination { + font-size: 1rem; + margin: -.25rem +} + +.is-rounded{ + border-radius: 5px; +} + +.pagination.is-small { + font-size:.75rem +} + +.pagination.is-medium { + font-size:1.25rem +} +.pagination.is-rounded .pagination-next, +.pagination.is-rounded .pagination-previous { + padding-left:1em; + padding-right:1em; + border-radius:4px; +} + +.pagination.is-rounded .pagination-link { + border-radius:4px; +} + +.pagination, +.pagination-list { + align-items:flex-start; + display:flex; + justify-content:center; + text-align:center +} +.pagination-ellipsis, +.pagination-link, +.pagination-next, +.pagination-previous { + justify-content:center; + margin:.25rem; + padding-left:.5em; + padding-right:.5em; + text-align:center +} +.pagination-link, +.pagination-next, +.pagination-previous { + border-color:#dbdbdb; + color: #000000; + min-width:2em +} +.pagination-link:hover, +.pagination-next:hover, +.pagination-previous:hover { + background-color: #004F99; + color: white; +} +.pagination-link:focus, +.pagination-next:focus, +.pagination-previous:focus { + border-color: #004F99; +} +.pagination-link:active, +.pagination-next:active, +.pagination-previous:active { + box-shadow:inset 0 1px 2px rgba(10,10,10,.2) +} + +.pagination-link.is-disabled, +.pagination-link[disabled], +.pagination-next.is-disabled, +.pagination-next[disabled], +.pagination-previous.is-disabled, +.pagination-previous[disabled] { + background-color:#dbdbdb; + border-color:#dbdbdb; + box-shadow:none; + color:#7a7a7a; + opacity:.5; +} +.pagination-next, +.pagination-previous { + padding-left:.75em; + padding-right:.75em; + white-space:nowrap +} +.pagination-link.is-current { + background-color: #004F99; + color:#fff +} +.pagination-ellipsis { + color:#b5b5b5; + pointer-events:none +} + +.pagination-list { + flex-wrap:wrap +} +.pagination-list li { + list-style:none +} +@media screen and (max-width:768px) { + .pagination { + flex-wrap:wrap + } + .pagination-next, + .pagination-previous { + flex-grow:1; + flex-shrink:1 + } + .pagination-list li { + flex-grow:1; + flex-shrink:1 + } +} +@media screen and (min-width:769px),print { + .pagination-list { + flex-grow:1; + flex-shrink:1; + justify-content:flex-start; + order:1 + } + .pagination-ellipsis, + .pagination-link, + .pagination-next, + .pagination-previous { + margin-bottom:0; + margin-top:0 + } + .pagination-previous { + order:2 + } + .pagination-next { + order:3 + } + .pagination { + justify-content:space-between; + margin-bottom:0; + margin-top:0 + } + .pagination.is-centered .pagination-previous { + order:1 + } + .pagination.is-centered .pagination-list { + justify-content:center; + order:2 + } + .pagination.is-centered .pagination-next { + order:3 + } + .pagination.is-right .pagination-previous { + order:1 + } + .pagination.is-right .pagination-next { + order:2 + } + .pagination.is-right .pagination-list { + justify-content:flex-end; + order:3 + } +} + +.pagination a.active { + background-color: #4CAF50; + color: white; + border-radius: 5px; +} + +.is-current{ + background-color: #004F99; + color: white !important; +} + +@media screen and (max-width:1024px) { + .navbar>.container { + display:block + } + .navbar-brand .navbar-item, + .navbar-tabs .navbar-item { + align-items:center; + display:flex + } + .navbar-link::after { + display:none + } + .navbar-menu { + box-shadow:0 8px 16px rgba(10,10,10,.1); + } + .navbar-menu.is-active { + display:block + } + .navbar.is-fixed-bottom-touch, + .navbar.is-fixed-top-touch { + left:0; + position:fixed; + right:0; + z-index:30 + } + .navbar.is-fixed-bottom-touch { + bottom:0 + } + .navbar.is-fixed-bottom-touch.has-shadow { + box-shadow:0 -2px 3px rgba(10,10,10,.1) + } + .navbar.is-fixed-top-touch { + top:0 + } + .navbar.is-fixed-top .navbar-menu, + .navbar.is-fixed-top-touch .navbar-menu { + -webkit-overflow-scrolling:touch; + max-height:calc(100vh - 3.25rem); + overflow:auto + } + body.has-navbar-fixed-top-touch, + html.has-navbar-fixed-top-touch { + padding-top:3.25rem + } + body.has-navbar-fixed-bottom-touch, + html.has-navbar-fixed-bottom-touch { + padding-bottom:3.25rem + } + + .project-page-header > h1{ + font-size: 28pt; + margin: 0 auto; + } + + .project-page-header > h1 > a { + font-size: inherit !important; + } + + p { + font-size: 18pt; + margin: 0 0 1em 0; + } + + + +} +@media screen and (min-width:1024px) { + /* Navbar */ + .navbar, + .navbar-end, + .navbar-menu, + .navbar-start { + align-items:stretch; + display:flex + } + .navbar { + min-height:3.25rem + } + .navbar.is-spaced { + padding:1rem 2rem + } + .navbar.is-spaced .navbar-end, + .navbar.is-spaced .navbar-start { + align-items:center + } + .navbar.is-spaced .navbar-link, + .navbar.is-spaced a.navbar-item { + border-radius:4px + } + .navbar.is-transparent .navbar-link.is-active, + .navbar.is-transparent .navbar-link:focus, + .navbar.is-transparent .navbar-link:hover, + .navbar.is-transparent a.navbar-item.is-active, + .navbar.is-transparent a.navbar-item:focus, + .navbar.is-transparent a.navbar-item:hover { + background-color:transparent!important + } + .navbar.is-transparent .navbar-item.has-dropdown.is-active .navbar-link, + .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus .navbar-link, + .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:focus-within .navbar-link, + .navbar.is-transparent .navbar-item.has-dropdown.is-hoverable:hover .navbar-link { + background-color:transparent!important + } + .navbar.is-transparent .navbar-dropdown a.navbar-item:focus, + .navbar.is-transparent .navbar-dropdown a.navbar-item:hover { + background-color:#f5f5f5; + color:#0a0a0a + } + .navbar.is-transparent .navbar-dropdown a.navbar-item.is-active { + background-color:#f5f5f5; + color:#485fc7 + } + .navbar-burger { + display:none + } + .navbar-item, + .navbar-link { + align-items:center; + display:flex + } + .navbar-item.has-dropdown { + align-items:stretch + } + .navbar-item.has-dropdown-up .navbar-link::after { + transform:rotate(135deg) translate(.25em,-.25em) + } + .navbar-item.has-dropdown-up .navbar-dropdown { + border-bottom:2px solid #dbdbdb; + border-radius:6px 6px 0 0; + border-top:none; + bottom:100%; + box-shadow:0 -8px 8px rgba(10,10,10,.1); + top:auto + } + .navbar-item.is-active .navbar-dropdown, + .navbar-item.is-hoverable:focus .navbar-dropdown, + .navbar-item.is-hoverable:focus-within .navbar-dropdown, + .navbar-item.is-hoverable:hover .navbar-dropdown { + display:block + } + .navbar-item.is-active .navbar-dropdown.is-boxed, + .navbar-item.is-hoverable:focus .navbar-dropdown.is-boxed, + .navbar-item.is-hoverable:focus-within .navbar-dropdown.is-boxed, + .navbar-item.is-hoverable:hover .navbar-dropdown.is-boxed, + .navbar.is-spaced .navbar-item.is-active .navbar-dropdown, + .navbar.is-spaced .navbar-item.is-hoverable:focus .navbar-dropdown, + .navbar.is-spaced .navbar-item.is-hoverable:focus-within .navbar-dropdown, + .navbar.is-spaced .navbar-item.is-hoverable:hover .navbar-dropdown { + opacity:1; + pointer-events:auto; + transform:translateY(0) + } + .navbar-menu { + flex-grow:1; + flex-shrink:0 + } + .navbar-start { + justify-content:flex-start; + margin-right:auto + } + .navbar-end { + justify-content:flex-end; + margin-left:auto + } + .navbar-dropdown { + background-color:#fff; + border-bottom-left-radius:6px; + border-bottom-right-radius:6px; + border-top:2px solid #dbdbdb; + box-shadow:0 8px 8px rgba(10,10,10,.1); + display:none; + font-size:.875rem; + left:0; + min-width:100%; + position:absolute; + top:100%; + z-index:20 + } + .navbar-dropdown .navbar-item { + padding:.375rem 1rem; + white-space:nowrap + } + .navbar-dropdown a.navbar-item { + padding-right:3rem + } + .navbar-dropdown a.navbar-item:focus, + .navbar-dropdown a.navbar-item:hover { + background-color:#f5f5f5; + color:#0a0a0a + } + .navbar-dropdown a.navbar-item.is-active { + background-color:#f5f5f5; + color:#485fc7 + } + .navbar-dropdown.is-boxed, + .navbar.is-spaced .navbar-dropdown { + border-radius:6px; + border-top:none; + box-shadow:0 8px 8px rgba(10,10,10,.1),0 0 0 1px rgba(10,10,10,.1); + display:block; + opacity:0; + pointer-events:none; + top:calc(100% + (-4px)); + transform:translateY(-5px); + transition-duration:86ms; + transition-property:opacity,transform + } + .navbar-dropdown.is-right { + left:auto; + right:0 + } + .navbar-divider { + display:block + } + .container>.navbar .navbar-brand, + .navbar>.container .navbar-brand { + margin-left:-.75rem + } + .container>.navbar .navbar-menu, + .navbar>.container .navbar-menu { + margin-right:-.75rem + } + .navbar.is-fixed-bottom-desktop, + .navbar.is-fixed-top-desktop { + left:0; + position:fixed; + right:0; + z-index:30 + } + .navbar.is-fixed-bottom-desktop { + bottom:0 + } + .navbar.is-fixed-bottom-desktop.has-shadow { + box-shadow:0 -2px 3px rgba(10,10,10,.1) + } + .navbar.is-fixed-top-desktop { + top:0 + } + body.has-navbar-fixed-top-desktop, + html.has-navbar-fixed-top-desktop { + padding-top:3.25rem + } + body.has-navbar-fixed-bottom-desktop, + html.has-navbar-fixed-bottom-desktop { + padding-bottom:3.25rem + } + body.has-spaced-navbar-fixed-top, + html.has-spaced-navbar-fixed-top { + padding-top:5.25rem + } + body.has-spaced-navbar-fixed-bottom, + html.has-spaced-navbar-fixed-bottom { + padding-bottom:5.25rem + } + .navbar-item.has-dropdown.is-active .navbar-link, + .navbar-item.has-dropdown:focus .navbar-link, + .navbar-item.has-dropdown:hover .navbar-link { + background-color:#fafafa + } +} +@media screen and (max-width:1023px) { + .hero.is-primary .navbar-menu { + background-color:#00d1b2 + } + + .major-icons{ + display: none; + } + + .page-metadata{ + font-size:18pt; + } +} + +.hero.is-primary .navbar-item, +.hero.is-primary .navbar-link { + color:rgba(255,255,255,.7) +} +.hero.is-primary .navbar-link.is-active, +.hero.is-primary .navbar-link:hover, +.hero.is-primary a.navbar-item.is-active, +.hero.is-primary a.navbar-item:hover { + background-color:#00b89c; + color:#fff +} +/* Project Page */ +.project-page-header { + margin: 1em 0 0 0; + text-align: center; +} + +.project-page-header > .title{ + font-weight: bold; + color: black; +} + +.project-page-header > .subtitle{ + color: black; + display: inline; +} + +.project-title-container { + display: inline-flex; +} + +.project-title{ + line-height: 1em; + color: black; +} + +.project-title > .tech{ + color: #333333; +} + + +.project-content > h2{ + color: black; + font-weight: bold; + font-size: 24pt; + margin-top: 1.5em; +} + +.project-content > h3 { + color: black; + font-style: italic; + font-size: 22pt; +} + +.project-content > h2:after{ + background: rgba(144, 144, 144, 0.5); + content: ''; + height: 1px; + margin: 1rem 0 1rem 0; + width: 6em; + padding-left: 1em; + display: flex; +} + +.project-content > p > code{ + background-color: black; + color: greenyellow; + border-radius: 4px; +} + +/* Footer */ +#footer { + padding: 2em 0 1em 0; + color: black; + text-align: center; +} + +#footer ul.major-icons li .icon { + border-color: #ffffff; +} + +#footer .icon.major { + color: #ffffff; +} + +#footer .icons { + margin: 1em; +} + +#footer .fa-lg{ + font-size: 2em !important; + padding: 5px; + margin-bottom: 0; +} + +#footer .copyright { + font-size: 0.8em; + list-style: none; + margin: 2em 0 0 0; + padding: 0; +} + +#footer .copyright li { + border-left: solid 1px; + display: inline-block; + line-height: 1em; + margin-left: 1em; + padding: 0 0 0 1em; +} + +#footer .copyright li:first-child { + border-left: 0; + margin-left: 0; + padding: 0; +} + + +/* XLarge */ + + @media screen and (max-width: 1680px) { + + /* Basic */ + + body, input, select, textarea { + font-size: 14pt; + } + + /* Header */ + + #header { + padding: 6em 0 6em 0 ; + } + + } + +/* Large */ + + @media screen and (max-width: 1140px) { + + /* Basic */ + + body, input, select, textarea { + font-size: 13pt; + } + + h1 br, h2 br, h3 br, h4 br, h5 br, h6 br { + display: none; + } + + /* List */ + + ul.major-icons li { + padding: 2em; + } + + ul.major-icons li .icon { + height: 8em; + line-height: 8em; + width: 8em; + } + + /* Main */ + + .main { + padding: 4em 0 2em 0; + } + + .main.style2 { + background-color: #333; + color: rgba(255, 255, 255, 0.75); + background-attachment: fixed, fixed; + background-size: auto, cover; + } + + /* Header */ + + #header { + padding: 5em 0 5em 0 ; + background-attachment: scroll; + } + + #header br { + display: inline; + } + + /* Footer */ + + #footer { + padding: 4em 0 4em 0 ; + background-attachment: scroll; + + } + + /* Image */ + .image.fit { + width: 75%; + } + + .project_logo{ + width: 25% !important; + } + + .profile { + margin: auto !important; + display: block !important; + } + + } + +/* Medium */ + @media screen and (max-width: 980px) { + + /* List */ + p { + text-align: left; + line-height: 1.5em; + } + ul li{ + font-size: 1.0rem; + line-height: 1.5rem; + } + + ul.major-icons li { + padding: 2em; + } + + ul.major-icons li .icon { + height: 7em; + line-height: 7em; + width: 7em; + } + + /* Main */ + + .main { + padding: 5em 3em 3em 3em ; + } + + /* Header */ + + #header { + padding: 8em 3em 8em 3em ; + } + + /* Footer */ + + #footer { + padding: 5em 3em 10em 3em ; + } + + /* One */ + + #one { + text-align: center; + } + + /* Two */ + + #two { + text-align: center; + } + + /* Profile Image */ + .image.fit { + width: 50%; + } + + /* Project Screenshots */ + .project_screenshot_mobile_right{ + width: 40%; + float: right; + margin: 2em; + } + + .project_screenshot_mobile_left{ + width: 40%; + float: left; + margin: 2em; + } + + #contact-form #name, #email { + width: 100%; + } + + .project_demo_desktop{ + width: 95%; + margin: 0.5em 0.5em 0.5em 0.5em; + } + } + +/* Small */ + + @media screen and (max-width: 736px) { + + /* Basic */ + + body, input, select, textarea { + font-size: 20pt !important; + } + + h1 { + font-size: 1.0em; + } + + h2 { + font-size: 0.9em; + } + + h3 { + font-size: 0.85em; + } + + h4 { + font-size: 0.75em; + } + + p { + line-height: 1.5rem; + font-size: 0.75em; + } + + + /* List */ + + ul li{ + line-height: 1.5rem; + } + + ul.major-icons{ + display: none; + } + + ul.major-icons li { + padding: 1.5em; + } + + ul.major-icons li .icon { + height: 5em; + line-height: 5em; + width: 5em; + } + + ul.major-icons li .icon:before { + font-size: 42px; + } + + /* Icon */ + + .icon.major { + margin: 0 0 1em 0; + } + + /* Button */ + + input[type="submit"], + input[type="reset"], + input[type="button"], + button, + .button { + height: 3em; + line-height: 3em; + } + + /* Main */ + + .main { + padding: 3em 1.5em 1em 1.5em ; + } + + /* Header */ + + #header { + padding: 4em 3em 4em 3em ; + } + + #header .actions { + margin: 2em 0 0 0; + } + + /* Footer */ + + #footer { + padding: 3em 1.5em 3em 1.5em ; + } + + .project-logo{ + width: 10%; + } + #contact-form #name, #email { + width: 100%; + } + #btnsubmit{ + padding-left: 0.5em; + padding-right: 0.5em; + } + + /* Project Screenshots */ + + .project_screenshot_mobile_right{ + width: 80%; + float: right; + margin: 1em; + } + + .project_screenshot_mobile_left{ + width: 80%; + float: left; + margin: 1em; + } + + .project_demo_video_embed{ + width: 95%; + } + + .project_demo_desktop{ + width: 115%; + margin: 0 0 0 0; + } + ul li{ + font-size: 1.0rem; + } + } + +/* XSmall */ + + @media screen and (max-width: 480px) { + + /* Button */ + + input[type="submit"], + input[type="reset"], + input[type="button"], + .button { + padding: 0; + } + + /* Main */ + + .main { + padding: 2em 1.5em 0.1em 1.5em ; + } + + .project-logo{ + display: none; + } + + /* Header */ + + #header { + padding: 4em 2em 4em 2em ; + font-size: 1rem; + } + + #header br { + display: none; + } + + /* Footer */ + + #footer { + padding: 2em 1.5em 2em 1.5em ; + } + + #footer .copyright { + margin: 1.5em 0 0 0; + } + + #footer .copyright li { + border: 0; + display: block; + margin: 1em 0 0 0; + padding: 0; + } + + #footer .copyright li:first-child { + margin-top: 0; + } + + } + +/* XXSmall */ + + @media screen and (max-width: 320px) { + + /* Basic */ + + html, body { + min-width: 320px; + } + + /* Main */ + + .main { + padding: 2em 1em 0.1em 1em ; + } + + /* Header */ + + #header { + padding: 3em 1em 3em 1em ; + } + + /* Footer */ + + #footer { + padding: 2em 1em 2em 1em ; + } + + } diff --git a/projects/axe/index.html b/projects/axe/index.html new file mode 100644 index 0000000..cf4666c --- /dev/null +++ b/projects/axe/index.html @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | WWU Accessibility Engine (ACE) + + + + + + + + + + +
+
+
+
+
+

+ WWU Accessibility Engine (ACE) + + - (Repository Link) + +

+ +

A full-stack accessibility automation tool developed for Wandke Consulting in Bellingham, Washington.

+ +
+
+ + + Published on + + +
+
+
+
+

About ACE

+

This is my capstone project during my senior year at Western Washington University. I led a team of 4 in the development of an accessibility testing program for Daman Wandke of Wandke Consulting, an accessibility consulting company +in Bellingham, WA. My team and I spent a year working on a full-stack application to streamline their website accessibility evaluation process. Initially, they used Deque Labs' aXe browser extension to determine whether a given webpage conforms to the World Wide Web Consortium's +Web Content Accessibility Guidelines (WCAG). From there, they manually entered the data from the accessibility scan into a CSV file, added some comments such as information about the specific WCAG violation, how to remedy that specific violation, and any other relevant notes. In addition +to aXe, it was requested that we also integrate Crest by VMware -- another accessibility testing engine. This is another python-based engine, so the project may need to be refactored to include some sort of python server to run both the spider and Crest.

+

Demonstration

+ +Youtube Video Preview of the WWU ACE project video + +

Technologies Used

+

This project uses Sails.js as the backend server, Vue.js as the frontend application, Selenium Webdriver to manipulate installed browsers, and Python to gather sub-pages of the inputted website to use as input on an accessibility scan. Initially the requirements included +two applications, one to run the accessibility scan and one to edit the results of the scan prior to exporting it to a CSV or PDF file. After analyzing the requirements, our client decided that simply retuning the results in a CSV format -- removing the need for a second +application.

+

The backend server is able to run independently of the frontend, and vice versa. To stress test the backend, I wrote 15 bash shell scripts to send POST requests containing different configurations. These configurations included +different lists of websites, different WCAG conformance levels, browser resolutions, and whether to spider a website for a given URL. At the moment it only supports Firefox and Chrome; we considered adding MS Edge to the list of testable +browsers, but ultimately we decided against it as both Chrome and Edge are chromium-based so the results would be the same for both browsers.

+

Integrating the spider was by far the most challenging aspect of this project. It would have been easier to simply use a Javascript web scraper, but there are more robust Python libraries that had the functionality I was looking for. +There are some Javascript libraries for running Python scripts, but our use case is unique enough to where I had to dig deep into forums and documentation to figure out how to make the python script is callable via POST request.

+

Thoughts

+

This was an interesting project. This was the first time I've considered the accessibility of my projects and the web in general. Both in passing and in a digital accessibility class, I learned about a case against Dominoes Pizza +where a man filed a lawsuit because their website didn't conform to WCAG AA guidelines. It even went all the way up to the Supreme Court. I always assumed (incorrectly so) that big companies such as Dominoes ensured that people of all abilities could use their website and applications.

+

This was the first time I took on a long-term project for an actual client and not a professor. I learned a lot about maintaining a professional relationship with someone outside my school, communicating with them on a regular basis to give updates on the status of projects, and leading a team. +We decided to use a Kanban methodology for developing this project because the vast majority of features that were requested were backend-heavy, so doing scrum-style sprints wouldn't have been the best fit. Once the core features were connected and functional, +we arranged a meeting with our client or sent an email with example output. Often times the email would be the more effective means of communication, as it gave them time to evaluate and think about what's been done so far and if any new features should be added.

+

Most of the time features came to fruition through trial and error. Integrating the Spider functionality for example took a significant amount of time researching and testing to implement. The biggest issue that I ran into was determining how to run the spider on both Unix and Windows operating systems. +I falsely assumed that if I created a virtual environment folder for just a *nix system it would work for any system. After one of my teammates attempted to run it on their Windows computer, errors popped up. I had to spin up a Windows 10 virtual machine to install and test our project, and I found that:

+
    +
  1. For some reason Windows 10 is missing a few features which prevents python from installing Scrapy -- the library we used to scrape for subpages of a website.
  2. +
  3. Python on Windows 10 has a different virtual environment structure, so checks needed to be added to ensure that the right environment was used whenever the spider is run.
  4. +
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/deadwood/index.html b/projects/deadwood/index.html new file mode 100644 index 0000000..69e9c6a --- /dev/null +++ b/projects/deadwood/index.html @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Deadwood + + + + + + + + + + +
+
+
+
+
+

+ Deadwood + + - (Repository Link) + +

+ +

A MVC board game developed in an Object-Oriented Programming class.

+ +
+
+ + + Published on + + +
+
+
+
+

About Deadwood

+

Deadwood is a free board game by Cheapass Games. This was a project for my OOP class, done in +Java and Swing. This was the first large-scale project I've done, and I decided to do it on my own despite it being a group project.

+

In Deadwood, each player is an "actor" trying to make a living. Each actor moves from set to set, taking on a role, and attempts to complete the scene to make money. The +player with the most money at the end of the game is the winner.

+

The Game

+

Game Components

+
    +
  • Players: The game supports between 2-8 players.
  • +
  • Boards: There are 4 panels that make up the board. Each panel contains sets for the player to work on, provided their rank is greater than or equal to the role's. Each set contains a section +for a card to be placed, as well as a spot for a user to take a role as an "extra". If a user takes a role, they get a payout on successfully completing the scene regardless whether they take a role as a main +character or as an extra.
  • +
  • Cards: Cards contain a scene, roles, and a budget.
  • +
  • Dice: The dice on the board represent the player game pieces. The side of the dice represents the player's rank, and whether a roll is a success or failure.
  • +
  • Money: Currency, used to upgrade user ranks.
  • +
  • Credits: An alternative form of currency, also used to upgrade user ranks.
  • +
  • Counters: Shot counters. These are values that track how many times an actor has to successfully act before the scene wraps.
  • +
+

Movement

+
    +
  • Players who aren't currently working can move from set to set.
  • +
  • If a player is working a role, whether it's a main role or an extra role, they can only act or rehearse. They're stuck until the role has completed.
  • +
  • A user can upgrade their rank at the casting office using either credits or money.
  • +
+

Working a Role

+

A player earns money and credits by working roles. The game die determines whether the shot succeeds or fails. A successful shot is when the die rolls a value greater than or equal to the budget. Otherwise, it's a failure. +When a player is working a card, on success the player removes a shot counter and earns two credits. On failure, they earn nothing. If a player is working off the card, on success they earn one credit and one dollar. On failure, +they earn one dollar. Each card has one to three shots which must be completed before the user moves on to another set.

+

Wrapping a Scene

+

When the last scene has finished, the scene wraps and the card is removed from the board. For players working a main role, the players role dice equal to the budget of the movie (e.g. 4 dice for a $4 million budget) and the bonuses are distributed +to players from the highest rank role to lowest.

+

Day's End

+

The day is considered "over" when there is one scene left on the board. All players are moved back to the start ("trailers"), the board gets wiped and new scenes are placed on the board. This repeats until all the days are over.

+

The formal rulebook can be seen on the Cheapass Games Website.

+

Technologies Used

+

I had some prior experience with Swing for a side project, but it wasn't as complex or detailed compared to Deadwood. +On top of game logic, I needed to design a GUI -- which is a project on its own. In the last Swing project I worked on, +I remember spending a lot of time organizing elements. Given the scale of Deadwood and the number of elements that needed +to be created, I was initially intimidated by the task. Thankfully, Intellj IDEA had a nifty +Swing designer tool which sped up development. Using this tool, I was able to effectively drag and drop elements (buttons, tables, etc.) +without having to go too heavily into editing the Swing code.

+

A screenshot of the Deadwood game on Desktop. On the left is the game board with each set, the top lists the current player, current day, and how many days the game has total. To the right of the board
+are 5 buttons: one for moving the player, working, taking a role, upgrading, and ending the current player's turn. Beneath those buttons is a table listing the player data. The first
+player named 'Michael' is rank 1, has 400 dollars, 0 credits, and 0 rehearsal chips. The second player, 'Taco', is rank 1, has 0 dollars, 0 credits, and 0 rehearsal chips.

+

I was familiar with Java enough at the time to where this wasn't an overly challenging project compared to creating a TCP chat client in C, +for example, but there were so many moving parts and rules to test to where the project was more time-consuming than anything.

+

What made the most sense to me for this project was to use a composition software development design pattern. The way I looked at it, +the board has anywhere from 2-3 sets per quadrant, and 2-8 players per game. Each set has a place for a card and extras. In each card, there are 1-3 roles that a player +can take. I used a singleton design pattern for the board, and created attributes and fields in each class to contain players and cards. In order +to help with the game logic, I created ENUM values which denoted what state the player was currently in (e.g. working, rehearsing, just completed, etc.)

+

A screenshot of a 2 player Deadwood game. The player 'Michael' is on Main Street working as an extra, and player 'Taco' is selecting a role on a card. To the right of the board the user has the 'Take Role' button selected,
+and the application is listing off all the available roles on the set, both on and off the card and their ranks.

+

The static data for this game is contained in two XML files. The board XML files contain information such as neighboring sets, locations, the number of takes, extra roles and associated role information, +and lastly where all of these elements are located on the board (x/y/h/w). The card XMl files list the name of each card, associated images, the scene numbers and descriptions, roles, and their respective locations on the card.

+

Thoughts

+

The first iteration of this project was a command line version. This command line version was by far the jankiest one I've worked on to date. I didn't have that firm of a grasp as to what needed to be done, or the rules for that matter, so +it barely worked. The second iteration required the use of a Swing GUI. It was at this point that I realized that this application was largely state driven. Given that a user is doing x, they can only do y or z for example. Once I +had that logic worked out, effectively rewriting my entire project, the remaining tasks were simple but tedious and repetitive. It reminded me of modifying HTML/CSS on a static webpage -- making small tweaks here and there which either worked or didn't.

+

Once I had all the Swing elements created, testing and fixing bugs took up the rest of my time. Due to the chronological nature of the game, I had to play the game at least a hundred times to test out specific features. For example +the end-of-game bonus, upgrading ranks, actions before/during/after completing a scene, and resetting the board after all the cards had been completed. To speed up testing of particular features, I created a test file with prepopulated +data (name, player die color, amount of credits/money, rank) to test out features that I would have otherwise had to play for a long time to test.

+

There are a few things that I could have done to streamline the code and the overall experience:

+
    +
  • I thought that it would be more efficient to place user objects in the scene objects; when the scene completes, all I would have to do is access the list of users on the particular set +to assign bonuses.
  • +
  • I didn't really adhere to any traditional design patterns for this project. I was focused on the mentality that each object contains objects themselves to where I wasn't really able to +find ways to use the design patterns learned in class.
  • +
  • Not working this project solo. This project was sizable, and working on it alone was a challenge. I had good reason for working on this alone, and I still think that my decision to work alone +was justified, but I most likely wouldn't have had to spend as long on it if I worked with another person.
  • +
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/django-react-chat-application/index.html b/projects/django-react-chat-application/index.html new file mode 100644 index 0000000..598923a --- /dev/null +++ b/projects/django-react-chat-application/index.html @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Django+React Chat Application + + + + + + + + + + +
+
+
+
+
+

+ Django+React Chat Application + + - (Repository Link) + +

+ +

A Full-Stack chat application utilizing Django, ReactJS, and websockets.

+ +
+
+ + + Published on + + +
+
+
+
+

About the Application

+

This project was given to me as a part of a project-based interview through a third-party hiring company. This was one of the first "interviews" I participated in, and gave me some enlightening +experiences and insights into what I needed to improve upon as a developer. I was added to a Slack channel with a number of other developers who would be helping me through the interview. +I was assigned 3 tasks that I was expected to accomplish within ~2 weeks or so. I've interacted with Django before, but React was totally new to me. The tasks were: Fix the application +such that two clients can send messages to each other, Add a "read receipt" feature, and redesign the database to allow for 3...n users to share a conversation (i.e. have a group conversation).

+

Issue No. 1 -- Message No Go

+

These issues were spread out between both the backend and the frontend applications. When a user sent a message to another user, the messages weren't showing up in the receiving user, and when the user +refreshed the page the messages appeared -- but they weren't in descending order. After doing some poking around, I found that the messages were populating the backend database, and were successfully being sent to +the receiver, but they weren't appearing in the receiver's conversation. I concluded that the messages weren't appearing due to React's state hook not updating. The backend fix was much easier than the frontend fix; +I just had to flip some variables around.

+

Issue No. 2 -- "I read that..."

+

This feature was a bit harder to implement. I've used chatting applications with read receipts for a large chunk of my life, but I had no real idea how to go about implementing it. I looked at a few existing +platforms, like Facebook Messenger and Signal. With Facebook Messenger, the read receipt is the other user(s) profile pictures. With Signal, the read receipt has 3 steps: Sent, Delivered, and Read. This would +require the server to send 3 total signals to a client: one that the server has received the message, that the server has successfully delivered the message, and that the receiving client has read the message.

+

Both applications more or less behaved the same, server differences aside. Whenever a client clicked on a conversation with unread messages, the messages were updated to reflect that the message(s) were read. +I opted to model this feature after Facebook Messenger's behavior to reduce the amount of work on my part. Then came the hard part.

+

The database was designed such that a conversation can only exist between two users. There could only be one unique combination of two users that make up a conversation. Each message sent belonged to a conversation. +I initially thought that the easiest way to implement this was associate the users userId to a particular message, denoting that user has read the most recent unread messages in the conversation. After some thought, +I realized that I could actually accomplish this by instead representing the read receipt as a boolean in the database and use client-side logic to display the correct read receipt. If the most recent message +is from the other user, it's assumed that they've read the conversation up until that point. If the message is from the current user and the message is marked as unread, then the other user hasn't read the conversation. +If it's marked as read, then the read receipt should be moved to the most recent message.

+

All Aboard the Struggle Bus

+

The two major issues I faced with this step was that I hadn't ever messed with Websockets, and that I didn't really understand what it meant to "deep copy" a conversation. +I was given the hint to modify the websocket, but it didn't really click what that meant. I was so hooked (so to speak) on the frontend application, that I didn't think to check the backend for an actual websocket application. That was the biggest +blocker for this ticket -- I wasn't able to make any meaningful progress because I was unable to test the application.

+

Issue No. 3 -- Redesign Everything

+

This last issue was to redesign the database such that it allowed for group conversations. A group consisted of 2...n users. This meant that the read receipt notification would need to be updated such that each +user would have their own read receipt in a conversation. My line of thinking was (and still is) that I could modify the database such that it could allow for 3...n users without having separate tables for conversations +between only 2 users. Each conversation would be held between a "group" of users. This "group" could be 2...n users. Each "group" would have a conversation, and each conversation would have 1...n messages. Having this concept +of group membership would also allow for group permissions, like the ability to add/remove users from the conversation for example.

+

Thoughts

+

All in all this was an interesting experience. This was the first time I've worked on a larger project in a more professional context. While it did show me my strengths and weaknesses, I can't help but +feel a bit disappointed by this experience. There were at times some issues with communication between myself and the reviewers. When I tried to ask follow-up questions to clarify any concepts that didn't make sense, +they often went unanswered. My implementation for Issue No. 2 took me a bit more time than I anticipated due to completely skipping over the websocket folder in the backend server. I opted to continue working on the project +because I was led to believe that the company I was applying for had a hiring freeze in place, and I could continue working on the application without penalty. After I completed the project, I heard nothing back +about whether I was still being considered as a candidate.

+

One piece of feedback that I was a little shocked by was that I didn't communicate often enough. Looking back through the messages I sent, I realized that there was some truth to this. I have a habit of getting engrossed +in projects, and I believe that's what resulted in my less-than-stellar communication. In my past jobs I was used to having either remote or face-to-face meetings. Communicating solely over messages +was very easy to forget. It was hard to accept that I could have done better, but this was most definitely a reality check for me. I knew that I was going to be constantly learning +when I started working, but communication wasn't something that I thought I needed to improve upon.

+

In retrospect, while I did learn a great deal about React, Django, and REST API's, I can't help but feel like my time could have been better spent brushing up on +Computer Science fundamentals in preparation for interviews.

+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/index.html b/projects/index.html new file mode 100644 index 0000000..7b6d2c9 --- /dev/null +++ b/projects/index.html @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | My Projects + + + + + + + + + + +
+
+
+

My Projects

+

While I have worked on a number of projects during my schooling, these are the ones that I am the most proud of.

+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/page/1/index.html b/projects/page/1/index.html new file mode 100644 index 0000000..bce99f3 --- /dev/null +++ b/projects/page/1/index.html @@ -0,0 +1,6 @@ + + + + +Redirect +

Click here to be redirected.

diff --git a/projects/recaptcha/index.html b/projects/recaptcha/index.html new file mode 100644 index 0000000..de1329b --- /dev/null +++ b/projects/recaptcha/index.html @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | reCAPTCHA Validator + + + + + + + + + + +
+
+
+
+
+

+ reCAPTCHA Validator + +

+ +

A small FastAPI server to validate the responses from a reCAPTCHA challenge.

+ +
+
+ + + Published on + + +
+
+
+
+

About ReCaptcha

+

According to Google:

+
+

reCAPTCHA uses an advanced risk analysis engine and adaptive challenges to keep malicious software from engaging in abusive activities on your website. Meanwhile, legitimate users will be able to login, make purchases, view pages, or create accounts and fake users will be blocked.

+
+

I wanted to integrate reCAPTCHA into my website, specifically in the "Contact" form. Once it was successfully tested and added to the contact form, Google informed +me that I wasn't validating the responses and linked the relevant documentation page. When wracking my brain for +possibilities, I remembered that FastAPI existed. I could have used Node for example, +but I don't need anything super-big that has a lot of requirements, configurations, yada yada yada. FastAPI fit the bill perfectly. I just wanted something lightweight to send POST requests to the Google API endpoint that didn't expose my reCAPTCHA secret key client side.

+

Technologies Used

+

Simply put, I used a FastAPI server, a javascript function located in my personal website's contact form, and an Azure application to host it. I initially opted to use Heroku as I already had an account, +but I thought that I'd use the Azure student credits I had accrued. Migrating my code from Heroku to Azure was painless, and I learned a bit about how to navigate the Azure dashboard. After some light testing, I found out that after +20 minutes the validation server powers down -- a policy set by Azure for free applications. Going with a paid plan would mean that I wouldn't have to deal with that policy, however there were a few downsides. The biggest issue is that I don't have a regular source of income. +This application isn't doing anything incredibly expensive computationally, so it ultimately may be much cheaper to run than I initially thought. That said, I'd rather not have to spend money to find out that my application requires a lot of computing time. Secondly, the memory requirements +for this application are pretty low to begin with. It can easily do its job on the free tier plan, and frankly hasn't even made a dent in the daily quota.

+

And that brings me to the issue of the application powering down. After a bit of thought, I realized that it's shutting down due to inactivity after 20 minutes. In order to prevent inactivity, I needed to find a way to keep it awake. If my print server VM had enough space (it's running +on a little rinkydink Surface 3) I could easily just set up a CRON job that sends a GET request to the reCAPTCHA validator to make sure it's still alive. After a bit of googling, I discovered cron-job.org. +It's a service that essentially acts is as if I created a CRON job on a local computer and let it do its thing. While it works, I was curious whether I could replicate the behavior in an Azure application.

+

Turns out I could! I created a Function Application which runs a python script on an interval. I set the interval to run every 15 minutes, however I think I may change it to 18 minutes to minimize the number of requests made. +While there were a few road bumps like not having the .ssl-key.log file added as an environment variable to my .zshrc file for some bizarre reason, the fix was relatively quick and easy to implement. I'll be monitoring both applications to see how this fix affects the free tier's daily quota.

+

Thoughts

+

FastAPI

+

I hate CORS. While I'm sure there's a very sound and logical reason to have it, the errors I usually get with CORS don't really explain how to fix my issue.

+

This project (along with the CRON project) took me less than 24 hours to throw together in total. Someone in a local Discord server mentioned that they were experimenting with FastAPI, and given the scale +and impact of my needs I thought it would be a fun, quick project to throw together.

+

Azure

+

Azure's documentation needs a bit of work. I was initially hoping to make an application with a few different endpoints for testing purposes, but as it turns out Azure function applications don't support that behavior. This reminds me of some issues I was having with +Windows' Assigned Access. While I was working in the Viking Union, I was tasked with creating a kiosk device. I wanted to use Assigned Access to achieve this, but I also required +the use of a specific browser extension. As it turns out, Assigned Access doesn't support browser extensions and this information was buried in the Microsoft documentation.

+

The documentation on creating Azure applications is unnecessarily spread out and at times cryptic.

+

Had I stayed with Heroku I probably would have the same issue where free-tier application goes to sleep after a set amount of time. Odds are I would have come up with a CRON-like solution to keep it running. That said, Heroku's dashboard is significantly friendlier compared to Azure. Many +of the settings are pretty self-explanatory whereas compared to Azure -- for example, an App Service has a few tabs which allude to the same function such as "Activity Log", "Logs", "App Service logs", "Log Stream". End of the day I really just switched to Azure because odds are I'd be working +with it in a professional environment. Heroku, Azure, Digital Ocean, they'll all get the job done.

+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/releave/index.html b/projects/releave/index.html new file mode 100644 index 0000000..ee89a3a --- /dev/null +++ b/projects/releave/index.html @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | ReLeave + + + + + + + + + + +
+
+
+
+
+

+ ReLeave + + - (Repository Link) + +

+ +

A cross-platform mobile application designed to aid a person going through Cannabis abuse recovery.

+ +
+
+ + + Published on + + +
+
+
+
+

About ReLeave

+

I came up with this project over the summer of 2020. I had discovered the /r/Leaves subreddit, and it occurred to me that there may +not be many applications out there specifically for cannabis abuse. Most applications I came across were a one-size-fits-all type application that +attempts to work for anyone, applications for alcoholics, people who are dependent on opioids, but not many applications for cannabis dependency.

+

Society is champing at the bit for cannabis legalization in the US. Often times people talk about the wonders that the plant can have on a person's body, how it +can help people undergoing chemotherapy, treat depression, anxiety, etc. however people don't often talk about cannabis dependency and the effects it can have on a person.

+

I had fully intended to create this application on my own, but I saw an opportunity to create this in a class called "Technology for Social Good". We were asked +to come up with a project idea and pitch it to the class. I made my pitch, and a few other students also thought that this would be a great project to work on. I decided to do this project in Flutter because technology is always a limiting factor for people. Some peopne can't afford the newest iPhone or the highest-spec +Android device, so it had to be friendly with most newer OS versions and not be resource-heavy. As a perk, this language is very friendly toward new users and is well documented.

+The picture contains a checkbox with the caption 'Did you refrain from using cannabis today?' with a box below that for the user to tick, and 7 sliders corresponding to feelings such as happiness, sadness, craving, for the user to rate their feelings at that given time. +

This application has the following features:

+
    +
  • Mood/Craving tracking.
  • +
  • Journaling system.
  • +
  • Custom goal creation.
  • +
  • Tracking features.
  • +
  • A badge system that awards the user whenever they reach a milestone (e.g. staying x days sober, saving x dollars by refraining from consuming cannabis products, etc.)
  • +
  • Interacting with a community of people who are also attemtping to maintain sobriety.
  • +
+

While this is purely anecdotal, many of the posts I've seen on /r/Leaves involve a lot of self reflection. People talk about behaviors they developed as a result of their dependency, how they treated others, missed opportunities, and how they felt that day after being sober for an extended period +of time. To aid with that reflection, we decided to implement a Mood/Craving tracker system which allows them to reflect back on their day. They will have the +option to rate how they're feeling on a scale from 1-10, and create a journal entry for any thoughts or feelings they have that a simple rating can't describe.

+

Also included are a few tracking features: the first is a sobriety tracker, measuring the number of days since the user started their journey; the second +is a money tracker. When the application is installed for the first time, the user would be asked how much money they spent on cannabis products, how much they +consume, and the method of consumption. The money tracker will calculate how much they've saved based on that inputted information, as well as how much they've +refrained from consuming.

+

The badge system is an attempt to "gamify" the application -- to make the user want to maintain their sobriety, not dissimilar to the coins used by Alcoholics +Anonymous but in this case digital and more than just maintaining sobriety for a set amount of time.

+

There are a lot of habit tracking applications out there that could be used to help with a person recover from substance abuse. However, many applications are missing a key feature: a community. It's not uncommon for support groups to hold meetings so members can share experiences, support others, and to not feel alone during +recovery. Many existing applications have a self-hosted platform for users to interact, but a downside of that especially for a new application such as ReLeave is +getting enough users on the platform in the first place. Instead of building out a platform for users to interact, I had the idea to instead leverage Reddit's /r/Leaves community.

+

Technologies Used

+A screenshot of the Reddit feature, listing off posts from users of the /r/Leaves subreddit. +

Flutter was chosen because, as mentioned before, it's a framework that can transpile code into code that can be run on both iOS and Android devices, +allowing people with any device to use it. Reddit is already designed for users to communicate, has a free API that I could leverage, and I wouldn't have to manage +another system and deal with user account issues. To achieve this, we used the dart package Draw or Dart Reddit API Wrapper to +interact with the subreddit. Data is stored in a local SQlite database, using a custom schema.

+

The journaling feature can either save the data to local memory or to post to the /r/Leaves subreddit, provided they already have +an account.

+

Thoughts

+

This was my first project where I felt satisfied at the completion of the course. Flutter made this application very easy to throw together, and working with +a team that was motivated and had a vested interest in this project made this an incredibly enjoyable experience. Technology wise, the features are in place +however they're not the prettiest and the database is quite frankly a mess. I designed the database, but looking back I really didn't know what I was doing. +I plan on reviving this project and pushing forward with it now that I have the time, the application is in dire need of a facelift and some stylistic +standardization, as well as a complete database overhaul.

+

This application was my first mobile application that I've ever worked on, and I plan on seeing it to the end and get it published to both iOS and Android app stores.

+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/uml-class-editor/index.html b/projects/uml-class-editor/index.html new file mode 100644 index 0000000..f7c7b4b --- /dev/null +++ b/projects/uml-class-editor/index.html @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | UML Class Editor + + + + + + + + + + +
+
+
+
+
+

+ UML Class Editor + + - (Repository Link) + +

+ +

An Android application for creating UML diagrams.

+ +
+
+ + + Published on + + +
+
+
+
+

About UML Class Editor

+

I came across this project while browsing FOSSdroid. After I took an OOP class, I realized +the importance of planning out a project before coding it up. In a project with lots of moving parts, I found that it +was helpful to draw out classes, their attributes, public/private methods, how they should interact, and to use that +as a "to do" list of sorts. Nothing beats pen and paper, but I had recently purchased a Samsung tablet that came with a stylus, and +I wanted to take advantage of that. I found websites like Draw.io incredibly useful, but it wasn't compatible +with tablet devices. I really like the tactile experience of interacting with an application or website, so finding +something similar to Draw.io for an Android tablet was a challenge. I found that the application suited my purposes perfectly, +however I had a few issues with it. First and foremost, the application toolbar/menu bar color irritated me. It initially +was a bright purple, which was a bit of an eyesore. Functionality wise, the menu organization wasn't the most intuitive, it had no +icons, and there were some bugs related to saving data.

+

I had experience working on 2 mobile applications, so tracking down the bugs was fairly easy. All I had to do was set a breakpoint +and replicate the actions that caused the application to crash.

+

Thoughts

+

This was a great application, but I had some issues with the way it was initially coded. Firstly, the author didn't wrap file/data operations +in try(){...}catch(){} blocks, which is why the application was crashing initially. I was trying to run a delete operation when I had no saved projects +which threw a NullPointerException(), causing the application to crash. That was an easy fix. The next issue I came across was that the application +used a deprecated API for loading/exporting data, onActivityResult(). +This wasn't causing the crash, but it was something that needed to be addressed. This took a bit more time to figure out as I didn't fully understand what it did, and how to implement the correct API, +registerForActivityResult().

+

Roadmap

+

I have a few ideas for how to make this application better, at least for my purposes.

+
    +
  • Color customization. I like to be able to choose the theme of the applications I use, like in Slide for Reddit for example +and I'd love to add that functionality to this application.
  • +
  • Exporting to different file types. Currently the data exports to .html files, which isn't the most practical when it comes to sharing files with others. I intend to create options to +export the diagrams to PDF and possibly JPG/PNG formats.
  • +
  • Cloud Storage integration. A lot of applications like this have the ability to sign in with a cloud storage account such as Google Drive, One Drive, Dropbox, etc. and I want to add that functionality +to this application as well.
  • +
  • Sharing diagrams as PDF/JPG/PNG to either email or some sort of messaging platform. Software development is a highly collaborative profession, +and adding this feature will make this more functional.
  • +
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/resume/index.html b/resume/index.html new file mode 100644 index 0000000..183eb76 --- /dev/null +++ b/resume/index.html @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Resume + + + + + + + + + + + + + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..27d6434 --- /dev/null +++ b/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Sitemap: https://www.michaelkennedy.dev//sitemap.xml \ No newline at end of file diff --git a/sass/libs/_breakpoints.scss b/sass/libs/_breakpoints.scss new file mode 100644 index 0000000..c5301d8 --- /dev/null +++ b/sass/libs/_breakpoints.scss @@ -0,0 +1,223 @@ +// breakpoints.scss v1.0 | @ajlkn | MIT licensed */ + +// Vars. + + /// Breakpoints. + /// @var {list} + $breakpoints: () !global; + +// Mixins. + + /// Sets breakpoints. + /// @param {map} $x Breakpoints. + @mixin breakpoints($x: ()) { + $breakpoints: $x !global; + } + + /// Wraps @content in a @media block targeting a specific orientation. + /// @param {string} $orientation Orientation. + @mixin orientation($orientation) { + @media screen and (orientation: #{$orientation}) { + @content; + } + } + + /// Wraps @content in a @media block using a given query. + /// @param {string} $query Query. + @mixin breakpoint($query: null) { + + $breakpoint: null; + $op: null; + $media: null; + + // Determine operator, breakpoint. + + // Greater than or equal. + @if (str-slice($query, 0, 2) == '>=') { + + $op: 'gte'; + $breakpoint: str-slice($query, 3); + + } + + // Less than or equal. + @elseif (str-slice($query, 0, 2) == '<=') { + + $op: 'lte'; + $breakpoint: str-slice($query, 3); + + } + + // Greater than. + @elseif (str-slice($query, 0, 1) == '>') { + + $op: 'gt'; + $breakpoint: str-slice($query, 2); + + } + + // Less than. + @elseif (str-slice($query, 0, 1) == '<') { + + $op: 'lt'; + $breakpoint: str-slice($query, 2); + + } + + // Not. + @elseif (str-slice($query, 0, 1) == '!') { + + $op: 'not'; + $breakpoint: str-slice($query, 2); + + } + + // Equal. + @else { + + $op: 'eq'; + $breakpoint: $query; + + } + + // Build media. + @if ($breakpoint and map-has-key($breakpoints, $breakpoint)) { + + $a: map-get($breakpoints, $breakpoint); + + // Range. + @if (type-of($a) == 'list') { + + $x: nth($a, 1); + $y: nth($a, 2); + + // Max only. + @if ($x == null) { + + // Greater than or equal (>= 0 / anything) + @if ($op == 'gte') { + $media: 'screen'; + } + + // Less than or equal (<= y) + @elseif ($op == 'lte') { + $media: 'screen and (max-width: ' + $y + ')'; + } + + // Greater than (> y) + @elseif ($op == 'gt') { + $media: 'screen and (min-width: ' + ($y + 1) + ')'; + } + + // Less than (< 0 / invalid) + @elseif ($op == 'lt') { + $media: 'screen and (max-width: -1px)'; + } + + // Not (> y) + @elseif ($op == 'not') { + $media: 'screen and (min-width: ' + ($y + 1) + ')'; + } + + // Equal (<= y) + @else { + $media: 'screen and (max-width: ' + $y + ')'; + } + + } + + // Min only. + @else if ($y == null) { + + // Greater than or equal (>= x) + @if ($op == 'gte') { + $media: 'screen and (min-width: ' + $x + ')'; + } + + // Less than or equal (<= inf / anything) + @elseif ($op == 'lte') { + $media: 'screen'; + } + + // Greater than (> inf / invalid) + @elseif ($op == 'gt') { + $media: 'screen and (max-width: -1px)'; + } + + // Less than (< x) + @elseif ($op == 'lt') { + $media: 'screen and (max-width: ' + ($x - 1) + ')'; + } + + // Not (< x) + @elseif ($op == 'not') { + $media: 'screen and (max-width: ' + ($x - 1) + ')'; + } + + // Equal (>= x) + @else { + $media: 'screen and (min-width: ' + $x + ')'; + } + + } + + // Min and max. + @else { + + // Greater than or equal (>= x) + @if ($op == 'gte') { + $media: 'screen and (min-width: ' + $x + ')'; + } + + // Less than or equal (<= y) + @elseif ($op == 'lte') { + $media: 'screen and (max-width: ' + $y + ')'; + } + + // Greater than (> y) + @elseif ($op == 'gt') { + $media: 'screen and (min-width: ' + ($y + 1) + ')'; + } + + // Less than (< x) + @elseif ($op == 'lt') { + $media: 'screen and (max-width: ' + ($x - 1) + ')'; + } + + // Not (< x and > y) + @elseif ($op == 'not') { + $media: 'screen and (max-width: ' + ($x - 1) + '), screen and (min-width: ' + ($y + 1) + ')'; + } + + // Equal (>= x and <= y) + @else { + $media: 'screen and (min-width: ' + $x + ') and (max-width: ' + $y + ')'; + } + + } + + } + + // String. + @else { + + // Missing a media type? Prefix with "screen". + @if (str-slice($a, 0, 1) == '(') { + $media: 'screen and ' + $a; + } + + // Otherwise, use as-is. + @else { + $media: $a; + } + + } + + } + + // Output. + @media #{$media} { + @content; + } + + } \ No newline at end of file diff --git a/sass/libs/_functions.scss b/sass/libs/_functions.scss new file mode 100644 index 0000000..f563aab --- /dev/null +++ b/sass/libs/_functions.scss @@ -0,0 +1,90 @@ +/// Removes a specific item from a list. +/// @author Hugo Giraudel +/// @param {list} $list List. +/// @param {integer} $index Index. +/// @return {list} Updated list. +@function remove-nth($list, $index) { + + $result: null; + + @if type-of($index) != number { + @warn "$index: #{quote($index)} is not a number for `remove-nth`."; + } + @else if $index == 0 { + @warn "List index 0 must be a non-zero integer for `remove-nth`."; + } + @else if abs($index) > length($list) { + @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; + } + @else { + + $result: (); + $index: if($index < 0, length($list) + $index + 1, $index); + + @for $i from 1 through length($list) { + + @if $i != $index { + $result: append($result, nth($list, $i)); + } + + } + + } + + @return $result; + +} + +/// Gets a value from a map. +/// @author Hugo Giraudel +/// @param {map} $map Map. +/// @param {string} $keys Key(s). +/// @return {string} Value. +@function val($map, $keys...) { + + @if nth($keys, 1) == null { + $keys: remove-nth($keys, 1); + } + + @each $key in $keys { + $map: map-get($map, $key); + } + + @return $map; + +} + +/// Gets a duration value. +/// @param {string} $keys Key(s). +/// @return {string} Value. +@function _duration($keys...) { + @return val($duration, $keys...); +} + +/// Gets a font value. +/// @param {string} $keys Key(s). +/// @return {string} Value. +@function _font($keys...) { + @return val($font, $keys...); +} + +/// Gets a misc value. +/// @param {string} $keys Key(s). +/// @return {string} Value. +@function _misc($keys...) { + @return val($misc, $keys...); +} + +/// Gets a palette value. +/// @param {string} $keys Key(s). +/// @return {string} Value. +@function _palette($keys...) { + @return val($palette, $keys...); +} + +/// Gets a size value. +/// @param {string} $keys Key(s). +/// @return {string} Value. +@function _size($keys...) { + @return val($size, $keys...); +} \ No newline at end of file diff --git a/sass/libs/_html-grid.scss b/sass/libs/_html-grid.scss new file mode 100644 index 0000000..7438a8c --- /dev/null +++ b/sass/libs/_html-grid.scss @@ -0,0 +1,149 @@ +// html-grid.scss v1.0 | @ajlkn | MIT licensed */ + +// Mixins. + + /// Initializes the current element as an HTML grid. + /// @param {mixed} $gutters Gutters (either a single number to set both column/row gutters, or a list to set them individually). + /// @param {mixed} $suffix Column class suffix (optional; either a single suffix or a list). + @mixin html-grid($gutters: 1.5em, $suffix: '') { + + // Initialize. + $cols: 12; + $multipliers: 0, 0.25, 0.5, 1, 1.50, 2.00; + $unit: 100% / $cols; + + // Suffixes. + $suffixes: null; + + @if (type-of($suffix) == 'list') { + $suffixes: $suffix; + } + @else { + $suffixes: ($suffix); + } + + // Gutters. + $guttersCols: null; + $guttersRows: null; + + @if (type-of($gutters) == 'list') { + + $guttersCols: nth($gutters, 1); + $guttersRows: nth($gutters, 2); + + } + @else { + + $guttersCols: $gutters; + $guttersRows: 0; + + } + + // Row. + display: flex; + flex-wrap: wrap; + box-sizing: border-box; + align-items: stretch; + + // Columns. + > * { + box-sizing: border-box; + } + + // Gutters. + &.gtr-uniform { + > * { + > :last-child { + margin-bottom: 0; + } + } + } + + // Alignment. + &.aln-left { + justify-content: flex-start; + } + + &.aln-center { + justify-content: center; + } + + &.aln-right { + justify-content: flex-end; + } + + &.aln-top { + align-items: flex-start; + } + + &.aln-middle { + align-items: center; + } + + &.aln-bottom { + align-items: flex-end; + } + + // Step through suffixes. + @each $suffix in $suffixes { + + // Suffix. + @if ($suffix != '') { + $suffix: '-' + $suffix; + } + @else { + $suffix: ''; + } + + // Row. + + // Important. + > .imp#{$suffix} { + order: -1; + } + + // Columns, offsets. + @for $i from 1 through $cols { + > .col-#{$i}#{$suffix} { + width: $unit * $i; + } + + > .off-#{$i}#{$suffix} { + margin-left: $unit * $i; + } + } + + // Step through multipliers. + @each $multiplier in $multipliers { + + // Gutters. + $class: null; + + @if ($multiplier != 1) { + $class: '.gtr-' + ($multiplier * 100); + } + + &#{$class} { + margin-top: ($guttersRows * $multiplier * -1); + margin-left: ($guttersCols * $multiplier * -1); + + > * { + padding: ($guttersRows * $multiplier) 0 0 ($guttersCols * $multiplier); + } + + // Uniform. + &.gtr-uniform { + margin-top: $guttersCols * $multiplier * -1; + + > * { + padding-top: $guttersCols * $multiplier; + } + } + + } + + } + + } + + } \ No newline at end of file diff --git a/sass/libs/_mixins.scss b/sass/libs/_mixins.scss new file mode 100644 index 0000000..19deb34 --- /dev/null +++ b/sass/libs/_mixins.scss @@ -0,0 +1,78 @@ +/// Makes an element's :before pseudoelement a FontAwesome icon. +/// @param {string} $content Optional content value to use. +/// @param {string} $category Optional category to use. +/// @param {string} $where Optional pseudoelement to target (before or after). +@mixin icon($content: false, $category: regular, $where: before) { + + text-decoration: none; + + &:#{$where} { + + @if $content { + content: $content; + } + + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; + text-transform: none !important; + + @if ($category == brands) { + font-family: 'Font Awesome 5 Brands'; + } + @elseif ($category == solid) { + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + } + @else { + font-family: 'Font Awesome 5 Free'; + font-weight: 400; + } + + } + +} + +/// Applies padding to an element, taking the current element-margin value into account. +/// @param {mixed} $tb Top/bottom padding. +/// @param {mixed} $lr Left/right padding. +/// @param {list} $pad Optional extra padding (in the following order top, right, bottom, left) +/// @param {bool} $important If true, adds !important. +//@mixin padding($tb, $lr, $pad: (0,0,0,0), $important: null) { +// +// @if $important { +// $important: '!important'; +// } +// +// $x: 0.1em; +// +// @if unit(_size(element-margin)) == 'rem' { +// $x: 0.1rem; +// } +// +// padding: ($tb + nth($pad,1)) ($lr + nth($pad,2)) max($x, $tb - _size(element-margin) + nth($pad,3)) ($lr + nth($pad,4)) #{$important}; +// +//} + +/// Encodes a SVG data URL so IE doesn't choke (via codepen.io/jakob-e/pen/YXXBrp). +/// @param {string} $svg SVG data URL. +/// @return {string} Encoded SVG data URL. +@function svg-url($svg) { + + $svg: str-replace($svg, '"', '\''); + $svg: str-replace($svg, '%', '%25'); + $svg: str-replace($svg, '<', '%3C'); + $svg: str-replace($svg, '>', '%3E'); + $svg: str-replace($svg, '&', '%26'); + $svg: str-replace($svg, '#', '%23'); + $svg: str-replace($svg, '{', '%7B'); + $svg: str-replace($svg, '}', '%7D'); + $svg: str-replace($svg, ';', '%3B'); + + @return url("data:image/svg+xml;charset=utf8,#{$svg}"); + +} \ No newline at end of file diff --git a/sass/libs/_vars.scss b/sass/libs/_vars.scss new file mode 100644 index 0000000..66bfb7c --- /dev/null +++ b/sass/libs/_vars.scss @@ -0,0 +1,60 @@ +// Misc. + $misc: ( + z-index-base: 10000 + ); + +// Duration. + $duration: ( + transition: 0.2s + ); + +// Size. + $size: ( + border-radius: 4px, + element-height: 2.75em, + element-margin: 2em, + container-width: 60em + ); + +// Font. + $font: ( + family: ('Source Sans Pro', Helvetica, sans-serif), + family-fixed: ('Courier New', monospace), + weight: 300, + weight-bold: 400 + ); + +// Palette. + $palette: ( + bg: #fff, + fg: #666, + fg-bold: #555, + fg-light: #999, + border: rgba(144,144,144,0.5), + border-bg: rgba(144,144,144,0.075), + border2: rgba(144,144,144,0.75), + border2-bg: rgba(144,144,144,0.2), + accent1: #c3e895, + accent2: #8addaa, + accent3: #6bd4c8, + accent4: #57aed3, + accent5: #4a87d3, + accent6: #6b88e6, + accent1-alt: desaturate(darken(#c3e895, 15), 20), + accent2-alt: desaturate(darken(#8addaa, 15), 20), + accent3-alt: desaturate(darken(#6bd4c8, 15), 20), + accent4-alt: desaturate(darken(#57aed3, 15), 20), + accent5-alt: desaturate(darken(#4a87d3, 15), 20), + accent6-alt: desaturate(darken(#6b88e6, 15), 20), + + dark: ( + bg: #666666, + fg-bold: #ffffff, + fg: rgba(255,255,255,0.75), + fg-light: rgba(255,255,255,0.5), + border: #ffffff, + border-bg: rgba(255,255,255,0.125), + border2: rgba(255,255,255,0.75), + border2-bg: rgba(255,255,255,0.25) + ) + ); \ No newline at end of file diff --git a/sass/libs/_vendor.scss b/sass/libs/_vendor.scss new file mode 100644 index 0000000..6599a3f --- /dev/null +++ b/sass/libs/_vendor.scss @@ -0,0 +1,376 @@ +// vendor.scss v1.0 | @ajlkn | MIT licensed */ + +// Vars. + + /// Vendor prefixes. + /// @var {list} + $vendor-prefixes: ( + '-moz-', + '-webkit-', + '-ms-', + '' + ); + + /// Properties that should be vendorized. + /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org + /// @var {list} + $vendor-properties: ( + + // Animation. + 'animation', + 'animation-delay', + 'animation-direction', + 'animation-duration', + 'animation-fill-mode', + 'animation-iteration-count', + 'animation-name', + 'animation-play-state', + 'animation-timing-function', + + // Appearance. + 'appearance', + + // Backdrop filter. + 'backdrop-filter', + + // Background image options. + 'background-clip', + 'background-origin', + 'background-size', + + // Box sizing. + 'box-sizing', + + // Clip path. + 'clip-path', + + // Filter effects. + 'filter', + + // Flexbox. + 'align-content', + 'align-items', + 'align-self', + 'flex', + 'flex-basis', + 'flex-direction', + 'flex-flow', + 'flex-grow', + 'flex-shrink', + 'flex-wrap', + 'justify-content', + 'order', + + // Font feature. + 'font-feature-settings', + 'font-language-override', + 'font-variant-ligatures', + + // Font kerning. + 'font-kerning', + + // Fragmented borders and backgrounds. + 'box-decoration-break', + + // Grid layout. + 'grid-column', + 'grid-column-align', + 'grid-column-end', + 'grid-column-start', + 'grid-row', + 'grid-row-align', + 'grid-row-end', + 'grid-row-start', + 'grid-template-columns', + 'grid-template-rows', + + // Hyphens. + 'hyphens', + 'word-break', + + // Masks. + 'mask', + 'mask-border', + 'mask-border-outset', + 'mask-border-repeat', + 'mask-border-slice', + 'mask-border-source', + 'mask-border-width', + 'mask-clip', + 'mask-composite', + 'mask-image', + 'mask-origin', + 'mask-position', + 'mask-repeat', + 'mask-size', + + // Multicolumn. + 'break-after', + 'break-before', + 'break-inside', + 'column-count', + 'column-fill', + 'column-gap', + 'column-rule', + 'column-rule-color', + 'column-rule-style', + 'column-rule-width', + 'column-span', + 'column-width', + 'columns', + + // Object fit. + 'object-fit', + 'object-position', + + // Regions. + 'flow-from', + 'flow-into', + 'region-fragment', + + // Scroll snap points. + 'scroll-snap-coordinate', + 'scroll-snap-destination', + 'scroll-snap-points-x', + 'scroll-snap-points-y', + 'scroll-snap-type', + + // Shapes. + 'shape-image-threshold', + 'shape-margin', + 'shape-outside', + + // Tab size. + 'tab-size', + + // Text align last. + 'text-align-last', + + // Text decoration. + 'text-decoration-color', + 'text-decoration-line', + 'text-decoration-skip', + 'text-decoration-style', + + // Text emphasis. + 'text-emphasis', + 'text-emphasis-color', + 'text-emphasis-position', + 'text-emphasis-style', + + // Text size adjust. + 'text-size-adjust', + + // Text spacing. + 'text-spacing', + + // Transform. + 'transform', + 'transform-origin', + + // Transform 3D. + 'backface-visibility', + 'perspective', + 'perspective-origin', + 'transform-style', + + // Transition. + 'transition', + 'transition-delay', + 'transition-duration', + 'transition-property', + 'transition-timing-function', + + // Unicode bidi. + 'unicode-bidi', + + // User select. + 'user-select', + + // Writing mode. + 'writing-mode', + + ); + + /// Values that should be vendorized. + /// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org + /// @var {list} + $vendor-values: ( + + // Cross fade. + 'cross-fade', + + // Element function. + 'element', + + // Filter function. + 'filter', + + // Flexbox. + 'flex', + 'inline-flex', + + // Grab cursors. + 'grab', + 'grabbing', + + // Gradients. + 'linear-gradient', + 'repeating-linear-gradient', + 'radial-gradient', + 'repeating-radial-gradient', + + // Grid layout. + 'grid', + 'inline-grid', + + // Image set. + 'image-set', + + // Intrinsic width. + 'max-content', + 'min-content', + 'fit-content', + 'fill', + 'fill-available', + 'stretch', + + // Sticky position. + 'sticky', + + // Transform. + 'transform', + + // Zoom cursors. + 'zoom-in', + 'zoom-out', + + ); + +// Functions. + + /// Removes a specific item from a list. + /// @author Hugo Giraudel + /// @param {list} $list List. + /// @param {integer} $index Index. + /// @return {list} Updated list. + @function remove-nth($list, $index) { + + $result: null; + + @if type-of($index) != number { + @warn "$index: #{quote($index)} is not a number for `remove-nth`."; + } + @else if $index == 0 { + @warn "List index 0 must be a non-zero integer for `remove-nth`."; + } + @else if abs($index) > length($list) { + @warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`."; + } + @else { + + $result: (); + $index: if($index < 0, length($list) + $index + 1, $index); + + @for $i from 1 through length($list) { + + @if $i != $index { + $result: append($result, nth($list, $i)); + } + + } + + } + + @return $result; + + } + + /// Replaces a substring within another string. + /// @author Hugo Giraudel + /// @param {string} $string String. + /// @param {string} $search Substring. + /// @param {string} $replace Replacement. + /// @return {string} Updated string. + @function str-replace($string, $search, $replace: '') { + + $index: str-index($string, $search); + + @if $index { + @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); + } + + @return $string; + + } + + /// Replaces a substring within each string in a list. + /// @param {list} $strings List of strings. + /// @param {string} $search Substring. + /// @param {string} $replace Replacement. + /// @return {list} Updated list of strings. + @function str-replace-all($strings, $search, $replace: '') { + + @each $string in $strings { + $strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace)); + } + + @return $strings; + + } + +// Mixins. + + /// Wraps @content in vendorized keyframe blocks. + /// @param {string} $name Name. + @mixin keyframes($name) { + + @-moz-keyframes #{$name} { @content; } + @-webkit-keyframes #{$name} { @content; } + @-ms-keyframes #{$name} { @content; } + @keyframes #{$name} { @content; } + + } + + /// Vendorizes a declaration's property and/or value(s). + /// @param {string} $property Property. + /// @param {mixed} $value String/list of value(s). + @mixin vendor($property, $value) { + + // Determine if property should expand. + $expandProperty: index($vendor-properties, $property); + + // Determine if value should expand (and if so, add '-prefix-' placeholder). + $expandValue: false; + + @each $x in $value { + @each $y in $vendor-values { + @if $y == str-slice($x, 1, str-length($y)) { + + $value: set-nth($value, index($value, $x), '-prefix-' + $x); + $expandValue: true; + + } + } + } + + // Expand property? + @if $expandProperty { + @each $vendor in $vendor-prefixes { + #{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; + } + } + + // Expand just the value? + @elseif $expandValue { + @each $vendor in $vendor-prefixes { + #{$property}: #{str-replace-all($value, '-prefix-', $vendor)}; + } + } + + // Neither? Treat them as a normal declaration. + @else { + #{$property}: #{$value}; + } + + } \ No newline at end of file diff --git a/sass/main.scss b/sass/main.scss new file mode 100644 index 0000000..55e99aa --- /dev/null +++ b/sass/main.scss @@ -0,0 +1,1540 @@ +@import 'libs/vars'; +@import 'libs/functions'; +@import 'libs/mixins'; +@import 'libs/vendor'; +@import 'libs/breakpoints'; +@import 'libs/html-grid'; +@import url('../css/fontawesome-all.min.css'); +@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300italic,400,400italic"); + +// Breakpoints. + + @include breakpoints(( + xlarge: ( 1141px, 1680px ), + large: ( 981px, 1140px ), + medium: ( 737px, 980px ), + small: ( 481px, 736px ), + xsmall: ( 321px, 480px ), + xxsmall: ( null, 320px ) + )); + +// Reset. +// Based on meyerweb.com/eric/tools/css/reset (v2.0 | 20110126 | License: public domain) + + html, body, div, span, applet, object, + iframe, h1, h2, h3, h4, h5, h6, p, blockquote, + pre, a, abbr, acronym, address, big, cite, + code, del, dfn, em, img, ins, kbd, q, s, samp, + small, strike, strong, sub, sup, tt, var, b, + u, i, center, dl, dt, dd, ol, ul, li, fieldset, + form, label, legend, table, caption, tbody, + tfoot, thead, tr, th, td, article, aside, + canvas, details, embed, figure, figcaption, + footer, header, hgroup, menu, nav, output, ruby, + section, summary, time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; + } + + article, aside, details, figcaption, figure, + footer, header, hgroup, menu, nav, section { + display: block; + } + + body { + line-height: 1; + } + + ol, ul { + list-style:none; + } + + blockquote, q { + quotes: none; + + &:before, + &:after { + content: ''; + content: none; + } + } + + table { + border-collapse: collapse; + border-spacing: 0; + } + + body { + -webkit-text-size-adjust: none; + } + + mark { + background-color: transparent; + color: inherit; + } + + input::-moz-focus-inner { + border: 0; + padding: 0; + } + + input, select, textarea { + -moz-appearance: none; + -webkit-appearance: none; + -ms-appearance: none; + appearance: none; + } + +/* Basic */ + + // Set box model to border-box. + // Based on css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice + html { + box-sizing: border-box; + } + + *, *:before, *:after { + box-sizing: inherit; + } + + body { + background: _palette(bg); + + // Stops initial animations until page loads. + &.is-preload { + *, *:before, *:after { + @include vendor('animation', 'none !important'); + @include vendor('transition', 'none !important'); + } + } + + } + + body, input, select, textarea { + color: _palette(fg); + font-family: _font(family); + font-size: 16pt; + font-weight: _font(weight); + line-height: 1.65em; + } + + a { + @include vendor('transition', ('color #{_duration(transition)} ease-in-out', 'border-color #{_duration(transition)} ease-in-out')); + border-bottom: dotted 1px _palette(fg); + color: inherit; + text-decoration: none; + + &:hover { + border-bottom-color: transparent !important; + color: _palette(accent3); + } + } + + strong, b { + color: _palette(fg-bold); + font-weight: _font(weight-bold); + } + + em, i { + font-style: italic; + } + + p { + margin: 0 0 _size(element-margin) 0; + } + + h1, h2, h3, h4, h5, h6 { + color: _palette(fg-bold); + line-height: 1em; + margin: 0 0 (_size(element-margin) * 0.5) 0; + + a { + color: inherit; + text-decoration: none; + } + } + + h1 { + font-size: 2.25em; + line-height: 1.35em; + } + + h2 { + font-size: 2em; + line-height: 1.35em; + } + + h3 { + font-size: 1.35em; + line-height: 1.5em; + } + + h4 { + font-size: 1.25em; + line-height: 1.5em; + } + + h5 { + font-size: 0.9em; + line-height: 1.5em; + } + + h6 { + font-size: 0.7em; + line-height: 1.5em; + } + + sub { + font-size: 0.8em; + position: relative; + top: 0.5em; + } + + sup { + font-size: 0.8em; + position: relative; + top: -0.5em; + } + + hr { + border: 0; + border-bottom: solid 1px _palette(border); + + // This is the *only* instance where we need to rely on margin collapse. + margin: _size(element-margin) 0; + + &.major { + margin: (_size(element-margin) * 1.5) 0; + } + } + + blockquote { + border-left: solid 4px _palette(border); + font-style: italic; + margin: 0 0 _size(element-margin) 0; + padding: 0.5em 0 0.5em 2em; + } + + code { + background: _palette(border-bg); + border-radius: _size(border-radius); + border: solid 1px _palette(border); + font-family: _font(family-fixed); + font-size: 0.9em; + margin: 0 0.25em; + padding: 0.25em 0.65em; + } + + pre { + -webkit-overflow-scrolling: touch; + font-family: _font(family-fixed); + font-size: 0.9em; + margin: 0 0 _size(element-margin) 0; + + code { + display: block; + line-height: 1.75em; + padding: 1em 1.5em; + overflow-x: auto; + } + } + + .align-left { + text-align: left; + } + + .align-center { + text-align: center; + } + + .align-right { + text-align: right; + } + +/* Container */ + + .container { + margin: 0 auto; + max-width: calc(100% - #{_size(element-margin) * 2}); + width: _size(container-width); + + &.xsmall { + width: (_size(container-width) * 0.25); + } + + &.small { + width: (_size(container-width) * 0.5); + } + + &.medium { + width: (_size(container-width) * 0.75); + } + + &.large { + width: (_size(container-width) * 1.25); + } + + &.xlarge { + width: (_size(container-width) * 1.5); + } + + &.max { + width: 100%; + } + + @include breakpoint('<=medium') { + max-width: 100% !important; + width: 100% !important; + } + + @include breakpoint('<=xsmall') { + max-width: calc(100% - #{_size(element-margin) * 1.5}); + } + } + +/* Row */ + + .row { + @include html-grid(2em); + + @include breakpoint('<=xlarge') { + @include html-grid(2em, 'xlarge'); + } + + @include breakpoint('<=large') { + @include html-grid(2em, 'large'); + } + + @include breakpoint('<=medium') { + @include html-grid(2em, 'medium'); + } + + @include breakpoint('<=small') { + @include html-grid(2em, 'small'); + } + + @include breakpoint('<=xsmall') { + @include html-grid(2em, 'xsmall'); + } + + @include breakpoint('<=xxsmall') { + @include html-grid(2em, 'xxsmall'); + } + } + +/* Section/Article */ + + section, article { + &.special { + text-align: center; + } + } + + header { + p { + color: _palette(fg-light); + margin: 0 0 (_size(element-margin) * 0.75) 0; + position: relative; + } + + h2 + p { + font-size: 1.25em; + line-height: 1.5em; + margin-top: (_size(element-margin) * -0.5); + } + + h3 + p { + font-size: 1.1em; + line-height: 1.5em; + margin-top: (_size(element-margin) * -0.4); + } + + h4 + p, + h5 + p, + h6 + p { + font-size: 0.9em; + line-height: 1.5em; + margin-top: (_size(element-margin) * -0.3); + } + + &.major { + margin: 0 0 (_size(element-margin) * 0.5) 0; + + &:after { + background: _palette(border); + content: ''; + display: inline-block; + height: 1px; + margin-top: (_size(element-margin) * 0.75); + width: 6em; + } + + h2, h3, h4, h5, h6 { + margin: 0; + } + + p { + margin: (_size(element-margin) * 0.35) 0 0 0; + } + } + + &.special { + text-align: center; + } + } + +/* Form */ + + form { + margin: 0 0 _size(element-margin) 0; + } + + label { + color: _palette(fg-bold); + display: block; + font-size: 0.9em; + font-weight: _font(weight-bold); + margin: 0 0 (_size(element-margin) * 0.5) 0; + } + + input[type="text"], + input[type="password"], + input[type="email"], + select, + textarea { + @include vendor('appearance', 'none'); + background: _palette(border-bg); + border-radius: _size(border-radius); + border: none; + border: solid 1px _palette(border); + color: inherit; + display: block; + outline: 0; + padding: 0 1em; + text-decoration: none; + width: 100%; + + &:invalid { + box-shadow: none; + } + + &:focus { + border-color: _palette(accent3); + } + } + + select { + background-image: svg-url(""); + background-size: 1.25rem; + background-repeat: no-repeat; + background-position: calc(100% - 1rem) center; + height: _size(element-height); + padding-right: _size(element-height); + text-overflow: ellipsis; + + option { + color: _palette(fg-bold); + background: _palette(bg); + } + + &:focus { + &::-ms-value { + background-color: transparent; + } + } + + &::-ms-expand { + display: none; + } + } + + input[type="text"], + input[type="password"], + input[type="email"], + select { + height: _size(element-height); + } + + textarea { + padding: 0.75em 1em; + } + + input[type="checkbox"], + input[type="radio"], { + @include vendor('appearance', 'none'); + display: block; + float: left; + margin-right: -2em; + opacity: 0; + width: 1em; + z-index: -1; + + & + label { + @include icon(false, solid); + color: _palette(fg); + cursor: pointer; + display: inline-block; + font-size: 1em; + font-weight: _font(weight); + padding-left: (_size(element-height) * 0.6) + 0.75em; + padding-right: 0.75em; + position: relative; + + &:before { + background: _palette(border-bg); + border-radius: _size(border-radius); + border: solid 1px _palette(border); + content: ''; + display: inline-block; + font-size: 0.8em; + height: (_size(element-height) * 0.75); + left: 0; + line-height: (_size(element-height) * 0.75); + position: absolute; + text-align: center; + top: 0; + width: (_size(element-height) * 0.75); + } + } + + &:checked + label { + &:before { + background: _palette(dark, bg); + border-color: _palette(dark, bg); + color: _palette(dark, fg-bold); + content: '\f00c'; + } + } + + &:focus + label { + &:before { + border-color: _palette(accent3); + } + } + } + + input[type="checkbox"] { + & + label { + &:before { + border-radius: _size(border-radius); + } + } + } + + input[type="radio"] { + & + label { + &:before { + border-radius: 100%; + } + } + } + + ::-webkit-input-placeholder { + color: _palette(fg-light) !important; + opacity: 1.0; + } + + :-moz-placeholder { + color: _palette(fg-light) !important; + opacity: 1.0; + } + + ::-moz-placeholder { + color: _palette(fg-light) !important; + opacity: 1.0; + } + + :-ms-input-placeholder { + color: _palette(fg-light) !important; + opacity: 1.0; + } + +/* Box */ + + .box { + border-radius: _size(border-radius); + border: solid 1px _palette(border); + margin-bottom: _size(element-margin); + padding: 1.5em; + + > :last-child, + > :last-child > :last-child, + > :last-child > :last-child > :last-child { + margin-bottom: 0; + } + + &.alt { + border: 0; + border-radius: 0; + padding: 0; + } + } + +/* Icon */ + + .icon { + @include icon; + border-bottom: none; + position: relative; + + > .label { + display: none; + } + + &:before { + line-height: inherit; + } + + &.solid { + &:before { + font-weight: 900 !important; + } + } + + &.brands { + &:before { + font-family: 'Font Awesome 5 Brands'; + } + } + + &.style1 { &:before { color: _palette(accent1); } } + &.style2 { &:before { color: _palette(accent2); } } + &.style3 { &:before { color: _palette(accent3); } } + &.style4 { &:before { color: _palette(accent4); } } + &.style5 { &:before { color: _palette(accent5); } } + &.style6 { &:before { color: _palette(accent6); } } + + &.major { + @include icon; + color: _palette(fg-bold); + cursor: default; + display: inline-block; + margin: 0 0 (_size(element-margin) * 0.75) 0; + + &:before { + font-size: 4em; + line-height: 1em; + } + } + } + +/* Image */ + + .image { + border-radius: _size(border-radius); + border: 0; + display: inline-block; + position: relative; + + img { + border-radius: _size(border-radius); + display: block; + } + + &.left { + float: left; + padding: 0 1.5em 1em 0; + top: 0.25em; + } + + &.right { + float: right; + padding: 0 0 1em 1.5em; + top: 0.25em; + } + + &.left, + &.right { + max-width: 40%; + + img { + width: 100%; + } + } + + &.fit { + display: block; + margin: 0 0 _size(element-margin) 0; + width: 100%; + + img { + width: 100%; + } + } + } + +/* List */ + + ol { + list-style: decimal; + margin: 0 0 _size(element-margin) 0; + padding-left: 1.25em; + + li { + padding-left: 0.25em; + } + } + + ul { + list-style: disc; + margin: 0 0 _size(element-margin) 0; + padding-left: 1em; + + li { + padding-left: 0.5em; + } + + &.alt { + list-style: none; + padding-left: 0; + + li { + border-top: solid 1px _palette(border); + padding: 0.5em 0; + + &:first-child { + border-top: 0; + padding-top: 0; + } + } + } + } + + dl { + margin: 0 0 _size(element-margin) 0; + } + +/* Actions */ + + ul.actions { + @include vendor('display', 'flex'); + cursor: default; + list-style: none; + margin-left: (_size(element-margin) * -0.5); + padding-left: 0; + + li { + padding: 0 0 0 (_size(element-margin) * 0.5); + vertical-align: middle; + } + + &.special { + @include vendor('justify-content', 'center'); + width: 100%; + margin-left: 0; + + li { + &:first-child { + padding-left: 0; + } + } + } + + &.stacked { + @include vendor('flex-direction', 'column'); + margin-left: 0; + + li { + padding: (_size(element-margin) * 0.65) 0 0 0; + + &:first-child { + padding-top: 0; + } + } + } + + &.fit { + width: calc(100% + #{_size(element-margin) * 0.5}); + + li { + @include vendor('flex-grow', '1'); + @include vendor('flex-shrink', '1'); + width: 100%; + + > * { + width: 100%; + } + } + + &.stacked { + width: 100%; + } + } + + @include breakpoint('<=xsmall') { + &:not(.fixed) { + @include vendor('flex-direction', 'column'); + margin-left: 0; + width: 100% !important; + + li { + @include vendor('flex-grow', '1'); + @include vendor('flex-shrink', '1'); + padding: (_size(element-margin) * 0.5) 0 0 0; + text-align: center; + width: 100%; + + > * { + width: 100%; + } + + &:first-child { + padding-top: 0; + } + + input[type="submit"], + input[type="reset"], + input[type="button"], + button, + .button { + width: 100%; + + &.icon { + &:before { + margin-left: -0.5em; + } + } + } + } + } + } + } + +/* Icons */ + + ul.icons { + cursor: default; + list-style: none; + padding-left: 0; + + li { + display: inline-block; + padding: 0 1.25em 0 0; + + &:last-child { + padding-right: 0; + } + + .icon { + &:before { + font-size: 1.5em; + } + } + } + } + +/* Major Icons */ + + ul.major-icons { + list-style: none; + padding-left: 0; + + li { + display: inline-block; + padding: 2.5em; + text-align: center; + + .icon { + @include vendor('transform', 'rotate(45deg)'); + border-radius: _size(border-radius); + border: solid 1px _palette(border); + display: inline-block; + height: 8em; + line-height: 8em; + margin: 0; + text-align: center; + width: 8em; + + &:before { + @include vendor('transform', 'rotate(-45deg)'); + display: inline-block; + line-height: inherit; + } + } + } + } + +/* Table */ + + .table-wrapper { + -webkit-overflow-scrolling: touch; + overflow-x: auto; + } + + table { + margin: 0 0 _size(element-margin) 0; + width: 100%; + + tbody { + tr { + border-left: 0; + border-right: 0; + + &:nth-child(2n + 1) { + background-color: _palette(border-bg); + } + } + } + + td { + padding: 0.75em 0.75em; + } + + th { + color: _palette(fg-bold); + font-size: 0.9em; + font-weight: _font(weight-bold); + padding: 0 0.75em 0.75em 0.75em; + text-align: left; + } + + thead { + border-bottom: solid 1px _palette(border); + } + + tfoot { + border-top: solid 1px _palette(border); + } + + &.alt { + border-collapse: separate; + + tbody { + tr { + td { + border: solid 1px _palette(border); + border-left-width: 0; + border-top-width: 0; + + &:first-child { + border-left-width: 1px; + } + } + + &:first-child { + td { + border-top-width: 1px; + } + } + } + } + + thead { + border-bottom: 0; + } + + tfoot { + border-top: 0; + } + } + } + +/* Button */ + + input[type="submit"], + input[type="reset"], + input[type="button"], + button, + .button { + @include vendor('appearance', 'none'); + @include vendor('transition', ('background-color #{_duration(transition)} ease-in-out', 'color #{_duration(transition)} ease-in-out')); + background-color: transparent; + border-radius: _size(border-radius); + border: 0; + box-shadow: inset 0 0 0 1px _palette(border); + color: _palette(fg-bold) !important; + cursor: pointer; + display: inline-block; + font-size: 0.9em; + font-weight: _font(weight-bold); + height: 2.75em; + letter-spacing: 0.125em; + line-height: 2.75em; + padding: 0 2em; + text-align: center; + text-decoration: none; + text-indent: 0.125em; + text-transform: uppercase; + white-space: nowrap; + + &:hover { + background-color: _palette(border-bg); + } + + &:active { + background-color: _palette(border2-bg); + } + + &.icon { + &:before { + margin-right: 0.5em; + } + } + + &.fit { + width: 100%; + } + + &.small { + font-size: 0.7em; + } + + &.large { + font-size: 1.25em; + } + + &.wide { + min-width: 12em; + } + + &.primary { + background-color: _palette(fg-bold); + box-shadow: none !important; + color: _palette(bg) !important; + + &:hover { + background-color: lighten(_palette(fg-bold), 5); + } + + &:active { + background-color: darken(_palette(fg-bold), 5); + } + } + + &.disabled, + &:disabled { + cursor: default; + opacity: 0.25; + } + } + +// Dark (mixin) + + @mixin dark($color-this-bg: _palette(dark, bg)) { + background-color: $color-this-bg; + color: _palette(dark, fg); + + a { + border-bottom-color: transparentize(_palette(dark, fg), 0.25); + + &:hover { + color: _palette(dark, fg-bold); + } + } + + h1, h2, h3, h4, h5, h6, strong, b { + color: _palette(dark, fg-bold); + } + + header { + p { + color: _palette(dark, fg-bold); + } + + &.major { + &:after { + background: _palette(dark, border); + } + } + } + + input[type="submit"], + input[type="reset"], + input[type="button"], + button, + .button { + box-shadow: inset 0 0 0 1px _palette(dark, border); + color: _palette(dark, fg-bold) !important; + + &:hover { + background-color: _palette(dark, border-bg); + } + + &:active { + background-color: _palette(dark, border2-bg); + } + + &.primary { + background-color: _palette(dark, fg-bold); + box-shadow: inset 0 0 0 1px _palette(dark, border) !important; + color: $color-this-bg !important; + + &:hover { + background-color: _palette(dark, border-bg) !important; + color: _palette(dark, fg-bold) !important; + } + + &:active { + background-color: _palette(dark, border2-bg) !important; + } + } + } + + ul { + &.major-icons { + li { + .icon { + border-color: _palette(dark, border); + } + } + } + } + + .icon { + &.major { + color: _palette(dark, fg-bold); + } + } + } + +/* Main */ + + .main { + @include padding(6em, 0); + + &.style1 { + background: _palette(bg); + } + + &.style2 { + @include dark(#333); + background-attachment: fixed, fixed; + background-image: url('images/overlay1.png'), url('../../templates/html5up-photon/images/header.jpg'); + background-size: auto, cover; + } + } + +/* Header */ + + #header { + @include padding(9em, 0, (0,0,_size(element-margin),0)); + @include dark(#4686a0); + background-attachment: fixed, fixed, fixed; + background-image: url('images/overlay2.png'), url('images/overlay3.svg'), linear-gradient(45deg, _palette(accent1-alt) 5%, _palette(accent3-alt) 30%, _palette(accent6-alt)); + background-position: top left, center center, center center; + background-size: auto, cover, cover; + overflow: hidden; + position: relative; + text-align: center; + + h1 { + margin: 0; + } + + p { + margin: (_size(element-margin) * 0.5) 0 0 0; + } + + .actions { + @include vendor('justify-content', 'center'); + margin-top: (_size(element-margin) * 1.25); + margin-left: 0; + position: relative; + + li { + &:first-child { + padding-left: 0; + } + } + + &:after { + background: _palette(dark, border); + content: ''; + height: 100vh; + left: 50%; + position: absolute; + top: 100%; + width: 1px; + } + } + + .inner { + @include vendor('transition', ('transform 1.5s ease', 'opacity 2s ease')); + @include vendor('transition-delay', '0.25s'); + @include vendor('transform', 'scale(1)'); + opacity: 1; + position: relative; + z-index: 1; + + .actions { + @include vendor('transition', 'transform 1.25s ease'); + @include vendor('transition-delay', '1s'); + @include vendor('transform', 'translateY(0)'); + opacity: 1; + } + } + + &:after { + @include vendor('transition', 'opacity 1s ease'); + background-image: linear-gradient(45deg, _palette(accent3-alt), _palette(accent6-alt)); + content: ''; + height: 100%; + left: 0; + opacity: 0; + position: absolute; + top: 0; + width: 100%; + } + } + + body.is-preload { + #header { + .inner { + @include vendor('transform', 'scale(1.05)'); + opacity: 0; + + .actions { + @include vendor('transform', 'translateY(30em)'); + opacity: 0; + } + } + + &:after { + opacity: 1; + } + } + } + +/* Footer */ + + #footer { + @include padding(6em, 0, (0,0,_size(element-margin),0)); + @include dark(#4686a0); + background-attachment: fixed, fixed, fixed; + background-image: url('images/overlay2.png'), url('images/overlay4.svg'), linear-gradient(45deg, _palette(accent6-alt), _palette(accent3-alt) 50%, _palette(accent1-alt) 95%); + background-position: top left, center center, center center; + background-size: auto, cover, cover; + text-align: center; + + .icons { + margin: 0; + } + + .copyright { + font-size: 0.8em; + list-style: none; + margin: _size(element-margin) 0 0 0; + padding: 0; + + li { + border-left: solid 1px; + display: inline-block; + line-height: 1em; + margin-left: 1em; + padding: 0 0 0 1em; + + &:first-child { + border-left: 0; + margin-left: 0; + padding: 0; + } + } + } + } + +/* XLarge */ + + @include breakpoint('<=xlarge') { + + /* Basic */ + + body, input, select, textarea { + font-size: 14pt; + } + + /* Header */ + + #header { + @include padding(6em, 0, (0,0,_size(element-margin),0)); + } + + } + +/* Large */ + + @include breakpoint('<=large') { + + /* Basic */ + + body, input, select, textarea { + font-size: 13pt; + } + + h1, h2, h3, h4, h5, h6 { + br { + display: none; + } + } + + /* List */ + + ul { + &.major-icons { + li { + padding: 2em; + + .icon { + height: 8em; + line-height: 8em; + width: 8em; + } + } + } + } + + /* Main */ + + .main { + @include padding(4em, 0); + + &.style2 { + background-attachment: scroll; + } + } + + /* Header */ + + #header { + @include padding(5em, 0, (0,0,_size(element-margin),0)); + background-attachment: scroll; + + br { + display: inline; + } + } + + /* Footer */ + + #footer { + @include padding(4em, 0, (0,0,_size(element-margin),0)); + background-attachment: scroll; + } + + } + +/* Medium */ + + @include breakpoint('<=medium') { + + /* List */ + + ul { + &.major-icons { + li { + padding: 2em; + + .icon { + height: 7em; + line-height: 7em; + width: 7em; + } + } + } + } + + /* Main */ + + .main { + @include padding(5em, 3em); + } + + /* Header */ + + #header { + @include padding(8em, 3em, (0,0,_size(element-margin),0)); + } + + /* Footer */ + + #footer { + @include padding(5em, 3em, (0,0,_size(element-margin),0)); + } + + /* One */ + + #one { + text-align: center; + } + + /* Two */ + + #two { + text-align: center; + } + + } + +/* Small */ + + @include breakpoint('<=small') { + + /* Basic */ + + body, input, select, textarea { + font-size: 12pt; + } + + h1 { + font-size: 1.75em; + } + + h2 { + font-size: 1.5em; + } + + h3 { + font-size: 1.1em; + } + + h4 { + font-size: 1em; + } + + /* List */ + + ul { + &.major-icons { + li { + padding: 1.5em; + + .icon { + height: 5em; + line-height: 5em; + width: 5em; + + &:before { + font-size: 42px; + } + } + } + } + } + + /* Icon */ + + .icon { + &.major { + margin: 0 0 (_size(element-margin) * 0.5) 0; + } + } + + /* Button */ + + input[type="submit"], + input[type="reset"], + input[type="button"], + button, + .button { + height: 3em; + line-height: 3em; + } + + /* Main */ + + .main { + @include padding(3em, 1.5em); + } + + /* Header */ + + #header { + @include padding(4em, 3em, (0,0,_size(element-margin),0)); + + .actions { + margin: _size(element-margin) 0 0 0; + } + } + + /* Footer */ + + #footer { + @include padding(3em, 1.5em, (0,0,_size(element-margin),0)); + } + + } + +/* XSmall */ + + @include breakpoint('<=xsmall') { + + /* Button */ + + input[type="submit"], + input[type="reset"], + input[type="button"], + .button { + padding: 0; + } + + /* Main */ + + .main { + @include padding(2em, 1.5em); + } + + /* Header */ + + #header { + @include padding(4em, 2em, (0,0,_size(element-margin),0)); + + br { + display: none; + } + } + + /* Footer */ + + #footer { + @include padding(2em, 1.5em, (0,0,_size(element-margin),0)); + + .copyright { + margin: (_size(element-margin) * 0.75) 0 0 0; + + li { + border: 0; + display: block; + margin: 1em 0 0 0; + padding: 0; + + &:first-child { + margin-top: 0; + } + } + } + } + + } + +/* XXSmall */ + + @include breakpoint('<=xxsmall') { + + /* Basic */ + + html, body { + min-width: 320px; + } + + /* Main */ + + .main { + @include padding(2em, 1em); + } + + /* Header */ + + #header { + @include padding(3em, 1em, (0,0,_size(element-margin),0)); + } + + /* Footer */ + + #footer { + @include padding(2em, 1em, (0,0,_size(element-margin),0)); + } + + } \ No newline at end of file diff --git a/sass/noscript.scss b/sass/noscript.scss new file mode 100644 index 0000000..11202e9 --- /dev/null +++ b/sass/noscript.scss @@ -0,0 +1,32 @@ +@import 'libs/vars'; +@import 'libs/functions'; +@import 'libs/mixins'; +@import 'libs/vendor'; +@import 'libs/breakpoints'; +@import 'libs/html-grid'; + +/* + Photon by HTML5 UP + html5up.net | @ajlkn + Free for personal and commercial use under the CCA 3.0 license (html5up.net/license) +*/ + +/* Header */ + + body.is-preload { + #header { + .inner { + @include vendor('transform', 'none'); + opacity: 1; + + .actions { + @include vendor('transform', 'none'); + opacity: 1; + } + } + + &:after { + opacity: 0; + } + } + } \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..5a29a1d --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,69 @@ + + + + https://www.michaelkennedy.dev/ + + + https://www.michaelkennedy.dev/ats-resume/ + + + https://www.michaelkennedy.dev/blog/ + + + https://www.michaelkennedy.dev/blog/1-07-24/ + 2024-01-07 + + + https://www.michaelkennedy.dev/blog/1-15-24/ + 2024-01-15 + + + https://www.michaelkennedy.dev/blog/page/1/ + + + https://www.michaelkennedy.dev/categories/ + + + https://www.michaelkennedy.dev/contact-me/ + + + https://www.michaelkennedy.dev/projects/ + + + https://www.michaelkennedy.dev/projects/axe/ + 2022-01-03 + + + https://www.michaelkennedy.dev/projects/deadwood/ + 2022-01-03 + + + https://www.michaelkennedy.dev/projects/django-react-chat-application/ + 2022-07-19 + + + https://www.michaelkennedy.dev/projects/page/1/ + + + https://www.michaelkennedy.dev/projects/recaptcha/ + 2022-03-01 + + + https://www.michaelkennedy.dev/projects/releave/ + 2022-01-02 + + + https://www.michaelkennedy.dev/projects/uml-class-editor/ + 2022-03-01 + + + https://www.michaelkennedy.dev/resume/ + + + https://www.michaelkennedy.dev/tags/ + + + https://www.michaelkennedy.dev/technologies/ + 2022-09-06 + + diff --git a/technologies/index.html b/technologies/index.html new file mode 100644 index 0000000..5813d0e --- /dev/null +++ b/technologies/index.html @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + +Michael Kennedy | Languages I've Used + + + + + + + + + + +
+
+
+
+
+

+ Languages I've Used + +

+ +
+
+ + + Published on + + +
+
+
+

So far in my educational and professional career, I've had the opportunity to use Java, C#, C, Flutter (Dart), Javascript + HTML/CSS, and Python.

+

At my previous position with Heritage Bank NW, I worked full-stack on their Java back-end server as well as their React.js front-end application. The majority of my education involved algorithms, data structures, and less on UX/UI to the point where I've developed a preference for more back-end technologies.

+

The easiest language I've worked with thus far is Flutter. The structure of the code is hierarchical, and it's very easy to throw together a functioning application in a short amount of time. For example, I developed ReLeave in a matter of months with a team of students who had never interacted with the language before. Flutter has a lot of potential with a ton of community support, and it's incredibly easy for new software developers to see their application ideas become reality.

+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/webfonts/fa-brands-400.eot b/webfonts/fa-brands-400.eot new file mode 100644 index 0000000..e79f40f Binary files /dev/null and b/webfonts/fa-brands-400.eot differ diff --git a/webfonts/fa-brands-400.svg b/webfonts/fa-brands-400.svg new file mode 100644 index 0000000..ba0d850 --- /dev/null +++ b/webfonts/fa-brands-400.svg @@ -0,0 +1,3442 @@ + + + + + +Created by FontForge 20190112 at Tue Jun 4 15:16:44 2019 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webfonts/fa-brands-400.ttf b/webfonts/fa-brands-400.ttf new file mode 100644 index 0000000..217ffe9 Binary files /dev/null and b/webfonts/fa-brands-400.ttf differ diff --git a/webfonts/fa-brands-400.woff b/webfonts/fa-brands-400.woff new file mode 100644 index 0000000..a2d8025 Binary files /dev/null and b/webfonts/fa-brands-400.woff differ diff --git a/webfonts/fa-brands-400.woff2 b/webfonts/fa-brands-400.woff2 new file mode 100644 index 0000000..e27b0bf Binary files /dev/null and b/webfonts/fa-brands-400.woff2 differ diff --git a/webfonts/fa-regular-400.eot b/webfonts/fa-regular-400.eot new file mode 100644 index 0000000..d62be2f Binary files /dev/null and b/webfonts/fa-regular-400.eot differ diff --git a/webfonts/fa-regular-400.svg b/webfonts/fa-regular-400.svg new file mode 100644 index 0000000..751083e --- /dev/null +++ b/webfonts/fa-regular-400.svg @@ -0,0 +1,803 @@ + + + + + +Created by FontForge 20190112 at Tue Jun 4 15:16:44 2019 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webfonts/fa-regular-400.ttf b/webfonts/fa-regular-400.ttf new file mode 100644 index 0000000..eb3cb5e Binary files /dev/null and b/webfonts/fa-regular-400.ttf differ diff --git a/webfonts/fa-regular-400.woff b/webfonts/fa-regular-400.woff new file mode 100644 index 0000000..43b1a9a Binary files /dev/null and b/webfonts/fa-regular-400.woff differ diff --git a/webfonts/fa-regular-400.woff2 b/webfonts/fa-regular-400.woff2 new file mode 100644 index 0000000..b9344a7 Binary files /dev/null and b/webfonts/fa-regular-400.woff2 differ diff --git a/webfonts/fa-solid-900.eot b/webfonts/fa-solid-900.eot new file mode 100644 index 0000000..c77baa8 Binary files /dev/null and b/webfonts/fa-solid-900.eot differ diff --git a/webfonts/fa-solid-900.svg b/webfonts/fa-solid-900.svg new file mode 100644 index 0000000..627128b --- /dev/null +++ b/webfonts/fa-solid-900.svg @@ -0,0 +1,4649 @@ + + + + + +Created by FontForge 20190112 at Tue Jun 4 15:16:44 2019 + By Robert Madole +Copyright (c) Font Awesome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/webfonts/fa-solid-900.ttf b/webfonts/fa-solid-900.ttf new file mode 100644 index 0000000..c6c3dd4 Binary files /dev/null and b/webfonts/fa-solid-900.ttf differ diff --git a/webfonts/fa-solid-900.woff b/webfonts/fa-solid-900.woff new file mode 100644 index 0000000..77c1786 Binary files /dev/null and b/webfonts/fa-solid-900.woff differ diff --git a/webfonts/fa-solid-900.woff2 b/webfonts/fa-solid-900.woff2 new file mode 100644 index 0000000..e30fb67 Binary files /dev/null and b/webfonts/fa-solid-900.woff2 differ