diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000000..7831750b738 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,91 @@ +# Ruby CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-ruby/ for more details +# +version: 2 +jobs: + build: + docker: + # Specify the Ruby version you desire here + - image: circleci/ruby:2.3.3-node-browsers + environment: + RAILS_ENV: test + CC_TEST_REPORTER_ID: faecd27e9aed532634b3f4d3e251542d7de9457cfca96a94208a63270ef9b42e + COVERAGE: true + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + - image: circleci/postgres:9.4.12-alpine + environment: + POSTGRES_USER: circleci + + - image: redis:4.0.1 + + working_directory: ~/identity-idp + + steps: + - checkout + + - restore-cache: + key: identity-idp-{{ checksum "Gemfile.lock" }} + + - run: + name: Install dependencies + command: | + gem install bundler + bundle install --deployment --jobs=4 --retry=3 --without deploy development doc production --path vendor/bundle + - run: + name: Install phantomjs + command: | + sudo curl --output /tmp/phantomjs https://s3.amazonaws.com/circle-downloads/phantomjs-2.1.1 + sudo chmod ugo+x /tmp/phantomjs + sudo ln -sf /tmp/phantomjs /usr/local/bin/phantomjs + - run: + name: Install Code Climate Test Reporter + command: | + curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter + chmod +x ./cc-test-reporter + + # Store bundle cache + - save-cache: + key: identity-idp-{{ checksum "Gemfile.lock" }} + paths: + - vendor/bundle + + - run: + name: Test Setup + command: | + npm install + npm run build + cp config/application.yml.example config/application.yml + cp certs/saml.crt.example certs/saml.crt + cp keys/saml.key.enc.example keys/saml.key.enc + cp keys/equifax_rsa.example keys/equifax_rsa + gpg --dearmor < keys/equifax_gpg.pub.example > keys/equifax_gpg.pub.bin + gpg --import keys/equifax_gpg.example + bundle exec rake db:setup --trace + bundle exec rake assets:precompile + + - run: + name: Run Tests + command: | + mkdir /tmp/test-results + ./cc-test-reporter before-build + + bundle exec rspec --format progress + bundle exec teaspoon + bundle exec slim-lint app/views + + - run: + name: Upload Test Results to Code Climate + command: | + ./cc-test-reporter format-coverage -t simplecov $CIRCLE_ARTIFACTS/coverage/.resultset.json + ./cc-test-reporter upload-coverage + + # collect reports + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + destination: test-results diff --git a/.gitignore b/.gitignore index b18320e46b5..aebd7c9ecef 100644 --- a/.gitignore +++ b/.gitignore @@ -50,17 +50,11 @@ Vagrantfile /kitchen/cookbooks /log/* /private_certs/* -/public/*.ico -/public/*.png -/public/*.svg -/public/browserconfig.xml -/public/manifest.json /public/system /public/user_flows /spec/tmp /test /tmp/* -/vendor/assets/fonts /vendor/bundle /node_modules diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a8d124fb2ba..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,54 +0,0 @@ -addons: - postgresql: 9.3 - code_climate: - repo_token: - secure: '0RG6L9Sfur37NAB4X9rZypo6tffcWQtTcTpuSi08SfLN9jgiG2nHArVvw0nfNcSg7EmJ27ZnQxQqRjXlG76ufndlmoxgVX6xs96VyDyCOEFzRecE+wziNis+B3ACZb5OHaoMpomzsYFA73nYoCnPkgKUPAQFReTIqW7IB2Z1t7auTZe6kYBkKP7yB37wAVD4HMUDwm0spT0U2ur2GzSi86EqFEXR4NfhzGu5o7Y/hzWPxyyz+CRrujXhdWZl1FNtMj0mUM0/zSEEgUuCRRClGkD31RECjDKQQrXUkgQ1b3O/Nbih/8EjDqs4udLGnBYbtoahZ0ogZ/SV5xj7n2umNBJeLLTZO/qhWyQA4YDPuAZCw61VK1jpyQE1uZKxawYkgXBScmTWCJeAwEqZ4V8z4H4W2y1ZgegAoBCYOhv2+Dq4d9IaBUaeH3ukhEKX9H38yF1DEkp2sXKfXOxyEgpr0g0IIII9YVYQ89WExNmnZnfgd6lBqMFlP4wj8pQkCAeMG8+e+O0QsewzwlVgDDp5pQCgHEYq5X3quvWv0bRJDBL68/4fU9kEjv+RAo8Wx99x3nrZSzJglBrSaPt2/+eoVf3VTIJX4p8oO3aC/gcpbrWZrsfcGfLgKCEiu/ggzhicYhWY+Aa+pdeOefrO51ki9BIu84PoMrP2I7EREp2s1vw=' - apt: - packages: - - jq -cache: - directories: - - "travis_phantomjs" -before_install: - - . $HOME/.nvm/nvm.sh - - nvm install stable - - nvm use stable - - npm install - - npm run build - # Install PhantomJS 2.1.1 manually - - "export PHANTOMJS_VERSION=2.1.1" - - "phantomjs --version" - - "export PATH=$PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64/bin:$PATH" - - "phantomjs --version" - - "if [ $(phantomjs --version) != '$PHANTOMJS_VERSION' ]; then rm -rf $PWD/travis_phantomjs; mkdir -p $PWD/travis_phantomjs; fi" - - "if [ $(phantomjs --version) != '$PHANTOMJS_VERSION' ]; then wget https://github.com/Medium/phantomjs/releases/download/v$PHANTOMJS_VERSION/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -O $PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2; fi" - - "if [ $(phantomjs --version) != '$PHANTOMJS_VERSION' ]; then tar -xvf $PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs; fi" - - "phantomjs --version" -before_script: - - cp config/application.yml.example config/application.yml - - cp certs/saml.crt.example certs/saml.crt - - cp keys/saml.key.enc.example keys/saml.key.enc - - cp keys/equifax_rsa.example keys/equifax_rsa - - gpg --dearmor < keys/equifax_gpg.pub.example > keys/equifax_gpg.pub.bin - - gpg --import keys/equifax_gpg.example - - bin/rake db:setup --trace - - bin/rake assets:precompile -bundler_args: "--deployment --jobs=3 --retry=3 --without deploy development doc production" -cache: bundler -language: ruby -matrix: - fast_finish: true -notifications: - email: false -rvm: - - ruby-2.3.3 -sudo: false -script: - - make test - - bundle exec slim-lint app/views - - bundle exec codeclimate-test-reporter -services: - - redis-server -env: - global: - - COVERAGE=true diff --git a/Gemfile b/Gemfile index 00cf77b0301..eae7aba60bd 100644 --- a/Gemfile +++ b/Gemfile @@ -30,7 +30,6 @@ gem 'phonelib' gem 'phony_rails' gem 'premailer-rails' gem 'proofer', github: '18F/identity-proofer-gem', branch: 'master' -gem 'rack-attack' gem 'rack-cors', require: 'rack/cors' gem 'readthis' gem 'redis-session-store', github: '18F/redis-session-store', branch: 'master' diff --git a/Gemfile.lock b/Gemfile.lock index 9ecc2a0fdc9..788f80f851e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: git@github.com:18F/identity-equifax-api-client-gem.git - revision: 889aad815bda2ff2a41cd2b108e2afae7f50d8b8 + revision: 8021646f4a67216b0a1bdb99e501ad652104f889 branch: master specs: equifax (1.0.0) @@ -712,7 +712,6 @@ DEPENDENCIES premailer-rails proofer! pry-byebug - rack-attack rack-cors rack-mini-profiler rack-test @@ -759,4 +758,4 @@ RUBY VERSION ruby 2.3.3p222 BUNDLED WITH - 1.15.3 + 1.15.4 diff --git a/app/assets/images/no-verify.svg b/app/assets/images/no-verify.svg new file mode 100644 index 00000000000..c302b772d27 --- /dev/null +++ b/app/assets/images/no-verify.svg @@ -0,0 +1 @@ +no-verify \ No newline at end of file diff --git a/app/assets/javascripts/app/form-validation.js b/app/assets/javascripts/app/form-validation.js index 7d534d6e6c0..33309692516 100644 --- a/app/assets/javascripts/app/form-validation.js +++ b/app/assets/javascripts/app/form-validation.js @@ -1,19 +1,35 @@ +import 'classlist.js'; + const I18n = window.LoginGov.I18n; document.addEventListener('DOMContentLoaded', () => { - const form = document.querySelector('form'); - if (form) { - const fields = ['dob', 'personal-key', 'ssn', 'zipcode']; + const forms = document.querySelectorAll('form'); + + function addListenerMulti(el, events, fn) { + events.split(' ').forEach(e => el.addEventListener(e, fn, false)); + } + + if (forms.length !== 0) { + [].forEach.call(forms, function(form) { + const inputs = form.querySelectorAll('.field'); + + if (inputs.length !== 0) { + [].forEach.call(inputs, function(input) { + const types = ['dob', 'personal-key', 'ssn', 'zipcode']; + + addListenerMulti(input, 'input invalid', (e) => { + e.target.setCustomValidity(''); - fields.forEach(function(f) { - const input = document.querySelector(`.${f}`); - if (input) { - input.addEventListener('input', () => { - if (input.validity.patternMismatch) { - input.setCustomValidity(I18n.t(`idv.errors.pattern_mismatch.${I18n.key(f)}`)); - } else { - input.setCustomValidity(''); - } + if (e.target.validity.valueMissing) { + e.target.setCustomValidity(I18n.t('simple_form.required.text')); + } else if (e.target.validity.patternMismatch) { + types.forEach(function(type) { + if (e.target.classList.contains(type)) { + e.target.setCustomValidity(I18n.t(`idv.errors.pattern_mismatch.${I18n.key(type)}`)); + } + }); + } + }); }); } }); diff --git a/app/assets/javascripts/misc/i18n-strings.js.erb b/app/assets/javascripts/misc/i18n-strings.js.erb index a2bd235c4c7..3ae56e9768b 100644 --- a/app/assets/javascripts/misc/i18n-strings.js.erb +++ b/app/assets/javascripts/misc/i18n-strings.js.erb @@ -19,6 +19,7 @@ window.LoginGov = window.LoginGov || {}; 'instructions.password.strength.iv', 'instructions.password.strength.v', 'links.remove', + 'simple_form.required.text', 'valid_email.validations.email.invalid', 'zxcvbn.feedback.a_word_by_itself_is_easy_to_guess', 'zxcvbn.feedback.add_another_word_or_two_uncommon_words_are_better', diff --git a/app/assets/stylesheets/_vendor.scss b/app/assets/stylesheets/_vendor.scss new file mode 100644 index 00000000000..241ef017389 --- /dev/null +++ b/app/assets/stylesheets/_vendor.scss @@ -0,0 +1,8 @@ +@import 'normalize.css/normalize'; +@import 'hint.css/hint'; + +@import 'basscss-sass/basscss'; +@import 'basscss/margin'; +@import 'basscss/padding'; +@import 'basscss/responsive-margin'; +@import 'basscss/responsive-padding'; diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index 36142a61986..f47af41e55b 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -1,5 +1,6 @@ @import 'fonts'; - -@import 'identity-style-guide/src/css/app'; - +@import 'variables/colors'; +@import 'variables/app'; +@import 'vendor'; +@import 'components/all'; @import 'print'; diff --git a/app/assets/stylesheets/components/_abbr.scss b/app/assets/stylesheets/components/_abbr.scss new file mode 100644 index 00000000000..6048d5e322b --- /dev/null +++ b/app/assets/stylesheets/components/_abbr.scss @@ -0,0 +1,3 @@ +// normalize.css adds a text underline by default +// scss-lint:disable QualifyingElement +abbr[title] { text-decoration: none; } diff --git a/app/assets/stylesheets/components/_accordion.scss b/app/assets/stylesheets/components/_accordion.scss new file mode 100644 index 00000000000..3a59a7e044c --- /dev/null +++ b/app/assets/stylesheets/components/_accordion.scss @@ -0,0 +1,87 @@ +.no-js { + .accordion { + .accordion-header { + cursor: initial; + } + + .accordion-footer { + display: none; + } + + .accordion-content { + display: block; + } + + [class*="btn-"] { + display: none; + } + } +} + +.accordion { + border: $border-width solid $border-color; + border-radius: $border-radius-md; + + .accordion-header { + color: $blue; + cursor: pointer; + position: relative; + + img { + position: absolute; + right: 1rem; + top: .8rem; + } + } + + .accordion-content { + border-top: $border-width solid $border-color; + display: none; + opacity: 1; + + &.shown { + display: block; + } + } + + .accordion-footer { + background-color: $blue-lightest; + border-top: $border-width solid $border-color; + color: $blue; + cursor: pointer; + text-align: center; + + img { + margin-top: -2px; + vertical-align: middle; + } + } +} + +.animate-in { + animation: accordionIn .2s normal ease-in both 1; +} + +.animate-out { + animation: accordionOut .15s normal ease-out both 1; +} + +@keyframes accordionIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes accordionOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} diff --git a/app/assets/stylesheets/components/_alert.scss b/app/assets/stylesheets/components/_alert.scss new file mode 100644 index 00000000000..48dd85515eb --- /dev/null +++ b/app/assets/stylesheets/components/_alert.scss @@ -0,0 +1,58 @@ +$ico-size: 1rem; +$ico-offset: 1rem; + +.alert { + background-color: $blue-lighter; + border-radius: $space-1; + color: #5b616a; + font-size: 1rem; + line-height: 1.5rem; + margin-bottom: $space-4; + padding: 12px $space-2; + position: relative; + + &::before { + background-image: none; + background-repeat: no-repeat; + content: ''; + height: $ico-size; + left: $ico-offset; + position: absolute; + top: $ico-offset; + width: $ico-size; + } +} + +.alert-success { + background-color: #ebfcef; + padding-left: $space-4; + + &::before { background-image: url(image-path('alert/success.svg')); } +} + +.alert-thumb { + background-color: #ebfcef; + padding-left: $space-4; + + &::before { background-image: url(image-path('alert/ico-thumb.svg')); } +} + +.alert-error, +.alert-alert { + background-color: #fff0f3; + padding-left: $space-4; + + &::before { background-image: url(image-path('alert/error.svg')); } +} + +.alert-warning { + background-color: #fffdd7; + padding-left: $space-4; + + &::before { background-image: url(image-path('alert/warning.svg')); } +} + +.alert-notice { + padding-left: $space-4; + &::before { background-image: url(image-path('alert/notice.svg')); } +} diff --git a/app/assets/stylesheets/components/_background.scss b/app/assets/stylesheets/components/_background.scss new file mode 100644 index 00000000000..9c26230e10c --- /dev/null +++ b/app/assets/stylesheets/components/_background.scss @@ -0,0 +1,9 @@ +.bg-gray-lighter { background-color: $gray-lighter; } +.bg-light-blue { background-color: $blue-light; } +.bg-lightest-blue { background-color: $blue-lightest; } + +@media #{$breakpoint-sm} { + .sm-bg-light-blue { background-color: $blue-light; } + .sm-bg-none { background-color: transparent; } + .sm-bg-navy { background-color: $navy; } +} diff --git a/app/assets/stylesheets/components/_border.scss b/app/assets/stylesheets/components/_border.scss new file mode 100644 index 00000000000..12256d68ed6 --- /dev/null +++ b/app/assets/stylesheets/components/_border.scss @@ -0,0 +1,16 @@ +.bw1 { border-width: 1px; } +.bw2 { border-width: 2px; } +.bw3 { border-width: 3px; } +.bw4 { border-width: 4px; } + +.border-dashed { border-style: dashed; } + +.rounded-md { border-radius: $border-radius-md; } +.rounded-lg { border-radius: $border-radius-lg; } +.rounded-xl { border-radius: $border-radius-xl; } +.rounded-xxl { border-radius: $border-radius-xxl; } + +@media #{$breakpoint-sm} { + .sm-border-none { border: 0; } + .sm-rounded-md { border-radius: $border-radius-md; } +} diff --git a/app/assets/stylesheets/components/_btn.scss b/app/assets/stylesheets/components/_btn.scss new file mode 100644 index 00000000000..f8f473d80fb --- /dev/null +++ b/app/assets/stylesheets/components/_btn.scss @@ -0,0 +1,80 @@ +@media #{$breakpoint-sm} { + .btn { font-size: $button-font-size-sm; } +} + +.btn { + white-space: normal; +} + +%btn-basic { + background: transparent; + border: 0; + box-shadow: none; + color: $blue; + font-size: $base-font-size; + font-weight: normal; + line-height: $line-height; + outline: none; + padding: 0; +} + +.btn-primary { + border-radius: $border-radius-lg; +} + +.btn-secondary { + border: 1px solid $blue; + border-radius: $border-radius-lg; + color: $blue; + + &:hover { + background-color: $blue-lightest; + } +} + +.btn-wide { + box-sizing: border-box; + min-width: 220px; + text-align: center; +} + +.btn-transparent { + @extend %btn-basic; + cursor: pointer; +} + +.btn-link { + @extend %btn-basic; + text-decoration: underline; + vertical-align: baseline; + + &:active, + &:focus, + &:hover, { + border: 0; + box-shadow: none; + text-decoration: underline; + } +} + +.btn-border { + border-color: $border-color; + border-radius: $border-radius-lg; + border-style: solid; + border-width: $border-width; + box-sizing: border-box; + display: inline-block; + padding: $space-1 $space-2; + + // &.is-focused { + // border-color: $field-focus-color; + // box-shadow: 0 0 0 2px rgba($field-focus-color, .5); + // outline: none; + // } +} + +.btn-disabled { + background-color: $gray-light; + border-color: $gray; + color: $gray; +} diff --git a/app/assets/stylesheets/components/_card.scss b/app/assets/stylesheets/components/_card.scss new file mode 100644 index 00000000000..017d0addade --- /dev/null +++ b/app/assets/stylesheets/components/_card.scss @@ -0,0 +1,23 @@ +.card { + background-color: $white; + max-width: $container-skinny-width; + + &-wide { + max-width: 100%; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + } + + @media #{$breakpoint-sm} { + border-radius: 5px; + + &-wide { + margin-top: $space-4; + max-width: 100%; + padding-bottom: 0; + padding-left: 0; + padding-right: 0; + } + } +} diff --git a/app/assets/stylesheets/components/_color.scss b/app/assets/stylesheets/components/_color.scss new file mode 100644 index 00000000000..572de70adf1 --- /dev/null +++ b/app/assets/stylesheets/components/_color.scss @@ -0,0 +1,3 @@ +@media #{$breakpoint-sm} { + .sm-white { color: $white; } +} diff --git a/app/assets/stylesheets/components/_container.scss b/app/assets/stylesheets/components/_container.scss new file mode 100644 index 00000000000..5bed3a6d2c0 --- /dev/null +++ b/app/assets/stylesheets/components/_container.scss @@ -0,0 +1,7 @@ +.cntnr-skinny { max-width: $container-skinny-width; } +.cntnr-xskinny { max-width: $container-xskinny-width; } +.cntnr-xxskinny { max-width: $container-xxskinny-width; } + +@media #{$breakpoint-sm} { + .cntnr-xxskinny { max-width: $container-xskinny-width; } +} diff --git a/app/assets/stylesheets/components/_footer.scss b/app/assets/stylesheets/components/_footer.scss new file mode 100644 index 00000000000..4b9e8042f51 --- /dev/null +++ b/app/assets/stylesheets/components/_footer.scss @@ -0,0 +1,31 @@ +// 1. Avoid the IE 10-11 `min-height` bug. +// 2. Set `flex-shrink` to `0` to prevent some browsers from +// letting these items shrink to smaller than their content's default +// minimum size. See http://bit.ly/1Mn35US for details. +// 3. Use `%` instead of `vh` since `vh` is buggy in older mobile Safari. +html { + height: 100%; +} + +.site { + display: flex; + flex-direction: column; + height: 100%; // 1, 3 +} + +.footer { + flex: none; // 2 + position: relative; +} + +.site-wrap { + flex: 1 0 auto; // 2 + width: 100%; +} + +.site-wrap::after { + content: '\00a0'; //   + display: block; + height: 0; + visibility: hidden; +} diff --git a/app/assets/stylesheets/components/_form.scss b/app/assets/stylesheets/components/_form.scss new file mode 100644 index 00000000000..71df7c2435c --- /dev/null +++ b/app/assets/stylesheets/components/_form.scss @@ -0,0 +1,272 @@ +$radio-checkbox-space: 1.5rem; + +@media #{$breakpoint-sm} { + input, + select, + textarea { + font-size: $form-field-font-size-sm; + } +} + +label { + display: inline-block; + margin-bottom: $space-tiny; +} + +textarea { + resize: vertical; +} + +.field { + background-color: #f2f9ff; + color: $gray; + font-weight: $bold-font-weight; + + &[type=number], + &.phone { + font-family: $monospace-font-family; + } + + &:focus, + &.is-focused { + border-color: $field-focus-color; + box-shadow: 0 0 0 2px rgba($field-focus-color, .5); + outline: none; + } + + &:invalid, + &.is-error { + border-color: $border-color; + } +} + +.radio-extra { + margin-left: $radio-checkbox-space; +} + + +// error states +.has-error input { + background-image: url(image-path('alert/error.svg')); + background-position: center right $form-field-padding-x; + background-repeat: no-repeat; + background-size: 1rem 1rem; + border-color: $red; + + &.date, + &.select { + background-image: none; + } + + &:focus { + border-color: $red; + box-shadow: 0 0 0 2px rgba($red, .5); + } +} + +// hide number field input spin box as per: +// http://stackoverflow.com/questions/3790935/can-i-hide-the-html5-number-input-s-spin-box +// and added .mfa class selector as per CodeClimate warning to: +// 'Avoid qualifying attribute selectors with an element.' +.mfa { + -moz-appearance: textfield; +} + +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + + +// wtf-forms.css +.checkbox, +.radio { + cursor: pointer; + padding-left: 24px; + position: relative; +} + +.checkbox input, +.radio input, { + opacity: 0; + position: absolute; + z-index: -1; +} + +// scss-lint:disable VendorPrefix +.indicator { + background-position: center center; + background-repeat: no-repeat; + background-size: .5rem .5rem; + box-sizing: border-box; + display: block; + font-size: 65%; + height: 1rem; + left: 0; + line-height: 1rem; + position: absolute; + text-align: center; + top: .25rem; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none; + width: 1rem; +} + +.checkbox input:focus ~ .indicator, +.radio input:focus ~ .indicator { + box-shadow: 0 0 0 2px rgba($blue, .5); +} + +.checkbox input:checked ~ .indicator, +.radio input:checked ~ .indicator { + background-color: $blue; + color: $white; +} + +.checkbox input:active ~ .indicator, +.radio input:active ~ .indicator { + background-color: $blue-light; + color: $white; +} + +.checkbox .indicator { + background-color: $white; + border: $border-width solid $blue; + border-radius: .25rem; +} + +.checkbox input:checked ~ .indicator { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNy4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgOCA4IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA4IDgiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTTYuNCwxTDUuNywxLjdMMi45LDQuNUwyLjEsMy43TDEuNCwzTDAsNC40bDAuNywwLjdsMS41LDEuNWwwLjcsMC43bDAuNy0wLjdsMy41LTMuNWwwLjctMC43TDYuNCwxTDYuNCwxeiINCgkvPg0KPC9zdmc+DQo=); +} + +.radio .indicator { + background-color: #f2f9ff; + border: $border-width solid $blue; + border-radius: 50%; +} + +.radio input:checked ~ .indicator { + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNy4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgOCA4IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA4IDgiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPHBhdGggZmlsbD0iI0ZGRkZGRiIgZD0iTTQsMUMyLjMsMSwxLDIuMywxLDRzMS4zLDMsMywzczMtMS4zLDMtM1M1LjcsMSw0LDF6Ii8+DQo8L3N2Zz4NCg==); +} + +.radio input:disabled ~ .indicator { + background-color: $gray-light; + border-color: $gray; +} + +.select-alt { + color: $white; + display: inline-block; + position: relative; + width: 100%; + + select { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + background-color: $navy; + border-right: 1px solid $blue; + color: $white; + cursor: pointer; + display: inline-block; + font-weight: normal; + line-height: 1.5; + padding-right: 2.25rem; + width: 100%; + } + + // Undo the Firefox inner focus ring + select:focus:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 $white; + } + + select:active { + background-color: $navy; + color: $white; + } + + // Hide the arrow in IE10 and up + select::-ms-expand { + display: none; + } + + // Separator + &::before { + border-right: 1px solid $blue; + content: ''; + height: -moz-calc(3rem - 2px); + height: -webkit-calc(3rem - 2px); + height: calc(3rem - 2px); + position: absolute; + right: 3rem; + top: 1px; + width: 0; + } + + // Dropdown arrow + &::after { + border-bottom: .35rem solid transparent; + border-left: .35rem solid transparent; + border-right: .35rem solid transparent; + border-top: .35rem solid; + content: ''; + display: inline-block; + height: 0; + margin-top: -.15rem; + pointer-events: none; + position: absolute; + right: 1.25rem; + top: 50%; + width: 0; + } +} + +// Media query to target Firefox only +@-moz-document url-prefix() { + // Firefox hack to hide the arrow + .select-alt select { + padding-right: 1rem; + text-indent: .01px; + text-overflow: ''; + } + + //