stackprofiler 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 */