├── app ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── concerns │ │ └── .keep │ └── braintree_gateway.rb ├── assets │ ├── images │ │ ├── .keep │ │ ├── favicon.png │ │ ├── fail.svg │ │ └── success.svg │ ├── fonts │ │ ├── bt-mono-Bold.eot │ │ ├── bt-mono-Bold.woff │ │ ├── bt-mono-Bold.woff2 │ │ ├── bt-mono-Medium.eot │ │ ├── bt-mono-Medium.woff │ │ ├── bt-mono-Medium.woff2 │ │ ├── bt-mono-Regular.eot │ │ ├── bt-mono-Regular.woff │ │ ├── bt-mono-Regular.woff2 │ │ ├── OpenSans-Bold-webfont.eot │ │ ├── OpenSans-Bold-webfont.ttf │ │ ├── OpenSans-Bold-webfont.woff │ │ ├── OpenSans-Light-webfont.eot │ │ ├── OpenSans-Light-webfont.ttf │ │ ├── OpenSans-Light-webfont.woff │ │ ├── OpenSans-Regular-webfont.eot │ │ ├── OpenSans-Regular-webfont.ttf │ │ ├── OpenSans-Regular-webfont.woff │ │ ├── OpenSans-Semibold-webfont.eot │ │ ├── OpenSans-Semibold-webfont.ttf │ │ └── OpenSans-Semibold-webfont.woff │ ├── stylesheets │ │ ├── checkout.scss │ │ ├── application.css │ │ ├── overrides.css.erb │ │ ├── app.css.map │ │ └── app.css.erb │ └── javascripts │ │ ├── checkout.coffee │ │ ├── demo.js │ │ └── application.js ├── controllers │ ├── concerns │ │ └── .keep │ ├── application_controller.rb │ └── checkouts_controller.rb ├── helpers │ ├── checkout_helper.rb │ └── application_helper.rb └── views │ ├── layouts │ ├── _notifications.html.erb │ └── application.html.erb │ └── checkouts │ ├── _paypal_account_details.html.erb │ ├── _credit_card_details.html.erb │ ├── new.html.erb │ └── show.html.erb ├── lib ├── assets │ └── .keep └── tasks │ ├── .keep │ └── rspec.rake ├── public ├── favicon.ico ├── robots.txt ├── 500.html ├── 422.html └── 404.html ├── .ruby-version ├── vendor └── assets │ ├── javascripts │ └── .keep │ └── stylesheets │ └── .keep ├── .ruby-gemset ├── Procfile ├── bin ├── rake ├── bundle ├── rails ├── yarn ├── spring ├── update └── setup ├── spec ├── helpers │ ├── checkout_helper_spec.rb │ └── application_helper_spec.rb ├── views │ └── checkouts │ │ ├── show.html.erb_spec.rb │ │ └── new.html.erb_spec.rb ├── models │ └── braintree_gateway_spec.rb ├── rails_helper.rb ├── integration │ └── controllers │ │ └── checkouts_controller_spec.rb ├── support │ └── mock_data.rb ├── spec_helper.rb └── controllers │ └── checkouts_controller_spec.rb ├── example.env ├── config ├── spring.rb ├── environment.rb ├── initializers │ ├── mime_types.rb │ ├── session_store.rb │ ├── filter_parameter_logging.rb │ ├── application_controller_renderer.rb │ ├── braintree.rb │ ├── cookies_serializer.rb │ ├── backtrace_silencers.rb │ ├── wrap_parameters.rb │ ├── assets.rb │ ├── inflections.rb │ └── content_security_policy.rb ├── boot.rb ├── routes.rb ├── database.yml ├── locales │ └── en.yml ├── secrets.yml ├── storage.yml ├── environments │ ├── test.rb │ ├── development.rb │ └── production.rb └── application.rb ├── config.ru ├── docker-compose.yml ├── Dockerfile ├── db ├── seeds.rb └── schema.rb ├── Rakefile ├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── app.json ├── .travis.yml ├── LICENSE ├── Gemfile ├── README.md └── Gemfile.lock /app/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.4.3 2 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | braintree_graphql_rails_example 2 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec rails server -p $PORT 2 | -------------------------------------------------------------------------------- /app/helpers/checkout_helper.rb: -------------------------------------------------------------------------------- 1 | module CheckoutHelper 2 | end 3 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /spec/helpers/checkout_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe CheckoutHelper, type: :helper do 4 | end 5 | -------------------------------------------------------------------------------- /example.env: -------------------------------------------------------------------------------- 1 | BT_PUBLIC_KEY='your braintree public key' 2 | BT_PRIVATE_KEY='your braintree private key' 3 | BT_VERSION='2018-11-11' 4 | -------------------------------------------------------------------------------- /app/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/images/favicon.png -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Bold.eot -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Bold.woff -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Bold.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Medium.eot -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Medium.woff -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Medium.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Regular.eot -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Regular.woff -------------------------------------------------------------------------------- /app/assets/fonts/bt-mono-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/bt-mono-Regular.woff2 -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | %w[ 2 | .ruby-version 3 | .rbenv-vars 4 | tmp/restart.txt 5 | tmp/caching-dev.txt 6 | ].each { |path| Spring.watch(path) } 7 | -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Bold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Bold-webfont.ttf -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Light-webfont.ttf -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Regular-webfont.ttf -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Semibold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Semibold-webfont.eot -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Semibold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Semibold-webfont.ttf -------------------------------------------------------------------------------- /app/assets/fonts/OpenSans-Semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/braintree/braintree_graphql_rails_example/HEAD/app/assets/fonts/OpenSans-Semibold-webfont.woff -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | def alert_string(alert) 3 | alert.is_a?(Array) ? safe_join(alert, "
".html_safe) : alert 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_braintree_graphql_rails_example_session' 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/checkout.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the checkout controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html 3 | root 'checkouts#new' 4 | 5 | resources :checkouts, only: [:new, :create, :show] 6 | end 7 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | web: 4 | build: . 5 | command: bin/rails server --port 4567 --binding 0.0.0.0 6 | ports: 7 | - "4567:4567" 8 | volumes: 9 | - .:/braintree_graphql_rails_example 10 | -------------------------------------------------------------------------------- /app/assets/javascripts/checkout.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | end 6 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /config/initializers/braintree.rb: -------------------------------------------------------------------------------- 1 | Dotenv.load 2 | 3 | if !ENV["BT_PUBLIC_KEY"] || !ENV["BT_PRIVATE_KEY"] || !ENV["BT_VERSION"] 4 | raise "Cannot find necessary environmental variables. See https://github.com/braintree/braintree_graphql_rails_example#setup-instructions for instructions"; 5 | end 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.3.1-onbuild 2 | 3 | RUN apt-get update && apt-get install -y build-essential nodejs 4 | 5 | ENV APP_HOME /braintree_graphql_rails_example 6 | RUN mkdir $APP_HOME 7 | WORKDIR $APP_HOME 8 | 9 | ADD Gemfile* $APP_HOME/ 10 | RUN bundle install 11 | 12 | ADD . $APP_HOME 13 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /app/views/layouts/_notifications.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <% if flash[:error] %> 3 |
4 | 5 | <%= alert_string(flash[:error]) %> 6 | 7 |
8 | <% end %> 9 |
10 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path('..', __dir__) 3 | Dir.chdir(APP_ROOT) do 4 | begin 5 | exec "yarnpkg", *ARGV 6 | rescue Errno::ENOENT 7 | $stderr.puts "Yarn executable was not detected in the system." 8 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 9 | exit 1 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) 7 | # Mayor.create(name: 'Emanuel', city: cities.first) 8 | -------------------------------------------------------------------------------- /lib/tasks/rspec.rake: -------------------------------------------------------------------------------- 1 | unless Rails.env.production? 2 | namespace :spec do 3 | desc "Run all specs in the spec directory (excluding integration specs)" 4 | RSpec::Core::RakeTask.new(:unit) do |task| 5 | task.pattern = FileList["spec/**/*_spec.rb"].exclude("spec/integration/**/*_spec.rb") 6 | end 7 | end 8 | 9 | Rake::Task[:default].prerequisites.clear 10 | task :default => "spec:unit" 11 | end 12 | -------------------------------------------------------------------------------- /app/assets/javascripts/demo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function () { 4 | var amount = document.querySelector('#amount'); 5 | var amountLabel = document.querySelector('label[for="amount"]'); 6 | 7 | amount.addEventListener('focus', function () { 8 | amountLabel.className = 'has-focus'; 9 | }, false); 10 | amount.addEventListener('blur', function () { 11 | amountLabel.className = ''; 12 | }, false); 13 | })(); 14 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require 'sdoc' 5 | require 'rdoc/task' 6 | 7 | require File.expand_path('../config/application', __FILE__) 8 | 9 | Rails.application.load_tasks 10 | 11 | 12 | RDoc::Task.new do |rdoc| 13 | rdoc.rdoc_dir = 'doc/rdoc' 14 | rdoc.options << '--format=sdoc' 15 | rdoc.template = 'rails' 16 | end 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### General information 2 | 3 | * Environment: 4 | * Language, language version, and OS: 5 | 6 | ### Issue description 7 | 8 | 9 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require 'rubygems' 8 | require 'bundler' 9 | 10 | if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)) 11 | Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) } 12 | gem 'spring', match[1] 13 | require 'spring/binstub' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /spec/helpers/application_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe ApplicationHelper, type: :helper do 4 | describe "#alert_string" do 5 | context "when given a string" do 6 | it "returns the string" do 7 | expect(alert_string("a string")).to eq("a string") 8 | end 9 | end 10 | 11 | context "when given an Array" do 12 | it "returns a string of the array elements joined with break tags" do 13 | expect(alert_string(["item1", "item2"])).to eq("item1
item2") 14 | end 15 | end 16 | end 17 | end 18 | 19 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | # Add Yarn node_modules folder to the asset load path. 9 | Rails.application.config.assets.paths << Rails.root.join('node_modules') 10 | 11 | # Precompile additional assets. 12 | # application.js, application.css, and all non-JS/CSS in the app/assets 13 | # folder are already added. 14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 15 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | pool: 5 9 | timeout: 5000 10 | 11 | development: 12 | <<: *default 13 | adapter: sqlite3 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | adapter: sqlite3 22 | database: db/test.sqlite3 23 | 24 | production: 25 | <<: *default 26 | adapter: postgresql 27 | database: bt_example_production 28 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require jquery 14 | //= require jquery_ujs 15 | //= require turbolinks 16 | //= require_tree . 17 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any styles 10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new 11 | * file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 0) do 15 | 16 | end 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbc 2 | capybara-*.html 3 | .rspec 4 | .env 5 | /log 6 | /tmp 7 | /db/*.sqlite3 8 | /db/*.sqlite3-journal 9 | /public/system 10 | /coverage/ 11 | /spec/tmp 12 | **.orig 13 | rerun.txt 14 | pickle-email-*.html 15 | 16 | # TODO Comment out these rules if you are OK with secrets being uploaded to the repo 17 | # config/initializers/secret_token.rb 18 | # config/secrets.yml 19 | 20 | ## Environment normalisation: 21 | /.bundle 22 | /vendor/bundle 23 | 24 | # these should all be checked in to normalise the environment: 25 | # Gemfile.lock, .ruby-version, .ruby-gemset 26 | 27 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 28 | .rvmrc 29 | 30 | # if using bower-rails ignore default bower_components path bower.json files 31 | /vendor/assets/bower_components 32 | *.bowerrc 33 | bower.json 34 | 35 | # Ignore pow environment settings 36 | .powenv 37 | -------------------------------------------------------------------------------- /app/views/checkouts/_paypal_account_details.html.erb: -------------------------------------------------------------------------------- 1 | <% paypal_account = locals[:paypal_account] %> 2 |
by PayPal Account
3 | 4 | 5 | <% if paypal_account["payer"] %> 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | <% end %> 23 | 24 | 25 | 26 | 27 | 28 |
email<%= paypal_account["payer"]["email"] %>
payer ID<%= paypal_account["payer"]["payerId"] %>
first name<%= paypal_account["payer"]["firstName"] %>
last name<%= paypal_account["payer"]["lastName"] %>
payer status<%= paypal_account["payerStatus"] %>
29 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Braintree GraphQL Example in Rails", 3 | "description": "An example Braintree integration with the GraphQL API using Ruby on Rails", 4 | "keywords": ["braintree", "graphql", "ruby", "rails"], 5 | "website": "https://www.braintreepayments.com", 6 | "repository": "https://github.com/braintree/braintree_graphql_rails_example", 7 | "logo": "https://avatars1.githubusercontent.com/u/3453", 8 | "success_url": "/", 9 | "env": { 10 | "BT_PUBLIC_KEY": { 11 | "description": "Your Braintree Public Key", 12 | "required": true 13 | }, 14 | "BT_PRIVATE_KEY": { 15 | "description": "Your Braintree Private Key", 16 | "required": true 17 | }, 18 | "BT_VERSION": { 19 | "description": "A date in the format YYYY-MM-DD (we recommend using the date you started using the GraphQL API)", 20 | "required": true 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /spec/views/checkouts/show.html.erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | require 'support/mock_data' 3 | 4 | RSpec.describe "checkouts/show.html.erb", type: :view do 5 | include_context 'mock_data' 6 | 7 | before(:each) do 8 | assign(:transaction, mock_successful_fetched_transaction["data"]["transaction"]) 9 | end 10 | 11 | it "renders the Transaction header" do 12 | render 13 | expect(rendered).to match /Transaction/ 14 | end 15 | 16 | it "includes the transaction id" do 17 | render 18 | expect(rendered).to match /my_id/ 19 | end 20 | 21 | it "includes the Credit Card Details" do 22 | render 23 | expect(rendered).to match /Payment/ 24 | end 25 | 26 | it "includes the 'Return to checkout page' link" do 27 | render 28 | expect(rendered).to match /Test Another Transaction/ 29 | expect(rendered).to match /checkouts\/new/ 30 | end 31 | end 32 | 33 | -------------------------------------------------------------------------------- /bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | include FileUtils 4 | 5 | # path to your application root. 6 | APP_ROOT = File.expand_path('..', __dir__) 7 | 8 | def system!(*args) 9 | system(*args) || abort("\n== Command #{args} failed ==") 10 | end 11 | 12 | chdir APP_ROOT do 13 | # This script is a way to update your development environment automatically. 14 | # Add necessary update steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies if using Yarn 21 | # system('bin/yarn') 22 | 23 | puts "\n== Updating database ==" 24 | system! 'bin/rails db:migrate' 25 | 26 | puts "\n== Removing old logs and tempfiles ==" 27 | system! 'bin/rails log:clear tmp:clear' 28 | 29 | puts "\n== Restarting application server ==" 30 | system! 'bin/rails restart' 31 | end 32 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.5.8 4 | before_install: 5 | - gem update --system 6 | - gem install bundler 7 | notifications: 8 | email: false 9 | slack: 10 | on_success: change 11 | on_failure: always 12 | on_pull_requests: false 13 | rooms: 14 | - secure: kRh0VhfoeS19wDeckS1go0272Y994UXPu59/Gmbc5APfEhM3UmqV84bSaJSN+gOqnFh5yJvUTdlj9dOM7CjtvcjUFSrRx1SXhhMDDPB9+iZCSQ7HfGljob4cLP6N26UZicZ2UtzujuDu1OpmhKqoosepzIRBaFM8i3Wa6uLtB6H+APFLtiuVNIpu/YaQIjrOjylZeafX7Usi5dWrs8cxtTJmwHT7xyTNm8nt5gQx+Gr5dFT6LAEsdfZBqSVK4fGipraLG9nb3jpRmWr5oRnGJ/0+DSUJKcv5XuzkCdbIVdnXxARXL1V32SVJFF1sfzE34Co5XriLqVF0WoIN+WEpPE4Qu7YR5SvwsXuE2/S4fW/cZ7sla1q28EKxN13IC5Lkn3VaRxfy4gn0iG9oOpEbmu9sHwEvFWuWxuU0bjIKsqzzAv3Yc1WLnyODxYpxEDoWZESYat3dB514yPmH10EVxlIurxApsDPnVGL31Akvr6/UOC43z6rP6YWrBmExc2T3QqpI1+iHaMyLaA4Y2sbfL6DRusmM6RQgVp3jJgJPT7ko8OMPzTzE0/X0NTtOHH8BS1YfkfGeYxts1CElZIol85EwFNwVnsoCMQohC2RccjFhxdfXCjusagd+7Sfh8sPz5R5BUE2kuJDUAZhERKG0axzfpr3xCWPNTfFsSqv3Zjg= 15 | -------------------------------------------------------------------------------- /spec/views/checkouts/new.html.erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe "checkouts/new.html.erb", type: :view do 4 | it "renders the checkout header" do 5 | render 6 | expect(rendered).to match /Let's test a transaction/ 7 | end 8 | 9 | it "includes the Braintree client token" do 10 | assign(:client_token, "your_client_token") 11 | render 12 | expect(rendered).to match /your_client_token/ 13 | end 14 | 15 | it "includes the checkout form" do 16 | render 17 | expect(rendered).to match /
12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at http://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BraintreeGraphQLRailsExample 5 | 6 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> 7 | <%= favicon_link_tag "favicon.png" %> 8 | <%= csrf_meta_tags %> 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 | PSEUDOSHOP 17 |
18 | 19 |
20 | Braintree 21 |
22 |
23 |
24 |
25 | 26 | <%= render partial: "layouts/notifications" %> 27 |
28 | 29 | <%= yield %> 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: a55a5164eed643f77d905e05dadb4b8b8db443920597954fad04284c65a1ba01bb3df923d3470cfda163fbd26e17f79f406d721f8b8db5cdc42774abc32257d1 15 | 16 | test: 17 | secret_key_base: 07f7d28035c5cfe56b55a6b246eefc0b7a26489f68e4b547fc9f10733d0c982d3ac99b3a523204e7f8576262a9a42cc716dfcfca333162294399afa1df12feb5 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | include FileUtils 4 | 5 | # path to your application root. 6 | APP_ROOT = File.expand_path('..', __dir__) 7 | 8 | def system!(*args) 9 | system(*args) || abort("\n== Command #{args} failed ==") 10 | end 11 | 12 | chdir APP_ROOT do 13 | # This script is a starting point to setup your application. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies if using Yarn 21 | # system('bin/yarn') 22 | 23 | # puts "\n== Copying sample files ==" 24 | # unless File.exist?('config/database.yml') 25 | # cp 'config/database.yml.sample', 'config/database.yml' 26 | # end 27 | 28 | puts "\n== Preparing database ==" 29 | system! 'bin/rails db:setup' 30 | 31 | puts "\n== Removing old logs and tempfiles ==" 32 | system! 'bin/rails log:clear tmp:clear' 33 | 34 | puts "\n== Restarting application server ==" 35 | system! 'bin/rails restart' 36 | end 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Braintree 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /app/assets/images/fail.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | check copy 5 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy 4 | # For further information see the following documentation 5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | # Rails.application.config.content_security_policy do |policy| 8 | # policy.default_src :self, :https 9 | # policy.font_src :self, :https, :data 10 | # policy.img_src :self, :https, :data 11 | # policy.object_src :none 12 | # policy.script_src :self, :https 13 | # policy.style_src :self, :https 14 | 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | 19 | # If you are using UJS then enable automatic nonce generation 20 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } 21 | 22 | # Report CSP violations to a specified URI 23 | # For further information see the following documentation: 24 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 25 | # Rails.application.config.content_security_policy_report_only = true 26 | -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket 23 | 24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /app/views/checkouts/_credit_card_details.html.erb: -------------------------------------------------------------------------------- 1 | <% credit_card = locals[:credit_card] %> 2 |
by Credit Card
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | <% if credit_card["origin"] %> 36 | 37 | <% else %> 38 | 39 | <% end %> 40 | 41 | 42 |
card type<%= credit_card["brandCode"] %>
bin<%= credit_card["bin"] %>
last 4<%= credit_card["last4"] %>
expiration month<%= credit_card["expirationMonth"] %>
expiration year<%= credit_card["expirationYear"] %>
cardholder name<%= credit_card["cardholderName"] %>
card issued in<%= credit_card.fetch("binData", {})["countryOfIssuance"] %>
card sourced from<%= credit_card["origin"]["type"] %>customer entering card details directly
43 | -------------------------------------------------------------------------------- /spec/models/braintree_gateway_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | require 'support/mock_data' 3 | 4 | RSpec.describe BraintreeGateway do 5 | include_context 'mock_data' 6 | 7 | before do 8 | mock_requester = class_double(HTTParty) 9 | @mock_response = double("Response") 10 | allow(mock_requester).to receive(:post).and_return(@mock_response) 11 | 12 | @gateway = BraintreeGateway.new(mock_requester) 13 | end 14 | 15 | describe "error handling" do 16 | it "throws a GraphQLError for nil data" do 17 | empty = {"data" => nil, "errors" => [{"message" => "an error message"}], "extensions" => {"requestId" => "not-a-real-request-1"}} 18 | expect(@mock_response).to receive(:parsed_response).and_return(empty) 19 | 20 | expect { @gateway.ping }.to raise_exception(BraintreeGateway::GraphQLError) 21 | end 22 | 23 | it "throws a GraphQLError when the expected data key is nil" do 24 | empty = {"data" => {"ping" => nil}, "errors" => [{"message" => "another error message"}], "extensions" => {"requestId" => "not-a-real-request-2"}} 25 | expect(@mock_response).to receive(:parsed_response).and_return(empty) 26 | 27 | expect { @gateway.ping }.to raise_exception(BraintreeGateway::GraphQLError) 28 | end 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /app/assets/images/success.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | check copy 3 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure public file server for tests with Cache-Control for performance. 16 | config.public_file_server.enabled = true 17 | config.public_file_server.headers = { 18 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}" 19 | } 20 | 21 | # Show full error reports and disable caching. 22 | config.consider_all_requests_local = true 23 | config.action_controller.perform_caching = false 24 | 25 | # Raise exceptions instead of rendering exception templates. 26 | config.action_dispatch.show_exceptions = false 27 | 28 | # Disable request forgery protection in test environment. 29 | config.action_controller.allow_forgery_protection = false 30 | 31 | # Store uploaded files on the local file system in a temporary directory 32 | config.active_storage.service = :test 33 | 34 | config.action_mailer.perform_caching = false 35 | 36 | # Tell Action Mailer not to deliver emails to the real world. 37 | # The :test delivery method accumulates sent emails in the 38 | # ActionMailer::Base.deliveries array. 39 | config.action_mailer.delivery_method = :test 40 | 41 | # Print deprecation notices to the stderr. 42 | config.active_support.deprecation = :stderr 43 | 44 | # Raises error for missing translations 45 | # config.action_view.raise_on_missing_translations = true 46 | end 47 | -------------------------------------------------------------------------------- /app/views/checkouts/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |

Hi,
Let's test a transaction

7 |

8 | Make a test payment with Braintree using PayPal or a card 9 |

