From 7cdeb3831c6d9abf09fe9630fc13108c941f2e34 Mon Sep 17 00:00:00 2001 From: zysam Date: Sat, 7 Nov 2015 21:46:47 +0800 Subject: [PATCH 1/3] start --- .gitignore | 26 + .jshintrc | 44 + .travis.yml | 31 + History.md | 208 + Makefile | 52 + README.md | 60 + api/v1/message.js | 93 + api/v1/middleware.js | 26 + api/v1/reply.js | 115 + api/v1/tools.js | 14 + api/v1/topic.js | 222 + api/v1/user.js | 57 + api_router_v1.js | 36 + app.js | 175 + bin/fix_at_problem.js | 17 + bin/generate_accesstoken.js | 41 + common/at.js | 111 + common/cache.js | 43 + common/logger.js | 62 + common/mail.js | 72 + common/message.js | 45 + common/push.js | 59 + common/redis.js | 17 + common/render_helper.js | 98 + common/store.js | 4 + common/store_local.js | 24 + common/store_qn.js | 10 + common/tools.js | 28 + config.default.js | 136 + controllers/github.js | 118 + controllers/message.js | 33 + controllers/reply.js | 191 + controllers/rss.js | 56 + controllers/search.js | 5 + controllers/sign.js | 291 + controllers/site.js | 151 + controllers/static.js | 37 + controllers/topic.js | 441 + controllers/user.js | 368 + gulpfile.js | 15 + middlewares/auth.js | 106 + middlewares/conf.js | 8 + middlewares/error_page.js | 16 + middlewares/github_strategy.js | 4 + middlewares/limit.js | 39 + middlewares/mongoose_log.js | 16 + middlewares/proxy.js | 30 + middlewares/render.js | 17 + middlewares/request_log.js | 22 + models/base_model.js | 15 + models/index.js | 25 + models/message.js | 26 + models/reply.js | 22 + models/topic.js | 45 + models/topic_collect.js | 13 + models/user.js | 79 + oneapm.js | 30 + package.json | 71 + proxy/index.js | 5 + proxy/message.js | 104 + proxy/reply.js | 149 + proxy/topic.js | 226 + proxy/topic_collect.js | 21 + proxy/user.js | 118 + public/favicon.ico | Bin 0 -> 1150 bytes public/github-card.html | 5 + public/images/cnode_icon_32.png | Bin 0 -> 2156 bytes public/images/cnode_icon_64.png | Bin 0 -> 1388 bytes public/images/cnode_logo_128.png | Bin 0 -> 7935 bytes public/images/cnode_logo_32.png | Bin 0 -> 4325 bytes public/images/cnodejs.svg | 54 + public/images/cnodejs_light.svg | 54 + public/images/digitalocean.png | Bin 0 -> 9370 bytes public/images/golangtc-logo.png | Bin 0 -> 16497 bytes public/images/iojs-logo-w150h50.png | Bin 0 -> 3627 bytes public/images/iojs-logo.png | Bin 0 -> 5813 bytes public/images/logo.png | Bin 0 -> 4083 bytes public/images/logo_bak.png | Bin 0 -> 3863 bytes public/images/nodejs_black.png | Bin 0 -> 2630 bytes public/images/phphub-logo.png | Bin 0 -> 14072 bytes public/images/qiniu.png | Bin 0 -> 8429 bytes public/images/ruby-china-20150529.png | Bin 0 -> 15734 bytes public/images/ruby-china-logo2.png | Bin 0 -> 20294 bytes public/images/search.png | Bin 0 -> 441 bytes public/images/ucloud.png | Bin 0 -> 8251 bytes public/images/upyun_logo.png | Bin 0 -> 5066 bytes public/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes public/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes public/javascripts/main.js | 41 + public/javascripts/responsive.js | 70 + .../bootstrap/css/bootstrap-responsive.css | 1345 +++ .../css/bootstrap-responsive.min.css | 1249 +++ public/libs/bootstrap/css/bootstrap.css | 6169 +++++++++++ public/libs/bootstrap/css/bootstrap.min.css | 5469 ++++++++++ .../img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../bootstrap/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes public/libs/bootstrap/js/bootstrap.js | 2117 ++++ public/libs/bootstrap/js/bootstrap.min.js | 644 ++ public/libs/code-prettify/lang-apollo.js | 12 + public/libs/code-prettify/lang-clj.js | 26 + public/libs/code-prettify/lang-css.js | 22 + public/libs/code-prettify/lang-go.js | 7 + public/libs/code-prettify/lang-hs.js | 12 + public/libs/code-prettify/lang-lisp.js | 14 + public/libs/code-prettify/lang-lua.js | 11 + public/libs/code-prettify/lang-ml.js | 11 + public/libs/code-prettify/lang-n.js | 21 + public/libs/code-prettify/lang-proto.js | 1 + public/libs/code-prettify/lang-scala.js | 16 + public/libs/code-prettify/lang-sql.js | 11 + public/libs/code-prettify/lang-tex.js | 10 + public/libs/code-prettify/lang-vb.js | 13 + public/libs/code-prettify/lang-vhdl.js | 13 + public/libs/code-prettify/lang-wiki.js | 14 + public/libs/code-prettify/lang-xq.js | 15 + public/libs/code-prettify/lang-yaml.js | 16 + public/libs/code-prettify/prettify.css | 142 + public/libs/code-prettify/prettify.js | 376 + public/libs/editor/editor.css | 422 + public/libs/editor/editor.js | 7337 +++++++++++++ public/libs/editor/ext.js | 246 + public/libs/editor/fonts/icomoon.dev.svg | 56 + public/libs/editor/fonts/icomoon.eot | Bin 0 -> 3440 bytes public/libs/editor/fonts/icomoon.svg | 56 + public/libs/editor/fonts/icomoon.ttf | Bin 0 -> 3276 bytes public/libs/editor/fonts/icomoon.woff | Bin 0 -> 3540 bytes public/libs/font-awesome/css/font-awesome.css | 1672 +++ .../libs/font-awesome/fonts/FontAwesome.otf | Bin 0 -> 85908 bytes .../fonts/fontawesome-webfont.eot | Bin 0 -> 56006 bytes .../fonts/fontawesome-webfont.svg | 520 + .../fonts/fontawesome-webfont.ttf | Bin 0 -> 112160 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 65452 bytes public/libs/jquery-2.1.0.js | 9083 ++++++++++++++++ public/libs/jquery-ujs.js | 420 + public/libs/jquery.atwho.js | 853 ++ public/libs/jquery.caret.js | 366 + public/libs/lodash.compat.js | 7186 +++++++++++++ public/libs/markdownit.js | 9345 +++++++++++++++++ public/libs/qrcode.js | 614 ++ public/libs/webuploader/Uploader.swf | Bin 0 -> 143169 bytes public/libs/webuploader/webuploader.css | 28 + .../webuploader/webuploader.withoutimage.js | 4666 ++++++++ public/stylesheets/common.css | 63 + public/stylesheets/jquery.atwho.css | 47 + public/stylesheets/responsive.css | 167 + public/stylesheets/style.less | 1262 +++ test/api/v1/message.test.js | 75 + test/api/v1/reply.test.js | 124 + test/api/v1/tools.test.js | 42 + test/api/v1/topic.test.js | 129 + test/api/v1/user.test.js | 20 + test/app.test.js | 14 + test/common/at.test.js | 238 + test/common/cache.test.js | 24 + test/common/mail.test.js | 16 + test/common/message.test.js | 85 + test/common/render_helper.test.js | 47 + test/common/store_local.test.js | 21 + test/common/tools.test.js | 19 + test/controllers/github.test.js | 156 + test/controllers/message.test.js | 30 + test/controllers/reply.test.js | 150 + test/controllers/rss.test.js | 71 + test/controllers/search.test.js | 13 + test/controllers/sign.test.js | 241 + test/controllers/site.test.js | 51 + test/controllers/static.test.js | 36 + test/controllers/topic.test.js | 297 + test/controllers/user.test.js | 290 + test/env.js | 6 + test/middlewares/conf.test.js | 14 + test/middlewares/limit.test.js | 40 + test/middlewares/proxy.test.js | 61 + test/models/user.test.js | 8 + test/proxy/message.test.js | 5 + test/proxy/reply.test.js | 6 + test/proxy/topic.test.js | 6 + test/proxy/user.test.js | 6 + test/support/support.js | 75 + views/_ads.html | 0 views/_sponsors.html | 17 + views/editor_sidebar.html | 32 + views/index.html | 28 + views/layout.html | 159 + views/message/index.html | 31 + views/message/message.html | 39 + views/notify/notify.html | 27 + views/reply/edit.html | 60 + views/reply/reply.html | 69 + views/sidebar.html | 124 + views/sign/new_oauth.html | 51 + views/sign/no_github_email.html | 12 + views/sign/reset.html | 43 + views/sign/search_pass.html | 38 + views/sign/sidebar.html | 18 + views/sign/signin.html | 47 + views/sign/signup.html | 74 + views/static/about.html | 39 + views/static/api.html | 203 + views/static/faq.html | 21 + views/static/getstart.html | 70 + views/topic/_top_good.html | 7 + views/topic/abstract.html | 39 + views/topic/edit.html | 115 + views/topic/index.html | 457 + views/topic/list.html | 57 + views/topic/small.html | 4 + views/user/card.html | 52 + views/user/collect_topics.html | 20 + views/user/followers.html | 19 + views/user/followings.html | 19 + views/user/index.html | 179 + views/user/replies.html | 26 + views/user/setting.html | 148 + views/user/star.html | 8 + views/user/stars.html | 19 + views/user/top.html | 4 + views/user/top100.html | 30 + views/user/top100_user.html | 12 + views/user/topics.html | 26 + views/user/user.html | 34 + web_router.js | 119 + 222 files changed, 72240 insertions(+) create mode 100644 .gitignore create mode 100644 .jshintrc create mode 100644 .travis.yml create mode 100644 History.md create mode 100644 Makefile create mode 100644 README.md create mode 100644 api/v1/message.js create mode 100644 api/v1/middleware.js create mode 100644 api/v1/reply.js create mode 100644 api/v1/tools.js create mode 100644 api/v1/topic.js create mode 100644 api/v1/user.js create mode 100644 api_router_v1.js create mode 100644 app.js create mode 100644 bin/fix_at_problem.js create mode 100644 bin/generate_accesstoken.js create mode 100644 common/at.js create mode 100644 common/cache.js create mode 100644 common/logger.js create mode 100644 common/mail.js create mode 100644 common/message.js create mode 100644 common/push.js create mode 100644 common/redis.js create mode 100644 common/render_helper.js create mode 100644 common/store.js create mode 100644 common/store_local.js create mode 100644 common/store_qn.js create mode 100644 common/tools.js create mode 100644 config.default.js create mode 100644 controllers/github.js create mode 100644 controllers/message.js create mode 100644 controllers/reply.js create mode 100644 controllers/rss.js create mode 100644 controllers/search.js create mode 100644 controllers/sign.js create mode 100644 controllers/site.js create mode 100644 controllers/static.js create mode 100644 controllers/topic.js create mode 100644 controllers/user.js create mode 100644 gulpfile.js create mode 100644 middlewares/auth.js create mode 100644 middlewares/conf.js create mode 100644 middlewares/error_page.js create mode 100644 middlewares/github_strategy.js create mode 100644 middlewares/limit.js create mode 100644 middlewares/mongoose_log.js create mode 100644 middlewares/proxy.js create mode 100644 middlewares/render.js create mode 100644 middlewares/request_log.js create mode 100644 models/base_model.js create mode 100644 models/index.js create mode 100644 models/message.js create mode 100644 models/reply.js create mode 100644 models/topic.js create mode 100644 models/topic_collect.js create mode 100644 models/user.js create mode 100644 oneapm.js create mode 100644 package.json create mode 100644 proxy/index.js create mode 100644 proxy/message.js create mode 100644 proxy/reply.js create mode 100644 proxy/topic.js create mode 100644 proxy/topic_collect.js create mode 100644 proxy/user.js create mode 100644 public/favicon.ico create mode 100644 public/github-card.html create mode 100644 public/images/cnode_icon_32.png create mode 100644 public/images/cnode_icon_64.png create mode 100644 public/images/cnode_logo_128.png create mode 100644 public/images/cnode_logo_32.png create mode 100644 public/images/cnodejs.svg create mode 100644 public/images/cnodejs_light.svg create mode 100644 public/images/digitalocean.png create mode 100644 public/images/golangtc-logo.png create mode 100644 public/images/iojs-logo-w150h50.png create mode 100644 public/images/iojs-logo.png create mode 100644 public/images/logo.png create mode 100644 public/images/logo_bak.png create mode 100644 public/images/nodejs_black.png create mode 100644 public/images/phphub-logo.png create mode 100644 public/images/qiniu.png create mode 100644 public/images/ruby-china-20150529.png create mode 100644 public/images/ruby-china-logo2.png create mode 100644 public/images/search.png create mode 100644 public/images/ucloud.png create mode 100644 public/images/upyun_logo.png create mode 100644 public/img/glyphicons-halflings-white.png create mode 100644 public/img/glyphicons-halflings.png create mode 100644 public/javascripts/main.js create mode 100644 public/javascripts/responsive.js create mode 100644 public/libs/bootstrap/css/bootstrap-responsive.css create mode 100644 public/libs/bootstrap/css/bootstrap-responsive.min.css create mode 100644 public/libs/bootstrap/css/bootstrap.css create mode 100644 public/libs/bootstrap/css/bootstrap.min.css create mode 100644 public/libs/bootstrap/img/glyphicons-halflings-white.png create mode 100644 public/libs/bootstrap/img/glyphicons-halflings.png create mode 100644 public/libs/bootstrap/js/bootstrap.js create mode 100644 public/libs/bootstrap/js/bootstrap.min.js create mode 100644 public/libs/code-prettify/lang-apollo.js create mode 100644 public/libs/code-prettify/lang-clj.js create mode 100644 public/libs/code-prettify/lang-css.js create mode 100644 public/libs/code-prettify/lang-go.js create mode 100644 public/libs/code-prettify/lang-hs.js create mode 100644 public/libs/code-prettify/lang-lisp.js create mode 100644 public/libs/code-prettify/lang-lua.js create mode 100644 public/libs/code-prettify/lang-ml.js create mode 100644 public/libs/code-prettify/lang-n.js create mode 100644 public/libs/code-prettify/lang-proto.js create mode 100644 public/libs/code-prettify/lang-scala.js create mode 100644 public/libs/code-prettify/lang-sql.js create mode 100644 public/libs/code-prettify/lang-tex.js create mode 100644 public/libs/code-prettify/lang-vb.js create mode 100644 public/libs/code-prettify/lang-vhdl.js create mode 100644 public/libs/code-prettify/lang-wiki.js create mode 100644 public/libs/code-prettify/lang-xq.js create mode 100644 public/libs/code-prettify/lang-yaml.js create mode 100644 public/libs/code-prettify/prettify.css create mode 100644 public/libs/code-prettify/prettify.js create mode 100644 public/libs/editor/editor.css create mode 100644 public/libs/editor/editor.js create mode 100644 public/libs/editor/ext.js create mode 100644 public/libs/editor/fonts/icomoon.dev.svg create mode 100644 public/libs/editor/fonts/icomoon.eot create mode 100644 public/libs/editor/fonts/icomoon.svg create mode 100644 public/libs/editor/fonts/icomoon.ttf create mode 100644 public/libs/editor/fonts/icomoon.woff create mode 100644 public/libs/font-awesome/css/font-awesome.css create mode 100644 public/libs/font-awesome/fonts/FontAwesome.otf create mode 100644 public/libs/font-awesome/fonts/fontawesome-webfont.eot create mode 100644 public/libs/font-awesome/fonts/fontawesome-webfont.svg create mode 100644 public/libs/font-awesome/fonts/fontawesome-webfont.ttf create mode 100644 public/libs/font-awesome/fonts/fontawesome-webfont.woff create mode 100644 public/libs/jquery-2.1.0.js create mode 100644 public/libs/jquery-ujs.js create mode 100644 public/libs/jquery.atwho.js create mode 100644 public/libs/jquery.caret.js create mode 100644 public/libs/lodash.compat.js create mode 100644 public/libs/markdownit.js create mode 100644 public/libs/qrcode.js create mode 100644 public/libs/webuploader/Uploader.swf create mode 100644 public/libs/webuploader/webuploader.css create mode 100644 public/libs/webuploader/webuploader.withoutimage.js create mode 100644 public/stylesheets/common.css create mode 100644 public/stylesheets/jquery.atwho.css create mode 100644 public/stylesheets/responsive.css create mode 100644 public/stylesheets/style.less create mode 100644 test/api/v1/message.test.js create mode 100644 test/api/v1/reply.test.js create mode 100644 test/api/v1/tools.test.js create mode 100644 test/api/v1/topic.test.js create mode 100644 test/api/v1/user.test.js create mode 100644 test/app.test.js create mode 100644 test/common/at.test.js create mode 100644 test/common/cache.test.js create mode 100644 test/common/mail.test.js create mode 100644 test/common/message.test.js create mode 100644 test/common/render_helper.test.js create mode 100644 test/common/store_local.test.js create mode 100644 test/common/tools.test.js create mode 100644 test/controllers/github.test.js create mode 100644 test/controllers/message.test.js create mode 100644 test/controllers/reply.test.js create mode 100644 test/controllers/rss.test.js create mode 100644 test/controllers/search.test.js create mode 100644 test/controllers/sign.test.js create mode 100644 test/controllers/site.test.js create mode 100644 test/controllers/static.test.js create mode 100644 test/controllers/topic.test.js create mode 100644 test/controllers/user.test.js create mode 100644 test/env.js create mode 100644 test/middlewares/conf.test.js create mode 100644 test/middlewares/limit.test.js create mode 100644 test/middlewares/proxy.test.js create mode 100644 test/models/user.test.js create mode 100644 test/proxy/message.test.js create mode 100644 test/proxy/reply.test.js create mode 100644 test/proxy/topic.test.js create mode 100644 test/proxy/user.test.js create mode 100644 test/support/support.js create mode 100644 views/_ads.html create mode 100644 views/_sponsors.html create mode 100644 views/editor_sidebar.html create mode 100644 views/index.html create mode 100644 views/layout.html create mode 100644 views/message/index.html create mode 100644 views/message/message.html create mode 100644 views/notify/notify.html create mode 100644 views/reply/edit.html create mode 100644 views/reply/reply.html create mode 100644 views/sidebar.html create mode 100644 views/sign/new_oauth.html create mode 100644 views/sign/no_github_email.html create mode 100644 views/sign/reset.html create mode 100644 views/sign/search_pass.html create mode 100644 views/sign/sidebar.html create mode 100644 views/sign/signin.html create mode 100644 views/sign/signup.html create mode 100644 views/static/about.html create mode 100644 views/static/api.html create mode 100644 views/static/faq.html create mode 100644 views/static/getstart.html create mode 100644 views/topic/_top_good.html create mode 100644 views/topic/abstract.html create mode 100644 views/topic/edit.html create mode 100644 views/topic/index.html create mode 100644 views/topic/list.html create mode 100644 views/topic/small.html create mode 100644 views/user/card.html create mode 100644 views/user/collect_topics.html create mode 100644 views/user/followers.html create mode 100644 views/user/followings.html create mode 100644 views/user/index.html create mode 100644 views/user/replies.html create mode 100644 views/user/setting.html create mode 100644 views/user/star.html create mode 100644 views/user/stars.html create mode 100644 views/user/top.html create mode 100644 views/user/top100.html create mode 100644 views/user/top100_user.html create mode 100644 views/user/topics.html create mode 100644 views/user/user.html create mode 100644 web_router.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..ab05ebd6ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +config.js +.cov +coverage +node_modules +.naeindex +coverage.html +.monitor + +*.min.*.js +*.min.*.css +assets.json + +# Ignore Mac OS desktop services store +.DS_Store + +# Ignore Windows desktop setting file +desktop.ini + +*.log + +.idea +public/upload/* + +*.sublime-project +*.sublime-workspace +*.swp diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000000..e21ccb39f1 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,44 @@ +{ + "predef": [ + "phantom", + "module", + "require", + "__dirname", + "process", + "console", + "it", + "describe", + "before", + "beforeEach", + "after", + "afterEach", + "ace", + "$" + ], + + "browser": true, + "node": true, + "es5": true, + "bitwise": true, + "curly": true, + "eqeqeq": true, + "forin": false, + "immed": true, + "latedef": true, + "newcap": true, + "noarg": true, + "noempty": true, + "nonew": true, + "plusplus": false, + "undef": true, + "strict": false, + "trailing": false, + "globalstrict": true, + "nonstandard": true, + "white": true, + "indent": 2, + "expr": true, + "multistr": true, + "onevar": false, + "unused": "vars" +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..64fe67e168 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +sudo: false + +language: node_js + +env: + - CXX=g++-4.8 + +node_js: + - '0.10' + - '0.12' + - 'iojs' + - '4' + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 + +services: + - mongodb + - redis + +before_install: + - $CXX --version + +script: make test-cov + +after_success: cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js + diff --git a/History.md b/History.md new file mode 100644 index 0000000000..918c8f4787 --- /dev/null +++ b/History.md @@ -0,0 +1,208 @@ +2.1.0 / 2015-09-15 +================== + +* 使用 oneapm 代替 newrelic + +2.0.1 / 2015-08-07 +================== + +* 去掉【收藏功能】 + +0.3.6 / 2013-11-22 +================== + + * fix #237 if topic not exists, do not modified it. + * Merge pull request #230 from JacksonTian/fix_null + * 修复给空值设置属性的错误 + * Merge pull request #224 from JacksonTian/config_ga + * 将Google tracker可配置化 + * Merge pull request #223 from jiyinyiyong/ga + * add Google Analytics + * Merge pull request #217 from leizongmin/master + * 编辑器进入全屏模式时,调整一下样式 + * hotfix sendAtMail + * fixed "TypeError: Cannot read property author_id of null" + * 使用七牛 gravatar.qiniudn.com 镜像 + * Merge pull request #212 from tjwudi/master + * Fix 'title' textarea layout problem. + * Merge pull request #211 from tjwudi/master + * Add OS regular files to .gitignore + * Merge pull request #209 from leizongmin/master + * 解决打开Topic时自动跳到输入框问题 + * Merge pull request #205 from jiyinyiyong/master + * Merge pull request #208 from leizongmin/master + * 帖子内容页面,增加表格样式 + * 发布帖子使用 EpicEditor 编辑器 + * xss白名单 增加thead标签 + * Merge pull request #204 from JacksonTian/assets_issue + * limit the length of message to 20 + * 兼容未启用压缩功能的情况 + * Merge pull request #193 from dead-horse/fix-block-count + * fix block count + * Merge pull request #190 from leizongmin/master + * 修正用户收藏的话题页面,页码链接不正确问题 + * Merge pull request #186 from phoenixlzx/master + * Fixed mongoose version + * Merge pull request #182 from JacksonTian/assets_mini + * 替换debug为mini + * Merge pull request #181 from JacksonTian/assets + * 用config.debug判断是否线上状态 + * Merge pull request #180 from JacksonTian/assets + * 升级data2xml + * 静态资源重构 + * Merge pull request #178 from JacksonTian/typo + * Node.JS => Node.js + * Merge pull request #177 from JacksonTian/style + * 文章页面的样式 + * Fix几个样式问题 + * fixed #175 stars max size + * fixed require package.json nae not support bug + * Merge pull request #174 from JacksonTian/style + * 去除用标签来制造空格的行为 + * 更新样式 + * Merge pull request #171 from jiyinyiyong/markdown-p + * limit image height + * limit pre-wrap inside p + * Merge pull request #165 from VitoLau/master + * 更新about faq页面结构 + * 调整about和faq页面 padding大小 + * Merge pull request #164 from jiyinyiyong/master + * fix: markdown-text use pre-wrap + * format indentations to 2 + * limit the with of message links to prevent line breaks + * 修复文字过长没有换行的问题 + +0.3.5 / 2013-05-30 +================== + + * Update logo based on the new official one (@finian) + * UI more flatter; use "white-space:pre" to show spaces (@jiyinyiyong) + * fixed #161 xss process after markdown transfer + * 修复reply2的逻辑;暂时屏蔽标签功能 + * use fixed-width font in reply + * a text align and a padding + * add padding to the read messages + * 点击回复数直接跳到最后一个回复 + * 支持html + * fixed #154 消息跳转没有直接跳转到回复 + * fixed #146 修复tag编辑bug + * 增加nae config + * 增加邮件提示内容 + * read file sync package.json + +0.3.4 / 2013-05-27 +================== + + * user markd instead showdown, use ace (@fengmk2) + * 使用加粗的边缘线; 过滤粉红色的边缘线; 加深 panel header 颜色; 去掉 scrollbar 定制 (@jiyinyiyong) + * 指定xss模块的配置信息,禁止HTML标签的style和class属性 (@lezongmin) + * shanzhai'd Github T3T (@jiyinyiyong) + * @jiyinyiyong 修改界面布局 fixed #139 + * 添加话题详情主要内容的行高 (@kerngven) + * 增加POST提交时间间隔限制 (@leizongmin) + * 中英文间用空格 + * 发帖页面优化 + * 文本框高度不要闪烁 + * use bootstrap 2; hide tags + * see the demo of new UI + * 搜索页面,如果回复时间过长,会产生断行的情况 + * unit test cases + * #132 Add https:// validate on user.js cnodejs/nodeclub#132 (@meteormatt) + * Add 0.10 for travis + * fixed #107 update user links + +0.3.3 / 2013-03-11 +================== + + * Merge pull request #126 from cnodejs/updateSignFlow + * 修复topic更新bug;修复@某人 bug + * reply2也可以定位到 + * 修复node 0.6 test cases + * 修复删除评论异常 + * 修复 exports.updateLastReply 没有callback的bug + * 管理员可以帮忙激活账号 + * Merge pull request #125 from JacksonTian/refine + * Fix http to https + * 重构注册和发帖以及发邮件的部分 + * Merge pull request #117 from JacksonTian/get_post + * 去除掉req.method的判断,分拆方法 + * Merge pull request #122 from JacksonTian/proxy + * 分离controller和数据操作业务逻辑 + * 改完下划线驼峰为小驼峰式风格 + * Merge pull request #116 from JacksonTian/codingstyle + * Coding style refine. + * Merge pull request #113 from JacksonTian/master + * 添加依赖服务状态图标 + * Merge pull request #112 from JacksonTian/refine + * 修正rewire.reset()导致的单元测试异常 + * Refine coding style + * Merge pull request #111 from JacksonTian/master + * Merge pull request #110 from JacksonTian/reset_history + * Update Authors + * 恢复History.md文件 + * Merge pull request #104 from ccding/master + * fix issue #27: lower case email address for gravatar + * Merge pull request #103 from ccding/master + * fix issue #92: email address with gmail label ("+" encode) + * fixed topic delete not post method security problem. + * empty author + * fixed author empty bug + * Merge pull request #99 from leizongmin/master + * 将Markdown中的H标题解析放到代码块解析后面 + * Merge pull request #96 from leizongmin/master + * 修正无法正确解析http://127.0.0.1这样的IP地址链接 + * fixed font + * fixed color style + * Merge pull request #87 from jiyinyiyong/rebased + * Merge pull request #91 from leizongmin/master + * 使用xss模块来过滤主题及回复内容 + * update to 0.3.2 + * Merge remote branch 'cnode/master' + * fix escape + * Merge pull request #89 from dead-horse/master + * fix test + * use in node-validator + * Merge remote branch 'cnode/master' + * support block code + * Merge pull request #88 from dead-horse/master + * fix + * change @me to markdown + * fix @ bug in topic content + * Merge pull request #86 from dead-horse/master + * not escape html in + * add preview + * remove tags in topics of home page + * some css + * 合并通知按钮 + * use escape replace of xss() + * fixed test cases + * Merge pull request #85 from dead-horse/master + * 过滤url允许绝对路径 + +0.3.2 / 2012-03-04 +================== + + * ensure IncomingForm.UPLOAD_DIR + * ensure upload image dir exists + * fixed csrf bug in mark message read + * remove customHost + * add .naeignore files + * * merge cnodeclub to nodeclub; * add more settings for custom site; * fixed upload.js not worked bug; + * Merge pull request #4 from dead-horse/master + * Merge pull request #11 from thebrecht/master + * 话题回复数纳入二级回复,样式调整 + * 支持table,邮件提醒 + * 加入亂數產生新密碼 + * fix style + * bugs fixed + * Merge pull request #3 from LeToNode/master + * Merge pull request #6 from ericzhang-cn/master + * markdown语法粗体应为两个星号,原描述有误 + * Merge pull request #2 from roymax/master + * change to async + * change to async + * Update README.md + * 修复`abc+label@gmail.com`格式的注册邮箱不能成功激活的问题 + * commit + * project init + * first commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..2d4d836963 --- /dev/null +++ b/Makefile @@ -0,0 +1,52 @@ +TESTS = $(shell find test -type f -name "*.test.js") +TEST_TIMEOUT = 5000 +MOCHA_REPORTER = spec +# NPM_REGISTRY = "--registry=http://registry.npm.taobao.org" +NPM_REGISTRY = "" + + +all: test + +install: + @npm install $(NPM_REGISTRY) + +pretest: + @if ! test -f config.js; then \ + cp config.default.js config.js; \ + fi + @if ! test -d public/upload; then \ + mkdir public/upload; \ + fi + +test: pretest + @NODE_ENV=test ./node_modules/mocha/bin/mocha \ + --reporter $(MOCHA_REPORTER) \ + -r should \ + -r test/env \ + --timeout $(TEST_TIMEOUT) \ + $(TESTS) + +test-cov cov: install pretest + @NODE_ENV=test node \ + node_modules/.bin/istanbul cover --preserve-comments \ + ./node_modules/.bin/_mocha \ + -- \ + -r should \ + -r test/env \ + --reporter $(MOCHA_REPORTER) \ + --timeout $(TEST_TIMEOUT) \ + $(TESTS) + +build: + @./node_modules/loader/bin/build views . + +run: + @node app.js + +start: install build + @NODE_ENV=production nohup ./node_modules/.bin/pm2 start app.js -i 0 --name "cnode" --max-memory-restart 400M >> cnode.log 2>&1 & + +restart: install build + @NODE_ENV=production nohup ./node_modules/.bin/pm2 restart "cnode" >> cnode.log 2>&1 & + +.PHONY: install test cov test-cov build run start restart diff --git a/README.md b/README.md new file mode 100644 index 0000000000..c200ca6716 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +Nodeclub += + +[![build status][travis-image]][travis-url] +[![Coverage Status][coverage-image]][coverage-url] +[![David deps][david-image]][david-url] +[![node version][node-image]][node-url] + +[travis-image]: https://img.shields.io/travis/cnodejs/nodeclub.svg?style=flat-square +[travis-url]: https://travis-ci.org/cnodejs/nodeclub +[coverage-image]: https://img.shields.io/coveralls/cnodejs/nodeclub.svg?style=flat-square +[coverage-url]: https://coveralls.io/r/cnodejs/nodeclub?branch=master +[david-image]: https://img.shields.io/david/cnodejs/nodeclub.svg?style=flat-square +[david-url]: https://david-dm.org/cnodejs/nodeclub +[node-image]: https://img.shields.io/badge/node.js-%3E=_0.10-green.svg?style=flat-square +[node-url]: http://nodejs.org/download/ + +## 介绍 + +Nodeclub 是使用 **Node.js** 和 **MongoDB** 开发的社区系统,界面优雅,功能丰富,小巧迅速, +已在Node.js 中文技术社区 [CNode(http://cnodejs.org)](http://cnodejs.org) 得到应用,但你完全可以用它搭建自己的社区。 + +## 安装部署 + +*不保证 Windows 系统的兼容性* + +线上跑的是 [io.js](https://iojs.org) v2.3.3,[MongoDB](https://www.mongodb.org) 是 v2.6,[Redis](http://redis.io) 是 v2.8.9。 + +``` +1. 安装 `Node.js/io.js[必须]` `MongoDB[必须]` `Redis[必须]` +2. 启动 MongoDB 和 Redis +3. `$ make install` 安装 Nodeclub 的依赖包 +4. `cp config.default.js config.js` 请根据需要修改配置文件 +5. `$ make test` 确保各项服务都正常 +6. `$ node app.js` +7. visit `http://localhost:3000` +8. done! +``` + +## 测试 + +跑测试 + +```bash +$ make test +``` + +跑覆盖率测试 + +```bash +$ make test-cov +``` + +## 贡献 + +有任何意见或建议都欢迎提 issue,或者直接提给 [@alsotang](https://github.com/alsotang) + +## License + +MIT diff --git a/api/v1/message.js b/api/v1/message.js new file mode 100644 index 0000000000..9cb19237a3 --- /dev/null +++ b/api/v1/message.js @@ -0,0 +1,93 @@ +var eventproxy = require('eventproxy'); +var Message = require('../../proxy').Message; +var at = require('../../common/at'); +var renderHelper = require('../../common/render_helper'); +var _ = require('lodash'); + +var index = function (req, res, next) { + var user_id = req.user._id; + var mdrender = req.query.mdrender === 'false' ? false : true; + var ep = new eventproxy(); + ep.fail(next); + + ep.all('has_read_messages', 'hasnot_read_messages', function (has_read_messages, hasnot_read_messages) { + res.send({ + data: { + has_read_messages: has_read_messages, + hasnot_read_messages: hasnot_read_messages + } + }); + }); + + ep.all('has_read', 'unread', function (has_read, unread) { + [has_read, unread].forEach(function (msgs, idx) { + var epfill = new eventproxy(); + epfill.fail(next); + epfill.after('message_ready', msgs.length, function (docs) { + docs = docs.filter(function (doc) { + return !doc.is_invalid; + }); + docs = docs.map(function (doc) { + doc.author = _.pick(doc.author, ['loginname', 'avatar_url']); + doc.topic = _.pick(doc.topic, ['id', 'author', 'title', 'last_reply_at']); + doc.reply = _.pick(doc.reply, ['id', 'content', 'ups', 'create_at']); + if (mdrender) { + doc.reply.content = renderHelper.markdown(at.linkUsers(doc.reply.content)); + } + doc = _.pick(doc, ['id', 'type', 'has_read', 'author', 'topic', 'reply']); + + return doc; + }); + ep.emit(idx === 0 ? 'has_read_messages' : 'hasnot_read_messages', docs); + }); + msgs.forEach(function (doc) { + Message.getMessageById(doc._id, epfill.group('message_ready')); + }); + }); + }); + + Message.getReadMessagesByUserId(user_id, ep.done('has_read')); + + Message.getUnreadMessageByUserId(user_id, ep.done('unread')); +}; + +exports.index = index; + +var markAll = function (req, res, next) { + var user_id = req.user._id; + var ep = new eventproxy(); + ep.fail(next); + Message.getUnreadMessageByUserId(user_id, ep.done('unread', function (docs) { + docs.forEach(function (doc) { + doc.has_read = true; + doc.save(); + }); + return docs; + })); + + ep.all('unread', function (unread) { + unread = unread.map(function (doc) { + doc = _.pick(doc, ['id']); + return doc; + }); + res.send({ + success: true, + marked_msgs: unread, + }); + }); +}; + +exports.markAll = markAll; + +var count = function (req, res, next) { + var userId = req.user.id; + + var ep = new eventproxy(); + ep.fail(next); + + Message.getMessagesCount(userId, ep.done(function (count) { + res.send({data: count}); + })); +}; + +exports.count = count; diff --git a/api/v1/middleware.js b/api/v1/middleware.js new file mode 100644 index 0000000000..40816e724c --- /dev/null +++ b/api/v1/middleware.js @@ -0,0 +1,26 @@ +var UserModel = require('../../models').User; +var eventproxy = require('eventproxy'); +var validator = require('validator'); + +var auth = function (req, res, next) { + var ep = new eventproxy(); + ep.fail(next); + + var accessToken = req.body.accesstoken || req.query.accesstoken; + accessToken = validator.trim(accessToken); + + UserModel.findOne({accessToken: accessToken}, ep.done(function (user) { + if (!user) { + res.status(403); + return res.send({error_msg: 'wrong accessToken'}); + } + if (user.is_block) { + return res.send({error_msg: 'your account is blocked'}); + } + req.user = user; + next(); + })); + +}; + +exports.auth = auth; diff --git a/api/v1/reply.js b/api/v1/reply.js new file mode 100644 index 0000000000..f3108c6007 --- /dev/null +++ b/api/v1/reply.js @@ -0,0 +1,115 @@ +var eventproxy = require('eventproxy'); +var validator = require('validator'); +var Topic = require('../../proxy').Topic; +var User = require('../../proxy').User; +var Reply = require('../../proxy').Reply; +var at = require('../../common/at'); +var message = require('../../common/message'); +var config = require('../../config'); + +var create = function (req, res, next) { + var topic_id = req.params.topic_id; + var content = req.body.content; + var reply_id = req.body.reply_id; + + var ep = new eventproxy(); + ep.fail(next); + + var str = validator.trim(content); + if (str === '') { + res.status(422); + res.send({error_msg: '回复内容不能为空!'}); + return; + } + + Topic.getTopic(topic_id, ep.done(function (topic) { + if (!topic) { + res.status(404); + res.send({error_msg: 'topic `' + topic_id + '` not found'}); + return; + } + if (topic.lock) { + res.status(403); + return res.send({error_msg: 'topic is locked'}); + } + ep.emit('topic', topic); + })); + + ep.all('topic', function (topic) { + User.getUserById(topic.author_id, ep.done('topic_author')); + }); + + ep.all('topic', 'topic_author', function (topic, topicAuthor) { + Reply.newAndSave(content, topic_id, req.user.id, reply_id, ep.done(function (reply) { + Topic.updateLastReply(topic_id, reply._id, ep.done(function () { + ep.emit('reply_saved', reply); + //发送at消息,并防止重复 at 作者 + var newContent = content.replace('@' + topicAuthor.loginname + ' ', ''); + at.sendMessageToMentionUsers(newContent, topic_id, req.user.id, reply._id); + })); + })); + + User.getUserById(req.user.id, ep.done(function (user) { + user.score += 5; + user.reply_count += 1; + user.save(); + ep.emit('score_saved'); + })); + }); + + ep.all('reply_saved', 'topic', function (reply, topic) { + if (topic.author_id.toString() !== req.user.id.toString()) { + message.sendReplyMessage(topic.author_id, req.user.id, topic._id, reply._id); + } + ep.emit('message_saved'); + }); + + ep.all('reply_saved', 'message_saved', 'score_saved', function (reply) { + res.send({ + success: true, + reply_id: reply._id, + }); + }); +}; + +exports.create = create; + +var ups = function (req, res, next) { + var replyId = req.params.reply_id; + var userId = req.user.id; + + Reply.getReplyById(replyId, function (err, reply) { + if (err) { + return next(err); + } + if (!reply) { + res.status(404); + return res.send({error_msg: 'reply `' + replyId + '` not found'}); + } + if (reply.author_id.equals(userId) && !config.debug) { + // 不能帮自己点赞 + res.send({ + error_msg: '呵呵,不能帮自己点赞。', + }); + } else { + var action; + reply.ups = reply.ups || []; + var upIndex = reply.ups.indexOf(userId); + if (upIndex === -1) { + reply.ups.push(userId); + action = 'up'; + } else { + reply.ups.splice(upIndex, 1); + action = 'down'; + } + reply.save(function () { + res.send({ + success: true, + action: action + }); + }); + } + }); +}; + +exports.ups = ups; diff --git a/api/v1/tools.js b/api/v1/tools.js new file mode 100644 index 0000000000..368bdb4bc8 --- /dev/null +++ b/api/v1/tools.js @@ -0,0 +1,14 @@ +var eventproxy = require('eventproxy'); + +var accesstoken = function (req, res, next) { + var ep = new eventproxy(); + ep.fail(next); + + res.send({ + success: true, + loginname: req.user.loginname, + avatar_url: req.user.avatar_url, + id: req.user.id, + }); +}; +exports.accesstoken = accesstoken; diff --git a/api/v1/topic.js b/api/v1/topic.js new file mode 100644 index 0000000000..96cddfdf7c --- /dev/null +++ b/api/v1/topic.js @@ -0,0 +1,222 @@ +var models = require('../../models'); +var TopicModel = models.Topic; +var TopicProxy = require('../../proxy').Topic; +var TopicCollect = require('../../proxy').TopicCollect; +var UserProxy = require('../../proxy').User; +var UserModel = models.User; +var config = require('../../config'); +var eventproxy = require('eventproxy'); +var _ = require('lodash'); +var at = require('../../common/at'); +var renderHelper = require('../../common/render_helper'); +var validator = require('validator'); + +var index = function (req, res, next) { + var page = parseInt(req.query.page, 10) || 1; + page = page > 0 ? page : 1; + var tab = req.query.tab || 'all'; + var limit = Number(req.query.limit) || config.list_topic_count; + var mdrender = req.query.mdrender === 'false' ? false : true; + + var query = {}; + if (tab && tab !== 'all') { + if (tab === 'good') { + query.good = true; + } else { + query.tab = tab; + } + } + query.deleted = false; + var options = { skip: (page - 1) * limit, limit: limit, sort: '-top -last_reply_at'}; + + var ep = new eventproxy(); + ep.fail(next); + + TopicModel.find(query, '', options, ep.done('topics')); + + ep.all('topics', function (topics) { + topics.forEach(function (topic) { + UserModel.findById(topic.author_id, ep.done(function (author) { + if (mdrender) { + topic.content = renderHelper.markdown(at.linkUsers(topic.content)); + } + topic.author = _.pick(author, ['loginname', 'avatar_url']); + ep.emit('author'); + })); + }); + + ep.after('author', topics.length, function () { + topics = topics.map(function (topic) { + return _.pick(topic, ['id', 'author_id', 'tab', 'content', 'title', 'last_reply_at', + 'good', 'top', 'reply_count', 'visit_count', 'create_at', 'author']); + }); + + res.send({data: topics}); + }); + }); +}; + +exports.index = index; + +var show = function (req, res, next) { + var topicId = req.params.id; + var mdrender = req.query.mdrender === 'false' ? false : true; + var ep = new eventproxy(); + + ep.fail(next); + + TopicProxy.getFullTopic(topicId, ep.done(function (msg, topic, author, replies) { + if (!topic) { + return res.send({error_msg: 'topic_id `' + topicId + '` is not exists.'}); + } + topic = _.pick(topic, ['id', 'author_id', 'tab', 'content', 'title', 'last_reply_at', + 'good', 'top', 'reply_count', 'visit_count', 'create_at', 'author']); + + if (mdrender) { + topic.content = renderHelper.markdown(at.linkUsers(topic.content)); + } + topic.author = _.pick(author, ['loginname', 'avatar_url']); + + topic.replies = replies.map(function (reply) { + if (mdrender) { + reply.content = renderHelper.markdown(at.linkUsers(reply.content)); + } + reply.author = _.pick(reply.author, ['loginname', 'avatar_url']); + reply = _.pick(reply, ['id', 'author', 'content', 'ups', 'create_at']); + return reply; + }); + res.send({data: topic}); + })); +}; + +exports.show = show; + +var create = function (req, res, next) { + var title = validator.trim(req.body.title); + var tab = validator.trim(req.body.tab); + var content = validator.trim(req.body.content); + + // 得到所有的 tab, e.g. ['ask', 'share', ..] + var allTabs = config.tabs.map(function (tPair) { + return tPair[0]; + }); + + // 验证 + var editError; + if (title === '') { + editError = '标题不能是空的。'; + } else if (title.length < 5 || title.length > 100) { + editError = '标题字数太多或太少。'; + } else if (!tab || allTabs.indexOf(tab) === -1) { + editError = '必须选择一个版块。'; + } else if (content === '') { + editError = '内容不可为空'; + } + // END 验证 + + if (editError) { + res.status(422); + return res.send({ + error_msg: editError, + }); + } + + TopicProxy.newAndSave(title, content, tab, req.user.id, function (err, topic) { + if (err) { + return next(err); + } + + var proxy = new eventproxy(); + proxy.fail(next); + + proxy.all('score_saved', function () { + res.send({ + success: true, + topic_id: topic.id, + }); + }); + UserProxy.getUserById(req.user.id, proxy.done(function (user) { + user.score += 5; + user.topic_count += 1; + user.save(); + req.user = user; + proxy.emit('score_saved'); + })); + + //发送at消息 + at.sendMessageToMentionUsers(content, topic.id, req.user.id); + }); +}; + +exports.create = create; + +exports.collect = function (req, res, next) { + var topic_id = req.body.topic_id; + TopicProxy.getTopic(topic_id, function (err, topic) { + if (err) { + return next(err); + } + if (!topic) { + return res.json({error_msg: '主题不存在'}); + } + + TopicCollect.getTopicCollect(req.user.id, topic._id, function (err, doc) { + if (err) { + return next(err); + } + if (doc) { + res.json({success: true}); + return; + } + + TopicCollect.newAndSave(req.user.id, topic._id, function (err) { + if (err) { + return next(err); + } + res.json({success: true}); + }); + UserProxy.getUserById(req.user.id, function (err, user) { + if (err) { + return next(err); + } + user.collect_topic_count += 1; + user.save(); + }); + + req.user.collect_topic_count += 1; + topic.collect_count += 1; + topic.save(); + }); + }); +}; + +exports.de_collect = function (req, res, next) { + var topic_id = req.body.topic_id; + TopicProxy.getTopic(topic_id, function (err, topic) { + if (err) { + return next(err); + } + if (!topic) { + return res.json({error_msg: '主题不存在'}); + } + TopicCollect.remove(req.user.id, topic._id, function (err) { + if (err) { + return next(err); + } + res.json({success: true}); + }); + + UserProxy.getUserById(req.user.id, function (err, user) { + if (err) { + return next(err); + } + user.collect_topic_count -= 1; + user.save(); + }); + + topic.collect_count -= 1; + topic.save(); + + req.user.collect_topic_count -= 1; + }); +}; diff --git a/api/v1/user.js b/api/v1/user.js new file mode 100644 index 0000000000..83e5e815e3 --- /dev/null +++ b/api/v1/user.js @@ -0,0 +1,57 @@ +var _ = require('lodash'); +var eventproxy = require('eventproxy'); +var UserProxy = require('../../proxy').User; +var TopicProxy = require('../../proxy').Topic; +var ReplyProxy = require('../../proxy').Reply; +var TopicCollect = require('../../proxy').TopicCollect; + +var show = function (req, res, next) { + var loginname = req.params.loginname; + var ep = new eventproxy(); + + ep.fail(next); + + UserProxy.getUserByLoginName(loginname, ep.done(function (user) { + if (!user) { + return res.send({error_msg: 'user `' + loginname + '` is not exists'}); + } + var query = {author_id: user._id}; + var opt = {limit: 5, sort: '-create_at'}; + TopicProxy.getTopicsByQuery(query, opt, ep.done('recent_topics')); + + ReplyProxy.getRepliesByAuthorId(user._id, {limit: 20, sort: '-create_at'}, + ep.done(function (replies) { + var topic_ids = []; + for (var i = 0; i < replies.length; i++) { + if (topic_ids.indexOf(replies[i].topic_id.toString()) < 0) { + topic_ids.push(replies[i].topic_id.toString()); + } + } + var query = {_id: {'$in': topic_ids}}; + var opt = {limit: 5, sort: '-create_at'}; + TopicProxy.getTopicsByQuery(query, opt, ep.done('recent_replies')); + })); + + ep.all('recent_topics', 'recent_replies', + function (recent_topics, recent_replies) { + + user = _.pick(user, ['loginname', 'avatar_url', 'githubUsername', + 'create_at', 'score']); + + user.recent_topics = recent_topics.map(function (topic) { + topic.author = _.pick(topic.author, ['loginname', 'avatar_url']); + topic = _.pick(topic, ['id', 'author', 'title', 'last_reply_at']); + return topic; + }); + user.recent_replies = recent_replies.map(function (topic) { + topic.author = _.pick(topic.author, ['loginname', 'avatar_url']); + topic = _.pick(topic, ['id', 'author', 'title', 'last_reply_at']); + return topic; + }); + + res.send({data: user}); + }); + })); +}; + +exports.show = show; diff --git a/api_router_v1.js b/api_router_v1.js new file mode 100644 index 0000000000..961fff5bc3 --- /dev/null +++ b/api_router_v1.js @@ -0,0 +1,36 @@ +var express = require('express'); +var topicController = require('./api/v1/topic'); +var userController = require('./api/v1/user'); +var toolsController = require('./api/v1/tools'); +var replyController = require('./api/v1/reply'); +var messageController = require('./api/v1/message'); +var middleware = require('./api/v1/middleware'); +var limit = require('./middlewares/limit'); +var config = require('./config'); + +var router = express.Router(); + + +// 主题 +router.get('/topics', topicController.index); +router.get('/topic/:id', topicController.show); +router.post('/topics', middleware.auth, limit.peruserperday('create_topic', config.create_post_per_day), topicController.create); +router.post('/topic/collect', middleware.auth, topicController.collect); // 关注某话题 +router.post('/topic/de_collect', middleware.auth, topicController.de_collect); // 取消关注某话题 + +// 用户 +router.get('/user/:loginname', userController.show); + +// accessToken 测试 +router.post('/accesstoken', middleware.auth, toolsController.accesstoken); + +// 评论 +router.post('/topic/:topic_id/replies', middleware.auth, limit.peruserperday('create_reply', config.create_reply_per_day), replyController.create); +router.post('/reply/:reply_id/ups', middleware.auth, replyController.ups); + +// 通知 +router.get('/messages', middleware.auth, messageController.index); +router.get('/message/count', middleware.auth, messageController.count); +router.post('/message/mark_all', middleware.auth, messageController.markAll); + +module.exports = router; diff --git a/app.js b/app.js new file mode 100644 index 0000000000..9fd4cddce4 --- /dev/null +++ b/app.js @@ -0,0 +1,175 @@ +/*! + * nodeclub - app.js + */ + +/** + * Module dependencies. + */ + +var config = require('./config'); + +if (!config.debug && config.oneapm_key) { + require('oneapm'); +} + +require('colors'); +var path = require('path'); +var Loader = require('loader'); +var express = require('express'); +var session = require('express-session'); +var passport = require('passport'); +require('./middlewares/mongoose_log'); // 打印 mongodb 查询日志 +require('./models'); +var GitHubStrategy = require('passport-github').Strategy; +var githubStrategyMiddleware = require('./middlewares/github_strategy'); +var webRouter = require('./web_router'); +var apiRouterV1 = require('./api_router_v1'); +var auth = require('./middlewares/auth'); +var errorPageMiddleware = require('./middlewares/error_page'); +var proxyMiddleware = require('./middlewares/proxy'); +var RedisStore = require('connect-redis')(session); +var _ = require('lodash'); +var csurf = require('csurf'); +var compress = require('compression'); +var bodyParser = require('body-parser'); +var busboy = require('connect-busboy'); +var errorhandler = require('errorhandler'); +var cors = require('cors'); +var requestLog = require('./middlewares/request_log'); +var renderMiddleware = require('./middlewares/render'); +var logger = require('./common/logger'); +var helmet = require('helmet'); + + +// 静态文件目录 +var staticDir = path.join(__dirname, 'public'); +// assets +var assets = {}; + +if (config.mini_assets) { + try { + assets = require('./assets.json'); + } catch (e) { + console.log('You must execute `make build` before start app when mini_assets is true.'); + throw e; + } +} + +var urlinfo = require('url').parse(config.host); +config.hostname = urlinfo.hostname || config.host; + +var app = express(); + +// configuration in all env +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'html'); +app.engine('html', require('ejs-mate')); +app.locals._layoutFile = 'layout.html'; +app.enable('trust proxy'); + +// Request logger。请求时间 +app.use(requestLog); + +if (config.debug) { + // 渲染时间 + app.use(renderMiddleware.render); +} + +// 静态资源 +app.use(Loader.less(__dirname)); +app.use('/public', express.static(staticDir)); +app.use('/agent', proxyMiddleware.proxy); + +// 通用的中间件 +app.use(require('response-time')()); +app.use(helmet.frameguard('sameorigin')); +app.use(bodyParser.json({limit: '1mb'})); +app.use(bodyParser.urlencoded({ extended: true, limit: '1mb' })); +app.use(require('method-override')()); +app.use(require('cookie-parser')(config.session_secret)); +app.use(compress()); +app.use(session({ + secret: config.session_secret, + store: new RedisStore({ + port: config.redis_port, + host: config.redis_host, + }), + resave: true, + saveUninitialized: true, +})); + +// oauth 中间件 +app.use(passport.initialize()); + +// github oauth +passport.serializeUser(function (user, done) { + done(null, user); +}); +passport.deserializeUser(function (user, done) { + done(null, user); +}); +passport.use(new GitHubStrategy(config.GITHUB_OAUTH, githubStrategyMiddleware)); + +// custom middleware +app.use(auth.authUser); +app.use(auth.blockUser()); + +if (!config.debug) { + app.use(function (req, res, next) { + if (req.path === '/api' || req.path.indexOf('/api') === -1) { + csurf()(req, res, next); + return; + } + next(); + }); + app.set('view cache', true); +} + +// for debug +// app.get('/err', function (req, res, next) { +// next(new Error('haha')) +// }); + +// set static, dynamic helpers +_.extend(app.locals, { + config: config, + Loader: Loader, + assets: assets +}); + +app.use(errorPageMiddleware.errorPage); +_.extend(app.locals, require('./common/render_helper')); +app.use(function (req, res, next) { + res.locals.csrf = req.csrfToken ? req.csrfToken() : ''; + next(); +}); + +app.use(busboy({ + limits: { + fileSize: 10 * 1024 * 1024 // 10MB + } +})); + +// routes +app.use('/api/v1', cors(), apiRouterV1); +app.use('/', webRouter); + +// error handler +if (config.debug) { + app.use(errorhandler()); +} else { + app.use(function (err, req, res, next) { + console.error('server 500 error:', err); + return res.status(500).send('500 status'); + }); +} + +app.listen(config.port, function () { + logger.log('NodeClub listening on port', config.port); + logger.log('God bless love....'); + logger.log('You can debug your app with http://' + config.hostname + ':' + config.port); + logger.log(''); +}); + + +module.exports = app; diff --git a/bin/fix_at_problem.js b/bin/fix_at_problem.js new file mode 100644 index 0000000000..a1beb0ad17 --- /dev/null +++ b/bin/fix_at_problem.js @@ -0,0 +1,17 @@ +// 一次性脚本 +var TopicModel = require('../models').Topic; + +TopicModel.find({content: /\[{2,}@/}).exec(function (err, topics) { + topics.forEach(function (topic) { + topic.content = fix(topic.content); + console.log(topic.id); + topic.save(); + }); +}); + +function fix(str) { + str = str.replace(/\[{1,}(\[@\w+)(\]\(.+?\))\2+/, function (match_text, $1, $2) { + return $1 + $2; + }); + return str; +} diff --git a/bin/generate_accesstoken.js b/bin/generate_accesstoken.js new file mode 100644 index 0000000000..fbe9780988 --- /dev/null +++ b/bin/generate_accesstoken.js @@ -0,0 +1,41 @@ +// 一次性脚本 +// 为所有老用户生成 accessToken + +var uuid = require('node-uuid'); +var mongoose = require('mongoose'); +var config = require('../config'); +var async = require('async'); +require('../models/user'); + +mongoose.connect(config.db, function (err) { + if (err) { + console.error('connect to %s error: ', config.db, err.message); + process.exit(1); + } +}); + +var UserModel = mongoose.model('User'); + +var hasRemain = true; +async.whilst( + function () { + return hasRemain; + }, + function (callback) { + UserModel.findOne({accessToken: {$exists: false}}, function (err, user) { + if (!user) { + hasRemain = false; + callback(); + return; + } + user.accessToken = uuid.v4(); + user.save(function () { + console.log(user.loginname + ' done!'); + callback(); + }); + }); + }, + function (err) { + mongoose.disconnect(); + }); + diff --git a/common/at.js b/common/at.js new file mode 100644 index 0000000000..8dbda554c9 --- /dev/null +++ b/common/at.js @@ -0,0 +1,111 @@ +/*! + * nodeclub - topic mention user controller. + * Copyright(c) 2012 fengmk2 + * Copyright(c) 2012 muyuan + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var User = require('../proxy').User; +var Message = require('./message'); +var EventProxy = require('eventproxy'); +var _ = require('lodash'); + +/** + * 从文本中提取出@username 标记的用户名数组 + * @param {String} text 文本内容 + * @return {Array} 用户名数组 + */ +var fetchUsers = function (text) { + if (!text) { + return []; + } + + var ignoreRegexs = [ + /```.+?```/g, // 去除单行的 ``` + /^```[\s\S]+?^```/gm, // ``` 里面的是 pre 标签内容 + /`[\s\S]+?`/g, // 同一行中,`some code` 中内容也不该被解析 + /^ .*/gm, // 4个空格也是 pre 标签,在这里 . 不会匹配换行 + /\b\S*?@[^\s]*?\..+?\b/g, // somebody@gmail.com 会被去除 + /\[@.+?\]\(\/.+?\)/g, // 已经被 link 的 username + ]; + + ignoreRegexs.forEach(function (ignore_regex) { + text = text.replace(ignore_regex, ''); + }); + + var results = text.match(/@[a-z0-9\-_]+\b/igm); + var names = []; + if (results) { + for (var i = 0, l = results.length; i < l; i++) { + var s = results[i]; + //remove leading char @ + s = s.slice(1); + names.push(s); + } + } + names = _.uniq(names); + return names; +}; +exports.fetchUsers = fetchUsers; + +/** + * 根据文本内容中读取用户,并发送消息给提到的用户 + * Callback: + * - err, 数据库异常 + * @param {String} text 文本内容 + * @param {String} topicId 主题ID + * @param {String} authorId 作者ID + * @param {String} reply_id 回复ID + * @param {Function} callback 回调函数 + */ +exports.sendMessageToMentionUsers = function (text, topicId, authorId, reply_id, callback) { + if (typeof reply_id === 'function') { + callback = reply_id; + reply_id = null; + } + callback = callback || _.noop; + + User.getUsersByNames(fetchUsers(text), function (err, users) { + if (err || !users) { + return callback(err); + } + var ep = new EventProxy(); + ep.fail(callback); + + users = users.filter(function (user) { + return !user._id.equals(authorId); + }); + + ep.after('sent', users.length, function () { + callback(); + }); + + users.forEach(function (user) { + Message.sendAtMessage(user._id, authorId, topicId, reply_id, ep.done('sent')); + }); + }); +}; + +/** + * 根据文本内容,替换为数据库中的数据 + * Callback: + * - err, 数据库异常 + * - text, 替换后的文本内容 + * @param {String} text 文本内容 + * @param {Function} callback 回调函数 + */ +exports.linkUsers = function (text, callback) { + var users = fetchUsers(text); + for (var i = 0, l = users.length; i < l; i++) { + var name = users[i]; + text = text.replace(new RegExp('@' + name + '\\b(?!\\])', 'g'), '[@' + name + '](/user/' + name + ')'); + } + if (!callback) { + return text; + } + return callback(null, text); +}; diff --git a/common/cache.js b/common/cache.js new file mode 100644 index 0000000000..e8fd75abaa --- /dev/null +++ b/common/cache.js @@ -0,0 +1,43 @@ +var redis = require('./redis'); +var _ = require('lodash'); +var logger = require('./logger'); + +var get = function (key, callback) { + var t = new Date(); + redis.get(key, function (err, data) { + if (err) { + return callback(err); + } + if (!data) { + return callback(); + } + data = JSON.parse(data); + var duration = (new Date() - t); + logger.debug('Cache', 'get', key, (duration + 'ms').green); + callback(null, data); + }); +}; + +exports.get = get; + +// time 参数可选,秒为单位 +var set = function (key, value, time, callback) { + var t = new Date(); + + if (typeof time === 'function') { + callback = time; + time = null; + } + callback = callback || _.noop; + value = JSON.stringify(value); + + if (!time) { + redis.set(key, value, callback); + } else { + redis.setex(key, time, value, callback); + } + var duration = (new Date() - t); + logger.debug("Cache", "set", key, (duration + 'ms').green); +}; + +exports.set = set; diff --git a/common/logger.js b/common/logger.js new file mode 100644 index 0000000000..f457c99c82 --- /dev/null +++ b/common/logger.js @@ -0,0 +1,62 @@ +var fs = require('fs'); +var config = require('../config'); + +if (!fs.existsSync("./log")) { + fs.mkdirSync("./log"); +} + +exports.log = function () { + writeLog('', 'info', arguments); +}; + +exports.info = function () { + writeLog(' ', 'info', arguments); +}; + +exports.debug = function () { + writeLog(" ", 'debug', arguments); +}; + +exports.warn = function () { + writeLog(" ", 'warn', arguments); +}; + +exports.error = function () { + writeLog(" ", 'error', arguments); +}; + +var env = process.env.NODE_ENV || "development"; +var consolePrint = config.debug && env !== 'test'; +var writeLog = function (prefix, logType, args) { + var filePrint = logType !== 'debug'; + + if (!filePrint && !consolePrint) { + return; + } + + var infos = Array.prototype.slice.call(args); + var logStr = infos.join(" "); + + switch (logType) { + case "debug": + logStr = logStr.gray; + break; + case 'warn': + logStr = logStr.yellow; + break; + case 'error': + logStr = logStr.red; + break; + } + + var line = prefix + logStr; + + if (filePrint) { + fs.appendFile('./log/' + env + '.log', line + "\n"); + } + if (consolePrint) { + console.log(line); + } +}; + + diff --git a/common/mail.js b/common/mail.js new file mode 100644 index 0000000000..6dde757506 --- /dev/null +++ b/common/mail.js @@ -0,0 +1,72 @@ +var mailer = require('nodemailer'); +var smtpTransport = require('nodemailer-smtp-transport'); +var config = require('../config'); +var util = require('util'); +var transporter = mailer.createTransport(smtpTransport(config.mail_opts)); +var SITE_ROOT_URL = 'http://' + config.host; + +/** + * Send an email + * @param {Object} data 邮件对象 + */ +var sendMail = function (data) { + if (config.debug) { + return; + } + // 遍历邮件数组,发送每一封邮件,如果有发送失败的,就再压入数组,同时触发mailEvent事件 + transporter.sendMail(data, function (err) { + if (err) { + // 写为日志 + console.log(err); + } + }); +}; +exports.sendMail = sendMail; + +/** + * 发送激活通知邮件 + * @param {String} who 接收人的邮件地址 + * @param {String} token 重置用的token字符串 + * @param {String} name 接收人的用户名 + */ +exports.sendActiveMail = function (who, token, name) { + var from = util.format('%s <%s>', config.name, config.mail_opts.auth.user); + var to = who; + var subject = config.name + '社区帐号激活'; + var html = '

您好:' + name + '

' + + '

我们收到您在' + config.name + '社区的注册信息,请点击下面的链接来激活帐户:

' + + '激活链接' + + '

若您没有在' + config.name + '社区填写过注册信息,说明有人滥用了您的电子邮箱,请删除此邮件,我们对给您造成的打扰感到抱歉。

' + + '

' + config.name + '社区 谨上。

'; + + exports.sendMail({ + from: from, + to: to, + subject: subject, + html: html + }); +}; + +/** + * 发送密码重置通知邮件 + * @param {String} who 接收人的邮件地址 + * @param {String} token 重置用的token字符串 + * @param {String} name 接收人的用户名 + */ +exports.sendResetPassMail = function (who, token, name) { + var from = util.format('%s <%s>', config.name, config.mail_opts.auth.user); + var to = who; + var subject = config.name + '社区密码重置'; + var html = '

您好:' + name + '

' + + '

我们收到您在' + config.name + '社区重置密码的请求,请在24小时内单击下面的链接来重置密码:

' + + '重置密码链接' + + '

若您没有在' + config.name + '社区填写过注册信息,说明有人滥用了您的电子邮箱,请删除此邮件,我们对给您造成的打扰感到抱歉。

' + + '

' + config.name + '社区 谨上。

'; + + exports.sendMail({ + from: from, + to: to, + subject: subject, + html: html + }); +}; diff --git a/common/message.js b/common/message.js new file mode 100644 index 0000000000..bba03e586e --- /dev/null +++ b/common/message.js @@ -0,0 +1,45 @@ +var models = require('../models'); +var eventproxy = require('eventproxy'); +var Message = models.Message; +var User = require('../proxy').User; +var push = require('../common/push'); +var messageProxy = require('../proxy/message'); +var _ = require('lodash'); + +exports.sendReplyMessage = function (master_id, author_id, topic_id, reply_id, callback) { + callback = callback || _.noop; + var ep = new eventproxy(); + ep.fail(callback); + + var message = new Message(); + message.type = 'reply'; + message.master_id = master_id; + message.author_id = author_id; + message.topic_id = topic_id; + message.reply_id = reply_id; + + message.save(ep.done('message_saved')); + ep.all('message_saved', function (msg) { + push.send(message.type, author_id, master_id, topic_id); + callback(null, msg); + }); +}; + +exports.sendAtMessage = function (master_id, author_id, topic_id, reply_id, callback) { + callback = callback || _.noop; + var ep = new eventproxy(); + ep.fail(callback); + + var message = new Message(); + message.type = 'at'; + message.master_id = master_id; + message.author_id = author_id; + message.topic_id = topic_id; + message.reply_id = reply_id; + + message.save(ep.done('message_saved')); + ep.all('message_saved', function (msg) { + push.send(message.type, author_id, master_id, topic_id); + callback(null, msg); + }); +}; diff --git a/common/push.js b/common/push.js new file mode 100644 index 0000000000..80c2f064b9 --- /dev/null +++ b/common/push.js @@ -0,0 +1,59 @@ +var User = require('../proxy/user'); +var Message = require('../proxy/message'); +var JPush = require("jpush-sdk"); +var eventproxy = require('eventproxy'); +var config = require('../config'); +var client = null; + +if (config.jpush && config.jpush.masterSecret !== 'YourSecretKeyyyyyyyyyyyyy') { + client = JPush.buildClient(config.jpush); +} + +/** + * 通过极光推送发生消息通知 + * @param {String} type 消息类型 + * @param {String} author_id 消息作者ID + * @param {String} master_id 被通知者ID + * @param {String} topic_id 相关主题ID + */ +exports.send = function (type, author_id, master_id, topic_id) { + if (client !== null) { + var ep = new eventproxy(); + User.getUserById(author_id, ep.done('author')); + Message.getMessagesCount(master_id, ep.done('count')); + ep.all('author', 'count', function (author, count) { + var msg = author.loginname + ' '; + var extras = { + topicId: topic_id + }; + switch (type) { + case 'at': + msg += '@了你'; + break; + case 'reply': + msg += '回复了你的主题'; + break; + default: + break; + } + client.push() + .setPlatform(JPush.ALL) + .setAudience(JPush.alias(master_id.toString())) + .setNotification(msg, + JPush.ios(msg, null, count, null, extras), + JPush.android(msg, null, null, extras) + ) + .setOptions(null, null, null, !config.debug) + .send(function (err, res) { + if (config.debug) { + if (err) { + console.log(err.message); + } else { + console.log('Sendno: ' + res.sendno); + console.log('Msg_id: ' + res.msg_id); + } + } + }); + }) + } +}; diff --git a/common/redis.js b/common/redis.js new file mode 100644 index 0000000000..07cb9cb98d --- /dev/null +++ b/common/redis.js @@ -0,0 +1,17 @@ +var config = require('../config'); +var Redis = require('ioredis'); + +var client = new Redis({ + port: config.redis_port, + host: config.redis_host, + db: config.redis_db, +}); + +client.on('error', function (err) { + if (err) { + console.error('connect to redis error, check your redis config', err); + process.exit(1); + } +}) + +exports = module.exports = client; diff --git a/common/render_helper.js b/common/render_helper.js new file mode 100644 index 0000000000..460520b585 --- /dev/null +++ b/common/render_helper.js @@ -0,0 +1,98 @@ +/*! + * nodeclub - common/render_helpers.js + * Copyright(c) 2013 fengmk2 + * MIT Licensed + */ + +"use strict"; + +/** + * Module dependencies. + */ + +var MarkdownIt = require('markdown-it'); +var _ = require('lodash'); +var config = require('../config'); +var validator = require('validator'); +var multiline = require('multiline'); +var jsxss = require('xss'); + +// Set default options +var md = new MarkdownIt(); + +md.set({ + html: true, // Enable HTML tags in source + xhtmlOut: false, // Use '/' to close single tags (
) + breaks: false, // Convert '\n' in paragraphs into
+ linkify: true, // Autoconvert URL-like text to links + typographer: true, // Enable smartypants and other sweet transforms +}); + +md.renderer.rules.fence = function (tokens, idx) { + var token = tokens[idx]; + var language = token.params && ('language-' + token.params) || ''; + language = validator.escape(language); + + return '
'
+    + '' + validator.escape(token.content) + ''
+    + '
'; +}; + +md.renderer.rules.code_block = function (tokens, idx /*, options*/) { + var token = tokens[idx]; + var language = token.params && ('language-' + token.params) || ''; + language = validator.escape(language); + + return '
'
+    + '' + validator.escape(token.content) + ''
+    + '
'; +}; + +md.renderer.rules.code_inline = function (tokens, idx /*, options*/) { + return '' + validator.escape(tokens[idx].content) + ''; +}; + +var myxss = new jsxss.FilterXSS({ + onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) { + // 让 prettyprint 可以工作 + if (tag === 'pre' && name === 'class') { + return name + '="' + jsxss.escapeAttrValue(value) + '"'; + } + } +}); + +exports.markdown = function (text) { + return '
' + myxss.process(md.render(text || '')) + '
'; +}; + +exports.multiline = multiline; + +exports.escapeSignature = function (signature) { + return signature.split('\n').map(function (p) { + return _.escape(p); + }).join('
'); +}; + +exports.staticFile = function (filePath) { + if (filePath.indexOf('http') === 0 || filePath.indexOf('//') === 0) { + return filePath; + } + return config.site_static_host + filePath; +}; + +exports.tabName = function (tab) { + var pair = _.find(config.tabs, function (pair) { + return pair[0] === tab; + }); + if (pair) { + return pair[1]; + } +}; + +exports.proxy = function (url) { + return url; + // 当 google 和 github 封锁严重时,则需要通过服务器代理访问它们的静态资源 + // return '/agent?url=' + encodeURIComponent(url); +}; + +exports._ = _; diff --git a/common/store.js b/common/store.js new file mode 100644 index 0000000000..c29ed81753 --- /dev/null +++ b/common/store.js @@ -0,0 +1,4 @@ +var qn = require('./store_qn'); +var local = require('./store_local'); + +module.exports = qn || local; diff --git a/common/store_local.js b/common/store_local.js new file mode 100644 index 0000000000..10bbd6e407 --- /dev/null +++ b/common/store_local.js @@ -0,0 +1,24 @@ +var config = require('../config'); +var utility = require('utility'); +var path = require('path'); +var fs = require('fs'); + +exports.upload = function (file, options, callback) { + var filename = options.filename; + + var newFilename = utility.md5(filename + String((new Date()).getTime())) + + path.extname(filename); + + var upload_path = config.upload.path; + var base_url = config.upload.url; + var filePath = path.join(upload_path, newFilename); + var fileUrl = base_url + newFilename; + + file.on('end', function () { + callback(null, { + url: fileUrl + }); + }); + + file.pipe(fs.createWriteStream(filePath)); +}; diff --git a/common/store_qn.js b/common/store_qn.js new file mode 100644 index 0000000000..0d3f73678e --- /dev/null +++ b/common/store_qn.js @@ -0,0 +1,10 @@ +var qn = require('qn'); +var config = require('../config'); + +//7牛 client +var qnClient = null; +if (config.qn_access && config.qn_access.secretKey !== 'your secret key') { + qnClient = qn.create(config.qn_access); +} + +module.exports = qnClient; diff --git a/common/tools.js b/common/tools.js new file mode 100644 index 0000000000..d047c393b9 --- /dev/null +++ b/common/tools.js @@ -0,0 +1,28 @@ +var bcrypt = require('bcryptjs'); +var moment = require('moment'); + +moment.locale('zh-cn'); // 使用中文 + +// 格式化时间 +exports.formatDate = function (date, friendly) { + date = moment(date); + + if (friendly) { + return date.fromNow(); + } else { + return date.format('YYYY-MM-DD HH:mm'); + } + +}; + +exports.validateId = function (str) { + return (/^[a-zA-Z0-9\-_]+$/i).test(str); +}; + +exports.bhash = function (str, callback) { + bcrypt.hash(str, 10, callback); +}; + +exports.bcompare = function (str, hash, callback) { + bcrypt.compare(str, hash, callback); +}; diff --git a/config.default.js b/config.default.js new file mode 100644 index 0000000000..4b2fad4ac7 --- /dev/null +++ b/config.default.js @@ -0,0 +1,136 @@ +/** + * config + */ + +var path = require('path'); + +var config = { + // debug 为 true 时,用于本地调试 + debug: true, + + get mini_assets() { return !this.debug; }, // 是否启用静态文件的合并压缩,详见视图中的Loader + + name: 'Nodeclub', // 社区名字 + description: 'CNode:Node.js专业中文社区', // 社区的描述 + keywords: 'nodejs, node, express, connect, socket.io', + + // 添加到 html head 中的信息 + site_headers: [ + '' + ], + site_logo: '/public/images/cnodejs_light.svg', // default is `name` + site_icon: '/public/images/cnode_icon_32.png', // 默认没有 favicon, 这里填写网址 + // 右上角的导航区 + site_navs: [ + // 格式 [ path, title, [target=''] ] + [ '/about', '关于' ] + ], + // cdn host,如 http://cnodejs.qiniudn.com + site_static_host: '', // 静态文件存储域名 + // 社区的域名 + host: 'localhost', + // 默认的Google tracker ID,自有站点请修改,申请地址:http://www.google.com/analytics/ + google_tracker_id: '', + // 默认的cnzz tracker ID,自有站点请修改 + cnzz_tracker_id: '', + + // mongodb 配置 + db: 'mongodb://127.0.0.1/node_club_dev', + + // redis 配置,默认是本地 + redis_host: '127.0.0.1', + redis_port: 6379, + redis_db: 0, + + session_secret: 'node_club_secret', // 务必修改 + auth_cookie_name: 'node_club', + + // 程序运行的端口 + port: 3000, + + // 话题列表显示的话题数量 + list_topic_count: 20, + + // RSS配置 + rss: { + title: 'CNode:Node.js专业中文社区', + link: 'http://cnodejs.org', + language: 'zh-cn', + description: 'CNode:Node.js专业中文社区', + //最多获取的RSS Item数量 + max_rss_items: 50 + }, + + // 邮箱配置 + mail_opts: { + host: 'smtp.126.com', + port: 25, + auth: { + user: 'club@126.com', + pass: 'club' + } + }, + + //weibo app key + weibo_key: 10000000, + weibo_id: 'your_weibo_id', + + // admin 可删除话题,编辑标签,设某人为达人 + admins: { user_login_name: true }, + + // github 登陆的配置 + GITHUB_OAUTH: { + clientID: 'your GITHUB_CLIENT_ID', + clientSecret: 'your GITHUB_CLIENT_SECRET', + callbackURL: 'http://cnodejs.org/auth/github/callback' + }, + // 是否允许直接注册(否则只能走 github 的方式) + allow_sign_up: true, + + // oneapm 是个用来监控网站性能的服务 + oneapm_key: '', + + // 下面两个配置都是文件上传的配置 + + // 7牛的access信息,用于文件上传 + qn_access: { + accessKey: 'your access key', + secretKey: 'your secret key', + bucket: 'your bucket name', + domain: 'http://your qiniu domain', + // 如果vps在国外,请使用 http://up.qiniug.com/ ,这是七牛的国际节点 + // 如果在国内,此项请留空 + uploadURL: 'http://xxxxxxxx', + }, + + // 文件上传配置 + // 注:如果填写 qn_access,则会上传到 7牛,以下配置无效 + upload: { + path: path.join(__dirname, 'public/upload/'), + url: '/public/upload/' + }, + + // 版块 + tabs: [ + ['share', '分享'], + ['ask', '问答'], + ['job', '招聘'], + ], + + // 极光推送 + jpush: { + appKey: 'YourAccessKeyyyyyyyyyyyy', + masterSecret: 'YourSecretKeyyyyyyyyyyyyy', + isDebug: false, + }, + + create_post_per_day: 1000, // 每个用户一天可以发的主题数 + create_reply_per_day: 1000, // 每个用户一天可以发的评论数 + visit_per_day: 1000, // 每个 ip 每天能访问的次数 +}; + +if (process.env.NODE_ENV === 'test') { + config.db = 'mongodb://127.0.0.1/node_club_test'; +} + +module.exports = config; diff --git a/controllers/github.js b/controllers/github.js new file mode 100644 index 0000000000..0c7d70fc60 --- /dev/null +++ b/controllers/github.js @@ -0,0 +1,118 @@ +var Models = require('../models'); +var User = Models.User; +var authMiddleWare = require('../middlewares/auth'); +var tools = require('../common/tools'); +var eventproxy = require('eventproxy'); +var uuid = require('node-uuid'); +var validator = require('validator'); + +exports.callback = function (req, res, next) { + var profile = req.user; + User.findOne({githubId: profile.id}, function (err, user) { + if (err) { + return next(err); + } + // 当用户已经是 cnode 用户时,通过 github 登陆将会更新他的资料 + if (user) { + user.githubUsername = profile.username; + user.githubId = profile.id; + user.githubAccessToken = profile.accessToken; + // user.loginname = profile.username; + user.avatar = profile._json.avatar_url; + if (profile.emails[0].value) { + user.email = profile.emails[0].value; + } + + user.save(function (err) { + if (err) { + return next(err); + } + authMiddleWare.gen_session(user, res); + return res.redirect('/'); + }); + } else { + // 如果用户还未存在,则建立新用户 + req.session.profile = profile; + return res.redirect('/auth/github/new'); + } + }); +}; + +exports.new = function (req, res, next) { + res.render('sign/new_oauth', {actionPath: '/auth/github/create'}); +}; + +exports.create = function (req, res, next) { + var profile = req.session.profile; + var isnew = req.body.isnew; + var loginname = validator.trim(req.body.name).toLowerCase(); + var password = validator.trim(req.body.pass); + var ep = new eventproxy(); + ep.fail(next); + + if (!profile) { + return res.redirect('/signin'); + } + delete req.session.profile; + if (isnew) { // 注册新账号 + var user = new User({ + loginname: profile.username, + pass: profile.accessToken, + email: profile.emails[0].value, + avatar: profile._json.avatar_url, + githubId: profile.id, + githubUsername: profile.username, + githubAccessToken: profile.accessToken, + active: true, + accessToken: uuid.v4(), + }); + user.save(function (err) { + if (err) { + // 根据 err.err 的错误信息决定如何回应用户,这个地方写得很难看 + if (err.message.indexOf('duplicate key error') !== -1) { + if (err.message.indexOf('email') !== -1) { + return res.status(500) + .render('sign/no_github_email'); + } + if (err.message.indexOf('loginname') !== -1) { + return res.status(500) + .send('您 GitHub 账号的用户名与之前在 CNodejs 注册的用户名重复了'); + } + } + return next(err); + // END 根据 err.err 的错误信息决定如何回应用户,这个地方写得很难看 + } + authMiddleWare.gen_session(user, res); + res.redirect('/'); + }); + } else { // 关联老账号 + ep.on('login_error', function (login_error) { + res.status(403); + res.render('sign/signin', { error: '账号名或密码错误。' }); + }); + User.findOne({loginname: loginname}, + ep.done(function (user) { + if (!user) { + return ep.emit('login_error'); + } + tools.bcompare(password, user.pass, ep.done(function (bool) { + if (!bool) { + return ep.emit('login_error'); + } + user.githubUsername = profile.username; + user.githubId = profile.id; + // user.loginname = profile.username; + user.avatar = profile._json.avatar_url; + user.githubAccessToken = profile.accessToken; + + user.save(function (err) { + if (err) { + return next(err); + } + authMiddleWare.gen_session(user, res); + res.redirect('/'); + }); + })); + })); + } +}; diff --git a/controllers/message.js b/controllers/message.js new file mode 100644 index 0000000000..ffdaa111e8 --- /dev/null +++ b/controllers/message.js @@ -0,0 +1,33 @@ +var Message = require('../proxy').Message; +var eventproxy = require('eventproxy'); + +exports.index = function (req, res, next) { + var user_id = req.session.user._id; + var ep = new eventproxy(); + ep.fail(next); + + ep.all('has_read_messages', 'hasnot_read_messages', function (has_read_messages, hasnot_read_messages) { + res.render('message/index', {has_read_messages: has_read_messages, hasnot_read_messages: hasnot_read_messages}); + }); + + ep.all('has_read', 'unread', function (has_read, unread) { + [has_read, unread].forEach(function (msgs, idx) { + var epfill = new eventproxy(); + epfill.fail(next); + epfill.after('message_ready', msgs.length, function (docs) { + docs = docs.filter(function (doc) { + return !doc.is_invalid; + }); + ep.emit(idx === 0 ? 'has_read_messages' : 'hasnot_read_messages', docs); + }); + msgs.forEach(function (doc) { + Message.getMessageRelations(doc, epfill.group('message_ready')); + }); + }); + + Message.updateMessagesToRead(user_id, unread); + }); + + Message.getReadMessagesByUserId(user_id, ep.done('has_read')); + Message.getUnreadMessageByUserId(user_id, ep.done('unread')); +}; diff --git a/controllers/reply.js b/controllers/reply.js new file mode 100644 index 0000000000..f7c965d20c --- /dev/null +++ b/controllers/reply.js @@ -0,0 +1,191 @@ +var validator = require('validator'); +var _ = require('lodash'); +var at = require('../common/at'); +var message = require('../common/message'); +var EventProxy = require('eventproxy'); +var User = require('../proxy').User; +var Topic = require('../proxy').Topic; +var Reply = require('../proxy').Reply; +var config = require('../config'); + +/** + * 添加回复 + */ +exports.add = function (req, res, next) { + var content = req.body.r_content; + var topic_id = req.params.topic_id; + var reply_id = req.body.reply_id; + + var str = validator.trim(content); + if (str === '') { + return res.renderError('回复内容不能为空!', 422); + } + + var ep = EventProxy.create(); + ep.fail(next); + + Topic.getTopic(topic_id, ep.doneLater(function (topic) { + if (!topic) { + ep.unbind(); + // just 404 page + return next(); + } + + if (topic.lock) { + return res.status(403).send('此主题已锁定。'); + } + ep.emit('topic', topic); + })); + + ep.all('topic', function (topic) { + User.getUserById(topic.author_id, ep.done('topic_author')); + }); + + ep.all('topic', 'topic_author', function (topic, topicAuthor) { + Reply.newAndSave(content, topic_id, req.session.user._id, reply_id, ep.done(function (reply) { + Topic.updateLastReply(topic_id, reply._id, ep.done(function () { + ep.emit('reply_saved', reply); + //发送at消息,并防止重复 at 作者 + var newContent = content.replace('@' + topicAuthor.loginname + ' ', ''); + at.sendMessageToMentionUsers(newContent, topic_id, req.session.user._id, reply._id); + })); + })); + + User.getUserById(req.session.user._id, ep.done(function (user) { + user.score += 5; + user.reply_count += 1; + user.save(); + req.session.user = user; + ep.emit('score_saved'); + })); + }); + + ep.all('reply_saved', 'topic', function (reply, topic) { + if (topic.author_id.toString() !== req.session.user._id.toString()) { + message.sendReplyMessage(topic.author_id, req.session.user._id, topic._id, reply._id); + } + ep.emit('message_saved'); + }); + + ep.all('reply_saved', 'message_saved', 'score_saved', function (reply) { + res.redirect('/topic/' + topic_id + '#' + reply._id); + }); +}; + +/** + * 删除回复信息 + */ +exports.delete = function (req, res, next) { + var reply_id = req.body.reply_id; + Reply.getReplyById(reply_id, function (err, reply) { + if (err) { + return next(err); + } + + if (!reply) { + res.status(422); + res.json({status: 'no reply ' + reply_id + ' exists'}); + return; + } + if (reply.author_id.toString() === req.session.user._id.toString() || req.session.user.is_admin) { + reply.deleted = true; + reply.save(); + res.json({status: 'success'}); + + if (!reply.reply_id) { + reply.author.score -= 5; + reply.author.reply_count -= 1; + reply.author.save(); + } + } else { + res.json({status: 'failed'}); + return; + } + + Topic.reduceCount(reply.topic_id, _.noop); + }); +}; +/* + 打开回复编辑器 + */ +exports.showEdit = function (req, res, next) { + var reply_id = req.params.reply_id; + + Reply.getReplyById(reply_id, function (err, reply) { + if (!reply) { + return res.render404('此回复不存在或已被删除。'); + } + if (req.session.user._id.equals(reply.author_id) || req.session.user.is_admin) { + res.render('reply/edit', { + reply_id: reply._id, + content: reply.content + }); + } else { + return res.renderError('对不起,你不能编辑此回复。', 403); + } + }); +}; +/* + 提交编辑回复 + */ +exports.update = function (req, res, next) { + var reply_id = req.params.reply_id; + var content = req.body.t_content; + + Reply.getReplyById(reply_id, function (err, reply) { + if (!reply) { + return res.render404('此回复不存在或已被删除。'); + } + + if (String(reply.author_id) === req.session.user._id.toString() || req.session.user.is_admin) { + + if (content.trim().length > 0) { + reply.content = content; + reply.save(function (err) { + if (err) { + return next(err); + } + res.redirect('/topic/' + reply.topic_id + '#' + reply._id); + }); + } else { + return res.renderError('回复的字数太少。', 400); + } + } else { + return res.renderError('对不起,你不能编辑此回复。', 403); + } + }); +}; + +exports.up = function (req, res, next) { + var replyId = req.params.reply_id; + var userId = req.session.user._id; + Reply.getReplyById(replyId, function (err, reply) { + if (err) { + return next(err); + } + if (reply.author_id.equals(userId) && !config.debug) { + // 不能帮自己点赞 + res.send({ + success: false, + message: '呵呵,不能帮自己点赞。', + }); + } else { + var action; + reply.ups = reply.ups || []; + var upIndex = reply.ups.indexOf(userId); + if (upIndex === -1) { + reply.ups.push(userId); + action = 'up'; + } else { + reply.ups.splice(upIndex, 1); + action = 'down'; + } + reply.save(function () { + res.send({ + success: true, + action: action + }); + }); + } + }); +}; diff --git a/controllers/rss.js b/controllers/rss.js new file mode 100644 index 0000000000..ab105582ab --- /dev/null +++ b/controllers/rss.js @@ -0,0 +1,56 @@ +var config = require('../config'); +var convert = require('data2xml')(); +var Topic = require('../proxy').Topic; +var cache = require('../common/cache'); +var renderHelper = require('../common/render_helper'); +var eventproxy = require('eventproxy'); + +exports.index = function (req, res, next) { + if (!config.rss) { + res.statusCode = 404; + return res.send('Please set `rss` in config.js'); + } + res.contentType('application/xml'); + + var ep = new eventproxy(); + ep.fail(next); + + cache.get('rss', ep.done(function (rss) { + if (!config.debug && rss) { + res.send(rss); + } else { + var opt = { limit: config.rss.max_rss_items, sort: '-create_at'}; + Topic.getTopicsByQuery({}, opt, function (err, topics) { + if (err) { + return next(err); + } + var rss_obj = { + _attr: { version: '2.0' }, + channel: { + title: config.rss.title, + link: config.rss.link, + language: config.rss.language, + description: config.rss.description, + item: [] + } + }; + + topics.forEach(function (topic) { + rss_obj.channel.item.push({ + title: topic.title, + link: config.rss.link + '/topic/' + topic._id, + guid: config.rss.link + '/topic/' + topic._id, + description: renderHelper.markdown(topic.content), + author: topic.author.loginname, + pubDate: topic.create_at.toUTCString() + }); + }); + + var rssContent = convert('rss', rss_obj); + + cache.set('rss', rssContent, 60 * 5); // 五分钟 + res.send(rssContent); + }); + } + })); +}; diff --git a/controllers/search.js b/controllers/search.js new file mode 100644 index 0000000000..d41c378208 --- /dev/null +++ b/controllers/search.js @@ -0,0 +1,5 @@ +exports.index = function (req, res, next) { + var q = req.query.q; + q = encodeURIComponent(q); + res.redirect('https://www.google.com.hk/#hl=zh-CN&q=site:cnodejs.org+' + q); +}; diff --git a/controllers/sign.js b/controllers/sign.js new file mode 100644 index 0000000000..4aef3dab89 --- /dev/null +++ b/controllers/sign.js @@ -0,0 +1,291 @@ +var validator = require('validator'); +var eventproxy = require('eventproxy'); +var config = require('../config'); +var User = require('../proxy').User; +var mail = require('../common/mail'); +var tools = require('../common/tools'); +var utility = require('utility'); +var authMiddleWare = require('../middlewares/auth'); +var uuid = require('node-uuid'); + +//sign up +exports.showSignup = function (req, res) { + res.render('sign/signup'); +}; + +exports.signup = function (req, res, next) { + var loginname = validator.trim(req.body.loginname).toLowerCase(); + var email = validator.trim(req.body.email).toLowerCase(); + var pass = validator.trim(req.body.pass); + var rePass = validator.trim(req.body.re_pass); + + var ep = new eventproxy(); + ep.fail(next); + ep.on('prop_err', function (msg) { + res.status(422); + res.render('sign/signup', {error: msg, loginname: loginname, email: email}); + }); + + // 验证信息的正确性 + if ([loginname, pass, rePass, email].some(function (item) { return item === ''; })) { + ep.emit('prop_err', '信息不完整。'); + return; + } + if (loginname.length < 5) { + ep.emit('prop_err', '用户名至少需要5个字符。'); + return; + } + if (!tools.validateId(loginname)) { + return ep.emit('prop_err', '用户名不合法。'); + } + if (!validator.isEmail(email)) { + return ep.emit('prop_err', '邮箱不合法。'); + } + if (pass !== rePass) { + return ep.emit('prop_err', '两次密码输入不一致。'); + } + // END 验证信息的正确性 + + + User.getUsersByQuery({'$or': [ + {'loginname': loginname}, + {'email': email} + ]}, {}, function (err, users) { + if (err) { + return next(err); + } + if (users.length > 0) { + ep.emit('prop_err', '用户名或邮箱已被使用。'); + return; + } + + tools.bhash(pass, ep.done(function (passhash) { + // create gravatar + var avatarUrl = User.makeGravatar(email); + User.newAndSave(loginname, loginname, passhash, email, avatarUrl, false, function (err) { + if (err) { + return next(err); + } + // 发送激活邮件 + mail.sendActiveMail(email, utility.md5(email + passhash + config.session_secret), loginname); + res.render('sign/signup', { + success: '欢迎加入 ' + config.name + '!我们已给您的注册邮箱发送了一封邮件,请点击里面的链接来激活您的帐号。' + }); + }); + + })); + }); +}; + +/** + * Show user login page. + * + * @param {HttpRequest} req + * @param {HttpResponse} res + */ +exports.showLogin = function (req, res) { + req.session._loginReferer = req.headers.referer; + res.render('sign/signin'); +}; + +/** + * define some page when login just jump to the home page + * @type {Array} + */ +var notJump = [ + '/active_account', //active page + '/reset_pass', //reset password page, avoid to reset twice + '/signup', //regist page + '/search_pass' //serch pass page +]; + +/** + * Handle user login. + * + * @param {HttpRequest} req + * @param {HttpResponse} res + * @param {Function} next + */ +exports.login = function (req, res, next) { + var loginname = validator.trim(req.body.name).toLowerCase(); + var pass = validator.trim(req.body.pass); + var ep = new eventproxy(); + + ep.fail(next); + + if (!loginname || !pass) { + res.status(422); + return res.render('sign/signin', { error: '信息不完整。' }); + } + + var getUser; + if (loginname.indexOf('@') !== -1) { + getUser = User.getUserByMail; + } else { + getUser = User.getUserByLoginName; + } + + ep.on('login_error', function (login_error) { + res.status(403); + res.render('sign/signin', { error: '用户名或密码错误' }); + }); + + getUser(loginname, function (err, user) { + if (err) { + return next(err); + } + if (!user) { + return ep.emit('login_error'); + } + var passhash = user.pass; + tools.bcompare(pass, passhash, ep.done(function (bool) { + if (!bool) { + return ep.emit('login_error'); + } + if (!user.active) { + // 重新发送激活邮件 + mail.sendActiveMail(user.email, utility.md5(user.email + passhash + config.session_secret), user.loginname); + res.status(403); + return res.render('sign/signin', { error: '此帐号还没有被激活,激活链接已发送到 ' + user.email + ' 邮箱,请查收。' }); + } + // store session cookie + authMiddleWare.gen_session(user, res); + //check at some page just jump to home page + var refer = req.session._loginReferer || '/'; + for (var i = 0, len = notJump.length; i !== len; ++i) { + if (refer.indexOf(notJump[i]) >= 0) { + refer = '/'; + break; + } + } + res.redirect(refer); + })); + }); +}; + +// sign out +exports.signout = function (req, res, next) { + req.session.destroy(); + res.clearCookie(config.auth_cookie_name, { path: '/' }); + res.redirect('/'); +}; + +exports.activeAccount = function (req, res, next) { + var key = validator.trim(req.query.key); + var name = validator.trim(req.query.name); + + User.getUserByLoginName(name, function (err, user) { + if (err) { + return next(err); + } + if (!user) { + return next(new Error('[ACTIVE_ACCOUNT] no such user: ' + name)); + } + var passhash = user.pass; + if (!user || utility.md5(user.email + passhash + config.session_secret) !== key) { + return res.render('notify/notify', {error: '信息有误,帐号无法被激活。'}); + } + if (user.active) { + return res.render('notify/notify', {error: '帐号已经是激活状态。'}); + } + user.active = true; + user.save(function (err) { + if (err) { + return next(err); + } + res.render('notify/notify', {success: '帐号已被激活,请登录'}); + }); + }); +}; + +exports.showSearchPass = function (req, res) { + res.render('sign/search_pass'); +}; + +exports.updateSearchPass = function (req, res, next) { + var email = validator.trim(req.body.email).toLowerCase(); + if (!validator.isEmail(email)) { + return res.render('sign/search_pass', {error: '邮箱不合法', email: email}); + } + + // 动态生成retrive_key和timestamp到users collection,之后重置密码进行验证 + var retrieveKey = uuid.v4(); + var retrieveTime = new Date().getTime(); + + User.getUserByMail(email, function (err, user) { + if (!user) { + res.render('sign/search_pass', {error: '没有这个电子邮箱。', email: email}); + return; + } + user.retrieve_key = retrieveKey; + user.retrieve_time = retrieveTime; + user.save(function (err) { + if (err) { + return next(err); + } + // 发送重置密码邮件 + mail.sendResetPassMail(email, retrieveKey, user.loginname); + res.render('notify/notify', {success: '我们已给您填写的电子邮箱发送了一封邮件,请在24小时内点击里面的链接来重置密码。'}); + }); + }); +}; + +/** + * reset password + * 'get' to show the page, 'post' to reset password + * after reset password, retrieve_key&time will be destroy + * @param {http.req} req + * @param {http.res} res + * @param {Function} next + */ +exports.resetPass = function (req, res, next) { + var key = validator.trim(req.query.key); + var name = validator.trim(req.query.name); + + User.getUserByNameAndKey(name, key, function (err, user) { + if (!user) { + res.status(403); + return res.render('notify/notify', {error: '信息有误,密码无法重置。'}); + } + var now = new Date().getTime(); + var oneDay = 1000 * 60 * 60 * 24; + if (!user.retrieve_time || now - user.retrieve_time > oneDay) { + res.status(403); + return res.render('notify/notify', {error: '该链接已过期,请重新申请。'}); + } + return res.render('sign/reset', {name: name, key: key}); + }); +}; + +exports.updatePass = function (req, res, next) { + var psw = validator.trim(req.body.psw) || ''; + var repsw = validator.trim(req.body.repsw) || ''; + var key = validator.trim(req.body.key) || ''; + var name = validator.trim(req.body.name) || ''; + + var ep = new eventproxy(); + ep.fail(next); + + if (psw !== repsw) { + return res.render('sign/reset', {name: name, key: key, error: '两次密码输入不一致。'}); + } + User.getUserByNameAndKey(name, key, ep.done(function (user) { + if (!user) { + return res.render('notify/notify', {error: '错误的激活链接'}); + } + tools.bhash(psw, ep.done(function (passhash) { + user.pass = passhash; + user.retrieve_key = null; + user.retrieve_time = null; + user.active = true; // 用户激活 + + user.save(function (err) { + if (err) { + return next(err); + } + return res.render('notify/notify', {success: '你的密码已重置。'}); + }); + })); + })); +}; + diff --git a/controllers/site.js b/controllers/site.js new file mode 100644 index 0000000000..40dfba7ab6 --- /dev/null +++ b/controllers/site.js @@ -0,0 +1,151 @@ +/*! + * nodeclub - site index controller. + * Copyright(c) 2012 fengmk2 + * Copyright(c) 2012 muyuan + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var User = require('../proxy').User; +var Topic = require('../proxy').Topic; +var config = require('../config'); +var eventproxy = require('eventproxy'); +var cache = require('../common/cache'); +var xmlbuilder = require('xmlbuilder'); +var renderHelper = require('../common/render_helper'); +var _ = require('lodash'); + +exports.index = function (req, res, next) { + var page = parseInt(req.query.page, 10) || 1; + page = page > 0 ? page : 1; + var tab = req.query.tab || 'all'; + + var proxy = new eventproxy(); + proxy.fail(next); + + // 取主题 + var query = {}; + if (tab && tab !== 'all') { + if (tab === 'good') { + query.good = true; + } else { + query.tab = tab; + } + } + + var limit = config.list_topic_count; + var options = { skip: (page - 1) * limit, limit: limit, sort: '-top -last_reply_at'}; + + Topic.getTopicsByQuery(query, options, proxy.done('topics', function (topics) { + return topics; + })); + + // 取排行榜上的用户 + cache.get('tops', proxy.done(function (tops) { + if (tops) { + proxy.emit('tops', tops); + } else { + User.getUsersByQuery( + {is_block: false}, + { limit: 10, sort: '-score'}, + proxy.done('tops', function (tops) { + cache.set('tops', tops, 60 * 1); + return tops; + }) + ); + } + })); + // END 取排行榜上的用户 + + // 取0回复的主题 + cache.get('no_reply_topics', proxy.done(function (no_reply_topics) { + if (no_reply_topics) { + proxy.emit('no_reply_topics', no_reply_topics); + } else { + Topic.getTopicsByQuery( + { reply_count: 0, tab: {$ne: 'job'}}, + { limit: 5, sort: '-create_at'}, + proxy.done('no_reply_topics', function (no_reply_topics) { + cache.set('no_reply_topics', no_reply_topics, 60 * 1); + return no_reply_topics; + })); + } + })); + // END 取0回复的主题 + + // 取分页数据 + var pagesCacheKey = JSON.stringify(query) + 'pages'; + cache.get(pagesCacheKey, proxy.done(function (pages) { + if (pages) { + proxy.emit('pages', pages); + } else { + Topic.getCountByQuery(query, proxy.done(function (all_topics_count) { + var pages = Math.ceil(all_topics_count / limit); + cache.set(pagesCacheKey, pages, 60 * 1); + proxy.emit('pages', pages); + })); + } + })); + // END 取分页数据 + + var tabName = renderHelper.tabName(tab); + proxy.all('topics', 'tops', 'no_reply_topics', 'pages', + function (topics, tops, no_reply_topics, pages) { + res.render('index', { + topics: topics, + current_page: page, + list_topic_count: limit, + tops: tops, + no_reply_topics: no_reply_topics, + pages: pages, + tabs: config.tabs, + tab: tab, + pageTitle: tabName && (tabName + '版块'), + }); + }); +}; + +exports.sitemap = function (req, res, next) { + var urlset = xmlbuilder.create('urlset', + {version: '1.0', encoding: 'UTF-8'}); + urlset.att('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9'); + + var ep = new eventproxy(); + ep.fail(next); + + ep.all('sitemap', function (sitemap) { + res.type('xml'); + res.send(sitemap); + }); + + cache.get('sitemap', ep.done(function (sitemapData) { + if (sitemapData) { + ep.emit('sitemap', sitemapData); + } else { + Topic.getLimit5w(function (err, topics) { + if (err) { + return next(err); + } + topics.forEach(function (topic) { + urlset.ele('url').ele('loc', 'http://cnodejs.org/topic/' + topic._id); + }); + + var sitemapData = urlset.end(); + // 缓存一天 + cache.set('sitemap', sitemapData, 3600 * 24); + ep.emit('sitemap', sitemapData); + }); + } + })); +}; + +exports.appDownload = function (req, res, next) { + if (/Android/i.test(req.headers['user-agent'])) { + res.redirect('http://fir.im/ks4u'); + } else { + res.redirect('https://itunes.apple.com/cn/app/id954734793'); + } +}; diff --git a/controllers/static.js b/controllers/static.js new file mode 100644 index 0000000000..b1b3f6fe67 --- /dev/null +++ b/controllers/static.js @@ -0,0 +1,37 @@ +var multiline = require('multiline'); +// static page +// About +exports.about = function (req, res, next) { + res.render('static/about', { + pageTitle: '关于我们' + }); +}; + +// FAQ +exports.faq = function (req, res, next) { + res.render('static/faq'); +}; + +exports.getstart = function (req, res) { + res.render('static/getstart', { + pageTitle: 'Node.js 新手入门' + }); +}; + + +exports.robots = function (req, res, next) { + res.type('text/plain'); + res.send(multiline(function () {; +/* +# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-Agent: * +# Disallow: / +*/ + })); +}; + +exports.api = function (req, res, next) { + res.render('static/api'); +}; diff --git a/controllers/topic.js b/controllers/topic.js new file mode 100644 index 0000000000..b29b095b14 --- /dev/null +++ b/controllers/topic.js @@ -0,0 +1,441 @@ +/*! + * nodeclub - controllers/topic.js + */ + +/** + * Module dependencies. + */ + +var validator = require('validator'); + +var at = require('../common/at'); +var User = require('../proxy').User; +var Topic = require('../proxy').Topic; +var TopicCollect = require('../proxy').TopicCollect; +var EventProxy = require('eventproxy'); +var tools = require('../common/tools'); +var store = require('../common/store'); +var config = require('../config'); +var _ = require('lodash'); +var cache = require('../common/cache'); + +/** + * Topic page + * + * @param {HttpRequest} req + * @param {HttpResponse} res + * @param {Function} next + */ +exports.index = function (req, res, next) { + function isUped(user, reply) { + if (!reply.ups) { + return false; + } + return reply.ups.indexOf(user._id) !== -1; + } + + var topic_id = req.params.tid; + if (topic_id.length !== 24) { + return res.render404('此话题不存在或已被删除。'); + } + var events = ['topic', 'other_topics', 'no_reply_topics']; + var ep = EventProxy.create(events, function (topic, other_topics, no_reply_topics) { + res.render('topic/index', { + topic: topic, + author_other_topics: other_topics, + no_reply_topics: no_reply_topics, + is_uped: isUped + }); + }); + + ep.fail(next); + + Topic.getFullTopic(topic_id, ep.done(function (message, topic, author, replies) { + if (message) { + ep.unbind(); + return res.renderError(message); + } + + topic.visit_count += 1; + topic.save(); + + topic.author = author; + topic.replies = replies; + + // 点赞数排名第三的回答,它的点赞数就是阈值 + topic.reply_up_threshold = (function () { + var allUpCount = replies.map(function (reply) { + return reply.ups && reply.ups.length || 0; + }); + allUpCount = _.sortBy(allUpCount, Number).reverse(); + + var threshold = allUpCount[2] || 0; + if (threshold < 3) { + threshold = 3; + } + return threshold; + })(); + + ep.emit('topic', topic); + + // get other_topics + var options = { limit: 5, sort: '-last_reply_at'}; + var query = { author_id: topic.author_id, _id: { '$nin': [ topic._id ] } }; + Topic.getTopicsByQuery(query, options, ep.done('other_topics')); + + // get no_reply_topics + cache.get('no_reply_topics', ep.done(function (no_reply_topics) { + if (no_reply_topics) { + ep.emit('no_reply_topics', no_reply_topics); + } else { + Topic.getTopicsByQuery( + { reply_count: 0, tab: {$ne: 'job'}}, + { limit: 5, sort: '-create_at'}, + ep.done('no_reply_topics', function (no_reply_topics) { + cache.set('no_reply_topics', no_reply_topics, 60 * 1); + return no_reply_topics; + })); + } + })); + })); +}; + +exports.create = function (req, res, next) { + res.render('topic/edit', { + tabs: config.tabs + }); +}; + + +exports.put = function (req, res, next) { + var title = validator.trim(req.body.title); + var tab = validator.trim(req.body.tab); + var content = validator.trim(req.body.t_content); + + // 得到所有的 tab, e.g. ['ask', 'share', ..] + var allTabs = config.tabs.map(function (tPair) { + return tPair[0]; + }); + + // 验证 + var editError; + if (title === '') { + editError = '标题不能是空的。'; + } else if (title.length < 5 || title.length > 100) { + editError = '标题字数太多或太少。'; + } else if (!tab || allTabs.indexOf(tab) === -1) { + editError = '必须选择一个版块。'; + } else if (content === '') { + editError = '内容不可为空'; + } + // END 验证 + + if (editError) { + res.status(422); + return res.render('topic/edit', { + edit_error: editError, + title: title, + content: content, + tabs: config.tabs + }); + } + + Topic.newAndSave(title, content, tab, req.session.user._id, function (err, topic) { + if (err) { + return next(err); + } + + var proxy = new EventProxy(); + + proxy.all('score_saved', function () { + res.redirect('/topic/' + topic._id); + }); + proxy.fail(next); + User.getUserById(req.session.user._id, proxy.done(function (user) { + user.score += 5; + user.topic_count += 1; + user.save(); + req.session.user = user; + proxy.emit('score_saved'); + })); + + //发送at消息 + at.sendMessageToMentionUsers(content, topic._id, req.session.user._id); + }); +}; + +exports.showEdit = function (req, res, next) { + var topic_id = req.params.tid; + + Topic.getTopicById(topic_id, function (err, topic, tags) { + if (!topic) { + res.render404('此话题不存在或已被删除。'); + return; + } + + if (String(topic.author_id) === String(req.session.user._id) || req.session.user.is_admin) { + res.render('topic/edit', { + action: 'edit', + topic_id: topic._id, + title: topic.title, + content: topic.content, + tab: topic.tab, + tabs: config.tabs + }); + } else { + res.renderError('对不起,你不能编辑此话题。', 403); + } + }); +}; + +exports.update = function (req, res, next) { + var topic_id = req.params.tid; + var title = req.body.title; + var tab = req.body.tab; + var content = req.body.t_content; + + Topic.getTopicById(topic_id, function (err, topic, tags) { + if (!topic) { + res.render404('此话题不存在或已被删除。'); + return; + } + + if (topic.author_id.equals(req.session.user._id) || req.session.user.is_admin) { + title = validator.trim(title); + tab = validator.trim(tab); + content = validator.trim(content); + + // 验证 + var editError; + if (title === '') { + editError = '标题不能是空的。'; + } else if (title.length < 5 || title.length > 100) { + editError = '标题字数太多或太少。'; + } else if (!tab) { + editError = '必须选择一个版块。'; + } + // END 验证 + + if (editError) { + return res.render('topic/edit', { + action: 'edit', + edit_error: editError, + topic_id: topic._id, + content: content, + tabs: config.tabs + }); + } + + //保存话题 + topic.title = title; + topic.content = content; + topic.tab = tab; + topic.update_at = new Date(); + + topic.save(function (err) { + if (err) { + return next(err); + } + //发送at消息 + at.sendMessageToMentionUsers(content, topic._id, req.session.user._id); + + res.redirect('/topic/' + topic._id); + + }); + } else { + res.renderError('对不起,你不能编辑此话题。', 403); + } + }); +}; + +exports.delete = function (req, res, next) { + //删除话题, 话题作者topic_count减1 + //删除回复,回复作者reply_count减1 + //删除topic_collect,用户collect_topic_count减1 + + var topic_id = req.params.tid; + + Topic.getTopic(topic_id, function (err, topic) { + if (err) { + return res.send({ success: false, message: err.message }); + } + if (!req.session.user.is_admin && !(topic.author_id.equals(req.session.user._id))) { + res.status(403); + return res.send({success: false, message: '无权限'}); + } + if (!topic) { + res.status(422); + return res.send({ success: false, message: '此话题不存在或已被删除。' }); + } + topic.deleted = true; + topic.save(function (err) { + if (err) { + return res.send({ success: false, message: err.message }); + } + res.send({ success: true, message: '话题已被删除。' }); + }); + }); +}; + +// 设为置顶 +exports.top = function (req, res, next) { + var topic_id = req.params.tid; + var referer = req.get('referer'); + + if (topic_id.length !== 24) { + res.render404('此话题不存在或已被删除。'); + return; + } + Topic.getTopic(topic_id, function (err, topic) { + if (err) { + return next(err); + } + if (!topic) { + res.render404('此话题不存在或已被删除。'); + return; + } + topic.top = !topic.top; + topic.save(function (err) { + if (err) { + return next(err); + } + var msg = topic.top ? '此话题已置顶。' : '此话题已取消置顶。'; + res.render('notify/notify', {success: msg, referer: referer}); + }); + }); +}; + +// 设为精华 +exports.good = function (req, res, next) { + var topicId = req.params.tid; + var referer = req.get('referer'); + + Topic.getTopic(topicId, function (err, topic) { + if (err) { + return next(err); + } + if (!topic) { + res.render404('此话题不存在或已被删除。'); + return; + } + topic.good = !topic.good; + topic.save(function (err) { + if (err) { + return next(err); + } + var msg = topic.good ? '此话题已加精。' : '此话题已取消加精。'; + res.render('notify/notify', {success: msg, referer: referer}); + }); + }); +}; + +// 锁定主题,不可再回复 +exports.lock = function (req, res, next) { + var topicId = req.params.tid; + var referer = req.get('referer'); + Topic.getTopic(topicId, function (err, topic) { + if (err) { + return next(err); + } + if (!topic) { + res.render404('此话题不存在或已被删除。'); + return; + } + topic.lock = !topic.lock; + topic.save(function (err) { + if (err) { + return next(err); + } + var msg = topic.lock ? '此话题已锁定。' : '此话题已取消锁定。'; + res.render('notify/notify', {success: msg, referer: referer}); + }); + }); +}; + +// 收藏主题 +exports.collect = function (req, res, next) { + var topic_id = req.body.topic_id; + Topic.getTopic(topic_id, function (err, topic) { + if (err) { + return next(err); + } + if (!topic) { + res.json({status: 'failed'}); + } + + TopicCollect.getTopicCollect(req.session.user._id, topic._id, function (err, doc) { + if (err) { + return next(err); + } + if (doc) { + res.json({status: 'success'}); + return; + } + + TopicCollect.newAndSave(req.session.user._id, topic._id, function (err) { + if (err) { + return next(err); + } + res.json({status: 'success'}); + }); + User.getUserById(req.session.user._id, function (err, user) { + if (err) { + return next(err); + } + user.collect_topic_count += 1; + user.save(); + }); + + req.session.user.collect_topic_count += 1; + topic.collect_count += 1; + topic.save(); + }); + }); +}; + +exports.de_collect = function (req, res, next) { + var topic_id = req.body.topic_id; + Topic.getTopic(topic_id, function (err, topic) { + if (err) { + return next(err); + } + if (!topic) { + res.json({status: 'failed'}); + } + TopicCollect.remove(req.session.user._id, topic._id, function (err) { + if (err) { + return next(err); + } + res.json({status: 'success'}); + }); + + User.getUserById(req.session.user._id, function (err, user) { + if (err) { + return next(err); + } + user.collect_topic_count -= 1; + user.save(); + }); + + topic.collect_count -= 1; + topic.save(); + + req.session.user.collect_topic_count -= 1; + }); +}; + +exports.upload = function (req, res, next) { + req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) { + store.upload(file, {filename: filename}, function (err, result) { + if (err) { + return next(err); + } + res.json({ + success: true, + url: result.url, + }); + }); + }); + + req.pipe(req.busboy); +}; diff --git a/controllers/user.js b/controllers/user.js new file mode 100644 index 0000000000..7981a2d44b --- /dev/null +++ b/controllers/user.js @@ -0,0 +1,368 @@ +var User = require('../proxy').User; +var Topic = require('../proxy').Topic; +var Reply = require('../proxy').Reply; +var TopicCollect = require('../proxy').TopicCollect; +var utility = require('utility'); +var util = require('util'); +var TopicModel = require('../models').Topic; +var ReplyModel = require('../models').Reply; +var tools = require('../common/tools'); +var config = require('../config'); +var EventProxy = require('eventproxy'); +var validator = require('validator'); +var utility = require('utility'); +var _ = require('lodash'); + +exports.index = function (req, res, next) { + var user_name = req.params.name; + User.getUserByLoginName(user_name, function (err, user) { + if (err) { + return next(err); + } + if (!user) { + res.render404('这个用户不存在。'); + return; + } + + var render = function (recent_topics, recent_replies) { + user.url = (function () { + if (user.url && user.url.indexOf('http') !== 0) { + return 'http://' + user.url; + } + return user.url; + })(); + // 如果用户没有激活,那么管理员可以帮忙激活 + var token = ''; + if (!user.active && req.session.user && req.session.user.is_admin) { + token = utility.md5(user.email + user.pass + config.session_secret); + } + res.render('user/index', { + user: user, + recent_topics: recent_topics, + recent_replies: recent_replies, + token: token, + pageTitle: util.format('@%s 的个人主页', user.loginname), + }); + }; + + var proxy = new EventProxy(); + proxy.assign('recent_topics', 'recent_replies', render); + proxy.fail(next); + + var query = {author_id: user._id}; + var opt = {limit: 5, sort: '-create_at'}; + Topic.getTopicsByQuery(query, opt, proxy.done('recent_topics')); + + Reply.getRepliesByAuthorId(user._id, {limit: 20, sort: '-create_at'}, + proxy.done(function (replies) { + var topic_ids = []; + for (var i = 0; i < replies.length; i++) { + if (topic_ids.indexOf(replies[i].topic_id.toString()) < 0) { + topic_ids.push(replies[i].topic_id.toString()); + } + } + var query = {_id: {'$in': topic_ids}}; + var opt = {limit: 5, sort: '-create_at'}; + Topic.getTopicsByQuery(query, opt, proxy.done('recent_replies')); + })); + }); +}; + +exports.listStars = function (req, res, next) { + User.getUsersByQuery({is_star: true}, {}, function (err, stars) { + if (err) { + return next(err); + } + res.render('user/stars', {stars: stars}); + }); +}; + +exports.showSetting = function (req, res, next) { + User.getUserById(req.session.user._id, function (err, user) { + if (err) { + return next(err); + } + if (req.query.save === 'success') { + user.success = '保存成功。'; + } + user.error = null; + return res.render('user/setting', user); + }); +}; + +exports.setting = function (req, res, next) { + var ep = new EventProxy(); + ep.fail(next); + + // 显示出错或成功信息 + function showMessage(msg, data, isSuccess) { + data = data || req.body; + var data2 = { + loginname: data.loginname, + email: data.email, + url: data.url, + location: data.location, + signature: data.signature, + weibo: data.weibo, + accessToken: data.accessToken, + }; + if (isSuccess) { + data2.success = msg; + } else { + data2.error = msg; + } + res.render('user/setting', data2); + } + + // post + var action = req.body.action; + if (action === 'change_setting') { + var url = validator.trim(req.body.url); + var location = validator.trim(req.body.location); + var weibo = validator.trim(req.body.weibo); + var signature = validator.trim(req.body.signature); + + User.getUserById(req.session.user._id, ep.done(function (user) { + user.url = url; + user.location = location; + user.signature = signature; + user.weibo = weibo; + user.save(function (err) { + if (err) { + return next(err); + } + req.session.user = user.toObject({virtual: true}); + return res.redirect('/setting?save=success'); + }); + })); + } + if (action === 'change_password') { + var old_pass = validator.trim(req.body.old_pass); + var new_pass = validator.trim(req.body.new_pass); + if (!old_pass || !new_pass) { + return res.send('旧密码或新密码不得为空'); + } + + User.getUserById(req.session.user._id, ep.done(function (user) { + tools.bcompare(old_pass, user.pass, ep.done(function (bool) { + if (!bool) { + return showMessage('当前密码不正确。', user); + } + + tools.bhash(new_pass, ep.done(function (passhash) { + user.pass = passhash; + user.save(function (err) { + if (err) { + return next(err); + } + return showMessage('密码已被修改。', user, true); + + }); + })); + })); + })); + } +}; + +exports.toggleStar = function (req, res, next) { + var user_id = req.body.user_id; + User.getUserById(user_id, function (err, user) { + if (err) { + return next(err); + } + if (!user) { + return next(new Error('user is not exists')); + } + user.is_star = !user.is_star; + user.save(function (err) { + if (err) { + return next(err); + } + res.json({ status: 'success' }); + }); + }); +}; + +exports.listCollectedTopics = function (req, res, next) { + var name = req.params.name; + User.getUserByLoginName(name, function (err, user) { + if (err || !user) { + return next(err); + } + + var page = Number(req.query.page) || 1; + var limit = config.list_topic_count; + + var render = function (topics, pages) { + res.render('user/collect_topics', { + topics: topics, + current_page: page, + pages: pages, + user: user + }); + }; + + var proxy = EventProxy.create('topics', 'pages', render); + proxy.fail(next); + + TopicCollect.getTopicCollectsByUserId(user._id, proxy.done(function (docs) { + var ids = []; + for (var i = 0; i < docs.length; i++) { + ids.push(docs[i].topic_id); + } + var query = { _id: { '$in': ids } }; + var opt = { + skip: (page - 1) * limit, + limit: limit, + sort: '-create_at' + }; + Topic.getTopicsByQuery(query, opt, proxy.done('topics')); + Topic.getCountByQuery(query, proxy.done(function (all_topics_count) { + var pages = Math.ceil(all_topics_count / limit); + proxy.emit('pages', pages); + })); + })); + }); +}; + +exports.top100 = function (req, res, next) { + var opt = {limit: 100, sort: '-score'}; + User.getUsersByQuery({is_block: false}, opt, function (err, tops) { + if (err) { + return next(err); + } + res.render('user/top100', { + users: tops, + pageTitle: 'top100', + }); + }); +}; + +exports.listTopics = function (req, res, next) { + var user_name = req.params.name; + var page = Number(req.query.page) || 1; + var limit = config.list_topic_count; + + User.getUserByLoginName(user_name, function (err, user) { + if (!user) { + res.render404('这个用户不存在。'); + return; + } + + var render = function (topics, pages) { + res.render('user/topics', { + user: user, + topics: topics, + current_page: page, + pages: pages + }); + }; + + var proxy = new EventProxy(); + proxy.assign('topics', 'pages', render); + proxy.fail(next); + + var query = {'author_id': user._id}; + var opt = {skip: (page - 1) * limit, limit: limit, sort: '-create_at'}; + Topic.getTopicsByQuery(query, opt, proxy.done('topics')); + + Topic.getCountByQuery(query, proxy.done(function (all_topics_count) { + var pages = Math.ceil(all_topics_count / limit); + proxy.emit('pages', pages); + })); + }); +}; + +exports.listReplies = function (req, res, next) { + var user_name = req.params.name; + var page = Number(req.query.page) || 1; + var limit = 50; + + User.getUserByLoginName(user_name, function (err, user) { + if (!user) { + res.render404('这个用户不存在。'); + return; + } + + var render = function (topics, pages) { + res.render('user/replies', { + user: user, + topics: topics, + current_page: page, + pages: pages + }); + }; + + var proxy = new EventProxy(); + proxy.assign('topics', 'pages', render); + proxy.fail(next); + + var opt = {skip: (page - 1) * limit, limit: limit, sort: '-create_at'}; + Reply.getRepliesByAuthorId(user._id, opt, proxy.done(function (replies) { + // 获取所有有评论的主题 + var topic_ids = replies.map(function (reply) { + return reply.topic_id; + }); + topic_ids = _.uniq(topic_ids); + var query = {'_id': {'$in': topic_ids}}; + Topic.getTopicsByQuery(query, {}, proxy.done('topics')); + })); + + Reply.getCountByAuthorId(user._id, proxy.done('pages', function (count) { + var pages = Math.ceil(count / limit); + return pages; + })); + }); +}; + +exports.block = function (req, res, next) { + var loginname = req.params.name; + var action = req.body.action; + + var ep = EventProxy.create(); + ep.fail(next); + + User.getUserByLoginName(loginname, ep.done(function (user) { + if (!user) { + return next(new Error('user is not exists')); + } + if (action === 'set_block') { + ep.all('block_user', + function (user) { + res.json({status: 'success'}); + }); + user.is_block = true; + user.save(ep.done('block_user')); + + } else if (action === 'cancel_block') { + user.is_block = false; + user.save(ep.done(function () { + + res.json({status: 'success'}); + })); + } + })); +}; + +exports.deleteAll = function (req, res, next) { + var loginname = req.params.name; + + var ep = EventProxy.create(); + ep.fail(next); + + User.getUserByLoginName(loginname, ep.done(function (user) { + if (!user) { + return next(new Error('user is not exists')); + } + ep.all('del_topics', 'del_replys', 'del_ups', + function () { + res.json({status: 'success'}); + }); + // 删除主题 + TopicModel.update({author_id: user._id}, {$set: {deleted: true}}, {multi: true}, ep.done('del_topics')); + // 删除评论 + ReplyModel.update({author_id: user._id}, {$set: {deleted: true}}, {multi: true}, ep.done('del_replys')); + // 点赞数也全部干掉 + ReplyModel.update({}, {$pull: {'ups': user._id}}, {multi: true}, ep.done('del_ups')); + })); +}; diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000000..2b6a105bff --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,15 @@ +var gulp = require('gulp'); +var mocha = require('gulp-mocha'); + +gulp.task('test', function () { + return gulp.src('test/**/*.test.js', {read: false}) + .pipe(mocha({ + timeout: 5000, + reporter: 'spec', + require: ['should'] + })) + .once('end',function(){ + process.exit(); + }) + ; +}); \ No newline at end of file diff --git a/middlewares/auth.js b/middlewares/auth.js new file mode 100644 index 0000000000..1e9e06cacd --- /dev/null +++ b/middlewares/auth.js @@ -0,0 +1,106 @@ +var mongoose = require('mongoose'); +var UserModel = mongoose.model('User'); +var Message = require('../proxy').Message; +var config = require('../config'); +var eventproxy = require('eventproxy'); +var UserProxy = require('../proxy').User; + +/** + * 需要管理员权限 + */ +exports.adminRequired = function (req, res, next) { + if (!req.session.user) { + return res.render('notify/notify', { error: '你还没有登录。' }); + } + + if (!req.session.user.is_admin) { + return res.render('notify/notify', { error: '需要管理员权限。' }); + } + + next(); +}; + +/** + * 需要登录 + */ +exports.userRequired = function (req, res, next) { + if (!req.session || !req.session.user) { + return res.status(403).send('forbidden!'); + } + + next(); +}; + +exports.blockUser = function () { + return function (req, res, next) { + if (req.path === '/signout') { + return next(); + } + + if (req.session.user && req.session.user.is_block && req.method !== 'GET') { + return res.status(403).send('您已被管理员屏蔽了。有疑问请联系 @alsotang。'); + } + next(); + }; +}; + + +function gen_session(user, res) { + var auth_token = user._id + '$$$$'; // 以后可能会存储更多信息,用 $$$$ 来分隔 + var opts = { + path: '/', + maxAge: 1000 * 60 * 60 * 24 * 30, + signed: true, + httpOnly: true + }; + res.cookie(config.auth_cookie_name, auth_token, opts); //cookie 有效期30天 +} + +exports.gen_session = gen_session; + +// 验证用户是否登录 +exports.authUser = function (req, res, next) { + var ep = new eventproxy(); + ep.fail(next); + + // Ensure current_user always has defined. + res.locals.current_user = null; + + if (config.debug && req.cookies['mock_user']) { + var mockUser = JSON.parse(req.cookies['mock_user']); + req.session.user = new UserModel(mockUser); + if (mockUser.is_admin) { + req.session.user.is_admin = true; + } + return next(); + } + + ep.all('get_user', function (user) { + if (!user) { + return next(); + } + user = res.locals.current_user = req.session.user = new UserModel(user); + + if (config.admins.hasOwnProperty(user.loginname)) { + user.is_admin = true; + } + + Message.getMessagesCount(user._id, ep.done(function (count) { + user.messages_count = count; + next(); + })); + }); + + if (req.session.user) { + ep.emit('get_user', req.session.user); + } else { + var auth_token = req.signedCookies[config.auth_cookie_name]; + if (!auth_token) { + return next(); + } + + var auth = auth_token.split('$$$$'); + var user_id = auth[0]; + UserProxy.getUserById(user_id, ep.done('get_user')); + } +}; diff --git a/middlewares/conf.js b/middlewares/conf.js new file mode 100644 index 0000000000..3257170746 --- /dev/null +++ b/middlewares/conf.js @@ -0,0 +1,8 @@ +var config = require('../config'); + +exports.github = function (req, res, next) { + if (config.GITHUB_OAUTH.clientID === 'your GITHUB_CLIENT_ID') { + return res.send('call the admin to set github oauth.'); + } + next(); +}; diff --git a/middlewares/error_page.js b/middlewares/error_page.js new file mode 100644 index 0000000000..c92a4b4ded --- /dev/null +++ b/middlewares/error_page.js @@ -0,0 +1,16 @@ +// ErrorPage middleware +exports.errorPage = function (req, res, next) { + + res.render404 = function (error) { + return res.status(404).render('notify/notify', { error: error }); + }; + + res.renderError = function (error, statusCode) { + if (statusCode === undefined) { + statusCode = 400; + } + return res.status(statusCode).render('notify/notify', { error: error }); + }; + + next(); +}; diff --git a/middlewares/github_strategy.js b/middlewares/github_strategy.js new file mode 100644 index 0000000000..3ae932cb1e --- /dev/null +++ b/middlewares/github_strategy.js @@ -0,0 +1,4 @@ +module.exports = function (accessToken, refreshToken, profile, done) { + profile.accessToken = accessToken; + done(null, profile); +}; diff --git a/middlewares/limit.js b/middlewares/limit.js new file mode 100644 index 0000000000..0ebdd9cbc5 --- /dev/null +++ b/middlewares/limit.js @@ -0,0 +1,39 @@ +var config = require('../config'); +var cache = require('../common/cache'); +var moment = require('moment'); + +var SEPARATOR = '^_^@T_T'; + +var makePerDayLimiter = function (identityName, identityFn) { + return function (name, limitCount) { + return function (req, res, next) { + var identity = identityFn(req); + var YYYYMMDD = moment().format('YYYYMMDD'); + var key = YYYYMMDD + SEPARATOR + identityName + SEPARATOR + name + SEPARATOR + identity; + + cache.get(key, function (err, count) { + if (err) { + return next(err); + } + count = count || 0; + if (count < limitCount) { + count += 1; + cache.set(key, count, 60 * 60 * 24); + res.set('X-RateLimit-Limit', limitCount); + res.set('X-RateLimit-Remaining', limitCount - count); + next(); + } else { + res.send('ratelimit forbidden. limit is ' + limitCount + ' per day.'); + } + }); + }; + }; +}; + +exports.peruserperday = makePerDayLimiter('peruserperday', function (req) { + return (req.user || req.session.user).loginname; +}); + +exports.peripperday = makePerDayLimiter('peripperday', function (req) { + return req.ip; +}); diff --git a/middlewares/mongoose_log.js b/middlewares/mongoose_log.js new file mode 100644 index 0000000000..5717ddb567 --- /dev/null +++ b/middlewares/mongoose_log.js @@ -0,0 +1,16 @@ +var mongoose = require('mongoose'); +var logger = require('../common/logger'); + +var traceMQuery = function (method, info, query) { + return function (err, result, millis) { + var infos = []; + infos.push(query._collection.collection.name + "." + method.blue); + infos.push(JSON.stringify(info)); + infos.push((millis + 'ms').green); + + // var duration = (new Date()) - t; + logger.debug("MONGO".magenta, infos.join(' ')); + }; +}; + +mongoose.Mongoose.prototype.mquery.setGlobalTraceFunction(traceMQuery); diff --git a/middlewares/proxy.js b/middlewares/proxy.js new file mode 100644 index 0000000000..f4bd86a7ab --- /dev/null +++ b/middlewares/proxy.js @@ -0,0 +1,30 @@ +var urllib = require('url'); +var request = require('request'); + + +var ALLOW_HOSTNAME = [ + 'avatars.githubusercontent.com', 'www.gravatar.com', + 'gravatar.com', 'www.google-analytics.com' +]; +exports.proxy = function (req, res, next) { + var url = decodeURIComponent(req.query.url); + var hostname = urllib.parse(url).hostname; + + if (ALLOW_HOSTNAME.indexOf(hostname) === -1) { + return res.send(hostname + ' is not allowed'); + } + + request.get({ + url: url, + headers: { + 'If-Modified-Since': req.header('If-Modified-Since') || '' + } + }) + .on('response', function (response) { + res.set(response.headers); + }) + .on('error', function (err) { + console.error(err); + }) + .pipe(res); +}; diff --git a/middlewares/render.js b/middlewares/render.js new file mode 100644 index 0000000000..0c10c27182 --- /dev/null +++ b/middlewares/render.js @@ -0,0 +1,17 @@ +var logger = require('../common/logger'); + +// Patch res.render method to output logger +exports.render = function (req, res, next) { + res._render = res.render; + + res.render = function (view, options, fn) { + var t = new Date(); + + res._render(view, options, fn); + + var duration = (new Date() - t); + logger.info("Render view", view, ("(" + duration + "ms)").green); + }; + + next(); +}; diff --git a/middlewares/request_log.js b/middlewares/request_log.js new file mode 100644 index 0000000000..334327d40e --- /dev/null +++ b/middlewares/request_log.js @@ -0,0 +1,22 @@ +var logger = require('../common/logger'); + +module.exports = function (req, res, next) { + // Assets do not out log. + if (exports.ignore.test(req.url)) { + next(); + return; + } + + var t = new Date(); + logger.log('\n\nStarted', t.toISOString(), req.method, req.url, req.ip); + + res.on('finish', function () { + var duration = ((new Date()) - t); + + logger.log('Completed', res.statusCode, ('(' + duration + 'ms)').green); + }); + + next(); +}; + +exports.ignore = /^\/(public|agent)/; diff --git a/models/base_model.js b/models/base_model.js new file mode 100644 index 0000000000..25e4caf0bd --- /dev/null +++ b/models/base_model.js @@ -0,0 +1,15 @@ +/** + * 给所有的 Model 扩展功能 + * http://mongoosejs.com/docs/plugins.html + */ +var tools = require('../common/tools'); + +module.exports = function (schema) { + schema.methods.create_at_ago = function () { + return tools.formatDate(this.create_at, true); + }; + + schema.methods.update_at_ago = function () { + return tools.formatDate(this.update_at, true); + }; +}; diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000000..9dc58a250b --- /dev/null +++ b/models/index.js @@ -0,0 +1,25 @@ +var mongoose = require('mongoose'); +var config = require('../config'); + +mongoose.connect(config.db, { + server: {poolSize: 20} +}, function (err) { + if (err) { + console.error('connect to %s error: ', config.db, err.message); + process.exit(1); + } +}); + +// models +require('./user'); +require('./topic'); +require('./reply'); +require('./topic_collect'); +require('./message'); + +exports.User = mongoose.model('User'); +exports.Topic = mongoose.model('Topic'); +exports.Reply = mongoose.model('Reply'); +exports.TopicCollect = mongoose.model('TopicCollect'); +exports.Message = mongoose.model('Message'); + diff --git a/models/message.js b/models/message.js new file mode 100644 index 0000000000..dd03cfd226 --- /dev/null +++ b/models/message.js @@ -0,0 +1,26 @@ +var mongoose = require('mongoose'); +var BaseModel = require("./base_model"); +var Schema = mongoose.Schema; +var ObjectId = Schema.ObjectId; + +/* + * type: + * reply: xx 回复了你的话题 + * reply2: xx 在话题中回复了你 + * follow: xx 关注了你 + * at: xx @了你 + */ + +var MessageSchema = new Schema({ + type: { type: String }, + master_id: { type: ObjectId}, + author_id: { type: ObjectId }, + topic_id: { type: ObjectId }, + reply_id: { type: ObjectId }, + has_read: { type: Boolean, default: false }, + create_at: { type: Date, default: Date.now } +}); +MessageSchema.plugin(BaseModel); +MessageSchema.index({master_id: 1, has_read: -1, create_at: -1}); + +mongoose.model('Message', MessageSchema); diff --git a/models/reply.js b/models/reply.js new file mode 100644 index 0000000000..a79a17e6fe --- /dev/null +++ b/models/reply.js @@ -0,0 +1,22 @@ +var mongoose = require('mongoose'); +var BaseModel = require("./base_model"); +var Schema = mongoose.Schema; +var ObjectId = Schema.ObjectId; + +var ReplySchema = new Schema({ + content: { type: String }, + topic_id: { type: ObjectId}, + author_id: { type: ObjectId }, + reply_id: { type: ObjectId }, + create_at: { type: Date, default: Date.now }, + update_at: { type: Date, default: Date.now }, + content_is_html: { type: Boolean }, + ups: [Schema.Types.ObjectId], + deleted: {type: Boolean, default: false}, +}); + +ReplySchema.plugin(BaseModel); +ReplySchema.index({topic_id: 1}); +ReplySchema.index({author_id: 1, create_at: -1}); + +mongoose.model('Reply', ReplySchema); diff --git a/models/topic.js b/models/topic.js new file mode 100644 index 0000000000..baecc34840 --- /dev/null +++ b/models/topic.js @@ -0,0 +1,45 @@ +var mongoose = require('mongoose'); +var BaseModel = require("./base_model"); +var Schema = mongoose.Schema; +var ObjectId = Schema.ObjectId; +var config = require('../config'); +var _ = require('lodash'); + +var TopicSchema = new Schema({ + title: { type: String }, + content: { type: String }, + author_id: { type: ObjectId }, + top: { type: Boolean, default: false }, // 置顶帖 + good: {type: Boolean, default: false}, // 精华帖 + lock: {type: Boolean, default: false}, // 被锁定主题 + reply_count: { type: Number, default: 0 }, + visit_count: { type: Number, default: 0 }, + collect_count: { type: Number, default: 0 }, + create_at: { type: Date, default: Date.now }, + update_at: { type: Date, default: Date.now }, + last_reply: { type: ObjectId }, + last_reply_at: { type: Date, default: Date.now }, + content_is_html: { type: Boolean }, + tab: {type: String}, + deleted: {type: Boolean, default: false}, +}); + +TopicSchema.plugin(BaseModel); +TopicSchema.index({create_at: -1}); +TopicSchema.index({top: -1, last_reply_at: -1}); +TopicSchema.index({author_id: 1, create_at: -1}); + +TopicSchema.virtual('tabName').get(function () { + var tab = this.tab; + var pair = _.find(config.tabs, function (_pair) { + return _pair[0] === tab; + }); + + if (pair) { + return pair[1]; + } else { + return ''; + } +}); + +mongoose.model('Topic', TopicSchema); diff --git a/models/topic_collect.js b/models/topic_collect.js new file mode 100644 index 0000000000..3d233ed346 --- /dev/null +++ b/models/topic_collect.js @@ -0,0 +1,13 @@ +var mongoose = require('mongoose'); +var BaseModel = require("./base_model"); +var Schema = mongoose.Schema; +var ObjectId = Schema.ObjectId; + +var TopicCollectSchema = new Schema({ + user_id: { type: ObjectId }, + topic_id: { type: ObjectId }, + create_at: { type: Date, default: Date.now } +}); + +TopicCollectSchema.plugin(BaseModel); +mongoose.model('TopicCollect', TopicCollectSchema); diff --git a/models/user.js b/models/user.js new file mode 100644 index 0000000000..c7dbca6348 --- /dev/null +++ b/models/user.js @@ -0,0 +1,79 @@ +var mongoose = require('mongoose'); +var BaseModel = require("./base_model"); +var renderHelper = require('../common/render_helper'); +var Schema = mongoose.Schema; +var utility = require('utility'); +var _ = require('lodash'); + +var UserSchema = new Schema({ + name: { type: String}, + loginname: { type: String}, + pass: { type: String }, + email: { type: String}, + url: { type: String }, + profile_image_url: {type: String}, + location: { type: String }, + signature: { type: String }, + profile: { type: String }, + weibo: { type: String }, + avatar: { type: String }, + githubId: { type: String}, + githubUsername: {type: String}, + githubAccessToken: {type: String}, + is_block: {type: Boolean, default: false}, + + score: { type: Number, default: 0 }, + topic_count: { type: Number, default: 0 }, + reply_count: { type: Number, default: 0 }, + follower_count: { type: Number, default: 0 }, + following_count: { type: Number, default: 0 }, + collect_tag_count: { type: Number, default: 0 }, + collect_topic_count: { type: Number, default: 0 }, + create_at: { type: Date, default: Date.now }, + update_at: { type: Date, default: Date.now }, + is_star: { type: Boolean }, + level: { type: String }, + active: { type: Boolean, default: false }, + + receive_reply_mail: {type: Boolean, default: false }, + receive_at_mail: { type: Boolean, default: false }, + from_wp: { type: Boolean }, + + retrieve_time: {type: Number}, + retrieve_key: {type: String}, + + accessToken: {type: String}, +}); + +UserSchema.plugin(BaseModel); +UserSchema.virtual('avatar_url').get(function () { + var url = this.avatar || ('https://gravatar.com/avatar/' + utility.md5(this.email.toLowerCase()) + '?size=48'); + + // www.gravatar.com 被墙 + url = url.replace('www.gravatar.com', 'gravatar.com'); + + // 让协议自适应 protocol,使用 `//` 开头 + if (url.indexOf('http:') === 0) { + url = url.slice(5); + } + + // 如果是 github 的头像,则限制大小 + if (url.indexOf('githubusercontent') !== -1) { + url += '&s=120'; + } + + return url; +}); + +UserSchema.virtual('isAdvanced').get(function () { + // 积分高于 700 则认为是高级用户 + return this.score > 700 || this.is_star; +}); + +UserSchema.index({loginname: 1}, {unique: true}); +UserSchema.index({email: 1}, {unique: true}); +UserSchema.index({score: -1}); +UserSchema.index({githubId: 1}); +UserSchema.index({accessToken: 1}); + +mongoose.model('User', UserSchema); diff --git a/oneapm.js b/oneapm.js new file mode 100644 index 0000000000..7471c3e1c7 --- /dev/null +++ b/oneapm.js @@ -0,0 +1,30 @@ +/** + * OneAPM agent configuration. + * + * See lib/config.defaults.js in the agent distribution for a more complete + * description of configuration variables and their potential values. + */ + +var config = require('./config'); + +exports.config = { + /** + * Array of application names. + */ + app_name : [config.name], + /** + * Your OneAPM license key. + */ + license_key : config.oneapm_key, + logging : { + /** + * Level at which to log. 'trace' is most useful to OneAPM when diagnosing + * issues with the agent, 'info' and higher will impose the least overhead on + * production applications. + */ + level : 'info' + }, + transaction_events: { + enabled: true + } +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000000..7ef7c82e58 --- /dev/null +++ b/package.json @@ -0,0 +1,71 @@ +{ + "name": "nodeclub", + "version": "2.1.0", + "private": true, + "main": "app.js", + "description": "A Node.js bbs using MongoDB", + "repository": "https://github.com/cnodejs/nodeclub", + "engines": { + "node": "0.12.x" + }, + "dependencies": { + "async": "0.9.0", + "bcryptjs": "2.3.0", + "body-parser": "1.9.2", + "colors": "1.1.0", + "compression": "1.2.0", + "connect-busboy": "0.0.1", + "connect-redis": "2.2.0", + "cookie-parser": "1.3.3", + "cors": "2.5.0", + "csurf": "1.6.2", + "data2xml": "0.8.0", + "ejs-mate": "2.0.0", + "eventproxy": "0.3.1", + "express": "4.9.5", + "express-session": "1.12.1", + "helmet": "~0.14.0", + "ioredis": "1.3.6", + "jpush-sdk": "3.2.0", + "loader": "0.1.4", + "lodash": "3.6.0", + "markdown-it": "3.0.3", + "memory-cache": "0.0.5", + "method-override": "1.0.2", + "moment": "2.9.0", + "mongoose": "4.2.4", + "multiline": "1.0.1", + "node-uuid": "1.4.1", + "nodemailer": "1.8.0", + "nodemailer-smtp-transport": "1.0.4", + "oneapm": "1.2.12", + "passport": "0.1.18", + "passport-github": "0.1.5", + "pm2": "0.15.10", + "qn": "1.0.1", + "ready": "0.1.1", + "request": "2.54.0", + "response-time": "2.2.0", + "superagent": "1.1.0", + "utility": "1.0.0", + "validator": "4.2.1", + "xmlbuilder": "4.0.0", + "xss": "0.1.15" + }, + "devDependencies": { + "coveralls": "2.11.2", + "errorhandler": "1.2.2", + "gulp": "^3.9.0", + "gulp-mocha": "^2.1.3", + "istanbul": "0.3.2", + "mm": "0.2.1", + "mocha": "2.0.1", + "nock": "2.17.0", + "pedding": "1.0.0", + "should": "4.1.0", + "supertest": "0.14.0" + }, + "scripts": { + "test": "make test" + } +} diff --git a/proxy/index.js b/proxy/index.js new file mode 100644 index 0000000000..fffc4c4feb --- /dev/null +++ b/proxy/index.js @@ -0,0 +1,5 @@ +exports.User = require('./user'); +exports.Message = require('./message'); +exports.Topic = require('./topic'); +exports.Reply = require('./reply'); +exports.TopicCollect = require('./topic_collect'); diff --git a/proxy/message.js b/proxy/message.js new file mode 100644 index 0000000000..50c9727a91 --- /dev/null +++ b/proxy/message.js @@ -0,0 +1,104 @@ +var EventProxy = require('eventproxy'); +var _ = require('lodash'); + +var Message = require('../models').Message; + +var User = require('./user'); +var Topic = require('./topic'); +var Reply = require('./reply'); + +/** + * 根据用户ID,获取未读消息的数量 + * Callback: + * 回调函数参数列表: + * - err, 数据库错误 + * - count, 未读消息数量 + * @param {String} id 用户ID + * @param {Function} callback 获取消息数量 + */ +exports.getMessagesCount = function (id, callback) { + Message.count({master_id: id, has_read: false}, callback); +}; + + +/** + * 根据消息Id获取消息 + * Callback: + * - err, 数据库错误 + * - message, 消息对象 + * @param {String} id 消息ID + * @param {Function} callback 回调函数 + */ +exports.getMessageById = function (id, callback) { + Message.findOne({_id: id}, function (err, message) { + if (err) { + return callback(err); + } + getMessageRelations(message, callback); + }); +}; + +var getMessageRelations = exports.getMessageRelations = function (message, callback) { + if (message.type === 'reply' || message.type === 'reply2' || message.type === 'at') { + var proxy = new EventProxy(); + proxy.fail(callback); + proxy.assign('author', 'topic', 'reply', function (author, topic, reply) { + message.author = author; + message.topic = topic; + message.reply = reply; + if (!author || !topic) { + message.is_invalid = true; + } + return callback(null, message); + }); // 接收异常 + User.getUserById(message.author_id, proxy.done('author')); + Topic.getTopicById(message.topic_id, proxy.done('topic')); + Reply.getReplyById(message.reply_id, proxy.done('reply')); + } else { + return callback(null, {is_invalid: true}); + } +}; + +/** + * 根据用户ID,获取已读消息列表 + * Callback: + * - err, 数据库异常 + * - messages, 消息列表 + * @param {String} userId 用户ID + * @param {Function} callback 回调函数 + */ +exports.getReadMessagesByUserId = function (userId, callback) { + Message.find({master_id: userId, has_read: true}, null, + {sort: '-create_at', limit: 20}, callback); +}; + +/** + * 根据用户ID,获取未读消息列表 + * Callback: + * - err, 数据库异常 + * - messages, 未读消息列表 + * @param {String} userId 用户ID + * @param {Function} callback 回调函数 + */ +exports.getUnreadMessageByUserId = function (userId, callback) { + Message.find({master_id: userId, has_read: false}, null, + {sort: '-create_at'}, callback); +}; + + +/** + * 将消息设置成已读 + */ +exports.updateMessagesToRead = function (userId, messages, callback) { + callback = callback || _.noop; + if (messages.length === 0) { + return callback(); + } + + var ids = messages.map(function (m) { + return m.id; + }); + + var query = { master_id: userId, _id: { $in: ids } }; + Message.update(query, { $set: { has_read: true } }, { multi: true }).exec(callback); +}; diff --git a/proxy/reply.js b/proxy/reply.js new file mode 100644 index 0000000000..5e95d45411 --- /dev/null +++ b/proxy/reply.js @@ -0,0 +1,149 @@ +var models = require('../models'); +var Reply = models.Reply; +var EventProxy = require('eventproxy'); +var tools = require('../common/tools'); +var User = require('./user'); +var at = require('../common/at'); + +/** + * 获取一条回复信息 + * @param {String} id 回复ID + * @param {Function} callback 回调函数 + */ +exports.getReply = function (id, callback) { + Reply.findOne({_id: id}, callback); +}; + +/** + * 根据回复ID,获取回复 + * Callback: + * - err, 数据库异常 + * - reply, 回复内容 + * @param {String} id 回复ID + * @param {Function} callback 回调函数 + */ +exports.getReplyById = function (id, callback) { + if (!id) { + return callback(null, null); + } + Reply.findOne({_id: id}, function (err, reply) { + if (err) { + return callback(err); + } + if (!reply) { + return callback(err, null); + } + + var author_id = reply.author_id; + User.getUserById(author_id, function (err, author) { + if (err) { + return callback(err); + } + reply.author = author; + // TODO: 添加更新方法,有些旧帖子可以转换为markdown格式的内容 + if (reply.content_is_html) { + return callback(null, reply); + } + at.linkUsers(reply.content, function (err, str) { + if (err) { + return callback(err); + } + reply.content = str; + return callback(err, reply); + }); + }); + }); +}; + +/** + * 根据主题ID,获取回复列表 + * Callback: + * - err, 数据库异常 + * - replies, 回复列表 + * @param {String} id 主题ID + * @param {Function} callback 回调函数 + */ +exports.getRepliesByTopicId = function (id, cb) { + Reply.find({topic_id: id, deleted: false}, '', {sort: 'create_at'}, function (err, replies) { + if (err) { + return cb(err); + } + if (replies.length === 0) { + return cb(null, []); + } + + var proxy = new EventProxy(); + proxy.after('reply_find', replies.length, function () { + cb(null, replies); + }); + for (var j = 0; j < replies.length; j++) { + (function (i) { + var author_id = replies[i].author_id; + User.getUserById(author_id, function (err, author) { + if (err) { + return cb(err); + } + replies[i].author = author || { _id: '' }; + if (replies[i].content_is_html) { + return proxy.emit('reply_find'); + } + at.linkUsers(replies[i].content, function (err, str) { + if (err) { + return cb(err); + } + replies[i].content = str; + proxy.emit('reply_find'); + }); + }); + })(j); + } + }); +}; + +/** + * 创建并保存一条回复信息 + * @param {String} content 回复内容 + * @param {String} topicId 主题ID + * @param {String} authorId 回复作者 + * @param {String} [replyId] 回复ID,当二级回复时设定该值 + * @param {Function} callback 回调函数 + */ +exports.newAndSave = function (content, topicId, authorId, replyId, callback) { + if (typeof replyId === 'function') { + callback = replyId; + replyId = null; + } + var reply = new Reply(); + reply.content = content; + reply.topic_id = topicId; + reply.author_id = authorId; + + if (replyId) { + reply.reply_id = replyId; + } + reply.save(function (err) { + callback(err, reply); + }); +}; + +/** + * 根据topicId查询到最新的一条未删除回复 + * @param topicId 主题ID + * @param callback 回调函数 + */ +exports.getLastReplyByTopId = function (topicId, callback) { + Reply.find({topic_id: topicId, deleted: false}, '_id', {sort: {create_at : -1}, limit : 1}, callback); +}; + +exports.getRepliesByAuthorId = function (authorId, opt, callback) { + if (!callback) { + callback = opt; + opt = null; + } + Reply.find({author_id: authorId}, {}, opt, callback); +}; + +// 通过 author_id 获取回复总数 +exports.getCountByAuthorId = function (authorId, callback) { + Reply.count({author_id: authorId}, callback); +}; diff --git a/proxy/topic.js b/proxy/topic.js new file mode 100644 index 0000000000..bdcad967d1 --- /dev/null +++ b/proxy/topic.js @@ -0,0 +1,226 @@ +var EventProxy = require('eventproxy'); +var models = require('../models'); +var Topic = models.Topic; +var User = require('./user'); +var Reply = require('./reply'); +var tools = require('../common/tools'); +var at = require('../common/at'); +var _ = require('lodash'); + + +/** + * 根据主题ID获取主题 + * Callback: + * - err, 数据库错误 + * - topic, 主题 + * - author, 作者 + * - lastReply, 最后回复 + * @param {String} id 主题ID + * @param {Function} callback 回调函数 + */ +exports.getTopicById = function (id, callback) { + var proxy = new EventProxy(); + var events = ['topic', 'author', 'last_reply']; + proxy.assign(events, function (topic, author, last_reply) { + if (!author) { + return callback(null, null, null, null); + } + return callback(null, topic, author, last_reply); + }).fail(callback); + + Topic.findOne({_id: id}, proxy.done(function (topic) { + if (!topic) { + proxy.emit('topic', null); + proxy.emit('author', null); + proxy.emit('last_reply', null); + return; + } + proxy.emit('topic', topic); + + User.getUserById(topic.author_id, proxy.done('author')); + + if (topic.last_reply) { + Reply.getReplyById(topic.last_reply, proxy.done(function (last_reply) { + proxy.emit('last_reply', last_reply); + })); + } else { + proxy.emit('last_reply', null); + } + })); +}; + +/** + * 获取关键词能搜索到的主题数量 + * Callback: + * - err, 数据库错误 + * - count, 主题数量 + * @param {String} query 搜索关键词 + * @param {Function} callback 回调函数 + */ +exports.getCountByQuery = function (query, callback) { + Topic.count(query, callback); +}; + +/** + * 根据关键词,获取主题列表 + * Callback: + * - err, 数据库错误 + * - count, 主题列表 + * @param {String} query 搜索关键词 + * @param {Object} opt 搜索选项 + * @param {Function} callback 回调函数 + */ +exports.getTopicsByQuery = function (query, opt, callback) { + query.deleted = false; + Topic.find(query, {}, opt, function (err, topics) { + if (err) { + return callback(err); + } + if (topics.length === 0) { + return callback(null, []); + } + + var proxy = new EventProxy(); + proxy.after('topic_ready', topics.length, function () { + topics = _.compact(topics); // 删除不合规的 topic + return callback(null, topics); + }); + proxy.fail(callback); + + topics.forEach(function (topic, i) { + var ep = new EventProxy(); + ep.all('author', 'reply', function (author, reply) { + // 保证顺序 + // 作者可能已被删除 + if (author) { + topic.author = author; + topic.reply = reply; + } else { + topics[i] = null; + } + proxy.emit('topic_ready'); + }); + + User.getUserById(topic.author_id, ep.done('author')); + // 获取主题的最后回复 + Reply.getReplyById(topic.last_reply, ep.done('reply')); + }); + }); +}; + +// for sitemap +exports.getLimit5w = function (callback) { + Topic.find({deleted: false}, '_id', {limit: 50000, sort: '-create_at'}, callback); +}; + +/** + * 获取所有信息的主题 + * Callback: + * - err, 数据库异常 + * - message, 消息 + * - topic, 主题 + * - author, 主题作者 + * - replies, 主题的回复 + * @param {String} id 主题ID + * @param {Function} callback 回调函数 + */ +exports.getFullTopic = function (id, callback) { + var proxy = new EventProxy(); + var events = ['topic', 'author', 'replies']; + proxy + .assign(events, function (topic, author, replies) { + callback(null, '', topic, author, replies); + }) + .fail(callback); + + Topic.findOne({_id: id, deleted: false}, proxy.done(function (topic) { + if (!topic) { + proxy.unbind(); + return callback(null, '此话题不存在或已被删除。'); + } + at.linkUsers(topic.content, proxy.done('topic', function (str) { + topic.linkedContent = str; + return topic; + })); + + User.getUserById(topic.author_id, proxy.done(function (author) { + if (!author) { + proxy.unbind(); + return callback(null, '话题的作者丢了。'); + } + proxy.emit('author', author); + })); + + Reply.getRepliesByTopicId(topic._id, proxy.done('replies')); + })); +}; + +/** + * 更新主题的最后回复信息 + * @param {String} topicId 主题ID + * @param {String} replyId 回复ID + * @param {Function} callback 回调函数 + */ +exports.updateLastReply = function (topicId, replyId, callback) { + Topic.findOne({_id: topicId}, function (err, topic) { + if (err || !topic) { + return callback(err); + } + topic.last_reply = replyId; + topic.last_reply_at = new Date(); + topic.reply_count += 1; + topic.save(callback); + }); +}; + +/** + * 根据主题ID,查找一条主题 + * @param {String} id 主题ID + * @param {Function} callback 回调函数 + */ +exports.getTopic = function (id, callback) { + Topic.findOne({_id: id}, callback); +}; + +/** + * 将当前主题的回复计数减1,并且更新最后回复的用户,删除回复时用到 + * @param {String} id 主题ID + * @param {Function} callback 回调函数 + */ +exports.reduceCount = function (id, callback) { + Topic.findOne({_id: id}, function (err, topic) { + if (err) { + return callback(err); + } + + if (!topic) { + return callback(new Error('该主题不存在')); + } + topic.reply_count -= 1; + + Reply.getLastReplyByTopId(id, function (err, reply) { + if (err) { + return callback(err); + } + + if (reply.length !== 0) { + topic.last_reply = reply[0]._id; + } else { + topic.last_reply = null; + } + + topic.save(callback); + }); + + }); +}; + +exports.newAndSave = function (title, content, tab, authorId, callback) { + var topic = new Topic(); + topic.title = title; + topic.content = content; + topic.tab = tab; + topic.author_id = authorId; + + topic.save(callback); +}; diff --git a/proxy/topic_collect.js b/proxy/topic_collect.js new file mode 100644 index 0000000000..1d763242fd --- /dev/null +++ b/proxy/topic_collect.js @@ -0,0 +1,21 @@ +var TopicCollect = require('../models').TopicCollect; + +exports.getTopicCollect = function (userId, topicId, callback) { + TopicCollect.findOne({user_id: userId, topic_id: topicId}, callback); +}; + +exports.getTopicCollectsByUserId = function (userId, callback) { + TopicCollect.find({user_id: userId}, callback); +}; + +exports.newAndSave = function (userId, topicId, callback) { + var topic_collect = new TopicCollect(); + topic_collect.user_id = userId; + topic_collect.topic_id = topicId; + topic_collect.save(callback); +}; + +exports.remove = function (userId, topicId, callback) { + TopicCollect.remove({user_id: userId, topic_id: topicId}, callback); +}; + diff --git a/proxy/user.js b/proxy/user.js new file mode 100644 index 0000000000..805186ad6c --- /dev/null +++ b/proxy/user.js @@ -0,0 +1,118 @@ +var models = require('../models'); +var User = models.User; +var utility = require('utility'); +var uuid = require('node-uuid'); + +/** + * 根据用户名列表查找用户列表 + * Callback: + * - err, 数据库异常 + * - users, 用户列表 + * @param {Array} names 用户名列表 + * @param {Function} callback 回调函数 + */ +exports.getUsersByNames = function (names, callback) { + if (names.length === 0) { + return callback(null, []); + } + User.find({ loginname: { $in: names } }, callback); +}; + +/** + * 根据登录名查找用户 + * Callback: + * - err, 数据库异常 + * - user, 用户 + * @param {String} loginName 登录名 + * @param {Function} callback 回调函数 + */ +exports.getUserByLoginName = function (loginName, callback) { + User.findOne({'loginname': loginName}, callback); +}; + +/** + * 根据用户ID,查找用户 + * Callback: + * - err, 数据库异常 + * - user, 用户 + * @param {String} id 用户ID + * @param {Function} callback 回调函数 + */ +exports.getUserById = function (id, callback) { + if (!id) { + return callback(); + } + User.findOne({_id: id}, callback); +}; + +/** + * 根据邮箱,查找用户 + * Callback: + * - err, 数据库异常 + * - user, 用户 + * @param {String} email 邮箱地址 + * @param {Function} callback 回调函数 + */ +exports.getUserByMail = function (email, callback) { + User.findOne({email: email}, callback); +}; + +/** + * 根据用户ID列表,获取一组用户 + * Callback: + * - err, 数据库异常 + * - users, 用户列表 + * @param {Array} ids 用户ID列表 + * @param {Function} callback 回调函数 + */ +exports.getUsersByIds = function (ids, callback) { + User.find({'_id': {'$in': ids}}, callback); +}; + +/** + * 根据关键字,获取一组用户 + * Callback: + * - err, 数据库异常 + * - users, 用户列表 + * @param {String} query 关键字 + * @param {Object} opt 选项 + * @param {Function} callback 回调函数 + */ +exports.getUsersByQuery = function (query, opt, callback) { + User.find(query, '', opt, callback); +}; + +/** + * 根据查询条件,获取一个用户 + * Callback: + * - err, 数据库异常 + * - user, 用户 + * @param {String} name 用户名 + * @param {String} key 激活码 + * @param {Function} callback 回调函数 + */ +exports.getUserByNameAndKey = function (loginname, key, callback) { + User.findOne({loginname: loginname, retrieve_key: key}, callback); +}; + +exports.newAndSave = function (name, loginname, pass, email, avatar_url, active, callback) { + var user = new User(); + user.name = loginname; + user.loginname = loginname; + user.pass = pass; + user.email = email; + user.avatar = avatar_url; + user.active = active || false; + user.accessToken = uuid.v4(); + + user.save(callback); +}; + +var makeGravatar = function (email) { + return 'http://www.gravatar.com/avatar/' + utility.md5(email.toLowerCase()) + '?size=48'; +}; +exports.makeGravatar = makeGravatar; + +exports.getGravatar = function (user) { + return user.avatar || makeGravatar(user); +}; diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..fc0fb33f2611566614ff94f8c720bc2069680bf3 GIT binary patch literal 1150 zcmdUsEo=fo5QXOg3BeRX2-FpUz~QjyIt)le1*xs6Z3PmIMWT@y0v3a)!tvt}HeGf5UQYMo>BW;^-71SPYLs9D}PLwH-4>q z&-=WL>znJj`Hxxwjh?$|`}_CFA7bvY$M+7lnk-D<*4bm`4Lhj%2kIC20=>_Yz5`i^ jqen~w*uf_hAyOAk`TY>_pG4*v%qa(WHaU@?dCmO;8j7dV literal 0 HcmV?d00001 diff --git a/public/github-card.html b/public/github-card.html new file mode 100644 index 0000000000..a17180c1c4 --- /dev/null +++ b/public/github-card.html @@ -0,0 +1,5 @@ + + + diff --git a/public/images/cnode_icon_32.png b/public/images/cnode_icon_32.png new file mode 100644 index 0000000000000000000000000000000000000000..9e69485a35ddb9d3035a730a2610d00dc5b64215 GIT binary patch literal 2156 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 literal 0 HcmV?d00001 diff --git a/public/images/cnodejs.svg b/public/images/cnodejs.svg new file mode 100644 index 0000000000..756fa8ca8b --- /dev/null +++ b/public/images/cnodejs.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/public/images/cnodejs_light.svg b/public/images/cnodejs_light.svg new file mode 100644 index 0000000000..7642b406dc --- /dev/null +++ b/public/images/cnodejs_light.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + diff --git a/public/images/digitalocean.png b/public/images/digitalocean.png new file mode 100644 index 0000000000000000000000000000000000000000..cc11d228c3bbfeb1b02a157105faa284eb0ba514 GIT binary patch literal 9370 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 VH$+1IE(C4>$x13pREik}{SU;l!U6yQ literal 0 HcmV?d00001 diff --git a/public/images/iojs-logo-w150h50.png b/public/images/iojs-logo-w150h50.png new file mode 100644 index 0000000000000000000000000000000000000000..55f6a9a0475bf0aa6659da921ef0757e74a718ad GIT binary patch literal 3627 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 B7Bm0= literal 0 HcmV?d00001 diff --git a/public/images/logo.png b/public/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c8dcf1a948489dff42fb56ae27ade8e9856c87c4 GIT binary patch literal 4083 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 MQ#+G-Bd<&U0eCAYWdHyG literal 0 HcmV?d00001 diff --git a/public/images/logo_bak.png b/public/images/logo_bak.png new file mode 100644 index 0000000000000000000000000000000000000000..8a4009e5a7af7417cc0a86c50d24e475d2d527bd GIT binary patch literal 3863 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 literal 0 HcmV?d00001 diff --git a/public/images/phphub-logo.png b/public/images/phphub-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b42bd4dbece8c6c87cd55a57ad1371ccf0568197 GIT binary patch literal 14072 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�N!0cmyYi)@FG8}%I3?ay7TAmY**Tx z|3q;^t*^mby-*nZEdc;9?BQBDyP3diBUds9<7rn|NZ+x_5I zQ|bPC`v7^hB7;)_vur>j=gOnkDr98n;xH9?$q-&J()EljKFofslys#KMol}oC`hC} za$))}`XM~2V_jNEl*>VKMKOt=!P~l+tC6B#3VQ^s8^IqsL=wxk=mrdE|f0xN@gh5 zLP0^1rRSvAKXqb}aaGA90XaTu&NSM@muL*Mic5Srg9uxLkqZI*5yfboF*G!MD4H`^ z=d*e&SHNSK7@$kNvSG+bOd?y}E;BK?scKiHjbmdbos>#at1XnnEbLYCdtUf@pVJM$ z0NyMfCtp^nZS6K>nlggatg};~7CyFHyQss|&0T&g;DEtTsEaZ;j#rKnmFl%*IiQXN zT~MHEwNU9&ut+f}M2ga1NIfE5MlgaX=-e<6zs8r%Y!1M>S2jbtS7Mekq?X)d2o0Q0 eynKg3fgr#th1>b#s{Hp`G+9YSiE1&!p#KAXR;@7r literal 0 HcmV?d00001 diff --git a/public/images/qiniu.png b/public/images/qiniu.png new file mode 100644 index 0000000000000000000000000000000000000000..d1c4ea5c80966d9f3fedbbaa14a1bc2807f0fc1e GIT binary patch literal 8429 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 P00000NkvXXu0mjfm_29F literal 0 HcmV?d00001 diff --git a/public/images/ruby-china-20150529.png b/public/images/ruby-china-20150529.png new file mode 100644 index 0000000000000000000000000000000000000000..09f2a81bfc5ee1653f3666d5989ea8d3557f0c92 GIT binary patch literal 15734 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 UvjJN^Xa#_bgrazr=#O9j2X#{WMF0Q* literal 0 HcmV?d00001 diff --git a/public/images/ruby-china-logo2.png b/public/images/ruby-china-logo2.png new file mode 100644 index 0000000000000000000000000000000000000000..68132f2358de99051021a04b356c3b4998d3ccdc GIT binary patch literal 20294 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 B7G?kd literal 0 HcmV?d00001 diff --git a/public/img/glyphicons-halflings.png b/public/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643 GIT binary patch literal 12799 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 literal 0 HcmV?d00001 diff --git a/public/javascripts/main.js b/public/javascripts/main.js new file mode 100644 index 0000000000..a62d7da679 --- /dev/null +++ b/public/javascripts/main.js @@ -0,0 +1,41 @@ +$(document).ready(function () { + var $backtotop = $('#backtotop'); + var top = $(window).height() - $backtotop.height() - 200; + + function moveBacktotop() { + $backtotop.css({ top: top, right: 0}); + } + + $backtotop.click(function () { + $('html,body').animate({ scrollTop: 0 }); + return false; + }); + $(window).scroll(function () { + var windowHeight = $(window).scrollTop(); + if (windowHeight > 200) { + $backtotop.fadeIn(); + } else { + $backtotop.fadeOut(); + } + }); + + moveBacktotop(); + $(window).resize(moveBacktotop); + + $('.topic_content a,.reply_content a').attr('target', '_blank'); + + // pretty code + prettyPrint(); + + // data-loading-text="提交中" + $('.submit_btn').click(function () { + $(this).button('loading'); + }); + + // 广告的统计信息 + $('.sponsor_outlink').click(function () { + var $this = $(this); + var label = $this.data('label'); + ga('send', 'event', 'banner', 'click', label, 1.00, {'nonInteraction': 1}); + }); +}); diff --git a/public/javascripts/responsive.js b/public/javascripts/responsive.js new file mode 100644 index 0000000000..3a62769729 --- /dev/null +++ b/public/javascripts/responsive.js @@ -0,0 +1,70 @@ +$(document).ready(function () { + var $responsiveBtn = $('#responsive-sidebar-trigger'), + $sidebarMask = $('#sidebar-mask'), + $sidebar = $('#sidebar'), + $main = $('#main'), + winWidth = $(window).width(), + startX = 0, + startY = 0, + delta = { + x: 0, + y: 0 + }, + swipeThreshold = winWidth / 3, + toggleSideBar = function () { + var isShow = $responsiveBtn.data('is-show'), + mainHeight = $main.height(), + sidebarHeight = $sidebar.outerHeight(); + $sidebar.css({right: isShow ? -300 : 0}); + $responsiveBtn.data('is-show', !isShow); + if (!isShow && mainHeight < sidebarHeight) { + $main.height(sidebarHeight); + } + $sidebarMask[isShow ? 'fadeOut' : 'fadeIn']().height($('body').height()); + }, + touchstart = function (e) { + var touchs = e.targetTouches; + startX = +touchs[0].pageX; + startY = +touchs[0].pageY; + delta.x = delta.y = 0; + document.body.addEventListener('touchmove', touchmove, false); + document.body.addEventListener('touchend', touchend, false); + }, + touchmove = function (e) { + var touchs = e.changedTouches; + delta.x = +touchs[0].pageX - startX; + delta.y = +touchs[0].pageY - startY; + //当水平距离大于垂直距离时,才认为是用户想滑动打开右侧栏 + if (Math.abs(delta.x) > Math.abs(delta.y)) { + e.preventDefault(); + } + }, + touchend = function (e) { + var touchs = e.changedTouches, + isShow = $responsiveBtn.data('is-show'); + delta.x = +touchs[0].pageX - startX; + //右侧栏未显示&&用户touch点在屏幕右侧1/4区域内&&move距离大于阀值时,打开右侧栏 + if (!isShow && (startX > winWidth * 3 / 4) && Math.abs(delta.x) > swipeThreshold) { + $responsiveBtn.trigger('click'); + } + //右侧栏显示中&&用户touch点在屏幕左侧侧1/4区域内&&move距离大于阀值时,关闭右侧栏 + if (isShow && (startX < winWidth * 1 / 4) && Math.abs(delta.x) > swipeThreshold) { + $responsiveBtn.trigger('click'); + } + startX = startY = 0; + delta.x = delta.y = 0; + document.body.removeEventListener('touchmove', touchmove, false); + document.body.removeEventListener('touchend', touchend, false); + }; + + if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { + document.body.addEventListener('touchstart', touchstart); + } + + $responsiveBtn.on('click', toggleSideBar); + + $sidebarMask.on('click', function () { + $responsiveBtn.trigger('click'); + }); + +}); \ No newline at end of file diff --git a/public/libs/bootstrap/css/bootstrap-responsive.css b/public/libs/bootstrap/css/bootstrap-responsive.css new file mode 100644 index 0000000000..d1c0a86039 --- /dev/null +++ b/public/libs/bootstrap/css/bootstrap-responsive.css @@ -0,0 +1,1345 @@ +/*! + * Bootstrap Responsive v2.3.1 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +@-ms-viewport { + width: device-width; +} + +.hidden { + display: none; + visibility: hidden; +} + +.visible-phone { + display: none !important; +} + +.visible-tablet { + display: none !important; +} + +.hidden-desktop { + display: none !important; +} + +.visible-desktop { + display: inherit !important; +} + +@media (min-width: 768px) and (max-width: 979px) { + .hidden-desktop { + display: inherit !important; + } + + .visible-desktop { + display: none !important; + } + + .visible-tablet { + display: inherit !important; + } + + .hidden-tablet { + display: none !important; + } +} + +@media (max-width: 767px) { + .hidden-desktop { + display: inherit !important; + } + + .visible-desktop { + display: none !important; + } + + .visible-phone { + display: inherit !important; + } + + .hidden-phone { + display: none !important; + } +} + +.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: inherit !important; + } + + .hidden-print { + display: none !important; + } +} + +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1; + } + + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + + .row:after { + clear: both; + } + + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 30px; + } + + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 1170px; + } + + .span12 { + width: 1170px; + } + + .span11 { + width: 1070px; + } + + .span10 { + width: 970px; + } + + .span9 { + width: 870px; + } + + .span8 { + width: 770px; + } + + .span7 { + width: 670px; + } + + .span6 { + width: 570px; + } + + .span5 { + width: 470px; + } + + .span4 { + width: 370px; + } + + .span3 { + width: 270px; + } + + .span2 { + width: 170px; + } + + .span1 { + width: 70px; + } + + .offset12 { + margin-left: 1230px; + } + + .offset11 { + margin-left: 1130px; + } + + .offset10 { + margin-left: 1030px; + } + + .offset9 { + margin-left: 930px; + } + + .offset8 { + margin-left: 830px; + } + + .offset7 { + margin-left: 730px; + } + + .offset6 { + margin-left: 630px; + } + + .offset5 { + margin-left: 530px; + } + + .offset4 { + margin-left: 430px; + } + + .offset3 { + margin-left: 330px; + } + + .offset2 { + margin-left: 230px; + } + + .offset1 { + margin-left: 130px; + } + + .row-fluid { + width: 100%; + *zoom: 1; + } + + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + + .row-fluid:after { + clear: both; + } + + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.564102564102564%; + *margin-left: 2.5109110747408616%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.564102564102564%; + } + + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + + .row-fluid .span11 { + width: 91.45299145299145%; + *width: 91.39979996362975%; + } + + .row-fluid .span10 { + width: 82.90598290598291%; + *width: 82.8527914166212%; + } + + .row-fluid .span9 { + width: 74.35897435897436%; + *width: 74.30578286961266%; + } + + .row-fluid .span8 { + width: 65.81196581196582%; + *width: 65.75877432260411%; + } + + .row-fluid .span7 { + width: 57.26495726495726%; + *width: 57.21176577559556%; + } + + .row-fluid .span6 { + width: 48.717948717948715%; + *width: 48.664757228587014%; + } + + .row-fluid .span5 { + width: 40.17094017094017%; + *width: 40.11774868157847%; + } + + .row-fluid .span4 { + width: 31.623931623931625%; + *width: 31.570740134569924%; + } + + .row-fluid .span3 { + width: 23.076923076923077%; + *width: 23.023731587561375%; + } + + .row-fluid .span2 { + width: 14.52991452991453%; + *width: 14.476723040552828%; + } + + .row-fluid .span1 { + width: 5.982905982905983%; + *width: 5.929714493544281%; + } + + .row-fluid .offset12 { + margin-left: 105.12820512820512%; + *margin-left: 105.02182214948171%; + } + + .row-fluid .offset12:first-child { + margin-left: 102.56410256410257%; + *margin-left: 102.45771958537915%; + } + + .row-fluid .offset11 { + margin-left: 96.58119658119658%; + *margin-left: 96.47481360247316%; + } + + .row-fluid .offset11:first-child { + margin-left: 94.01709401709402%; + *margin-left: 93.91071103837061%; + } + + .row-fluid .offset10 { + margin-left: 88.03418803418803%; + *margin-left: 87.92780505546462%; + } + + .row-fluid .offset10:first-child { + margin-left: 85.47008547008548%; + *margin-left: 85.36370249136206%; + } + + .row-fluid .offset9 { + margin-left: 79.48717948717949%; + *margin-left: 79.38079650845607%; + } + + .row-fluid .offset9:first-child { + margin-left: 76.92307692307693%; + *margin-left: 76.81669394435352%; + } + + .row-fluid .offset8 { + margin-left: 70.94017094017094%; + *margin-left: 70.83378796144753%; + } + + .row-fluid .offset8:first-child { + margin-left: 68.37606837606839%; + *margin-left: 68.26968539734497%; + } + + .row-fluid .offset7 { + margin-left: 62.393162393162385%; + *margin-left: 62.28677941443899%; + } + + .row-fluid .offset7:first-child { + margin-left: 59.82905982905982%; + *margin-left: 59.72267685033642%; + } + + .row-fluid .offset6 { + margin-left: 53.84615384615384%; + *margin-left: 53.739770867430444%; + } + + .row-fluid .offset6:first-child { + margin-left: 51.28205128205128%; + *margin-left: 51.175668303327875%; + } + + .row-fluid .offset5 { + margin-left: 45.299145299145295%; + *margin-left: 45.1927623204219%; + } + + .row-fluid .offset5:first-child { + margin-left: 42.73504273504273%; + *margin-left: 42.62865975631933%; + } + + .row-fluid .offset4 { + margin-left: 36.75213675213675%; + *margin-left: 36.645753773413354%; + } + + .row-fluid .offset4:first-child { + margin-left: 34.18803418803419%; + *margin-left: 34.081651209310785%; + } + + .row-fluid .offset3 { + margin-left: 28.205128205128204%; + *margin-left: 28.0987452264048%; + } + + .row-fluid .offset3:first-child { + margin-left: 25.641025641025642%; + *margin-left: 25.53464266230224%; + } + + .row-fluid .offset2 { + margin-left: 19.65811965811966%; + *margin-left: 19.551736679396257%; + } + + .row-fluid .offset2:first-child { + margin-left: 17.094017094017094%; + *margin-left: 16.98763411529369%; + } + + .row-fluid .offset1 { + margin-left: 11.11111111111111%; + *margin-left: 11.004728132387708%; + } + + .row-fluid .offset1:first-child { + margin-left: 8.547008547008547%; + *margin-left: 8.440625568285142%; + } + + input, + textarea, + .uneditable-input { + margin-left: 0; + } + + .controls-row [class*="span"] + [class*="span"] { + margin-left: 30px; + } + + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 1156px; + } + + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 1056px; + } + + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 956px; + } + + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 856px; + } + + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 756px; + } + + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 656px; + } + + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 556px; + } + + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 456px; + } + + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 356px; + } + + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 256px; + } + + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 156px; + } + + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 56px; + } + + .thumbnails { + margin-left: -30px; + } + + .thumbnails > li { + margin-left: 30px; + } + + .row-fluid .thumbnails { + margin-left: 0; + } +} + +@media (min-width: 768px) and (max-width: 979px) { + .row { + margin-left: -20px; + *zoom: 1; + } + + .row:before, + .row:after { + display: table; + line-height: 0; + content: ""; + } + + .row:after { + clear: both; + } + + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; + } + + .container, + .navbar-static-top .container, + .navbar-fixed-top .container, + .navbar-fixed-bottom .container { + width: 724px; + } + + .span12 { + width: 724px; + } + + .span11 { + width: 662px; + } + + .span10 { + width: 600px; + } + + .span9 { + width: 538px; + } + + .span8 { + width: 476px; + } + + .span7 { + width: 414px; + } + + .span6 { + width: 352px; + } + + .span5 { + width: 290px; + } + + .span4 { + width: 228px; + } + + .span3 { + width: 166px; + } + + .span2 { + width: 104px; + } + + .span1 { + width: 42px; + } + + .offset12 { + margin-left: 764px; + } + + .offset11 { + margin-left: 702px; + } + + .offset10 { + margin-left: 640px; + } + + .offset9 { + margin-left: 578px; + } + + .offset8 { + margin-left: 516px; + } + + .offset7 { + margin-left: 454px; + } + + .offset6 { + margin-left: 392px; + } + + .offset5 { + margin-left: 330px; + } + + .offset4 { + margin-left: 268px; + } + + .offset3 { + margin-left: 206px; + } + + .offset2 { + margin-left: 144px; + } + + .offset1 { + margin-left: 82px; + } + + .row-fluid { + width: 100%; + *zoom: 1; + } + + .row-fluid:before, + .row-fluid:after { + display: table; + line-height: 0; + content: ""; + } + + .row-fluid:after { + clear: both; + } + + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.7624309392265194%; + *margin-left: 2.709239449864817%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + + .row-fluid [class*="span"]:first-child { + margin-left: 0; + } + + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.7624309392265194%; + } + + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; + } + + .row-fluid .span11 { + width: 91.43646408839778%; + *width: 91.38327259903608%; + } + + .row-fluid .span10 { + width: 82.87292817679558%; + *width: 82.81973668743387%; + } + + .row-fluid .span9 { + width: 74.30939226519337%; + *width: 74.25620077583166%; + } + + .row-fluid .span8 { + width: 65.74585635359117%; + *width: 65.69266486422946%; + } + + .row-fluid .span7 { + width: 57.18232044198895%; + *width: 57.12912895262725%; + } + + .row-fluid .span6 { + width: 48.61878453038674%; + *width: 48.56559304102504%; + } + + .row-fluid .span5 { + width: 40.05524861878453%; + *width: 40.00205712942283%; + } + + .row-fluid .span4 { + width: 31.491712707182323%; + *width: 31.43852121782062%; + } + + .row-fluid .span3 { + width: 22.92817679558011%; + *width: 22.87498530621841%; + } + + .row-fluid .span2 { + width: 14.3646408839779%; + *width: 14.311449394616199%; + } + + .row-fluid .span1 { + width: 5.801104972375691%; + *width: 5.747913483013988%; + } + + .row-fluid .offset12 { + margin-left: 105.52486187845304%; + *margin-left: 105.41847889972962%; + } + + .row-fluid .offset12:first-child { + margin-left: 102.76243093922652%; + *margin-left: 102.6560479605031%; + } + + .row-fluid .offset11 { + margin-left: 96.96132596685082%; + *margin-left: 96.8549429881274%; + } + + .row-fluid .offset11:first-child { + margin-left: 94.1988950276243%; + *margin-left: 94.09251204890089%; + } + + .row-fluid .offset10 { + margin-left: 88.39779005524862%; + *margin-left: 88.2914070765252%; + } + + .row-fluid .offset10:first-child { + margin-left: 85.6353591160221%; + *margin-left: 85.52897613729868%; + } + + .row-fluid .offset9 { + margin-left: 79.8342541436464%; + *margin-left: 79.72787116492299%; + } + + .row-fluid .offset9:first-child { + margin-left: 77.07182320441989%; + *margin-left: 76.96544022569647%; + } + + .row-fluid .offset8 { + margin-left: 71.2707182320442%; + *margin-left: 71.16433525332079%; + } + + .row-fluid .offset8:first-child { + margin-left: 68.50828729281768%; + *margin-left: 68.40190431409427%; + } + + .row-fluid .offset7 { + margin-left: 62.70718232044199%; + *margin-left: 62.600799341718584%; + } + + .row-fluid .offset7:first-child { + margin-left: 59.94475138121547%; + *margin-left: 59.838368402492065%; + } + + .row-fluid .offset6 { + margin-left: 54.14364640883978%; + *margin-left: 54.037263430116376%; + } + + .row-fluid .offset6:first-child { + margin-left: 51.38121546961326%; + *margin-left: 51.27483249088986%; + } + + .row-fluid .offset5 { + margin-left: 45.58011049723757%; + *margin-left: 45.47372751851417%; + } + + .row-fluid .offset5:first-child { + margin-left: 42.81767955801105%; + *margin-left: 42.71129657928765%; + } + + .row-fluid .offset4 { + margin-left: 37.01657458563536%; + *margin-left: 36.91019160691196%; + } + + .row-fluid .offset4:first-child { + margin-left: 34.25414364640884%; + *margin-left: 34.14776066768544%; + } + + .row-fluid .offset3 { + margin-left: 28.45303867403315%; + *margin-left: 28.346655695309746%; + } + + .row-fluid .offset3:first-child { + margin-left: 25.69060773480663%; + *margin-left: 25.584224756083227%; + } + + .row-fluid .offset2 { + margin-left: 19.88950276243094%; + *margin-left: 19.783119783707537%; + } + + .row-fluid .offset2:first-child { + margin-left: 17.12707182320442%; + *margin-left: 17.02068884448102%; + } + + .row-fluid .offset1 { + margin-left: 11.32596685082873%; + *margin-left: 11.219583872105325%; + } + + .row-fluid .offset1:first-child { + margin-left: 8.56353591160221%; + *margin-left: 8.457152932878806%; + } + + input, + textarea, + .uneditable-input { + margin-left: 0; + } + + .controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; + } + + input.span12, + textarea.span12, + .uneditable-input.span12 { + width: 710px; + } + + input.span11, + textarea.span11, + .uneditable-input.span11 { + width: 648px; + } + + input.span10, + textarea.span10, + .uneditable-input.span10 { + width: 586px; + } + + input.span9, + textarea.span9, + .uneditable-input.span9 { + width: 524px; + } + + input.span8, + textarea.span8, + .uneditable-input.span8 { + width: 462px; + } + + input.span7, + textarea.span7, + .uneditable-input.span7 { + width: 400px; + } + + input.span6, + textarea.span6, + .uneditable-input.span6 { + width: 338px; + } + + input.span5, + textarea.span5, + .uneditable-input.span5 { + width: 276px; + } + + input.span4, + textarea.span4, + .uneditable-input.span4 { + width: 214px; + } + + input.span3, + textarea.span3, + .uneditable-input.span3 { + width: 152px; + } + + input.span2, + textarea.span2, + .uneditable-input.span2 { + width: 90px; + } + + input.span1, + textarea.span1, + .uneditable-input.span1 { + width: 28px; + } +} + +@media (max-width: 767px) { + body { + padding-right: 20px; + padding-left: 20px; + } + + .navbar-fixed-top, + .navbar-fixed-bottom, + .navbar-static-top { + margin-right: -20px; + margin-left: -20px; + } + + .container-fluid { + padding: 0; + } + + .dl-horizontal dt { + float: none; + width: auto; + clear: none; + text-align: left; + } + + .dl-horizontal dd { + margin-left: 0; + } + + .container { + width: auto; + } + + .row-fluid { + width: 100%; + } + + .row, + .thumbnails { + margin-left: 0; + } + + .thumbnails > li { + float: none; + margin-left: 0; + } + + [class*="span"], + .uneditable-input[class*="span"], + .row-fluid [class*="span"] { + display: block; + float: none; + width: 100%; + margin-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + + .span12, + .row-fluid .span12 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + + .row-fluid [class*="offset"]:first-child { + margin-left: 0; + } + + .input-large, + .input-xlarge, + .input-xxlarge, + input[class*="span"], + select[class*="span"], + textarea[class*="span"], + .uneditable-input { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + + .input-prepend input, + .input-append input, + .input-prepend input[class*="span"], + .input-append input[class*="span"] { + display: inline-block; + width: auto; + } + + .controls-row [class*="span"] + [class*="span"] { + margin-left: 0; + } + + .modal { + position: fixed; + top: 20px; + right: 20px; + left: 20px; + width: auto; + margin: 0; + } + + .modal.fade { + top: -100px; + } + + .modal.fade.in { + top: 20px; + } +} + +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0); + } + + .page-header h1 small { + display: block; + line-height: 20px; + } + + input[type="checkbox"], + input[type="radio"] { + border: 1px solid #ccc; + } + + .form-horizontal .control-label { + float: none; + width: auto; + padding-top: 0; + text-align: left; + } + + .form-horizontal .controls { + margin-left: 0; + } + + .form-horizontal .control-list { + padding-top: 0; + } + + .form-horizontal .form-actions { + padding-right: 10px; + padding-left: 10px; + } + + .media .pull-left, + .media .pull-right { + display: block; + float: none; + margin-bottom: 10px; + } + + .media-object { + margin-right: 0; + margin-left: 0; + } + + .modal { + top: 10px; + right: 10px; + left: 10px; + } + + .modal-header .close { + padding: 10px; + margin: -10px; + } + + .carousel-caption { + position: static; + } +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } + + .navbar-fixed-top, + .navbar-fixed-bottom { + position: static; + } + + .navbar-fixed-top { + margin-bottom: 20px; + } + + .navbar-fixed-bottom { + margin-top: 20px; + } + + .navbar-fixed-top .navbar-inner, + .navbar-fixed-bottom .navbar-inner { + padding: 5px; + } + + .navbar .container { + width: auto; + padding: 0; + } + + .navbar .brand { + padding-right: 10px; + padding-left: 10px; + margin: 0 0 0 -5px; + } + + .nav-collapse { + clear: both; + } + + .nav-collapse .nav { + float: none; + margin: 0 0 10px; + } + + .nav-collapse .nav > li { + float: none; + } + + .nav-collapse .nav > li > a { + margin-bottom: 2px; + } + + .nav-collapse .nav > .divider-vertical { + display: none; + } + + .nav-collapse .nav .nav-header { + color: #777777; + text-shadow: none; + } + + .nav-collapse .nav > li > a, + .nav-collapse .dropdown-menu a { + padding: 9px 15px; + font-weight: bold; + color: #777777; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + } + + .nav-collapse .btn { + padding: 4px 10px 4px; + font-weight: normal; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + } + + .nav-collapse .dropdown-menu li + li a { + margin-bottom: 2px; + } + + .nav-collapse .nav > li > a:hover, + .nav-collapse .nav > li > a:focus, + .nav-collapse .dropdown-menu a:hover, + .nav-collapse .dropdown-menu a:focus { + background-color: #f2f2f2; + } + + .navbar-inverse .nav-collapse .nav > li > a, + .navbar-inverse .nav-collapse .dropdown-menu a { + color: #999999; + } + + .navbar-inverse .nav-collapse .nav > li > a:hover, + .navbar-inverse .nav-collapse .nav > li > a:focus, + .navbar-inverse .nav-collapse .dropdown-menu a:hover, + .navbar-inverse .nav-collapse .dropdown-menu a:focus { + background-color: #111111; + } + + .nav-collapse.in .btn-group { + padding: 0; + margin-top: 5px; + } + + .nav-collapse .dropdown-menu { + position: static; + top: auto; + left: auto; + display: none; + float: none; + max-width: none; + padding: 0; + margin: 0 15px; + background-color: transparent; + border: none; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + } + + .nav-collapse .open > .dropdown-menu { + display: block; + } + + .nav-collapse .dropdown-menu:before, + .nav-collapse .dropdown-menu:after { + display: none; + } + + .nav-collapse .dropdown-menu .divider { + display: none; + } + + .nav-collapse .nav > li > .dropdown-menu:before, + .nav-collapse .nav > li > .dropdown-menu:after { + display: none; + } + + .nav-collapse .navbar-form, + .nav-collapse .navbar-search { + float: none; + padding: 10px 15px; + margin: 10px 0; + border-top: 1px solid #f2f2f2; + border-bottom: 1px solid #f2f2f2; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + } + + .navbar-inverse .nav-collapse .navbar-form, + .navbar-inverse .nav-collapse .navbar-search { + border-top-color: #111111; + border-bottom-color: #111111; + } + + .navbar .nav-collapse .nav.pull-right { + float: none; + margin-left: 0; + } + + .nav-collapse, + .nav-collapse.collapse { + height: 0; + overflow: hidden; + } + + .navbar .btn-navbar { + display: block; + } + + .navbar-static .navbar-inner { + padding-right: 10px; + padding-left: 10px; + } +} + +@media (min-width: 980px) { + .nav-collapse.collapse { + height: auto !important; + overflow: visible !important; + } +} diff --git a/public/libs/bootstrap/css/bootstrap-responsive.min.css b/public/libs/bootstrap/css/bootstrap-responsive.min.css new file mode 100644 index 0000000000..1f415d0007 --- /dev/null +++ b/public/libs/bootstrap/css/bootstrap-responsive.min.css @@ -0,0 +1,1249 @@ +/*! + * Bootstrap Responsive v2.3.1 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ +.clearfix { + *zoom: 1 +} + +.clearfix:before, .clearfix:after { + display: table; + line-height: 0; + content: "" +} + +.clearfix:after { + clear: both +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0 +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +@-ms-viewport { + width: device-width +} + +.hidden { + display: none; + visibility: hidden +} + +.visible-phone { + display: none !important +} + +.visible-tablet { + display: none !important +} + +.hidden-desktop { + display: none !important +} + +.visible-desktop { + display: inherit !important +} + +@media (min-width: 768px) and (max-width: 979px) { + .hidden-desktop { + display: inherit !important + } + + .visible-desktop { + display: none !important + } + + .visible-tablet { + display: inherit !important + } + + .hidden-tablet { + display: none !important + } +} + +@media (max-width: 767px) { + .hidden-desktop { + display: inherit !important + } + + .visible-desktop { + display: none !important + } + + .visible-phone { + display: inherit !important + } + + .hidden-phone { + display: none !important + } +} + +.visible-print { + display: none !important +} + +@media print { + .visible-print { + display: inherit !important + } + + .hidden-print { + display: none !important + } +} + +@media (min-width: 1200px) { + .row { + margin-left: -30px; + *zoom: 1 + } + + .row:before, .row:after { + display: table; + line-height: 0; + content: "" + } + + .row:after { + clear: both + } + + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 30px + } + + .container, .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { + width: 1170px + } + + .span12 { + width: 1170px + } + + .span11 { + width: 1070px + } + + .span10 { + width: 970px + } + + .span9 { + width: 870px + } + + .span8 { + width: 770px + } + + .span7 { + width: 670px + } + + .span6 { + width: 570px + } + + .span5 { + width: 470px + } + + .span4 { + width: 370px + } + + .span3 { + width: 270px + } + + .span2 { + width: 170px + } + + .span1 { + width: 70px + } + + .offset12 { + margin-left: 1230px + } + + .offset11 { + margin-left: 1130px + } + + .offset10 { + margin-left: 1030px + } + + .offset9 { + margin-left: 930px + } + + .offset8 { + margin-left: 830px + } + + .offset7 { + margin-left: 730px + } + + .offset6 { + margin-left: 630px + } + + .offset5 { + margin-left: 530px + } + + .offset4 { + margin-left: 430px + } + + .offset3 { + margin-left: 330px + } + + .offset2 { + margin-left: 230px + } + + .offset1 { + margin-left: 130px + } + + .row-fluid { + width: 100%; + *zoom: 1 + } + + .row-fluid:before, .row-fluid:after { + display: table; + line-height: 0; + content: "" + } + + .row-fluid:after { + clear: both + } + + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.564102564102564%; + *margin-left: 2.5109110747408616%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box + } + + .row-fluid [class*="span"]:first-child { + margin-left: 0 + } + + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.564102564102564% + } + + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829% + } + + .row-fluid .span11 { + width: 91.45299145299145%; + *width: 91.39979996362975% + } + + .row-fluid .span10 { + width: 82.90598290598291%; + *width: 82.8527914166212% + } + + .row-fluid .span9 { + width: 74.35897435897436%; + *width: 74.30578286961266% + } + + .row-fluid .span8 { + width: 65.81196581196582%; + *width: 65.75877432260411% + } + + .row-fluid .span7 { + width: 57.26495726495726%; + *width: 57.21176577559556% + } + + .row-fluid .span6 { + width: 48.717948717948715%; + *width: 48.664757228587014% + } + + .row-fluid .span5 { + width: 40.17094017094017%; + *width: 40.11774868157847% + } + + .row-fluid .span4 { + width: 31.623931623931625%; + *width: 31.570740134569924% + } + + .row-fluid .span3 { + width: 23.076923076923077%; + *width: 23.023731587561375% + } + + .row-fluid .span2 { + width: 14.52991452991453%; + *width: 14.476723040552828% + } + + .row-fluid .span1 { + width: 5.982905982905983%; + *width: 5.929714493544281% + } + + .row-fluid .offset12 { + margin-left: 105.12820512820512%; + *margin-left: 105.02182214948171% + } + + .row-fluid .offset12:first-child { + margin-left: 102.56410256410257%; + *margin-left: 102.45771958537915% + } + + .row-fluid .offset11 { + margin-left: 96.58119658119658%; + *margin-left: 96.47481360247316% + } + + .row-fluid .offset11:first-child { + margin-left: 94.01709401709402%; + *margin-left: 93.91071103837061% + } + + .row-fluid .offset10 { + margin-left: 88.03418803418803%; + *margin-left: 87.92780505546462% + } + + .row-fluid .offset10:first-child { + margin-left: 85.47008547008548%; + *margin-left: 85.36370249136206% + } + + .row-fluid .offset9 { + margin-left: 79.48717948717949%; + *margin-left: 79.38079650845607% + } + + .row-fluid .offset9:first-child { + margin-left: 76.92307692307693%; + *margin-left: 76.81669394435352% + } + + .row-fluid .offset8 { + margin-left: 70.94017094017094%; + *margin-left: 70.83378796144753% + } + + .row-fluid .offset8:first-child { + margin-left: 68.37606837606839%; + *margin-left: 68.26968539734497% + } + + .row-fluid .offset7 { + margin-left: 62.393162393162385%; + *margin-left: 62.28677941443899% + } + + .row-fluid .offset7:first-child { + margin-left: 59.82905982905982%; + *margin-left: 59.72267685033642% + } + + .row-fluid .offset6 { + margin-left: 53.84615384615384%; + *margin-left: 53.739770867430444% + } + + .row-fluid .offset6:first-child { + margin-left: 51.28205128205128%; + *margin-left: 51.175668303327875% + } + + .row-fluid .offset5 { + margin-left: 45.299145299145295%; + *margin-left: 45.1927623204219% + } + + .row-fluid .offset5:first-child { + margin-left: 42.73504273504273%; + *margin-left: 42.62865975631933% + } + + .row-fluid .offset4 { + margin-left: 36.75213675213675%; + *margin-left: 36.645753773413354% + } + + .row-fluid .offset4:first-child { + margin-left: 34.18803418803419%; + *margin-left: 34.081651209310785% + } + + .row-fluid .offset3 { + margin-left: 28.205128205128204%; + *margin-left: 28.0987452264048% + } + + .row-fluid .offset3:first-child { + margin-left: 25.641025641025642%; + *margin-left: 25.53464266230224% + } + + .row-fluid .offset2 { + margin-left: 19.65811965811966%; + *margin-left: 19.551736679396257% + } + + .row-fluid .offset2:first-child { + margin-left: 17.094017094017094%; + *margin-left: 16.98763411529369% + } + + .row-fluid .offset1 { + margin-left: 11.11111111111111%; + *margin-left: 11.004728132387708% + } + + .row-fluid .offset1:first-child { + margin-left: 8.547008547008547%; + *margin-left: 8.440625568285142% + } + + input, textarea, .uneditable-input { + margin-left: 0 + } + + .controls-row [class*="span"] + [class*="span"] { + margin-left: 30px + } + + input.span12, textarea.span12, .uneditable-input.span12 { + width: 1156px + } + + input.span11, textarea.span11, .uneditable-input.span11 { + width: 1056px + } + + input.span10, textarea.span10, .uneditable-input.span10 { + width: 956px + } + + input.span9, textarea.span9, .uneditable-input.span9 { + width: 856px + } + + input.span8, textarea.span8, .uneditable-input.span8 { + width: 756px + } + + input.span7, textarea.span7, .uneditable-input.span7 { + width: 656px + } + + input.span6, textarea.span6, .uneditable-input.span6 { + width: 556px + } + + input.span5, textarea.span5, .uneditable-input.span5 { + width: 456px + } + + input.span4, textarea.span4, .uneditable-input.span4 { + width: 356px + } + + input.span3, textarea.span3, .uneditable-input.span3 { + width: 256px + } + + input.span2, textarea.span2, .uneditable-input.span2 { + width: 156px + } + + input.span1, textarea.span1, .uneditable-input.span1 { + width: 56px + } + + .thumbnails { + margin-left: -30px + } + + .thumbnails > li { + margin-left: 30px + } + + .row-fluid .thumbnails { + margin-left: 0 + } +} + +@media (min-width: 768px) and (max-width: 979px) { + .row { + margin-left: -20px; + *zoom: 1 + } + + .row:before, .row:after { + display: table; + line-height: 0; + content: "" + } + + .row:after { + clear: both + } + + [class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px + } + + .container, .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { + width: 724px + } + + .span12 { + width: 724px + } + + .span11 { + width: 662px + } + + .span10 { + width: 600px + } + + .span9 { + width: 538px + } + + .span8 { + width: 476px + } + + .span7 { + width: 414px + } + + .span6 { + width: 352px + } + + .span5 { + width: 290px + } + + .span4 { + width: 228px + } + + .span3 { + width: 166px + } + + .span2 { + width: 104px + } + + .span1 { + width: 42px + } + + .offset12 { + margin-left: 764px + } + + .offset11 { + margin-left: 702px + } + + .offset10 { + margin-left: 640px + } + + .offset9 { + margin-left: 578px + } + + .offset8 { + margin-left: 516px + } + + .offset7 { + margin-left: 454px + } + + .offset6 { + margin-left: 392px + } + + .offset5 { + margin-left: 330px + } + + .offset4 { + margin-left: 268px + } + + .offset3 { + margin-left: 206px + } + + .offset2 { + margin-left: 144px + } + + .offset1 { + margin-left: 82px + } + + .row-fluid { + width: 100%; + *zoom: 1 + } + + .row-fluid:before, .row-fluid:after { + display: table; + line-height: 0; + content: "" + } + + .row-fluid:after { + clear: both + } + + .row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.7624309392265194%; + *margin-left: 2.709239449864817%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box + } + + .row-fluid [class*="span"]:first-child { + margin-left: 0 + } + + .row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.7624309392265194% + } + + .row-fluid .span12 { + width: 100%; + *width: 99.94680851063829% + } + + .row-fluid .span11 { + width: 91.43646408839778%; + *width: 91.38327259903608% + } + + .row-fluid .span10 { + width: 82.87292817679558%; + *width: 82.81973668743387% + } + + .row-fluid .span9 { + width: 74.30939226519337%; + *width: 74.25620077583166% + } + + .row-fluid .span8 { + width: 65.74585635359117%; + *width: 65.69266486422946% + } + + .row-fluid .span7 { + width: 57.18232044198895%; + *width: 57.12912895262725% + } + + .row-fluid .span6 { + width: 48.61878453038674%; + *width: 48.56559304102504% + } + + .row-fluid .span5 { + width: 40.05524861878453%; + *width: 40.00205712942283% + } + + .row-fluid .span4 { + width: 31.491712707182323%; + *width: 31.43852121782062% + } + + .row-fluid .span3 { + width: 22.92817679558011%; + *width: 22.87498530621841% + } + + .row-fluid .span2 { + width: 14.3646408839779%; + *width: 14.311449394616199% + } + + .row-fluid .span1 { + width: 5.801104972375691%; + *width: 5.747913483013988% + } + + .row-fluid .offset12 { + margin-left: 105.52486187845304%; + *margin-left: 105.41847889972962% + } + + .row-fluid .offset12:first-child { + margin-left: 102.76243093922652%; + *margin-left: 102.6560479605031% + } + + .row-fluid .offset11 { + margin-left: 96.96132596685082%; + *margin-left: 96.8549429881274% + } + + .row-fluid .offset11:first-child { + margin-left: 94.1988950276243%; + *margin-left: 94.09251204890089% + } + + .row-fluid .offset10 { + margin-left: 88.39779005524862%; + *margin-left: 88.2914070765252% + } + + .row-fluid .offset10:first-child { + margin-left: 85.6353591160221%; + *margin-left: 85.52897613729868% + } + + .row-fluid .offset9 { + margin-left: 79.8342541436464%; + *margin-left: 79.72787116492299% + } + + .row-fluid .offset9:first-child { + margin-left: 77.07182320441989%; + *margin-left: 76.96544022569647% + } + + .row-fluid .offset8 { + margin-left: 71.2707182320442%; + *margin-left: 71.16433525332079% + } + + .row-fluid .offset8:first-child { + margin-left: 68.50828729281768%; + *margin-left: 68.40190431409427% + } + + .row-fluid .offset7 { + margin-left: 62.70718232044199%; + *margin-left: 62.600799341718584% + } + + .row-fluid .offset7:first-child { + margin-left: 59.94475138121547%; + *margin-left: 59.838368402492065% + } + + .row-fluid .offset6 { + margin-left: 54.14364640883978%; + *margin-left: 54.037263430116376% + } + + .row-fluid .offset6:first-child { + margin-left: 51.38121546961326%; + *margin-left: 51.27483249088986% + } + + .row-fluid .offset5 { + margin-left: 45.58011049723757%; + *margin-left: 45.47372751851417% + } + + .row-fluid .offset5:first-child { + margin-left: 42.81767955801105%; + *margin-left: 42.71129657928765% + } + + .row-fluid .offset4 { + margin-left: 37.01657458563536%; + *margin-left: 36.91019160691196% + } + + .row-fluid .offset4:first-child { + margin-left: 34.25414364640884%; + *margin-left: 34.14776066768544% + } + + .row-fluid .offset3 { + margin-left: 28.45303867403315%; + *margin-left: 28.346655695309746% + } + + .row-fluid .offset3:first-child { + margin-left: 25.69060773480663%; + *margin-left: 25.584224756083227% + } + + .row-fluid .offset2 { + margin-left: 19.88950276243094%; + *margin-left: 19.783119783707537% + } + + .row-fluid .offset2:first-child { + margin-left: 17.12707182320442%; + *margin-left: 17.02068884448102% + } + + .row-fluid .offset1 { + margin-left: 11.32596685082873%; + *margin-left: 11.219583872105325% + } + + .row-fluid .offset1:first-child { + margin-left: 8.56353591160221%; + *margin-left: 8.457152932878806% + } + + input, textarea, .uneditable-input { + margin-left: 0 + } + + .controls-row [class*="span"] + [class*="span"] { + margin-left: 20px + } + + input.span12, textarea.span12, .uneditable-input.span12 { + width: 710px + } + + input.span11, textarea.span11, .uneditable-input.span11 { + width: 648px + } + + input.span10, textarea.span10, .uneditable-input.span10 { + width: 586px + } + + input.span9, textarea.span9, .uneditable-input.span9 { + width: 524px + } + + input.span8, textarea.span8, .uneditable-input.span8 { + width: 462px + } + + input.span7, textarea.span7, .uneditable-input.span7 { + width: 400px + } + + input.span6, textarea.span6, .uneditable-input.span6 { + width: 338px + } + + input.span5, textarea.span5, .uneditable-input.span5 { + width: 276px + } + + input.span4, textarea.span4, .uneditable-input.span4 { + width: 214px + } + + input.span3, textarea.span3, .uneditable-input.span3 { + width: 152px + } + + input.span2, textarea.span2, .uneditable-input.span2 { + width: 90px + } + + input.span1, textarea.span1, .uneditable-input.span1 { + width: 28px + } +} + +@media (max-width: 767px) { + body { + padding-right: 20px; + padding-left: 20px + } + + .navbar-fixed-top, .navbar-fixed-bottom, .navbar-static-top { + margin-right: -20px; + margin-left: -20px + } + + .container-fluid { + padding: 0 + } + + .dl-horizontal dt { + float: none; + width: auto; + clear: none; + text-align: left + } + + .dl-horizontal dd { + margin-left: 0 + } + + .container { + width: auto + } + + .row-fluid { + width: 100% + } + + .row, .thumbnails { + margin-left: 0 + } + + .thumbnails > li { + float: none; + margin-left: 0 + } + + [class*="span"], .uneditable-input[class*="span"], .row-fluid [class*="span"] { + display: block; + float: none; + width: 100%; + margin-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box + } + + .span12, .row-fluid .span12 { + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box + } + + .row-fluid [class*="offset"]:first-child { + margin-left: 0 + } + + .input-large, .input-xlarge, .input-xxlarge, input[class*="span"], select[class*="span"], textarea[class*="span"], .uneditable-input { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box + } + + .input-prepend input, .input-append input, .input-prepend input[class*="span"], .input-append input[class*="span"] { + display: inline-block; + width: auto + } + + .controls-row [class*="span"] + [class*="span"] { + margin-left: 0 + } + + .modal { + position: fixed; + top: 20px; + right: 20px; + left: 20px; + width: auto; + margin: 0 + } + + .modal.fade { + top: -100px + } + + .modal.fade.in { + top: 20px + } +} + +@media (max-width: 480px) { + .nav-collapse { + -webkit-transform: translate3d(0, 0, 0) + } + + .page-header h1 small { + display: block; + line-height: 20px + } + + input[type="checkbox"], input[type="radio"] { + border: 1px solid #ccc + } + + .form-horizontal .control-label { + float: none; + width: auto; + padding-top: 0; + text-align: left + } + + .form-horizontal .controls { + margin-left: 0 + } + + .form-horizontal .control-list { + padding-top: 0 + } + + .form-horizontal .form-actions { + padding-right: 10px; + padding-left: 10px + } + + .media .pull-left, .media .pull-right { + display: block; + float: none; + margin-bottom: 10px + } + + .media-object { + margin-right: 0; + margin-left: 0 + } + + .modal { + top: 10px; + right: 10px; + left: 10px + } + + .modal-header .close { + padding: 10px; + margin: -10px + } + + .carousel-caption { + position: static + } +} + +@media (max-width: 979px) { + body { + padding-top: 0 + } + + .navbar-fixed-top, .navbar-fixed-bottom { + position: static + } + + .navbar-fixed-top { + margin-bottom: 20px + } + + .navbar-fixed-bottom { + margin-top: 20px + } + + .navbar-fixed-top .navbar-inner, .navbar-fixed-bottom .navbar-inner { + padding: 5px + } + + .navbar .container { + width: auto; + padding: 0 + } + + .navbar .brand { + padding-right: 10px; + padding-left: 10px; + margin: 0 0 0 -5px + } + + .nav-collapse { + clear: both + } + + .nav-collapse .nav { + float: none; + margin: 0 0 10px + } + + .nav-collapse .nav > li { + float: none + } + + .nav-collapse .nav > li > a { + margin-bottom: 2px + } + + .nav-collapse .nav > .divider-vertical { + display: none + } + + .nav-collapse .nav .nav-header { + color: #777; + text-shadow: none + } + + .nav-collapse .nav > li > a, .nav-collapse .dropdown-menu a { + padding: 9px 15px; + font-weight: bold; + color: #777; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px + } + + .nav-collapse .btn { + padding: 4px 10px 4px; + font-weight: normal; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px + } + + .nav-collapse .dropdown-menu li + li a { + margin-bottom: 2px + } + + .nav-collapse .nav > li > a:hover, .nav-collapse .nav > li > a:focus, .nav-collapse .dropdown-menu a:hover, .nav-collapse .dropdown-menu a:focus { + background-color: #f2f2f2 + } + + .navbar-inverse .nav-collapse .nav > li > a, .navbar-inverse .nav-collapse .dropdown-menu a { + color: #999 + } + + .navbar-inverse .nav-collapse .nav > li > a:hover, .navbar-inverse .nav-collapse .nav > li > a:focus, .navbar-inverse .nav-collapse .dropdown-menu a:hover, .navbar-inverse .nav-collapse .dropdown-menu a:focus { + background-color: #111 + } + + .nav-collapse.in .btn-group { + padding: 0; + margin-top: 5px + } + + .nav-collapse .dropdown-menu { + position: static; + top: auto; + left: auto; + display: none; + float: none; + max-width: none; + padding: 0; + margin: 0 15px; + background-color: transparent; + border: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none + } + + .nav-collapse .open > .dropdown-menu { + display: block + } + + .nav-collapse .dropdown-menu:before, .nav-collapse .dropdown-menu:after { + display: none + } + + .nav-collapse .dropdown-menu .divider { + display: none + } + + .nav-collapse .nav > li > .dropdown-menu:before, .nav-collapse .nav > li > .dropdown-menu:after { + display: none + } + + .nav-collapse .navbar-form, .nav-collapse .navbar-search { + float: none; + padding: 10px 15px; + margin: 10px 0; + border-top: 1px solid #f2f2f2; + border-bottom: 1px solid #f2f2f2; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1) + } + + .navbar-inverse .nav-collapse .navbar-form, .navbar-inverse .nav-collapse .navbar-search { + border-top-color: #111; + border-bottom-color: #111 + } + + .navbar .nav-collapse .nav.pull-right { + float: none; + margin-left: 0 + } + + .nav-collapse, .nav-collapse.collapse { + height: 0; + overflow: hidden + } + + .navbar .btn-navbar { + display: block + } + + .navbar-static .navbar-inner { + padding-right: 10px; + padding-left: 10px + } +} + +@media (min-width: 980px) { + .nav-collapse.collapse { + height: auto !important; + overflow: visible !important + } +} diff --git a/public/libs/bootstrap/css/bootstrap.css b/public/libs/bootstrap/css/bootstrap.css new file mode 100644 index 0000000000..c57ed57bd7 --- /dev/null +++ b/public/libs/bootstrap/css/bootstrap.css @@ -0,0 +1,6169 @@ +/*! + * Bootstrap v2.3.1 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +.clearfix { + *zoom: 1; +} + +.clearfix:before, +.clearfix:after { + display: table; + line-height: 0; + content: ""; +} + +.clearfix:after { + clear: both; +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +a:hover, +a:active { + outline: 0; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + width: auto\9; + height: auto; + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic; +} + +#map_canvas img, +.google-maps img { + max-width: none; +} + +button, +input, +select, +textarea { + margin: 0; + font-size: 100%; + vertical-align: middle; +} + +button, +input { + *overflow: visible; + line-height: normal; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +label, +select, +button, +input[type="button"], +input[type="reset"], +input[type="submit"], +input[type="radio"], +input[type="checkbox"] { + cursor: pointer; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + @page { + margin: 0.5cm; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333333; + background-color: #ffffff; +} + +a { + color: #0088cc; + text-decoration: none; +} + +a:hover, +a:focus { + color: #005580; + text-decoration: underline; +} + +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; +} + +.row { + margin-left: -20px; + *zoom: 1; +} + +.row:before, +.row:after { + display: table; + line-height: 0; + content: ""; +} + +.row:after { + clear: both; +} + +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px; +} + +.container, +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.span12 { + width: 940px; +} + +.span11 { + width: 860px; +} + +.span10 { + width: 780px; +} + +.span9 { + width: 700px; +} + +.span8 { + width: 620px; +} + +.span7 { + width: 540px; +} + +.span6 { + width: 460px; +} + +.span5 { + width: 380px; +} + +.span4 { + width: 300px; +} + +.span3 { + width: 220px; +} + +.span2 { + width: 140px; +} + +.span1 { + width: 60px; +} + +.offset12 { + margin-left: 980px; +} + +.offset11 { + margin-left: 900px; +} + +.offset10 { + margin-left: 820px; +} + +.offset9 { + margin-left: 740px; +} + +.offset8 { + margin-left: 660px; +} + +.offset7 { + margin-left: 580px; +} + +.offset6 { + margin-left: 500px; +} + +.offset5 { + margin-left: 420px; +} + +.offset4 { + margin-left: 340px; +} + +.offset3 { + margin-left: 260px; +} + +.offset2 { + margin-left: 180px; +} + +.offset1 { + margin-left: 100px; +} + +.row-fluid { + width: 100%; + *zoom: 1; +} + +.row-fluid:before, +.row-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.row-fluid:after { + clear: both; +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.127659574468085%; + *margin-left: 2.074468085106383%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0; +} + +.row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.127659574468085%; +} + +.row-fluid .span12 { + width: 100%; + *width: 99.94680851063829%; +} + +.row-fluid .span11 { + width: 91.48936170212765%; + *width: 91.43617021276594%; +} + +.row-fluid .span10 { + width: 82.97872340425532%; + *width: 82.92553191489361%; +} + +.row-fluid .span9 { + width: 74.46808510638297%; + *width: 74.41489361702126%; +} + +.row-fluid .span8 { + width: 65.95744680851064%; + *width: 65.90425531914893%; +} + +.row-fluid .span7 { + width: 57.44680851063829%; + *width: 57.39361702127659%; +} + +.row-fluid .span6 { + width: 48.93617021276595%; + *width: 48.88297872340425%; +} + +.row-fluid .span5 { + width: 40.42553191489362%; + *width: 40.37234042553192%; +} + +.row-fluid .span4 { + width: 31.914893617021278%; + *width: 31.861702127659576%; +} + +.row-fluid .span3 { + width: 23.404255319148934%; + *width: 23.351063829787233%; +} + +.row-fluid .span2 { + width: 14.893617021276595%; + *width: 14.840425531914894%; +} + +.row-fluid .span1 { + width: 6.382978723404255%; + *width: 6.329787234042553%; +} + +.row-fluid .offset12 { + margin-left: 104.25531914893617%; + *margin-left: 104.14893617021275%; +} + +.row-fluid .offset12:first-child { + margin-left: 102.12765957446808%; + *margin-left: 102.02127659574467%; +} + +.row-fluid .offset11 { + margin-left: 95.74468085106382%; + *margin-left: 95.6382978723404%; +} + +.row-fluid .offset11:first-child { + margin-left: 93.61702127659574%; + *margin-left: 93.51063829787232%; +} + +.row-fluid .offset10 { + margin-left: 87.23404255319149%; + *margin-left: 87.12765957446807%; +} + +.row-fluid .offset10:first-child { + margin-left: 85.1063829787234%; + *margin-left: 84.99999999999999%; +} + +.row-fluid .offset9 { + margin-left: 78.72340425531914%; + *margin-left: 78.61702127659572%; +} + +.row-fluid .offset9:first-child { + margin-left: 76.59574468085106%; + *margin-left: 76.48936170212764%; +} + +.row-fluid .offset8 { + margin-left: 70.2127659574468%; + *margin-left: 70.10638297872339%; +} + +.row-fluid .offset8:first-child { + margin-left: 68.08510638297872%; + *margin-left: 67.9787234042553%; +} + +.row-fluid .offset7 { + margin-left: 61.70212765957446%; + *margin-left: 61.59574468085106%; +} + +.row-fluid .offset7:first-child { + margin-left: 59.574468085106375%; + *margin-left: 59.46808510638297%; +} + +.row-fluid .offset6 { + margin-left: 53.191489361702125%; + *margin-left: 53.085106382978715%; +} + +.row-fluid .offset6:first-child { + margin-left: 51.063829787234035%; + *margin-left: 50.95744680851063%; +} + +.row-fluid .offset5 { + margin-left: 44.68085106382979%; + *margin-left: 44.57446808510638%; +} + +.row-fluid .offset5:first-child { + margin-left: 42.5531914893617%; + *margin-left: 42.4468085106383%; +} + +.row-fluid .offset4 { + margin-left: 36.170212765957444%; + *margin-left: 36.06382978723405%; +} + +.row-fluid .offset4:first-child { + margin-left: 34.04255319148936%; + *margin-left: 33.93617021276596%; +} + +.row-fluid .offset3 { + margin-left: 27.659574468085104%; + *margin-left: 27.5531914893617%; +} + +.row-fluid .offset3:first-child { + margin-left: 25.53191489361702%; + *margin-left: 25.425531914893618%; +} + +.row-fluid .offset2 { + margin-left: 19.148936170212764%; + *margin-left: 19.04255319148936%; +} + +.row-fluid .offset2:first-child { + margin-left: 17.02127659574468%; + *margin-left: 16.914893617021278%; +} + +.row-fluid .offset1 { + margin-left: 10.638297872340425%; + *margin-left: 10.53191489361702%; +} + +.row-fluid .offset1:first-child { + margin-left: 8.51063829787234%; + *margin-left: 8.404255319148938%; +} + +[class*="span"].hide, +.row-fluid [class*="span"].hide { + display: none; +} + +[class*="span"].pull-right, +.row-fluid [class*="span"].pull-right { + float: right; +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1; +} + +.container:before, +.container:after { + display: table; + line-height: 0; + content: ""; +} + +.container:after { + clear: both; +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1; +} + +.container-fluid:before, +.container-fluid:after { + display: table; + line-height: 0; + content: ""; +} + +.container-fluid:after { + clear: both; +} + +p { + margin: 0 0 10px; +} + +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px; +} + +small { + font-size: 85%; +} + +strong { + font-weight: bold; +} + +em { + font-style: italic; +} + +cite { + font-style: normal; +} + +.muted { + color: #999999; +} + +a.muted:hover, +a.muted:focus { + color: #808080; +} + +.text-warning { + color: #c09853; +} + +a.text-warning:hover, +a.text-warning:focus { + color: #a47e3c; +} + +.text-error { + color: #b94a48; +} + +a.text-error:hover, +a.text-error:focus { + color: #953b39; +} + +.text-info { + color: #3a87ad; +} + +a.text-info:hover, +a.text-info:focus { + color: #2d6987; +} + +.text-success { + color: #468847; +} + +a.text-success:hover, +a.text-success:focus { + color: #356635; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small { + font-weight: normal; + line-height: 1; + color: #999999; +} + +h1, +h2, +h3 { + line-height: 40px; +} + +h1 { + font-size: 38.5px; +} + +h2 { + font-size: 31.5px; +} + +h3 { + font-size: 24.5px; +} + +h4 { + font-size: 17.5px; +} + +h5 { + font-size: 14px; +} + +h6 { + font-size: 11.9px; +} + +h1 small { + font-size: 24.5px; +} + +h2 small { + font-size: 17.5px; +} + +h3 small { + font-size: 14px; +} + +h4 small { + font-size: 14px; +} + +.page-header { + padding-bottom: 9px; + margin: 20px 0 30px; + border-bottom: 1px solid #eeeeee; +} + +ul, +ol { + padding: 0; + margin: 0 0 10px 25px; +} + +ul ul, +ul ol, +ol ol, +ol ul { + margin-bottom: 0; +} + +li { + line-height: 20px; +} + +ul.unstyled, +ol.unstyled { + margin-left: 0; + list-style: none; +} + +ul.inline, +ol.inline { + margin-left: 0; + list-style: none; +} + +ul.inline > li, +ol.inline > li { + display: inline-block; + *display: inline; + padding-right: 5px; + padding-left: 5px; + *zoom: 1; +} + +dl { + margin-bottom: 20px; +} + +dt, +dd { + line-height: 20px; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 10px; +} + +.dl-horizontal { + *zoom: 1; +} + +.dl-horizontal:before, +.dl-horizontal:after { + display: table; + line-height: 0; + content: ""; +} + +.dl-horizontal:after { + clear: both; +} + +.dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dl-horizontal dd { + margin-left: 180px; +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px solid #eeeeee; + border-bottom: 1px solid #ffffff; +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + margin-bottom: 0; + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +blockquote small { + display: block; + line-height: 20px; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +blockquote.pull-right small:before { + content: ''; +} + +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 20px; +} + +code, +pre { + padding: 0 3px 2px; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +code { + padding: 2px 4px; + color: #d14; + white-space: nowrap; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 20px; +} + +pre code { + padding: 0; + color: inherit; + white-space: pre; + white-space: pre-wrap; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +form { + margin: 0 0 20px; +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +legend small { + font-size: 15px; + color: #999999; +} + +label, +input, +button, +select, +textarea { + font-size: 14px; + font-weight: normal; + line-height: 20px; +} + +input, +button, +select, +textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +label { + display: block; + margin-bottom: 5px; +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + height: 20px; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555555; + vertical-align: middle; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +input, +textarea, +.uneditable-input { + width: 206px; +} + +textarea { + height: auto; +} + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +textarea:focus, +input[type="text"]:focus, +input[type="password"]:focus, +input[type="datetime"]:focus, +input[type="datetime-local"]:focus, +input[type="date"]:focus, +input[type="month"]:focus, +input[type="time"]:focus, +input[type="week"]:focus, +input[type="number"]:focus, +input[type="email"]:focus, +input[type="url"]:focus, +input[type="search"]:focus, +input[type="tel"]:focus, +input[type="color"]:focus, +.uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + /* IE6-9 */ + + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + *margin-top: 0; + line-height: normal; +} + +input[type="file"], +input[type="image"], +input[type="submit"], +input[type="reset"], +input[type="button"], +input[type="radio"], +input[type="checkbox"] { + width: auto; +} + +select, +input[type="file"] { + height: 30px; + /* In IE7, the height of the select element cannot be changed by height, only font-size */ + + *margin-top: 4px; + /* For IE7, add top margin to align select with labels */ + + line-height: 30px; +} + +select { + width: 220px; + background-color: #ffffff; + border: 1px solid #cccccc; +} + +select[multiple], +select[size] { + height: auto; +} + +select:focus, +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.uneditable-input, +.uneditable-textarea { + color: #999999; + cursor: not-allowed; + background-color: #fcfcfc; + border-color: #cccccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap; +} + +.uneditable-textarea { + width: auto; + height: auto; +} + +input:-moz-placeholder, +textarea:-moz-placeholder { + color: #999999; +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #999999; +} + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #999999; +} + +.radio, +.checkbox { + min-height: 20px; + padding-left: 20px; +} + +.radio input[type="radio"], +.checkbox input[type="checkbox"] { + float: left; + margin-left: -20px; +} + +.controls > .radio:first-child, +.controls > .checkbox:first-child { + padding-top: 5px; +} + +.radio.inline, +.checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle; +} + +.radio.inline + .radio.inline, +.checkbox.inline + .checkbox.inline { + margin-left: 10px; +} + +.input-mini { + width: 60px; +} + +.input-small { + width: 90px; +} + +.input-medium { + width: 150px; +} + +.input-large { + width: 210px; +} + +.input-xlarge { + width: 270px; +} + +.input-xxlarge { + width: 530px; +} + +input[class*="span"], +select[class*="span"], +textarea[class*="span"], +.uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0; +} + +.input-append input[class*="span"], +.input-append .uneditable-input[class*="span"], +.input-prepend input[class*="span"], +.input-prepend .uneditable-input[class*="span"], +.row-fluid input[class*="span"], +.row-fluid select[class*="span"], +.row-fluid textarea[class*="span"], +.row-fluid .uneditable-input[class*="span"], +.row-fluid .input-prepend [class*="span"], +.row-fluid .input-append [class*="span"] { + display: inline-block; +} + +input, +textarea, +.uneditable-input { + margin-left: 0; +} + +.controls-row [class*="span"] + [class*="span"] { + margin-left: 20px; +} + +input.span12, +textarea.span12, +.uneditable-input.span12 { + width: 926px; +} + +input.span11, +textarea.span11, +.uneditable-input.span11 { + width: 846px; +} + +input.span10, +textarea.span10, +.uneditable-input.span10 { + width: 766px; +} + +input.span9, +textarea.span9, +.uneditable-input.span9 { + width: 686px; +} + +input.span8, +textarea.span8, +.uneditable-input.span8 { + width: 606px; +} + +input.span7, +textarea.span7, +.uneditable-input.span7 { + width: 526px; +} + +input.span6, +textarea.span6, +.uneditable-input.span6 { + width: 446px; +} + +input.span5, +textarea.span5, +.uneditable-input.span5 { + width: 366px; +} + +input.span4, +textarea.span4, +.uneditable-input.span4 { + width: 286px; +} + +input.span3, +textarea.span3, +.uneditable-input.span3 { + width: 206px; +} + +input.span2, +textarea.span2, +.uneditable-input.span2 { + width: 126px; +} + +input.span1, +textarea.span1, +.uneditable-input.span1 { + width: 46px; +} + +.controls-row { + *zoom: 1; +} + +.controls-row:before, +.controls-row:after { + display: table; + line-height: 0; + content: ""; +} + +.controls-row:after { + clear: both; +} + +.controls-row [class*="span"], +.row-fluid .controls-row [class*="span"] { + float: left; +} + +.controls-row .checkbox[class*="span"], +.controls-row .radio[class*="span"] { + padding-top: 5px; +} + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly], +select[readonly], +textarea[readonly] { + cursor: not-allowed; + background-color: #eeeeee; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; +} + +.control-group.warning .control-label, +.control-group.warning .help-block, +.control-group.warning .help-inline { + color: #c09853; +} + +.control-group.warning .checkbox, +.control-group.warning .radio, +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + color: #c09853; +} + +.control-group.warning input, +.control-group.warning select, +.control-group.warning textarea { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.warning input:focus, +.control-group.warning select:focus, +.control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} + +.control-group.warning .input-prepend .add-on, +.control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.control-group.error .control-label, +.control-group.error .help-block, +.control-group.error .help-inline { + color: #b94a48; +} + +.control-group.error .checkbox, +.control-group.error .radio, +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + color: #b94a48; +} + +.control-group.error input, +.control-group.error select, +.control-group.error textarea { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.error input:focus, +.control-group.error select:focus, +.control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} + +.control-group.error .input-prepend .add-on, +.control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.control-group.success .control-label, +.control-group.success .help-block, +.control-group.success .help-inline { + color: #468847; +} + +.control-group.success .checkbox, +.control-group.success .radio, +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + color: #468847; +} + +.control-group.success input, +.control-group.success select, +.control-group.success textarea { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.success input:focus, +.control-group.success select:focus, +.control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} + +.control-group.success .input-prepend .add-on, +.control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +.control-group.info .control-label, +.control-group.info .help-block, +.control-group.info .help-inline { + color: #3a87ad; +} + +.control-group.info .checkbox, +.control-group.info .radio, +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + color: #3a87ad; +} + +.control-group.info input, +.control-group.info select, +.control-group.info textarea { + border-color: #3a87ad; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.control-group.info input:focus, +.control-group.info select:focus, +.control-group.info textarea:focus { + border-color: #2d6987; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; +} + +.control-group.info .input-prepend .add-on, +.control-group.info .input-append .add-on { + color: #3a87ad; + background-color: #d9edf7; + border-color: #3a87ad; +} + +input:focus:invalid, +textarea:focus:invalid, +select:focus:invalid { + color: #b94a48; + border-color: #ee5f5b; +} + +input:focus:invalid:focus, +textarea:focus:invalid:focus, +select:focus:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7; +} + +.form-actions { + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1; +} + +.form-actions:before, +.form-actions:after { + display: table; + line-height: 0; + content: ""; +} + +.form-actions:after { + clear: both; +} + +.help-block, +.help-inline { + color: #595959; +} + +.help-block { + display: block; + margin-bottom: 10px; +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1; +} + +.input-append, +.input-prepend { + display: inline-block; + margin-bottom: 10px; + font-size: 0; + white-space: nowrap; + vertical-align: middle; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input, +.input-append .dropdown-menu, +.input-prepend .dropdown-menu, +.input-append .popover, +.input-prepend .popover { + font-size: 14px; +} + +.input-append input, +.input-prepend input, +.input-append select, +.input-prepend select, +.input-append .uneditable-input, +.input-prepend .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: top; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append input:focus, +.input-prepend input:focus, +.input-append select:focus, +.input-prepend select:focus, +.input-append .uneditable-input:focus, +.input-prepend .uneditable-input:focus { + z-index: 2; +} + +.input-append .add-on, +.input-prepend .add-on { + display: inline-block; + width: auto; + height: 20px; + min-width: 16px; + padding: 4px 5px; + font-size: 14px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + background-color: #eeeeee; + border: 1px solid #ccc; +} + +.input-append .add-on, +.input-prepend .add-on, +.input-append .btn, +.input-prepend .btn, +.input-append .btn-group > .dropdown-toggle, +.input-prepend .btn-group > .dropdown-toggle { + vertical-align: top; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-append .active, +.input-prepend .active { + background-color: #a9dba9; + border-color: #46a546; +} + +.input-prepend .add-on, +.input-prepend .btn { + margin-right: -1px; +} + +.input-prepend .add-on:first-child, +.input-prepend .btn:first-child { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input, +.input-append select, +.input-append .uneditable-input { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-append input + .btn-group .btn:last-child, +.input-append select + .btn-group .btn:last-child, +.input-append .uneditable-input + .btn-group .btn:last-child { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-append .add-on, +.input-append .btn, +.input-append .btn-group { + margin-left: -1px; +} + +.input-append .add-on:last-child, +.input-append .btn:last-child, +.input-append .btn-group:last-child > .dropdown-toggle { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append input, +.input-prepend.input-append select, +.input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.input-prepend.input-append input + .btn-group .btn, +.input-prepend.input-append select + .btn-group .btn, +.input-prepend.input-append .uneditable-input + .btn-group .btn { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .add-on:first-child, +.input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.input-prepend.input-append .add-on:last-child, +.input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.input-prepend.input-append .btn-group:first-child { + margin-left: 0; +} + +input.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + /* IE7-8 doesn't have border-radius, so don't indent the padding */ + + margin-bottom: 0; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +/* Allow for input prepend/append in search forms */ + +.form-search .input-append .search-query, +.form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0; +} + +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px; +} + +.form-search input, +.form-inline input, +.form-horizontal input, +.form-search textarea, +.form-inline textarea, +.form-horizontal textarea, +.form-search select, +.form-inline select, +.form-horizontal select, +.form-search .help-inline, +.form-inline .help-inline, +.form-horizontal .help-inline, +.form-search .uneditable-input, +.form-inline .uneditable-input, +.form-horizontal .uneditable-input, +.form-search .input-prepend, +.form-inline .input-prepend, +.form-horizontal .input-prepend, +.form-search .input-append, +.form-inline .input-append, +.form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + vertical-align: middle; + *zoom: 1; +} + +.form-search .hide, +.form-inline .hide, +.form-horizontal .hide { + display: none; +} + +.form-search label, +.form-inline label, +.form-search .btn-group, +.form-inline .btn-group { + display: inline-block; +} + +.form-search .input-append, +.form-inline .input-append, +.form-search .input-prepend, +.form-inline .input-prepend { + margin-bottom: 0; +} + +.form-search .radio, +.form-search .checkbox, +.form-inline .radio, +.form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle; +} + +.form-search .radio input[type="radio"], +.form-search .checkbox input[type="checkbox"], +.form-inline .radio input[type="radio"], +.form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0; +} + +.control-group { + margin-bottom: 10px; +} + +legend + .control-group { + margin-top: 20px; + -webkit-margin-top-collapse: separate; +} + +.form-horizontal .control-group { + margin-bottom: 20px; + *zoom: 1; +} + +.form-horizontal .control-group:before, +.form-horizontal .control-group:after { + display: table; + line-height: 0; + content: ""; +} + +.form-horizontal .control-group:after { + clear: both; +} + +.form-horizontal .control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right; +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 180px; + *margin-left: 0; +} + +.form-horizontal .controls:first-child { + *padding-left: 180px; +} + +.form-horizontal .help-block { + margin-bottom: 0; +} + +.form-horizontal input + .help-block, +.form-horizontal select + .help-block, +.form-horizontal textarea + .help-block, +.form-horizontal .uneditable-input + .help-block, +.form-horizontal .input-prepend + .help-block, +.form-horizontal .input-append + .help-block { + margin-top: 10px; +} + +.form-horizontal .form-actions { + padding-left: 180px; +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0; +} + +.table { + width: 100%; + margin-bottom: 20px; +} + +.table th, +.table td { + padding: 8px; + line-height: 20px; + text-align: left; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table th { + font-weight: bold; +} + +.table thead th { + vertical-align: bottom; +} + +.table caption + thead tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child th, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child th, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table .table { + background-color: #ffffff; +} + +.table-condensed th, +.table-condensed td { + padding: 4px 5px; +} + +.table-bordered { + border: 1px solid #dddddd; + border-collapse: separate; + *border-collapse: collapse; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.table-bordered th, +.table-bordered td { + border-left: 1px solid #dddddd; +} + +.table-bordered caption + thead tr:first-child th, +.table-bordered caption + tbody tr:first-child th, +.table-bordered caption + tbody tr:first-child td, +.table-bordered colgroup + thead tr:first-child th, +.table-bordered colgroup + tbody tr:first-child th, +.table-bordered colgroup + tbody tr:first-child td, +.table-bordered thead:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child th, +.table-bordered tbody:first-child tr:first-child td { + border-top: 0; +} + +.table-bordered thead:first-child tr:first-child > th:first-child, +.table-bordered tbody:first-child tr:first-child > td:first-child, +.table-bordered tbody:first-child tr:first-child > th:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered thead:first-child tr:first-child > th:last-child, +.table-bordered tbody:first-child tr:first-child > td:last-child, +.table-bordered tbody:first-child tr:first-child > th:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:first-child, +.table-bordered tbody:last-child tr:last-child > td:first-child, +.table-bordered tbody:last-child tr:last-child > th:first-child, +.table-bordered tfoot:last-child tr:last-child > td:first-child, +.table-bordered tfoot:last-child tr:last-child > th:first-child { + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.table-bordered thead:last-child tr:last-child > th:last-child, +.table-bordered tbody:last-child tr:last-child > td:last-child, +.table-bordered tbody:last-child tr:last-child > th:last-child, +.table-bordered tfoot:last-child tr:last-child > td:last-child, +.table-bordered tfoot:last-child tr:last-child > th:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomleft: 0; +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomright: 0; +} + +.table-bordered caption + thead tr:first-child th:first-child, +.table-bordered caption + tbody tr:first-child td:first-child, +.table-bordered colgroup + thead tr:first-child th:first-child, +.table-bordered colgroup + tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.table-bordered caption + thead tr:first-child th:last-child, +.table-bordered caption + tbody tr:first-child td:last-child, +.table-bordered colgroup + thead tr:first-child th:last-child, +.table-bordered colgroup + tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; +} + +.table-striped tbody > tr:nth-child(odd) > td, +.table-striped tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +.table-hover tbody tr:hover > td, +.table-hover tbody tr:hover > th { + background-color: #f5f5f5; +} + +table td[class*="span"], +table th[class*="span"], +.row-fluid table td[class*="span"], +.row-fluid table th[class*="span"] { + display: table-cell; + float: none; + margin-left: 0; +} + +.table td.span1, +.table th.span1 { + float: none; + width: 44px; + margin-left: 0; +} + +.table td.span2, +.table th.span2 { + float: none; + width: 124px; + margin-left: 0; +} + +.table td.span3, +.table th.span3 { + float: none; + width: 204px; + margin-left: 0; +} + +.table td.span4, +.table th.span4 { + float: none; + width: 284px; + margin-left: 0; +} + +.table td.span5, +.table th.span5 { + float: none; + width: 364px; + margin-left: 0; +} + +.table td.span6, +.table th.span6 { + float: none; + width: 444px; + margin-left: 0; +} + +.table td.span7, +.table th.span7 { + float: none; + width: 524px; + margin-left: 0; +} + +.table td.span8, +.table th.span8 { + float: none; + width: 604px; + margin-left: 0; +} + +.table td.span9, +.table th.span9 { + float: none; + width: 684px; + margin-left: 0; +} + +.table td.span10, +.table th.span10 { + float: none; + width: 764px; + margin-left: 0; +} + +.table td.span11, +.table th.span11 { + float: none; + width: 844px; + margin-left: 0; +} + +.table td.span12, +.table th.span12 { + float: none; + width: 924px; + margin-left: 0; +} + +.table tbody tr.success > td { + background-color: #dff0d8; +} + +.table tbody tr.error > td { + background-color: #f2dede; +} + +.table tbody tr.warning > td { + background-color: #fcf8e3; +} + +.table tbody tr.info > td { + background-color: #d9edf7; +} + +.table-hover tbody tr.success:hover > td { + background-color: #d0e9c6; +} + +.table-hover tbody tr.error:hover > td { + background-color: #ebcccc; +} + +.table-hover tbody tr.warning:hover > td { + background-color: #faf2cc; +} + +.table-hover tbody tr.info:hover > td { + background-color: #c4e3f3; +} + +[class^="icon-"], +[class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + margin-top: 1px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; +} + +/* White icons with optional class, or on hover/focus/active states of certain elements */ + +.icon-white, +.nav-pills > .active > a > [class^="icon-"], +.nav-pills > .active > a > [class*=" icon-"], +.nav-list > .active > a > [class^="icon-"], +.nav-list > .active > a > [class*=" icon-"], +.navbar-inverse .nav > .active > a > [class^="icon-"], +.navbar-inverse .nav > .active > a > [class*=" icon-"], +.dropdown-menu > li > a:hover > [class^="icon-"], +.dropdown-menu > li > a:focus > [class^="icon-"], +.dropdown-menu > li > a:hover > [class*=" icon-"], +.dropdown-menu > li > a:focus > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"], +.dropdown-submenu:hover > a > [class^="icon-"], +.dropdown-submenu:focus > a > [class^="icon-"], +.dropdown-submenu:hover > a > [class*=" icon-"], +.dropdown-submenu:focus > a > [class*=" icon-"] { + background-image: url("../img/glyphicons-halflings-white.png"); +} + +.icon-glass { + background-position: 0 0; +} + +.icon-music { + background-position: -24px 0; +} + +.icon-search { + background-position: -48px 0; +} + +.icon-envelope { + background-position: -72px 0; +} + +.icon-heart { + background-position: -96px 0; +} + +.icon-star { + background-position: -120px 0; +} + +.icon-star-empty { + background-position: -144px 0; +} + +.icon-user { + background-position: -168px 0; +} + +.icon-film { + background-position: -192px 0; +} + +.icon-th-large { + background-position: -216px 0; +} + +.icon-th { + background-position: -240px 0; +} + +.icon-th-list { + background-position: -264px 0; +} + +.icon-ok { + background-position: -288px 0; +} + +.icon-remove { + background-position: -312px 0; +} + +.icon-zoom-in { + background-position: -336px 0; +} + +.icon-zoom-out { + background-position: -360px 0; +} + +.icon-off { + background-position: -384px 0; +} + +.icon-signal { + background-position: -408px 0; +} + +.icon-cog { + background-position: -432px 0; +} + +.icon-trash { + background-position: -456px 0; +} + +.icon-home { + background-position: 0 -24px; +} + +.icon-file { + background-position: -24px -24px; +} + +.icon-time { + background-position: -48px -24px; +} + +.icon-road { + background-position: -72px -24px; +} + +.icon-download-alt { + background-position: -96px -24px; +} + +.icon-download { + background-position: -120px -24px; +} + +.icon-upload { + background-position: -144px -24px; +} + +.icon-inbox { + background-position: -168px -24px; +} + +.icon-play-circle { + background-position: -192px -24px; +} + +.icon-repeat { + background-position: -216px -24px; +} + +.icon-refresh { + background-position: -240px -24px; +} + +.icon-list-alt { + background-position: -264px -24px; +} + +.icon-lock { + background-position: -287px -24px; +} + +.icon-flag { + background-position: -312px -24px; +} + +.icon-headphones { + background-position: -336px -24px; +} + +.icon-volume-off { + background-position: -360px -24px; +} + +.icon-volume-down { + background-position: -384px -24px; +} + +.icon-volume-up { + background-position: -408px -24px; +} + +.icon-qrcode { + background-position: -432px -24px; +} + +.icon-barcode { + background-position: -456px -24px; +} + +.icon-tag { + background-position: 0 -48px; +} + +.icon-tags { + background-position: -25px -48px; +} + +.icon-book { + background-position: -48px -48px; +} + +.icon-bookmark { + background-position: -72px -48px; +} + +.icon-print { + background-position: -96px -48px; +} + +.icon-camera { + background-position: -120px -48px; +} + +.icon-font { + background-position: -144px -48px; +} + +.icon-bold { + background-position: -167px -48px; +} + +.icon-italic { + background-position: -192px -48px; +} + +.icon-text-height { + background-position: -216px -48px; +} + +.icon-text-width { + background-position: -240px -48px; +} + +.icon-align-left { + background-position: -264px -48px; +} + +.icon-align-center { + background-position: -288px -48px; +} + +.icon-align-right { + background-position: -312px -48px; +} + +.icon-align-justify { + background-position: -336px -48px; +} + +.icon-list { + background-position: -360px -48px; +} + +.icon-indent-left { + background-position: -384px -48px; +} + +.icon-indent-right { + background-position: -408px -48px; +} + +.icon-facetime-video { + background-position: -432px -48px; +} + +.icon-picture { + background-position: -456px -48px; +} + +.icon-pencil { + background-position: 0 -72px; +} + +.icon-map-marker { + background-position: -24px -72px; +} + +.icon-adjust { + background-position: -48px -72px; +} + +.icon-tint { + background-position: -72px -72px; +} + +.icon-edit { + background-position: -96px -72px; +} + +.icon-share { + background-position: -120px -72px; +} + +.icon-check { + background-position: -144px -72px; +} + +.icon-move { + background-position: -168px -72px; +} + +.icon-step-backward { + background-position: -192px -72px; +} + +.icon-fast-backward { + background-position: -216px -72px; +} + +.icon-backward { + background-position: -240px -72px; +} + +.icon-play { + background-position: -264px -72px; +} + +.icon-pause { + background-position: -288px -72px; +} + +.icon-stop { + background-position: -312px -72px; +} + +.icon-forward { + background-position: -336px -72px; +} + +.icon-fast-forward { + background-position: -360px -72px; +} + +.icon-step-forward { + background-position: -384px -72px; +} + +.icon-eject { + background-position: -408px -72px; +} + +.icon-chevron-left { + background-position: -432px -72px; +} + +.icon-chevron-right { + background-position: -456px -72px; +} + +.icon-plus-sign { + background-position: 0 -96px; +} + +.icon-minus-sign { + background-position: -24px -96px; +} + +.icon-remove-sign { + background-position: -48px -96px; +} + +.icon-ok-sign { + background-position: -72px -96px; +} + +.icon-question-sign { + background-position: -96px -96px; +} + +.icon-info-sign { + background-position: -120px -96px; +} + +.icon-screenshot { + background-position: -144px -96px; +} + +.icon-remove-circle { + background-position: -168px -96px; +} + +.icon-ok-circle { + background-position: -192px -96px; +} + +.icon-ban-circle { + background-position: -216px -96px; +} + +.icon-arrow-left { + background-position: -240px -96px; +} + +.icon-arrow-right { + background-position: -264px -96px; +} + +.icon-arrow-up { + background-position: -289px -96px; +} + +.icon-arrow-down { + background-position: -312px -96px; +} + +.icon-share-alt { + background-position: -336px -96px; +} + +.icon-resize-full { + background-position: -360px -96px; +} + +.icon-resize-small { + background-position: -384px -96px; +} + +.icon-plus { + background-position: -408px -96px; +} + +.icon-minus { + background-position: -433px -96px; +} + +.icon-asterisk { + background-position: -456px -96px; +} + +.icon-exclamation-sign { + background-position: 0 -120px; +} + +.icon-gift { + background-position: -24px -120px; +} + +.icon-leaf { + background-position: -48px -120px; +} + +.icon-fire { + background-position: -72px -120px; +} + +.icon-eye-open { + background-position: -96px -120px; +} + +.icon-eye-close { + background-position: -120px -120px; +} + +.icon-warning-sign { + background-position: -144px -120px; +} + +.icon-plane { + background-position: -168px -120px; +} + +.icon-calendar { + background-position: -192px -120px; +} + +.icon-random { + width: 16px; + background-position: -216px -120px; +} + +.icon-comment { + background-position: -240px -120px; +} + +.icon-magnet { + background-position: -264px -120px; +} + +.icon-chevron-up { + background-position: -288px -120px; +} + +.icon-chevron-down { + background-position: -313px -119px; +} + +.icon-retweet { + background-position: -336px -120px; +} + +.icon-shopping-cart { + background-position: -360px -120px; +} + +.icon-folder-close { + width: 16px; + background-position: -384px -120px; +} + +.icon-folder-open { + width: 16px; + background-position: -408px -120px; +} + +.icon-resize-vertical { + background-position: -432px -119px; +} + +.icon-resize-horizontal { + background-position: -456px -118px; +} + +.icon-hdd { + background-position: 0 -144px; +} + +.icon-bullhorn { + background-position: -24px -144px; +} + +.icon-bell { + background-position: -48px -144px; +} + +.icon-certificate { + background-position: -72px -144px; +} + +.icon-thumbs-up { + background-position: -96px -144px; +} + +.icon-thumbs-down { + background-position: -120px -144px; +} + +.icon-hand-right { + background-position: -144px -144px; +} + +.icon-hand-left { + background-position: -168px -144px; +} + +.icon-hand-up { + background-position: -192px -144px; +} + +.icon-hand-down { + background-position: -216px -144px; +} + +.icon-circle-arrow-right { + background-position: -240px -144px; +} + +.icon-circle-arrow-left { + background-position: -264px -144px; +} + +.icon-circle-arrow-up { + background-position: -288px -144px; +} + +.icon-circle-arrow-down { + background-position: -312px -144px; +} + +.icon-globe { + background-position: -336px -144px; +} + +.icon-wrench { + background-position: -360px -144px; +} + +.icon-tasks { + background-position: -384px -144px; +} + +.icon-filter { + background-position: -408px -144px; +} + +.icon-briefcase { + background-position: -432px -144px; +} + +.icon-fullscreen { + background-position: -456px -144px; +} + +.dropup, +.dropdown { + position: relative; +} + +.dropdown-toggle { + *margin-bottom: -3px; +} + +.dropdown-toggle:active, +.open .dropdown-toggle { + outline: 0; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: ""; +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-submenu:hover > a, +.dropdown-submenu:focus > a { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #0088cc, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); + background-image: -o-linear-gradient(top, #0088cc, #0077b3); + background-image: linear-gradient(to bottom, #0088cc, #0077b3); + background-repeat: repeat-x; + outline: 0; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); +} + +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} + +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.open { + *z-index: 1000; +} + +.open > .dropdown-menu { + display: block; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000000; + content: ""; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover > .dropdown-menu { + display: block; +} + +.dropup .dropdown-submenu > .dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 5px 5px 5px 0; + -moz-border-radius: 5px 5px 5px 0; + border-radius: 5px 5px 5px 0; +} + +.dropdown-submenu > a:after { + display: block; + float: right; + width: 0; + height: 0; + margin-top: 5px; + margin-right: -10px; + border-color: transparent; + border-left-color: #cccccc; + border-style: solid; + border-width: 5px 0 5px 5px; + content: " "; +} + +.dropdown-submenu:hover > a:after { + border-left-color: #ffffff; +} + +.dropdown-submenu.pull-left { + float: none; +} + +.dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.dropdown .dropdown-menu .nav-header { + padding-right: 20px; + padding-left: 20px; +} + +.typeahead { + z-index: 1051; + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + -moz-transition: height 0.35s ease; + -o-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +.collapse.in { + height: auto; +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 20px; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + filter: alpha(opacity=40); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 12px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 14px; + line-height: 20px; + color: #333333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); + background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); + background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #cccccc; + *border: 0; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn:hover, +.btn:focus, +.btn:active, +.btn.active, +.btn.disabled, +.btn[disabled] { + color: #333333; + background-color: #e6e6e6; + *background-color: #d9d9d9; +} + +.btn:active, +.btn.active { + background-color: #cccccc \9; +} + +.btn:first-child { + *margin-left: 0; +} + +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn.active, +.btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn.disabled, +.btn[disabled] { + cursor: default; + background-image: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-large { + padding: 11px 19px; + font-size: 17.5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.btn-large [class^="icon-"], +.btn-large [class*=" icon-"] { + margin-top: 4px; +} + +.btn-small { + padding: 2px 10px; + font-size: 11.9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-small [class^="icon-"], +.btn-small [class*=" icon-"] { + margin-top: 0; +} + +.btn-mini [class^="icon-"], +.btn-mini [class*=" icon-"] { + margin-top: -1px; +} + +.btn-mini { + padding: 0 6px; + font-size: 10.5px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.btn-block + .btn-block { + margin-top: 5px; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.btn-primary.active, +.btn-warning.active, +.btn-danger.active, +.btn-success.active, +.btn-info.active, +.btn-inverse.active { + color: rgba(255, 255, 255, 0.75); +} + +.btn-primary { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + *background-color: #0044cc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); + background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); + background-image: -o-linear-gradient(top, #0088cc, #0044cc); + background-image: linear-gradient(to bottom, #0088cc, #0044cc); + background-repeat: repeat-x; + border-color: #0044cc #0044cc #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.btn-primary.disabled, +.btn-primary[disabled] { + color: #ffffff; + background-color: #0044cc; + *background-color: #003bb3; +} + +.btn-primary:active, +.btn-primary.active { + background-color: #003399 \9; +} + +.btn-warning { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #faa732; + *background-color: #f89406; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.btn-warning.disabled, +.btn-warning[disabled] { + color: #ffffff; + background-color: #f89406; + *background-color: #df8505; +} + +.btn-warning:active, +.btn-warning.active { + background-color: #c67605 \9; +} + +.btn-danger { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #da4f49; + *background-color: #bd362f; + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.btn-danger.disabled, +.btn-danger[disabled] { + color: #ffffff; + background-color: #bd362f; + *background-color: #a9302a; +} + +.btn-danger:active, +.btn-danger.active { + background-color: #942a25 \9; +} + +.btn-success { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #5bb75b; + *background-color: #51a351; + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.btn-success.disabled, +.btn-success[disabled] { + color: #ffffff; + background-color: #51a351; + *background-color: #499249; +} + +.btn-success:active, +.btn-success.active { + background-color: #408140 \9; +} + +.btn-info { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.btn-info.disabled, +.btn-info[disabled] { + color: #ffffff; + background-color: #2f96b4; + *background-color: #2a85a0; +} + +.btn-info:active, +.btn-info.active { + background-color: #24748c \9; +} + +.btn-inverse { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; + *background-color: #222222; + background-image: -moz-linear-gradient(top, #444444, #222222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); + background-image: -webkit-linear-gradient(top, #444444, #222222); + background-image: -o-linear-gradient(top, #444444, #222222); + background-image: linear-gradient(to bottom, #444444, #222222); + background-repeat: repeat-x; + border-color: #222222 #222222 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.btn-inverse:hover, +.btn-inverse:focus, +.btn-inverse:active, +.btn-inverse.active, +.btn-inverse.disabled, +.btn-inverse[disabled] { + color: #ffffff; + background-color: #222222; + *background-color: #151515; +} + +.btn-inverse:active, +.btn-inverse.active { + background-color: #080808 \9; +} + +button.btn, +input[type="submit"].btn { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn::-moz-focus-inner, +input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0; +} + +button.btn.btn-large, +input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px; +} + +button.btn.btn-small, +input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px; +} + +button.btn.btn-mini, +input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px; +} + +.btn-link, +.btn-link:active, +.btn-link[disabled] { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.btn-link { + color: #0088cc; + cursor: pointer; + border-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-link:hover, +.btn-link:focus { + color: #005580; + text-decoration: underline; + background-color: transparent; +} + +.btn-link[disabled]:hover, +.btn-link[disabled]:focus { + color: #333333; + text-decoration: none; +} + +.btn-group { + position: relative; + display: inline-block; + *display: inline; + *margin-left: .3em; + font-size: 0; + white-space: nowrap; + vertical-align: middle; + *zoom: 1; +} + +.btn-group:first-child { + *margin-left: 0; +} + +.btn-group + .btn-group { + margin-left: 5px; +} + +.btn-toolbar { + margin-top: 10px; + margin-bottom: 10px; + font-size: 0; +} + +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group { + margin-left: 5px; +} + +.btn-group > .btn { + position: relative; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group > .btn + .btn { + margin-left: -1px; +} + +.btn-group > .btn, +.btn-group > .dropdown-menu, +.btn-group > .popover { + font-size: 14px; +} + +.btn-group > .btn-mini { + font-size: 10.5px; +} + +.btn-group > .btn-small { + font-size: 11.9px; +} + +.btn-group > .btn-large { + font-size: 17.5px; +} + +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.btn-group > .btn:last-child, +.btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.btn-group > .btn.large:last-child, +.btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active { + z-index: 2; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group > .btn + .dropdown-toggle { + *padding-top: 5px; + padding-right: 8px; + *padding-bottom: 5px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group > .btn-mini + .dropdown-toggle { + *padding-top: 2px; + padding-right: 5px; + *padding-bottom: 2px; + padding-left: 5px; +} + +.btn-group > .btn-small + .dropdown-toggle { + *padding-top: 5px; + *padding-bottom: 4px; +} + +.btn-group > .btn-large + .dropdown-toggle { + *padding-top: 7px; + padding-right: 12px; + *padding-bottom: 7px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6; +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #0044cc; +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406; +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f; +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351; +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4; +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222222; +} + +.btn .caret { + margin-top: 8px; + margin-left: 0; +} + +.btn-large .caret { + margin-top: 6px; +} + +.btn-large .caret { + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px; +} + +.btn-mini .caret, +.btn-small .caret { + margin-top: 8px; +} + +.dropup .btn-large .caret { + border-bottom-width: 5px; +} + +.btn-primary .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret, +.btn-success .caret, +.btn-inverse .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.btn-group-vertical { + display: inline-block; + *display: inline; + /* IE7 inline-block hack */ + + *zoom: 1; +} + +.btn-group-vertical > .btn { + display: block; + float: none; + max-width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.btn-group-vertical > .btn + .btn { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.btn-group-vertical > .btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.btn-group-vertical > .btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0; +} + +.btn-group-vertical > .btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.alert, +.alert h4 { + color: #c09853; +} + +.alert h4 { + margin: 0; +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 20px; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-success h4 { + color: #468847; +} + +.alert-danger, +.alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-danger h4, +.alert-error h4 { + color: #b94a48; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-info h4 { + color: #3a87ad; +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px; +} + +.alert-block > p, +.alert-block > ul { + margin-bottom: 0; +} + +.alert-block p + p { + margin-top: 5px; +} + +.nav { + margin-bottom: 20px; + margin-left: 0; + list-style: none; +} + +.nav > li > a { + display: block; +} + +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > li > a > img { + max-width: none; +} + +.nav > .pull-right { + float: right; +} + +.nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + color: #999999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase; +} + +.nav li + .nav-header { + margin-top: 9px; +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0; +} + +.nav-list > li > a, +.nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} + +.nav-list > li > a { + padding: 3px 15px; +} + +.nav-list > .active > a, +.nav-list > .active > a:hover, +.nav-list > .active > a:focus { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #0088cc; +} + +.nav-list [class^="icon-"], +.nav-list [class*=" icon-"] { + margin-right: 2px; +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #ffffff; +} + +.nav-tabs, +.nav-pills { + *zoom: 1; +} + +.nav-tabs:before, +.nav-pills:before, +.nav-tabs:after, +.nav-pills:after { + display: table; + line-height: 0; + content: ""; +} + +.nav-tabs:after, +.nav-pills:after { + clear: both; +} + +.nav-tabs > li, +.nav-pills > li { + float: left; +} + +.nav-tabs > li > a, +.nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px; +} + +.nav-tabs { + border-bottom: 1px solid #ddd; +} + +.nav-tabs > li { + margin-bottom: -1px; +} + +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 20px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover, +.nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover, +.nav-tabs > .active > a:focus { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} + +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.nav-pills > .active > a, +.nav-pills > .active > a:hover, +.nav-pills > .active > a:focus { + color: #ffffff; + background-color: #0088cc; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li > a { + margin-right: 0; +} + +.nav-tabs.nav-stacked { + border-bottom: 0; +} + +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; +} + +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px; +} + +.nav-tabs.nav-stacked > li > a:hover, +.nav-tabs.nav-stacked > li > a:focus { + z-index: 2; + border-color: #ddd; +} + +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px; +} + +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px; +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.nav .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #0088cc; + border-bottom-color: #0088cc; +} + +.nav .dropdown-toggle:hover .caret, +.nav .dropdown-toggle:focus .caret { + border-top-color: #005580; + border-bottom-color: #005580; +} + +/* move down carets for tabs */ + +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px; +} + +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff; +} + +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.nav > .dropdown.active > a:hover, +.nav > .dropdown.active > a:focus { + cursor: pointer; +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover, +.nav > li.dropdown.open.active > a:focus { + color: #ffffff; + background-color: #999999; + border-color: #999999; +} + +.nav li.dropdown.open .caret, +.nav li.dropdown.open.active .caret, +.nav li.dropdown.open a:hover .caret, +.nav li.dropdown.open a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} + +.tabs-stacked .open > a:hover, +.tabs-stacked .open > a:focus { + border-color: #999999; +} + +.tabbable { + *zoom: 1; +} + +.tabbable:before, +.tabbable:after { + display: table; + line-height: 0; + content: ""; +} + +.tabbable:after { + clear: both; +} + +.tab-content { + overflow: auto; +} + +.tabs-below > .nav-tabs, +.tabs-right > .nav-tabs, +.tabs-left > .nav-tabs { + border-bottom: 0; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd; +} + +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0; +} + +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.tabs-below > .nav-tabs > li > a:hover, +.tabs-below > .nav-tabs > li > a:focus { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover, +.tabs-below > .nav-tabs > .active > a:focus { + border-color: transparent #ddd #ddd #ddd; +} + +.tabs-left > .nav-tabs > li, +.tabs-right > .nav-tabs > li { + float: none; +} + +.tabs-left > .nav-tabs > li > a, +.tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px; +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd; +} + +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; +} + +.tabs-left > .nav-tabs > li > a:hover, +.tabs-left > .nav-tabs > li > a:focus { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover, +.tabs-left > .nav-tabs .active > a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #ffffff; +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd; +} + +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; +} + +.tabs-right > .nav-tabs > li > a:hover, +.tabs-right > .nav-tabs > li > a:focus { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover, +.tabs-right > .nav-tabs .active > a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} + +.nav > .disabled > a { + color: #999999; +} + +.nav > .disabled > a:hover, +.nav > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 20px; + overflow: visible; +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); + background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); + background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); + background-repeat: repeat-x; + border: 1px solid #d4d4d4; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + *zoom: 1; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); +} + +.navbar-inner:before, +.navbar-inner:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-inner:after { + clear: both; +} + +.navbar .container { + width: auto; +} + +.nav-collapse.collapse { + height: auto; + overflow: visible; +} + +.navbar .brand { + display: block; + float: left; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: #777777; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .brand:hover, +.navbar .brand:focus { + text-decoration: none; +} + +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777777; +} + +.navbar-link { + color: #777777; +} + +.navbar-link:hover, +.navbar-link:focus { + color: #333333; +} + +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-right: 1px solid #ffffff; + border-left: 1px solid #f2f2f2; +} + +.navbar .btn, +.navbar .btn-group { + margin-top: 5px; +} + +.navbar .btn-group .btn, +.navbar .input-prepend .btn, +.navbar .input-append .btn, +.navbar .input-prepend .btn-group, +.navbar .input-append .btn-group { + margin-top: 0; +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1; +} + +.navbar-form:before, +.navbar-form:after { + display: table; + line-height: 0; + content: ""; +} + +.navbar-form:after { + clear: both; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .radio, +.navbar-form .checkbox { + margin-top: 5px; +} + +.navbar-form input, +.navbar-form select, +.navbar-form .btn { + display: inline-block; + margin-bottom: 0; +} + +.navbar-form input[type="image"], +.navbar-form input[type="checkbox"], +.navbar-form input[type="radio"] { + margin-top: 3px; +} + +.navbar-form .input-append, +.navbar-form .input-prepend { + margin-top: 5px; + white-space: nowrap; +} + +.navbar-form .input-append input, +.navbar-form .input-prepend input { + margin-top: 0; +} + +.navbar-search { + position: relative; + float: left; + margin-top: 5px; + margin-bottom: 0; +} + +.navbar-search .search-query { + padding: 4px 14px; + margin-bottom: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.navbar-static-top { + position: static; + margin-bottom: 0; +} + +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + border-width: 0 0 1px; +} + +.navbar-fixed-bottom .navbar-inner { + border-width: 1px 0 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.navbar-static-top .container, +.navbar-fixed-top .container, +.navbar-fixed-bottom .container { + width: 940px; +} + +.navbar-fixed-top { + top: 0; +} + +.navbar-fixed-top .navbar-inner, +.navbar-static-top .navbar-inner { + -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar-fixed-bottom { + bottom: 0; +} + +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0; +} + +.navbar .nav.pull-right { + float: right; + margin-right: 0; +} + +.navbar .nav > li { + float: left; +} + +.navbar .nav > li > a { + float: none; + padding: 10px 15px 10px; + color: #777777; + text-decoration: none; + text-shadow: 0 1px 0 #ffffff; +} + +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px; +} + +.navbar .nav > li > a:focus, +.navbar .nav > li > a:hover { + color: hsl(210, 53%, 51%); + text-decoration: none; + background-color: transparent; +} + +.navbar .nav > .active > a, +.navbar .nav > .active > a:hover, +.navbar .nav > .active > a:focus { + color: #555555; + text-decoration: none; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + *background-color: #e5e5e5; + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-repeat: repeat-x; + border-color: #e5e5e5 #e5e5e5 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); +} + +.navbar .btn-navbar:hover, +.navbar .btn-navbar:focus, +.navbar .btn-navbar:active, +.navbar .btn-navbar.active, +.navbar .btn-navbar.disabled, +.navbar .btn-navbar[disabled] { + color: #ffffff; + background-color: #e5e5e5; + *background-color: #d9d9d9; +} + +.navbar .btn-navbar:active, +.navbar .btn-navbar.active { + background-color: #cccccc \9; +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); +} + +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px; +} + +.navbar .nav > li > .dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: ''; +} + +.navbar .nav > li > .dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + border-left: 6px solid transparent; + content: ''; +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2); +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #ffffff; + border-bottom: 0; +} + +.navbar .nav li.dropdown > a:hover .caret, +.navbar .nav li.dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle, +.navbar .nav li.dropdown.active > .dropdown-toggle, +.navbar .nav li.dropdown.open.active > .dropdown-toggle { + color: #555555; + background-color: #e5e5e5; +} + +.navbar .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} + +.navbar .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar .pull-right > li > .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:before, +.navbar .nav > li > .dropdown-menu.pull-right:before { + right: 12px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu:after, +.navbar .nav > li > .dropdown-menu.pull-right:after { + right: 13px; + left: auto; +} + +.navbar .pull-right > li > .dropdown-menu .dropdown-menu, +.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { + right: 100%; + left: auto; + margin-right: -1px; + margin-left: 0; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; +} + +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222222, #111111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); + background-image: -webkit-linear-gradient(top, #222222, #111111); + background-image: -o-linear-gradient(top, #222222, #111111); + background-image: linear-gradient(to bottom, #222222, #111111); + background-repeat: repeat-x; + border-color: #252525; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); +} + +.navbar-inverse .brand, +.navbar-inverse .nav > li > a { + color: #999999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-inverse .brand:hover, +.navbar-inverse .nav > li > a:hover, +.navbar-inverse .brand:focus, +.navbar-inverse .nav > li > a:focus { + color: #ffffff; +} + +.navbar-inverse .brand { + color: #999999; +} + +.navbar-inverse .navbar-text { + color: #999999; +} + +.navbar-inverse .nav > li > a:focus, +.navbar-inverse .nav > li > a:hover { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .nav .active > a, +.navbar-inverse .nav .active > a:hover, +.navbar-inverse .nav .active > a:focus { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover, +.navbar-inverse .navbar-link:focus { + color: #ffffff; +} + +.navbar-inverse .divider-vertical { + border-right-color: #222222; + border-left-color: #111111; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { + color: #ffffff; + background-color: #111111; +} + +.navbar-inverse .nav li.dropdown > a:hover .caret, +.navbar-inverse .nav li.dropdown > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, +.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .navbar-search .search-query { + color: #ffffff; + background-color: #515151; + border-color: #111111; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} + +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #cccccc; +} + +.navbar-inverse .navbar-search .search-query:focus, +.navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333333; + text-shadow: 0 1px 0 #ffffff; + background-color: #ffffff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); +} + +.navbar-inverse .btn-navbar { + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + *background-color: #040404; + background-image: -moz-linear-gradient(top, #151515, #040404); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-repeat: repeat-x; + border-color: #040404 #040404 #000000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.navbar-inverse .btn-navbar:hover, +.navbar-inverse .btn-navbar:focus, +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active, +.navbar-inverse .btn-navbar.disabled, +.navbar-inverse .btn-navbar[disabled] { + color: #ffffff; + background-color: #040404; + *background-color: #000000; +} + +.navbar-inverse .btn-navbar:active, +.navbar-inverse .btn-navbar.active { + background-color: #000000 \9; +} + +.breadcrumb { + padding: 8px 15px; + margin: 0 0 20px; + list-style: none; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.breadcrumb > li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #ffffff; + *zoom: 1; +} + +.breadcrumb > li > .divider { + padding: 0 5px; + color: #ccc; +} + +.breadcrumb > .active { + color: #999999; +} + +.pagination { + margin: 20px 0; +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.pagination ul > li { + display: inline; +} + +.pagination ul > li > a, +.pagination ul > li > span { + float: left; + padding: 4px 12px; + line-height: 20px; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; + border-left-width: 0; +} + +.pagination ul > li > a:hover, +.pagination ul > li > a:focus, +.pagination ul > .active > a, +.pagination ul > .active > span { + background-color: #f5f5f5; +} + +.pagination ul > .active > a, +.pagination ul > .active > span { + color: #999999; + cursor: default; +} + +.pagination ul > .disabled > span, +.pagination ul > .disabled > a, +.pagination ul > .disabled > a:hover, +.pagination ul > .disabled > a:focus { + color: #999999; + cursor: default; + background-color: transparent; +} + +.pagination ul > li:first-child > a, +.pagination ul > li:first-child > span { + border-left-width: 1px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; +} + +.pagination ul > li:last-child > a, +.pagination ul > li:last-child > span { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; +} + +.pagination-centered { + text-align: center; +} + +.pagination-right { + text-align: right; +} + +.pagination-large ul > li > a, +.pagination-large ul > li > span { + padding: 11px 19px; + font-size: 17.5px; +} + +.pagination-large ul > li:first-child > a, +.pagination-large ul > li:first-child > span { + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px; +} + +.pagination-large ul > li:last-child > a, +.pagination-large ul > li:last-child > span { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px; +} + +.pagination-mini ul > li:first-child > a, +.pagination-small ul > li:first-child > a, +.pagination-mini ul > li:first-child > span, +.pagination-small ul > li:first-child > span { + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-topleft: 3px; +} + +.pagination-mini ul > li:last-child > a, +.pagination-small ul > li:last-child > a, +.pagination-mini ul > li:last-child > span, +.pagination-small ul > li:last-child > span { + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px; +} + +.pagination-small ul > li > a, +.pagination-small ul > li > span { + padding: 2px 10px; + font-size: 11.9px; +} + +.pagination-mini ul > li > a, +.pagination-mini ul > li > span { + padding: 0 6px; + font-size: 10.5px; +} + +.pager { + margin: 20px 0; + text-align: center; + list-style: none; + *zoom: 1; +} + +.pager:before, +.pager:after { + display: table; + line-height: 0; + content: ""; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px; +} + +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #f5f5f5; +} + +.pager .next > a, +.pager .next > span { + float: right; +} + +.pager .previous > a, +.pager .previous > span { + float: left; +} + +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + cursor: default; + background-color: #fff; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop, +.modal-backdrop.fade.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #ffffff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; + -moz-transition: opacity 0.3s linear, top 0.3s ease-out; + -o-transition: opacity 0.3s linear, top 0.3s ease-out; + transition: opacity 0.3s linear, top 0.3s ease-out; +} + +.modal.fade.in { + top: 10%; +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} + +.modal-header .close { + margin-top: 2px; +} + +.modal-header h3 { + margin: 0; + line-height: 30px; +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto; +} + +.modal-form { + margin-bottom: 0; +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + line-height: 0; + content: ""; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 11px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} + +.tooltip-inner { + max-width: 200px; + padding: 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000000; + border-width: 5px 5px 5px 0; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000000; + border-width: 5px 0 5px 5px; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #ffffff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.popover.top { + margin-top: -10px; +} + +.popover.right { + margin-left: 10px; +} + +.popover.bottom { + margin-top: 10px; +} + +.popover.left { + margin-left: -10px; +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0; +} + +.popover-title:empty { + display: none; +} + +.popover-content { + padding: 9px 14px; +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow { + border-width: 11px; +} + +.popover .arrow:after { + border-width: 10px; + content: ""; +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0; +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #ffffff; + border-bottom-width: 0; +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0; +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #ffffff; + border-left-width: 0; +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0; +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #ffffff; + border-top-width: 0; +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0; +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #ffffff; + border-right-width: 0; +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1; +} + +.thumbnails:before, +.thumbnails:after { + display: table; + line-height: 0; + content: ""; +} + +.thumbnails:after { + clear: both; +} + +.row-fluid .thumbnails { + margin-left: 0; +} + +.thumbnails > li { + float: left; + margin-bottom: 20px; + margin-left: 20px; +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #0088cc; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); +} + +.thumbnail > img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; + color: #555555; +} + +.media, +.media-body { + overflow: hidden; + *overflow: visible; + zoom: 1; +} + +.media, +.media .media { + margin-top: 15px; +} + +.media:first-child { + margin-top: 0; +} + +.media-object { + display: block; +} + +.media-heading { + margin: 0 0 5px; +} + +.media > .pull-left { + margin-right: 10px; +} + +.media > .pull-right { + margin-left: 10px; +} + +.media-list { + margin-left: 0; + list-style: none; +} + +.label, +.badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; +} + +.label { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.badge { + padding-right: 9px; + padding-left: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} + +.label:empty, +.badge:empty { + display: none; +} + +a.label:hover, +a.label:focus, +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label-important, +.badge-important { + background-color: #b94a48; +} + +.label-important[href], +.badge-important[href] { + background-color: #953b39; +} + +.label-warning, +.badge-warning { + background-color: #f89406; +} + +.label-warning[href], +.badge-warning[href] { + background-color: #c67605; +} + +.label-success, +.badge-success { + background-color: #468847; +} + +.label-success[href], +.badge-success[href] { + background-color: #356635; +} + +.label-info, +.badge-info { + background-color: #3a87ad; +} + +.label-info[href], +.badge-info[href] { + background-color: #2d6987; +} + +.label-inverse, +.badge-inverse { + background-color: #333333; +} + +.label-inverse[href], +.badge-inverse[href] { + background-color: #1a1a1a; +} + +.btn .label, +.btn .badge { + position: relative; + top: -1px; +} + +.btn-mini .label, +.btn-mini .badge { + top: 0; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress .bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #ffffff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width 0.6s ease; + -moz-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress .bar + .bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px; +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-danger .bar, +.progress .bar-danger { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); +} + +.progress-danger.progress-striped .bar, +.progress-striped .bar-danger { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-success .bar, +.progress .bar-success { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); +} + +.progress-success.progress-striped .bar, +.progress-striped .bar-success { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-info .bar, +.progress .bar-info { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); +} + +.progress-info.progress-striped .bar, +.progress-striped .bar-info { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-warning .bar, +.progress .bar-warning { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); +} + +.progress-warning.progress-striped .bar, +.progress-striped .bar-warning { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.accordion { + margin-bottom: 20px; +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.accordion-heading { + border-bottom: 0; +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px; +} + +.accordion-toggle { + cursor: pointer; +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5; +} + +.carousel { + position: relative; + margin-bottom: 20px; + line-height: 1; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + -moz-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + line-height: 1; +} + +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} + +.carousel-inner > .active { + left: 0; +} + +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel-inner > .next { + left: 100%; +} + +.carousel-inner > .prev { + left: -100%; +} + +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} + +.carousel-inner > .active.left { + left: -100%; +} + +.carousel-inner > .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #ffffff; + text-align: center; + background: #222222; + border: 3px solid #ffffff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: 0.5; + filter: alpha(opacity=50); +} + +.carousel-control.right { + right: 15px; + left: auto; +} + +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.carousel-indicators { + position: absolute; + top: 15px; + right: 15px; + z-index: 5; + margin: 0; + list-style: none; +} + +.carousel-indicators li { + display: block; + float: left; + width: 10px; + height: 10px; + margin-left: 5px; + text-indent: -999px; + background-color: #ccc; + background-color: rgba(255, 255, 255, 0.25); + border-radius: 5px; +} + +.carousel-indicators .active { + background-color: #fff; +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 15px; + background: #333333; + background: rgba(0, 0, 0, 0.75); +} + +.carousel-caption h4, +.carousel-caption p { + line-height: 20px; + color: #ffffff; +} + +.carousel-caption h4 { + margin: 0 0 5px; +} + +.carousel-caption p { + margin-bottom: 0; +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + font-size: 18px; + font-weight: 200; + line-height: 30px; + color: inherit; + background-color: #eeeeee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit; +} + +.hero-unit li { + line-height: 30px; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.hide { + display: none; +} + +.show { + display: block; +} + +.invisible { + visibility: hidden; +} + +.affix { + position: fixed; +} diff --git a/public/libs/bootstrap/css/bootstrap.min.css b/public/libs/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000000..65f6b06b2d --- /dev/null +++ b/public/libs/bootstrap/css/bootstrap.min.css @@ -0,0 +1,5469 @@ +/*! + * Bootstrap v2.3.1 + * + * Copyright 2012 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ +.clearfix { + *zoom: 1 +} + +.clearfix:before, .clearfix:after { + display: table; + line-height: 0; + content: "" +} + +.clearfix:after { + clear: both +} + +.hide-text { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0 +} + +.input-block-level { + display: block; + width: 100%; + min-height: 30px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { + display: block +} + +audio, canvas, video { + display: inline-block; + *display: inline; + *zoom: 1 +} + +audio:not([controls]) { + display: none +} + +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100% +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} + +a:hover, a:active { + outline: 0 +} + +sub, sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline +} + +sup { + top: -0.5em +} + +sub { + bottom: -0.25em +} + +img { + width: auto\9; + height: auto; + max-width: 100%; + vertical-align: middle; + border: 0; + -ms-interpolation-mode: bicubic +} + +#map_canvas img, .google-maps img { + max-width: none +} + +button, input, select, textarea { + margin: 0; + font-size: 100%; + vertical-align: middle +} + +button, input { + *overflow: visible; + line-height: normal +} + +button::-moz-focus-inner, input::-moz-focus-inner { + padding: 0; + border: 0 +} + +button, html input[type="button"], input[type="reset"], input[type="submit"] { + cursor: pointer; + -webkit-appearance: button +} + +label, select, button, input[type="button"], input[type="reset"], input[type="submit"], input[type="radio"], input[type="checkbox"] { + cursor: pointer +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield +} + +input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none +} + +textarea { + overflow: auto; + vertical-align: top +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important + } + + a, a:visited { + text-decoration: underline + } + + a[href]:after { + content: " (" attr(href) ")" + } + + abbr[title]:after { + content: " (" attr(title) ")" + } + + .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { + content: "" + } + + pre, blockquote { + border: 1px solid #999; + page-break-inside: avoid + } + + thead { + display: table-header-group + } + + tr, img { + page-break-inside: avoid + } + + img { + max-width: 100% !important + } + + @page { + margin: .5cm + } + + p, h2, h3 { + orphans: 3; + widows: 3 + } + + h2, h3 { + page-break-after: avoid + } +} + +body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 20px; + color: #333; + background-color: #fff +} + +a { + color: #08c; + text-decoration: none +} + +a:hover, a:focus { + color: #005580; + text-decoration: underline +} + +.img-rounded { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.img-polaroid { + padding: 4px; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) +} + +.img-circle { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px +} + +.row { + margin-left: -20px; + *zoom: 1 +} + +.row:before, .row:after { + display: table; + line-height: 0; + content: "" +} + +.row:after { + clear: both +} + +[class*="span"] { + float: left; + min-height: 1px; + margin-left: 20px +} + +.container, .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { + width: 940px +} + +.span12 { + width: 940px +} + +.span11 { + width: 860px +} + +.span10 { + width: 780px +} + +.span9 { + width: 700px +} + +.span8 { + width: 620px +} + +.span7 { + width: 540px +} + +.span6 { + width: 460px +} + +.span5 { + width: 380px +} + +.span4 { + width: 300px +} + +.span3 { + width: 220px +} + +.span2 { + width: 140px +} + +.span1 { + width: 60px +} + +.offset12 { + margin-left: 980px +} + +.offset11 { + margin-left: 900px +} + +.offset10 { + margin-left: 820px +} + +.offset9 { + margin-left: 740px +} + +.offset8 { + margin-left: 660px +} + +.offset7 { + margin-left: 580px +} + +.offset6 { + margin-left: 500px +} + +.offset5 { + margin-left: 420px +} + +.offset4 { + margin-left: 340px +} + +.offset3 { + margin-left: 260px +} + +.offset2 { + margin-left: 180px +} + +.offset1 { + margin-left: 100px +} + +.row-fluid { + width: 100%; + *zoom: 1 +} + +.row-fluid:before, .row-fluid:after { + display: table; + line-height: 0; + content: "" +} + +.row-fluid:after { + clear: both +} + +.row-fluid [class*="span"] { + display: block; + float: left; + width: 100%; + min-height: 30px; + margin-left: 2.127659574468085%; + *margin-left: 2.074468085106383%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +.row-fluid [class*="span"]:first-child { + margin-left: 0 +} + +.row-fluid .controls-row [class*="span"] + [class*="span"] { + margin-left: 2.127659574468085% +} + +.row-fluid .span12 { + width: 100%; + *width: 99.94680851063829% +} + +.row-fluid .span11 { + width: 91.48936170212765%; + *width: 91.43617021276594% +} + +.row-fluid .span10 { + width: 82.97872340425532%; + *width: 82.92553191489361% +} + +.row-fluid .span9 { + width: 74.46808510638297%; + *width: 74.41489361702126% +} + +.row-fluid .span8 { + width: 65.95744680851064%; + *width: 65.90425531914893% +} + +.row-fluid .span7 { + width: 57.44680851063829%; + *width: 57.39361702127659% +} + +.row-fluid .span6 { + width: 48.93617021276595%; + *width: 48.88297872340425% +} + +.row-fluid .span5 { + width: 40.42553191489362%; + *width: 40.37234042553192% +} + +.row-fluid .span4 { + width: 31.914893617021278%; + *width: 31.861702127659576% +} + +.row-fluid .span3 { + width: 23.404255319148934%; + *width: 23.351063829787233% +} + +.row-fluid .span2 { + width: 14.893617021276595%; + *width: 14.840425531914894% +} + +.row-fluid .span1 { + width: 6.382978723404255%; + *width: 6.329787234042553% +} + +.row-fluid .offset12 { + margin-left: 104.25531914893617%; + *margin-left: 104.14893617021275% +} + +.row-fluid .offset12:first-child { + margin-left: 102.12765957446808%; + *margin-left: 102.02127659574467% +} + +.row-fluid .offset11 { + margin-left: 95.74468085106382%; + *margin-left: 95.6382978723404% +} + +.row-fluid .offset11:first-child { + margin-left: 93.61702127659574%; + *margin-left: 93.51063829787232% +} + +.row-fluid .offset10 { + margin-left: 87.23404255319149%; + *margin-left: 87.12765957446807% +} + +.row-fluid .offset10:first-child { + margin-left: 85.1063829787234%; + *margin-left: 84.99999999999999% +} + +.row-fluid .offset9 { + margin-left: 78.72340425531914%; + *margin-left: 78.61702127659572% +} + +.row-fluid .offset9:first-child { + margin-left: 76.59574468085106%; + *margin-left: 76.48936170212764% +} + +.row-fluid .offset8 { + margin-left: 70.2127659574468%; + *margin-left: 70.10638297872339% +} + +.row-fluid .offset8:first-child { + margin-left: 68.08510638297872%; + *margin-left: 67.9787234042553% +} + +.row-fluid .offset7 { + margin-left: 61.70212765957446%; + *margin-left: 61.59574468085106% +} + +.row-fluid .offset7:first-child { + margin-left: 59.574468085106375%; + *margin-left: 59.46808510638297% +} + +.row-fluid .offset6 { + margin-left: 53.191489361702125%; + *margin-left: 53.085106382978715% +} + +.row-fluid .offset6:first-child { + margin-left: 51.063829787234035%; + *margin-left: 50.95744680851063% +} + +.row-fluid .offset5 { + margin-left: 44.68085106382979%; + *margin-left: 44.57446808510638% +} + +.row-fluid .offset5:first-child { + margin-left: 42.5531914893617%; + *margin-left: 42.4468085106383% +} + +.row-fluid .offset4 { + margin-left: 36.170212765957444%; + *margin-left: 36.06382978723405% +} + +.row-fluid .offset4:first-child { + margin-left: 34.04255319148936%; + *margin-left: 33.93617021276596% +} + +.row-fluid .offset3 { + margin-left: 27.659574468085104%; + *margin-left: 27.5531914893617% +} + +.row-fluid .offset3:first-child { + margin-left: 25.53191489361702%; + *margin-left: 25.425531914893618% +} + +.row-fluid .offset2 { + margin-left: 19.148936170212764%; + *margin-left: 19.04255319148936% +} + +.row-fluid .offset2:first-child { + margin-left: 17.02127659574468%; + *margin-left: 16.914893617021278% +} + +.row-fluid .offset1 { + margin-left: 10.638297872340425%; + *margin-left: 10.53191489361702% +} + +.row-fluid .offset1:first-child { + margin-left: 8.51063829787234%; + *margin-left: 8.404255319148938% +} + +[class*="span"].hide, .row-fluid [class*="span"].hide { + display: none +} + +[class*="span"].pull-right, .row-fluid [class*="span"].pull-right { + float: right +} + +.container { + margin-right: auto; + margin-left: auto; + *zoom: 1 +} + +.container:before, .container:after { + display: table; + line-height: 0; + content: "" +} + +.container:after { + clear: both +} + +.container-fluid { + padding-right: 20px; + padding-left: 20px; + *zoom: 1 +} + +.container-fluid:before, .container-fluid:after { + display: table; + line-height: 0; + content: "" +} + +.container-fluid:after { + clear: both +} + +p { + margin: 0 0 10px +} + +.lead { + margin-bottom: 20px; + font-size: 21px; + font-weight: 200; + line-height: 30px +} + +small { + font-size: 85% +} + +strong { + font-weight: bold +} + +em { + font-style: italic +} + +cite { + font-style: normal +} + +.muted { + color: #999 +} + +a.muted:hover, a.muted:focus { + color: #808080 +} + +.text-warning { + color: #c09853 +} + +a.text-warning:hover, a.text-warning:focus { + color: #a47e3c +} + +.text-error { + color: #b94a48 +} + +a.text-error:hover, a.text-error:focus { + color: #953b39 +} + +.text-info { + color: #3a87ad +} + +a.text-info:hover, a.text-info:focus { + color: #2d6987 +} + +.text-success { + color: #468847 +} + +a.text-success:hover, a.text-success:focus { + color: #356635 +} + +.text-left { + text-align: left +} + +.text-right { + text-align: right +} + +.text-center { + text-align: center +} + +h1, h2, h3, h4, h5, h6 { + margin: 10px 0; + font-family: inherit; + font-weight: bold; + line-height: 20px; + color: inherit; + text-rendering: optimizelegibility +} + +h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { + font-weight: normal; + line-height: 1; + color: #999 +} + +h1, h2, h3 { + line-height: 40px +} + +h1 { + font-size: 38.5px +} + +h2 { + font-size: 31.5px +} + +h3 { + font-size: 24.5px +} + +h4 { + font-size: 17.5px +} + +h5 { + font-size: 14px +} + +h6 { + font-size: 11.9px +} + +h1 small { + font-size: 24.5px +} + +h2 small { + font-size: 17.5px +} + +h3 small { + font-size: 14px +} + +h4 small { + font-size: 14px +} + +.page-header { + padding-bottom: 9px; + margin: 20px 0 30px; + border-bottom: 1px solid #eee +} + +ul, ol { + padding: 0; + margin: 0 0 10px 25px +} + +ul ul, ul ol, ol ol, ol ul { + margin-bottom: 0 +} + +li { + line-height: 20px +} + +ul.unstyled, ol.unstyled { + margin-left: 0; + list-style: none +} + +ul.inline, ol.inline { + margin-left: 0; + list-style: none +} + +ul.inline > li, ol.inline > li { + display: inline-block; + *display: inline; + padding-right: 5px; + padding-left: 5px; + *zoom: 1 +} + +dl { + margin-bottom: 20px +} + +dt, dd { + line-height: 20px +} + +dt { + font-weight: bold +} + +dd { + margin-left: 10px +} + +.dl-horizontal { + *zoom: 1 +} + +.dl-horizontal:before, .dl-horizontal:after { + display: table; + line-height: 0; + content: "" +} + +.dl-horizontal:after { + clear: both +} + +.dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap +} + +.dl-horizontal dd { + margin-left: 180px +} + +hr { + margin: 20px 0; + border: 0; + border-top: 1px solid #eee; + border-bottom: 1px solid #fff +} + +abbr[title], abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999 +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase +} + +blockquote { + padding: 0 0 0 15px; + margin: 0 0 20px; + border-left: 5px solid #eee +} + +blockquote p { + margin-bottom: 0; + font-size: 17.5px; + font-weight: 300; + line-height: 1.25 +} + +blockquote small { + display: block; + line-height: 20px; + color: #999 +} + +blockquote small:before { + content: '\2014 \00A0' +} + +blockquote.pull-right { + float: right; + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eee; + border-left: 0 +} + +blockquote.pull-right p, blockquote.pull-right small { + text-align: right +} + +blockquote.pull-right small:before { + content: '' +} + +blockquote.pull-right small:after { + content: '\00A0 \2014' +} + +q:before, q:after, blockquote:before, blockquote:after { + content: "" +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 20px +} + +code, pre { + padding: 0 3px 2px; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; + font-size: 12px; + color: #333; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +code { + padding: 2px 4px; + color: #d14; + white-space: nowrap; + background-color: #f7f7f9; + border: 1px solid #e1e1e8 +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 20px; + word-break: break-all; + word-wrap: break-word; + white-space: pre; + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +pre.prettyprint { + margin-bottom: 20px +} + +pre code { + padding: 0; + color: inherit; + white-space: pre; + white-space: pre-wrap; + background-color: transparent; + border: 0 +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll +} + +form { + margin: 0 0 20px +} + +fieldset { + padding: 0; + margin: 0; + border: 0 +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5 +} + +legend small { + font-size: 15px; + color: #999 +} + +label, input, button, select, textarea { + font-size: 14px; + font-weight: normal; + line-height: 20px +} + +input, button, select, textarea { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif +} + +label { + display: block; + margin-bottom: 5px +} + +select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input { + display: inline-block; + height: 20px; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555; + vertical-align: middle; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +input, textarea, .uneditable-input { + width: 206px +} + +textarea { + height: auto +} + +textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input { + background-color: #fff; + border: 1px solid #ccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear .2s, box-shadow linear .2s; + -moz-transition: border linear .2s, box-shadow linear .2s; + -o-transition: border linear .2s, box-shadow linear .2s; + transition: border linear .2s, box-shadow linear .2s +} + +textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus, .uneditable-input:focus { + border-color: rgba(82, 168, 236, 0.8); + outline: 0; + outline: thin dotted \9; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6) +} + +input[type="radio"], input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + *margin-top: 0; + line-height: normal +} + +input[type="file"], input[type="image"], input[type="submit"], input[type="reset"], input[type="button"], input[type="radio"], input[type="checkbox"] { + width: auto +} + +select, input[type="file"] { + height: 30px; + *margin-top: 4px; + line-height: 30px +} + +select { + width: 220px; + background-color: #fff; + border: 1px solid #ccc +} + +select[multiple], select[size] { + height: auto +} + +select:focus, input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} + +.uneditable-input, .uneditable-textarea { + color: #999; + cursor: not-allowed; + background-color: #fcfcfc; + border-color: #ccc; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025) +} + +.uneditable-input { + overflow: hidden; + white-space: nowrap +} + +.uneditable-textarea { + width: auto; + height: auto +} + +input:-moz-placeholder, textarea:-moz-placeholder { + color: #999 +} + +input:-ms-input-placeholder, textarea:-ms-input-placeholder { + color: #999 +} + +input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { + color: #999 +} + +.radio, .checkbox { + min-height: 20px; + padding-left: 20px +} + +.radio input[type="radio"], .checkbox input[type="checkbox"] { + float: left; + margin-left: -20px +} + +.controls > .radio:first-child, .controls > .checkbox:first-child { + padding-top: 5px +} + +.radio.inline, .checkbox.inline { + display: inline-block; + padding-top: 5px; + margin-bottom: 0; + vertical-align: middle +} + +.radio.inline + .radio.inline, .checkbox.inline + .checkbox.inline { + margin-left: 10px +} + +.input-mini { + width: 60px +} + +.input-small { + width: 90px +} + +.input-medium { + width: 150px +} + +.input-large { + width: 210px +} + +.input-xlarge { + width: 270px +} + +.input-xxlarge { + width: 530px +} + +input[class*="span"], select[class*="span"], textarea[class*="span"], .uneditable-input[class*="span"], .row-fluid input[class*="span"], .row-fluid select[class*="span"], .row-fluid textarea[class*="span"], .row-fluid .uneditable-input[class*="span"] { + float: none; + margin-left: 0 +} + +.input-append input[class*="span"], .input-append .uneditable-input[class*="span"], .input-prepend input[class*="span"], .input-prepend .uneditable-input[class*="span"], .row-fluid input[class*="span"], .row-fluid select[class*="span"], .row-fluid textarea[class*="span"], .row-fluid .uneditable-input[class*="span"], .row-fluid .input-prepend [class*="span"], .row-fluid .input-append [class*="span"] { + display: inline-block +} + +input, textarea, .uneditable-input { + margin-left: 0 +} + +.controls-row [class*="span"] + [class*="span"] { + margin-left: 20px +} + +input.span12, textarea.span12, .uneditable-input.span12 { + width: 926px +} + +input.span11, textarea.span11, .uneditable-input.span11 { + width: 846px +} + +input.span10, textarea.span10, .uneditable-input.span10 { + width: 766px +} + +input.span9, textarea.span9, .uneditable-input.span9 { + width: 686px +} + +input.span8, textarea.span8, .uneditable-input.span8 { + width: 606px +} + +input.span7, textarea.span7, .uneditable-input.span7 { + width: 526px +} + +input.span6, textarea.span6, .uneditable-input.span6 { + width: 446px +} + +input.span5, textarea.span5, .uneditable-input.span5 { + width: 366px +} + +input.span4, textarea.span4, .uneditable-input.span4 { + width: 286px +} + +input.span3, textarea.span3, .uneditable-input.span3 { + width: 206px +} + +input.span2, textarea.span2, .uneditable-input.span2 { + width: 126px +} + +input.span1, textarea.span1, .uneditable-input.span1 { + width: 46px +} + +.controls-row { + *zoom: 1 +} + +.controls-row:before, .controls-row:after { + display: table; + line-height: 0; + content: "" +} + +.controls-row:after { + clear: both +} + +.controls-row [class*="span"], .row-fluid .controls-row [class*="span"] { + float: left +} + +.controls-row .checkbox[class*="span"], .controls-row .radio[class*="span"] { + padding-top: 5px +} + +input[disabled], select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { + cursor: not-allowed; + background-color: #eee +} + +input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="radio"][readonly], input[type="checkbox"][readonly] { + background-color: transparent +} + +.control-group.warning .control-label, .control-group.warning .help-block, .control-group.warning .help-inline { + color: #c09853 +} + +.control-group.warning .checkbox, .control-group.warning .radio, .control-group.warning input, .control-group.warning select, .control-group.warning textarea { + color: #c09853 +} + +.control-group.warning input, .control-group.warning select, .control-group.warning textarea { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) +} + +.control-group.warning input:focus, .control-group.warning select:focus, .control-group.warning textarea:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e +} + +.control-group.warning .input-prepend .add-on, .control-group.warning .input-append .add-on { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853 +} + +.control-group.error .control-label, .control-group.error .help-block, .control-group.error .help-inline { + color: #b94a48 +} + +.control-group.error .checkbox, .control-group.error .radio, .control-group.error input, .control-group.error select, .control-group.error textarea { + color: #b94a48 +} + +.control-group.error input, .control-group.error select, .control-group.error textarea { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) +} + +.control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392 +} + +.control-group.error .input-prepend .add-on, .control-group.error .input-append .add-on { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48 +} + +.control-group.success .control-label, .control-group.success .help-block, .control-group.success .help-inline { + color: #468847 +} + +.control-group.success .checkbox, .control-group.success .radio, .control-group.success input, .control-group.success select, .control-group.success textarea { + color: #468847 +} + +.control-group.success input, .control-group.success select, .control-group.success textarea { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) +} + +.control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b +} + +.control-group.success .input-prepend .add-on, .control-group.success .input-append .add-on { + color: #468847; + background-color: #dff0d8; + border-color: #468847 +} + +.control-group.info .control-label, .control-group.info .help-block, .control-group.info .help-inline { + color: #3a87ad +} + +.control-group.info .checkbox, .control-group.info .radio, .control-group.info input, .control-group.info select, .control-group.info textarea { + color: #3a87ad +} + +.control-group.info input, .control-group.info select, .control-group.info textarea { + border-color: #3a87ad; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075) +} + +.control-group.info input:focus, .control-group.info select:focus, .control-group.info textarea:focus { + border-color: #2d6987; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3 +} + +.control-group.info .input-prepend .add-on, .control-group.info .input-append .add-on { + color: #3a87ad; + background-color: #d9edf7; + border-color: #3a87ad +} + +input:focus:invalid, textarea:focus:invalid, select:focus:invalid { + color: #b94a48; + border-color: #ee5f5b +} + +input:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:focus { + border-color: #e9322d; + -webkit-box-shadow: 0 0 6px #f8b9b7; + -moz-box-shadow: 0 0 6px #f8b9b7; + box-shadow: 0 0 6px #f8b9b7 +} + +.form-actions { + padding: 19px 20px 20px; + margin-top: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-top: 1px solid #e5e5e5; + *zoom: 1 +} + +.form-actions:before, .form-actions:after { + display: table; + line-height: 0; + content: "" +} + +.form-actions:after { + clear: both +} + +.help-block, .help-inline { + color: #595959 +} + +.help-block { + display: block; + margin-bottom: 10px +} + +.help-inline { + display: inline-block; + *display: inline; + padding-left: 5px; + vertical-align: middle; + *zoom: 1 +} + +.input-append, .input-prepend { + display: inline-block; + margin-bottom: 10px; + font-size: 0; + white-space: nowrap; + vertical-align: middle +} + +.input-append input, .input-prepend input, .input-append select, .input-prepend select, .input-append .uneditable-input, .input-prepend .uneditable-input, .input-append .dropdown-menu, .input-prepend .dropdown-menu, .input-append .popover, .input-prepend .popover { + font-size: 14px +} + +.input-append input, .input-prepend input, .input-append select, .input-prepend select, .input-append .uneditable-input, .input-prepend .uneditable-input { + position: relative; + margin-bottom: 0; + *margin-left: 0; + vertical-align: top; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-append input:focus, .input-prepend input:focus, .input-append select:focus, .input-prepend select:focus, .input-append .uneditable-input:focus, .input-prepend .uneditable-input:focus { + z-index: 2 +} + +.input-append .add-on, .input-prepend .add-on { + display: inline-block; + width: auto; + height: 20px; + min-width: 16px; + padding: 4px 5px; + font-size: 14px; + font-weight: normal; + line-height: 20px; + text-align: center; + text-shadow: 0 1px 0 #fff; + background-color: #eee; + border: 1px solid #ccc +} + +.input-append .add-on, .input-prepend .add-on, .input-append .btn, .input-prepend .btn, .input-append .btn-group > .dropdown-toggle, .input-prepend .btn-group > .dropdown-toggle { + vertical-align: top; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.input-append .active, .input-prepend .active { + background-color: #a9dba9; + border-color: #46a546 +} + +.input-prepend .add-on, .input-prepend .btn { + margin-right: -1px +} + +.input-prepend .add-on:first-child, .input-prepend .btn:first-child { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px +} + +.input-append input, .input-append select, .input-append .uneditable-input { + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px +} + +.input-append input + .btn-group .btn:last-child, .input-append select + .btn-group .btn:last-child, .input-append .uneditable-input + .btn-group .btn:last-child { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-append .add-on, .input-append .btn, .input-append .btn-group { + margin-left: -1px +} + +.input-append .add-on:last-child, .input-append .btn:last-child, .input-append .btn-group:last-child > .dropdown-toggle { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-prepend.input-append input, .input-prepend.input-append select, .input-prepend.input-append .uneditable-input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.input-prepend.input-append input + .btn-group .btn, .input-prepend.input-append select + .btn-group .btn, .input-prepend.input-append .uneditable-input + .btn-group .btn { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-prepend.input-append .add-on:first-child, .input-prepend.input-append .btn:first-child { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px +} + +.input-prepend.input-append .add-on:last-child, .input-prepend.input-append .btn:last-child { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.input-prepend.input-append .btn-group:first-child { + margin-left: 0 +} + +input.search-query { + padding-right: 14px; + padding-right: 4px \9; + padding-left: 14px; + padding-left: 4px \9; + margin-bottom: 0; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px +} + +.form-search .input-append .search-query, .form-search .input-prepend .search-query { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.form-search .input-append .search-query { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px +} + +.form-search .input-append .btn { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0 +} + +.form-search .input-prepend .search-query { + -webkit-border-radius: 0 14px 14px 0; + -moz-border-radius: 0 14px 14px 0; + border-radius: 0 14px 14px 0 +} + +.form-search .input-prepend .btn { + -webkit-border-radius: 14px 0 0 14px; + -moz-border-radius: 14px 0 0 14px; + border-radius: 14px 0 0 14px +} + +.form-search input, .form-inline input, .form-horizontal input, .form-search textarea, .form-inline textarea, .form-horizontal textarea, .form-search select, .form-inline select, .form-horizontal select, .form-search .help-inline, .form-inline .help-inline, .form-horizontal .help-inline, .form-search .uneditable-input, .form-inline .uneditable-input, .form-horizontal .uneditable-input, .form-search .input-prepend, .form-inline .input-prepend, .form-horizontal .input-prepend, .form-search .input-append, .form-inline .input-append, .form-horizontal .input-append { + display: inline-block; + *display: inline; + margin-bottom: 0; + vertical-align: middle; + *zoom: 1 +} + +.form-search .hide, .form-inline .hide, .form-horizontal .hide { + display: none +} + +.form-search label, .form-inline label, .form-search .btn-group, .form-inline .btn-group { + display: inline-block +} + +.form-search .input-append, .form-inline .input-append, .form-search .input-prepend, .form-inline .input-prepend { + margin-bottom: 0 +} + +.form-search .radio, .form-search .checkbox, .form-inline .radio, .form-inline .checkbox { + padding-left: 0; + margin-bottom: 0; + vertical-align: middle +} + +.form-search .radio input[type="radio"], .form-search .checkbox input[type="checkbox"], .form-inline .radio input[type="radio"], .form-inline .checkbox input[type="checkbox"] { + float: left; + margin-right: 3px; + margin-left: 0 +} + +.control-group { + margin-bottom: 10px +} + +legend + .control-group { + margin-top: 20px; + -webkit-margin-top-collapse: separate +} + +.form-horizontal .control-group { + margin-bottom: 20px; + *zoom: 1 +} + +.form-horizontal .control-group:before, .form-horizontal .control-group:after { + display: table; + line-height: 0; + content: "" +} + +.form-horizontal .control-group:after { + clear: both +} + +.form-horizontal .control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right +} + +.form-horizontal .controls { + *display: inline-block; + *padding-left: 20px; + margin-left: 180px; + *margin-left: 0 +} + +.form-horizontal .controls:first-child { + *padding-left: 180px +} + +.form-horizontal .help-block { + margin-bottom: 0 +} + +.form-horizontal input + .help-block, .form-horizontal select + .help-block, .form-horizontal textarea + .help-block, .form-horizontal .uneditable-input + .help-block, .form-horizontal .input-prepend + .help-block, .form-horizontal .input-append + .help-block { + margin-top: 10px +} + +.form-horizontal .form-actions { + padding-left: 180px +} + +table { + max-width: 100%; + background-color: transparent; + border-collapse: collapse; + border-spacing: 0 +} + +.table { + width: 100%; + margin-bottom: 20px +} + +.table th, .table td { + padding: 8px; + line-height: 20px; + text-align: left; + vertical-align: top; + border-top: 1px solid #ddd +} + +.table th { + font-weight: bold +} + +.table thead th { + vertical-align: bottom +} + +.table caption + thead tr:first-child th, .table caption + thead tr:first-child td, .table colgroup + thead tr:first-child th, .table colgroup + thead tr:first-child td, .table thead:first-child tr:first-child th, .table thead:first-child tr:first-child td { + border-top: 0 +} + +.table tbody + tbody { + border-top: 2px solid #ddd +} + +.table .table { + background-color: #fff +} + +.table-condensed th, .table-condensed td { + padding: 4px 5px +} + +.table-bordered { + border: 1px solid #ddd; + border-collapse: separate; + *border-collapse: collapse; + border-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.table-bordered th, .table-bordered td { + border-left: 1px solid #ddd +} + +.table-bordered caption + thead tr:first-child th, .table-bordered caption + tbody tr:first-child th, .table-bordered caption + tbody tr:first-child td, .table-bordered colgroup + thead tr:first-child th, .table-bordered colgroup + tbody tr:first-child th, .table-bordered colgroup + tbody tr:first-child td, .table-bordered thead:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child td { + border-top: 0 +} + +.table-bordered thead:first-child tr:first-child > th:first-child, .table-bordered tbody:first-child tr:first-child > td:first-child, .table-bordered tbody:first-child tr:first-child > th:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px +} + +.table-bordered thead:first-child tr:first-child > th:last-child, .table-bordered tbody:first-child tr:first-child > td:last-child, .table-bordered tbody:first-child tr:first-child > th:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px +} + +.table-bordered thead:last-child tr:last-child > th:first-child, .table-bordered tbody:last-child tr:last-child > td:first-child, .table-bordered tbody:last-child tr:last-child > th:first-child, .table-bordered tfoot:last-child tr:last-child > td:first-child, .table-bordered tfoot:last-child tr:last-child > th:first-child { + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px +} + +.table-bordered thead:last-child tr:last-child > th:last-child, .table-bordered tbody:last-child tr:last-child > td:last-child, .table-bordered tbody:last-child tr:last-child > th:last-child, .table-bordered tfoot:last-child tr:last-child > td:last-child, .table-bordered tfoot:last-child tr:last-child > th:last-child { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:first-child { + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomleft: 0 +} + +.table-bordered tfoot + tbody:last-child tr:last-child td:last-child { + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomright: 0 +} + +.table-bordered caption + thead tr:first-child th:first-child, .table-bordered caption + tbody tr:first-child td:first-child, .table-bordered colgroup + thead tr:first-child th:first-child, .table-bordered colgroup + tbody tr:first-child td:first-child { + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px +} + +.table-bordered caption + thead tr:first-child th:last-child, .table-bordered caption + tbody tr:first-child td:last-child, .table-bordered colgroup + thead tr:first-child th:last-child, .table-bordered colgroup + tbody tr:first-child td:last-child { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -moz-border-radius-topright: 4px +} + +.table-striped tbody > tr:nth-child(odd) > td, .table-striped tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9 +} + +.table-hover tbody tr:hover > td, .table-hover tbody tr:hover > th { + background-color: #f5f5f5 +} + +table td[class*="span"], table th[class*="span"], .row-fluid table td[class*="span"], .row-fluid table th[class*="span"] { + display: table-cell; + float: none; + margin-left: 0 +} + +.table td.span1, .table th.span1 { + float: none; + width: 44px; + margin-left: 0 +} + +.table td.span2, .table th.span2 { + float: none; + width: 124px; + margin-left: 0 +} + +.table td.span3, .table th.span3 { + float: none; + width: 204px; + margin-left: 0 +} + +.table td.span4, .table th.span4 { + float: none; + width: 284px; + margin-left: 0 +} + +.table td.span5, .table th.span5 { + float: none; + width: 364px; + margin-left: 0 +} + +.table td.span6, .table th.span6 { + float: none; + width: 444px; + margin-left: 0 +} + +.table td.span7, .table th.span7 { + float: none; + width: 524px; + margin-left: 0 +} + +.table td.span8, .table th.span8 { + float: none; + width: 604px; + margin-left: 0 +} + +.table td.span9, .table th.span9 { + float: none; + width: 684px; + margin-left: 0 +} + +.table td.span10, .table th.span10 { + float: none; + width: 764px; + margin-left: 0 +} + +.table td.span11, .table th.span11 { + float: none; + width: 844px; + margin-left: 0 +} + +.table td.span12, .table th.span12 { + float: none; + width: 924px; + margin-left: 0 +} + +.table tbody tr.success > td { + background-color: #dff0d8 +} + +.table tbody tr.error > td { + background-color: #f2dede +} + +.table tbody tr.warning > td { + background-color: #fcf8e3 +} + +.table tbody tr.info > td { + background-color: #d9edf7 +} + +.table-hover tbody tr.success:hover > td { + background-color: #d0e9c6 +} + +.table-hover tbody tr.error:hover > td { + background-color: #ebcccc +} + +.table-hover tbody tr.warning:hover > td { + background-color: #faf2cc +} + +.table-hover tbody tr.info:hover > td { + background-color: #c4e3f3 +} + +[class^="icon-"], [class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + margin-top: 1px; + *margin-right: .3em; + line-height: 14px; + vertical-align: text-top; + background-image: url("../img/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat +} + +.icon-white, .nav-pills > .active > a > [class^="icon-"], .nav-pills > .active > a > [class*=" icon-"], .nav-list > .active > a > [class^="icon-"], .nav-list > .active > a > [class*=" icon-"], .navbar-inverse .nav > .active > a > [class^="icon-"], .navbar-inverse .nav > .active > a > [class*=" icon-"], .dropdown-menu > li > a:hover > [class^="icon-"], .dropdown-menu > li > a:focus > [class^="icon-"], .dropdown-menu > li > a:hover > [class*=" icon-"], .dropdown-menu > li > a:focus > [class*=" icon-"], .dropdown-menu > .active > a > [class^="icon-"], .dropdown-menu > .active > a > [class*=" icon-"], .dropdown-submenu:hover > a > [class^="icon-"], .dropdown-submenu:focus > a > [class^="icon-"], .dropdown-submenu:hover > a > [class*=" icon-"], .dropdown-submenu:focus > a > [class*=" icon-"] { + background-image: url("../img/glyphicons-halflings-white.png") +} + +.icon-glass { + background-position: 0 0 +} + +.icon-music { + background-position: -24px 0 +} + +.icon-search { + background-position: -48px 0 +} + +.icon-envelope { + background-position: -72px 0 +} + +.icon-heart { + background-position: -96px 0 +} + +.icon-star { + background-position: -120px 0 +} + +.icon-star-empty { + background-position: -144px 0 +} + +.icon-user { + background-position: -168px 0 +} + +.icon-film { + background-position: -192px 0 +} + +.icon-th-large { + background-position: -216px 0 +} + +.icon-th { + background-position: -240px 0 +} + +.icon-th-list { + background-position: -264px 0 +} + +.icon-ok { + background-position: -288px 0 +} + +.icon-remove { + background-position: -312px 0 +} + +.icon-zoom-in { + background-position: -336px 0 +} + +.icon-zoom-out { + background-position: -360px 0 +} + +.icon-off { + background-position: -384px 0 +} + +.icon-signal { + background-position: -408px 0 +} + +.icon-cog { + background-position: -432px 0 +} + +.icon-trash { + background-position: -456px 0 +} + +.icon-home { + background-position: 0 -24px +} + +.icon-file { + background-position: -24px -24px +} + +.icon-time { + background-position: -48px -24px +} + +.icon-road { + background-position: -72px -24px +} + +.icon-download-alt { + background-position: -96px -24px +} + +.icon-download { + background-position: -120px -24px +} + +.icon-upload { + background-position: -144px -24px +} + +.icon-inbox { + background-position: -168px -24px +} + +.icon-play-circle { + background-position: -192px -24px +} + +.icon-repeat { + background-position: -216px -24px +} + +.icon-refresh { + background-position: -240px -24px +} + +.icon-list-alt { + background-position: -264px -24px +} + +.icon-lock { + background-position: -287px -24px +} + +.icon-flag { + background-position: -312px -24px +} + +.icon-headphones { + background-position: -336px -24px +} + +.icon-volume-off { + background-position: -360px -24px +} + +.icon-volume-down { + background-position: -384px -24px +} + +.icon-volume-up { + background-position: -408px -24px +} + +.icon-qrcode { + background-position: -432px -24px +} + +.icon-barcode { + background-position: -456px -24px +} + +.icon-tag { + background-position: 0 -48px +} + +.icon-tags { + background-position: -25px -48px +} + +.icon-book { + background-position: -48px -48px +} + +.icon-bookmark { + background-position: -72px -48px +} + +.icon-print { + background-position: -96px -48px +} + +.icon-camera { + background-position: -120px -48px +} + +.icon-font { + background-position: -144px -48px +} + +.icon-bold { + background-position: -167px -48px +} + +.icon-italic { + background-position: -192px -48px +} + +.icon-text-height { + background-position: -216px -48px +} + +.icon-text-width { + background-position: -240px -48px +} + +.icon-align-left { + background-position: -264px -48px +} + +.icon-align-center { + background-position: -288px -48px +} + +.icon-align-right { + background-position: -312px -48px +} + +.icon-align-justify { + background-position: -336px -48px +} + +.icon-list { + background-position: -360px -48px +} + +.icon-indent-left { + background-position: -384px -48px +} + +.icon-indent-right { + background-position: -408px -48px +} + +.icon-facetime-video { + background-position: -432px -48px +} + +.icon-picture { + background-position: -456px -48px +} + +.icon-pencil { + background-position: 0 -72px +} + +.icon-map-marker { + background-position: -24px -72px +} + +.icon-adjust { + background-position: -48px -72px +} + +.icon-tint { + background-position: -72px -72px +} + +.icon-edit { + background-position: -96px -72px +} + +.icon-share { + background-position: -120px -72px +} + +.icon-check { + background-position: -144px -72px +} + +.icon-move { + background-position: -168px -72px +} + +.icon-step-backward { + background-position: -192px -72px +} + +.icon-fast-backward { + background-position: -216px -72px +} + +.icon-backward { + background-position: -240px -72px +} + +.icon-play { + background-position: -264px -72px +} + +.icon-pause { + background-position: -288px -72px +} + +.icon-stop { + background-position: -312px -72px +} + +.icon-forward { + background-position: -336px -72px +} + +.icon-fast-forward { + background-position: -360px -72px +} + +.icon-step-forward { + background-position: -384px -72px +} + +.icon-eject { + background-position: -408px -72px +} + +.icon-chevron-left { + background-position: -432px -72px +} + +.icon-chevron-right { + background-position: -456px -72px +} + +.icon-plus-sign { + background-position: 0 -96px +} + +.icon-minus-sign { + background-position: -24px -96px +} + +.icon-remove-sign { + background-position: -48px -96px +} + +.icon-ok-sign { + background-position: -72px -96px +} + +.icon-question-sign { + background-position: -96px -96px +} + +.icon-info-sign { + background-position: -120px -96px +} + +.icon-screenshot { + background-position: -144px -96px +} + +.icon-remove-circle { + background-position: -168px -96px +} + +.icon-ok-circle { + background-position: -192px -96px +} + +.icon-ban-circle { + background-position: -216px -96px +} + +.icon-arrow-left { + background-position: -240px -96px +} + +.icon-arrow-right { + background-position: -264px -96px +} + +.icon-arrow-up { + background-position: -289px -96px +} + +.icon-arrow-down { + background-position: -312px -96px +} + +.icon-share-alt { + background-position: -336px -96px +} + +.icon-resize-full { + background-position: -360px -96px +} + +.icon-resize-small { + background-position: -384px -96px +} + +.icon-plus { + background-position: -408px -96px +} + +.icon-minus { + background-position: -433px -96px +} + +.icon-asterisk { + background-position: -456px -96px +} + +.icon-exclamation-sign { + background-position: 0 -120px +} + +.icon-gift { + background-position: -24px -120px +} + +.icon-leaf { + background-position: -48px -120px +} + +.icon-fire { + background-position: -72px -120px +} + +.icon-eye-open { + background-position: -96px -120px +} + +.icon-eye-close { + background-position: -120px -120px +} + +.icon-warning-sign { + background-position: -144px -120px +} + +.icon-plane { + background-position: -168px -120px +} + +.icon-calendar { + background-position: -192px -120px +} + +.icon-random { + width: 16px; + background-position: -216px -120px +} + +.icon-comment { + background-position: -240px -120px +} + +.icon-magnet { + background-position: -264px -120px +} + +.icon-chevron-up { + background-position: -288px -120px +} + +.icon-chevron-down { + background-position: -313px -119px +} + +.icon-retweet { + background-position: -336px -120px +} + +.icon-shopping-cart { + background-position: -360px -120px +} + +.icon-folder-close { + width: 16px; + background-position: -384px -120px +} + +.icon-folder-open { + width: 16px; + background-position: -408px -120px +} + +.icon-resize-vertical { + background-position: -432px -119px +} + +.icon-resize-horizontal { + background-position: -456px -118px +} + +.icon-hdd { + background-position: 0 -144px +} + +.icon-bullhorn { + background-position: -24px -144px +} + +.icon-bell { + background-position: -48px -144px +} + +.icon-certificate { + background-position: -72px -144px +} + +.icon-thumbs-up { + background-position: -96px -144px +} + +.icon-thumbs-down { + background-position: -120px -144px +} + +.icon-hand-right { + background-position: -144px -144px +} + +.icon-hand-left { + background-position: -168px -144px +} + +.icon-hand-up { + background-position: -192px -144px +} + +.icon-hand-down { + background-position: -216px -144px +} + +.icon-circle-arrow-right { + background-position: -240px -144px +} + +.icon-circle-arrow-left { + background-position: -264px -144px +} + +.icon-circle-arrow-up { + background-position: -288px -144px +} + +.icon-circle-arrow-down { + background-position: -312px -144px +} + +.icon-globe { + background-position: -336px -144px +} + +.icon-wrench { + background-position: -360px -144px +} + +.icon-tasks { + background-position: -384px -144px +} + +.icon-filter { + background-position: -408px -144px +} + +.icon-briefcase { + background-position: -432px -144px +} + +.icon-fullscreen { + background-position: -456px -144px +} + +.dropup, .dropdown { + position: relative +} + +.dropdown-toggle { + *margin-bottom: -3px +} + +.dropdown-toggle:active, .open .dropdown-toggle { + outline: 0 +} + +.caret { + display: inline-block; + width: 0; + height: 0; + vertical-align: top; + border-top: 4px solid #000; + border-right: 4px solid transparent; + border-left: 4px solid transparent; + content: "" +} + +.dropdown .caret { + margin-top: 8px; + margin-left: 2px +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + *border-right-width: 2px; + *border-bottom-width: 2px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box +} + +.dropdown-menu.pull-right { + right: 0; + left: auto +} + +.dropdown-menu .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #fff +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #333; + white-space: nowrap +} + +.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus, .dropdown-submenu:hover > a, .dropdown-submenu:focus > a { + color: #fff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #08c, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #08c, #0077b3); + background-image: -o-linear-gradient(top, #08c, #0077b3); + background-image: linear-gradient(to bottom, #08c, #0077b3); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0) +} + +.dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top, #08c, #0077b3); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3)); + background-image: -webkit-linear-gradient(top, #08c, #0077b3); + background-image: -o-linear-gradient(top, #08c, #0077b3); + background-image: linear-gradient(to bottom, #08c, #0077b3); + background-repeat: repeat-x; + outline: 0; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0) +} + +.dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { + color: #999 +} + +.dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.open { + *z-index: 1000 +} + +.open > .dropdown-menu { + display: block +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto +} + +.dropup .caret, .navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid #000; + content: "" +} + +.dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px +} + +.dropdown-submenu { + position: relative +} + +.dropdown-submenu > .dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + -webkit-border-radius: 0 6px 6px 6px; + -moz-border-radius: 0 6px 6px 6px; + border-radius: 0 6px 6px 6px +} + +.dropdown-submenu:hover > .dropdown-menu { + display: block +} + +.dropup .dropdown-submenu > .dropdown-menu { + top: auto; + bottom: 0; + margin-top: 0; + margin-bottom: -2px; + -webkit-border-radius: 5px 5px 5px 0; + -moz-border-radius: 5px 5px 5px 0; + border-radius: 5px 5px 5px 0 +} + +.dropdown-submenu > a:after { + display: block; + float: right; + width: 0; + height: 0; + margin-top: 5px; + margin-right: -10px; + border-color: transparent; + border-left-color: #ccc; + border-style: solid; + border-width: 5px 0 5px 5px; + content: " " +} + +.dropdown-submenu:hover > a:after { + border-left-color: #fff +} + +.dropdown-submenu.pull-left { + float: none +} + +.dropdown-submenu.pull-left > .dropdown-menu { + left: -100%; + margin-left: 10px; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px +} + +.dropdown .dropdown-menu .nav-header { + padding-right: 20px; + padding-left: 20px +} + +.typeahead { + z-index: 1051; + margin-top: 2px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05) +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15) +} + +.well-large { + padding: 24px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.well-small { + padding: 9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -moz-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear +} + +.fade.in { + opacity: 1 +} + +.collapse { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height .35s ease; + -moz-transition: height .35s ease; + -o-transition: height .35s ease; + transition: height .35s ease +} + +.collapse.in { + height: auto +} + +.close { + float: right; + font-size: 20px; + font-weight: bold; + line-height: 20px; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: .2; + filter: alpha(opacity=20) +} + +.close:hover, .close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + opacity: .4; + filter: alpha(opacity=40) +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none +} + +.btn { + display: inline-block; + *display: inline; + padding: 4px 12px; + margin-bottom: 0; + *margin-left: .3em; + font-size: 14px; + line-height: 20px; + color: #333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + vertical-align: middle; + cursor: pointer; + background-color: #f5f5f5; + *background-color: #e6e6e6; + background-image: -moz-linear-gradient(top, #fff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #fff, #e6e6e6); + background-image: -o-linear-gradient(top, #fff, #e6e6e6); + background-image: linear-gradient(to bottom, #fff, #e6e6e6); + background-repeat: repeat-x; + border: 1px solid #ccc; + *border: 0; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-bottom-color: #b3b3b3; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.btn:hover, .btn:focus, .btn:active, .btn.active, .btn.disabled, .btn[disabled] { + color: #333; + background-color: #e6e6e6; + *background-color: #d9d9d9 +} + +.btn:active, .btn.active { + background-color: #ccc \9 +} + +.btn:first-child { + *margin-left: 0 +} + +.btn:hover, .btn:focus { + color: #333; + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position .1s linear; + -moz-transition: background-position .1s linear; + -o-transition: background-position .1s linear; + transition: background-position .1s linear +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px +} + +.btn.active, .btn:active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.btn.disabled, .btn[disabled] { + cursor: default; + background-image: none; + opacity: .65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none +} + +.btn-large { + padding: 11px 19px; + font-size: 17.5px; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.btn-large [class^="icon-"], .btn-large [class*=" icon-"] { + margin-top: 4px +} + +.btn-small { + padding: 2px 10px; + font-size: 11.9px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +.btn-small [class^="icon-"], .btn-small [class*=" icon-"] { + margin-top: 0 +} + +.btn-mini [class^="icon-"], .btn-mini [class*=" icon-"] { + margin-top: -1px +} + +.btn-mini { + padding: 0 6px; + font-size: 10.5px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +.btn-block + .btn-block { + margin-top: 5px +} + +input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { + width: 100% +} + +.btn-primary.active, .btn-warning.active, .btn-danger.active, .btn-success.active, .btn-info.active, .btn-inverse.active { + color: rgba(255, 255, 255, 0.75) +} + +.btn-primary { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #006dcc; + *background-color: #04c; + background-image: -moz-linear-gradient(top, #08c, #04c); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c)); + background-image: -webkit-linear-gradient(top, #08c, #04c); + background-image: -o-linear-gradient(top, #08c, #04c); + background-image: linear-gradient(to bottom, #08c, #04c); + background-repeat: repeat-x; + border-color: #04c #04c #002a80; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { + color: #fff; + background-color: #04c; + *background-color: #003bb3 +} + +.btn-primary:active, .btn-primary.active { + background-color: #039 \9 +} + +.btn-warning { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #faa732; + *background-color: #f89406; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + border-color: #f89406 #f89406 #ad6704; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .btn-warning.disabled, .btn-warning[disabled] { + color: #fff; + background-color: #f89406; + *background-color: #df8505 +} + +.btn-warning:active, .btn-warning.active { + background-color: #c67605 \9 +} + +.btn-danger { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #da4f49; + *background-color: #bd362f; + background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); + background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); + background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); + background-repeat: repeat-x; + border-color: #bd362f #bd362f #802420; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .btn-danger.disabled, .btn-danger[disabled] { + color: #fff; + background-color: #bd362f; + *background-color: #a9302a +} + +.btn-danger:active, .btn-danger.active { + background-color: #942a25 \9 +} + +.btn-success { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #5bb75b; + *background-color: #51a351; + background-image: -moz-linear-gradient(top, #62c462, #51a351); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); + background-image: -webkit-linear-gradient(top, #62c462, #51a351); + background-image: -o-linear-gradient(top, #62c462, #51a351); + background-image: linear-gradient(to bottom, #62c462, #51a351); + background-repeat: repeat-x; + border-color: #51a351 #51a351 #387038; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .btn-success.disabled, .btn-success[disabled] { + color: #fff; + background-color: #51a351; + *background-color: #499249 +} + +.btn-success:active, .btn-success.active { + background-color: #408140 \9 +} + +.btn-info { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #49afcd; + *background-color: #2f96b4; + background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); + background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); + background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); + background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); + background-repeat: repeat-x; + border-color: #2f96b4 #2f96b4 #1f6377; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .btn-info.disabled, .btn-info[disabled] { + color: #fff; + background-color: #2f96b4; + *background-color: #2a85a0 +} + +.btn-info:active, .btn-info.active { + background-color: #24748c \9 +} + +.btn-inverse { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #363636; + *background-color: #222; + background-image: -moz-linear-gradient(top, #444, #222); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#222)); + background-image: -webkit-linear-gradient(top, #444, #222); + background-image: -o-linear-gradient(top, #444, #222); + background-image: linear-gradient(to bottom, #444, #222); + background-repeat: repeat-x; + border-color: #222 #222 #000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.btn-inverse:hover, .btn-inverse:focus, .btn-inverse:active, .btn-inverse.active, .btn-inverse.disabled, .btn-inverse[disabled] { + color: #fff; + background-color: #222; + *background-color: #151515 +} + +.btn-inverse:active, .btn-inverse.active { + background-color: #080808 \9 +} + +button.btn, input[type="submit"].btn { + *padding-top: 3px; + *padding-bottom: 3px +} + +button.btn::-moz-focus-inner, input[type="submit"].btn::-moz-focus-inner { + padding: 0; + border: 0 +} + +button.btn.btn-large, input[type="submit"].btn.btn-large { + *padding-top: 7px; + *padding-bottom: 7px +} + +button.btn.btn-small, input[type="submit"].btn.btn-small { + *padding-top: 3px; + *padding-bottom: 3px +} + +button.btn.btn-mini, input[type="submit"].btn.btn-mini { + *padding-top: 1px; + *padding-bottom: 1px +} + +.btn-link, .btn-link:active, .btn-link[disabled] { + background-color: transparent; + background-image: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none +} + +.btn-link { + color: #08c; + cursor: pointer; + border-color: transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.btn-link:hover, .btn-link:focus { + color: #005580; + text-decoration: underline; + background-color: transparent +} + +.btn-link[disabled]:hover, .btn-link[disabled]:focus { + color: #333; + text-decoration: none +} + +.btn-group { + position: relative; + display: inline-block; + *display: inline; + *margin-left: .3em; + font-size: 0; + white-space: nowrap; + vertical-align: middle; + *zoom: 1 +} + +.btn-group:first-child { + *margin-left: 0 +} + +.btn-group + .btn-group { + margin-left: 5px +} + +.btn-toolbar { + margin-top: 10px; + margin-bottom: 10px; + font-size: 0 +} + +.btn-toolbar > .btn + .btn, .btn-toolbar > .btn-group + .btn, .btn-toolbar > .btn + .btn-group { + margin-left: 5px +} + +.btn-group > .btn { + position: relative; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.btn-group > .btn + .btn { + margin-left: -1px +} + +.btn-group > .btn, .btn-group > .dropdown-menu, .btn-group > .popover { + font-size: 14px +} + +.btn-group > .btn-mini { + font-size: 10.5px +} + +.btn-group > .btn-small { + font-size: 11.9px +} + +.btn-group > .btn-large { + font-size: 17.5px +} + +.btn-group > .btn:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px +} + +.btn-group > .btn:last-child, .btn-group > .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px +} + +.btn-group > .btn.large:first-child { + margin-left: 0; + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px +} + +.btn-group > .btn.large:last-child, .btn-group > .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px +} + +.btn-group > .btn:hover, .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active { + z-index: 2 +} + +.btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { + outline: 0 +} + +.btn-group > .btn + .dropdown-toggle { + *padding-top: 5px; + padding-right: 8px; + *padding-bottom: 5px; + padding-left: 8px; + -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.btn-group > .btn-mini + .dropdown-toggle { + *padding-top: 2px; + padding-right: 5px; + *padding-bottom: 2px; + padding-left: 5px +} + +.btn-group > .btn-small + .dropdown-toggle { + *padding-top: 5px; + *padding-bottom: 4px +} + +.btn-group > .btn-large + .dropdown-toggle { + *padding-top: 7px; + padding-right: 12px; + *padding-bottom: 7px; + padding-left: 12px +} + +.btn-group.open .dropdown-toggle { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.btn-group.open .btn.dropdown-toggle { + background-color: #e6e6e6 +} + +.btn-group.open .btn-primary.dropdown-toggle { + background-color: #04c +} + +.btn-group.open .btn-warning.dropdown-toggle { + background-color: #f89406 +} + +.btn-group.open .btn-danger.dropdown-toggle { + background-color: #bd362f +} + +.btn-group.open .btn-success.dropdown-toggle { + background-color: #51a351 +} + +.btn-group.open .btn-info.dropdown-toggle { + background-color: #2f96b4 +} + +.btn-group.open .btn-inverse.dropdown-toggle { + background-color: #222 +} + +.btn .caret { + margin-top: 8px; + margin-left: 0 +} + +.btn-large .caret { + margin-top: 6px +} + +.btn-large .caret { + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px +} + +.btn-mini .caret, .btn-small .caret { + margin-top: 8px +} + +.dropup .btn-large .caret { + border-bottom-width: 5px +} + +.btn-primary .caret, .btn-warning .caret, .btn-danger .caret, .btn-info .caret, .btn-success .caret, .btn-inverse .caret { + border-top-color: #fff; + border-bottom-color: #fff +} + +.btn-group-vertical { + display: inline-block; + *display: inline; + *zoom: 1 +} + +.btn-group-vertical > .btn { + display: block; + float: none; + max-width: 100%; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.btn-group-vertical > .btn + .btn { + margin-top: -1px; + margin-left: 0 +} + +.btn-group-vertical > .btn:first-child { + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0 +} + +.btn-group-vertical > .btn:last-child { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px +} + +.btn-group-vertical > .btn-large:first-child { + -webkit-border-radius: 6px 6px 0 0; + -moz-border-radius: 6px 6px 0 0; + border-radius: 6px 6px 0 0 +} + +.btn-group-vertical > .btn-large:last-child { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px +} + +.alert { + padding: 8px 35px 8px 14px; + margin-bottom: 20px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + background-color: #fcf8e3; + border: 1px solid #fbeed5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.alert, .alert h4 { + color: #c09853 +} + +.alert h4 { + margin: 0 +} + +.alert .close { + position: relative; + top: -2px; + right: -21px; + line-height: 20px +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6 +} + +.alert-success h4 { + color: #468847 +} + +.alert-danger, .alert-error { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7 +} + +.alert-danger h4, .alert-error h4 { + color: #b94a48 +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1 +} + +.alert-info h4 { + color: #3a87ad +} + +.alert-block { + padding-top: 14px; + padding-bottom: 14px +} + +.alert-block > p, .alert-block > ul { + margin-bottom: 0 +} + +.alert-block p + p { + margin-top: 5px +} + +.nav { + margin-bottom: 20px; + margin-left: 0; + list-style: none +} + +.nav > li > a { + display: block +} + +.nav > li > a:hover, .nav > li > a:focus { + text-decoration: none; + background-color: #eee +} + +.nav > li > a > img { + max-width: none +} + +.nav > .pull-right { + float: right +} + +.nav-header { + display: block; + padding: 3px 15px; + font-size: 11px; + font-weight: bold; + line-height: 20px; + color: #999; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-transform: uppercase +} + +.nav li + .nav-header { + margin-top: 9px +} + +.nav-list { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 0 +} + +.nav-list > li > a, .nav-list .nav-header { + margin-right: -15px; + margin-left: -15px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) +} + +.nav-list > li > a { + padding: 3px 15px +} + +.nav-list > .active > a, .nav-list > .active > a:hover, .nav-list > .active > a:focus { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + background-color: #08c +} + +.nav-list [class^="icon-"], .nav-list [class*=" icon-"] { + margin-right: 2px +} + +.nav-list .divider { + *width: 100%; + height: 1px; + margin: 9px 1px; + *margin: -5px 0 5px; + overflow: hidden; + background-color: #e5e5e5; + border-bottom: 1px solid #fff +} + +.nav-tabs, .nav-pills { + *zoom: 1 +} + +.nav-tabs:before, .nav-pills:before, .nav-tabs:after, .nav-pills:after { + display: table; + line-height: 0; + content: "" +} + +.nav-tabs:after, .nav-pills:after { + clear: both +} + +.nav-tabs > li, .nav-pills > li { + float: left +} + +.nav-tabs > li > a, .nav-pills > li > a { + padding-right: 12px; + padding-left: 12px; + margin-right: 2px; + line-height: 14px +} + +.nav-tabs { + border-bottom: 1px solid #ddd +} + +.nav-tabs > li { + margin-bottom: -1px +} + +.nav-tabs > li > a { + padding-top: 8px; + padding-bottom: 8px; + line-height: 20px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0 +} + +.nav-tabs > li > a:hover, .nav-tabs > li > a:focus { + border-color: #eee #eee #ddd +} + +.nav-tabs > .active > a, .nav-tabs > .active > a:hover, .nav-tabs > .active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent +} + +.nav-pills > li > a { + padding-top: 8px; + padding-bottom: 8px; + margin-top: 2px; + margin-bottom: 2px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px +} + +.nav-pills > .active > a, .nav-pills > .active > a:hover, .nav-pills > .active > a:focus { + color: #fff; + background-color: #08c +} + +.nav-stacked > li { + float: none +} + +.nav-stacked > li > a { + margin-right: 0 +} + +.nav-tabs.nav-stacked { + border-bottom: 0 +} + +.nav-tabs.nav-stacked > li > a { + border: 1px solid #ddd; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.nav-tabs.nav-stacked > li:first-child > a { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px +} + +.nav-tabs.nav-stacked > li:last-child > a { + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -moz-border-radius-bottomright: 4px; + -moz-border-radius-bottomleft: 4px +} + +.nav-tabs.nav-stacked > li > a:hover, .nav-tabs.nav-stacked > li > a:focus { + z-index: 2; + border-color: #ddd +} + +.nav-pills.nav-stacked > li > a { + margin-bottom: 3px +} + +.nav-pills.nav-stacked > li:last-child > a { + margin-bottom: 1px +} + +.nav-tabs .dropdown-menu { + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px +} + +.nav-pills .dropdown-menu { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.nav .dropdown-toggle .caret { + margin-top: 6px; + border-top-color: #08c; + border-bottom-color: #08c +} + +.nav .dropdown-toggle:hover .caret, .nav .dropdown-toggle:focus .caret { + border-top-color: #005580; + border-bottom-color: #005580 +} + +.nav-tabs .dropdown-toggle .caret { + margin-top: 8px +} + +.nav .active .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff +} + +.nav-tabs .active .dropdown-toggle .caret { + border-top-color: #555; + border-bottom-color: #555 +} + +.nav > .dropdown.active > a:hover, .nav > .dropdown.active > a:focus { + cursor: pointer +} + +.nav-tabs .open .dropdown-toggle, .nav-pills .open .dropdown-toggle, .nav > li.dropdown.open.active > a:hover, .nav > li.dropdown.open.active > a:focus { + color: #fff; + background-color: #999; + border-color: #999 +} + +.nav li.dropdown.open .caret, .nav li.dropdown.open.active .caret, .nav li.dropdown.open a:hover .caret, .nav li.dropdown.open a:focus .caret { + border-top-color: #fff; + border-bottom-color: #fff; + opacity: 1; + filter: alpha(opacity=100) +} + +.tabs-stacked .open > a:hover, .tabs-stacked .open > a:focus { + border-color: #999 +} + +.tabbable { + *zoom: 1 +} + +.tabbable:before, .tabbable:after { + display: table; + line-height: 0; + content: "" +} + +.tabbable:after { + clear: both +} + +.tab-content { + overflow: auto +} + +.tabs-below > .nav-tabs, .tabs-right > .nav-tabs, .tabs-left > .nav-tabs { + border-bottom: 0 +} + +.tab-content > .tab-pane, .pill-content > .pill-pane { + display: none +} + +.tab-content > .active, .pill-content > .active { + display: block +} + +.tabs-below > .nav-tabs { + border-top: 1px solid #ddd +} + +.tabs-below > .nav-tabs > li { + margin-top: -1px; + margin-bottom: 0 +} + +.tabs-below > .nav-tabs > li > a { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px +} + +.tabs-below > .nav-tabs > li > a:hover, .tabs-below > .nav-tabs > li > a:focus { + border-top-color: #ddd; + border-bottom-color: transparent +} + +.tabs-below > .nav-tabs > .active > a, .tabs-below > .nav-tabs > .active > a:hover, .tabs-below > .nav-tabs > .active > a:focus { + border-color: transparent #ddd #ddd #ddd +} + +.tabs-left > .nav-tabs > li, .tabs-right > .nav-tabs > li { + float: none +} + +.tabs-left > .nav-tabs > li > a, .tabs-right > .nav-tabs > li > a { + min-width: 74px; + margin-right: 0; + margin-bottom: 3px +} + +.tabs-left > .nav-tabs { + float: left; + margin-right: 19px; + border-right: 1px solid #ddd +} + +.tabs-left > .nav-tabs > li > a { + margin-right: -1px; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px +} + +.tabs-left > .nav-tabs > li > a:hover, .tabs-left > .nav-tabs > li > a:focus { + border-color: #eee #ddd #eee #eee +} + +.tabs-left > .nav-tabs .active > a, .tabs-left > .nav-tabs .active > a:hover, .tabs-left > .nav-tabs .active > a:focus { + border-color: #ddd transparent #ddd #ddd; + *border-right-color: #fff +} + +.tabs-right > .nav-tabs { + float: right; + margin-left: 19px; + border-left: 1px solid #ddd +} + +.tabs-right > .nav-tabs > li > a { + margin-left: -1px; + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0 +} + +.tabs-right > .nav-tabs > li > a:hover, .tabs-right > .nav-tabs > li > a:focus { + border-color: #eee #eee #eee #ddd +} + +.tabs-right > .nav-tabs .active > a, .tabs-right > .nav-tabs .active > a:hover, .tabs-right > .nav-tabs .active > a:focus { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #fff +} + +.nav > .disabled > a { + color: #999 +} + +.nav > .disabled > a:hover, .nav > .disabled > a:focus { + text-decoration: none; + cursor: default; + background-color: transparent +} + +.navbar { + *position: relative; + *z-index: 2; + margin-bottom: 20px; + overflow: visible +} + +.navbar-inner { + min-height: 40px; + padding-right: 20px; + padding-left: 20px; + background-color: #fafafa; + background-image: -moz-linear-gradient(top, #fff, #f2f2f2); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#f2f2f2)); + background-image: -webkit-linear-gradient(top, #fff, #f2f2f2); + background-image: -o-linear-gradient(top, #fff, #f2f2f2); + background-image: linear-gradient(to bottom, #fff, #f2f2f2); + background-repeat: repeat-x; + border: 1px solid #d4d4d4; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); + *zoom: 1; + -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065) +} + +.navbar-inner:before, .navbar-inner:after { + display: table; + line-height: 0; + content: "" +} + +.navbar-inner:after { + clear: both +} + +.navbar .container { + width: auto +} + +.nav-collapse.collapse { + height: auto; + overflow: visible +} + +.navbar .brand { + display: block; + float: left; + padding: 10px 20px 10px; + margin-left: -20px; + font-size: 20px; + font-weight: 200; + color: #777; + text-shadow: 0 1px 0 #fff +} + +.navbar .brand:hover, .navbar .brand:focus { + text-decoration: none +} + +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777 +} + +.navbar-link { + color: #777 +} + +.navbar-link:hover, .navbar-link:focus { + color: #333 +} + +.navbar .divider-vertical { + height: 40px; + margin: 0 9px; + border-right: 1px solid #fff; + border-left: 1px solid #f2f2f2 +} + +.navbar .btn, .navbar .btn-group { + margin-top: 5px +} + +.navbar .btn-group .btn, .navbar .input-prepend .btn, .navbar .input-append .btn, .navbar .input-prepend .btn-group, .navbar .input-append .btn-group { + margin-top: 0 +} + +.navbar-form { + margin-bottom: 0; + *zoom: 1 +} + +.navbar-form:before, .navbar-form:after { + display: table; + line-height: 0; + content: "" +} + +.navbar-form:after { + clear: both +} + +.navbar-form input, .navbar-form select, .navbar-form .radio, .navbar-form .checkbox { + margin-top: 5px +} + +.navbar-form input, .navbar-form select, .navbar-form .btn { + display: inline-block; + margin-bottom: 0 +} + +.navbar-form input[type="image"], .navbar-form input[type="checkbox"], .navbar-form input[type="radio"] { + margin-top: 3px +} + +.navbar-form .input-append, .navbar-form .input-prepend { + margin-top: 5px; + white-space: nowrap +} + +.navbar-form .input-append input, .navbar-form .input-prepend input { + margin-top: 0 +} + +.navbar-search { + position: relative; + float: left; + margin-top: 5px; + margin-bottom: 0 +} + +.navbar-search .search-query { + padding: 4px 14px; + margin-bottom: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + font-weight: normal; + line-height: 1; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px +} + +.navbar-static-top { + position: static; + margin-bottom: 0 +} + +.navbar-static-top .navbar-inner { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.navbar-fixed-top, .navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; + margin-bottom: 0 +} + +.navbar-fixed-top .navbar-inner, .navbar-static-top .navbar-inner { + border-width: 0 0 1px +} + +.navbar-fixed-bottom .navbar-inner { + border-width: 1px 0 0 +} + +.navbar-fixed-top .navbar-inner, .navbar-fixed-bottom .navbar-inner { + padding-right: 0; + padding-left: 0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0 +} + +.navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { + width: 940px +} + +.navbar-fixed-top { + top: 0 +} + +.navbar-fixed-top .navbar-inner, .navbar-static-top .navbar-inner { + -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1) +} + +.navbar-fixed-bottom { + bottom: 0 +} + +.navbar-fixed-bottom .navbar-inner { + -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); + box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1) +} + +.navbar .nav { + position: relative; + left: 0; + display: block; + float: left; + margin: 0 10px 0 0 +} + +.navbar .nav.pull-right { + float: right; + margin-right: 0 +} + +.navbar .nav > li { + float: left +} + +.navbar .nav > li > a { + float: none; + padding: 10px 15px 10px; + color: #777; + text-decoration: none; + text-shadow: 0 1px 0 #fff +} + +.navbar .nav .dropdown-toggle .caret { + margin-top: 8px +} + +.navbar .nav > li > a:focus, .navbar .nav > li > a:hover { + color: #333; + text-decoration: none; + background-color: transparent +} + +.navbar .nav > .active > a, .navbar .nav > .active > a:hover, .navbar .nav > .active > a:focus { + color: #555; + text-decoration: none; + background-color: #e5e5e5; + -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125) +} + +.navbar .btn-navbar { + display: none; + float: right; + padding: 7px 10px; + margin-right: 5px; + margin-left: 5px; + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #ededed; + *background-color: #e5e5e5; + background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); + background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); + background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); + background-repeat: repeat-x; + border-color: #e5e5e5 #e5e5e5 #bfbfbf; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075) +} + +.navbar .btn-navbar:hover, .navbar .btn-navbar:focus, .navbar .btn-navbar:active, .navbar .btn-navbar.active, .navbar .btn-navbar.disabled, .navbar .btn-navbar[disabled] { + color: #fff; + background-color: #e5e5e5; + *background-color: #d9d9d9 +} + +.navbar .btn-navbar:active, .navbar .btn-navbar.active { + background-color: #ccc \9 +} + +.navbar .btn-navbar .icon-bar { + display: block; + width: 18px; + height: 2px; + background-color: #f5f5f5; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25) +} + +.btn-navbar .icon-bar + .icon-bar { + margin-top: 3px +} + +.navbar .nav > li > .dropdown-menu:before { + position: absolute; + top: -7px; + left: 9px; + display: inline-block; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-left: 7px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + content: '' +} + +.navbar .nav > li > .dropdown-menu:after { + position: absolute; + top: -6px; + left: 10px; + display: inline-block; + border-right: 6px solid transparent; + border-bottom: 6px solid #fff; + border-left: 6px solid transparent; + content: '' +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:before { + top: auto; + bottom: -7px; + border-top: 7px solid #ccc; + border-bottom: 0; + border-top-color: rgba(0, 0, 0, 0.2) +} + +.navbar-fixed-bottom .nav > li > .dropdown-menu:after { + top: auto; + bottom: -6px; + border-top: 6px solid #fff; + border-bottom: 0 +} + +.navbar .nav li.dropdown > a:hover .caret, .navbar .nav li.dropdown > a:focus .caret { + border-top-color: #333; + border-bottom-color: #333 +} + +.navbar .nav li.dropdown.open > .dropdown-toggle, .navbar .nav li.dropdown.active > .dropdown-toggle, .navbar .nav li.dropdown.open.active > .dropdown-toggle { + color: #555; + background-color: #e5e5e5 +} + +.navbar .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #777; + border-bottom-color: #777 +} + +.navbar .nav li.dropdown.open > .dropdown-toggle .caret, .navbar .nav li.dropdown.active > .dropdown-toggle .caret, .navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #555; + border-bottom-color: #555 +} + +.navbar .pull-right > li > .dropdown-menu, .navbar .nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto +} + +.navbar .pull-right > li > .dropdown-menu:before, .navbar .nav > li > .dropdown-menu.pull-right:before { + right: 12px; + left: auto +} + +.navbar .pull-right > li > .dropdown-menu:after, .navbar .nav > li > .dropdown-menu.pull-right:after { + right: 13px; + left: auto +} + +.navbar .pull-right > li > .dropdown-menu .dropdown-menu, .navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { + right: 100%; + left: auto; + margin-right: -1px; + margin-left: 0; + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px +} + +.navbar-inverse .navbar-inner { + background-color: #1b1b1b; + background-image: -moz-linear-gradient(top, #222, #111); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222), to(#111)); + background-image: -webkit-linear-gradient(top, #222, #111); + background-image: -o-linear-gradient(top, #222, #111); + background-image: linear-gradient(to bottom, #222, #111); + background-repeat: repeat-x; + border-color: #252525; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0) +} + +.navbar-inverse .brand, .navbar-inverse .nav > li > a { + color: #999; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25) +} + +.navbar-inverse .brand:hover, .navbar-inverse .nav > li > a:hover, .navbar-inverse .brand:focus, .navbar-inverse .nav > li > a:focus { + color: #fff +} + +.navbar-inverse .brand { + color: #999 +} + +.navbar-inverse .navbar-text { + color: #999 +} + +.navbar-inverse .nav > li > a:focus, .navbar-inverse .nav > li > a:hover { + color: #fff; + background-color: transparent +} + +.navbar-inverse .nav .active > a, .navbar-inverse .nav .active > a:hover, .navbar-inverse .nav .active > a:focus { + color: #fff; + background-color: #111 +} + +.navbar-inverse .navbar-link { + color: #999 +} + +.navbar-inverse .navbar-link:hover, .navbar-inverse .navbar-link:focus { + color: #fff +} + +.navbar-inverse .divider-vertical { + border-right-color: #222; + border-left-color: #111 +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle, .navbar-inverse .nav li.dropdown.active > .dropdown-toggle, .navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { + color: #fff; + background-color: #111 +} + +.navbar-inverse .nav li.dropdown > a:hover .caret, .navbar-inverse .nav li.dropdown > a:focus .caret { + border-top-color: #fff; + border-bottom-color: #fff +} + +.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { + border-top-color: #999; + border-bottom-color: #999 +} + +.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, .navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, .navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { + border-top-color: #fff; + border-bottom-color: #fff +} + +.navbar-inverse .navbar-search .search-query { + color: #fff; + background-color: #515151; + border-color: #111; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none +} + +.navbar-inverse .navbar-search .search-query:-moz-placeholder { + color: #ccc +} + +.navbar-inverse .navbar-search .search-query:-ms-input-placeholder { + color: #ccc +} + +.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { + color: #ccc +} + +.navbar-inverse .navbar-search .search-query:focus, .navbar-inverse .navbar-search .search-query.focused { + padding: 5px 15px; + color: #333; + text-shadow: 0 1px 0 #fff; + background-color: #fff; + border: 0; + outline: 0; + -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15) +} + +.navbar-inverse .btn-navbar { + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e0e0e; + *background-color: #040404; + background-image: -moz-linear-gradient(top, #151515, #040404); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); + background-image: -webkit-linear-gradient(top, #151515, #040404); + background-image: -o-linear-gradient(top, #151515, #040404); + background-image: linear-gradient(to bottom, #151515, #040404); + background-repeat: repeat-x; + border-color: #040404 #040404 #000; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false) +} + +.navbar-inverse .btn-navbar:hover, .navbar-inverse .btn-navbar:focus, .navbar-inverse .btn-navbar:active, .navbar-inverse .btn-navbar.active, .navbar-inverse .btn-navbar.disabled, .navbar-inverse .btn-navbar[disabled] { + color: #fff; + background-color: #040404; + *background-color: #000 +} + +.navbar-inverse .btn-navbar:active, .navbar-inverse .btn-navbar.active { + background-color: #000 \9 +} + +.breadcrumb { + padding: 8px 15px; + margin: 0 0 20px; + list-style: none; + background-color: #f5f5f5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.breadcrumb > li { + display: inline-block; + *display: inline; + text-shadow: 0 1px 0 #fff; + *zoom: 1 +} + +.breadcrumb > li > .divider { + padding: 0 5px; + color: #ccc +} + +.breadcrumb > .active { + color: #999 +} + +.pagination { + margin: 20px 0 +} + +.pagination ul { + display: inline-block; + *display: inline; + margin-bottom: 0; + margin-left: 0; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + *zoom: 1; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) +} + +.pagination ul > li { + display: inline +} + +.pagination ul > li > a, .pagination ul > li > span { + float: left; + padding: 4px 12px; + line-height: 20px; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; + border-left-width: 0 +} + +.pagination ul > li > a:hover, .pagination ul > li > a:focus, .pagination ul > .active > a, .pagination ul > .active > span { + background-color: #f5f5f5 +} + +.pagination ul > .active > a, .pagination ul > .active > span { + color: #999; + cursor: default +} + +.pagination ul > .disabled > span, .pagination ul > .disabled > a, .pagination ul > .disabled > a:hover, .pagination ul > .disabled > a:focus { + color: #999; + cursor: default; + background-color: transparent +} + +.pagination ul > li:first-child > a, .pagination ul > li:first-child > span { + border-left-width: 1px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px +} + +.pagination ul > li:last-child > a, .pagination ul > li:last-child > span { + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px +} + +.pagination-centered { + text-align: center +} + +.pagination-right { + text-align: right +} + +.pagination-large ul > li > a, .pagination-large ul > li > span { + padding: 11px 19px; + font-size: 17.5px +} + +.pagination-large ul > li:first-child > a, .pagination-large ul > li:first-child > span { + -webkit-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -webkit-border-top-left-radius: 6px; + border-top-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + -moz-border-radius-topleft: 6px +} + +.pagination-large ul > li:last-child > a, .pagination-large ul > li:last-child > span { + -webkit-border-top-right-radius: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + -moz-border-radius-topright: 6px; + -moz-border-radius-bottomright: 6px +} + +.pagination-mini ul > li:first-child > a, .pagination-small ul > li:first-child > a, .pagination-mini ul > li:first-child > span, .pagination-small ul > li:first-child > span { + -webkit-border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; + -webkit-border-top-left-radius: 3px; + border-top-left-radius: 3px; + -moz-border-radius-bottomleft: 3px; + -moz-border-radius-topleft: 3px +} + +.pagination-mini ul > li:last-child > a, .pagination-small ul > li:last-child > a, .pagination-mini ul > li:last-child > span, .pagination-small ul > li:last-child > span { + -webkit-border-top-right-radius: 3px; + border-top-right-radius: 3px; + -webkit-border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; + -moz-border-radius-topright: 3px; + -moz-border-radius-bottomright: 3px +} + +.pagination-small ul > li > a, .pagination-small ul > li > span { + padding: 2px 10px; + font-size: 11.9px +} + +.pagination-mini ul > li > a, .pagination-mini ul > li > span { + padding: 0 6px; + font-size: 10.5px +} + +.pager { + margin: 20px 0; + text-align: center; + list-style: none; + *zoom: 1 +} + +.pager:before, .pager:after { + display: table; + line-height: 0; + content: "" +} + +.pager:after { + clear: both +} + +.pager li { + display: inline +} + +.pager li > a, .pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; + border-radius: 15px +} + +.pager li > a:hover, .pager li > a:focus { + text-decoration: none; + background-color: #f5f5f5 +} + +.pager .next > a, .pager .next > span { + float: right +} + +.pager .previous > a, .pager .previous > span { + float: left +} + +.pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { + color: #999; + cursor: default; + background-color: #fff +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000 +} + +.modal-backdrop.fade { + opacity: 0 +} + +.modal-backdrop, .modal-backdrop.fade.in { + opacity: .8; + filter: alpha(opacity=80) +} + +.modal { + position: fixed; + top: 10%; + left: 50%; + z-index: 1050; + width: 560px; + margin-left: -280px; + background-color: #fff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.3); + *border: 1px solid #999; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box +} + +.modal.fade { + top: -25%; + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out +} + +.modal.fade.in { + top: 10% +} + +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee +} + +.modal-header .close { + margin-top: 2px +} + +.modal-header h3 { + margin: 0; + line-height: 30px +} + +.modal-body { + position: relative; + max-height: 400px; + padding: 15px; + overflow-y: auto +} + +.modal-form { + margin-bottom: 0 +} + +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + text-align: right; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + *zoom: 1; + -webkit-box-shadow: inset 0 1px 0 #fff; + -moz-box-shadow: inset 0 1px 0 #fff; + box-shadow: inset 0 1px 0 #fff +} + +.modal-footer:before, .modal-footer:after { + display: table; + line-height: 0; + content: "" +} + +.modal-footer:after { + clear: both +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0 +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 11px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible +} + +.tooltip.in { + opacity: .8; + filter: alpha(opacity=80) +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px +} + +.tooltip-inner { + max-width: 200px; + padding: 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000; + border-width: 5px 5px 0 +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000; + border-width: 5px 5px 5px 0 +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000; + border-width: 5px 0 5px 5px +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000; + border-width: 0 5px 5px +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box +} + +.popover.top { + margin-top: -10px +} + +.popover.right { + margin-left: 10px +} + +.popover.bottom { + margin-top: 10px +} + +.popover.left { + margin-left: -10px +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + -webkit-border-radius: 5px 5px 0 0; + -moz-border-radius: 5px 5px 0 0; + border-radius: 5px 5px 0 0 +} + +.popover-title:empty { + display: none +} + +.popover-content { + padding: 9px 14px +} + +.popover .arrow, .popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid +} + +.popover .arrow { + border-width: 11px +} + +.popover .arrow:after { + border-width: 10px; + content: "" +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0 +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #fff; + border-bottom-width: 0 +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0 +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #fff; + border-left-width: 0 +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0 +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #fff; + border-top-width: 0 +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0 +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #fff; + border-right-width: 0 +} + +.thumbnails { + margin-left: -20px; + list-style: none; + *zoom: 1 +} + +.thumbnails:before, .thumbnails:after { + display: table; + line-height: 0; + content: "" +} + +.thumbnails:after { + clear: both +} + +.row-fluid .thumbnails { + margin-left: 0 +} + +.thumbnails > li { + float: left; + margin-bottom: 20px; + margin-left: 20px +} + +.thumbnail { + display: block; + padding: 4px; + line-height: 20px; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); + -webkit-transition: all .2s ease-in-out; + -moz-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out +} + +a.thumbnail:hover, a.thumbnail:focus { + border-color: #08c; + -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); + box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25) +} + +.thumbnail > img { + display: block; + max-width: 100%; + margin-right: auto; + margin-left: auto +} + +.thumbnail .caption { + padding: 9px; + color: #555 +} + +.media, .media-body { + overflow: hidden; + *overflow: visible; + zoom: 1 +} + +.media, .media .media { + margin-top: 15px +} + +.media:first-child { + margin-top: 0 +} + +.media-object { + display: block +} + +.media-heading { + margin: 0 0 5px +} + +.media > .pull-left { + margin-right: 10px +} + +.media > .pull-right { + margin-left: 10px +} + +.media-list { + margin-left: 0; + list-style: none +} + +.label, .badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999 +} + +.label { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px +} + +.badge { + padding-right: 9px; + padding-left: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px +} + +.label:empty, .badge:empty { + display: none +} + +a.label:hover, a.label:focus, a.badge:hover, a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer +} + +.label-important, .badge-important { + background-color: #b94a48 +} + +.label-important[href], .badge-important[href] { + background-color: #953b39 +} + +.label-warning, .badge-warning { + background-color: #f89406 +} + +.label-warning[href], .badge-warning[href] { + background-color: #c67605 +} + +.label-success, .badge-success { + background-color: #468847 +} + +.label-success[href], .badge-success[href] { + background-color: #356635 +} + +.label-info, .badge-info { + background-color: #3a87ad +} + +.label-info[href], .badge-info[href] { + background-color: #2d6987 +} + +.label-inverse, .badge-inverse { + background-color: #333 +} + +.label-inverse[href], .badge-inverse[href] { + background-color: #1a1a1a +} + +.btn .label, .btn .badge { + position: relative; + top: -1px +} + +.btn-mini .label, .btn-mini .badge { + top: 0 +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + to { + background-position: 0 0 + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + to { + background-position: 0 0 + } +} + +@-ms-keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + to { + background-position: 0 0 + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0 + } + to { + background-position: 40px 0 + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0 + } + to { + background-position: 0 0 + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f7f7f7; + background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); + background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); + background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); + background-repeat: repeat-x; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1) +} + +.progress .bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #fff; + text-align: center; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #0e90d2; + background-image: -moz-linear-gradient(top, #149bdf, #0480be); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); + background-image: -webkit-linear-gradient(top, #149bdf, #0480be); + background-image: -o-linear-gradient(top, #149bdf, #0480be); + background-image: linear-gradient(to bottom, #149bdf, #0480be); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-transition: width .6s ease; + -moz-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease +} + +.progress .bar + .bar { + -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15) +} + +.progress-striped .bar { + background-color: #149bdf; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + -moz-background-size: 40px 40px; + -o-background-size: 40px 40px; + background-size: 40px 40px +} + +.progress.active .bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite +} + +.progress-danger .bar, .progress .bar-danger { + background-color: #dd514c; + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0) +} + +.progress-danger.progress-striped .bar, .progress-striped .bar-danger { + background-color: #ee5f5b; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) +} + +.progress-success .bar, .progress .bar-success { + background-color: #5eb95e; + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(to bottom, #62c462, #57a957); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0) +} + +.progress-success.progress-striped .bar, .progress-striped .bar-success { + background-color: #62c462; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) +} + +.progress-info .bar, .progress .bar-info { + background-color: #4bb1cf; + background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); + background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); + background-image: -o-linear-gradient(top, #5bc0de, #339bb9); + background-image: linear-gradient(to bottom, #5bc0de, #339bb9); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0) +} + +.progress-info.progress-striped .bar, .progress-striped .bar-info { + background-color: #5bc0de; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) +} + +.progress-warning .bar, .progress .bar-warning { + background-color: #faa732; + background-image: -moz-linear-gradient(top, #fbb450, #f89406); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: -o-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0) +} + +.progress-warning.progress-striped .bar, .progress-striped .bar-warning { + background-color: #fbb450; + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent) +} + +.accordion { + margin-bottom: 20px +} + +.accordion-group { + margin-bottom: 2px; + border: 1px solid #e5e5e5; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px +} + +.accordion-heading { + border-bottom: 0 +} + +.accordion-heading .accordion-toggle { + display: block; + padding: 8px 15px +} + +.accordion-toggle { + cursor: pointer +} + +.accordion-inner { + padding: 9px 15px; + border-top: 1px solid #e5e5e5 +} + +.carousel { + position: relative; + margin-bottom: 20px; + line-height: 1 +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden +} + +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -moz-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left +} + +.carousel-inner > .item > img, .carousel-inner > .item > a > img { + display: block; + line-height: 1 +} + +.carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { + display: block +} + +.carousel-inner > .active { + left: 0 +} + +.carousel-inner > .next, .carousel-inner > .prev { + position: absolute; + top: 0; + width: 100% +} + +.carousel-inner > .next { + left: 100% +} + +.carousel-inner > .prev { + left: -100% +} + +.carousel-inner > .next.left, .carousel-inner > .prev.right { + left: 0 +} + +.carousel-inner > .active.left { + left: -100% +} + +.carousel-inner > .active.right { + left: 100% +} + +.carousel-control { + position: absolute; + top: 40%; + left: 15px; + width: 40px; + height: 40px; + margin-top: -20px; + font-size: 60px; + font-weight: 100; + line-height: 30px; + color: #fff; + text-align: center; + background: #222; + border: 3px solid #fff; + -webkit-border-radius: 23px; + -moz-border-radius: 23px; + border-radius: 23px; + opacity: .5; + filter: alpha(opacity=50) +} + +.carousel-control.right { + right: 15px; + left: auto +} + +.carousel-control:hover, .carousel-control:focus { + color: #fff; + text-decoration: none; + opacity: .9; + filter: alpha(opacity=90) +} + +.carousel-indicators { + position: absolute; + top: 15px; + right: 15px; + z-index: 5; + margin: 0; + list-style: none +} + +.carousel-indicators li { + display: block; + float: left; + width: 10px; + height: 10px; + margin-left: 5px; + text-indent: -999px; + background-color: #ccc; + background-color: rgba(255, 255, 255, 0.25); + border-radius: 5px +} + +.carousel-indicators .active { + background-color: #fff +} + +.carousel-caption { + position: absolute; + right: 0; + bottom: 0; + left: 0; + padding: 15px; + background: #333; + background: rgba(0, 0, 0, 0.75) +} + +.carousel-caption h4, .carousel-caption p { + line-height: 20px; + color: #fff +} + +.carousel-caption h4 { + margin: 0 0 5px +} + +.carousel-caption p { + margin-bottom: 0 +} + +.hero-unit { + padding: 60px; + margin-bottom: 30px; + font-size: 18px; + font-weight: 200; + line-height: 30px; + color: inherit; + background-color: #eee; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px +} + +.hero-unit h1 { + margin-bottom: 0; + font-size: 60px; + line-height: 1; + letter-spacing: -1px; + color: inherit +} + +.hero-unit li { + line-height: 30px +} + +.pull-right { + float: right +} + +.pull-left { + float: left +} + +.hide { + display: none +} + +.show { + display: block +} + +.invisible { + visibility: hidden +} + +.affix { + position: fixed +} diff --git a/public/libs/bootstrap/img/glyphicons-halflings-white.png b/public/libs/bootstrap/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf6484a29d8da269f9bc874b25493a45fae3bae GIT binary patch literal 8777 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 B7G?kd literal 0 HcmV?d00001 diff --git a/public/libs/bootstrap/img/glyphicons-halflings.png b/public/libs/bootstrap/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643 GIT binary patch literal 12799 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 literal 0 HcmV?d00001 diff --git a/public/libs/bootstrap/js/bootstrap.js b/public/libs/bootstrap/js/bootstrap.js new file mode 100644 index 0000000000..87fa5b4eb0 --- /dev/null +++ b/public/libs/bootstrap/js/bootstrap.js @@ -0,0 +1,2117 @@ +/* =================================================== + * bootstrap-transition.js v2.3.1 + * http://twitter.github.com/bootstrap/javascript.html#transitions + * =================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) + * ======================================================= */ + + $(function () { + + $.support.transition = (function () { + + var transitionEnd = (function () { + + var el = document.createElement('bootstrap') + , transEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd otransitionend', 'transition': 'transitionend' + } + , name + + for (name in transEndEventNames) { + if (el.style[name] !== undefined) { + return transEndEventNames[name] + } + } + + }()) + + return transitionEnd && { + end: transitionEnd + } + + })() + + }) + +}(window.jQuery); +/* ========================================================== + * bootstrap-alert.js v2.3.1 + * http://twitter.github.com/bootstrap/javascript.html#alerts + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* ALERT CLASS DEFINITION + * ====================== */ + + var dismiss = '[data-dismiss="alert"]' + , Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + , selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = $(selector) + + e && e.preventDefault() + + $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) + + $parent.trigger(e = $.Event('close')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent + .trigger('closed') + .remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent.on($.support.transition.end, removeElement) : + removeElement() + } + + + /* ALERT PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('alert') + if (!data) $this.data('alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + /* ALERT NO CONFLICT + * ================= */ + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + /* ALERT DATA-API + * ============== */ + + $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) + +}(window.jQuery); +/* ============================================================ + * bootstrap-button.js v2.3.1 + * http://twitter.github.com/bootstrap/javascript.html#buttons + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* BUTTON PUBLIC CLASS DEFINITION + * ============================== */ + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.button.defaults, options) + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + , $el = this.$element + , data = $el.data() + , val = $el.is('input') ? 'val' : 'html' + + state = state + 'Text' + data.resetText || $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout(function () { + state == 'loadingText' ? + $el.addClass(d).attr(d, d) : + $el.removeClass(d).removeAttr(d) + }, 0) + } + + Button.prototype.toggle = function () { + var $parent = this.$element.closest('[data-toggle="buttons-radio"]') + + $parent && $parent + .find('.active') + .removeClass('active') + + this.$element.toggleClass('active') + } + + + /* BUTTON PLUGIN DEFINITION + * ======================== */ + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('button') + , options = typeof option == 'object' && option + if (!data) $this.data('button', (data = new Button(this, options))) + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.defaults = { + loadingText: 'loading...' + } + + $.fn.button.Constructor = Button + + + /* BUTTON NO CONFLICT + * ================== */ + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + /* BUTTON DATA-API + * =============== */ + + $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + }) + +}(window.jQuery); +/* ========================================================== + * bootstrap-carousel.js v2.3.1 + * http://twitter.github.com/bootstrap/javascript.html#carousel + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* CAROUSEL CLASS DEFINITION + * ========================= */ + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.prototype = { + + cycle: function (e) { + if (!e) this.paused = false + if (this.interval) clearInterval(this.interval); + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + return this + }, getActiveIndex: function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + return this.$items.index(this.$active) + }, to: function (pos) { + var activeIndex = this.getActiveIndex() + , that = this + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) { + return this.$element.one('slid', function () { + that.to(pos) + }) + } + + if (activeIndex == pos) { + return this.pause().cycle() + } + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + }, pause: function (e) { + if (!e) this.paused = true + if (this.$element.find('.next, .prev').length && $.support.transition.end) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + clearInterval(this.interval) + this.interval = null + return this + }, next: function () { + if (this.sliding) return + return this.slide('next') + }, prev: function () { + if (this.sliding) return + return this.slide('prev') + }, slide: function (type, next) { + var $active = this.$element.find('.item.active') + , $next = next || $active[type]() + , isCycling = this.interval + , direction = type == 'next' ? 'left' : 'right' + , fallback = type == 'next' ? 'first' : 'last' + , that = this + , e + + this.sliding = true + + isCycling && this.pause() + + $next = $next.length ? $next : this.$element.find('.item')[fallback]() + + e = $.Event('slide', { + relatedTarget: $next[0], direction: direction + }) + + if ($next.hasClass('active')) return + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + this.$element.one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { + that.$element.trigger('slid') + }, 0) + }) + } else { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } + + isCycling && this.cycle() + + return this + } + + } + + + /* CAROUSEL PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('carousel') + , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) + , action = typeof option == 'string' ? option : options.slide + if (!data) $this.data('carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.defaults = { + interval: 5000, pause: 'hover' + } + + $.fn.carousel.Constructor = Carousel + + + /* CAROUSEL NO CONFLICT + * ==================== */ + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + /* CAROUSEL DATA-API + * ================= */ + + $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + , options = $.extend({}, $target.data(), $this.data()) + , slideIndex + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('carousel').pause().to(slideIndex).cycle() + } + + e.preventDefault() + }) + +}(window.jQuery); +/* ============================================================= + * bootstrap-collapse.js v2.3.1 + * http://twitter.github.com/bootstrap/javascript.html#collapse + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* COLLAPSE PUBLIC CLASS DEFINITION + * ================================ */ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.collapse.defaults, options) + + if (this.options.parent) { + this.$parent = $(this.options.parent) + } + + this.options.toggle && this.toggle() + } + + Collapse.prototype = { + + constructor: Collapse, dimension: function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + }, show: function () { + var dimension + , scroll + , actives + , hasData + + if (this.transitioning || this.$element.hasClass('in')) return + + dimension = this.dimension() + scroll = $.camelCase(['scroll', dimension].join('-')) + actives = this.$parent && this.$parent.find('> .accordion-group > .in') + + if (actives && actives.length) { + hasData = actives.data('collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('collapse', null) + } + + this.$element[dimension](0) + this.transition('addClass', $.Event('show'), 'shown') + $.support.transition && this.$element[dimension](this.$element[0][scroll]) + }, hide: function () { + var dimension + if (this.transitioning || !this.$element.hasClass('in')) return + dimension = this.dimension() + this.reset(this.$element[dimension]()) + this.transition('removeClass', $.Event('hide'), 'hidden') + this.$element[dimension](0) + }, reset: function (size) { + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + [dimension](size || 'auto') + [0].offsetWidth + + this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') + + return this + }, transition: function (method, startEvent, completeEvent) { + var that = this + , complete = function () { + if (startEvent.type == 'show') that.reset() + that.transitioning = 0 + that.$element.trigger(completeEvent) + } + + this.$element.trigger(startEvent) + + if (startEvent.isDefaultPrevented()) return + + this.transitioning = 1 + + this.$element[method]('in') + + $.support.transition && this.$element.hasClass('collapse') ? + this.$element.one($.support.transition.end, complete) : + complete() + }, toggle: function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* COLLAPSE PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('collapse') + , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.defaults = { + toggle: true + } + + $.fn.collapse.Constructor = Collapse + + + /* COLLAPSE NO CONFLICT + * ==================== */ + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + /* COLLAPSE DATA-API + * ================= */ + + $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + , target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + , option = $(target).data('collapse') ? 'toggle' : $this.data() + $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + $(target).collapse(option) + }) + +}(window.jQuery); +/* ============================================================ + * bootstrap-dropdown.js v2.3.1 + * http://twitter.github.com/bootstrap/javascript.html#dropdowns + * ============================================================ + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown, toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + $parent.toggleClass('open') + } + + $this.focus() + + return false + }, keydown: function (e) { + var $this + , $items + , $active + , $parent + , isActive + , index + + if (!/(38|40|27)/.test(e.keyCode)) return + + $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + if (!isActive || (isActive && e.keyCode == 27)) { + if (e.which == 27) $parent.find(toggle).focus() + return $this.click() + } + + $items = $('[role=menu] li:not(.divider):visible a', $parent) + + if (!$items.length) return + + index = $items.index($items.filter(':focus')) + + if (e.keyCode == 38 && index > 0) index-- // up + if (e.keyCode == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 + + $items + .eq(index) + .focus() + } + + } + + function clearMenus() { + $(toggle).each(function () { + getParent($(this)).removeClass('open') + }) + } + + function getParent($this) { + var selector = $this.attr('data-target') + , $parent + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + $parent = selector && $(selector) + + if (!$parent || !$parent.length) $parent = $this.parent() + + return $parent + } + + + /* DROPDOWN PLUGIN DEFINITION + * ========================== */ + + var old = $.fn.dropdown + + $.fn.dropdown = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('dropdown') + if (!data) $this.data('dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.dropdown.Constructor = Dropdown + + + /* DROPDOWN NO CONFLICT + * ==================== */ + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + /* APPLY TO STANDARD DROPDOWN ELEMENTS + * =================================== */ + + $(document) + .on('click.dropdown.data-api', clearMenus) + .on('click.dropdown.data-api', '.dropdown form', function (e) { + e.stopPropagation() + }) + .on('click.dropdown-menu', function (e) { + e.stopPropagation() + }) + .on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle) + .on('keydown.dropdown.data-api', toggle + ', [role=menu]', Dropdown.prototype.keydown) + +}(window.jQuery); +/* ========================================================= + * bootstrap-modal.js v2.3.1 + * http://twitter.github.com/bootstrap/javascript.html#modals + * ========================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* MODAL CLASS DEFINITION + * ====================== */ + + var Modal = function (element, options) { + this.options = options + this.$element = $(element) + .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) + this.options.remote && this.$element.find('.modal-body').load(this.options.remote) + } + + Modal.prototype = { + + constructor: Modal, toggle: function () { + return this[!this.isShown ? 'show' : 'hide']() + }, show: function () { + var that = this + , e = $.Event('show') + + this.$element.trigger(e) + + if (this.isShown || e.isDefaultPrevented()) return + + this.isShown = true + + this.escape() + + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + if (!that.$element.parent().length) { + that.$element.appendTo(document.body) //don't move modals dom position + } + + that.$element.show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element + .addClass('in') + .attr('aria-hidden', false) + + that.enforceFocus() + + transition ? + that.$element.one($.support.transition.end, function () { + that.$element.focus().trigger('shown') + }) : + that.$element.focus().trigger('shown') + + }) + }, hide: function (e) { + e && e.preventDefault() + + var that = this + + e = $.Event('hide') + + this.$element.trigger(e) + + if (!this.isShown || e.isDefaultPrevented()) return + + this.isShown = false + + this.escape() + + $(document).off('focusin.modal') + + this.$element + .removeClass('in') + .attr('aria-hidden', true) + + $.support.transition && this.$element.hasClass('fade') ? + this.hideWithTransition() : + this.hideModal() + }, enforceFocus: function () { + var that = this + $(document).on('focusin.modal', function (e) { + if (that.$element[0] !== e.target && !that.$element.has(e.target).length) { + that.$element.focus() + } + }) + }, escape: function () { + var that = this + if (this.isShown && this.options.keyboard) { + this.$element.on('keyup.dismiss.modal', function (e) { + e.which == 27 && that.hide() + }) + } else if (!this.isShown) { + this.$element.off('keyup.dismiss.modal') + } + }, hideWithTransition: function () { + var that = this + , timeout = setTimeout(function () { + that.$element.off($.support.transition.end) + that.hideModal() + }, 500) + + this.$element.one($.support.transition.end, function () { + clearTimeout(timeout) + that.hideModal() + }) + }, hideModal: function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.removeBackdrop() + that.$element.trigger('hidden') + }) + }, removeBackdrop: function () { + this.$backdrop && this.$backdrop.remove() + this.$backdrop = null + }, backdrop: function (callback) { + var that = this + , animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $('