stackprofiler 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +81 -0
  6. data/Rakefile +2 -0
  7. data/lib/stackprofiler.rb +21 -0
  8. data/lib/stackprofiler/data_collector.rb +24 -0
  9. data/lib/stackprofiler/filters/compress_tree.rb +25 -0
  10. data/lib/stackprofiler/filters/js_tree.rb +24 -0
  11. data/lib/stackprofiler/filters/stackprofiler_elision.rb +12 -0
  12. data/lib/stackprofiler/middleware.rb +18 -0
  13. data/lib/stackprofiler/run_data_source.rb +43 -0
  14. data/lib/stackprofiler/version.rb +3 -0
  15. data/lib/stackprofiler/web_ui.rb +111 -0
  16. data/lib/stackprofiler/web_ui/public/css/bootstrap-theme.css +442 -0
  17. data/lib/stackprofiler/web_ui/public/css/bootstrap-theme.css.map +1 -0
  18. data/lib/stackprofiler/web_ui/public/css/bootstrap-theme.min.css +5 -0
  19. data/lib/stackprofiler/web_ui/public/css/bootstrap.css +6203 -0
  20. data/lib/stackprofiler/web_ui/public/css/bootstrap.css.map +1 -0
  21. data/lib/stackprofiler/web_ui/public/css/bootstrap.min.css +5 -0
  22. data/lib/stackprofiler/web_ui/public/css/coderay.css +131 -0
  23. data/lib/stackprofiler/web_ui/public/css/jquery-ui.css +1225 -0
  24. data/lib/stackprofiler/web_ui/public/css/splitter.css +57 -0
  25. data/lib/stackprofiler/web_ui/public/fonts/glyphicons-halflings-regular.eot +0 -0
  26. data/lib/stackprofiler/web_ui/public/fonts/glyphicons-halflings-regular.svg +229 -0
  27. data/lib/stackprofiler/web_ui/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  28. data/lib/stackprofiler/web_ui/public/fonts/glyphicons-halflings-regular.woff +0 -0
  29. data/lib/stackprofiler/web_ui/public/js/bootstrap.js +2114 -0
  30. data/lib/stackprofiler/web_ui/public/js/bootstrap.min.js +6 -0
  31. data/lib/stackprofiler/web_ui/public/js/jquery.min.js +4 -0
  32. data/lib/stackprofiler/web_ui/public/js/splitter.js +293 -0
  33. data/lib/stackprofiler/web_ui/public/jstree/jstree.js +7073 -0
  34. data/lib/stackprofiler/web_ui/public/jstree/jstree.min.js +5 -0
  35. data/lib/stackprofiler/web_ui/public/jstree/themes/default-dark/32px.png +0 -0
  36. data/lib/stackprofiler/web_ui/public/jstree/themes/default-dark/40px.png +0 -0
  37. data/lib/stackprofiler/web_ui/public/jstree/themes/default-dark/style.css +1094 -0
  38. data/lib/stackprofiler/web_ui/public/jstree/themes/default-dark/style.min.css +1 -0
  39. data/lib/stackprofiler/web_ui/public/jstree/themes/default-dark/throbber.gif +0 -0
  40. data/lib/stackprofiler/web_ui/public/jstree/themes/default/32px.png +0 -0
  41. data/lib/stackprofiler/web_ui/public/jstree/themes/default/40px.png +0 -0
  42. data/lib/stackprofiler/web_ui/public/jstree/themes/default/style.css +1050 -0
  43. data/lib/stackprofiler/web_ui/public/jstree/themes/default/style.min.css +1 -0
  44. data/lib/stackprofiler/web_ui/public/jstree/themes/default/throbber.gif +0 -0
  45. data/lib/stackprofiler/web_ui/public/octicons/LICENSE.txt +9 -0
  46. data/lib/stackprofiler/web_ui/public/octicons/README.md +1 -0
  47. data/lib/stackprofiler/web_ui/public/octicons/octicons-local.ttf +0 -0
  48. data/lib/stackprofiler/web_ui/public/octicons/octicons.css +235 -0
  49. data/lib/stackprofiler/web_ui/public/octicons/octicons.eot +0 -0
  50. data/lib/stackprofiler/web_ui/public/octicons/octicons.less +233 -0
  51. data/lib/stackprofiler/web_ui/public/octicons/octicons.svg +198 -0
  52. data/lib/stackprofiler/web_ui/public/octicons/octicons.ttf +0 -0
  53. data/lib/stackprofiler/web_ui/public/octicons/octicons.woff +0 -0
  54. data/lib/stackprofiler/web_ui/public/octicons/sprockets-octicons.scss +230 -0
  55. data/lib/stackprofiler/web_ui/views/code.erb +18 -0
  56. data/lib/stackprofiler/web_ui/views/index.erb +45 -0
  57. data/lib/stackprofiler/web_ui/views/layout.erb +79 -0
  58. data/stackprofiler.gemspec +30 -0
  59. metadata +213 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ec396ab3126b59c0e52b0b0e35abe6a67bfbc39c