10 |
11 | 12 | <%= form_tag("/checkouts", method: "post", id: "payment-form") do %> 13 |
14 | 20 | 21 |
22 |
23 |
24 |
25 | 26 | 27 | 28 | <% end %> 29 | 30 |
31 |
32 |
33 | 34 | 35 | 62 | <%= javascript_include_tag 'application', 'data-turbolinks-suppress-warning' => true, 'data-turbolinks-track' => true %> 63 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative 'boot' 2 | 3 | require "rails" 4 | # Pick the frameworks you want: 5 | require "active_model/railtie" 6 | require "active_job/railtie" 7 | require "active_record/railtie" 8 | require "active_storage/engine" 9 | require "action_controller/railtie" 10 | require "action_mailer/railtie" 11 | require "action_view/railtie" 12 | # require "action_cable/engine" 13 | require "sprockets/railtie" 14 | require "rails/test_unit/railtie" 15 | 16 | # Require the gems listed in Gemfile, including any gems 17 | # you've limited to :test, :development, or :production. 18 | Bundler.require(*Rails.groups) 19 | 20 | module BraintreeGraphQLRailsExample 21 | class Application < Rails::Application 22 | # Initialize configuration defaults for originally generated Rails version. 23 | config.load_defaults 5.2 24 | Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true 25 | # New for Rails 5.2: 26 | # Make Active Record use stable #cache_key alongside new #cache_version method. 27 | # This is needed for recyclable cache keys. 28 | Rails.application.config.active_record.cache_versioning = true 29 | # Use AES-256-GCM authenticated encryption for encrypted cookies. 30 | Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true 31 | # Add default protection from forgery to ActionController::Base instead of in 32 | # ApplicationController 33 | Rails.application.config.action_controller.default_protect_from_forgery = true 34 | # Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. 35 | Rails.application.config.active_support.use_sha1_digests = true 36 | # Make `form_with` generate id attributes for any generated HTML tags. 37 | Rails.application.config.action_view.form_with_generates_ids = true 38 | # Settings in config/environments/* take precedence over those specified here. 39 | # Application configuration can go into files in config/initializers 40 | # -- all .rb files in that directory are automatically loaded after loading 41 | # the framework and any gems in your application. 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby '>= 2.5.0' 4 | 5 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 6 | gem 'rails', '5.2.4.6' 7 | # Bootsnap for Rails 5 to optimize and cache expensive computations, Read more: https://github.com/Shopify/bootsnap 8 | gem 'bootsnap', '1.3.2' 9 | # Use SCSS for stylesheets 10 | gem 'sass-rails', '~> 5.0' 11 | # Use Uglifier as compressor for JavaScript assets 12 | gem 'uglifier', '>= 1.3.0' 13 | # Use CoffeeScript for .coffee assets and views 14 | gem 'coffee-rails', '~> 4.2.2' 15 | # See https://github.com/rails/execjs#readme for more supported runtimes 16 | # gem 'therubyracer', platforms: :ruby 17 | 18 | # Use jquery as the JavaScript library 19 | gem 'jquery-rails' 20 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks 21 | gem 'turbolinks' 22 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 23 | gem 'jbuilder', '~> 2.0' 24 | # bundle exec rake rdoc generates the API under doc/api. 25 | gem 'sdoc', '>= 2.2.0', group: :doc 26 | 27 | gem 'dotenv', '~> 2.0' 28 | 29 | gem 'httparty', '~> 0.16.2' 30 | 31 | gem 'nokogiri', '>= 1.11.4' 32 | 33 | group :development, :test do 34 | # Use sqlite in development and test for ease of setup 35 | gem 'sqlite3' 36 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 37 | gem 'byebug' 38 | # Only running rspec in development and test, rails-controller-testing gem needed with Rails 5 39 | gem 'rspec-rails' 40 | gem 'rails-controller-testing' 41 | end 42 | 43 | group :production do 44 | # Use postgres in production as many prod environments don't support sqlite (e.g. Heroku) 45 | gem 'pg', '~> 0.21.0' 46 | # Use Heroku asset addressing scheme and logging in production; should not affect other environments 47 | gem 'rails_12factor' 48 | end 49 | 50 | group :development do 51 | # Access an IRB console on exception pages or by using <%= console %> in views 52 | gem 'web-console', '~> 2.0' 53 | 54 | # The Listen gem listens to file modifications and notifies you about the changes. 55 | gem 'listen', '>= 3.1.5' 56 | 57 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 58 | gem 'spring' 59 | end 60 | -------------------------------------------------------------------------------- /app/controllers/checkouts_controller.rb: -------------------------------------------------------------------------------- 1 | class CheckoutsController < ApplicationController 2 | TRANSACTION_SUCCESS_STATUSES = [ 3 | "AUTHORIZED", 4 | "AUTHORIZING", 5 | "SETTLED", 6 | "SETTLEMENT_PENDING", 7 | "SETTLING", 8 | "SUBMITTED_FOR_SETTLEMENT", 9 | ] 10 | 11 | def new 12 | @client_token = gateway.client_token.dig("data", "createClientToken", "clientToken") 13 | end 14 | 15 | def show 16 | begin 17 | @transaction = gateway.node_fetch_transaction(params[:id]).fetch("data", {})["transaction"] 18 | @result = _create_status_result_hash(@transaction) 19 | rescue BraintreeGateway::GraphQLError => error 20 | _flash_errors(error) 21 | redirect_to new_checkout_path 22 | end 23 | end 24 | 25 | def create 26 | amount = params["amount"] # In production you should not take amounts directly from clients 27 | nonce = params["payment_method_nonce"] 28 | 29 | begin 30 | result = gateway.transaction(nonce, amount) 31 | id = result.dig("data", "chargePaymentMethod", "transaction", "id") 32 | 33 | if id 34 | redirect_to checkout_path(id) 35 | else 36 | raise BraintreeGateway::GraphQLError.new(result) 37 | end 38 | rescue BraintreeGateway::GraphQLError => error 39 | _flash_errors(error) 40 | redirect_to new_checkout_path 41 | end 42 | end 43 | 44 | def _create_status_result_hash(transaction) 45 | status = transaction["status"] 46 | 47 | if TRANSACTION_SUCCESS_STATUSES.include? status 48 | result_hash = { 49 | :header => "Sweet Success!", 50 | :icon => "success", 51 | :message => "Your test transaction has been successfully processed. See the Braintree API response and try again." 52 | } 53 | else 54 | result_hash = { 55 | :header => "Transaction Unsuccessful", 56 | :icon => "fail", 57 | :message => "Your test transaction has a status of #{status}. See the Braintree API response and try again." 58 | } 59 | end 60 | end 61 | 62 | def _flash_errors(error) 63 | if error.messages != nil and !error.messages.empty? 64 | flash[:error] = error.messages 65 | else 66 | flash[:error] = ["Error: Something unexpected went wrong! Try again."] 67 | end 68 | end 69 | 70 | def gateway 71 | @gateway ||= BraintreeGateway.new(HTTParty) 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports. 13 | config.consider_all_requests_local = true 14 | 15 | # Enable/disable caching. By default caching is disabled. 16 | # Run rails dev:cache to toggle caching. 17 | if Rails.root.join('tmp', 'caching-dev.txt').exist? 18 | config.action_controller.perform_caching = true 19 | 20 | config.cache_store = :memory_store 21 | config.public_file_server.headers = { 22 | 'Cache-Control' => "public, max-age=#{2.days.to_i}" 23 | } 24 | else 25 | config.action_controller.perform_caching = false 26 | 27 | config.cache_store = :null_store 28 | end 29 | 30 | # Store uploaded files on the local file system (see config/storage.yml for options) 31 | config.active_storage.service = :local 32 | 33 | # Don't care if the mailer can't send. 34 | config.action_mailer.raise_delivery_errors = false 35 | 36 | config.action_mailer.perform_caching = false 37 | 38 | # Print deprecation notices to the Rails logger. 39 | config.active_support.deprecation = :log 40 | 41 | # Raise an error on page load if there are pending migrations. 42 | config.active_record.migration_error = :page_load 43 | 44 | # Highlight code that triggered database queries in logs. 45 | config.active_record.verbose_query_logs = true 46 | 47 | # Debug mode disables concatenation and preprocessing of assets. 48 | # This option may cause significant delays in view rendering with a large 49 | # number of complex assets. 50 | config.assets.debug = true 51 | 52 | # Suppress logger output for asset requests. 53 | config.assets.quiet = true 54 | 55 | # Raises error for missing translations 56 | # config.action_view.raise_on_missing_translations = true 57 | 58 | # Use an evented file watcher to asynchronously detect changes in source code, 59 | # routes, locales, etc. This feature depends on the listen gem. 60 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker 61 | end 62 | -------------------------------------------------------------------------------- /spec/rails_helper.rb: -------------------------------------------------------------------------------- 1 | # This file is copied to spec/ when you run 'rails generate rspec:install' 2 | ENV['RAILS_ENV'] ||= 'test' 3 | require File.expand_path('../../config/environment', __FILE__) 4 | # Prevent database truncation if the environment is production 5 | abort("The Rails environment is running in production mode!") if Rails.env.production? 6 | require 'spec_helper' 7 | require 'rspec/rails' 8 | # Add additional requires below this line. Rails is not loaded until this point! 9 | 10 | # Requires supporting ruby files with custom matchers and macros, etc, in 11 | # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are 12 | # run as spec files by default. This means that files in spec/support that end 13 | # in _spec.rb will both be required and run as specs, causing the specs to be 14 | # run twice. It is recommended that you do not name files matching this glob to 15 | # end with _spec.rb. You can configure this pattern with the --pattern 16 | # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. 17 | # 18 | # The following line is provided for convenience purposes. It has the downside 19 | # of increasing the boot-up time by auto-requiring all files in the support 20 | # directory. Alternatively, in the individual `*_spec.rb` files, manually 21 | # require only the support files necessary. 22 | # 23 | # Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } 24 | 25 | # Checks for pending migrations before tests are run. 26 | # If you are not using ActiveRecord, you can remove this line. 27 | ActiveRecord::Migration.maintain_test_schema! 28 | 29 | RSpec.configure do |config| 30 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 31 | config.fixture_path = "#{::Rails.root}/spec/fixtures" 32 | 33 | # If you're not using ActiveRecord, or you'd prefer not to run each of your 34 | # examples within a transaction, remove the following line or assign false 35 | # instead of true. 36 | config.use_transactional_fixtures = true 37 | 38 | # RSpec Rails can automatically mix in different behaviours to your tests 39 | # based on their file location, for example enabling you to call `get` and 40 | # `post` in specs under `spec/controllers`. 41 | # 42 | # You can disable this behaviour by removing the line below, and instead 43 | # explicitly tag your specs with their type, e.g.: 44 | # 45 | # RSpec.describe UsersController, :type => :controller do 46 | # # ... 47 | # end 48 | # 49 | # The different available types are documented in the features, such as in 50 | # https://relishapp.com/rspec/rspec-rails/docs 51 | config.infer_spec_type_from_file_location! 52 | end 53 | -------------------------------------------------------------------------------- /spec/integration/controllers/checkouts_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'rails_helper' 3 | 4 | RSpec.describe CheckoutsController, type: :controller do 5 | render_views 6 | 7 | let!(:random) { Random.new } 8 | 9 | describe "GET #new" do 10 | it "retrieves the Braintree client token and adds it to the page" do 11 | get :new 12 | client_token = assigns(:client_token) 13 | expect(client_token).to_not be_nil 14 | expect(response.body).to match /#{client_token}/ 15 | end 16 | end 17 | 18 | describe "GET #show" do 19 | let(:gateway) { 20 | Braintree::Gateway.new( 21 | :environment => ENV["BT_ENVIRONMENT"].to_sym, 22 | :merchant_id => ENV["BT_MERCHANT_ID"], 23 | :public_key => ENV["BT_PUBLIC_KEY"], 24 | :private_key => ENV["BT_PRIVATE_KEY"], 25 | ) 26 | } 27 | 28 | it "retrieves the Braintree transaction and displays its attributes" do 29 | # Using a random amount to prevent duplicate checking errors 30 | amount = "#{random.rand(100)}.#{random.rand(100)}" 31 | result = BraintreeGateway.new(HTTParty).transaction("fake-valid-nonce", amount) 32 | expect(result["data"]["chargePaymentMethod"]).not_to be_nil 33 | 34 | transaction = result["data"]["chargePaymentMethod"]["transaction"] 35 | 36 | get :show, params: { id: transaction["id"] } 37 | 38 | expect(response).to have_http_status(:success) 39 | expect(response.body).to match Regexp.new(transaction["id"]) 40 | expect(response.body).to match Regexp.new(amount) 41 | expect(response.body).to match "SUBMITTED_FOR_SETTLEMENT" 42 | end 43 | end 44 | 45 | describe "POST #create" do 46 | it "creates a transaction and redirects to checkouts#show" do 47 | amount = "#{random.rand(100)}.#{random.rand(100)}" 48 | post :create, params: { payment_method_nonce: "fake-valid-nonce", amount: amount } 49 | 50 | expect(response).not_to redirect_to(new_checkout_path) 51 | expect(response).to redirect_to(/\/checkouts\/[\w+]/) 52 | end 53 | 54 | context "when it's unsuccessful" do 55 | it "creates a transaction and displays status when there are processor errors" do 56 | amount = "2000" 57 | post :create, params: { payment_method_nonce: "fake-valid-nonce", amount: amount } 58 | 59 | expect(response).not_to redirect_to(new_checkout_path) 60 | expect(response).to redirect_to(/\/checkouts\/[\w+]/) 61 | end 62 | 63 | it "redirects to the new_checkout_path when the transaction was invalid" do 64 | amount = "#{random.rand(100)}.#{random.rand(100)}" 65 | post :create, params: { payment_method_nonce: "fake-consumed-nonce", amount: amount } 66 | 67 | expect(response).to redirect_to(new_checkout_path) 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /app/views/checkouts/show.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <% if @result %> 5 |
6 | alt=""> 7 |
8 | 9 |

<%= @result[:header] %>

10 |
11 |

<%= @result[:message] %>

12 |
13 | <% else %> 14 |
15 |

Test another transaction or see the Braintree API response.