4
+ data.tar.gz: 035f170274d6bfe42cc4ca507a53069658fe1592
5
+ SHA512:
6
+ metadata.gz: a3f64d23fd792ae533c17df0b31a21ae6125d1df0b1c7d1f4c890e5609b66bf03280031d370c5613c385d27a0459b6456844b6416531ac365cb63351ace2a999
7
+ data.tar.gz: 4e303ce9b29293ea6340bffbc0a0a22950251a47a5f9c765d39757f0441a7c9cc74c55d0d1b850d2bb0577ed4dbe66eb685393ffdf997be20a1b64932e93a617
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .idea
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in stackprofiler.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Aidan Steele
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # Stackprofiler
2
+
3
+ Stackprofiler is a web UI wrapper for the excellent [`stackprof`][1]
4
+ sampling call-stack profiler for Ruby 2.1+. `stackprof` features a
5
+ command-line tool that is very handy for inspecting hotspots in code,
6
+ but seeing the "bigger picture" can be difficult without a GUI to
7
+ click around in. Hence: Stackprofiler.
8
+
9
+ There already exist gems in this vein. Most (all?) are based on
10
+ [`rubyprof`][2], an instrumenting profiler for Ruby 1.9.3+.
11
+ Unfortunately, in my experience RubyProf has an unacceptably
12
+ high overhead when profiling already-slow code and this makes
13
+ profiling very frustrating, if not useless. Maybe I'm holding it
14
+ wrong, but `stackprof` seems much more useful.
15
+
16
+ Stackprofiler is in an **incredibly early** state of development. The
17
+ only reason it has been published this early is as supporting evidence
18
+ for a job application! Please keep that in mind when you find all the
19
+ rough edges :)
20
+
21
+ ![Screenshot](http://i.imgur.com/8UJV9Oo.png)
22
+
23
+ ## Installation
24
+
25
+ Add this line to your application's Gemfile:
26
+
27
+ ```ruby
28
+ gem 'stackprofiler'
29
+ ```
30
+
31
+ And then execute:
32
+
33
+ $ bundle
34
+
35
+ Or install it yourself as:
36
+
37
+ $ gem install stackprofiler
38
+
39
+ ## Usage
40
+
41
+ Using Stackprofiler at this stage is pretty simple on account of there
42
+ not yet being much flexibility in the way of configuration. This will be
43
+ fixed later - hopefully the simplicity can remain.
44
+
45
+ Once installed, add Stackprofiler's middleware somewhere in your Rack
46
+ chain, e.g.:
47
+
48
+ config.middleware.use Stackprofiler::Middleware
49
+
50
+ Now start your server like normal. If you wish to profile a request,
51
+ append `profile=true` to the query string. This will inform Stackprofiler
52
+ that it should do its thing. Take note that the response will remain
53
+ unchanged - Stackprofiler will record its statistics for your later perusal
54
+ elsewhere. This is to make it easier to profile requests that don't return
55
+ visible results, e.g. XHR.
56
+
57
+ Once you have profiled a request or two, you can head over to Stackprofiler's
58
+ GUI. This is located on the same port as your website, albeit at the
59
+ path `/__stackprofiler`. If your server is running on port 5000 in development,
60
+ the link might be [`http://localhost:5000/__stackprofiler`]([http://localhost:5000/__stackprofiler]).
61
+
62
+ You should now see a page that looks like the screenshot above. Click on any
63
+ line in the stack trace to see the code for that method annotated with the
64
+ performance characteristics for each line. I would document those here but
65
+ they are going to change in the next few dev hours, so I'll come back to that
66
+ later.
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it ( https://github.com/glassechidna/stackprofiler/fork )
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create a new Pull Request
75
+
76
+ ## TODO
77
+
78
+ So much. First todo: write a todo list.
79
+
80
+ [1]: https://github.com/tmm1/stackprof
81
+ [2]: https://github.com/ruby-prof/ruby-prof
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+
@@ -0,0 +1,21 @@
1
+ require 'oj'
2
+ require 'tree'
3
+ require 'coderay'
4
+ require 'objspace'
5
+ require 'stackprof'
6
+ require 'sinatra/base'
7
+ require 'sinatra/content_for'
8
+
9
+ require 'stackprofiler/version'
10
+ require 'stackprofiler/web_ui'
11
+ require 'stackprofiler/middleware'
12
+ require 'stackprofiler/data_collector'
13
+ require 'stackprofiler/run_data_source'
14
+
15
+ require 'stackprofiler/filters/js_tree'
16
+ require 'stackprofiler/filters/compress_tree'
17
+ require 'stackprofiler/filters/stackprofiler_elision'
18
+
19
+ module Stackprofiler
20
+ # Your code goes here...
21
+ end
@@ -0,0 +1,24 @@
1
+ module Stackprofiler
2
+ class DataCollector
3
+ def initialize(app, options = {})
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ puts env['PATH_INFO']
9
+ if env['QUERY_STRING'] =~ /profile=true/
10
+ out = nil
11
+ profile = StackProf.run(mode: :wall, interval: 1000, raw: true) { out = @app.call env }
12
+
13
+ req = Rack::Request.new env
14
+ run = Run.new req.fullpath, profile, Time.now
15
+ RunDataSource.runs << run
16
+
17
+ out
18
+ else
19
+ @app.call env
20
+ end
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,25 @@
1
+ module Stackprofiler
2
+ module Filter
3
+ class CompressTree
4
+ def filter root, frames
5
+ depths = Hash.new {|h, k| h[k] = [] }
6
+ root.each {|n| depths[n.node_depth].push n }
7
+ depths.delete 0
8
+
9
+ depths.keys.sort.reverse.each do |depth|
10
+ nodes = depths[depth]
11
+ nodes.each do |node|
12
+ if node.out_degree == 1
13
+ hash = node.content.dup
14
+ hash[:addrs] = hash[:addrs] + node.first_child.content[:addrs]
15
+ repl = Tree::TreeNode.new(node.name, hash)
16
+ node.first_child.children.each {|n| repl << n }
17
+ node.replace_with repl
18
+ end
19
+ end
20
+ end
21
+ root
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ module Stackprofiler
2
+ module Filter
3
+ class JsTree
4
+ def filter root, frames
5
+ addrs = root.content[:addrs]
6
+ name = addrs.first.to_i
7
+ frame = frames[name]
8
+
9
+ escaped = addrs.map do |addr|
10
+ this_frame = frames[addr.to_i]
11
+ this_name = CGI::escapeHTML(this_frame[:name])
12
+ "#{this_name} (<b>#{this_frame[:samples]}</b>)"
13
+ end
14
+ text = escaped.join("<br> ↳ ")
15
+
16
+ children = root.children.map { |n| filter(n, frames) }
17
+ open = frame[:total_samples] > 100
18
+ {text: text, children: children, state: {opened: open}, icon: false, data: {addrs: addrs}}
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+
@@ -0,0 +1,12 @@
1
+ module Stackprofiler
2
+ module Filter
3
+ class StackprofilerElision
4
+ def filter root, frames
5
+ root.find do |node|
6
+ addr = node.content[:addrs].first.to_i
7
+ frames[addr][:name] == 'Stackprofiler::DataCollector#call'
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ module Stackprofiler
2
+ class Middleware
3
+ def initialize(app, options = {})
4
+ mid = Rack::Builder.new do
5
+ use Rack::Deflater
6
+ run WebUI
7
+ end
8
+
9
+ @app = Rack::URLMap.new({'/__stackprofiler' => mid, '/' => DataCollector.new(app)})
10
+ @options = options
11
+ end
12
+
13
+ def call(env)
14
+ @app.call env
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,43 @@
1
+ module Stackprofiler
2
+ class Run
3
+ attr_accessor :url
4
+ attr_accessor :profile
5
+ attr_accessor :timestamp
6
+
7
+ def initialize(url, profile, timestamp)
8
+ @url = url
9
+ @profile = profile
10
+ @timestamp = timestamp
11
+ end
12
+
13
+ def stacks
14
+ @stacks ||= begin
15
+ off = 0
16
+ stacks = []
17
+ raw = @profile[:raw]
18
+ while off < raw.length
19
+ len = raw[off]
20
+ these_frames = raw[off + 1..off + len]
21
+ off += len + 2
22
+
23
+ stacks.push these_frames
24
+ end
25
+ stacks
26
+ end
27
+ end
28
+
29
+ def duration
30
+ profile[:samples] * profile[:interval] / 1e6
31
+ end
32
+ end
33
+
34
+ class RunDataSource
35
+ class << self
36
+ RUNS = []
37
+
38
+ def runs
39
+ RUNS
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ module Stackprofiler
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,111 @@
1
+ module Stackprofiler
2
+ module Filter
3
+ class QuickMethodElision
4
+ def filter root, frames
5
+ root.each do |node|
6
+ next if node == root
7
+
8
+ addr = node.name.to_i
9
+ frame = frames[addr]
10
+ if frame[:samples] < 10
11
+ parent = node.parent
12
+ node.remove_from_parent!
13
+
14
+ node.children.each do |n|
15
+ n.remove_from_parent!
16
+ parent << n
17
+ end
18
+ end
19
+ end
20
+ root
21
+ end
22
+ end
23
+ end
24
+
25
+ class WebUI < Sinatra::Base
26
+ helpers Sinatra::ContentFor
27
+ set :views, proc { File.join(root, 'web_ui', 'views') }
28
+ set :public_folder, proc { File.join(root, 'web_ui', 'public') }
29
+
30
+ get '/' do
31
+ @runs = RunDataSource.runs
32
+ @run_id = params[:run_id].try(:to_i) || (@runs.count - 1)
33
+ erb :index
34
+ end
35
+
36
+ get '/stats' do
37
+ content_type 'application/json'
38
+ RunDataSource.runs.map do |run|
39
+ objs = ObjectSpace.reachable_objects_from run.profile
40
+ objs.reduce(0) {|size, obj| size + ObjectSpace::memsize_of(obj) }
41
+ end.to_json
42
+ end
43
+
44
+ get '/frames' do
45
+ content_type 'application/json'
46
+ run_id = params[:run_id].to_i
47
+ run = RunDataSource.runs[run_id]
48
+ run.profile[:frames].to_json
49
+ end
50
+
51
+ get '/code/:addr' do
52
+ addr = params[:addr].to_i
53
+
54
+ run_id = params[:run_id].to_i
55
+ run = RunDataSource.runs[run_id]
56
+
57
+ data = run.profile
58
+ frames = data[:frames]
59
+
60
+ frame = frames[addr]
61
+ halt 404 if frame.nil?
62
+
63
+ file, first_line = frame.values_at :file, :line
64
+ first_line ||= 1
65
+
66
+ last_line = frame[:lines].keys.max || first_line + 5
67
+ line_range = first_line..last_line
68
+
69
+ @source = File.readlines(file).select.with_index {|line, idx| line_range.include? (idx + 1) }.join
70
+ @output = CodeRay.scan(@source, :ruby).div(wrap: nil).lines.map.with_index do |code, idx|
71
+ line_index = idx + first_line
72
+ samples = frame[:lines][line_index] || []
73
+ {code: code, samples: samples.first}
74
+ end
75
+
76
+ erb :code, layout: nil
77
+ end
78
+
79
+ get '/json' do
80
+ content_type 'application/json'
81
+
82
+ run_id = params[:run_id].to_i
83
+ run = RunDataSource.runs[run_id]
84
+ frames = run.profile[:frames]
85
+ stacks = run.stacks
86
+
87
+ root_addr = stacks[0][0].to_s
88
+ root = Tree::TreeNode.new root_addr, {text: 'root', addrs: [root_addr]}
89
+
90
+ stacks.each do |stack|
91
+ prev = root
92
+ stack.each do |addr|
93
+ addr = addr.to_s
94
+ node = prev[addr]
95
+ if node.nil?
96
+ hash = {count: 0, text: frames[addr.to_i][:name], addrs: [addr]}
97
+ node = Tree::TreeNode.new(addr, hash)
98
+ prev << node
99
+ end
100
+ node.content[:count] +=1
101
+ prev = node
102
+ end
103
+ end
104
+
105
+ filters = [Filter::StackprofilerElision.new, Filter::CompressTree.new, Filter::JsTree.new]
106
+ filtered = filters.reduce(root) {|memo, filter| filter.filter(memo, frames) }
107
+
108
+ Oj.dump(filtered, mode: :compat)
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,442 @@
1
+ /*!
2
+ * Bootstrap v3.2.0 (http://getbootstrap.com)
3
+ * Copyright 2011-2014 Twitter, Inc.
4
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5
+ */
6
+
7
+ .btn-default,
8
+ .btn-primary,
9
+ .btn-success,
10
+ .btn-info,
11
+ .btn-warning,
12
+ .btn-danger {
13
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
14
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
15
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
16
+ }
17
+ .btn-default:active,
18
+ .btn-primary:active,
19
+ .btn-success:active,
20
+ .btn-info:active,
21
+ .btn-warning:active,
22
+ .btn-danger:active,
23
+ .btn-default.active,
24
+ .btn-primary.active,
25
+ .btn-success.active,
26
+ .btn-info.active,
27
+ .btn-warning.active,
28
+ .btn-danger.active {
29
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
30
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
31
+ }
32
+ .btn:active,
33
+ .btn.active {
34
+ background-image: none;
35
+ }
36
+ .btn-default {
37
+ text-shadow: 0 1px 0 #fff;
38
+ background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
39
+ background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
40
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
41
+ background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
42
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
43
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
44
+ background-repeat: repeat-x;
45
+ border-color: #dbdbdb;
46
+ border-color: #ccc;
47
+ }
48
+ .btn-default:hover,
49
+ .btn-default:focus {
50
+ background-color: #e0e0e0;
51
+ background-position: 0 -15px;
52
+ }
53
+ .btn-default:active,
54
+ .btn-default.active {
55
+ background-color: #e0e0e0;
56
+ border-color: #dbdbdb;
57
+ }
58
+ .btn-default:disabled,
59
+ .btn-default[disabled] {
60
+ background-color: #e0e0e0;
61
+ background-image: none;
62
+ }
63
+ .btn-primary {
64
+ background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
65
+ background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
66
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2));
67
+ background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
68
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
69
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
70
+ background-repeat: repeat-x;
71
+ border-color: #2b669a;
72
+ }
73
+ .btn-primary:hover,
74
+ .btn-primary:focus {
75
+ background-color: #2d6ca2;
76
+ background-position: 0 -15px;
77
+ }
78
+ .btn-primary:active,
79
+ .btn-primary.active {
80
+ background-color: #2d6ca2;
81
+ border-color: #2b669a;
82
+ }
83
+ .btn-primary:disabled,
84
+ .btn-primary[disabled] {
85
+ background-color: #2d6ca2;
86
+ background-image: none;
87
+ }
88
+ .btn-success {
89
+ background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
90
+ background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
91
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
92
+ background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
93
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
94
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
95
+ background-repeat: repeat-x;
96
+ border-color: #3e8f3e;
97
+ }
98
+ .btn-success:hover,
99
+ .btn-success:focus {
100
+ background-color: #419641;
101
+ background-position: 0 -15px;
102
+ }
103
+ .btn-success:active,
104
+ .btn-success.active {
105
+ background-color: #419641;
106
+ border-color: #3e8f3e;
107
+ }
108
+ .btn-success:disabled,
109
+ .btn-success[disabled] {
110
+ background-color: #419641;
111
+ background-image: none;
112
+ }
113
+ .btn-info {
114
+ background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
115
+ background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
116
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
117
+ background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
118
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
119
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
120
+ background-repeat: repeat-x;
121
+ border-color: #28a4c9;
122
+ }
123
+ .btn-info:hover,
124
+ .btn-info:focus {
125
+ background-color: #2aabd2;
126
+ background-position: 0 -15px;
127
+ }
128
+ .btn-info:active,
129
+ .btn-info.active {
130
+ background-color: #2aabd2;
131
+ border-color: #28a4c9;
132
+ }
133
+ .btn-info:disabled,
134
+ .btn-info[disabled] {
135
+ background-color: #2aabd2;
136
+ background-image: none;
137
+ }
138
+ .btn-warning {
139
+ background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
140
+ background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
141
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
142
+ background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
143
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
144
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
145
+ background-repeat: repeat-x;
146
+ border-color: #e38d13;
147
+ }
148
+ .btn-warning:hover,
149
+ .btn-warning:focus {
150
+ background-color: #eb9316;
151
+ background-position: 0 -15px;
152
+ }
153
+ .btn-warning:active,
154
+ .btn-warning.active {
155
+ background-color: #eb9316;
156
+ border-color: #e38d13;
157
+ }
158
+ .btn-warning:disabled,
159
+ .btn-warning[disabled] {
160
+ background-color: #eb9316;
161
+ background-image: none;
162
+ }
163
+ .btn-danger {
164
+ background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
165
+ background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
166
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
167
+ background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
168
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
169
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
170
+ background-repeat: repeat-x;
171
+ border-color: #b92c28;
172
+ }
173
+ .btn-danger:hover,
174
+ .btn-danger:focus {
175
+ background-color: #c12e2a;
176
+ background-position: 0 -15px;
177
+ }
178
+ .btn-danger:active,
179
+ .btn-danger.active {
180
+ background-color: #c12e2a;
181
+ border-color: #b92c28;
182
+ }
183
+ .btn-danger:disabled,
184
+ .btn-danger[disabled] {
185
+ background-color: #c12e2a;
186
+ background-image: none;
187
+ }
188
+ .thumbnail,
189
+ .img-thumbnail {
190
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
191
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
192
+ }
193
+ .dropdown-menu > li > a:hover,
194
+ .dropdown-menu > li > a:focus {
195
+ background-color: #e8e8e8;
196
+ background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
197
+ background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
198
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
199
+ background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
200
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
201
+ background-repeat: repeat-x;
202
+ }
203
+ .dropdown-menu > .active > a,
204
+ .dropdown-menu > .active > a:hover,
205
+ .dropdown-menu > .active > a:focus {
206
+ background-color: #357ebd;
207
+ background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
208
+ background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
209
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
210
+ background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
211
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
212
+ background-repeat: repeat-x;
213
+ }
214
+ .navbar-default {
215
+ background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
216
+ background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
217
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
218
+ background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
219
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
220
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
221
+ background-repeat: repeat-x;
222
+ border-radius: 4px;
223
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
224
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
225
+ }
226
+ .navbar-default .navbar-nav > .active > a {
227
+ background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
228
+ background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
229
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3));
230
+ background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
231
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
232
+ background-repeat: repeat-x;
233
+ -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
234
+ box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
235
+ }
236
+ .navbar-brand,
237
+ .navbar-nav > li > a {
238
+ text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
239
+ }
240
+ .navbar-inverse {
241
+ background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
242
+ background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
243
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
244
+ background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
245
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
246
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
247
+ background-repeat: repeat-x;
248
+ }
249
+ .navbar-inverse .navbar-nav > .active > a {
250
+ background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);
251
+ background-image: -o-linear-gradient(top, #222 0%, #282828 100%);
252
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828));
253
+ background-image: linear-gradient(to bottom, #222 0%, #282828 100%);
254
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
255
+ background-repeat: repeat-x;
256
+ -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
257
+ box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
258
+ }
259
+ .navbar-inverse .navbar-brand,
260
+ .navbar-inverse .navbar-nav > li > a {
261
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
262
+ }
263
+ .navbar-static-top,
264
+ .navbar-fixed-top,
265
+ .navbar-fixed-bottom {
266
+ border-radius: 0;
267
+ }
268
+ .alert {
269
+ text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
270
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
271
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
272
+ }
273
+ .alert-success {
274
+ background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
275
+ background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
276
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
277
+ background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
278
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
279
+ background-repeat: repeat-x;
280
+ border-color: #b2dba1;
281
+ }
282
+ .alert-info {
283
+ background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
284
+ background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
285
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
286
+ background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
287
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
288
+ background-repeat: repeat-x;
289
+ border-color: #9acfea;
290
+ }
291
+ .alert-warning {
292
+ background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
293
+ background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
294
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
295
+ background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
296
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
297
+ background-repeat: repeat-x;
298
+ border-color: #f5e79e;
299
+ }
300
+ .alert-danger {
301
+ background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
302
+ background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
303
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
304
+ background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
305
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
306
+ background-repeat: repeat-x;
307
+ border-color: #dca7a7;
308
+ }
309
+ .progress {
310
+ background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
311
+ background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
312
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
313
+ background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
314
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
315
+ background-repeat: repeat-x;
316
+ }
317
+ .progress-bar {
318
+ background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
319
+ background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%);
320
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9));
321
+ background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
322
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
323
+ background-repeat: repeat-x;
324
+ }
325
+ .progress-bar-success {
326
+ background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
327
+ background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
328
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
329
+ background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
330
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
331
+ background-repeat: repeat-x;
332
+ }
333
+ .progress-bar-info {
334
+ background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
335
+ background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
336
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
337
+ background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
338
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
339
+ background-repeat: repeat-x;
340
+ }
341
+ .progress-bar-warning {
342
+ background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
343
+ background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
344
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
345
+ background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
346
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
347
+ background-repeat: repeat-x;
348
+ }
349
+ .progress-bar-danger {
350
+ background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
351
+ background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
352
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
353
+ background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
354
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
355
+ background-repeat: repeat-x;
356
+ }
357
+ .progress-bar-striped {
358
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
359
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
360
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
361
+ }
362
+ .list-group {
363
+ border-radius: 4px;
364
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
365
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
366
+ }
367
+ .list-group-item.active,
368
+ .list-group-item.active:hover,
369
+ .list-group-item.active:focus {
370
+ text-shadow: 0 -1px 0 #3071a9;
371
+ background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
372
+ background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%);
373
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3));
374
+ background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
375
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
376
+ background-repeat: repeat-x;
377
+ border-color: #3278b3;
378
+ }
379
+ .panel {
380
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
381
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
382
+ }
383
+ .panel-default > .panel-heading {
384
+ background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
385
+ background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
386
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
387
+ background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
388
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
389
+ background-repeat: repeat-x;
390
+ }
391
+ .panel-primary > .panel-heading {
392
+ background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
393
+ background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
394
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
395
+ background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
396
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
397
+ background-repeat: repeat-x;
398
+ }
399
+ .panel-success > .panel-heading {
400
+ background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
401
+ background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
402
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
403
+ background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
404
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
405
+ background-repeat: repeat-x;
406
+ }
407
+ .panel-info > .panel-heading {
408
+ background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
409
+ background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
410
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
411
+ background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
412
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
413
+ background-repeat: repeat-x;
414
+ }
415
+ .panel-warning > .panel-heading {
416
+ background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
417
+ background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
418
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
419
+ background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
420
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
421
+ background-repeat: repeat-x;
422
+ }
423
+ .panel-danger > .panel-heading {
424
+ background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
425
+ background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
426
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
427
+ background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
428
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
429
+ background-repeat: repeat-x;
430
+ }
431
+ .well {
432
+ background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
433
+ background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
434
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
435
+ background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
436
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
437
+ background-repeat: repeat-x;
438
+ border-color: #dcdcdc;
439
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
440
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
441
+ }
442
+ /*# sourceMappingURL=bootstrap-theme.css.map */