16 |
17 | 18 | <% end %> 19 | 20 |
21 | 22 | Test Another Transaction 23 | 24 |
25 |
26 |
27 |
28 | 29 | 88 | -------------------------------------------------------------------------------- /app/assets/stylesheets/overrides.css.erb: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Open Sans light'; 3 | src: url('<%= asset_path("OpenSans-Light-webfont.eot") %>'); 4 | src: url('<%= asset_path("OpenSans-Light-webfont.eot") %>?#iefix') format("embedded-opentype"), url('<%= asset_path("OpenSans-Light-webfont.woff") %>') format("woff"), url('<%= asset_path("OpenSans-Light-webfont.ttf") %>') format("truetype"), url('<%= asset_path("OpenSans-Light-webfont.svg") %>#open_sansbold') format("svg"); 5 | } 6 | @font-face { 7 | font-family: 'Open Sans regular'; 8 | src: url('<%= asset_path("OpenSans-Regular-webfont.eot") %>'); 9 | src: url('<%= asset_path("OpenSans-Regular-webfont.eot") %>?#iefix') format("embedded-opentype"), url('<%= asset_path("OpenSans-Regular-webfont.woff") %>') format("woff"), url('<%= asset_path("OpenSans-Regular-webfont.ttf") %>') format("truetype"), url('<%= asset_path("OpenSans-Regular-webfont.svg") %>#open_sansregular') format("svg"); 10 | } 11 | @font-face { 12 | font-family: 'Open Sans semibold'; 13 | src: url('<%= asset_path("OpenSans-Semibold-webfont.eot") %>'); 14 | src: url('<%= asset_path("OpenSans-Semibold-webfont.eot") %>?#iefix') format("embedded-opentype"), url('<%= asset_path("OpenSans-Semibold-webfont.woff") %>') format("woff"), url('<%= asset_path("OpenSans-Semibold-webfont.ttf") %>') format("truetype"), url('<%= asset_path("OpenSans-Semibold-webfont.svg") %>#open_sanssemibold') format("svg"); 15 | } 16 | @font-face { 17 | font-family: 'Open Sans bold'; 18 | src: url('<%= asset_path("OpenSans-Bold-webfont.eot") %>'); 19 | src: url('<%= asset_path("OpenSans-Bold-webfont.eot") %>?#iefix') format("embedded-opentype"), url('<%= asset_path("OpenSans-Bold-webfont.woff") %>') format("woff"), url('<%= asset_path("OpenSans-Bold-webfont.ttf") %>') format("truetype"), url('<%= asset_path("OpenSans-Bold-webfont.svg") %>#open_sansbold') format("svg"); 20 | } 21 | @font-face { 22 | font-family: 'BT Mono'; 23 | src: url('<%= asset_path("bt-mono-Regular.eot") %>'); 24 | src: url('<%= asset_path("bt-mono-Regular.eot") %>?#iefix') format("embedded-opentype"), url('<%= asset_path("bt-mono-Regular.woff2") %>') format("woff2"), url('<%= asset_path("bt-mono-Regular.woff") %>') format("woff"), url('<%= asset_path("bt-mono-Regular.ttf") %>') format("truetype"), url('<%= asset_path("bt-mono-Regular.svg") %>#bt_monoregular') format("svg"); 25 | } 26 | @font-face { 27 | font-family: 'BT Mono medium'; 28 | src: url('<%= asset_path("bt-mono-Medium.eot") %>'); 29 | src: url('<%= asset_path("bt-mono-Medium.eot") %>?#iefix') format("embedded-opentype"), url('<%= asset_path("bt-mono-Medium.woff2") %>') format("woff2"), url('<%= asset_path("bt-mono-Medium.woff") %>') format("woff"), url('<%= asset_path("bt-mono-Medium.ttf") %>') format("truetype"), url('<%= asset_path("bt-mono-Medium.svg") %>#bt_monobold') format("svg"); 30 | } 31 | @font-face { 32 | font-family: 'BT Mono bold'; 33 | src: url('<%= asset_path("bt-mono-Bold.eot") %>'); 34 | src: url('<%= asset_path("bt-mono-Bold.eot") %>?#iefix') format("embedded-opentype"), url('<%= asset_path("bt-mono-Bold.woff2") %>') format("woff2"), url('<%= asset_path("bt-mono-Bold.woff") %>') format("woff"), url('<%= asset_path("bt-mono-Bold.ttf") %>') format("truetype"), url('<%= asset_path("bt-mono-Bold.svg") %>#bt_monobold') format("svg"); 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Braintree GraphQL Example in Rails 2 | 3 | [![Build Status](https://travis-ci.org/braintree/braintree_graphql_rails_example.svg?branch=master)](https://travis-ci.org/braintree/braintree_graphql_rails_example) 4 | 5 | An example Braintree integration with the [GraphQL API](https://graphql.braintreepayments.com/) using Ruby on Rails. Forked from [braintree/braintree_rails_example](https://github.com/braintree/braintree_rails_example). 6 | 7 | ## Setup Instructions 8 | 9 | 1. Install bundler: 10 | 11 | ```sh 12 | gem install bundler 13 | ``` 14 | 15 | 2. Bundle: 16 | 17 | ```sh 18 | bundle 19 | ``` 20 | 21 | 3. Copy the contents of `example.env` into a new file named `.env` and fill in your Braintree API credentials. Credentials can be found by navigating to Account > My User > View Authorizations in the Braintree Control Panel. Full instructions can be [found on our support site](https://articles.braintreepayments.com/control-panel/important-gateway-credentials#api-credentials). 22 | 23 | 4. Start rails: 24 | 25 | ```sh 26 | rails server 27 | ``` 28 | 29 | ## Deploying to Heroku 30 | 31 | You can deploy this app directly to Heroku to see the app live. Skip the setup instructions above and click the button below. This will walk you through getting this app up and running on Heroku in minutes. 32 | 33 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/braintree/braintree_graphql_rails_example&env[BT_VERSION]=2019-11-11) 34 | 35 | ## Running Tests 36 | 37 | ### Running Unit Tests 38 | 39 | Unit tests do not make API calls to Braintree and do not require Braintree credentials. You can run this project's unit tests by 40 | calling `rake` (or `rails -R spec`) on the command line. 41 | 42 | ### Running Integration Tests 43 | 44 | Integration tests make API calls to Braintree and require that you set up your Braintree credentials. You can run this project's integration tests by adding your sandbox API credentials to `.env` and calling `rake spec:integration` (or `rails spec:integration`) on the command line. 45 | 46 | ### Running All Tests 47 | 48 | You can run both unit and integrations tests by calling `rake spec` (or `rails spec`) on the command line. 49 | 50 | ## Testing Transactions 51 | 52 | Sandbox transactions must be made with [sample credit card numbers](https://developers.braintreepayments.com/reference/general/testing/ruby#credit-card-numbers), and the response of a `Braintree::Transaction.sale()` call is dependent on the [amount of the transaction](https://developers.braintreepayments.com/reference/general/testing/ruby#test-amounts). 53 | 54 | ## Pro Tips 55 | 56 | * Run `rails s -b 0.0.0.0` when launching Rails server to listen on all interfaces. 57 | 58 | ## Help 59 | 60 | * Found a bug? Have a suggestion for improvement? Want to tell us we're awesome? [Submit an issue](https://github.com/braintree/braintree_graphql_rails_example/issues) 61 | * Trouble with your integration? Contact [Braintree Support](https://support.braintreepayments.com/) / support@braintreepayments.com 62 | * Want to contribute? [Submit a pull request](https://help.github.com/articles/creating-a-pull-request) 63 | 64 | ## Disclaimer 65 | 66 | This code is provided as is and is only intended to be used for illustration purposes. This code is not production-ready and is not meant to be used in a production environment. This repository is to be used as a tool to help merchants learn how to integrate with Braintree. Any use of this repository or any of its code in a production environment is highly discouraged. 67 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] 18 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). 19 | # config.require_master_key = true 20 | 21 | # Disable serving static files from the `/public` folder by default since 22 | # Apache or NGINX already handles this. 23 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? 24 | 25 | # Compress JavaScripts and CSS. 26 | config.assets.js_compressor = :uglifier 27 | # config.assets.css_compressor = :sass 28 | 29 | # Do not fallback to assets pipeline if a precompiled asset is missed. 30 | config.assets.compile = false 31 | 32 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb 33 | 34 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 35 | # config.action_controller.asset_host = 'http://assets.example.com' 36 | 37 | # Specifies the header that your server uses for sending files. 38 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 39 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 40 | 41 | # Store uploaded files on the local file system (see config/storage.yml for options) 42 | config.active_storage.service = :local 43 | 44 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 45 | # config.force_ssl = true 46 | 47 | # Use the lowest log level to ensure availability of diagnostic information 48 | # when problems arise. 49 | config.log_level = :debug 50 | 51 | # Prepend all log lines with the following tags. 52 | config.log_tags = [ :request_id ] 53 | 54 | # Use a different cache store in production. 55 | # config.cache_store = :mem_cache_store 56 | 57 | # Use a real queuing backend for Active Job (and separate queues per environment) 58 | # config.active_job.queue_adapter = :resque 59 | # config.active_job.queue_name_prefix = "braintree_graphql_rails_example_#{Rails.env}" 60 | 61 | config.action_mailer.perform_caching = false 62 | 63 | # Ignore bad email addresses and do not raise email delivery errors. 64 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 65 | # config.action_mailer.raise_delivery_errors = false 66 | 67 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 68 | # the I18n.default_locale when a translation cannot be found). 69 | config.i18n.fallbacks = true 70 | 71 | # Send deprecation notices to registered listeners. 72 | config.active_support.deprecation = :notify 73 | 74 | # Use default logging formatter so that PID and timestamp are not suppressed. 75 | config.log_formatter = ::Logger::Formatter.new 76 | 77 | # Use a different logger for distributed setups. 78 | # require 'syslog/logger' 79 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') 80 | 81 | if ENV["RAILS_LOG_TO_STDOUT"].present? 82 | logger = ActiveSupport::Logger.new(STDOUT) 83 | logger.formatter = config.log_formatter 84 | config.logger = ActiveSupport::TaggedLogging.new(logger) 85 | end 86 | 87 | # Do not dump schema after migrations. 88 | config.active_record.dump_schema_after_migration = false 89 | end 90 | -------------------------------------------------------------------------------- /spec/support/mock_data.rb: -------------------------------------------------------------------------------- 1 | RSpec.shared_context 'mock_data' do 2 | 3 | let(:mock_successful_fetched_transaction) { 4 | { 5 | "data" => { 6 | "transaction" => { 7 | "id" => "my_id", 8 | "amount" => { 9 | "value" => "12.12", 10 | "currencyIsoCode" => "CAD", 11 | }, 12 | "status" => "SUBMITTED_FOR_SETTLEMENT", 13 | "createdAt" => "2019-08-07T15:47:54.000000Z", 14 | "paymentMethodSnapshot" => { 15 | "__typename" => "CreditCardDetails", 16 | "bin" => "545454", 17 | "brandCode" => "MASTERCARD", 18 | "cardholderName" => "Billy Bobby Pins", 19 | "expirationMonth" => "12", 20 | "expirationYear" => "2020", 21 | "last4" => "4444", 22 | "binData" => { 23 | "countryOfIssuance" => "USA", 24 | }, 25 | "origin" => nil, 26 | }, 27 | } 28 | }, 29 | "extensions" => { 30 | "requestId" => "abc-request-123-id" 31 | } 32 | } 33 | } 34 | 35 | let(:mock_processor_decline_fetched_transaction) { 36 | { 37 | "data" => { 38 | "transaction" => { 39 | "id" => "spaceodyssey", 40 | "amount" => { 41 | "value" => "2001.00", 42 | "currencyIsoCode" => "USD", 43 | }, 44 | "status" => "PROCESSOR_DECLINED", 45 | "gatewayRejectionReason" => nil, 46 | "processorResponse" => { 47 | "legacyCode" => "2001", 48 | "message" => "Insufficient Funds", 49 | }, 50 | "paymentMethodSnapshot" => { 51 | "__typename" => "CreditCardDetails", 52 | "bin" => "545454", 53 | "brandCode" => "MASTERCARD", 54 | "cardholderName" => "Billy Bobby Pins", 55 | "expirationMonth" => "12", 56 | "expirationYear" => "2020", 57 | "last4" => "4444", 58 | "binData" => { 59 | "countryOfIssuance" => "USA", 60 | }, 61 | "origin" => nil, 62 | }, 63 | } 64 | }, 65 | "extensions" => { 66 | "requestId" => "def-request-456-id" 67 | } 68 | } 69 | } 70 | 71 | let(:mock_created_transaction) { 72 | { 73 | "data" => { 74 | "chargePaymentMethod" => { 75 | "transaction" => { 76 | "id" => "my_id" 77 | } 78 | } 79 | } 80 | } 81 | } 82 | 83 | let(:mock_transaction_validation_error) { 84 | { 85 | "data" => { 86 | "chargePaymentMethod" => nil, 87 | }, 88 | "errors" => [ 89 | { 90 | "message" => "Unknown or expired payment method ID.", 91 | "locations" => [ 92 | { 93 | "line" => 2, 94 | "column" => 3 95 | } 96 | ], 97 | "path" => [ 98 | "chargePaymentMethod" 99 | ], 100 | "extensions" => { 101 | "errorType" => "user_error", 102 | "errorClass" => "VALIDATION", 103 | "legacyCode" => "91565", 104 | "inputPath" => [ 105 | "input", 106 | "transaction", 107 | "singleUseTokenId" 108 | ] 109 | } 110 | } 111 | ], 112 | "extensions" => { 113 | "requestId" => "ghi-request-789-id" 114 | } 115 | } 116 | } 117 | 118 | let(:mock_transaction_graphql_error) { 119 | { 120 | "data" => nil, 121 | "errors" => [ 122 | { 123 | "message" => "Variable 'amount' has an invalid value. Values of type Amount must contain exactly 0, 2 or 3 decimal places.", 124 | "locations" => [ 125 | { 126 | "line" => 1, 127 | "column" => 11 128 | } 129 | ] 130 | } 131 | ], 132 | "extensions" => { 133 | "requestId" => "jkl-request-012-id" 134 | } 135 | } 136 | } 137 | end 138 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # This file was generated by the `rails generate rspec:install` command. Conventionally, all 2 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. 3 | # The generated `.rspec` file contains `--require spec_helper` which will cause 4 | # this file to always be loaded, without a need to explicitly require it in any 5 | # files. 6 | # 7 | # Given that it is always loaded, you are encouraged to keep this file as 8 | # light-weight as possible. Requiring heavyweight dependencies from this file 9 | # will add to the boot time of your test suite on EVERY test run, even for an 10 | # individual file that may not need all of that loaded. Instead, consider making 11 | # a separate helper file that requires the additional dependencies and performs 12 | # the additional setup, and require it from the spec files that actually need 13 | # it. 14 | # 15 | # The `.rspec` file also contains a few flags that are not defaults but that 16 | # users commonly want. 17 | # 18 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 19 | RSpec.configure do |config| 20 | # rspec-expectations config goes here. You can use an alternate 21 | # assertion/expectation library such as wrong or the stdlib/minitest 22 | # assertions if you prefer. 23 | config.expect_with :rspec do |expectations| 24 | # This option will default to `true` in RSpec 4. It makes the `description` 25 | # and `failure_message` of custom matchers include text for helper methods 26 | # defined using `chain`, e.g.: 27 | # be_bigger_than(2).and_smaller_than(4).description 28 | # # => "be bigger than 2 and smaller than 4" 29 | # ...rather than: 30 | # # => "be bigger than 2" 31 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 32 | end 33 | 34 | # rspec-mocks config goes here. You can use an alternate test double 35 | # library (such as bogus or mocha) by changing the `mock_with` option here. 36 | config.mock_with :rspec do |mocks| 37 | # Prevents you from mocking or stubbing a method that does not exist on 38 | # a real object. This is generally recommended, and will default to 39 | # `true` in RSpec 4. 40 | mocks.verify_partial_doubles = true 41 | end 42 | 43 | config.before(:suite) do 44 | # Prevent BraintreeGateway from logging to standard out during tests 45 | BraintreeGateway::LOGGER = Logger.new("/dev/null") 46 | end 47 | 48 | # The settings below are suggested to provide a good initial experience 49 | # with RSpec, but feel free to customize to your heart's content. 50 | =begin 51 | # These two settings work together to allow you to limit a spec run 52 | # to individual examples or groups you care about by tagging them with 53 | # `:focus` metadata. When nothing is tagged with `:focus`, all examples 54 | # get run. 55 | config.filter_run :focus 56 | config.run_all_when_everything_filtered = true 57 | 58 | # Allows RSpec to persist some state between runs in order to support 59 | # the `--only-failures` and `--next-failure` CLI options. We recommend 60 | # you configure your source control system to ignore this file. 61 | config.example_status_persistence_file_path = "spec/examples.txt" 62 | 63 | # Limits the available syntax to the non-monkey patched syntax that is 64 | # recommended. For more details, see: 65 | # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax 66 | # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ 67 | # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching 68 | config.disable_monkey_patching! 69 | 70 | # Many RSpec users commonly either run the entire suite or an individual 71 | # file, and it's useful to allow more verbose output when running an 72 | # individual spec file. 73 | if config.files_to_run.one? 74 | # Use the documentation formatter for detailed output, 75 | # unless a formatter has already been configured 76 | # (e.g. via a command-line flag). 77 | config.default_formatter = 'doc' 78 | end 79 | 80 | # Print the 10 slowest examples and example groups at the 81 | # end of the spec run, to help surface which specs are running 82 | # particularly slow. 83 | config.profile_examples = 10 84 | 85 | # Run specs in random order to surface order dependencies. If you find an 86 | # order dependency and want to debug it, you can fix the order by providing 87 | # the seed, which is printed after each run. 88 | # --seed 1234 89 | config.order = :random 90 | 91 | # Seed global randomization in this process using the `--seed` CLI option. 92 | # Setting this allows you to use `--seed` to deterministically reproduce 93 | # test failures related to randomization by passing the same `--seed` value 94 | # as the one that triggered the failure. 95 | Kernel.srand config.seed 96 | =end 97 | end 98 | -------------------------------------------------------------------------------- /app/models/braintree_gateway.rb: -------------------------------------------------------------------------------- 1 | class BraintreeGateway 2 | LOGGER = ::Logger.new(STDOUT) 3 | ENDPOINT = "https://payments.sandbox.braintree-api.com/graphql" 4 | CONTENT_TYPE = "application/json" 5 | VERSION = ENV["BT_VERSION"] 6 | BASIC_AUTH_USERNAME = ENV["BT_PUBLIC_KEY"] 7 | BASIC_AUTH_PASSWORD = ENV["BT_PRIVATE_KEY"] 8 | 9 | def initialize(requester_class) 10 | @requester = requester_class 11 | end 12 | 13 | def ping 14 | _make_request("ping", "{ ping }") 15 | end 16 | 17 | def client_token 18 | operation_name = "createClientToken" 19 | result = _make_request(operation_name, "mutation { #{operation_name}(input: {}) { clientToken } }") 20 | end 21 | 22 | def transaction(payment_method_id, amount) 23 | operation_name = "chargePaymentMethod" 24 | query = <<~GRAPHQL 25 | mutation($input: ChargePaymentMethodInput!) { 26 | #{operation_name}(input: $input) { 27 | transaction { 28 | id 29 | } 30 | } 31 | } 32 | GRAPHQL 33 | variables = { 34 | :input => { 35 | :paymentMethodId => payment_method_id, 36 | :transaction => { 37 | :amount => amount, 38 | }, 39 | } 40 | } 41 | 42 | _make_request(operation_name, query, variables) 43 | end 44 | 45 | def vault(single_use_payment_method_id) 46 | operation_name = "vaultPaymentMethod" 47 | _make_request( 48 | operation_name, 49 | "mutation($input: VaultPaymentMethodInput!) { #{operation_name}(input: $input) { paymentMethod { id usage } } }", 50 | {:input => { 51 | :paymentMethodId => single_use_payment_method_id, 52 | }} 53 | ) 54 | end 55 | 56 | def node_fetch_transaction(transaction_id) 57 | operation_name = "transaction" 58 | query = <<~GRAPHQL 59 | query { 60 | #{operation_name}:node(id: "#{transaction_id}") { 61 | ... on Transaction { 62 | id 63 | amount { value currencyIsoCode } 64 | status 65 | createdAt 66 | paymentMethodSnapshot { 67 | __typename 68 | ... on CreditCardDetails { 69 | bin 70 | brandCode 71 | cardholderName 72 | expirationMonth 73 | expirationYear 74 | last4 75 | binData { countryOfIssuance } 76 | origin { type } 77 | } 78 | ... on PayPalTransactionDetails { 79 | payer { 80 | email 81 | payerId 82 | firstName 83 | lastName 84 | } 85 | payerStatus 86 | } 87 | } 88 | } 89 | } 90 | } 91 | GRAPHQL 92 | _make_request(operation_name, query) 93 | end 94 | 95 | def _generate_payload(query_string, variables_hash) 96 | JSON.generate({ 97 | :query => query_string, 98 | :variables => variables_hash 99 | }).to_s 100 | end 101 | 102 | def _make_request(operation_name, query_string, variables_hash = {}) 103 | # rescue http exceptions thrown by httparty and throw a GraphQLError 104 | payload = _generate_payload(query_string, variables_hash) 105 | result = @requester.post( 106 | ENDPOINT, 107 | { 108 | :body => payload, 109 | :basic_auth => { 110 | :username => BASIC_AUTH_USERNAME, 111 | :password => BASIC_AUTH_PASSWORD, 112 | }, 113 | :headers => { 114 | "Braintree-Version" => VERSION, 115 | "Content-Type" => CONTENT_TYPE, 116 | }, 117 | :logger => LOGGER, 118 | :log_level => :debug, 119 | } 120 | ).parsed_response 121 | is_any_data_present = (result["data"] != nil and result["data"][operation_name] != nil) 122 | 123 | if result["errors"] 124 | LOGGER.error( 125 | <<~SEMISTRUCTUREDLOG 126 | "top_level_message" => "Error present on GraphQL request to Braintree.", 127 | "operation_name" => #{operation_name}, 128 | "braintree_request_id" => #{self.class.parse_braintree_request_id(result)}, 129 | "result" => #{result}, 130 | "request" => #{payload}" 131 | SEMISTRUCTUREDLOG 132 | ) 133 | end 134 | 135 | if is_any_data_present 136 | return result 137 | else 138 | raise GraphQLError.new(result) 139 | end 140 | end 141 | 142 | def self.parse_braintree_request_id(result) 143 | result.dig("extensions", "requestId") 144 | end 145 | 146 | class GraphQLError < StandardError 147 | attr_reader :messages 148 | def initialize(graphql_result) 149 | @messages = graphql_result["errors"].map { |error| "Error: " + error["message"] } if graphql_result["errors"] 150 | 151 | LOGGER.error( 152 | <<~SEMISTRUCTUREDLOG 153 | "top_level_message" => #{@messages.to_s}, 154 | "braintree_request_id" => #{BraintreeGateway.parse_braintree_request_id(graphql_result)}, 155 | "result" => #{graphql_result}, 156 | SEMISTRUCTUREDLOG 157 | ) 158 | end 159 | end 160 | end 161 | -------------------------------------------------------------------------------- /spec/controllers/checkouts_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | require 'support/mock_data' 3 | 4 | RSpec.describe CheckoutsController, type: :controller do 5 | render_views 6 | include_context 'mock_data' 7 | 8 | before do 9 | @mock_gateway = instance_double("BraintreeGateway") 10 | allow(@mock_gateway).to receive(:client_token).and_return({ 11 | "data" => { 12 | "createClientToken" => { 13 | "clientToken" => "your_client_token" 14 | } 15 | } 16 | }) 17 | 18 | allow(BraintreeGateway).to receive(:new).and_return(@mock_gateway) 19 | end 20 | 21 | describe "GET #new" do 22 | it "returns http success" do 23 | get :new 24 | expect(response).to have_http_status(:success) 25 | end 26 | 27 | it "adds the Braintree client token to the page" do 28 | get :new 29 | expect(response.body).to match /your_client_token/ 30 | end 31 | end 32 | 33 | describe "GET #show" do 34 | it "returns http success" do 35 | allow(@mock_gateway).to receive(:node_fetch_transaction).and_return(mock_successful_fetched_transaction) 36 | 37 | get :show, params: { id: "my_id" } 38 | 39 | expect(response).to have_http_status(:success) 40 | end 41 | 42 | it "displays the transaction's fields" do 43 | allow(@mock_gateway).to receive(:node_fetch_transaction).and_return(mock_successful_fetched_transaction) 44 | 45 | get :show, params: { id: "my_id" } 46 | 47 | expect(response.body).to match /my_id/ 48 | expect(response.body).to match /12\.12/ 49 | expect(response.body).to match /CAD/ 50 | expect(response.body).to match /SUBMITTED_FOR_SETTLEMENT/ 51 | expect(response.body).to match /545454/ 52 | expect(response.body).to match /4444/ 53 | expect(response.body).to match /Billy Bobby Pins/ 54 | expect(response.body).to match /12/ 55 | expect(response.body).to match /2020/ 56 | expect(response.body).to match /USA/ 57 | end 58 | 59 | it "populates result object with success for a succesful transaction" do 60 | allow(@mock_gateway).to receive(:node_fetch_transaction).and_return(mock_successful_fetched_transaction) 61 | 62 | get :show, params: { id: "my_id" } 63 | 64 | expect(assigns(:result)).to eq({ 65 | :header => "Sweet Success!", 66 | :icon => "success", 67 | :message => "Your test transaction has been successfully processed. See the Braintree API response and try again." 68 | }) 69 | end 70 | 71 | 72 | it "populates result object with failure for a failed transaction" do 73 | allow(@mock_gateway).to receive(:node_fetch_transaction).and_return(mock_processor_decline_fetched_transaction) 74 | 75 | get :show, params: { id: "my_id" } 76 | 77 | expect(assigns(:result)).to eq({ 78 | :header => "Transaction Unsuccessful", 79 | :icon => "fail", 80 | :message => "Your test transaction has a status of PROCESSOR_DECLINED. See the Braintree API response and try again." 81 | }) 82 | expect(response.body).to match /PROCESSOR_DECLINED/ 83 | end 84 | end 85 | 86 | describe "POST #create" do 87 | it "returns http success" do 88 | amount = "10.00" 89 | nonce = "fake-valid-nonce" 90 | 91 | allow(@mock_gateway).to receive(:transaction).and_return(mock_created_transaction) 92 | 93 | post :create, params: { payment_method_nonce: nonce, amount: amount } 94 | 95 | expect(response).to redirect_to("/checkouts/#{mock_created_transaction["data"]["chargePaymentMethod"]["transaction"]["id"]}") 96 | end 97 | 98 | context "when braintree returns an error" do 99 | it "displays graphql errors" do 100 | amount = "nine and three quarters" 101 | nonce = "fake-valid-nonce" 102 | 103 | allow(@mock_gateway).to receive(:transaction).and_raise( 104 | BraintreeGateway::GraphQLError.new(mock_transaction_graphql_error) 105 | ) 106 | 107 | post :create, params: { payment_method_nonce: nonce, amount: amount } 108 | 109 | expect(flash[:error]).to eq([ 110 | "Error: Variable 'amount' has an invalid value. Values of type Amount must contain exactly 0, 2 or 3 decimal places." 111 | ]) 112 | end 113 | 114 | it "displays validation errors" do 115 | amount = "9.75" 116 | nonce = "non-fake-invalid-nonce" 117 | 118 | allow(@mock_gateway).to receive(:transaction).and_raise( 119 | BraintreeGateway::GraphQLError.new(mock_transaction_validation_error) 120 | ) 121 | 122 | post :create, params: { payment_method_nonce: nonce, amount: amount } 123 | 124 | expect(flash[:error]).to eq([ 125 | "Error: Unknown or expired payment method ID.", 126 | ]) 127 | end 128 | 129 | it "redirects to the new_checkout_path" do 130 | amount = "not_a_valid_amount" 131 | nonce = "not_a_valid_nonce" 132 | 133 | allow(@mock_gateway).to receive(:transaction).and_raise( 134 | BraintreeGateway::GraphQLError.new(mock_transaction_graphql_error) 135 | ) 136 | 137 | post :create, params: { payment_method_nonce: nonce, amount: amount } 138 | 139 | expect(response).to redirect_to(new_checkout_path) 140 | end 141 | 142 | it "gracefully handles unexpected errors" do 143 | amount = "10.10" 144 | nonce = "a-very-valid-nonce" 145 | 146 | allow(@mock_gateway).to receive(:transaction).and_raise( 147 | BraintreeGateway::GraphQLError.new({ 148 | "data" => nil, 149 | "errors" => nil, 150 | }) 151 | ) 152 | 153 | post :create, params: { payment_method_nonce: nonce, amount: amount } 154 | 155 | expect(flash[:error]).to eq([ 156 | "Error: Something unexpected went wrong! Try again." 157 | ]) 158 | expect(response).to redirect_to(new_checkout_path) 159 | end 160 | end 161 | end 162 | end 163 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actioncable (5.2.4.6) 5 | actionpack (= 5.2.4.6) 6 | nio4r (~> 2.0) 7 | websocket-driver (>= 0.6.1) 8 | actionmailer (5.2.4.6) 9 | actionpack (= 5.2.4.6) 10 | actionview (= 5.2.4.6) 11 | activejob (= 5.2.4.6) 12 | mail (~> 2.5, >= 2.5.4) 13 | rails-dom-testing (~> 2.0) 14 | actionpack (5.2.4.6) 15 | actionview (= 5.2.4.6) 16 | activesupport (= 5.2.4.6) 17 | rack (~> 2.0, >= 2.0.8) 18 | rack-test (>= 0.6.3) 19 | rails-dom-testing (~> 2.0) 20 | rails-html-sanitizer (~> 1.0, >= 1.0.2) 21 | actionview (5.2.4.6) 22 | activesupport (= 5.2.4.6) 23 | builder (~> 3.1) 24 | erubi (~> 1.4) 25 | rails-dom-testing (~> 2.0) 26 | rails-html-sanitizer (~> 1.0, >= 1.0.3) 27 | activejob (5.2.4.6) 28 | activesupport (= 5.2.4.6) 29 | globalid (>= 0.3.6) 30 | activemodel (5.2.4.6) 31 | activesupport (= 5.2.4.6) 32 | activerecord (5.2.4.6) 33 | activemodel (= 5.2.4.6) 34 | activesupport (= 5.2.4.6) 35 | arel (>= 9.0) 36 | activestorage (5.2.4.6) 37 | actionpack (= 5.2.4.6) 38 | activerecord (= 5.2.4.6) 39 | marcel (~> 0.3.1) 40 | activesupport (5.2.4.6) 41 | concurrent-ruby (~> 1.0, >= 1.0.2) 42 | i18n (>= 0.7, < 2) 43 | minitest (~> 5.1) 44 | tzinfo (~> 1.1) 45 | arel (9.0.0) 46 | binding_of_caller (0.8.0) 47 | debug_inspector (>= 0.0.1) 48 | bootsnap (1.3.2) 49 | msgpack (~> 1.0) 50 | builder (3.2.4) 51 | byebug (10.0.2) 52 | coffee-rails (4.2.2) 53 | coffee-script (>= 2.2.0) 54 | railties (>= 4.0.0) 55 | coffee-script (2.4.1) 56 | coffee-script-source 57 | execjs 58 | coffee-script-source (1.12.2) 59 | concurrent-ruby (1.1.8) 60 | crass (1.0.6) 61 | debug_inspector (0.0.3) 62 | diff-lcs (1.3) 63 | dotenv (2.5.0) 64 | erubi (1.10.0) 65 | execjs (2.7.0) 66 | ffi (1.15.0) 67 | globalid (0.4.2) 68 | activesupport (>= 4.2.0) 69 | httparty (0.16.2) 70 | concurrent-ruby (~> 1.0) 71 | multi_xml (>= 0.5.2) 72 | i18n (1.8.10) 73 | concurrent-ruby (~> 1.0) 74 | jbuilder (2.8.0) 75 | activesupport (>= 4.2.0) 76 | multi_json (>= 1.2) 77 | jquery-rails (4.3.3) 78 | rails-dom-testing (>= 1, < 3) 79 | railties (>= 4.2.0) 80 | thor (>= 0.14, < 2.0) 81 | listen (3.5.1) 82 | rb-fsevent (~> 0.10, >= 0.10.3) 83 | rb-inotify (~> 0.9, >= 0.9.10) 84 | loofah (2.9.1) 85 | crass (~> 1.0.2) 86 | nokogiri (>= 1.5.9) 87 | mail (2.7.1) 88 | mini_mime (>= 0.1.1) 89 | marcel (0.3.3) 90 | mimemagic (~> 0.3.2) 91 | method_source (1.0.0) 92 | mimemagic (0.3.10) 93 | nokogiri (~> 1) 94 | rake 95 | mini_mime (1.1.0) 96 | mini_portile2 (2.5.1) 97 | minitest (5.14.4) 98 | msgpack (1.2.10) 99 | multi_json (1.13.1) 100 | multi_xml (0.6.0) 101 | nio4r (2.5.7) 102 | nokogiri (1.11.5) 103 | mini_portile2 (~> 2.5.0) 104 | racc (~> 1.4) 105 | pg (0.21.0) 106 | racc (1.5.2) 107 | rack (2.2.3) 108 | rack-test (1.1.0) 109 | rack (>= 1.0, < 3) 110 | rails (5.2.4.6) 111 | actioncable (= 5.2.4.6) 112 | actionmailer (= 5.2.4.6) 113 | actionpack (= 5.2.4.6) 114 | actionview (= 5.2.4.6) 115 | activejob (= 5.2.4.6) 116 | activemodel (= 5.2.4.6) 117 | activerecord (= 5.2.4.6) 118 | activestorage (= 5.2.4.6) 119 | activesupport (= 5.2.4.6) 120 | bundler (>= 1.3.0) 121 | railties (= 5.2.4.6) 122 | sprockets-rails (>= 2.0.0) 123 | rails-controller-testing (1.0.4) 124 | actionpack (>= 5.0.1.x) 125 | actionview (>= 5.0.1.x) 126 | activesupport (>= 5.0.1.x) 127 | rails-dom-testing (2.0.3) 128 | activesupport (>= 4.2.0) 129 | nokogiri (>= 1.6) 130 | rails-html-sanitizer (1.3.0) 131 | loofah (~> 2.3) 132 | rails_12factor (0.0.3) 133 | rails_serve_static_assets 134 | rails_stdout_logging 135 | rails_serve_static_assets (0.0.5) 136 | rails_stdout_logging (0.0.5) 137 | railties (5.2.4.6) 138 | actionpack (= 5.2.4.6) 139 | activesupport (= 5.2.4.6) 140 | method_source 141 | rake (>= 0.8.7) 142 | thor (>= 0.19.0, < 2.0) 143 | rake (13.0.3) 144 | rb-fsevent (0.10.4) 145 | rb-inotify (0.10.1) 146 | ffi (~> 1.0) 147 | rdoc (6.3.1) 148 | rspec-core (3.8.0) 149 | rspec-support (~> 3.8.0) 150 | rspec-expectations (3.8.2) 151 | diff-lcs (>= 1.2.0, < 2.0) 152 | rspec-support (~> 3.8.0) 153 | rspec-mocks (3.8.0) 154 | diff-lcs (>= 1.2.0, < 2.0) 155 | rspec-support (~> 3.8.0) 156 | rspec-rails (3.8.1) 157 | actionpack (>= 3.0) 158 | activesupport (>= 3.0) 159 | railties (>= 3.0) 160 | rspec-core (~> 3.8.0) 161 | rspec-expectations (~> 3.8.0) 162 | rspec-mocks (~> 3.8.0) 163 | rspec-support (~> 3.8.0) 164 | rspec-support (3.8.0) 165 | sass (3.7.3) 166 | sass-listen (~> 4.0.0) 167 | sass-listen (4.0.0) 168 | rb-fsevent (~> 0.9, >= 0.9.4) 169 | rb-inotify (~> 0.9, >= 0.9.7) 170 | sass-rails (5.0.7) 171 | railties (>= 4.0.0, < 6) 172 | sass (~> 3.1) 173 | sprockets (>= 2.8, < 4.0) 174 | sprockets-rails (>= 2.0, < 4.0) 175 | tilt (>= 1.1, < 3) 176 | sdoc (2.2.0) 177 | rdoc (>= 5.0) 178 | spring (2.0.2) 179 | activesupport (>= 4.2) 180 | sprockets (3.7.2) 181 | concurrent-ruby (~> 1.0) 182 | rack (> 1, < 3) 183 | sprockets-rails (3.2.2) 184 | actionpack (>= 4.0) 185 | activesupport (>= 4.0) 186 | sprockets (>= 3.0.0) 187 | sqlite3 (1.3.13) 188 | thor (1.1.0) 189 | thread_safe (0.3.6) 190 | tilt (2.0.9) 191 | turbolinks (5.2.0) 192 | turbolinks-source (~> 5.2) 193 | turbolinks-source (5.2.0) 194 | tzinfo (1.2.9) 195 | thread_safe (~> 0.1) 196 | uglifier (4.1.20) 197 | execjs (>= 0.3.0, < 3) 198 | web-console (2.3.0) 199 | activemodel (>= 4.0) 200 | binding_of_caller (>= 0.7.2) 201 | railties (>= 4.0) 202 | sprockets-rails (>= 2.0, < 4.0) 203 | websocket-driver (0.7.3) 204 | websocket-extensions (>= 0.1.0) 205 | websocket-extensions (0.1.5) 206 | 207 | PLATFORMS 208 | ruby 209 | 210 | DEPENDENCIES 211 | bootsnap (= 1.3.2) 212 | byebug 213 | coffee-rails (~> 4.2.2) 214 | dotenv (~> 2.0) 215 | httparty (~> 0.16.2) 216 | jbuilder (~> 2.0) 217 | jquery-rails 218 | listen (>= 3.1.5) 219 | nokogiri (>= 1.11.4) 220 | pg (~> 0.21.0) 221 | rails (= 5.2.4.6) 222 | rails-controller-testing 223 | rails_12factor 224 | rspec-rails 225 | sass-rails (~> 5.0) 226 | sdoc (>= 2.2.0) 227 | spring 228 | sqlite3 229 | turbolinks 230 | uglifier (>= 1.3.0) 231 | web-console (~> 2.0) 232 | 233 | RUBY VERSION 234 | ruby 2.5.8p224 235 | 236 | BUNDLED WITH 237 | 2.2.4 238 | -------------------------------------------------------------------------------- /app/assets/stylesheets/app.css.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "mappings": "AAAA,4DAA4D;AAAA,IAAI;EAAC,WAAW,EAAC,UAAU;EAAC,oBAAoB,EAAC,IAAI;EAAC,wBAAwB,EAAC,IAAI;;AAAC,IAAI;EAAC,MAAM,EAAC,CAAC;;AAAC,sGAA0F;EAAC,OAAO,EAAC,KAAK;;AAAC,8BAA2B;EAAC,OAAO,EAAC,YAAY;EAAC,cAAc,EAAC,QAAQ;;AAAC,qBAAqB;EAAC,OAAO,EAAC,IAAI;EAAC,MAAM,EAAC,CAAC;;AAAC,kBAAiB;EAAC,OAAO,EAAC,IAAI;;AAAC,CAAC;EAAC,gBAAgB,EAAC,WAAW;;AAAC,iBAAgB;EAAC,OAAO,EAAC,CAAC;;AAAC,WAAW;EAAC,aAAa,EAAC,UAAU;;AAAC,SAAQ;EAAC,WAAW,EAAC,IAAI;;AAAC,GAAG;EAAC,UAAU,EAAC,MAAM;;AAAC,EAAE;EAAC,SAAS,EAAC,GAAG;EAAC,MAAM,EAAC,QAAQ;;AAAC,IAAI;EAAC,UAAU,EAAC,IAAI;EAAC,KAAK,EAAC,IAAI;;AAAC,KAAK;EAAC,SAAS,EAAC,GAAG;;AAAC,QAAO;EAAC,SAAS,EAAC,GAAG;EAAC,WAAW,EAAC,CAAC;EAAC,QAAQ,EAAC,QAAQ;EAAC,cAAc,EAAC,QAAQ;;AAAC,GAAG;EAAC,GAAG,EAAC,MAAM;;AAAC,GAAG;EAAC,MAAM,EAAC,OAAO;;AAAC,GAAG;EAAC,MAAM,EAAC,CAAC;;AAAC,cAAc;EAAC,QAAQ,EAAC,MAAM;;AAAC,MAAM;EAAC,MAAM,EAAC,QAAQ;;AAAC,EAAE;EAAC,eAAe,EAAC,WAAW;EAAC,kBAAkB,EAAC,WAAW;EAAC,UAAU,EAAC,WAAW;EAAC,MAAM,EAAC,CAAC;;AAAC,GAAG;EAAC,QAAQ,EAAC,IAAI;;AAAC,oBAAiB;EAAC,WAAW,EAAC,oBAAoB;EAAC,SAAS,EAAC,GAAG;;AAAC,yCAAqC;EAAC,KAAK,EAAC,OAAO;EAAC,IAAI,EAAC,OAAO;EAAC,MAAM,EAAC,CAAC;;AAAC,MAAM;EAAC,QAAQ,EAAC,OAAO;;AAAC,cAAa;EAAC,cAAc,EAAC,IAAI;;AAAC,4EAAyE;EAAC,kBAAkB,EAAC,MAAM;EAAC,MAAM,EAAC,OAAO;;AAAC,sCAAqC;EAAC,MAAM,EAAC,OAAO;;AAAC,iDAAgD;EAAC,MAAM,EAAC,CAAC;EAAC,OAAO,EAAC,CAAC;;AAAC,KAAK;EAAC,WAAW,EAAC,MAAM;;AAAC,2CAA0C;EAAC,kBAAkB,EAAC,UAAU;EAAC,eAAe,EAAC,UAAU;EAAC,UAAU,EAAC,UAAU;EAAC,OAAO,EAAC,CAAC;;AAAC,gGAA+F;EAAC,MAAM,EAAC,IAAI;;AAAC,oBAAoB;EAAC,kBAAkB,EAAC,SAAS;EAAC,eAAe,EAAC,WAAW;EAAC,kBAAkB,EAAC,WAAW;EAAC,UAAU,EAAC,WAAW;;AAAC,mGAAkG;EAAC,kBAAkB,EAAC,IAAI;;AAAC,QAAQ;EAAC,MAAM,EAAC,iBAAiB;EAAC,MAAM,EAAC,KAAK;EAAC,OAAO,EAAC,qBAAqB;;AAAC,MAAM;EAAC,MAAM,EAAC,CAAC;EAAC,OAAO,EAAC,CAAC;;AAAC,QAAQ;EAAC,QAAQ,EAAC,IAAI;;AAAC,QAAQ;EAAC,WAAW,EAAC,IAAI;;AAAC,KAAK;EAAC,eAAe,EAAC,QAAQ;EAAC,cAAc,EAAC,CAAC;;AAAC,MAAK;EAAC,OAAO,EAAC,CAAC;;ACAljE,2CAA4B;EAAE,OAAO,EAAE,EAAE;EAAE,OAAO,EAAE,KAAK;EAAE,KAAK,EAAE,IAAI;;AACtE,cAAe;EAAE,OAAO,EAAE,KAAK;EAAE,KAAK,EAAE,IAAI;EAAE,MAAM,EAAE,IAAI;EAAE,QAAQ,EAAE,IAAI;;AAC1E,MAAO;EAAE,OAAO,EAAE,UAAU;EAAE,cAAc,EAAE,MAAM;;AACpD,KAAM;EAAE,OAAO,EAAE,KAAK;EAAE,KAAK,EAAE,IAAI;;AACnC,MAAO;EAAE,KAAK,EAAE,KAAK;;AACrB,KAAM;EAAE,KAAK,EAAE,IAAI;;AACnB,OAAQ;EACN,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,IAAI;EACjB,YAAY,EAAE,IAAI;;AAEpB,MAAO;EACL,SAAS,EAAE,IAAI;;AAEjB,gHAAQ;EACN,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,IAAI;EACZ,IAAI,EAAE,GAAG;EACT,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,KAAK,EAAE,IAAI;;ACrBb,UASC;EARD,WAAW,EAAE,iBAAiB;EAC9B,GAAG,EAAE,oDAAoD;EACzD,GAAG,EAAE,wTAGgF;EACrF,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAElB,UASC;EARG,WAAW,EAAE,mBAAmB;EAChC,GAAG,EAAE,sDAAsD;EAC3D,GAAG,EAAE,mUAGqF;EAC1F,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAEtB,UASC;EARG,WAAW,EAAE,oBAAoB;EACjC,GAAG,EAAE,uDAAuD;EAC5D,GAAG,EAAE,wUAGuF;EAC5F,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAEtB,UASC;EARD,WAAW,EAAE,gBAAgB;EAC7B,GAAG,EAAE,mDAAmD;EACxD,GAAG,EAAE,oTAG+E;EACpF,WAAW,EAAE,MAAM;EACnB,UAAU,EAAE,MAAM;AAKlB,UAUC;EATC,WAAW,EAAE,SAAS;EACtB,GAAG,EAAE,2CAA2C;EAChD,GAAG,EAAE,oVAIwE;EAC7E,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,GAAG;AAElB,UAUC;EATC,WAAW,EAAE,gBAAgB;EAC7B,GAAG,EAAE,0CAA0C;EAC/C,GAAG,EAAE,4UAIoE;EACzE,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AAEpB,UAUC;EATC,WAAW,EAAE,cAAc;EAC3B,GAAG,EAAE,wCAAwC;EAC7C,GAAG,EAAE,kUAIkE;EACvE,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,MAAM;AC/DhB,yBAEC;ECXH,EAAG;IACD,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,OAAO,EAAE,CAAC;ADaV,sBAEC;ECnBH,EAAG;IACD,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,OAAO,EAAE,CAAC;ADyBV,iBAEC;EC/BH,EAAG;IACD,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,OAAO,EAAE,CAAC;ADKV,2BAEC;ECFH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADE1B,wBAEC;ECVH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADc1B,mBAEC;ECtBH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADN1B,6BAEC;ECSH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,iBAAiB;EAE9B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADT1B,0BAEC;ECCH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,iBAAiB;EAE9B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADG1B,qBAEC;ECXH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,iBAAiB;EAE9B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADjB1B,6BAEC;ECoBH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADpB1B,0BAEC;ECYH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADR1B,qBAEC;ECAH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;AD5B1B,8BAEC;EC+BH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,iBAAiB;EAE9B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;AD/B1B,2BAEC;ECuBH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,iBAAiB;EAE9B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADnB1B,sBAEC;ECWH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,iBAAiB;EAE9B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;ADvC1B,8BAEC;EC0CH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;EAE5B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;AD1C3B,2BAEC;ECkCH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;EAE5B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;AD9B3B,sBAEC;ECsBH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;EAE5B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;ADlD3B,+BAEC;ECqDH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;EAE5B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;ADrD3B,4BAEC;EC6CH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;EAE5B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;ADzC3B,uBAEC;ECiCH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,eAAe;EAE5B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;AD7D3B,4BAEC;ECgEH,EAAG;IACD,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,SAAS,EAAE,cAAc;AD9DzB,yBAEC;ECwDH,EAAG;IACD,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,SAAS,EAAE,cAAc;ADlDzB,oBAEC;EC4CH,EAAG;IACD,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,SAAS,EAAE,cAAc;ADtEzB,4BAEC;ECyEH,EAAG;ICnDG,iBAAoB,EAAE,gBAAM;EDsDlC,IAAK;ICtDC,iBAAoB,EAAE,cAAM;AFhBhC,yBAEC;ECiEH,EAAG;IC/CG,cAAiB,EAAE,gBAAM;EDkD/B,IAAK;IClDC,cAAiB,EAAE,cAAM;AFR7B,oBAEC;ECqDH,EAAG;ICnDG,iBAAoB,EAAE,gBAAM;IAI5B,cAAiB,EAAE,gBAAM;IAIzB,aAAgB,EAAE,gBAAM;IAIxB,YAAe,EAAE,gBAAM;IAIvB,SAAY,EAAE,gBAAM;EDsC1B,IAAK;ICtDC,iBAAoB,EAAE,cAAM;IAI5B,cAAiB,EAAE,cAAM;IAIzB,aAAgB,EAAE,cAAM;IAIxB,YAAe,EAAE,cAAM;IAIvB,SAAY,EAAE,cAAM;AFxCxB,6BAEC;ECkFH,EAAG;IC5DG,iBAAoB,EAAE,cAAM;ED+DlC,IAAK;IC/DC,iBAAoB,EAAE,gBAAM;AFhBhC,0BAEC;EC0EH,EAAG;ICxDG,cAAiB,EAAE,cAAM;ED2D/B,IAAK;IC3DC,cAAiB,EAAE,gBAAM;AFR7B,qBAEC;EC8DH,EAAG;IC5DG,iBAAoB,EAAE,cAAM;IAI5B,cAAiB,EAAE,cAAM;IAIzB,aAAgB,EAAE,cAAM;IAIxB,YAAe,EAAE,cAAM;IAIvB,SAAY,EAAE,cAAM;ED+C1B,IAAK;IC/DC,iBAAoB,EAAE,gBAAM;IAI5B,cAAiB,EAAE,gBAAM;IAIzB,aAAgB,EAAE,gBAAM;IAIxB,YAAe,EAAE,gBAAM;IAIvB,SAAY,EAAE,gBAAM;AFxCxB,gCAEC;EC2FH,EAAG;ICrEG,iBAAoB,EAAE,eAAM;EDwElC,IAAK;ICxEC,iBAAoB,EAAE,qBAAM;AFhBhC,6BAEC;ECmFH,EAAG;ICjEG,cAAiB,EAAE,eAAM;EDoE/B,IAAK;ICpEC,cAAiB,EAAE,qBAAM;AFR7B,wBAEC;ECuEH,EAAG;ICrEG,iBAAoB,EAAE,eAAM;IAI5B,cAAiB,EAAE,eAAM;IAIzB,aAAgB,EAAE,eAAM;IAIxB,YAAe,EAAE,eAAM;IAIvB,SAAY,EAAE,eAAM;EDwD1B,IAAK;ICxEC,iBAAoB,EAAE,qBAAM;IAI5B,cAAiB,EAAE,qBAAM;IAIzB,aAAgB,EAAE,qBAAM;IAIxB,YAAe,EAAE,qBAAM;IAIvB,SAAY,EAAE,qBAAM;AFxCxB,gCAEC;ECoGH,EAAG;IC9EG,iBAAoB,EAAE,eAAM;EDiFlC,IAAK;ICjFC,iBAAoB,EAAE,qBAAM;AFhBhC,6BAEC;EC4FH,EAAG;IC1EG,cAAiB,EAAE,eAAM;ED6E/B,IAAK;IC7EC,cAAiB,EAAE,qBAAM;AFR7B,wBAEC;ECgFH,EAAG;IC9EG,iBAAoB,EAAE,eAAM;IAI5B,cAAiB,EAAE,eAAM;IAIzB,aAAgB,EAAE,eAAM;IAIxB,YAAe,EAAE,eAAM;IAIvB,SAAY,EAAE,eAAM;EDiE1B,IAAK;ICjFC,iBAAoB,EAAE,qBAAM;IAI5B,cAAiB,EAAE,qBAAM;IAIzB,aAAgB,EAAE,qBAAM;IAIxB,YAAe,EAAE,qBAAM;IAIvB,SAAY,EAAE,qBAAM;AFxCxB,2BAEC;EC6GH,EAAG;ICvFG,iBAAoB,EAAE,eAAM;ED0FlC,GAAI;IC1FE,iBAAoB,EAAE,iBAAM;ED6FlC,GAAI;IC7FE,iBAAoB,EAAE,eAAM;EDgGlC,IAAK;IChGC,iBAAoB,EAAE,eAAM;AFhBhC,wBAEC;ECqGH,EAAG;ICnFG,cAAiB,EAAE,eAAM;EDsF/B,GAAI;ICtFE,cAAiB,EAAE,iBAAM;EDyF/B,GAAI;ICzFE,cAAiB,EAAE,eAAM;ED4F/B,IAAK;IC5FC,cAAiB,EAAE,eAAM;AFR7B,mBAEC;ECyFH,EAAG;ICvFG,iBAAoB,EAAE,eAAM;IAI5B,cAAiB,EAAE,eAAM;IAIzB,aAAgB,EAAE,eAAM;IAIxB,YAAe,EAAE,eAAM;IAIvB,SAAY,EAAE,eAAM;ED0E1B,GAAI;IC1FE,iBAAoB,EAAE,iBAAM;IAI5B,cAAiB,EAAE,iBAAM;IAIzB,aAAgB,EAAE,iBAAM;IAIxB,YAAe,EAAE,iBAAM;IAIvB,SAAY,EAAE,iBAAM;ED6E1B,GAAI;IC7FE,iBAAoB,EAAE,eAAM;IAI5B,cAAiB,EAAE,eAAM;IAIzB,aAAgB,EAAE,eAAM;IAIxB,YAAe,EAAE,eAAM;IAIvB,SAAY,EAAE,eAAM;EDgF1B,IAAK;IChGC,iBAAoB,EAAE,eAAM;IAI5B,cAAiB,EAAE,eAAM;IAIzB,aAAgB,EAAE,eAAM;IAIxB,YAAe,EAAE,eAAM;IAIvB,SAAY,EAAE,eAAM;AFxCxB,uBAEC;EC4HH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,cAAc;ADpIzB,oBAEC;ECoHH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,cAAc;ADxHzB,eAEC;ECwGH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,cAAc;AD5IzB,uBAEC;EC+IH,EAAG;IACD,OAAO,EAAE,CAAC;IC1HN,iBAAoB,EAAE,UAAM;ED6HlC,GAAI;IACF,OAAO,EAAE,CAAC;IC9HN,iBAAoB,EAAE,WAAM;EDiIlC,GAAI;ICjIE,iBAAoB,EAAE,UAAM;EDoIlC,GAAI;ICpIE,iBAAoB,EAAE,WAAM;EDuIlC,GAAI;ICvIE,iBAAoB,EAAE,UAAM;ED0IlC,IAAK;IACH,OAAO,EAAE,CAAC;IC3IN,iBAAoB,EAAE,QAAM;AFhBhC,oBAEC;ECuIH,EAAG;IACD,OAAO,EAAE,CAAC;ICtHN,cAAiB,EAAE,UAAM;EDyH/B,GAAI;IACF,OAAO,EAAE,CAAC;IC1HN,cAAiB,EAAE,WAAM;ED6H/B,GAAI;IC7HE,cAAiB,EAAE,UAAM;EDgI/B,GAAI;IChIE,cAAiB,EAAE,WAAM;EDmI/B,GAAI;ICnIE,cAAiB,EAAE,UAAM;EDsI/B,IAAK;IACH,OAAO,EAAE,CAAC;ICvIN,cAAiB,EAAE,QAAM;AFR7B,eAEC;EC2HH,EAAG;IACD,OAAO,EAAE,CAAC;IC1HN,iBAAoB,EAAE,UAAM;IAI5B,cAAiB,EAAE,UAAM;IAIzB,aAAgB,EAAE,UAAM;IAIxB,YAAe,EAAE,UAAM;IAIvB,SAAY,EAAE,UAAM;ED6G1B,GAAI;IACF,OAAO,EAAE,CAAC;IC9HN,iBAAoB,EAAE,WAAM;IAI5B,cAAiB,EAAE,WAAM;IAIzB,aAAgB,EAAE,WAAM;IAIxB,YAAe,EAAE,WAAM;IAIvB,SAAY,EAAE,WAAM;EDiH1B,GAAI;ICjIE,iBAAoB,EAAE,UAAM;IAI5B,cAAiB,EAAE,UAAM;IAIzB,aAAgB,EAAE,UAAM;IAIxB,YAAe,EAAE,UAAM;IAIvB,SAAY,EAAE,UAAM;EDoH1B,GAAI;ICpIE,iBAAoB,EAAE,WAAM;IAI5B,cAAiB,EAAE,WAAM;IAIzB,aAAgB,EAAE,WAAM;IAIxB,YAAe,EAAE,WAAM;IAIvB,SAAY,EAAE,WAAM;EDuH1B,GAAI;ICvIE,iBAAoB,EAAE,UAAM;IAI5B,cAAiB,EAAE,UAAM;IAIzB,aAAgB,EAAE,UAAM;IAIxB,YAAe,EAAE,UAAM;IAIvB,SAAY,EAAE,UAAM;ED0H1B,IAAK;IACH,OAAO,EAAE,CAAC;IC3IN,iBAAoB,EAAE,QAAM;IAI5B,cAAiB,EAAE,QAAM;IAIzB,aAAgB,EAAE,QAAM;IAIxB,YAAe,EAAE,QAAM;IAIvB,SAAY,EAAE,QAAM;AFxCxB,2BAEC;ECuKH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;EAEZ,GAAI;IACF,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,SAAS,EAAE,eAAe;AD5K1B,wBAEC;EC+JH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;EAEZ,GAAI;IACF,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,SAAS,EAAE,eAAe;ADhK1B,mBAEC;ECmJH,EAAG;IACD,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,gBAAgB;EAE7B,GAAI;IACF,OAAO,EAAE,CAAC;EAEZ,GAAI;IACF,SAAS,EAAE,gBAAgB;EAE7B,IAAK;IACH,SAAS,EAAE,eAAe;ADpL1B,uBAEC;ECuLH,EAAG;IACD,SAAS,EAAE,aAAa;EAE1B,IAAK;IACH,SAAS,EAAE,eAAe;ADrL1B,oBAEC;EC+KH,EAAG;IACD,SAAS,EAAE,aAAa;EAE1B,IAAK;IACH,SAAS,EAAE,eAAe;ADzK1B,eAEC;ECmKH,EAAG;IACD,SAAS,EAAE,aAAa;EAE1B,IAAK;IACH,SAAS,EAAE,eAAe;AD7L1B,0BAEC;ECgMH,EAAG;IACD,SAAS,EAAE,aAAa;IC3KpB,iCAAoB,EAAE,qCAAM;EDoLlC,GAAI;IACF,SAAS,EAAE,eAAe;ICrLtB,iCAAoB,EAAE,uCAAM;EDwLlC,GAAI;IACF,SAAS,EAAE,eAAe;ICzLtB,iCAAoB,EAAE,oCAAM;ED4LlC,GAAI;IACF,SAAS,EAAE,eAAe;EAE5B;MACK;IACH,SAAS,EAAE,aAAa;ADjNxB,uBAEC;ECwLH,EAAG;IACD,SAAS,EAAE,aAAa;ICvKpB,8BAAiB,EAAE,qCAAM;EDgL/B,GAAI;IACF,SAAS,EAAE,eAAe;ICjLtB,8BAAiB,EAAE,uCAAM;EDoL/B,GAAI;IACF,SAAS,EAAE,eAAe;ICrLtB,8BAAiB,EAAE,oCAAM;EDwL/B,GAAI;IACF,SAAS,EAAE,eAAe;EAE5B;MACK;IACH,SAAS,EAAE,aAAa;ADrMxB,kBAEC;EC4KH,EAAG;IACD,SAAS,EAAE,aAAa;IC3KpB,iCAAoB,EAAE,qCAAM;IAI5B,8BAAiB,EAAE,qCAAM;IAYzB,yBAAY,EAAE,qCAAM;EDoK1B,GAAI;IACF,SAAS,EAAE,eAAe;ICrLtB,iCAAoB,EAAE,uCAAM;IAI5B,8BAAiB,EAAE,uCAAM;IAYzB,yBAAY,EAAE,uCAAM;EDwK1B,GAAI;IACF,SAAS,EAAE,eAAe;ICzLtB,iCAAoB,EAAE,oCAAM;IAI5B,8BAAiB,EAAE,oCAAM;IAYzB,yBAAY,EAAE,oCAAM;ED4K1B,GAAI;IACF,SAAS,EAAE,eAAe;EAE5B;MACK;IACH,SAAS,EAAE,aAAa;ADzNxB,yBAEC;EC4NH;KACI;IACF,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;EAGZ,GAAI;IAEF,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,CAAC;EAEZ,GAAI;IACF,SAAS,EAAE,gBAAgB;IAC3B,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;ADvOV,sBAEC;ECoNH;KACI;IACF,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;EAGZ,GAAI;IAEF,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,CAAC;EAEZ,GAAI;IACF,SAAS,EAAE,gBAAgB;IAC3B,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;AD3NV,iBAEC;ECwMH;KACI;IACF,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;EAGZ,GAAI;IAEF,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,CAAC;EAEZ,GAAI;IACF,SAAS,EAAE,gBAAgB;IAC3B,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;AD/OV,2BAEC;ECkPH;KACI;IACF,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;EAGZ,GAAI;IAEF,SAAS,EAAE,gBAAgB;IAC3B,OAAO,EAAE,CAAC;EAEZ,GAAI;IAEF,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;AD9PV,wBAEC;EC0OH;KACI;IACF,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;EAGZ,GAAI;IAEF,SAAS,EAAE,gBAAgB;IAC3B,OAAO,EAAE,CAAC;EAEZ,GAAI;IAEF,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;ADlPV,mBAEC;EC8NH;KACI;IACF,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;EAGZ,GAAI;IAEF,SAAS,EAAE,gBAAgB;IAC3B,OAAO,EAAE,CAAC;EAEZ,GAAI;IAEF,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,CAAC;EAEZ,IAAK;IACH,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC;ADtQV,wBAEC;EC0QH,EAAG;IACD,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;EAEpD,GAAI;IACF,gBAAgB,EAAE,uBAAuB;IACzC,UAAU,EAAE,uBAAsC;EAEpD;KACI;IACF,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;EAEpD,IAAK;IACH,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;ADnRlD,qBAEC;ECkQH,EAAG;IACD,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;EAEpD,GAAI;IACF,gBAAgB,EAAE,uBAAuB;IACzC,UAAU,EAAE,uBAAsC;EAEpD;KACI;IACF,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;EAEpD,IAAK;IACH,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;ADvQlD,gBAEC;ECsPH,EAAG;IACD,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;EAEpD,GAAI;IACF,gBAAgB,EAAE,uBAAuB;IACzC,UAAU,EAAE,uBAAsC;EAEpD;KACI;IACF,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;EAEpD,IAAK;IACH,gBAAgB,EAAE,qBAAsB;IACxC,UAAU,EAAE,qCAAsC;AEtStD,IAAK;EACH,gBAAgB,EAAE,IAAI;EACtB,KAAK,ECAM,OAAO;EDClB,WAAW,ECgBO,kDAAkD;EDfpE,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,MAAM;EACnB,sBAAsB,EAAE,WAAW;EACnC,cAAc,EAAE,MAAM;EACtB,cAAc,EAAE,kBAAkB;EAClC,WAAW,EAAE,IAAI;;AAGnB,sBAAuB;EACrB,KAAK,ECXM,OAAO;EDYlB,WAAW,ECMM,yDAAyD;EDL1E,WAAW,EAAE,MAAM;EACnB,WAAW,EAAE,GAAG;EAChB,MAAM,EAAE,CAAC;;AAIT,0DAAuB;EACrB,KAAK,EAAE,IAAI;;AAIf;EACG;EACD,WAAW,ECRM,yDAAyD;EDS1E,cAAc,EAAE,IAAI;;AAGtB,EAAG;EACD,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,KAAK;EAClB,MAAM,EAAE,aAAa;;AAGvB,EAAG;EACD,MAAM,EAAE,QAAQ;EAChB,SAAS,EAAE,IAAI;;AAGjB,EAAG;EACD,SAAS,EAAE,IAAI;;AAGjB,EAAG;EACD,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,SAAS;;AAG3B,EAAG;EACD,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,MAAM;;AAGrB,CAAE;EACA,KAAK,ECvDQ,OAAO;EDwDpB,WAAW,EAAE,GAAG;EAChB,MAAM,EAAE,KAAK;;AAGf;EACG;EACD,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,CAAC;;AAGZ,MAAO;EACL,WAAW,ECxCC,uEAAuE;EDyCnF,WAAW,EAAE,MAAM;;AAGrB,CAAE;EErDA,kBAAkB,EAAE,wCAAK;EACzB,eAAe,EAAE,wCAAK;EACtB,cAAc,EAAE,wCAAK;EACrB,aAAa,EAAE,wCAAK;EACpB,UAAU,EAAE,wCAAK;EFmDjB,KAAK,EC1EM,OAAO;ED2ElB,eAAe,EAAE,IAAI;EAErB,0BAES;IACP,KAAK,EClFO,OAAO;IDmFnB,YAAY,ECnFA,OAAO;EDsFrB,SACK;IACH,WAAW,ECpEI,yDAAyD;IDqExE,aAAa,EAAE,iBAAsB;IACrC,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,OAAO;IAEf,qBAAQ;MACN,YAAY,EC9FF,OAAO;;ADqGvB,GAAI;EACF,OAAO,EAAE,KAAK;EACd,SAAS,EAAE,IAAI;;AGvGjB,IAAK;EAAE,UAAU,EAAE,UAAU;;AAC7B,oBAAqB;EAAE,UAAU,EAAE,OAAO;;AAE1C;IACK;EACH,MAAM,EAAC,IAAI;EACX,UAAU,EAAC,IAAI;EACf,KAAK,EAAE,IAAI;EACX,QAAQ,EAAE,IAAI;;AAGhB,IAAK;EACH,UAAU,EAAE,MAAM;EDPnB,0BAA2B;ICM5B,IAAK;MC0DD,OAAO,EAAE,WAAW;MACpB,OAAO,EAAE,QAAQ;MACjB,OAAO,EAAE,GAAG;MAGZ,OAAO,EAAE,YAAY;MACrB,OAAO,EAAE,SAAS;MAClB,OAAO,EAAE,WAAW;MACpB,OAAO,EAAE,IAAI;ML1CT,iBAAoB,EKmMd,MAAM;ML/LZ,cAAiB,EK+LX,MAAM;MLnLZ,SAAY,EKmLN,MAAM;MLnMZ,mBAAoB,EKmMd,MAAM;ML/LZ,gBAAiB,EK+LX,MAAM;ML3LZ,eAAgB,EK2LV,MAAM;MLvLZ,cAAe,EKuLT,MAAM;MLnLZ,WAAY,EKmLN,MAAM;MAelB,cAAc,EAfF,MAAM;MLnMZ,kBAAoB,EKyNb,OAAM;MLrNb,eAAiB,EKqNV,OAAM;MLzMb,UAAY,EKyML,OAAM;MAWnB,mBAAmB,EAXN,OAAM;MLzNb,kBAAoB,EKyFX,QAAQ;MLrFjB,eAAiB,EKqFR,QAAQ;MLzEjB,UAAY,EKyEH,QAAQ;MLzFjB,qBAAoB,EKiFd,MAAM;ML7EZ,kBAAiB,EK6EX,MAAM;MLjEZ,aAAY,EKiEN,MAAM;MLjFZ,sBAAoB,EKgFb,MAAM;ML5Eb,mBAAiB,EK4EV,MAAM;MLhEb,cAAY,EKgEL,MAAM;MAuBnB,kBAAkB,EAvBL,MAAM;MLhFb,gBAAoB,EK+Dd,CAAc;ML3DpB,aAAiB,EK2DX,CAAc;ML/CpB,QAAY,EK+CN,CAAc;ML/DpB,YAAoB,EIhBV,QAAQ;MJoBlB,SAAiB,EIpBP,QAAQ;MJwBlB,QAAgB,EIxBN,QAAQ;MJgClB,IAAY,EIhCF,QAAQ;MAEtB,QAAQ,EAAE,MAAM;;AAIpB;MACO;EACL,KAAK,EAAE,IAAI;;AAEb,WAAY;EACV,QAAQ,EAAE,KAAK;EACf,IAAI,EAAE,GAAG;EACT,GAAG,EAAE,GAAG;EACR,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,EAAE;EACX,gBAAgB,EAAE,IAAI;EACtB,aAAa,EAAE,iBAAsB;ED/BtC,0BAA2B;ICwB5B,WAAY;MAUR,gBAAgB,EAAE,WAAW;MAC7B,aAAa,EAAE,IAAI;;AAGvB,MAAO;EJRC,gBAAoB,EK+Dd,CAAc;EL3DpB,aAAiB,EK2DX,CAAc;EL/CpB,QAAY,EK+CN,CAAc;EL/DpB,YAAoB,EISZ,QAAQ;EJLhB,SAAiB,EIKT,QAAQ;EJDhB,QAAgB,EICR,QAAQ;EJOhB,IAAY,EIPJ,QAAQ;EJThB,kBAAoB,EKyNb,UAAM;ELrNb,eAAiB,EKqNV,UAAM;ELzMb,UAAY,EKyML,UAAM;EAWnB,mBAAmB,EATJ,KAAK;;AD/MtB,OAAQ;EJZA,gBAAoB,EK+Dd,CAAc;EL3DpB,aAAiB,EK2DX,CAAc;EL/CpB,QAAY,EK+CN,CAAc;EL/DpB,YAAoB,EIaZ,QAAQ;EJThB,SAAiB,EIST,QAAQ;EJLhB,QAAgB,EIKR,QAAQ;EJGhB,IAAY,EIHJ,QAAQ;EJbhB,kBAAoB,EKyNb,OAAM;ELrNb,eAAiB,EKqNV,OAAM;ELzMb,UAAY,EKyML,OAAM;EAWnB,mBAAmB,EAXN,OAAM;EDzMnB,QAAQ,EAAE,QAAQ;EAClB,QAAQ,EAAE,IAAI;EACd,0BAA0B,EAAE,KAAK;EACjC,OAAO,EAAE,CAAC;;AAEZ,MAAO;EJrBC,gBAAoB,EK+Dd,CAAc;EL3DpB,aAAiB,EK2DX,CAAc;EL/CpB,QAAY,EK+CN,CAAc;EL/DpB,YAAoB,EIsBZ,QAAQ;EJlBhB,SAAiB,EIkBT,QAAQ;EJdhB,QAAgB,EIcR,QAAQ;EJNhB,IAAY,EIMJ,QAAQ;EJtBhB,kBAAoB,EKyNb,QAAM;ELrNb,eAAiB,EKqNV,QAAM;ELzMb,UAAY,EKyML,QAAM;EAWnB,mBAAmB,EAPJ,GAAG;EDpMlB,gBAAgB,EAAE,OAAO;;AAG3B,QAAS;EACP,KAAK,EAAE,IAAI;EACX,QAAQ,EAAE,IAAI;EACd,OAAO,EAAE,CAAC;EACV,OAAO,EAAE,KAAK;ED9Df,0BAA2B;IC0D5B,QAAS;MCML,OAAO,EAAE,WAAW;MACpB,OAAO,EAAE,QAAQ;MACjB,OAAO,EAAE,GAAG;MAGZ,OAAO,EAAE,YAAY;MACrB,OAAO,EAAE,SAAS;MAClB,OAAO,EAAE,WAAW;MACpB,OAAO,EAAE,IAAI;ML1CT,gBAAoB,EK+Dd,CAAc;ML3DpB,aAAiB,EK2DX,CAAc;ML/CpB,QAAY,EK+CN,CAAc;ML/DpB,YAAoB,EIoCV,QAAQ;MJhClB,SAAiB,EIgCP,QAAQ;MJ5BlB,QAAgB,EI4BN,QAAQ;MJpBlB,IAAY,EIoBF,QAAQ;;AAI1B,UAAW;EACT,SAAS,EAAE,IAAI;EACf,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EAEX,eAAO;IACL,SAAS,EAAE,IAAI;;AAInB,QAAS;EAGP,OAAO,EAAE,SAAS;EAElB,+BACU;IACR,OAAO,EAAE,IAAI;ED3FhB,yBAA0B;ICoF3B,QAAS;MAWL,OAAO,EAAE,SAAS;MAElB,aAAO;QACL,OAAO,EAAE,SAAS;MAGpB,gBAAU;QACR,OAAO,EAAE,SAAS;EDlGvB,0BAA2B;ICgF5B,QAAS;MAuBL,OAAO,EAAE,SAAS;MAElB,aAAO;QACL,OAAO,EAAE,SAAS;MAGpB,gBAAU;QACR,OAAO,EAAE,IAAI;EDlGjB,yBAA0B;ICuGxB,uBAAU;MACR,WAAW,EAAE,IAAI;MACjB,cAAc,EAAE,IAAI;;AAK1B,OAAQ;EACN,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAI;EACX,aAAa,EAAE,IAAI;EACnB,OAAO,EAAE,CAAC;EAEV,kBAAa;IACX,aAAa,EAAE,CAAC;EDrHlB,yBAA0B;IC8G5B,OAAQ;MAWJ,aAAa,EAAE,IAAI;;AAqBvB;IACK;EJ7HG,qBAAoB,EK2Ob,OAAM;ELvOb,kBAAiB,EKuOV,OAAM;EL3Nb,aAAY,EK2NL,OAAM;EAenB,kBAAkB,EAfL,OAAM;EL3Ob,iBAAoB,EKmMd,MAAM;EL/LZ,cAAiB,EK+LX,MAAM;ELnLZ,SAAY,EKmLN,MAAM;ELnMZ,mBAAoB,EKmMd,MAAM;EL/LZ,gBAAiB,EK+LX,MAAM;EL3LZ,eAAgB,EK2LV,MAAM;ELvLZ,cAAe,EKuLT,MAAM;ELnLZ,WAAY,EKmLN,MAAM;EAelB,cAAc,EAfF,MAAM;EAjKhB,OAAO,EAAE,WAAW;EACpB,OAAO,EAAE,QAAQ;EACjB,OAAO,EAAE,GAAG;EAGZ,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,SAAS;EAClB,OAAO,EAAE,WAAW;EACpB,OAAO,EAAE,IAAI;EL1CT,kBAAoB,EKyFX,QAAQ;ELrFjB,eAAiB,EKqFR,QAAQ;ELzEjB,UAAY,EKyEH,QAAQ;ELzFjB,qBAAoB,EKiFd,MAAM;EL7EZ,kBAAiB,EK6EX,MAAM;ELjEZ,aAAY,EKiEN,MAAM;ELjFZ,sBAAoB,EKgFb,MAAM;EL5Eb,mBAAiB,EK4EV,MAAM;ELhEb,cAAY,EKgEL,MAAM;EAuBnB,kBAAkB,EAvBL,MAAM;EFlHpB,yBAA0B;IC8J3B;QACK;MJ7HG,kBAAoB,EKoFX,UAAU;MLhFnB,eAAiB,EKgFR,UAAU;MLpEnB,UAAY,EKoEH,UAAU;MLpFnB,qBAAoB,EKiFd,MAAM;ML7EZ,kBAAiB,EK6EX,MAAM;MLjEZ,aAAY,EKiEN,MAAM;MLjFZ,sBAAoB,EKgFb,GAAM;ML5Eb,mBAAiB,EK4EV,GAAM;MLhEb,cAAY,EKgEL,GAAM;MAuBnB,kBAAkB,EAvBL,GAAM;;AD2DrB,IAAK;ECzGD,OAAO,EAAE,WAAW;EACpB,OAAO,EAAE,QAAQ;EACjB,OAAO,EAAE,GAAG;EAGZ,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,SAAS;EAClB,OAAO,EAAE,WAAW;EACpB,OAAO,EAAE,IAAI;EL1CT,kBAAoB,EKoFX,UAAU;ELhFnB,eAAiB,EKgFR,UAAU;ELpEnB,UAAY,EKoEH,UAAU;ELpFnB,qBAAoB,EKiFd,MAAM;EL7EZ,kBAAiB,EK6EX,MAAM;ELjEZ,aAAY,EKiEN,MAAM;ELjFZ,sBAAoB,EKgFb,GAAM;EL5Eb,mBAAiB,EK4EV,GAAM;ELhEb,cAAY,EKgEL,GAAM;EAuBnB,kBAAkB,EAvBL,GAAM;ELhFb,iBAAoB,EI8IP,CAAC;EJ1Id,cAAiB,EI0IJ,CAAC;EJ9Hd,SAAY,EI8HC,CAAC;ECMpB,iBAAiB,EDNE,CAAC;EACpB,MAAM,EAAE,MAAM;;AAGhB;IACK;EACH,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,IAAI;;AAGd,KAAM;EJxJE,iBAAoB,EIyJP,CAAC;EJrJd,cAAiB,EIqJJ,CAAC;EJzId,SAAY,EIyIC,CAAC;ECLpB,iBAAiB,EDKE,CAAC;;AAGtB,IAAK;EJ5JG,iBAAoB,EI6JP,CAAC;EJzJd,cAAiB,EIyJJ,CAAC;EJ7Id,SAAY,EI6IC,CAAC;ECTpB,iBAAiB,EDSE,CAAC;;AEhMtB,OAAQ;EHqBN,kBAAkB,EAAE,8NAAK;EACzB,eAAe,EAAE,8NAAK;EACtB,cAAc,EAAE,8NAAK;EACrB,aAAa,EAAE,8NAAK;EACpB,UAAU,EAAE,8NAAK;EGrBjB,gBAAgB,EJJF,OAAO;EIKrB,MAAM,EAAE,IAAI;EACZ,aAAa,EJEN,GAAG;EIDV,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAI;EACX,WAAW,EJYI,uDAAuD;EIXtE,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,CAAC;EACjB,WAAW,EAAE,MAAM;EACnB,OAAO,EAAE,CAAC;EACV,OAAO,EAAE,IAAI;EACb,OAAO,EAAE,CAAC;EACV,QAAQ,EAAE,QAAQ;EAClB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,MAAM;EAClB,KAAK,EAAE,IAAI;EHlBZ,yBAA0B;IGD3B,OAAQ;MAsBJ,KAAK,EAAE,IAAI;EAGb,YAAO;IACL,KAAK,EAAE,IAAI;EAGb,4BACQ;IACN,gBAAgB,EAAE,OAA2B;IAC7C,KAAK,EAAE,IAAI;EAGb,aAAQ;IACN,OAAO,EAAE,IAAI;IACb,YAAY,EAAE,OAA0B;EAG1C,WAAM;IACJ,KAAK,EAAE,WAAW;EAGpB,YAAK;IHvBL,kBAAkB,EAAE,gBAAK;IACzB,eAAe,EAAE,gBAAK;IACtB,cAAc,EAAE,gBAAK;IACrB,aAAa,EAAE,gBAAK;IACpB,UAAU,EAAE,gBAAK;IGsBf,OAAO,EAAE,YAAY;IAErB,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,QAAQ;IAClB,UAAU,EAAE,MAAM;IAElB,kBAAQ;MNlBJ,iBAAoB,EAAE,mFAAM;MAI5B,cAAiB,EAAE,mFAAM;MAYzB,SAAY,EAAE,mFAAM;MG9B1B,kBAAkB,EAAE,kBAAK;MACzB,eAAe,EAAE,kBAAK;MACtB,cAAc,EAAE,kBAAK;MACrB,aAAa,EAAE,kBAAK;MACpB,UAAU,EAAE,kBAAK;MGiCb,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,aAAa,EAAE,GAAG;MAClB,MAAM,EAAE,cAAc;MACtB,gBAAgB,EAAE,WAAW;MAC7B,IAAI,EAAE,GAAG;MACT,OAAO,EAAE,CAAC;MACV,GAAG,EAAE,GAAG;MACR,MAAM,EAAE,eAAe;EAI3B,eAAU;IACR,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,OAA0B;IAE5C,oBAAK;MACH,KAAK,EAAE,WAAW;MAElB,0BAAQ;QN1CN,4BAAoB,EAAE,OAAM;QAI5B,yBAAiB,EAAE,OAAM;QAYzB,oBAAY,EAAE,OAAM;QM4BpB,OAAO,EAAE,CAAC;EAKhB,0CACc;IACZ,OAAO,EAAE,CAAC;;AAId,iBAAkB;EAChB,gBAAgB,EAAE,WAAW;EAC7B,MAAM,EAAE,iBAAwB;EAChC,KAAK,EJ7FS,OAAO;EI8FrB,SAAS,EAAE,IAAI;EAEf,uBAAQ;IACN,KAAK,EAAE,IAAI;IACX,gBAAgB,EJlGJ,OAAO;;AIsGvB,WAAY;EACV,KAAK,EAAE,IAAI;EACX,aAAa,EAAE,eAAe;;ACxGhC,2BAA4B;EAC1B,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,CAAC;;AAEhB,iBAAkB;EAChB,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,CAAC;;AAEhB,kBAAmB;EACjB,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,CAAC;;AAEhB,sBAAuB;EACrB,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,CAAC;;AAGhB,sCAAuC;EACrC,KAAK,EAAE,OAAO;;AAEhB,4BAA6B;EAC3B,KAAK,EAAE,OAAO;;AAEhB,6BAA8B;EAC5B,KAAK,EAAE,OAAO;;AAEhB,iCAAkC;EAChC,KAAK,EAAE,OAAO;;AAGhB,KAAM;EJTJ,kBAAkB,EAAE,+GAAK;EACzB,eAAe,EAAE,+GAAK;EACtB,cAAc,EAAE,+GAAK;EACrB,aAAa,EAAE,+GAAK;EACpB,UAAU,EAAE,+GAAK;EIQjB,UAAU,EAAE,iBAAsB;EAClC,aAAa,EAAE,iBAAsB;EACrC,KAAK,EAAE,OAAO;EACd,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,KAAK;EACd,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,+DAA+D;EAC5E,WAAW,EAAE,GAAG;EAChB,OAAO,EAAE,SAAS;EAClB,QAAQ,EAAE,QAAQ;EAClB,UAAU,EAAE,IAAI;EAChB,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,CAAC;EAEV,kBAAa;IJ1Bb,kBAAkB,EAAE,kDAAK;IACzB,eAAe,EAAE,kDAAK;IACtB,cAAc,EAAE,kDAAK;IACrB,aAAa,EAAE,kDAAK;IACpB,UAAU,EAAE,kDAAK;IIyBf,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,CAAC;IACd,aAAa,EAAE,GAAG;IAClB,OAAO,EAAE,CAAC;EAGZ,eAAY;IACV,gBAAgB,ELtDJ,OAAO;IKuDnB,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,CAAC;IAEV,oCAAqB;MACnB,KAAK,EL9DE,OAAO;IKiEhB,4BAAa;MACX,KAAK,EAAE,IAAI;EAKb,4BAAa;IACX,OAAO,EAAE,CAAC;;AAIhB,KAAM;EACJ,gBAAgB,EAAE,WAAW;EAC7B,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,OAAO;EACf,SAAS,EAAE,IAAI;EACf,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,CAAC;EACd,KAAK,EAAE,IAAI;;AAEb,cAAe;EACb,QAAQ,EAAE,QAAQ;;AAIlB,qBAAM;EJzEN,kBAAkB,EAAE,oEAAK;EACzB,eAAe,EAAE,oEAAK;EACtB,cAAc,EAAE,oEAAK;EACrB,aAAa,EAAE,oEAAK;EACpB,UAAU,EAAE,oEAAK;EHUX,iBAAoB,EAAE,iBAAM;EAI5B,cAAiB,EAAE,iBAAM;EAIzB,aAAgB,EAAE,iBAAM;EAIxB,YAAe,EAAE,iBAAM;EAIvB,SAAY,EAAE,iBAAM;EO8CxB,OAAO,EAAE,MAAM;AAGjB,qBAAQ;EJ/ER,kBAAkB,EAAE,iBAAK;EACzB,eAAe,EAAE,iBAAK;EACtB,cAAc,EAAE,iBAAK;EACrB,aAAa,EAAE,iBAAK;EACpB,UAAU,EAAE,iBAAK;EHUX,iBAAoB,EAAE,gBAAM;EAI5B,cAAiB,EAAE,gBAAM;EAIzB,aAAgB,EAAE,gBAAM;EAIxB,YAAe,EAAE,gBAAM;EAIvB,SAAY,EAAE,gBAAM;EOqDxB,OAAO,EAAE,GAAG;EACZ,KAAK,ELvGI,OAAO;EKwGhB,OAAO,EAAE,YAAY;EACrB,WAAW,EAAE,CAAC;EACd,IAAI,EAAE,GAAG;EACT,OAAO,EAAE,CAAC;EACV,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;AAKR,kEAAM;EPjFF,iBAAoB,EAAE,eAAM;EAI5B,cAAiB,EAAE,eAAM;EAIzB,aAAgB,EAAE,eAAM;EAIxB,YAAe,EAAE,eAAM;EAIvB,SAAY,EAAE,eAAM;AOsE1B,kEACmB;EACjB,OAAO,EAAE,CAAC;;AC3Hd,MAAO;ELqBL,kBAAkB,EAAE,0GAAK;EACzB,eAAe,EAAE,0GAAK;EACtB,cAAc,EAAE,0GAAK;EACrB,aAAa,EAAE,0GAAK;EACpB,UAAU,EAAE,0GAAK;EHUX,iBAAoB,EAAE,UAAM;EAI5B,cAAiB,EAAE,UAAM;EAIzB,aAAgB,EAAE,UAAM;EAIxB,YAAe,EAAE,UAAM;EAIvB,SAAY,EAAE,UAAM;EQ/C1B,gBAAgB,EAAE,yBAAqB;EACvC,MAAM,EAAE,IAAI;EACZ,OAAO,EAAE,CAAC;EACV,QAAQ,EAAE,IAAI;EACd,OAAO,EAAE,GAAG;EACZ,cAAc,EAAE,IAAI;EACpB,QAAQ,EAAE,KAAK;EACf,GAAG,EAAE,GAAG;EACR,IAAI,EAAE,GAAG;EACT,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,GAAG;EAEZ,aAAS;IRmBH,iBAAoB,EAAE,QAAM;IAI5B,cAAiB,EAAE,QAAM;IAIzB,aAAgB,EAAE,QAAM;IAIxB,YAAe,EAAE,QAAM;IAIvB,SAAY,EAAE,QAAM;IQjCxB,OAAO,EAAE,CAAC;IACV,cAAc,EAAE,IAAI;;AAIxB,gBAAiB;EACf,gBAAgB,EAAE,IAAI;EACtB,UAAU,EAAE,oBAAoB;EAChC,MAAM,EAAE,MAAM;EACd,SAAS,EAAE,IAAI;EACf,OAAO,EAAE,CAAC;EACV,UAAU,EAAE,IAAI;;AAGlB,cAAe;EACb,WAAW,EAAE,iBAAsB;EACnC,YAAY,EAAE,iBAAsB;EACpC,OAAO,EAAE,IAAI;;AAGf,aAAc;EACZ,MAAM,EAAE,iBAAsB;EAC9B,aAAa,EAAE,WAAW;EAC1B,OAAO,EAAE,GAAG;EACZ,UAAU,EAAE,MAAM;EAClB,QAAQ,EAAE,QAAQ;;AAGpB,YAAa;ELzBX,kBAAkB,EAAE,eAAK;EACzB,eAAe,EAAE,eAAK;EACtB,cAAc,EAAE,eAAK;EACrB,aAAa,EAAE,eAAK;EACpB,UAAU,EAAE,eAAK;EHUX,iBAAoB,EAAE,gBAAM;EAI5B,cAAiB,EAAE,gBAAM;EAIzB,aAAgB,EAAE,gBAAM;EAIxB,YAAe,EAAE,gBAAM;EAIvB,SAAY,EAAE,gBAAM;EQD1B,KAAK,EAAE,OAAO;EACd,OAAO,EAAE,SAAS;EAClB,QAAQ,EAAE,QAAQ;EAClB,GAAG,EAAE,GAAG;EACR,KAAK,EAAE,GAAG;EACV,WAAW,EN3BC,kFAAkF;EM4B9F,SAAS,EAAE,IAAI;EACf,OAAO,EAAE,KAAK;EACd,WAAW,EAAE,CAAC;EAEd,kBAAQ;IACN,KAAK,EN7DO,OAAO;;AOAvB,aAAa;AAGX,YAAM;EACJ,UAAU,EAAE,IAAI;;AAIpB;;UAEW;EACT,OAAO,EAAE,YAAY;EACrB,eAAe,EAAE,IAAI;EACrB,cAAc,EAAE,MAAM;;AAGxB;UACW;EACT,gBAAgB,EAAE,IAAI;EACtB,OAAO,EAAE,OAAO;EAChB,MAAM,EAAE,MAAM;;AAGhB,WAAY;ENFV,kBAAkB,EAAE,gBAAK;EACzB,eAAe,EAAE,gBAAK;EACtB,cAAc,EAAE,gBAAK;EACrB,aAAa,EAAE,gBAAK;EACpB,UAAU,EAAE,gBAAK;EHUX,yBAAoB,ESVX,CAAC;ETcV,sBAAiB,ESdR,CAAC;ET0BV,iBAAY,ES1BH,CAAC;ETUV,aAAoB,ESVX,CAAC;ETcV,UAAiB,ESdR,CAAC;ET0BV,KAAY,ES1BH,CAAC;EJwJhB,cAAc,EIxJC,CAAC;EAEhB,KAAK,EPzBM,OAAO;EO0BlB,WAAW,EPCN,sEAAsE;EOA3E,UAAU,EAAE,IAAI;EAEhB,kBAAO;IACL,WAAW,EPDH,mEAAmE;EC9B9E,yBAA0B;IMsB3B,WAAY;MTYJ,yBAAoB,ESCT,CAAC;MTGZ,sBAAiB,ESHN,CAAC;MTeZ,iBAAY,ESfD,CAAC;MTDZ,aAAoB,ESCT,CAAC;MTGZ,UAAiB,ESHN,CAAC;MTeZ,KAAY,ESfD,CAAC;MJ6IlB,cAAc,EI7IG,CAAC;EAGlB,iBAAQ;IACN,KAAK,EPrCM,OAAO;;AOyCtB,UAAW;ENvBT,kBAAkB,EAAE,kBAAK;EACzB,eAAe,EAAE,kBAAK;EACtB,cAAc,EAAE,kBAAK;EACrB,aAAa,EAAE,kBAAK;EACpB,UAAU,EAAE,kBAAK;EHUX,yBAAoB,ESWX,CAAC;ETPV,sBAAiB,ESOR,CAAC;ETKV,iBAAY,ESLH,CAAC;ETXV,aAAoB,ESWX,CAAC;ETPV,UAAiB,ESOR,CAAC;ETKV,KAAY,ESLH,CAAC;EJmIhB,cAAc,EInIC,CAAC;EAEhB,KAAK,EP9CM,OAAO;EO+ClB,SAAS,EAAE,IAAI;EACf,WAAW,EP7BI,uDAAuD;EO8BtE,OAAO,EAAE,EAAE;EAEX,sBAAc;IACZ,OAAO,EAAE,IAAI;EAGf,gBAAQ;IACN,gBAAgB,EAAE,WAAW;IAC7B,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,CAAC;EN3Db,yBAA0B;IM2C3B,UAAW;MTTH,yBAAoB,ES6BT,CAAC;MTzBZ,sBAAiB,ESyBN,CAAC;MTbZ,iBAAY,ESaD,CAAC;MT7BZ,aAAoB,ES6BT,CAAC;MTzBZ,UAAiB,ESyBN,CAAC;MTbZ,KAAY,ESaD,CAAC;MJiHlB,cAAc,EIjHG,CAAC;MAEhB,sBAAc;QACZ,OAAO,EAAE,YAAY;EAIzB,gBAAQ;IACN,OAAO,EAAE,CAAC;EAGZ,0CACS;IACP,KAAK,EP3EI,OAAO;ECGnB,0BAA2B;IM2E1B,uBAAe;MT7CT,iBAAoB,EAAE,6EAAM;MAI5B,cAAiB,EAAE,6EAAM;MAYzB,SAAY,EAAE,6EAAM;ESmC1B,kBAAU;ITnDJ,iBAAoB,EAAE,uEAAM;IAI5B,cAAiB,EAAE,uEAAM;IAYzB,SAAY,EAAE,uEAAM;IAhBpB,uBAAoB,EAAE,EAAM;IAI5B,oBAAiB,EAAE,EAAM;IAYzB,eAAY,EAAE,EAAM;;AUnD5B,eAAgB;EACd,WAAW,ERmBM,yDAAyD;EQf1E,UAAU,EAAE,MAAM;EAClB,KAAK,EAAE,IAAI;EACX,QAAQ,EAAE,MAAM;;AAKlB,OAAQ;EPSN,kBAAkB,EAAE,oDAAK;EACzB,eAAe,EAAE,oDAAK;EACtB,cAAc,EAAE,oDAAK;EACrB,aAAa,EAAE,oDAAK;EACpB,UAAU,EAAE,oDAAK;EHUX,iBAAoB,EAAE,iBAAM;EAI5B,cAAiB,EAAE,iBAAM;EAIzB,aAAgB,EAAE,iBAAM;EAIxB,YAAe,EAAE,iBAAM;EAIvB,SAAY,EAAE,iBAAM;EUpC1B,aAAa,EAAE,GAAG;EAElB,gBAAgB,EAAE,OAAO;EACzB,KAAK,ERfQ,OAAO;EQiBpB,OAAO,EAAE,IAAI;EACb,KAAK,EAAE,IAAI;EAEX,aAAQ;IACN,gBAAgB,ERlBN,OAAO;IQmBjB,KAAK,EAAE,IAAI;EAGb,YAAO;IVOD,iBAAoB,EAAE,cAAM;IAI5B,cAAiB,EAAE,cAAM;IAIzB,aAAgB,EAAE,cAAM;IAIxB,YAAe,EAAE,cAAM;IAIvB,SAAY,EAAE,cAAM;;AWnD5B,KAAM;EACJ,KAAK,EAAE,IAAI;;AAGb,EAAG;EACD,UAAU,EAAE,iBAAsB;EAElC,aAAa;IACX,aAAa,EAAE,iBAAsB;;AAIzC;EACG;ERgBD,aAAa,EAAE,UAAU;EACzB,SAAS,EAAE,UAAU;EACrB,cAAc,EAAE,SAAS;EACzB,UAAU,EAAE,UAAU;EACtB,WAAW,EAAE,IAAI;EACjB,YAAY,EAAE,IAAI;EAClB,eAAe,EAAE,IAAI;EACrB,OAAO,EAAE,IAAI;EQrBb,WAAW,EAAE,KAAK;EAClB,SAAS,EAAE,IAAI;EACf,cAAc,EAAE,KAAK;EACrB,OAAO,EAAE,MAAM;EACf,cAAc,EAAE,GAAG;EACnB,UAAU,EAAE,IAAI;;AAGlB,EAAG;EACD,KAAK,ETrBQ,OAAO;ESsBpB,WAAW,EAAE,MAAM;EACnB,WAAW,ETPO,kDAAkD;;ASUtE,EAAG;EACD,KAAK,ET5BM,OAAO;ES6BlB,WAAW,ETXM,yDAAyD;ESY1E,KAAK,EAAE,GAAG;EACV,OAAO,EAAE,gBAAgB;;ACjC3B,SAAU;EACR,UAAU,EAAE,IAAI;EAEhB,iBAAQ;IACN,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,MAAM;ITJlB,yBAA0B;MSEzB,iBAAQ;QAKJ,OAAO,EAAE,MAAM;ITHpB,0BAA2B;MSF1B,iBAAQ;QASJ,OAAO,EAAE,MAAM;EAInB,iBAAU;IZmBJ,iBAAoB,EAAE,sEAAM;IAI5B,cAAiB,EAAE,sEAAM;IAYzB,SAAY,EAAE,sEAAM;EY/B1B;;;mBAGQ;IZYF,iBAAoB,EAAE,mEAAM;IAI5B,cAAiB,EAAE,mEAAM;IAYzB,SAAY,EAAE,mEAAM;EYxB1B,YAAS;IZQH,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;EYvB1B,kBAAS;IZOH,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;EYtB1B,iBAAS;IZMH,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;IAhBpB,0BAAoB,EAAE,KAAM;IAI5B,uBAAiB,EAAE,KAAM;IAYzB,kBAAY,EAAE,KAAM;EYrB1B,iBAAS;IZKH,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;IAhBpB,0BAAoB,EAAE,KAAM;IAI5B,uBAAiB,EAAE,KAAM;IAYzB,kBAAY,EAAE,KAAM;;AanD5B,mBAAoB;EAClB,QAAQ,EAAE,QAAQ;EAClB,OAAO,EAAE,CAAC;;AAGZ,uBAAwB;EAEtB,gBAAgB,EXFF,OAAO;EWKrB,MAAM,EAAE,KAAK;EACb,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;EAClB,KAAK,EXVQ,OAAO;EWWpB,MAAM,EAAE,kBAAuB;EAC/B,aAAa,EAAE,IAAI;EACnB,OAAO,EAAE,KAAK;EAEd,8BAAS;IACP,OAAO,EAAE,WAAW;IACpB,KAAK,EXjBM,OAAO;IWoBlB,OAAO,EAAE,UAAU;IACnB,cAAc,EAAE,MAAM;;ACxB1B,SAAU;EACR,UAAU,EAAE,MAAM;EXInB,0BAA2B;IWL5B,SAAU;MdmCF,iBAAoB,EAAE,6EAAM;MAI5B,cAAiB,EAAE,6EAAM;MAYzB,SAAY,EAAE,6EAAM;Mc9CxB,OAAO,EAAE,CAAC;MACV,KAAK,EAAE,GAAG;MACV,KAAK,EAAE,IAAI;EAGb;;;mBAGQ;IdsBF,iBAAoB,EAAE,mEAAM;IAI5B,cAAiB,EAAE,mEAAM;IAYzB,SAAY,EAAE,mEAAM;EclC1B,eAAS;IdkBH,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;EcjC1B,YAAS;IdiBH,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;EchC1B,gCAAwB;IdgBlB,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;Ec/B1B,gCAAwB;IdelB,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;Ec9B1B,gCAAwB;IdclB,uBAAoB,EAAE,KAAM;IAI5B,oBAAiB,EAAE,KAAM;IAYzB,eAAY,EAAE,KAAM;Ec7B1B,gCAAwB;IdalB,uBAAoB,EAAE,MAAM;IAI5B,oBAAiB,EAAE,MAAM;IAYzB,eAAY,EAAE,MAAM;Ec5B1B,4BAAmB;IdYb,0BAAoB,EAAE,KAAM;IAI5B,uBAAiB,EAAE,KAAM;IAYzB,kBAAY,EAAE,KAAM;Ec1B1B,eAAM;IACJ,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,MAAM;EAGhB,YAAG;IACD,MAAM,EAAE,aAAa;EAGvB,eAAM;IACJ,OAAO,EAAE,KAAK;EAIhB,WAAE;IACA,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,MAAM;EAGhB,iBAAQ;IACN,UAAU,EAAE,GAAG;;AC9CnB,YAAa;EfmCL,iBAAoB,EAAE,yEAAM;EAI5B,cAAiB,EAAE,yEAAM;EAYzB,SAAY,EAAE,yEAAM;EehD1B,KAAK,EAAE,IAAI;EACX,gBAAgB,EbFL,OAAO;EaGlB,UAAU,EAAE,IAAI;EZAjB,0BAA2B;IYL5B,YAAa;MVqET,OAAO,EAAE,WAAW;MACpB,OAAO,EAAE,QAAQ;MACjB,OAAO,EAAE,GAAG;MAGZ,OAAO,EAAE,YAAY;MACrB,OAAO,EAAE,SAAS;MAClB,OAAO,EAAE,WAAW;MACpB,OAAO,EAAE,IAAI;ML1CT,gBAAoB,EK+Dd,CAAc;ML3DpB,aAAiB,EK2DX,CAAc;ML/CpB,QAAY,EK+CN,CAAc;ML/DpB,YAAoB,Ee1BV,QAAQ;Mf8BlB,SAAiB,Ee9BP,QAAQ;MfkClB,QAAgB,EelCN,QAAQ;Mf0ClB,IAAY,Ee1CF,QAAQ;Mf0BlB,kBAAoB,EKyNb,OAAM;MLrNb,eAAiB,EKqNV,OAAM;MLzMb,UAAY,EKyML,OAAM;MAWnB,mBAAmB,EAXN,OAAM;MLzNb,kBAAoB,EKyFX,QAAQ;MLrFjB,eAAiB,EKqFR,QAAQ;MLzEjB,UAAY,EKyEH,QAAQ;MLzFjB,qBAAoB,EKiFd,MAAM;ML7EZ,kBAAiB,EK6EX,MAAM;MLjEZ,aAAY,EKiEN,MAAM;MLjFZ,sBAAoB,EKgFb,MAAM;ML5Eb,mBAAiB,EK4EV,MAAM;MLhEb,cAAY,EKgEL,MAAM;MAuBnB,kBAAkB,EAvBL,MAAM;MLhFb,iBAAoB,EAAE,yEAAM;MAI5B,cAAiB,EAAE,yEAAM;MAYzB,SAAY,EAAE,yEAAM;MerCxB,OAAO,EAAE,CAAC;MACV,QAAQ,EAAE,KAAK;MACf,KAAK,EAAE,OAAO;MACd,KAAK,EAAE,QAAQ;MACf,MAAM,EAAE,IAAI;MACZ,MAAM,EAAE,KAAK;MACb,KAAK,EAAE,GAAG;MACV,GAAG,EAAE,GAAG;MACR,MAAM,EAAE,GAAG;MACX,OAAO,EAAE,GAAG;MACZ,QAAQ,EAAE,MAAM;MAEhB,iBAAO;QfSH,iBAAoB,EAAE,0EAAM;QAI5B,cAAiB,EAAE,0EAAM;QAYzB,SAAY,EAAE,0EAAM;QAhBpB,uBAAoB,EAAE,EAAM;QAI5B,oBAAiB,EAAE,EAAM;QAYzB,eAAY,EAAE,EAAM;EejB1B;sBACQ;IACN,KAAK,EAAE,IAAI;EAGb,mBAAO;IACL,QAAQ,EAAE,QAAQ;IAClB,aAAa,EAAE,iBAAiB;IAChC,UAAU,EAAE,MAAM;IAClB,OAAO,EAAE,EAAE;IAEX,0BAAS;MACP,OAAO,EAAE,IAAI;MAEb,QAAQ,EAAE,QAAQ;MAClB,cAAc,EAAE,IAAI;MACpB,GAAG,EAAE,IAAI;MACT,MAAM,EAnBe,IAAI;MAoBzB,UAAU,EAAE,GAAG;MACf,gBAAgB,EAAE,6DAAiE;MACnF,gBAAgB,EAAE,wDAA4D;MAC9E,gBAAgB,EAAE,qDAAyD;EAI/E,oBAAQ;IACN,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,EAAE;IAEX,uDACQ;MAEN,QAAQ,EAAE,KAAK;MACf,cAAc,EAAE,IAAI;MACpB,OAAO,EAAE,IAAI;IZ/DlB,0BAA2B;MYsD1B,oBAAQ;QAaJ,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,KAAK;IAaf,0BAAQ;MACN,OAAO,EAAE,IAAI;MACb,GAAG,EAAE,IAAI;MACT,MAAM,EAAE,GAAG;MACX,MAAM,EA1De,IAAI;MA2DzB,gBAAgB,EAAE,6DAAiE;MACnF,gBAAgB,EAAE,wDAA4D;MAC9E,gBAAgB,EAAE,qDAAyD;EZxFhF,0BAA2B;IY6FxB;+BACe;MACb,OAAO,EAAE,KAAK;EAIlB,eAAG;IACD,WAAW,EbrFI,yDAAyD;IasFxE,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,KAAK;IAClB,SAAS,EAAE,IAAI;IACf,cAAc,EAAE,KAAK;IACrB,MAAM,EAAE,QAAQ;EAGlB,eAAG;IACD,YAAY,EAAE,OAAO;EAGvB;iBACG;IACD,SAAS,EAAE,IAAI;EAGjB,eAAG;IACD,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,GAAG;EAGZ,eAAG;IACD,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,GAAG;EAGZ,cAAE;IACA,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;EAGjB,wBAAY;IACV,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,yBAAwB;IACpC,KAAK,EAAE,sBAAqB;IAC5B,WAAW,EAAE,IAAI", 4 | "sources": ["vendor/_normalize.scss","base/_utility.scss","base/_fonts.scss","vendor/bourbon/css3/_keyframes.scss","base/_animations.scss","vendor/bourbon/addons/_prefixer.scss","base/_base.scss","base/_variables.scss","base/_mixins.scss","base/_layout.scss","vendor/bourbon/css3/_flex-box.scss","components/_buttons.scss","components/_forms.scss","components/_modals.scss","components/_header.scss","components/_notices.scss","components/_tables.scss","modules/_checkout.scss","modules/_dropin.scss","modules/_response.scss","modules/_drawer.scss"], 5 | "names": [], 6 | "file": "app.css" 7 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/app.css.erb: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | html { 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 5 | -ms-text-size-adjust: 100%; 6 | -webkit-text-size-adjust: 100%; 7 | } 8 | 9 | body { 10 | margin: 0; 11 | } 12 | 13 | article, 14 | aside, 15 | details, 16 | figcaption, 17 | figure, 18 | footer, 19 | header, 20 | hgroup, 21 | main, 22 | menu, 23 | nav, 24 | section, 25 | summary { 26 | display: block; 27 | } 28 | 29 | audio, 30 | canvas, 31 | progress, 32 | video { 33 | display: inline-block; 34 | vertical-align: baseline; 35 | } 36 | 37 | audio:not([controls]) { 38 | display: none; 39 | height: 0; 40 | } 41 | 42 | [hidden], 43 | template { 44 | display: none; 45 | } 46 | 47 | a { 48 | background-color: transparent; 49 | } 50 | 51 | a:active, 52 | a:hover { 53 | outline: 0; 54 | } 55 | 56 | abbr[title] { 57 | border-bottom: 1px dotted; 58 | } 59 | 60 | b, 61 | strong { 62 | font-weight: bold; 63 | } 64 | 65 | dfn { 66 | font-style: italic; 67 | } 68 | 69 | h1 { 70 | font-size: 2em; 71 | margin: 0.67em 0; 72 | } 73 | 74 | mark { 75 | background: #ff0; 76 | color: #000; 77 | } 78 | 79 | small { 80 | font-size: 80%; 81 | } 82 | 83 | sub, 84 | sup { 85 | font-size: 75%; 86 | line-height: 0; 87 | position: relative; 88 | vertical-align: baseline; 89 | } 90 | 91 | sup { 92 | top: -0.5em; 93 | } 94 | 95 | sub { 96 | bottom: -0.25em; 97 | } 98 | 99 | img { 100 | border: 0; 101 | } 102 | 103 | svg:not(:root) { 104 | overflow: hidden; 105 | } 106 | 107 | figure { 108 | margin: 1em 40px; 109 | } 110 | 111 | hr { 112 | -moz-box-sizing: content-box; 113 | -webkit-box-sizing: content-box; 114 | box-sizing: content-box; 115 | height: 0; 116 | } 117 | 118 | pre { 119 | overflow: auto; 120 | } 121 | 122 | code, 123 | kbd, 124 | pre, 125 | samp { 126 | font-family: monospace, monospace; 127 | font-size: 1em; 128 | } 129 | 130 | button, 131 | input, 132 | optgroup, 133 | select, 134 | textarea { 135 | color: inherit; 136 | font: inherit; 137 | margin: 0; 138 | } 139 | 140 | button { 141 | overflow: visible; 142 | } 143 | 144 | button, 145 | select { 146 | text-transform: none; 147 | } 148 | 149 | button, 150 | html input[type="button"], 151 | input[type="reset"], 152 | input[type="submit"] { 153 | -webkit-appearance: button; 154 | cursor: pointer; 155 | } 156 | 157 | button[disabled], 158 | html input[disabled] { 159 | cursor: default; 160 | } 161 | 162 | button::-moz-focus-inner, 163 | input::-moz-focus-inner { 164 | border: 0; 165 | padding: 0; 166 | } 167 | 168 | input { 169 | line-height: normal; 170 | } 171 | 172 | input[type="checkbox"], 173 | input[type="radio"] { 174 | -webkit-box-sizing: border-box; 175 | -moz-box-sizing: border-box; 176 | box-sizing: border-box; 177 | padding: 0; 178 | } 179 | 180 | input[type="number"]::-webkit-inner-spin-button, 181 | input[type="number"]::-webkit-outer-spin-button { 182 | height: auto; 183 | } 184 | 185 | input[type="search"] { 186 | -webkit-appearance: textfield; 187 | -moz-box-sizing: content-box; 188 | -webkit-box-sizing: content-box; 189 | box-sizing: content-box; 190 | } 191 | 192 | input[type="search"]::-webkit-search-cancel-button, 193 | input[type="search"]::-webkit-search-decoration { 194 | -webkit-appearance: none; 195 | } 196 | 197 | fieldset { 198 | border: 1px solid #c0c0c0; 199 | margin: 0 2px; 200 | padding: 0.35em 0.625em 0.75em; 201 | } 202 | 203 | legend { 204 | border: 0; 205 | padding: 0; 206 | } 207 | 208 | textarea { 209 | overflow: auto; 210 | } 211 | 212 | optgroup { 213 | font-weight: bold; 214 | } 215 | 216 | table { 217 | border-collapse: collapse; 218 | border-spacing: 0; 219 | } 220 | 221 | td, 222 | th { 223 | padding: 0; 224 | } 225 | 226 | .clearfix:after, 227 | .content:after, 228 | .row:after { 229 | content: ""; 230 | display: table; 231 | clear: both; 232 | } 233 | 234 | .stage-wrapper { 235 | display: table; 236 | width: 100%; 237 | height: 100%; 238 | overflow: auto; 239 | } 240 | 241 | .stage { 242 | display: table-cell; 243 | vertical-align: middle; 244 | } 245 | 246 | .full { 247 | display: block; 248 | width: 100%; 249 | } 250 | 251 | .right { 252 | float: right; 253 | } 254 | 255 | .left { 256 | float: left; 257 | } 258 | 259 | .center { 260 | text-align: center; 261 | margin-left: auto; 262 | margin-right: auto; 263 | } 264 | 265 | .small { 266 | font-size: 14px; 267 | } 268 | 269 | .pseudo, 270 | .button span:after, 271 | aside.drawer header:before, 272 | aside.drawer article:before, 273 | aside.drawer article:after { 274 | content: ""; 275 | display: inline-block; 276 | height: 100%; 277 | left: 0px; 278 | position: absolute; 279 | top: 0px; 280 | width: 100%; 281 | } 282 | 283 | @font-face { 284 | font-family: 'Open Sans light'; 285 | src: url("../fonts/open-sans/OpenSans-Light-webfont.eot"); 286 | src: url("../fonts/open-sans/OpenSans-Light-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/open-sans/OpenSans-Light-webfont.woff") format("woff"), url("../fonts/open-sans/OpenSans-Light-webfont.ttf") format("truetype"), url("../fonts/open-sans/OpenSans-Light-webfont.svg#open_sansbold") format("svg"); 287 | font-weight: normal; 288 | font-style: normal; 289 | } 290 | 291 | @font-face { 292 | font-family: 'Open Sans regular'; 293 | src: url("../fonts/open-sans/OpenSans-Regular-webfont.eot"); 294 | src: url("../fonts/open-sans/OpenSans-Regular-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/open-sans/OpenSans-Regular-webfont.woff") format("woff"), url("../fonts/open-sans/OpenSans-Regular-webfont.ttf") format("truetype"), url("../fonts/open-sans/OpenSans-Regular-webfont.svg#open_sansregular") format("svg"); 295 | font-weight: normal; 296 | font-style: normal; 297 | } 298 | 299 | @font-face { 300 | font-family: 'Open Sans semibold'; 301 | src: url("../fonts/open-sans/OpenSans-Semibold-webfont.eot"); 302 | src: url("../fonts/open-sans/OpenSans-Semibold-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/open-sans/OpenSans-Semibold-webfont.woff") format("woff"), url("../fonts/open-sans/OpenSans-Semibold-webfont.ttf") format("truetype"), url("../fonts/open-sans/OpenSans-Semibold-webfont.svg#open_sanssemibold") format("svg"); 303 | font-weight: normal; 304 | font-style: normal; 305 | } 306 | 307 | @font-face { 308 | font-family: 'Open Sans bold'; 309 | src: url("../fonts/open-sans/OpenSans-Bold-webfont.eot"); 310 | src: url("../fonts/open-sans/OpenSans-Bold-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/open-sans/OpenSans-Bold-webfont.woff") format("woff"), url("../fonts/open-sans/OpenSans-Bold-webfont.ttf") format("truetype"), url("../fonts/open-sans/OpenSans-Bold-webfont.svg#open_sansbold") format("svg"); 311 | font-weight: normal; 312 | font-style: normal; 313 | } 314 | 315 | @font-face { 316 | font-family: 'BT Mono'; 317 | src: url("../fonts/bt-mono/bt-mono-Regular.eot"); 318 | src: url("../fonts/bt-mono/bt-mono-Regular.eot?#iefix") format("embedded-opentype"), url("../fonts/bt-mono/bt-mono-Regular.woff2") format("woff2"), url("../fonts/bt-mono/bt-mono-Regular.woff") format("woff"), url("../fonts/bt-mono/bt-mono-Regular.ttf") format("truetype"), url("../fonts/bt-mono/bt-mono-Regular.svg#bt_monoregular") format("svg"); 319 | font-style: normal; 320 | font-weight: 400; 321 | } 322 | 323 | @font-face { 324 | font-family: 'BT Mono medium'; 325 | src: url("../fonts/bt-mono/bt-mono-Medium.eot"); 326 | src: url("../fonts/bt-mono/bt-mono-Medium.eot?#iefix") format("embedded-opentype"), url("../fonts/bt-mono/bt-mono-Medium.woff2") format("woff2"), url("../fonts/bt-mono/bt-mono-Medium.woff") format("woff"), url("../fonts/bt-mono/bt-mono-Medium.ttf") format("truetype"), url("../fonts/bt-mono/bt-mono-Medium.svg#bt_monobold") format("svg"); 327 | font-weight: 600; 328 | font-style: normal; 329 | } 330 | 331 | @font-face { 332 | font-family: 'BT Mono bold'; 333 | src: url("../fonts/bt-mono/bt-mono-Bold.eot"); 334 | src: url("../fonts/bt-mono/bt-mono-Bold.eot?#iefix") format("embedded-opentype"), url("../fonts/bt-mono/bt-mono-Bold.woff2") format("woff2"), url("../fonts/bt-mono/bt-mono-Bold.woff") format("woff"), url("../fonts/bt-mono/bt-mono-Bold.ttf") format("truetype"), url("../fonts/bt-mono/bt-mono-Bold.svg#bt_monobold") format("svg"); 335 | font-weight: 700; 336 | font-style: normal; 337 | } 338 | 339 | @-webkit-keyframes fadeIn { 340 | 0% { 341 | opacity: 0; 342 | } 343 | 100% { 344 | opacity: 1; 345 | } 346 | } 347 | 348 | @-moz-keyframes fadeIn { 349 | 0% { 350 | opacity: 0; 351 | } 352 | 100% { 353 | opacity: 1; 354 | } 355 | } 356 | 357 | @keyframes fadeIn { 358 | 0% { 359 | opacity: 0; 360 | } 361 | 100% { 362 | opacity: 1; 363 | } 364 | } 365 | 366 | @-webkit-keyframes fadeInUp { 367 | 0% { 368 | opacity: 0; 369 | transform: translateY(40px); 370 | } 371 | 100% { 372 | opacity: 1; 373 | transform: translateY(0px); 374 | } 375 | } 376 | 377 | @-moz-keyframes fadeInUp { 378 | 0% { 379 | opacity: 0; 380 | transform: translateY(40px); 381 | } 382 | 100% { 383 | opacity: 1; 384 | transform: translateY(0px); 385 | } 386 | } 387 | 388 | @keyframes fadeInUp { 389 | 0% { 390 | opacity: 0; 391 | transform: translateY(40px); 392 | } 393 | 100% { 394 | opacity: 1; 395 | transform: translateY(0px); 396 | } 397 | } 398 | 399 | @-webkit-keyframes fadeInDown { 400 | 0% { 401 | opacity: 0; 402 | transform: translateY(-30px); 403 | } 404 | 100% { 405 | opacity: 1; 406 | transform: translateY(0px); 407 | } 408 | } 409 | 410 | @-moz-keyframes fadeInDown { 411 | 0% { 412 | opacity: 0; 413 | transform: translateY(-30px); 414 | } 415 | 100% { 416 | opacity: 1; 417 | transform: translateY(0px); 418 | } 419 | } 420 | 421 | @keyframes fadeInDown { 422 | 0% { 423 | opacity: 0; 424 | transform: translateY(-30px); 425 | } 426 | 100% { 427 | opacity: 1; 428 | transform: translateY(0px); 429 | } 430 | } 431 | 432 | @-webkit-keyframes fadeInLeft { 433 | 0% { 434 | opacity: 0; 435 | transform: translateX(60px); 436 | } 437 | 100% { 438 | opacity: 1; 439 | transform: translateX(0px); 440 | } 441 | } 442 | 443 | @-moz-keyframes fadeInLeft { 444 | 0% { 445 | opacity: 0; 446 | transform: translateX(60px); 447 | } 448 | 100% { 449 | opacity: 1; 450 | transform: translateX(0px); 451 | } 452 | } 453 | 454 | @keyframes fadeInLeft { 455 | 0% { 456 | opacity: 0; 457 | transform: translateX(60px); 458 | } 459 | 100% { 460 | opacity: 1; 461 | transform: translateX(0px); 462 | } 463 | } 464 | 465 | @-webkit-keyframes fadeInRight { 466 | 0% { 467 | opacity: 0; 468 | transform: translateX(-60px); 469 | } 470 | 100% { 471 | opacity: 1; 472 | transform: translateX(0px); 473 | } 474 | } 475 | 476 | @-moz-keyframes fadeInRight { 477 | 0% { 478 | opacity: 0; 479 | transform: translateX(-60px); 480 | } 481 | 100% { 482 | opacity: 1; 483 | transform: translateX(0px); 484 | } 485 | } 486 | 487 | @keyframes fadeInRight { 488 | 0% { 489 | opacity: 0; 490 | transform: translateX(-60px); 491 | } 492 | 100% { 493 | opacity: 1; 494 | transform: translateX(0px); 495 | } 496 | } 497 | 498 | @-webkit-keyframes fadeOutDown { 499 | 0% { 500 | opacity: 1; 501 | transform: translateY(0px); 502 | } 503 | 100% { 504 | opacity: 0; 505 | transform: translateY(40px); 506 | } 507 | } 508 | 509 | @-moz-keyframes fadeOutDown { 510 | 0% { 511 | opacity: 1; 512 | transform: translateY(0px); 513 | } 514 | 100% { 515 | opacity: 0; 516 | transform: translateY(40px); 517 | } 518 | } 519 | 520 | @keyframes fadeOutDown { 521 | 0% { 522 | opacity: 1; 523 | transform: translateY(0px); 524 | } 525 | 100% { 526 | opacity: 0; 527 | transform: translateY(40px); 528 | } 529 | } 530 | 531 | @-webkit-keyframes fadeOutRight { 532 | 0% { 533 | opacity: 1; 534 | transform: translateX(0px); 535 | } 536 | 100% { 537 | opacity: 0; 538 | transform: translateX(40px); 539 | } 540 | } 541 | 542 | @-moz-keyframes fadeOutRight { 543 | 0% { 544 | opacity: 1; 545 | transform: translateX(0px); 546 | } 547 | 100% { 548 | opacity: 0; 549 | transform: translateX(40px); 550 | } 551 | } 552 | 553 | @keyframes fadeOutRight { 554 | 0% { 555 | opacity: 1; 556 | transform: translateX(0px); 557 | } 558 | 100% { 559 | opacity: 0; 560 | transform: translateX(40px); 561 | } 562 | } 563 | 564 | @-webkit-keyframes slideInUp { 565 | 0% { 566 | transform: translateY(100%); 567 | } 568 | 100% { 569 | transform: translateY(0%); 570 | } 571 | } 572 | 573 | @-moz-keyframes slideInUp { 574 | 0% { 575 | transform: translateY(100%); 576 | } 577 | 100% { 578 | transform: translateY(0%); 579 | } 580 | } 581 | 582 | @keyframes slideInUp { 583 | 0% { 584 | transform: translateY(100%); 585 | } 586 | 100% { 587 | transform: translateY(0%); 588 | } 589 | } 590 | 591 | @-webkit-keyframes slideLeft { 592 | 0% { 593 | -webkit-transform: translateX(100%); 594 | } 595 | 100% { 596 | -webkit-transform: translateX(0%); 597 | } 598 | } 599 | 600 | @-moz-keyframes slideLeft { 601 | 0% { 602 | -moz-transform: translateX(100%); 603 | } 604 | 100% { 605 | -moz-transform: translateX(0%); 606 | } 607 | } 608 | 609 | @keyframes slideLeft { 610 | 0% { 611 | -webkit-transform: translateX(100%); 612 | -moz-transform: translateX(100%); 613 | -ms-transform: translateX(100%); 614 | -o-transform: translateX(100%); 615 | transform: translateX(100%); 616 | } 617 | 100% { 618 | -webkit-transform: translateX(0%); 619 | -moz-transform: translateX(0%); 620 | -ms-transform: translateX(0%); 621 | -o-transform: translateX(0%); 622 | transform: translateX(0%); 623 | } 624 | } 625 | 626 | @-webkit-keyframes slideRight { 627 | 0% { 628 | -webkit-transform: translateX(0%); 629 | } 630 | 100% { 631 | -webkit-transform: translateX(100%); 632 | } 633 | } 634 | 635 | @-moz-keyframes slideRight { 636 | 0% { 637 | -moz-transform: translateX(0%); 638 | } 639 | 100% { 640 | -moz-transform: translateX(100%); 641 | } 642 | } 643 | 644 | @keyframes slideRight { 645 | 0% { 646 | -webkit-transform: translateX(0%); 647 | -moz-transform: translateX(0%); 648 | -ms-transform: translateX(0%); 649 | -o-transform: translateX(0%); 650 | transform: translateX(0%); 651 | } 652 | 100% { 653 | -webkit-transform: translateX(100%); 654 | -moz-transform: translateX(100%); 655 | -ms-transform: translateX(100%); 656 | -o-transform: translateX(100%); 657 | transform: translateX(100%); 658 | } 659 | } 660 | 661 | @-webkit-keyframes pullLeftSmall { 662 | 0% { 663 | -webkit-transform: translateX(0vw); 664 | } 665 | 100% { 666 | -webkit-transform: translateX(-16.666vw); 667 | } 668 | } 669 | 670 | @-moz-keyframes pullLeftSmall { 671 | 0% { 672 | -moz-transform: translateX(0vw); 673 | } 674 | 100% { 675 | -moz-transform: translateX(-16.666vw); 676 | } 677 | } 678 | 679 | @keyframes pullLeftSmall { 680 | 0% { 681 | -webkit-transform: translateX(0vw); 682 | -moz-transform: translateX(0vw); 683 | -ms-transform: translateX(0vw); 684 | -o-transform: translateX(0vw); 685 | transform: translateX(0vw); 686 | } 687 | 100% { 688 | -webkit-transform: translateX(-16.666vw); 689 | -moz-transform: translateX(-16.666vw); 690 | -ms-transform: translateX(-16.666vw); 691 | -o-transform: translateX(-16.666vw); 692 | transform: translateX(-16.666vw); 693 | } 694 | } 695 | 696 | @-webkit-keyframes pullLeftLarge { 697 | 0% { 698 | -webkit-transform: translateX(0vw); 699 | } 700 | 100% { 701 | -webkit-transform: translateX(-33.333vw); 702 | } 703 | } 704 | 705 | @-moz-keyframes pullLeftLarge { 706 | 0% { 707 | -moz-transform: translateX(0vw); 708 | } 709 | 100% { 710 | -moz-transform: translateX(-33.333vw); 711 | } 712 | } 713 | 714 | @keyframes pullLeftLarge { 715 | 0% { 716 | -webkit-transform: translateX(0vw); 717 | -moz-transform: translateX(0vw); 718 | -ms-transform: translateX(0vw); 719 | -o-transform: translateX(0vw); 720 | transform: translateX(0vw); 721 | } 722 | 100% { 723 | -webkit-transform: translateX(-33.333vw); 724 | -moz-transform: translateX(-33.333vw); 725 | -ms-transform: translateX(-33.333vw); 726 | -o-transform: translateX(-33.333vw); 727 | transform: translateX(-33.333vw); 728 | } 729 | } 730 | 731 | @-webkit-keyframes yankLeft { 732 | 0% { 733 | -webkit-transform: translateX(0px); 734 | } 735 | 40% { 736 | -webkit-transform: translateX(-14px); 737 | } 738 | 70% { 739 | -webkit-transform: translateX(4px); 740 | } 741 | 100% { 742 | -webkit-transform: translateX(0px); 743 | } 744 | } 745 | 746 | @-moz-keyframes yankLeft { 747 | 0% { 748 | -moz-transform: translateX(0px); 749 | } 750 | 40% { 751 | -moz-transform: translateX(-14px); 752 | } 753 | 70% { 754 | -moz-transform: translateX(4px); 755 | } 756 | 100% { 757 | -moz-transform: translateX(0px); 758 | } 759 | } 760 | 761 | @keyframes yankLeft { 762 | 0% { 763 | -webkit-transform: translateX(0px); 764 | -moz-transform: translateX(0px); 765 | -ms-transform: translateX(0px); 766 | -o-transform: translateX(0px); 767 | transform: translateX(0px); 768 | } 769 | 40% { 770 | -webkit-transform: translateX(-14px); 771 | -moz-transform: translateX(-14px); 772 | -ms-transform: translateX(-14px); 773 | -o-transform: translateX(-14px); 774 | transform: translateX(-14px); 775 | } 776 | 70% { 777 | -webkit-transform: translateX(4px); 778 | -moz-transform: translateX(4px); 779 | -ms-transform: translateX(4px); 780 | -o-transform: translateX(4px); 781 | transform: translateX(4px); 782 | } 783 | 100% { 784 | -webkit-transform: translateX(0px); 785 | -moz-transform: translateX(0px); 786 | -ms-transform: translateX(0px); 787 | -o-transform: translateX(0px); 788 | transform: translateX(0px); 789 | } 790 | } 791 | 792 | @-webkit-keyframes rise { 793 | 0% { 794 | opacity: 0; 795 | transform: translateY(110%); 796 | } 797 | 30% { 798 | opacity: 1; 799 | transform: translateY(100%); 800 | } 801 | 70% { 802 | opacity: 1; 803 | transform: translateY(100%); 804 | } 805 | 100% { 806 | opacity: 1; 807 | transform: translateY(0%); 808 | } 809 | } 810 | 811 | @-moz-keyframes rise { 812 | 0% { 813 | opacity: 0; 814 | transform: translateY(110%); 815 | } 816 | 30% { 817 | opacity: 1; 818 | transform: translateY(100%); 819 | } 820 | 70% { 821 | opacity: 1; 822 | transform: translateY(100%); 823 | } 824 | 100% { 825 | opacity: 1; 826 | transform: translateY(0%); 827 | } 828 | } 829 | 830 | @keyframes rise { 831 | 0% { 832 | opacity: 0; 833 | transform: translateY(110%); 834 | } 835 | 30% { 836 | opacity: 1; 837 | transform: translateY(100%); 838 | } 839 | 70% { 840 | opacity: 1; 841 | transform: translateY(100%); 842 | } 843 | 100% { 844 | opacity: 1; 845 | transform: translateY(0%); 846 | } 847 | } 848 | 849 | @-webkit-keyframes boop { 850 | 0% { 851 | opacity: 0; 852 | -webkit-transform: scale(1.5); 853 | } 854 | 15% { 855 | opacity: 1; 856 | -webkit-transform: scale(0.75); 857 | } 858 | 30% { 859 | -webkit-transform: scale(1.2); 860 | } 861 | 50% { 862 | -webkit-transform: scale(0.85); 863 | } 864 | 75% { 865 | -webkit-transform: scale(1.1); 866 | } 867 | 100% { 868 | opacity: 1; 869 | -webkit-transform: scale(1); 870 | } 871 | } 872 | 873 | @-moz-keyframes boop { 874 | 0% { 875 | opacity: 0; 876 | -moz-transform: scale(1.5); 877 | } 878 | 15% { 879 | opacity: 1; 880 | -moz-transform: scale(0.75); 881 | } 882 | 30% { 883 | -moz-transform: scale(1.2); 884 | } 885 | 50% { 886 | -moz-transform: scale(0.85); 887 | } 888 | 75% { 889 | -moz-transform: scale(1.1); 890 | } 891 | 100% { 892 | opacity: 1; 893 | -moz-transform: scale(1); 894 | } 895 | } 896 | 897 | @keyframes boop { 898 | 0% { 899 | opacity: 0; 900 | -webkit-transform: scale(1.5); 901 | -moz-transform: scale(1.5); 902 | -ms-transform: scale(1.5); 903 | -o-transform: scale(1.5); 904 | transform: scale(1.5); 905 | } 906 | 15% { 907 | opacity: 1; 908 | -webkit-transform: scale(0.75); 909 | -moz-transform: scale(0.75); 910 | -ms-transform: scale(0.75); 911 | -o-transform: scale(0.75); 912 | transform: scale(0.75); 913 | } 914 | 30% { 915 | -webkit-transform: scale(1.2); 916 | -moz-transform: scale(1.2); 917 | -ms-transform: scale(1.2); 918 | -o-transform: scale(1.2); 919 | transform: scale(1.2); 920 | } 921 | 50% { 922 | -webkit-transform: scale(0.85); 923 | -moz-transform: scale(0.85); 924 | -ms-transform: scale(0.85); 925 | -o-transform: scale(0.85); 926 | transform: scale(0.85); 927 | } 928 | 75% { 929 | -webkit-transform: scale(1.1); 930 | -moz-transform: scale(1.1); 931 | -ms-transform: scale(1.1); 932 | -o-transform: scale(1.1); 933 | transform: scale(1.1); 934 | } 935 | 100% { 936 | opacity: 1; 937 | -webkit-transform: scale(1); 938 | -moz-transform: scale(1); 939 | -ms-transform: scale(1); 940 | -o-transform: scale(1); 941 | transform: scale(1); 942 | } 943 | } 944 | 945 | @-webkit-keyframes revealUp { 946 | 0% { 947 | opacity: 0; 948 | transform: translateY(37vh); 949 | } 950 | 25% { 951 | opacity: 1; 952 | } 953 | 50% { 954 | transform: translateY(37vh); 955 | } 956 | 100% { 957 | transform: translateY(0vh); 958 | } 959 | } 960 | 961 | @-moz-keyframes revealUp { 962 | 0% { 963 | opacity: 0; 964 | transform: translateY(37vh); 965 | } 966 | 25% { 967 | opacity: 1; 968 | } 969 | 50% { 970 | transform: translateY(37vh); 971 | } 972 | 100% { 973 | transform: translateY(0vh); 974 | } 975 | } 976 | 977 | @keyframes revealUp { 978 | 0% { 979 | opacity: 0; 980 | transform: translateY(37vh); 981 | } 982 | 25% { 983 | opacity: 1; 984 | } 985 | 50% { 986 | transform: translateY(37vh); 987 | } 988 | 100% { 989 | transform: translateY(0vh); 990 | } 991 | } 992 | 993 | @-webkit-keyframes spin { 994 | 0% { 995 | transform: rotateZ(0deg); 996 | } 997 | 100% { 998 | transform: rotateZ(360deg); 999 | } 1000 | } 1001 | 1002 | @-moz-keyframes spin { 1003 | 0% { 1004 | transform: rotateZ(0deg); 1005 | } 1006 | 100% { 1007 | transform: rotateZ(360deg); 1008 | } 1009 | } 1010 | 1011 | @keyframes spin { 1012 | 0% { 1013 | transform: rotateZ(0deg); 1014 | } 1015 | 100% { 1016 | transform: rotateZ(360deg); 1017 | } 1018 | } 1019 | 1020 | @-webkit-keyframes ratchet { 1021 | 0% { 1022 | transform: rotateZ(0deg); 1023 | -webkit-animation-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); 1024 | } 1025 | 50% { 1026 | transform: rotateZ(900deg); 1027 | -webkit-animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); 1028 | } 1029 | 65% { 1030 | transform: rotateZ(945deg); 1031 | -webkit-animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); 1032 | } 1033 | 70% { 1034 | transform: rotateZ(900deg); 1035 | } 1036 | 71%, 1037 | 100% { 1038 | transform: rotateZ(0deg); 1039 | } 1040 | } 1041 | 1042 | @-moz-keyframes ratchet { 1043 | 0% { 1044 | transform: rotateZ(0deg); 1045 | -moz-animation-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); 1046 | } 1047 | 50% { 1048 | transform: rotateZ(900deg); 1049 | -moz-animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); 1050 | } 1051 | 65% { 1052 | transform: rotateZ(945deg); 1053 | -moz-animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); 1054 | } 1055 | 70% { 1056 | transform: rotateZ(900deg); 1057 | } 1058 | 71%, 1059 | 100% { 1060 | transform: rotateZ(0deg); 1061 | } 1062 | } 1063 | 1064 | @keyframes ratchet { 1065 | 0% { 1066 | transform: rotateZ(0deg); 1067 | -webkit-animation-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); 1068 | -moz-animation-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); 1069 | animation-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); 1070 | } 1071 | 50% { 1072 | transform: rotateZ(900deg); 1073 | -webkit-animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); 1074 | -moz-animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); 1075 | animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); 1076 | } 1077 | 65% { 1078 | transform: rotateZ(945deg); 1079 | -webkit-animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); 1080 | -moz-animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); 1081 | animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); 1082 | } 1083 | 70% { 1084 | transform: rotateZ(900deg); 1085 | } 1086 | 71%, 1087 | 100% { 1088 | transform: rotateZ(0deg); 1089 | } 1090 | } 1091 | 1092 | @-webkit-keyframes sendUp { 1093 | 0%, 1094 | 70% { 1095 | transform: translateY(0px); 1096 | opacity: 1; 1097 | } 1098 | 85% { 1099 | transform: translateY(-30px); 1100 | opacity: 0; 1101 | } 1102 | 86% { 1103 | transform: translateY(30px); 1104 | opacity: 0; 1105 | } 1106 | 100% { 1107 | transform: translateY(0px); 1108 | opacity: 1; 1109 | } 1110 | } 1111 | 1112 | @-moz-keyframes sendUp { 1113 | 0%, 1114 | 70% { 1115 | transform: translateY(0px); 1116 | opacity: 1; 1117 | } 1118 | 85% { 1119 | transform: translateY(-30px); 1120 | opacity: 0; 1121 | } 1122 | 86% { 1123 | transform: translateY(30px); 1124 | opacity: 0; 1125 | } 1126 | 100% { 1127 | transform: translateY(0px); 1128 | opacity: 1; 1129 | } 1130 | } 1131 | 1132 | @keyframes sendUp { 1133 | 0%, 1134 | 70% { 1135 | transform: translateY(0px); 1136 | opacity: 1; 1137 | } 1138 | 85% { 1139 | transform: translateY(-30px); 1140 | opacity: 0; 1141 | } 1142 | 86% { 1143 | transform: translateY(30px); 1144 | opacity: 0; 1145 | } 1146 | 100% { 1147 | transform: translateY(0px); 1148 | opacity: 1; 1149 | } 1150 | } 1151 | 1152 | @-webkit-keyframes sendDown { 1153 | 0%, 1154 | 70% { 1155 | transform: translateY(0px); 1156 | opacity: 1; 1157 | } 1158 | 85% { 1159 | transform: translateY(30px); 1160 | opacity: 0; 1161 | } 1162 | 86% { 1163 | transform: translateY(-30px); 1164 | opacity: 0; 1165 | } 1166 | 100% { 1167 | transform: translateY(0px); 1168 | opacity: 1; 1169 | } 1170 | } 1171 | 1172 | @-moz-keyframes sendDown { 1173 | 0%, 1174 | 70% { 1175 | transform: translateY(0px); 1176 | opacity: 1; 1177 | } 1178 | 85% { 1179 | transform: translateY(30px); 1180 | opacity: 0; 1181 | } 1182 | 86% { 1183 | transform: translateY(-30px); 1184 | opacity: 0; 1185 | } 1186 | 100% { 1187 | transform: translateY(0px); 1188 | opacity: 1; 1189 | } 1190 | } 1191 | 1192 | @keyframes sendDown { 1193 | 0%, 1194 | 70% { 1195 | transform: translateY(0px); 1196 | opacity: 1; 1197 | } 1198 | 85% { 1199 | transform: translateY(30px); 1200 | opacity: 0; 1201 | } 1202 | 86% { 1203 | transform: translateY(-30px); 1204 | opacity: 0; 1205 | } 1206 | 100% { 1207 | transform: translateY(0px); 1208 | opacity: 1; 1209 | } 1210 | } 1211 | 1212 | @-webkit-keyframes pulse { 1213 | 0% { 1214 | background-color: rgba(92, 212, 147, 0); 1215 | box-shadow: 0px 0px 0px 0px rgba(92, 212, 147, 0); 1216 | } 1217 | 20% { 1218 | background-color: rgba(92, 212, 147, 0.5); 1219 | box-shadow: 0px 0px 0px 0px #5cd493; 1220 | } 1221 | 80%, 1222 | 99% { 1223 | background-color: rgba(92, 212, 147, 0); 1224 | box-shadow: 0px 0px 0px 8px rgba(92, 212, 147, 0); 1225 | } 1226 | 100% { 1227 | background-color: rgba(92, 212, 147, 0); 1228 | box-shadow: 0px 0px 0px 0px rgba(92, 212, 147, 0); 1229 | } 1230 | } 1231 | 1232 | @-moz-keyframes pulse { 1233 | 0% { 1234 | background-color: rgba(92, 212, 147, 0); 1235 | box-shadow: 0px 0px 0px 0px rgba(92, 212, 147, 0); 1236 | } 1237 | 20% { 1238 | background-color: rgba(92, 212, 147, 0.5); 1239 | box-shadow: 0px 0px 0px 0px #5cd493; 1240 | } 1241 | 80%, 1242 | 99% { 1243 | background-color: rgba(92, 212, 147, 0); 1244 | box-shadow: 0px 0px 0px 8px rgba(92, 212, 147, 0); 1245 | } 1246 | 100% { 1247 | background-color: rgba(92, 212, 147, 0); 1248 | box-shadow: 0px 0px 0px 0px rgba(92, 212, 147, 0); 1249 | } 1250 | } 1251 | 1252 | @keyframes pulse { 1253 | 0% { 1254 | background-color: rgba(92, 212, 147, 0); 1255 | box-shadow: 0px 0px 0px 0px rgba(92, 212, 147, 0); 1256 | } 1257 | 20% { 1258 | background-color: rgba(92, 212, 147, 0.5); 1259 | box-shadow: 0px 0px 0px 0px #5cd493; 1260 | } 1261 | 80%, 1262 | 99% { 1263 | background-color: rgba(92, 212, 147, 0); 1264 | box-shadow: 0px 0px 0px 8px rgba(92, 212, 147, 0); 1265 | } 1266 | 100% { 1267 | background-color: rgba(92, 212, 147, 0); 1268 | box-shadow: 0px 0px 0px 0px rgba(92, 212, 147, 0); 1269 | } 1270 | } 1271 | 1272 | body { 1273 | background-color: #fff; 1274 | color: #393536; 1275 | font-family: "BT Mono", "Helvetica Neue", Helvetica, Sans-serif; 1276 | font-size: 16px; 1277 | font-weight: normal; 1278 | -webkit-font-smoothing: antialiased; 1279 | letter-spacing: .008em; 1280 | text-rendering: optimizeLegibility; 1281 | line-height: 25px; 1282 | } 1283 | 1284 | h1, 1285 | h2, 1286 | h3, 1287 | h4, 1288 | h5, 1289 | h6 { 1290 | color: #393536; 1291 | font-family: "BT Mono medium", "Helvetica Neue", Helvetica, Sans-serif; 1292 | font-weight: normal; 1293 | line-height: 1.3; 1294 | margin: 0; 1295 | } 1296 | 1297 | .dark h1, 1298 | .dark h2, 1299 | .dark h3, 1300 | .dark h4, 1301 | .dark h5, 1302 | .dark h6 { 1303 | color: #fff; 1304 | } 1305 | 1306 | h1, 1307 | h2 { 1308 | font-family: "BT Mono medium", "Helvetica Neue", Helvetica, Sans-serif; 1309 | letter-spacing: -1px; 1310 | } 1311 | 1312 | h1 { 1313 | font-size: 42px; 1314 | line-height: 1.1em; 1315 | margin: 0 0 0 -0.05em; 1316 | } 1317 | 1318 | h2 { 1319 | margin: 0 0 25px; 1320 | font-size: 42px; 1321 | } 1322 | 1323 | h3 { 1324 | font-size: 23px; 1325 | } 1326 | 1327 | h4 { 1328 | font-size: 20px; 1329 | text-transform: uppercase; 1330 | } 1331 | 1332 | h5 { 1333 | font-size: 18px; 1334 | font-weight: normal; 1335 | } 1336 | 1337 | p { 1338 | font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 1339 | line-height: 1.4; 1340 | margin: 1em 0; 1341 | } 1342 | 1343 | ul, 1344 | ol { 1345 | list-style: none; 1346 | padding: 0; 1347 | } 1348 | 1349 | strong { 1350 | font-family: "Open Sans semibold", "Avenir", "Helvetica Neue", Helvetica, Sans-serif; 1351 | font-weight: normal; 1352 | } 1353 | 1354 | a { 1355 | -webkit-transition: color 0.2s ease, border-color, 0.2s ease; 1356 | -moz-transition: color 0.2s ease, border-color, 0.2s ease; 1357 | -ms-transition: color 0.2s ease, border-color, 0.2s ease; 1358 | -o-transition: color 0.2s ease, border-color, 0.2s ease; 1359 | transition: color 0.2s ease, border-color, 0.2s ease; 1360 | color: #393536; 1361 | text-decoration: none; 1362 | } 1363 | 1364 | a:hover, 1365 | a:focus, 1366 | a:active { 1367 | color: #5CD493; 1368 | border-color: #5CD493; 1369 | } 1370 | 1371 | p a, 1372 | li a { 1373 | font-family: "BT Mono medium", "Helvetica Neue", Helvetica, Sans-serif; 1374 | border-bottom: solid 1px #DEE2E5; 1375 | padding: .2em .1em; 1376 | margin: 0 -.1em; 1377 | } 1378 | 1379 | p a:hover, 1380 | li a:hover { 1381 | border-color: #5CD493; 1382 | } 1383 | 1384 | img { 1385 | display: block; 1386 | max-width: 100%; 1387 | } 1388 | 1389 | html { 1390 | box-sizing: border-box; 1391 | } 1392 | 1393 | *, 1394 | *:before, 1395 | *:after { 1396 | box-sizing: inherit; 1397 | } 1398 | 1399 | html, 1400 | body { 1401 | height: 100%; 1402 | min-height: 100%; 1403 | width: 100%; 1404 | overflow: auto; 1405 | } 1406 | 1407 | body { 1408 | text-align: center; 1409 | } 1410 | 1411 | @media (min-width: 1025px) { 1412 | body { 1413 | display: -webkit-box; 1414 | display: -moz-box; 1415 | display: box; 1416 | display: -webkit-flex; 1417 | display: -moz-flex; 1418 | display: -ms-flexbox; 1419 | display: flex; 1420 | -webkit-box-align: center; 1421 | -moz-box-align: center; 1422 | box-align: center; 1423 | -webkit-align-items: center; 1424 | -moz-align-items: center; 1425 | -ms-align-items: center; 1426 | -o-align-items: center; 1427 | align-items: center; 1428 | -ms-flex-align: center; 1429 | -webkit-align-self: stretch; 1430 | -moz-align-self: stretch; 1431 | align-self: stretch; 1432 | -ms-flex-item-align: stretch; 1433 | -webkit-box-orient: vertical; 1434 | -moz-box-orient: vertical; 1435 | box-orient: vertical; 1436 | -webkit-box-direction: normal; 1437 | -moz-box-direction: normal; 1438 | box-direction: normal; 1439 | -webkit-flex-direction: column; 1440 | -moz-flex-direction: column; 1441 | flex-direction: column; 1442 | -ms-flex-direction: column; 1443 | -webkit-box-flex: 1; 1444 | -moz-box-flex: 1; 1445 | box-flex: 1; 1446 | -webkit-flex: 1 1 auto; 1447 | -moz-flex: 1 1 auto; 1448 | -ms-flex: 1 1 auto; 1449 | flex: 1 1 auto; 1450 | overflow: hidden; 1451 | } 1452 | } 1453 | 1454 | header.main, 1455 | footer { 1456 | width: 100%; 1457 | } 1458 | 1459 | header.main { 1460 | position: fixed; 1461 | left: 0px; 1462 | top: 0px; 1463 | width: 100%; 1464 | z-index: 20; 1465 | background-color: #fff; 1466 | border-bottom: solid 1px #DEE2E5; 1467 | } 1468 | 1469 | @media (min-width: 1025px) { 1470 | header.main { 1471 | background-color: transparent; 1472 | border-bottom: none; 1473 | } 1474 | } 1475 | 1476 | header { 1477 | -webkit-box-flex: 0; 1478 | -moz-box-flex: 0; 1479 | box-flex: 0; 1480 | -webkit-flex: 0 0 auto; 1481 | -moz-flex: 0 0 auto; 1482 | -ms-flex: 0 0 auto; 1483 | flex: 0 0 auto; 1484 | -webkit-align-self: flex-start; 1485 | -moz-align-self: flex-start; 1486 | align-self: flex-start; 1487 | -ms-flex-item-align: start; 1488 | } 1489 | 1490 | article { 1491 | -webkit-box-flex: 1; 1492 | -moz-box-flex: 1; 1493 | box-flex: 1; 1494 | -webkit-flex: 1 1 auto; 1495 | -moz-flex: 1 1 auto; 1496 | -ms-flex: 1 1 auto; 1497 | flex: 1 1 auto; 1498 | -webkit-align-self: stretch; 1499 | -moz-align-self: stretch; 1500 | align-self: stretch; 1501 | -ms-flex-item-align: stretch; 1502 | position: relative; 1503 | overflow: auto; 1504 | -webkit-overflow-scrolling: touch; 1505 | z-index: 0; 1506 | } 1507 | 1508 | footer { 1509 | -webkit-box-flex: 0; 1510 | -moz-box-flex: 0; 1511 | box-flex: 0; 1512 | -webkit-flex: 0 0 auto; 1513 | -moz-flex: 0 0 auto; 1514 | -ms-flex: 0 0 auto; 1515 | flex: 0 0 auto; 1516 | -webkit-align-self: flex-end; 1517 | -moz-align-self: flex-end; 1518 | align-self: flex-end; 1519 | -ms-flex-item-align: end; 1520 | background-color: #f6f6f6; 1521 | } 1522 | 1523 | .wrapper { 1524 | width: 100%; 1525 | overflow: auto; 1526 | z-index: 0; 1527 | padding: 4em 0; 1528 | } 1529 | 1530 | @media (min-width: 1025px) { 1531 | .wrapper { 1532 | display: -webkit-box; 1533 | display: -moz-box; 1534 | display: box; 1535 | display: -webkit-flex; 1536 | display: -moz-flex; 1537 | display: -ms-flexbox; 1538 | display: flex; 1539 | -webkit-box-flex: 1; 1540 | -moz-box-flex: 1; 1541 | box-flex: 1; 1542 | -webkit-flex: 1 1 auto; 1543 | -moz-flex: 1 1 auto; 1544 | -ms-flex: 1 1 auto; 1545 | flex: 1 1 auto; 1546 | } 1547 | } 1548 | 1549 | .container { 1550 | max-width: 46em; 1551 | margin: 0 auto; 1552 | width: 100%; 1553 | } 1554 | 1555 | .container.wide { 1556 | max-width: 100%; 1557 | } 1558 | 1559 | .content { 1560 | padding: 36px 12px; 1561 | } 1562 | 1563 | .content.slim, 1564 | .content.compact { 1565 | padding: 12px; 1566 | } 1567 | 1568 | @media (min-width: 641px) { 1569 | .content { 1570 | padding: 36px 24px; 1571 | } 1572 | .content.slim { 1573 | padding: 24px 24px; 1574 | } 1575 | .content.compact { 1576 | padding: 24px 24px; 1577 | } 1578 | } 1579 | 1580 | @media (min-width: 1025px) { 1581 | .content { 1582 | padding: 36px 44px; 1583 | } 1584 | .content.slim { 1585 | padding: 24px 44px; 1586 | } 1587 | .content.compact { 1588 | padding: 40px; 1589 | } 1590 | } 1591 | 1592 | @media (max-height: 30em) { 1593 | .content, 1594 | .content.slim { 1595 | padding-top: 10px; 1596 | padding-bottom: 10px; 1597 | } 1598 | } 1599 | 1600 | section { 1601 | display: inline-block; 1602 | width: 100%; 1603 | margin-bottom: 30px; 1604 | z-index: 1; 1605 | } 1606 | 1607 | section:last-child { 1608 | margin-bottom: 0; 1609 | } 1610 | 1611 | @media (max-height: 30em) { 1612 | section { 1613 | margin-bottom: 10px; 1614 | } 1615 | } 1616 | 1617 | .row, 1618 | .set { 1619 | -webkit-align-content: stretch; 1620 | -moz-align-content: stretch; 1621 | align-content: stretch; 1622 | -ms-flex-line-pack: stretch; 1623 | -webkit-box-align: center; 1624 | -moz-box-align: center; 1625 | box-align: center; 1626 | -webkit-align-items: center; 1627 | -moz-align-items: center; 1628 | -ms-align-items: center; 1629 | -o-align-items: center; 1630 | align-items: center; 1631 | -ms-flex-align: center; 1632 | display: -webkit-box; 1633 | display: -moz-box; 1634 | display: box; 1635 | display: -webkit-flex; 1636 | display: -moz-flex; 1637 | display: -ms-flexbox; 1638 | display: flex; 1639 | -webkit-box-orient: vertical; 1640 | -moz-box-orient: vertical; 1641 | box-orient: vertical; 1642 | -webkit-box-direction: normal; 1643 | -moz-box-direction: normal; 1644 | box-direction: normal; 1645 | -webkit-flex-direction: column; 1646 | -moz-flex-direction: column; 1647 | flex-direction: column; 1648 | -ms-flex-direction: column; 1649 | } 1650 | 1651 | @media (min-width: 641px) { 1652 | .row, 1653 | .set { 1654 | -webkit-box-orient: horizontal; 1655 | -moz-box-orient: horizontal; 1656 | box-orient: horizontal; 1657 | -webkit-box-direction: normal; 1658 | -moz-box-direction: normal; 1659 | box-direction: normal; 1660 | -webkit-flex-direction: row; 1661 | -moz-flex-direction: row; 1662 | flex-direction: row; 1663 | -ms-flex-direction: row; 1664 | } 1665 | } 1666 | 1667 | .col { 1668 | display: -webkit-box; 1669 | display: -moz-box; 1670 | display: box; 1671 | display: -webkit-flex; 1672 | display: -moz-flex; 1673 | display: -ms-flexbox; 1674 | display: flex; 1675 | -webkit-box-orient: horizontal; 1676 | -moz-box-orient: horizontal; 1677 | box-orient: horizontal; 1678 | -webkit-box-direction: normal; 1679 | -moz-box-direction: normal; 1680 | box-direction: normal; 1681 | -webkit-flex-direction: row; 1682 | -moz-flex-direction: row; 1683 | flex-direction: row; 1684 | -ms-flex-direction: row; 1685 | -webkit-flex-grow: 1; 1686 | -moz-flex-grow: 1; 1687 | flex-grow: 1; 1688 | -ms-flex-positive: 1; 1689 | margin: 0 auto; 1690 | } 1691 | 1692 | .fill, 1693 | .fit { 1694 | display: inline-block; 1695 | margin: auto; 1696 | } 1697 | 1698 | .fill { 1699 | -webkit-flex-grow: 1; 1700 | -moz-flex-grow: 1; 1701 | flex-grow: 1; 1702 | -ms-flex-positive: 1; 1703 | } 1704 | 1705 | .fit { 1706 | -webkit-flex-grow: 0; 1707 | -moz-flex-grow: 0; 1708 | flex-grow: 0; 1709 | -ms-flex-positive: 0; 1710 | } 1711 | 1712 | .button { 1713 | -webkit-transition: background-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), border-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), opacity 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1714 | -moz-transition: background-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), border-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), opacity 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1715 | -ms-transition: background-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), border-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), opacity 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1716 | -o-transition: background-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), border-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), opacity 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1717 | transition: background-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), border-color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95), opacity 140ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1718 | background-color: #5CD493; 1719 | border: none; 1720 | border-radius: 2px; 1721 | display: inline-block; 1722 | color: #fff; 1723 | font-family: "BT Mono bold", "Helvetica Neue", Helvetica, Sans-serif; 1724 | font-size: 16px; 1725 | letter-spacing: 0; 1726 | line-height: normal; 1727 | opacity: 1; 1728 | outline: none; 1729 | padding: 0; 1730 | position: relative; 1731 | text-decoration: none; 1732 | text-align: center; 1733 | width: 100%; 1734 | } 1735 | 1736 | @media (min-width: 641px) { 1737 | .button { 1738 | width: auto; 1739 | } 1740 | } 1741 | 1742 | .button.full { 1743 | width: 100%; 1744 | } 1745 | 1746 | .button:hover, 1747 | .button:focus { 1748 | background-color: #7cdda8; 1749 | color: #fff; 1750 | } 1751 | 1752 | .button:focus { 1753 | outline: none; 1754 | border-color: #44ce83; 1755 | } 1756 | 1757 | .button.out { 1758 | color: transparent; 1759 | } 1760 | 1761 | .button span { 1762 | -webkit-transition: color 140ms ease; 1763 | -moz-transition: color 140ms ease; 1764 | -ms-transition: color 140ms ease; 1765 | -o-transition: color 140ms ease; 1766 | transition: color 140ms ease; 1767 | display: inline-block; 1768 | padding: 1em 2.5em 1.15em; 1769 | position: relative; 1770 | text-align: center; 1771 | } 1772 | 1773 | .button span:after { 1774 | -webkit-animation: spin 400ms infinite normal cubic-bezier(0.445, 0.05, 0.55, 0.95) forwards 0s paused; 1775 | -moz-animation: spin 400ms infinite normal cubic-bezier(0.445, 0.05, 0.55, 0.95) forwards 0s paused; 1776 | animation: spin 400ms infinite normal cubic-bezier(0.445, 0.05, 0.55, 0.95) forwards 0s paused; 1777 | -webkit-transition: opacity 200ms ease; 1778 | -moz-transition: opacity 200ms ease; 1779 | -ms-transition: opacity 200ms ease; 1780 | -o-transition: opacity 200ms ease; 1781 | transition: opacity 200ms ease; 1782 | width: 20px; 1783 | height: 20px; 1784 | border-radius: 50%; 1785 | border: solid 2px #fff; 1786 | border-top-color: transparent; 1787 | left: 50%; 1788 | opacity: 0; 1789 | top: 50%; 1790 | margin: -10px 0 0 -10px; 1791 | } 1792 | 1793 | .button.loading { 1794 | cursor: none; 1795 | background-color: #bdbdbf; 1796 | } 1797 | 1798 | .button.loading span { 1799 | color: transparent; 1800 | } 1801 | 1802 | .button.loading span:after { 1803 | -webkit-animation-play-state: running; 1804 | -moz-animation-play-state: running; 1805 | animation-play-state: running; 1806 | opacity: 1; 1807 | } 1808 | 1809 | .button.loading:after, 1810 | .button:hover:after { 1811 | opacity: 0; 1812 | } 1813 | 1814 | .button.secondary { 1815 | background-color: transparent; 1816 | border: solid 1px #5CD493; 1817 | color: #5CD493; 1818 | font-size: 16px; 1819 | } 1820 | 1821 | .button.secondary:hover { 1822 | color: #fff; 1823 | background-color: #5CD493; 1824 | } 1825 | 1826 | .button.cap { 1827 | width: 100%; 1828 | border-radius: 0px 0px 3px 3px; 1829 | } 1830 | 1831 | ::-webkit-input-placeholder { 1832 | color: #6E787F; 1833 | line-height: 1; 1834 | } 1835 | 1836 | :-moz-placeholder { 1837 | color: #6E787F; 1838 | line-height: 1; 1839 | } 1840 | 1841 | ::-moz-placeholder { 1842 | color: #6E787F; 1843 | line-height: 1; 1844 | } 1845 | 1846 | :-ms-input-placeholder { 1847 | color: #6E787F; 1848 | line-height: 1; 1849 | } 1850 | 1851 | input:focus::-webkit-input-placeholder { 1852 | color: #283036; 1853 | } 1854 | 1855 | input:focus:-moz-placeholder { 1856 | color: #283036; 1857 | } 1858 | 1859 | input:focus::-moz-placeholder { 1860 | color: #283036; 1861 | } 1862 | 1863 | input:focus:-ms-input-placeholder { 1864 | color: #283036; 1865 | } 1866 | 1867 | label[for="amount"] { 1868 | -webkit-transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1869 | -moz-transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1870 | -ms-transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1871 | -o-transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1872 | transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95), color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95); 1873 | border-top: solid 1px #DEE2E5; 1874 | border-bottom: solid 1px #DEE2E5; 1875 | color: #6E787F; 1876 | cursor: pointer; 1877 | display: block; 1878 | font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 1879 | font-weight: 300; 1880 | padding: 12px 14px; 1881 | position: relative; 1882 | margin-top: -11px; 1883 | width: 100%; 1884 | z-index: 1; 1885 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 1886 | font-size: 1.2rem; 1887 | margin-bottom: 1rem; 1888 | } 1889 | 1890 | @media (min-width: 720px) { 1891 | label[for="amount"] { 1892 | border: 1px solid #b5b5b5; 1893 | border-radius: 3px; 1894 | } 1895 | } 1896 | 1897 | label[for="amount"] .input-label { 1898 | -webkit-transition: opacity 0.2s cubic-bezier(0.445, 0.05, 0.55, 0.95); 1899 | -moz-transition: opacity 0.2s cubic-bezier(0.445, 0.05, 0.55, 0.95); 1900 | -ms-transition: opacity 0.2s cubic-bezier(0.445, 0.05, 0.55, 0.95); 1901 | -o-transition: opacity 0.2s cubic-bezier(0.445, 0.05, 0.55, 0.95); 1902 | transition: opacity 0.2s cubic-bezier(0.445, 0.05, 0.55, 0.95); 1903 | color: #000; 1904 | display: block; 1905 | font-size: 12px; 1906 | font-weight: 500; 1907 | line-height: 1; 1908 | margin-bottom: 4px; 1909 | } 1910 | 1911 | label[for="amount"].has-focus { 1912 | background-color: #f9f9f9; 1913 | cursor: text; 1914 | z-index: 2; 1915 | } 1916 | 1917 | label[for="amount"].has-focus .input-wrapper:after { 1918 | color: #393536; 1919 | } 1920 | 1921 | label[for="amount"].has-focus .input-label { 1922 | color: #000; 1923 | } 1924 | 1925 | input { 1926 | background-color: transparent; 1927 | display: block; 1928 | border: none; 1929 | color: #000; 1930 | cursor: pointer; 1931 | font-size: 1.2rem; 1932 | outline: none; 1933 | line-height: 1; 1934 | width: 100%; 1935 | } 1936 | 1937 | .input-wrapper { 1938 | position: relative; 1939 | } 1940 | 1941 | .amount-wrapper input { 1942 | -webkit-transition: transform 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), color 0.2s ease; 1943 | -moz-transition: transform 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), color 0.2s ease; 1944 | -ms-transition: transform 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), color 0.2s ease; 1945 | -o-transition: transform 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), color 0.2s ease; 1946 | transition: transform 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), color 0.2s ease; 1947 | padding: 0 14px; 1948 | } 1949 | 1950 | .amount-wrapper:after { 1951 | -webkit-transition: opacity 0.2s ease; 1952 | -moz-transition: opacity 0.2s ease; 1953 | -ms-transition: opacity 0.2s ease; 1954 | -o-transition: opacity 0.2s ease; 1955 | transition: opacity 0.2s ease; 1956 | -webkit-transform: translateY(-50%); 1957 | -moz-transform: translateY(-50%); 1958 | -ms-transform: translateY(-50%); 1959 | -o-transform: translateY(-50%); 1960 | transform: translateY(-50%); 1961 | content: "$"; 1962 | color: #393536; 1963 | display: inline-block; 1964 | line-height: 1; 1965 | left: 0px; 1966 | position: absolute; 1967 | top: 50%; 1968 | } 1969 | 1970 | /* Modules */ 1971 | 1972 | header .fill { 1973 | text-align: left; 1974 | } 1975 | 1976 | header a, 1977 | .pseudoshop, 1978 | .braintree { 1979 | display: inline-block; 1980 | text-decoration: none; 1981 | vertical-align: middle; 1982 | } 1983 | 1984 | .pseudoshop, 1985 | .braintree { 1986 | background-color: #fff; 1987 | padding: 3px 8px; 1988 | margin: 0 -8px; 1989 | } 1990 | 1991 | .pseudoshop { 1992 | -webkit-transition: color 160ms ease; 1993 | -moz-transition: color 160ms ease; 1994 | -ms-transition: color 160ms ease; 1995 | -o-transition: color 160ms ease; 1996 | transition: color 160ms ease; 1997 | -webkit-box-ordinal-group: 2; 1998 | -moz-box-ordinal-group: 2; 1999 | box-ordinal-group: 2; 2000 | -webkit-order: 2; 2001 | -moz-order: 2; 2002 | order: 2; 2003 | -ms-flex-order: 2; 2004 | color: #393536; 2005 | font-family: "Open Sans regular", "Avenir", "Helvetica Neue", Helvetica, Sans-serif; 2006 | text-align: left; 2007 | } 2008 | 2009 | .pseudoshop strong { 2010 | font-family: "Open Sans bold", "Avenir", "Helvetica Neue", Helvetica, Sans-serif; 2011 | } 2012 | 2013 | @media (min-width: 641px) { 2014 | .pseudoshop { 2015 | -webkit-box-ordinal-group: 1; 2016 | -moz-box-ordinal-group: 1; 2017 | box-ordinal-group: 1; 2018 | -webkit-order: 1; 2019 | -moz-order: 1; 2020 | order: 1; 2021 | -ms-flex-order: 1; 2022 | } 2023 | } 2024 | 2025 | .pseudoshop:hover { 2026 | color: #707073; 2027 | } 2028 | 2029 | .braintree { 2030 | -webkit-transition: opacity 160ms ease; 2031 | -moz-transition: opacity 160ms ease; 2032 | -ms-transition: opacity 160ms ease; 2033 | -o-transition: opacity 160ms ease; 2034 | transition: opacity 160ms ease; 2035 | -webkit-box-ordinal-group: 1; 2036 | -moz-box-ordinal-group: 1; 2037 | box-ordinal-group: 1; 2038 | -webkit-order: 1; 2039 | -moz-order: 1; 2040 | order: 1; 2041 | -ms-flex-order: 1; 2042 | color: #393536; 2043 | font-size: 12px; 2044 | font-family: "BT Mono bold", "Helvetica Neue", Helvetica, Sans-serif; 2045 | opacity: .5; 2046 | } 2047 | 2048 | header.main .braintree { 2049 | display: none; 2050 | } 2051 | 2052 | .dark .braintree { 2053 | background-color: transparent; 2054 | color: #fff; 2055 | opacity: 1; 2056 | } 2057 | 2058 | @media (min-width: 641px) { 2059 | .braintree { 2060 | -webkit-box-ordinal-group: 2; 2061 | -moz-box-ordinal-group: 2; 2062 | box-ordinal-group: 2; 2063 | -webkit-order: 2; 2064 | -moz-order: 2; 2065 | order: 2; 2066 | -ms-flex-order: 2; 2067 | } 2068 | header.main .braintree { 2069 | display: inline-block; 2070 | } 2071 | } 2072 | 2073 | .braintree:hover { 2074 | opacity: 1; 2075 | } 2076 | 2077 | .braintree.notification, 2078 | .braintree.active { 2079 | color: #393536; 2080 | } 2081 | 2082 | @media (min-width: 1025px) { 2083 | .braintree.notification { 2084 | -webkit-animation: pullLeftLarge 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1125ms; 2085 | -moz-animation: pullLeftLarge 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1125ms; 2086 | animation: pullLeftLarge 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1125ms; 2087 | } 2088 | } 2089 | 2090 | .braintree.dismiss { 2091 | -webkit-animation: fadeOutRight 300ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2092 | -moz-animation: fadeOutRight 300ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2093 | animation: fadeOutRight 300ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2094 | -webkit-animation-delay: 0s; 2095 | -moz-animation-delay: 0s; 2096 | animation-delay: 0s; 2097 | } 2098 | 2099 | .notice-wrapper { 2100 | font-family: "BT Mono medium", "Helvetica Neue", Helvetica, Sans-serif; 2101 | text-align: center; 2102 | width: 100%; 2103 | overflow: hidden; 2104 | } 2105 | 2106 | .notice { 2107 | -webkit-transition: transform 300ms cubic-bezier(0.645, 0.045, 0.355, 1); 2108 | -moz-transition: transform 300ms cubic-bezier(0.645, 0.045, 0.355, 1); 2109 | -ms-transition: transform 300ms cubic-bezier(0.645, 0.045, 0.355, 1); 2110 | -o-transition: transform 300ms cubic-bezier(0.645, 0.045, 0.355, 1); 2111 | transition: transform 300ms cubic-bezier(0.645, 0.045, 0.355, 1); 2112 | -webkit-transform: translateY(-100%); 2113 | -moz-transform: translateY(-100%); 2114 | -ms-transform: translateY(-100%); 2115 | -o-transform: translateY(-100%); 2116 | transform: translateY(-100%); 2117 | border-radius: 1px; 2118 | background-color: #f6f6f6; 2119 | color: #707073; 2120 | padding: 15px; 2121 | width: 100%; 2122 | } 2123 | 2124 | .notice.error { 2125 | background-color: #FF6161; 2126 | color: #fff; 2127 | } 2128 | 2129 | .notice.show { 2130 | -webkit-transform: translateY(0%); 2131 | -moz-transform: translateY(0%); 2132 | -ms-transform: translateY(0%); 2133 | -o-transform: translateY(0%); 2134 | transform: translateY(0%); 2135 | } 2136 | 2137 | table { 2138 | width: 100%; 2139 | } 2140 | 2141 | tr { 2142 | border-top: solid 1px #DEE2E5; 2143 | } 2144 | 2145 | tr:last-child { 2146 | border-bottom: solid 1px #DEE2E5; 2147 | } 2148 | 2149 | th, 2150 | td { 2151 | overflow-wrap: break-word; 2152 | word-wrap: break-word; 2153 | -ms-word-break: break-all; 2154 | word-break: break-word; 2155 | -ms-hyphens: none; 2156 | -moz-hyphens: none; 2157 | -webkit-hyphens: none; 2158 | hyphens: none; 2159 | line-height: 1.3em; 2160 | font-size: 14px; 2161 | letter-spacing: .02em; 2162 | padding: .6em 0; 2163 | vertical-align: top; 2164 | text-align: left; 2165 | } 2166 | 2167 | th { 2168 | color: #707073; 2169 | font-weight: normal; 2170 | font-family: "BT Mono", "Helvetica Neue", Helvetica, Sans-serif; 2171 | } 2172 | 2173 | td { 2174 | color: #393536; 2175 | font-family: "BT Mono medium", "Helvetica Neue", Helvetica, Sans-serif; 2176 | width: 60%; 2177 | padding: .6em 0 .6em .6em; 2178 | } 2179 | 2180 | .checkout { 2181 | text-align: left; 2182 | } 2183 | 2184 | .checkout section { 2185 | margin: 0; 2186 | padding: 0; 2187 | 2188 | } 2189 | 2190 | @media (min-width: 641px) { 2191 | .checkout section { 2192 | padding: 30px 0; 2193 | } 2194 | } 2195 | 2196 | @media (min-width: 1025px) { 2197 | .checkout section { 2198 | padding: 10px 0; 2199 | } 2200 | } 2201 | 2202 | .checkout.dismiss { 2203 | -webkit-animation: fadeOutDown 250ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2204 | -moz-animation: fadeOutDown 250ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2205 | animation: fadeOutDown 250ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2206 | } 2207 | 2208 | .checkout h1, 2209 | .checkout p, 2210 | .checkout section, 2211 | .checkout .button { 2212 | animation: none; 2213 | } 2214 | 2215 | .checkout h1 { 2216 | -webkit-animation-delay: 200ms; 2217 | -moz-animation-delay: 200ms; 2218 | animation-delay: 200ms; 2219 | } 2220 | 2221 | .checkout header p { 2222 | -webkit-animation-delay: 300ms; 2223 | -moz-animation-delay: 300ms; 2224 | animation-delay: 300ms; 2225 | } 2226 | 2227 | .checkout section { 2228 | -webkit-animation-delay: 450ms; 2229 | -moz-animation-delay: 450ms; 2230 | animation-delay: 450ms; 2231 | -webkit-animation-duration: 550ms; 2232 | -moz-animation-duration: 550ms; 2233 | animation-duration: 550ms; 2234 | } 2235 | 2236 | .checkout .button { 2237 | -webkit-animation-delay: 650ms; 2238 | -moz-animation-delay: 650ms; 2239 | animation-delay: 650ms; 2240 | -webkit-animation-duration: 700ms; 2241 | -moz-animation-duration: 700ms; 2242 | animation-duration: 700ms; 2243 | } 2244 | 2245 | .bt-drop-in-wrapper { 2246 | min-height: 200px; 2247 | position: relative; 2248 | z-index: 1; 2249 | } 2250 | 2251 | .bt-drop-in-placeholder { 2252 | background-color: #f9f9f9; 2253 | height: 187px; 2254 | width: 100%; 2255 | text-align: center; 2256 | color: #707073; 2257 | border: dashed 1px #DEE2E5; 2258 | border-bottom: none; 2259 | display: table; 2260 | } 2261 | 2262 | .bt-drop-in-placeholder:before { 2263 | content: "(Drop-in)"; 2264 | color: #707073; 2265 | display: table-cell; 2266 | vertical-align: middle; 2267 | } 2268 | 2269 | .response { 2270 | text-align: center; 2271 | } 2272 | 2273 | @media (min-width: 1025px) { 2274 | .response { 2275 | -webkit-animation: pullLeftSmall 600ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1100ms; 2276 | -moz-animation: pullLeftSmall 600ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1100ms; 2277 | animation: pullLeftSmall 600ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1100ms; 2278 | padding: 0; 2279 | width: 60%; 2280 | width: 60vw; 2281 | } 2282 | } 2283 | 2284 | .response .notice-wrapper, 2285 | .response .icon, 2286 | .response h1, 2287 | .response section { 2288 | -webkit-animation: fadeInUp 600ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2289 | -moz-animation: fadeInUp 600ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2290 | animation: fadeInUp 600ms 1 normal cubic-bezier(0.215, 0.61, 0.355, 1) both 0s; 2291 | } 2292 | 2293 | .response .icon { 2294 | -webkit-animation-delay: 100ms; 2295 | -moz-animation-delay: 100ms; 2296 | animation-delay: 100ms; 2297 | } 2298 | 2299 | .response h1 { 2300 | -webkit-animation-delay: 200ms; 2301 | -moz-animation-delay: 200ms; 2302 | animation-delay: 200ms; 2303 | } 2304 | 2305 | .response section:nth-of-type(1) { 2306 | -webkit-animation-delay: 400ms; 2307 | -moz-animation-delay: 400ms; 2308 | animation-delay: 400ms; 2309 | } 2310 | 2311 | .response section:nth-of-type(2) { 2312 | -webkit-animation-delay: 600ms; 2313 | -moz-animation-delay: 600ms; 2314 | animation-delay: 600ms; 2315 | } 2316 | 2317 | .response section:nth-of-type(3) { 2318 | -webkit-animation-delay: 800ms; 2319 | -moz-animation-delay: 800ms; 2320 | animation-delay: 800ms; 2321 | } 2322 | 2323 | .response section:nth-of-type(4) { 2324 | -webkit-animation-delay: 1000ms; 2325 | -moz-animation-delay: 1000ms; 2326 | animation-delay: 1000ms; 2327 | } 2328 | 2329 | .response section:last-child { 2330 | -webkit-animation-duration: 800ms; 2331 | -moz-animation-duration: 800ms; 2332 | animation-duration: 800ms; 2333 | } 2334 | 2335 | .response .icon { 2336 | display: inline-block; 2337 | margin: 0 auto; 2338 | } 2339 | 2340 | .response h1 { 2341 | margin: 0.6em 0 0.8em; 2342 | } 2343 | 2344 | .response table { 2345 | margin: auto; 2346 | max-width: 10em; 2347 | } 2348 | 2349 | .response p { 2350 | max-width: 26em; 2351 | display: inline-block; 2352 | margin: 0 auto; 2353 | } 2354 | 2355 | .response .button { 2356 | margin-top: 3em; 2357 | } 2358 | 2359 | aside.drawer { 2360 | -webkit-animation: slideInUp 1200ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 800ms; 2361 | -moz-animation: slideInUp 1200ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 800ms; 2362 | animation: slideInUp 1200ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 800ms; 2363 | width: 100%; 2364 | background-color: #393536; 2365 | text-align: left; 2366 | } 2367 | 2368 | @media (min-width: 1025px) { 2369 | aside.drawer { 2370 | display: -webkit-box; 2371 | display: -moz-box; 2372 | display: box; 2373 | display: -webkit-flex; 2374 | display: -moz-flex; 2375 | display: -ms-flexbox; 2376 | display: flex; 2377 | -webkit-box-flex: 1; 2378 | -moz-box-flex: 1; 2379 | box-flex: 1; 2380 | -webkit-flex: 1 1 auto; 2381 | -moz-flex: 1 1 auto; 2382 | -ms-flex: 1 1 auto; 2383 | flex: 1 1 auto; 2384 | -webkit-align-self: stretch; 2385 | -moz-align-self: stretch; 2386 | align-self: stretch; 2387 | -ms-flex-item-align: stretch; 2388 | -webkit-box-orient: vertical; 2389 | -moz-box-orient: vertical; 2390 | box-orient: vertical; 2391 | -webkit-box-direction: normal; 2392 | -moz-box-direction: normal; 2393 | box-direction: normal; 2394 | -webkit-flex-direction: column; 2395 | -moz-flex-direction: column; 2396 | flex-direction: column; 2397 | -ms-flex-direction: column; 2398 | -webkit-animation: slideLeft 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1200ms; 2399 | -moz-animation: slideLeft 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1200ms; 2400 | animation: slideLeft 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1200ms; 2401 | padding: 0; 2402 | position: fixed; 2403 | width: 33.333%; 2404 | width: 33.333vw; 2405 | height: 100%; 2406 | height: 100vh; 2407 | right: 0px; 2408 | top: 0px; 2409 | bottom: 0px; 2410 | z-index: 900; 2411 | overflow: hidden; 2412 | } 2413 | .out aside.drawer { 2414 | -webkit-animation: slideRight 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1200ms; 2415 | -moz-animation: slideRight 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1200ms; 2416 | animation: slideRight 700ms 1 normal cubic-bezier(0.645, 0.045, 0.355, 1) both 1200ms; 2417 | -webkit-animation-delay: 0s; 2418 | -moz-animation-delay: 0s; 2419 | animation-delay: 0s; 2420 | } 2421 | } 2422 | 2423 | aside.drawer header, 2424 | aside.drawer article { 2425 | width: 100%; 2426 | } 2427 | 2428 | aside.drawer header { 2429 | position: relative; 2430 | border-bottom: solid 1px #4B4A4E; 2431 | text-align: center; 2432 | z-index: 20; 2433 | } 2434 | 2435 | aside.drawer header:before { 2436 | opacity: 0.75; 2437 | position: absolute; 2438 | pointer-events: none; 2439 | top: 100%; 2440 | height: 40px; 2441 | margin-top: 1px; 2442 | background-image: -webkit-linear-gradient(#393536 0%, rgba(48, 46, 51, 0) 100%); 2443 | background-image: -o-linear-gradient(#393536 0%, rgba(48, 46, 51, 0) 100%); 2444 | background-image: linear-gradient(#393536 0%, rgba(48, 46, 51, 0) 100%); 2445 | } 2446 | 2447 | aside.drawer article { 2448 | position: relative; 2449 | z-index: 10; 2450 | } 2451 | 2452 | aside.drawer article:before, 2453 | aside.drawer article:after { 2454 | position: fixed; 2455 | pointer-events: none; 2456 | display: none; 2457 | } 2458 | 2459 | @media (min-width: 1025px) { 2460 | aside.drawer article { 2461 | height: 100%; 2462 | height: 100vh; 2463 | } 2464 | } 2465 | 2466 | aside.drawer article:after { 2467 | opacity: 0.75; 2468 | top: auto; 2469 | bottom: 0px; 2470 | height: 40px; 2471 | background-image: -webkit-linear-gradient(rgba(48, 46, 51, 0) 0%, #393536 100%); 2472 | background-image: -o-linear-gradient(rgba(48, 46, 51, 0) 0%, #393536 100%); 2473 | background-image: linear-gradient(rgba(48, 46, 51, 0) 0%, #393536 100%); 2474 | } 2475 | 2476 | @media (min-width: 1025px) { 2477 | aside.drawer article:after, 2478 | aside.drawer article:before { 2479 | display: block; 2480 | } 2481 | } 2482 | 2483 | aside.drawer h5 { 2484 | font-family: "BT Mono medium", "Helvetica Neue", Helvetica, Sans-serif; 2485 | color: #fff; 2486 | line-height: 1.3em; 2487 | font-size: 16px; 2488 | letter-spacing: .02em; 2489 | margin: 0 0 .9em; 2490 | } 2491 | 2492 | aside.drawer tr { 2493 | border-color: #4B4A4E; 2494 | } 2495 | 2496 | aside.drawer th, 2497 | aside.drawer td { 2498 | font-size: 12px; 2499 | } 2500 | 2501 | aside.drawer th { 2502 | color: #BABABD; 2503 | width: 45%; 2504 | } 2505 | 2506 | aside.drawer td { 2507 | color: #fff; 2508 | width: 55%; 2509 | } 2510 | 2511 | aside.drawer p { 2512 | color: #fff; 2513 | max-width: 22em; 2514 | } 2515 | 2516 | aside.drawer ::selection { 2517 | opacity: 1; 2518 | background: rgba(255, 255, 255, 0.99); 2519 | color: rgba(62, 60, 65, 0.99); 2520 | text-shadow: none; 2521 | } 2522 | --------------------------------------------------------------------------------