Explorar el Código

Initial commit

Markus Ochel hace 13 años
commit
d9a4cbb2b9
Se han modificado 51 ficheros con 2520 adiciones y 0 borrados
  1. 5 0
      .gitignore
  2. 19 0
      README.md
  3. 67 0
      admin/controllers/index.coffee
  4. 37 0
      admin/kanso.json
  5. 223 0
      admin/lib/spine-couch-ajax.coffee
  6. 14 0
      admin/models/author.coffee
  7. 14 0
      admin/models/block.coffee
  8. 16 0
      admin/models/collection.coffee
  9. 14 0
      admin/models/contact.coffee
  10. 16 0
      admin/models/essay.coffee
  11. 14 0
      admin/models/site.coffee
  12. 15 0
      admin/models/sponsor.coffee
  13. 0 0
      admin/server/lists.coffee
  14. 51 0
      admin/server/rewrites.coffee
  15. 6 0
      admin/server/setup.coffee
  16. 9 0
      admin/server/shows.coffee
  17. 35 0
      admin/server/updates.coffee
  18. 20 0
      admin/server/validate.coffee
  19. 15 0
      admin/server/views.coffee
  20. 719 0
      admin/static/css/bootstrap.css
  21. 3 0
      admin/static/css/index.styl
  22. 89 0
      admin/static/css/mixin.styl
  23. 0 0
      admin/static/css/theme.styl
  24. 1 0
      admin/templates/404.html
  25. 20 0
      admin/templates/base.html
  26. 31 0
      admin/templates/home.html
  27. 12 0
      admin/templates/index.html
  28. 1 0
      admin/templates/test.html
  29. 35 0
      site/kanso.json
  30. 8 0
      site/lib/app.coffee
  31. 2 0
      site/server/filters.coffee
  32. 206 0
      site/server/lists.coffee
  33. 67 0
      site/server/rewrites.coffee
  34. 6 0
      site/server/setup.coffee
  35. 9 0
      site/server/shows.coffee
  36. 0 0
      site/server/utils.coffee
  37. 58 0
      site/server/views.coffee
  38. 3 0
      site/static/css/index.styl
  39. 94 0
      site/static/css/mixin.styl
  40. 65 0
      site/static/css/responsive.styl
  41. 274 0
      site/static/css/theme.styl
  42. 3 0
      site/static/js/modernizr.custom.js
  43. 1 0
      site/templates/404.html
  44. 1 0
      site/templates/area.html
  45. 68 0
      site/templates/base.html
  46. 44 0
      site/templates/collection.html
  47. 14 0
      site/templates/collections.html
  48. 71 0
      site/templates/essay.html
  49. 17 0
      site/templates/essays.html
  50. 7 0
      site/templates/home.html
  51. 1 0
      site/templates/test.html

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+.DS_Store
+.kansorc
+*.sublime-*
+packages
+node_modules

+ 19 - 0
README.md

@@ -0,0 +1,19 @@
+Fonts
+-----
+
+**Google Fonts URL**
+
+http://www.google.com/webfonts#ReviewPlace:refine/Collection:Dosis:200,400,700|Lato:300,400,700|Droid+Serif:400,700,400italic,700italic
+
+    font-family: 'Lato', sans-serif;
+    font-weight: normal;
+    font-size: 18px;
+    letter-spacing: 0em;
+    word-spacing: 0.2em;
+    line-height: 1.5;
+
+
+Donation URL
+------------
+
+    https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N62XWCYGBQRQY

+ 67 - 0
admin/controllers/index.coffee

@@ -0,0 +1,67 @@
+Spine       = require('spine/core')
+templates   = require('duality/templates')
+session     = require('session')
+
+# Sites       = require('controllers/sites')
+# Authors     = require('controllers/authors')
+# Collections = require('controllers/collections')
+# Essays      = require('controllers/essays')
+# Blocks      = require('controllers/blocks')
+# Sponsors    = require('controllers/sponsors')
+# Contacts    = require('controllers/contacts')
+
+Site        = require('models/site')
+Author      = require('models/author')
+Collection  = require('models/collection')
+Essay       = require('models/essay')
+Block       = require('models/block')
+Sponsor     = require('models/sponsor')
+Contact     = require('models/contact')
+
+
+class App extends Spine.Controller
+  
+  constructor: ->
+    super
+    @checkSession()
+
+  checkSession: ->
+    session.info (err, info) =>
+      if '_admin' in info.userCtx.roles
+        @render()
+      else
+        username = 'admin'
+        pass = 'couchaxs'
+        session.login username, pass, (err, resp) =>
+          if err
+            alert "Error logging in as #{username}: #{err}"
+          else
+            if '_admin' in resp.roles
+              @render()
+            else
+              alert "User #{username} does not have permission"
+
+  render: ->
+    site = new Sites
+    Site.fetch()
+    Author.fetch()
+    Collection.fetch()
+    Essay.fetch()
+    Block.fetch()
+    Sponsor.fetch()
+    Contact.fetch()
+
+    @context =
+      sites: Site.all()
+      authors: Author.all()
+      collections: Collection.all()
+      essays: Essay.all()
+      blocks: Block.all()
+      sponsors: Sponsor.all()
+      contacts: Contact.all()
+
+    @el.html templates.render('home.html', {}, @context)
+
+
+module.exports = App
+    

+ 37 - 0
admin/kanso.json

@@ -0,0 +1,37 @@
+{
+  "name": "admin",
+  "version": "0.0.1",
+  "description": "Kleks admin application that allows writers to manage content.",
+  "load": "server/setup",
+  "modules": ["server","controllers","models","lib"],
+  "handlebars": {
+    "templates": "templates"
+  },
+  "attachments": ["static"],
+  "duality": { "base_template": "base.html" },
+  "coffee-script": {
+    "modules": ["server","controllers","models","lib"]
+  },
+  "stylus": {
+      "compress": true,
+      "compile": "static/css/index.styl",
+      "remove_from_attachments": true
+  },
+  "dependencies": {
+    "modules": null,
+    "settings": null,
+    "attachments": null,
+    "properties": null,
+    "db": null,
+    "coffee-script-precompiler": null,
+    "stylus-precompiler": null,
+    "duality": null,
+    "handlebars": null,
+    "handlebars-helpers": null,
+    "duality-handlebars": null,
+
+    "jquery": null,
+    "spine": null,
+    "underscore": null
+  }
+}

+ 223 - 0
admin/lib/spine-couch-ajax.coffee

@@ -0,0 +1,223 @@
+Spine   = require('spine/core')
+$       = Spine.$
+Model   = Spine.Model
+{_}     = require("underscore")
+duality = require("duality/core")
+
+Spine.Model.include
+  toJSON: ->
+    result = {}
+    for key in @constructor.attributes when key of @
+      if typeof @[key] is 'function'
+        result[key] = @[key]()
+      else
+        result[key] = @[key]
+    result.id = result._id = @_id if @_id
+    result
+
+Spine.Model.extend
+  fromJSON: (objects) ->
+    make_object = (val) =>
+      val.id = val._id unless val.id
+      val._id = val.id unless val._id
+      new @(val)
+    return unless objects
+    if typeof objects is 'string'
+      objects = JSON.parse(objects)
+    if Spine.isArray(objects)
+      for value in objects
+        make_object(value)
+    else
+      make_object(objects)
+
+CouchAjax =
+  getURL: (object) ->
+    object and object.url?() or object.url
+
+  enabled:  true
+  pending:  false
+  requests: []
+
+  disable: (callback) ->
+    @enabled = false
+    do callback
+    @enabled = true
+
+  requestNext: ->
+    next = @requests.shift()
+    if next
+      @request(next)
+    else
+      @pending = false
+
+  request: (callback) ->
+    (do callback).complete(=> do @requestNext)
+      
+  queue: (callback) ->
+    return unless @enabled
+    if @pending
+      @requests.push(callback)
+    else
+      @pending = true
+      @request(callback)    
+    callback
+    
+class Base
+  defaults:
+    contentType: 'application/json'
+    dataType: 'json'
+    processData: false
+    headers: {'X-Requested-With': 'XMLHttpRequest'}
+  
+  ajax: (params, defaults) ->
+    $.ajax($.extend({}, @defaults, defaults, params))
+    
+  queue: (callback) ->
+    CouchAjax.queue(callback)
+
+class Collection extends Base
+  constructor: (@model) -> 
+    
+  find: (id, params) ->
+    record = new @model(id: id)
+    @ajax(
+      params,
+      type: 'GET',
+      url:  CouchAjax.getURL(record)
+    ).success(@recordsResponse)
+     .error(@errorResponse)
+    
+  all: (params) ->
+    @ajax(
+      params,
+      type: 'GET',
+      url:  CouchAjax.getURL(@model)
+    ).success(@recordsResponse)
+     .error(@errorResponse)
+    
+  fetch: (params = {}) ->
+    if id = params.id
+      delete params.id
+      @find(id, params).success (record) =>
+        @model.refresh(_.pluck(record.rows, "doc"))
+    else
+      @all(params).success (records) =>
+        @model.refresh(_.pluck(records.rows, "doc"))
+    
+  recordsResponse: (data, status, xhr) =>
+    @model.trigger('ajaxSuccess', null, status, xhr)
+
+  errorResponse: (xhr, statusText, error) =>
+    @model.trigger('ajaxError', null, xhr, statusText, error)
+
+class Singleton extends Base
+  constructor: (@record) ->
+    @model = @record.constructor
+  
+  reload: (params, options) ->
+    @queue =>
+      @ajax(
+        params,
+        type: 'GET'
+        url:  CouchAjax.getURL(@record)
+      ).success(@recordResponse(options))
+       .error(@errorResponse(options))
+  
+  create: (params, options) ->
+    @queue =>
+      @ajax(
+        params,
+        type: 'POST'
+        data: JSON.stringify(@record)
+        url:  CouchAjax.getURL(@model)
+      ).success(@recordResponse(options))
+       .error(@errorResponse(options))
+
+  update: (params, options) ->
+    @queue =>
+      @ajax(
+        params,
+        type: 'PUT'
+        data: JSON.stringify(@record)
+        url:  CouchAjax.getURL(@record)
+      ).success(@recordResponse(options))
+       .error(@errorResponse(options))
+  
+  destroy: (params, options) ->
+    @queue =>
+      @ajax(
+        params,
+        type: 'DELETE'
+        url:  CouchAjax.getURL(@record)
+      ).success(@recordResponse(options))
+       .error(@errorResponse(options))
+
+  # Private
+
+  recordResponse: (options = {}) =>
+    (data, status, xhr) =>
+      if Spine.isBlank(data)
+        data = false
+      else if data.rows
+        data = @model.fromJSON(_.pluck(data.rows, "doc"))
+      else
+        data = @model.fromJSON(data)
+    
+      CouchAjax.disable =>
+        if data
+          # ID change, need to do some shifting
+          if data.id and @record.id isnt data.id
+            @record.changeID(data.id)
+
+          # Update with latest data
+          @record.updateAttributes(data.attributes())
+        
+      @record.trigger('ajaxSuccess', data, status, xhr)
+      options.success?.apply(@record)
+      
+  errorResponse: (options = {}) =>
+    (xhr, statusText, error) =>
+      @record.trigger('ajaxError', xhr, statusText, error)
+      options.error?.apply(@record)
+
+# CouchAjax endpoint
+Model.host = ''
+
+Include =
+  ajax: -> new Singleton(this)
+
+  url: ->
+    base = CouchAjax.getURL(@constructor)
+    base += '/' unless base.charAt(base.length - 1) is '/'
+    base += encodeURIComponent(@id)
+    base
+    
+Extend = 
+  ajax: -> new Collection(this)
+
+  url: ->
+    "#{duality.getBaseURL()}/spine-adapter/#{@className.toLowerCase()}"
+      
+Model.CouchAjax =
+  extended: ->
+    @fetch @ajaxFetch
+    @change @ajaxChange
+    
+    @extend Extend
+    @include Include
+    
+  ajaxFetch: ->
+    @ajax().fetch(arguments...)
+    
+  ajaxChange: (record, type, options = {}) ->
+    record.ajax()[type](options.ajax, options)
+    
+Model.CouchAjax.Methods = 
+  extended: ->
+    @extend Extend
+    @include Include
+    
+# Globals
+CouchAjax.defaults   = Base::defaults
+Spine.CouchAjax      = CouchAjax
+module?.exports = CouchAjax

+ 14 - 0
admin/models/author.coffee

@@ -0,0 +1,14 @@
+Spine = require('spine/core')
+require('lib/spine-couch-ajax')
+
+class Author extends Spine.Model
+  @configure "Author", "site", "name", "email", "bio", "links", "photo_url"
+  @extend Spine.Model.CouchAjax
+  
+  @nameSort: (a, b) ->
+    if a.name > b.name then 1 else -1
+    
+  validate: ->
+    return 'Name is required' unless @name
+
+module.exports = Author

+ 14 - 0
admin/models/block.coffee

@@ -0,0 +1,14 @@
+Spine = require('spine/core')
+require('lib/spine-couch-ajax')
+
+class Block extends Spine.Model
+  @configure "Block", "site", "code", "name", "content"
+  @extend Spine.Model.CouchAjax
+  
+  @nameSort: (a, b) ->
+    if a.name > b.name then 1 else -1
+    
+  validate: ->
+    return 'Name is required' unless @name
+
+module.exports = Block

+ 16 - 0
admin/models/collection.coffee

@@ -0,0 +1,16 @@
+Spine = require('spine/core')
+require('lib/spine-couch-ajax')
+
+class Collection extends Spine.Model
+  @configure "Collection", "site", "slug", "name", "intro"
+  @extend Spine.Model.CouchAjax
+  
+  @nameSort: (a, b) ->
+    if a.name > b.name then 1 else -1
+    
+  validate: ->
+    return 'Site is required' unless @site
+    return 'Slug is required' unless @slug
+    return 'Name is required' unless @name
+
+module.exports = Collection

+ 14 - 0
admin/models/contact.coffee

@@ -0,0 +1,14 @@
+Spine = require('spine/core')
+require('lib/spine-couch-ajax')
+
+class Contact extends Spine.Model
+  @configure "Contact", "name", "email", "note"
+  @extend Spine.Model.CouchAjax
+  
+  @nameSort: (a, b) ->
+    if a.name > b.name then 1 else -1
+    
+  validate: ->
+    return 'Name is required' unless @name
+
+module.exports = Contact

+ 16 - 0
admin/models/essay.coffee

@@ -0,0 +1,16 @@
+Spine = require('spine/core')
+require('lib/spine-couch-ajax')
+
+class Essay extends Spine.Model
+  @configure "Essay", "site", "slug", "title", "intro", "body", "published", "published_at", "updated_at", "author_id", "sponsor_id", "collections"
+  @extend Spine.Model.CouchAjax
+  
+  @titleSort: (a, b) ->
+    if (a.title or a.published_at) > (b.title or b.published_at) then 1 else -1
+    
+  validate: ->
+    return 'Site is required' unless @site
+    return 'Slug is required' unless @slug
+    return 'Title is required' unless @title
+
+module.exports = Essay

+ 14 - 0
admin/models/site.coffee

@@ -0,0 +1,14 @@
+Spine = require('spine/core')
+require('lib/spine-couch-ajax')
+
+class Site extends Spine.Model
+  @configure "Site", "name", "name_html", "tagline", "footer_html", "url", "theme", "css", "google_analytics_code"
+  @extend Spine.Model.CouchAjax
+  
+  @nameSort: (a, b) ->
+    if a.name > b.name then 1 else -1
+    
+  validate: ->
+    return 'Name is required' unless @name
+
+module.exports = Site

+ 15 - 0
admin/models/sponsor.coffee

@@ -0,0 +1,15 @@
+Spine = require('spine/core')
+require('lib/spine-couch-ajax')
+
+class Sponsor extends Spine.Model
+  @configure "Sponsor", "format", "name", "url", "label", "content", "note", "contact_id"
+  @extend Spine.Model.CouchAjax
+  
+  @nameSort: (a, b) ->
+    if a.name > b.name then 1 else -1
+    
+  validate: ->
+    @format ?= 'text'
+    return 'Name is required' unless @name
+
+module.exports = Sponsor

+ 0 - 0
admin/server/lists.coffee


+ 51 - 0
admin/server/rewrites.coffee

@@ -0,0 +1,51 @@
+module.exports = [
+  # static
+  { from: "/static/*", to: "static/*" }
+
+  # Spine adapter
+  {
+    from: "/spine-adapter/:type",
+    to: "_update/spine_adapter_model",
+    method: "POST"
+  }
+
+  {
+    from: "/spine-adapter/:type/:id",
+    to: "_update/spine_adapter_model/:id",
+    method: "PUT"
+  }
+
+  {
+    from: "/spine-adapter/:type/:id",
+    to: "_update/spine_adapter_model/:id",
+    method: "DELETE"
+  }
+
+  {
+    from: "/spine-adapter/:type",
+    to: "_view/docs_by_type",
+    method: "GET",
+    query: {
+      start_key: [":type"],
+      end_key: [":type", {}],
+      include_docs: "true"
+    }
+  }
+
+  {
+    from: "/spine-adapter/:type/:id",
+    to: "_view/docs_by_type",
+    method: "GET",
+    query: {
+      start_key: [":type", ":id"],
+      end_key: [":type", ":id", {}],
+      include_docs: "true"
+    }
+  }
+
+  # show root
+  { from: "/", to: "_show/index" }
+
+  # catch all
+  { from: "*", to: "_show/not_found" }
+]

+ 6 - 0
admin/server/setup.coffee

@@ -0,0 +1,6 @@
+module.exports =
+  shows: require("./shows")
+  views: require("./views") 
+  lists: require("./lists")
+  rewrites: require("./rewrites")
+  validate_doc_update: require('./validate').validate_doc_update

+ 9 - 0
admin/server/shows.coffee

@@ -0,0 +1,9 @@
+templates = require("duality/templates") 
+
+exports.index = (doc, req) ->
+  title: "Kleks Admin"
+  content: templates.render("index.html", req, {})
+
+exports.not_found = (doc, req) ->
+  title: "404 Not Found"
+  content: templates.render("404.html", req, {})

+ 35 - 0
admin/server/updates.coffee

@@ -0,0 +1,35 @@
+_   = require('underscore')._
+
+exports.spine_adapter_model = (doc, req) ->
+  if req.method is 'POST'    
+    create(doc, req)
+  else if req.method is 'PUT'
+    update(doc, req)
+  else if req.method is 'DELETE'
+    destroy(doc, req)
+
+create = (doc, req) ->
+  doc = JSON.parse req.body
+  doc.type = req.query.type
+  doc._id = req.uuid unless doc._id
+  resp =
+    ok: yes
+    body: JSON.stringify(doc)
+  [doc, resp]
+
+update = (doc, req) ->
+  delete doc._revisions
+  new_fields = JSON.parse(req.body)
+  delete new_fields.id
+  updated_doc = _.defaults(new_fields, doc)
+  resp =
+    ok: yes
+    body: JSON.stringify(updated_doc)
+  [updated_doc, resp]
+
+destroy = (doc, req) ->
+  doc._deleted = yes
+  resp =
+    ok: yes
+    body: JSON.stringify({})
+  [doc, resp]

+ 20 - 0
admin/server/validate.coffee

@@ -0,0 +1,20 @@
+exports.validate_doc_update = (newDoc, oldDoc, userCtx) ->
+
+  is_admin = if '_admin' in userCtx.roles then true else false
+
+  if not is_admin
+    throw unauthorized: 'You are not a database admin'
+
+  if newDoc.type is 'essay'    
+    if not newDoc.site
+      throw forbidden: 'site is a required field'
+
+    if not newDoc.slug
+      throw forbidden: 'slug is a required field'
+    
+    if not newDoc.title
+      throw forbidden: 'title is a required field'
+    
+    if newDoc.published
+      if not newDoc.published_at
+        throw forbidden: 'Published essay must have a publish date'

+ 15 - 0
admin/server/views.coffee

@@ -0,0 +1,15 @@
+exports.docs_by_site =
+  map: (doc) ->
+    if doc.site and doc.type
+      emit [doc.site, doc.type, doc._id], doc.title or doc.name
+    else if doc.type
+      emit ['global', doc.type, doc._id], doc.title or doc.name
+    else
+      emit ['global', '_doc_', doc._id], doc.title or doc.name
+  reduce: (key, values, rereduce) ->
+    key.length
+
+exports.docs_by_type =
+  map: (doc) ->
+    if doc.type
+      emit [doc.type, doc._id], doc.title or doc.name

+ 719 - 0
admin/static/css/bootstrap.css

@@ -0,0 +1,719 @@
+/*
+ * Bootstrap v2.0.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.
+ */
+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%;}
+html -webkit-text-size-adjust: 100%{-ms-text-size-adjust:100%}
+a:hover,a:active{outline:0}
+sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{max-width:100%;height:auto;border:0;-ms-interpolation-mode:bicubic}
+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,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}
+input[type="search"]{-webkit-appearance:textfield;}
+input[type="search"] -webkit-box-sizing: content-box -moz-box-sizing: content-box{box-sizing:content-box}
+input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}
+textarea{overflow:auto;vertical-align:top}
+body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333;background-color:#fff}
+a{color:#08c;text-decoration:none}
+a:hover{color:#0074ad;text-decoration:underline}
+.row{margin-left:-20px;*zoom:1;}
+.row:before,.row:after{display:table;content:""}
+.row:after{clear:both}
+[class*="span"]{float:left;margin-left:20px}
+.span1{width:60px}
+.span2{width:140px}
+.span3{width:220px}
+.span4{width:300px}
+.span5{width:380px}
+.span6{width:460px}
+.span7{width:540px}
+.span8{width:620px}
+.span9{width:700px}
+.span10{width:780px}
+.span11{width:860px}
+.span12,.container{width:940px}
+.offset1{margin-left:100px}
+.offset2{margin-left:180px}
+.offset3{margin-left:260px}
+.offset4{margin-left:340px}
+.offset5{margin-left:420px}
+.offset6{margin-left:500px}
+.offset7{margin-left:580px}
+.offset8{margin-left:660px}
+.offset9{margin-left:740px}
+.offset10{margin-left:820px}
+.offset11{margin-left:900px}
+.row-fluid{width:100%;*zoom:1;}
+.row-fluid:before,.row-fluid:after{display:table;content:""}
+.row-fluid:after{clear:both}
+.row-fluid > [class*="span"]{float:left;margin-left:2.127659574%}
+.row-fluid > [class*="span"]:first-child{margin-left:0}
+.row-fluid > .span1{width:6.382978723%}
+.row-fluid > .span2{width:14.89361702%}
+.row-fluid > .span3{width:23.404255317%}
+.row-fluid > .span4{width:31.914893614%}
+.row-fluid > .span5{width:40.425531911%}
+.row-fluid > .span6{width:48.93617020799999%}
+.row-fluid > .span7{width:57.446808505%}
+.row-fluid > .span8{width:65.95744680199999%}
+.row-fluid > .span9{width:74.468085099%}
+.row-fluid > .span10{width:82.97872339599999%}
+.row-fluid > .span11{width:91.489361693%}
+.row-fluid > .span12{width:99.99999998999999%}
+.container{width:940px;margin-left:auto;margin-right:auto;*zoom:1;}
+.container:before,.container:after{display:table;content:""}
+.container:after{clear:both}
+.container-fluid{padding-left:20px;padding-right:20px;*zoom:1;}
+.container-fluid:before,.container-fluid:after{display:table;content:""}
+.container-fluid:after{clear:both}
+p{margin:0 0 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}
+p small{font-size:11px;color:#999}
+.lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px}
+h1,h2,h3,h4,h5,h6{margin:0;font-weight:bold;color:#333;text-rendering:optimizelegibility;}
+h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999}
+h1{font-size:30px;line-height:36px;}
+h1 small{font-size:18px}
+h2{font-size:24px;line-height:36px;}
+h2 small{font-size:18px}
+h3{line-height:27px;font-size:18px;}
+h3 small{font-size:14px}
+h4,h5,h6{line-height:18px}
+h4{font-size:14px;}
+h4 small{font-size:12px}
+h5{font-size:12px}
+h6{font-size:11px;color:#999;text-transform:uppercase}
+.page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eee}
+.page-header h1{line-height:1}
+ul,ol{padding:0;margin:0 0 9px 25px}
+ul ul,ul ol,ol ol,ol ul{margin-bottom:0}
+ul{list-style:disc}
+ol{list-style:decimal}
+li{line-height:18px}
+ul.unstyled,ol.unstyled{margin-left:0;list-style:none}
+dl{margin-bottom:18px}
+dt,dd{line-height:18px}
+dt{font-weight:bold}
+dd{margin-left:9px}
+hr{margin:18px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}
+strong{font-weight:bold}
+em{font-style:italic}
+.muted{color:#999}
+abbr{font-size:90%;text-transform:uppercase;border-bottom:1px dotted #ddd;cursor:help}
+blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eee;}
+blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px}
+blockquote small{display:block;line-height:18px;color:#999;}
+blockquote small:before{content:'\2014 \00A0'}
+blockquote.pull-right{float:right;padding-left:0;padding-right:15px;border-left:0;border-right:5px solid #eee;}
+blockquote.pull-right p,blockquote.pull-right small{text-align:right}
+q:before,q:after,blockquote:before,blockquote:after{content:""}
+address{display:block;margin-bottom:18px;line-height:18px;font-style:normal}
+small{font-size:100%}
+cite{font-style:normal}
+code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
+code{padding:3px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8}
+pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12px;line-height:18px;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;white-space:pre;white-space:pre-wrap;word-break:break-all;word-wrap:break-word;}
+pre.prettyprint{margin-bottom:18px}
+pre code{padding:0;color:inherit;background-color:transparent;border:0}
+.pre-scrollable{max-height:340px;overflow-y:scroll}
+form{margin:0 0 18px}
+fieldset{padding:0;margin:0;border:0}
+legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333;border:0;border-bottom:1px solid #eee;}
+legend small{font-size:13.5px;color:#999}
+label,input,button,select,textarea{font-size:13px;font-weight:normal;line-height:18px}
+input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}
+label{display:block;margin-bottom:5px;color:#333}
+input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
+.uneditable-textarea{width:auto;height:auto}
+label input,label textarea,label select{display:block}
+input[type="image"],input[type="checkbox"],input[type="radio"]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;cursor:pointer;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;border:0 9;}
+input[type="image"]{border:0}
+input[type="file"]{width:auto;padding:initial;line-height:initial;border:initial;background-color:#fff;background-color:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}
+input[type="button"],input[type="reset"],input[type="submit"]{width:auto;height:auto}
+select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px}
+input[type="file"]{line-height:18px 9}
+select{width:220px;background-color:#fff}
+select[multiple],select[size]{height:auto}
+input[type="image"]{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}
+textarea{height:auto}
+input[type="hidden"]{display:none}
+.radio,.checkbox{padding-left:18px}
+.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px}
+.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,textarea{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.07);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.07);box-shadow:inset 0 1px 1px rgba(0,0,0,0.07);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-ms-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}
+input:focus,textarea:focus{border-color:rgba(82,168,236,0.80);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.07),0 0 8px rgba(82,168,236,0.60);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.07),0 0 8px rgba(82,168,236,0.60);box-shadow:inset 0 1px 1px rgba(0,0,0,0.07),0 0 8px rgba(82,168,236,0.60);outline:0;outline:thin dotted 9;}
+input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}
+.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{float:none;margin-left:0}
+input.span1,textarea.span1,.uneditable-input.span1{width:50px}
+input.span2,textarea.span2,.uneditable-input.span2{width:130px}
+input.span3,textarea.span3,.uneditable-input.span3{width:210px}
+input.span4,textarea.span4,.uneditable-input.span4{width:290px}
+input.span5,textarea.span5,.uneditable-input.span5{width:370px}
+input.span6,textarea.span6,.uneditable-input.span6{width:450px}
+input.span7,textarea.span7,.uneditable-input.span7{width:530px}
+input.span8,textarea.span8,.uneditable-input.span8{width:610px}
+input.span9,textarea.span9,.uneditable-input.span9{width:690px}
+input.span10,textarea.span10,.uneditable-input.span10{width:770px}
+input.span11,textarea.span11,.uneditable-input.span11{width:850px}
+input.span12,textarea.span12,.uneditable-input.span12{width:930px}
+input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed}
+.control-group.warning > label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}
+.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853;}
+.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#b58b42;-webkit-box-shadow:0 0 6px #cdad75;-moz-box-shadow:0 0 6px #cdad75;box-shadow:0 0 6px #cdad75}
+.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 > label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}
+.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48;}
+.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#a74240;-webkit-box-shadow:0 0 6px #c76e6d;-moz-box-shadow:0 0 6px #c76e6d;box-shadow:0 0 6px #c76e6d}
+.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 > label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}
+.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847;}
+.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#3f7a40;-webkit-box-shadow:0 0 6px #5eac60;-moz-box-shadow:0 0 6px #5eac60;box-shadow:0 0 6px #5eac60}
+.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}
+input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b;}
+input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#eb423d;-webkit-box-shadow:0 0 6px #f17f7c;-moz-box-shadow:0 0 6px #f17f7c;box-shadow:0 0 6px #f17f7c}
+.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #ddd}
+.uneditable-input{display:block;background-color:#fff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.03);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.03);box-shadow:inset 0 1px 2px rgba(0,0,0,0.03);cursor:not-allowed}
+:-moz-placeholder{color:#999}
+::-webkit-input-placeholder{color:#999}
+.help-block{display:block;margin-top:5px;margin-bottom:0;color:#999}
+.help-inline{display:inline-block;*display:inline;*zoom:1;margin-bottom:9px;vertical-align:middle;padding-left:5px}
+.input-prepend,.input-append{margin-bottom:5px;*zoom:1;}
+.input-prepend:before,.input-append:before,.input-prepend:after,.input-append:after{display:table;content:""}
+.input-prepend:after,.input-append:after{clear:both}
+.input-prepend input,.input-append input,.input-prepend .uneditable-input,.input-append .uneditable-input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
+.input-prepend input:focus,.input-append input:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{position:relative;z-index:2}
+.input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc}
+.input-prepend .add-on,.input-append .add-on{float:left;display:block;width:auto;min-width:16px;height:18px;margin-right:-1px;padding:4px 5px;font-weight:normal;line-height:18px;color:#999;text-align:center;text-shadow:0 1px 0 #fff;background-color:#f5f5f5;border:1px solid #ccc;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}
+.input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546}
+.input-prepend .add-on{*margin-top:1px;}
+.input-append input,.input-append .uneditable-input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}
+.input-append .uneditable-input{border-left-color:#eee;border-right-color:#ccc}
+.input-append .add-on{margin-right:0;margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}
+.input-append input:first-child{*margin-left:-160px;}
+.input-append input:first-child+.add-on{*margin-left:-21px}
+.search-query{padding-left:14px;padding-right:14px;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius: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{display:inline-block;margin-bottom:0}
+.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}
+.form-search label,.form-inline label,.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{display:inline-block}
+.form-search .input-append .add-on,.form-inline .input-prepend .add-on,.form-search .input-append .add-on,.form-inline .input-prepend .add-on{vertical-align:middle}
+.form-search .radio,.form-inline .radio,.form-search .checkbox,.form-inline .checkbox{margin-bottom:0;vertical-align:middle}
+.control-group{margin-bottom:9px}
+legend + .control-group{margin-top:18px;-webkit-margin-top-collapse:separate}
+.form-horizontal .control-group{margin-bottom:18px;*zoom:1;}
+.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:""}
+.form-horizontal .control-group:after{clear:both}
+.form-horizontal .control-label{float:left;width:140px;padding-top:5px;text-align:right}
+.form-horizontal .controls{margin-left:160px}
+.form-horizontal .form-actions{padding-left:160px}
+table{max-width:100%;border-collapse:collapse;border-spacing:0}
+.table{width:100%;margin-bottom:18px;}
+.table th,.table td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid #ddd}
+.table th{font-weight:bold}
+.table thead th{vertical-align:bottom}
+.table thead:first-child tr th,.table thead:first-child tr td{border-top:0}
+.table tbody + tbody{border-top:2px solid #ddd}
+.table-condensed th,.table-condensed td{padding:4px 5px}
+.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
+.table-bordered th + th,.table-bordered td + td,.table-bordered th + td,.table-bordered td + th{border-left:1px solid #ddd}
+.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{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0}
+.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0}
+.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px}
+.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0}
+.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9}
+.table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5}
+table .span1{float:none;width:44px;margin-left:0}
+table .span2{float:none;width:124px;margin-left:0}
+table .span3{float:none;width:204px;margin-left:0}
+table .span4{float:none;width:284px;margin-left:0}
+table .span5{float:none;width:364px;margin-left:0}
+table .span6{float:none;width:444px;margin-left:0}
+table .span7{float:none;width:524px;margin-left:0}
+table .span8{float:none;width:604px;margin-left:0}
+table .span9{float:none;width:684px;margin-left:0}
+table .span10{float:none;width:764px;margin-left:0}
+table .span11{float:none;width:844px;margin-left:0}
+table .span12{float:none;width:924px;margin-left:0}
+[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;*margin-right:.3em;}
+[class^="icon-"]:last-child,[class*=" icon-"]:last-child{*margin-left:0}
+.icon-white{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{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{background-position:-384px -120px}
+.icon-folder-open{background-position:-408px -120px}
+.icon-resize-vertical{background-position:-432px -119px}
+.icon-resize-horizontal{background-position:-456px -118px}
+.dropdown{position:relative}
+.dropdown-toggle{*margin-bottom:-3px}
+.dropdown-toggle:active,.open .dropdown-toggle{outline:0}
+.caret{display:inline-block;width:0;height:0;text-indent:-99999px;*text-indent:0;vertical-align:top;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000;opacity:.3;filter:"alpha(opacity=$op)";content:"\2193"}
+.dropdown .caret{margin-top:8px;margin-left:2px}
+.dropdown:hover .caret,.open.dropdown .caret{opacity:1;filter:"alpha(opacity=$op)"}
+.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;_width:160px;padding:4px 0;margin:0;list-style:none;background-color:#fff;border-color:#ccc;border-color:rgba(0,0,0,0.20);border-style:solid;border-width:1px;-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.20);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.20);box-shadow:0 5px 10px rgba(0,0,0,0.20);*border-right-width:2px;*border-bottom-width:2px;}
+.dropdown-menu -webkit-background-clip: padding-box -moz-background-clip: padding{background-clip:padding-box}
+.dropdown-menu.bottom-up{top:auto;bottom:100%;margin-bottom:2px}
+.dropdown-menu .divider{height:1px;margin:5px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff;*width:100%;*margin:-5px 0 5px}
+.dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#555;white-space:nowrap}
+.dropdown-menu li > a:hover,.dropdown-menu .active > a,.dropdown-menu .active > a:hover{color:#fff;text-decoration:none;background-color:#08c}
+.dropdown.open{*z-index:1000;}
+.dropdown.open .dropdown-toggle{color:#fff;background:#ccc;background:rgba(0,0,0,0.30)}
+.dropdown.open .dropdown-menu{display:block}
+.typeahead{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 #eee;border:1px solid rgba(0,0,0,0.05);-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)}
+.fade{-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-ms-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear;opacity:0;}
+.fade.in{opacity:1}
+.collapse{-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-ms-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease;position:relative;overflow:hidden;height:0;}
+.collapse.in{height:auto}
+.close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:"alpha(opacity=$op)";}
+.close:hover{color:#000;text-decoration:none;opacity:.4;filter:"alpha(opacity=$op)";cursor:pointer}
+.btn{display:inline-block;padding:4px 10px 4px;margin-bottom:0;font-size:13px;line-height:18px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-ms-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(top,#fff,#e6e6e6);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border-color:#e6e6e6 #e6e6e6 #c4c4c4;border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.10) fadein(rgba(0,0,0,0.10),15%);filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.20),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.20),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.20),0 1px 2px rgba(0,0,0,0.05);cursor:pointer;filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";*margin-left:.3em;}
+.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{background-color:#e6e6e6}
+.btn:active,.btn.active{background-color:#cfcfcf e("\9")}
+.btn:first-child{*margin-left:0}
+.btn:hover{color:#333;text-decoration:none;background-color:#e6e6e6;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-ms-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;-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);background-color:#e6e6e6;background-color:#d9d9d9 e("\9");outline:0}
+.btn.disabled,.btn[disabled]{cursor:default;background-image:none;background-color:#e6e6e6;opacity:.65;filter:"alpha(opacity=$op)";-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}
+.btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}
+.btn-large [class^="icon-"]{margin-top:1px}
+.btn-small{padding:5px 9px;font-size:11px;line-height:16px}
+.btn-small [class^="icon-"]{margin-top:-1px}
+.btn-mini{padding:2px 6px;font-size:11px;line-height:14px}
+.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover,.btn-inverse,.btn-inverse:hover{text-shadow:0 -1px 0 rgba(0,0,0,0.25);color:#fff}
+.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-dark.active{color:rgba(255,255,255,0.75)}
+.btn-primary{background-color:#006ccc;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-ms-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(top,#08c,#04c);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border-color:#04c #04c #003aad;border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.10) fadein(rgba(0,0,0,0.10),15%);filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";}
+.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#04c}
+.btn-primary:active,.btn-primary.active{background-color:#003db8 e("\9")}
+.btn-warning{background-color:#f99d1c;background-image:-moz-linear-gradient(top,#faa42b,#f89406);background-image:-ms-linear-gradient(top,#faa42b,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#faa42b),to(#f89406));background-image:-webkit-linear-gradient(top,#faa42b,#f89406);background-image:-o-linear-gradient(top,#faa42b,#f89406);background-image:linear-gradient(top,#faa42b,#f89406);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border-color:#f89406 #f89406 #d37e05;border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.10) fadein(rgba(0,0,0,0.10),15%);filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";}
+.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406}
+.btn-warning:active,.btn-warning.active{background-color:#df8505 e("\9")}
+.btn-danger{background-color:#da4e49;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-ms-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(top,#ee5f5b,#bd362f);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border-color:#bd362f #bd362f #a12e28;border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.10) fadein(rgba(0,0,0,0.10),15%);filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";}
+.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f}
+.btn-danger:active,.btn-danger.active{background-color:#aa312a e("\9")}
+.btn-success{background-color:#5bb65b;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-ms-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(top,#62c462,#51a351);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border-color:#51a351 #51a351 #458b45;border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.10) fadein(rgba(0,0,0,0.10),15%);filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";}
+.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351}
+.btn-success:active,.btn-success.active{background-color:#499349 e("\9")}
+.btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-ms-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(top,#5bc0de,#2f96b4);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border-color:#2f96b4 #2f96b4 #287f99;border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.10) fadein(rgba(0,0,0,0.10),15%);filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";}
+.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4}
+.btn-info:active,.btn-info.active{background-color:#2a87a2 e("\9")}
+.btn-inverse{background-color:#383838;background-image:-moz-linear-gradient(top,#454545,#262626);background-image:-ms-linear-gradient(top,#454545,#262626);background-image:-webkit-gradient(linear,0 0,0 100%,from(#454545),to(#262626));background-image:-webkit-linear-gradient(top,#454545,#262626);background-image:-o-linear-gradient(top,#454545,#262626);background-image:linear-gradient(top,#454545,#262626);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border-color:#262626 #262626 #202020;border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.10) fadein(rgba(0,0,0,0.10),15%);filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";}
+.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{background-color:#262626}
+.btn-inverse:active,.btn-inverse.active{background-color:#222 e("\9")}
+button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px;}
+button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}
+button.btn.large,input[type="submit"].btn.large{*padding-top:7px;*padding-bottom:7px}
+button.btn.small,input[type="submit"].btn.small{*padding-top:3px;*padding-bottom:3px}
+.btn-group{position:relative;*zoom:1;*margin-left:.3em;}
+.btn-group:before,.btn-group:after{display:table;content:""}
+.btn-group:after{clear:both}
+.btn-group:first-child{*margin-left:0}
+.btn-group + .btn-group{margin-left:5px}
+.btn-toolbar{margin-top:9px;margin-bottom:9px;}
+.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1}
+.btn-group .btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}
+.btn-group .btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px}
+.btn-group .btn:last-child,.btn-group .dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px}
+.btn-group .btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px}
+.btn-group .btn.large:last-child,.btn-group .large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius: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 .dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.13),inset 0 1px 0 rgba(255,255,255,0.20),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.13),inset 0 1px 0 rgba(255,255,255,0.20),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.13),inset 0 1px 0 rgba(255,255,255,0.20),0 1px 2px rgba(0,0,0,0.05);*padding-top:5px;*padding-bottom:5px}
+.btn-group.open{*z-index:1000;}
+.btn-group.open .dropdown-menu{display:block;margin-top:1px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}
+.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 1px 6px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 6px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 6px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}
+.btn .caret{margin-top:7px;margin-left:0}
+.btn:hover .caret,.open.btn-group .caret{opacity:1;filter:"alpha(opacity=$op)"}
+.btn-primary .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;opacity:.75;filter:"alpha(opacity=$op)"}
+.btn-small .caret{margin-top:4px}
+.alert{padding:8px 35px 8px 14px;margin-bottom:18px;text-shadow:0 1px 0 rgba(255,255,255,0.50);background-color:#fcf8e3;border:1px solid #fbefd6;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}
+.alert,.alert-heading{color:#c09853}
+.alert .close{position:relative;top:-2px;right:-21px;line-height:18px}
+.alert-success{background-color:#dff0d8;border-color:#d7eac8}
+.alert-success,.alert-success .alert-heading{color:#468847}
+.alert-danger,.alert-error{background-color:#f2dede;border-color:#eed4d8}
+.alert-danger,.alert-error,.alert-danger .alert-heading,.alert-error .alert-heading{color:#b94a48}
+.alert-info{background-color:#d9edf7;border-color:#bee9f1}
+.alert-info,.alert-info .alert-heading{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-left:0;margin-bottom:18px;list-style:none}
+.nav > li > a{display:block}
+.nav > li > a:hover{text-decoration:none;background-color:#eee}
+.nav .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:18px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.50);text-transform:uppercase}
+.nav li + .nav-header{margin-top:9px}
+.nav-list{padding-left:14px;padding-right:14px;margin-bottom:0}
+.nav-list > li > a,.nav-list .nav-header{margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.50)}
+.nav-list > li > a{padding:3px 15px}
+.nav-list .active > a,.nav-list .active > a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.20);background-color:#08c}
+.nav-list [class^="icon-"]{margin-right:2px}
+.nav-tabs,.nav-pills{*zoom:1;}
+.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;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:9px;padding-bottom:9px;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{border-color:#eee #eee #ddd}
+.nav-tabs > .active > a,.nav-tabs > .active > a:hover{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}
+.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{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-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}
+.nav-tabs.nav-stacked > li:last-child > a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}
+.nav-tabs.nav-stacked > li > a:hover{border-color:#ddd;z-index:2}
+.nav-pills.nav-stacked > li > a{margin-bottom:3px}
+.nav-pills.nav-stacked > li:last-child > a{margin-bottom:1px}
+.nav-tabs .dropdown-menu,.nav-pills .dropdown-menu{margin-top:1px;border-width:1px}
+.nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}
+.nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{border-top-color:#08c;margin-top:6px}
+.nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#0074ad}
+.nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333}
+.nav > .dropdown.active > a:hover{color:#000;cursor:pointer}
+.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav > .open.active > a:hover{color:#fff;background-color:#999;border-color:#999}
+.nav .open .caret,.nav .open.active .caret,.nav .open a:hover .caret{border-top-color:#fff;opacity:1;filter:"alpha(opacity=$op)"}
+.tabs-stacked .open > a:hover{border-color:#999}
+.tabbable{*zoom:1;}
+.tabbable:before,.tabbable:after{display:table;content:""}
+.tabbable:after{clear:both}
+.tab-content{overflow:hidden}
+.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{border-bottom-color:transparent;border-top-color:#ddd}
+.tabs-below .nav-tabs .active > a,.tabs-below .nav-tabs .active > a:hover{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{border-color:#eee #ddd #eee #eee}
+.tabs-left .nav-tabs .active > a,.tabs-left .nav-tabs .active > a:hover{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{border-color:#eee #eee #eee #ddd}
+.tabs-right .nav-tabs .active > a,.tabs-right .nav-tabs .active > a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}
+.navbar{overflow:visible;margin-bottom:18px}
+.navbar-inner{padding-left:20px;padding-right:20px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top,#333,#222);background-image:-ms-linear-gradient(top,#333,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#333),to(#222));background-image:-webkit-linear-gradient(top,#333,#222);background-image:-o-linear-gradient(top,#333,#222);background-image:linear-gradient(top,#333,#222);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.10);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.10);box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.10)}
+.btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top,#333,#222);background-image:-ms-linear-gradient(top,#333,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#333),to(#222));background-image:-webkit-linear-gradient(top,#333,#222);background-image:-o-linear-gradient(top,#333,#222);background-image:linear-gradient(top,#333,#222);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border-color:#222 #222 #1d1d1d;border-color:rgba(0,0,0,0.10) rgba(0,0,0,0.10) fadein(rgba(0,0,0,0.10),15%);filter:"progid:DXImageTransform.Microsoft$gradient(enabled = false)";-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.10),0 1px 0 rgba(255,255,255,0.07);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.10),0 1px 0 rgba(255,255,255,0.07);box-shadow:inset 0 1px 0 rgba(255,255,255,0.10),0 1px 0 rgba(255,255,255,0.07)}
+.btn-navbar:hover,.btn-navbar:active,.btn-navbar.active,.btn-navbar.disabled,.btn-navbar[disabled]{background-color:#222}
+.btn-navbar:active,.btn-navbar.active{background-color:#1f1f1f e("\9")}
+.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}
+.nav-collapse.collapse{height:auto}
+.navbar .brand:hover{text-decoration:none}
+.navbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#fff}
+.navbar .navbar-text{margin-bottom:0;line-height:40px;color:#999;}
+.navbar .navbar-text a:hover{color:#fff;background-color:transparent}
+.navbar .btn,.navbar .btn-group{margin-top:5px}
+.navbar .btn-group .btn{margin-top:0}
+.navbar-form{margin-bottom:0;*zoom:1;}
+.navbar-form:before,.navbar-form:after{display:table;content:""}
+.navbar-form:after{clear:both}
+.navbar-form input,.navbar-form select{display:inline-block;margin-top:5px;margin-bottom:0}
+.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}
+.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:6px;white-space:nowrap;}
+.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}
+.navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0;}
+.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#fff;color:rgba(255,255,255,0.75);background:#666;background:rgba(255,255,255,0.30);border:1px solid #111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.10),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.10),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.10),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}
+.navbar-search .search-query :-moz-placeholder{color:#eee}
+.navbar-search .search-query ::-webkit-input-placeholder{color:#eee}
+.navbar-search .search-query:hover{color:#fff;background-color:#999;background-color:rgba(255,255,255,0.50)}
+.navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border: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);outline:0}
+.navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}
+.navbar-fixed-top .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}
+.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}
+.navbar .nav.pull-right{float:right}
+.navbar .nav > li{display:block;float:left}
+.navbar .nav > li > a{float:none;padding:10px 10px 11px;line-height:19px;color:#999;text-decoration:none;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}
+.navbar .nav > li > a:hover{background-color:transparent;color:#fff;text-decoration:none}
+.navbar .nav .active > a,.navbar .nav .active > a:hover{color:#fff;text-decoration:none;background-color:#222}
+.navbar .divider-vertical{height:40px;width:1px;margin:0 9px;overflow:hidden;background-color:#222;border-right:1px solid #333}
+.navbar .nav.pull-right{margin-left:10px;margin-right:0}
+.navbar .dropdown-menu{margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
+.navbar .dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.20);position:absolute;top:-7px;left:9px}
+.navbar .dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:10px}
+.navbar .nav .dropdown-toggle .caret,.navbar .nav .open.dropdown .caret{border-top-color:#fff}
+.navbar .nav .active .caret{opacity:1;filter:"alpha(opacity=$op)"}
+.navbar .nav .open > .dropdown-toggle,.navbar .nav .active > .dropdown-toggle,.navbar .nav .open.active > .dropdown-toggle{background-color:transparent}
+.navbar .nav .active > .dropdown-toggle:hover{color:#fff}
+.navbar .nav.pull-right .dropdown-menu{left:auto;right:0;}
+.navbar .nav.pull-right .dropdown-menu:before{left:auto;right:12px}
+.navbar .nav.pull-right .dropdown-menu:after{left:auto;right:13px}
+.breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#fbfbfb;background-image:-moz-linear-gradient(top,#fff,#f5f5f5);background-image:-ms-linear-gradient(top,#fff,#f5f5f5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#fff,#f5f5f5);background-image:-o-linear-gradient(top,#fff,#f5f5f5);background-image:linear-gradient(top,#fff,#f5f5f5);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff;}
+.breadcrumb li{display:inline-block;text-shadow:0 1px 0 #fff}
+.breadcrumb .divider{padding:0 5px;color:#999}
+.breadcrumb .active a{color:#333}
+.pagination{height:36px;margin:18px 0}
+.pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-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 li{display:inline}
+.pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0}
+.pagination a:hover,.pagination .active a{background-color:#f5f5f5}
+.pagination .active a{color:#999;cursor:default}
+.pagination .disabled a,.pagination .disabled a:hover{color:#999;background-color:transparent;cursor:default}
+.pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}
+.pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}
+.pagination-centered{text-align:center}
+.pagination-right{text-align:right}
+.pager{margin-left:0;margin-bottom:18px;list-style:none;text-align:center;*zoom:1;}
+.pager:before,.pager:after{display:table;content:""}
+.pager:after{clear:both}
+.pager li{display:inline}
+.pager a{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 a:hover{text-decoration:none;background-color:#f5f5f5}
+.pager .next a{float:right}
+.pager .previous a{float:left}
+.modal-open .dropdown-menu{z-index:2050}
+.modal-open .dropdown.open{*z-index:2050}
+.modal-open .popover{z-index:2060}
+.modal-open .tooltip{z-index:2070}
+.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=$op)"}
+.modal{position:fixed;top:50%;left:50%;z-index:1050;max-height:500px;overflow:auto;width:560px;margin:-250px 0 0 -280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.30);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.30);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.30);box-shadow:0 3px 7px rgba(0,0,0,0.30);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}
+.modal.fade{-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-ms-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;top:-25%}
+.modal.fade.in{top:50%}
+.modal-header{padding:9px 15px;border-bottom:1px solid #eee;}
+.modal-header .close{margin-top:2px}
+.modal-body{padding:15px}
+.modal-body .modal-form{margin-bottom:0}
+.modal-footer{padding:14px 15px 15px;margin-bottom:0;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;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff;*zoom:1;}
+.modal-footer:before,.modal-footer:after{display:table;content:""}
+.modal-footer:after{clear:both}
+.modal-footer .btn{float:right;margin-left:5px;margin-bottom:0}
+.tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:"alpha(opacity=$op)";}
+.tooltip.in{opacity:.8;filter:"alpha(opacity=$op)"}
+.tooltip.top{margin-top:-2px}
+.tooltip.right{margin-left:2px}
+.tooltip.bottom{margin-top:2px}
+.tooltip.left{margin-left:-2px}
+.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-$arrowWidth;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000}
+.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-$arrowWidth;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000}
+.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-$arrowWidth;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000}
+.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-$arrowWidth;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000}
+.tooltip-inner{max-width:200px;padding:3px 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}
+.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}
+.popover.top{margin-top:-5px}
+.popover.right{margin-left:5px}
+.popover.bottom{margin-top:5px}
+.popover.left{margin-left:-5px}
+.popover.top .arrow{bottom:0;left:50%;margin-left:-$arrowWidth;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000}
+.popover.right .arrow{top:50%;left:0;margin-top:-$arrowWidth;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000}
+.popover.bottom .arrow{top:0;left:50%;margin-left:-$arrowWidth;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000}
+.popover.left .arrow{top:50%;right:0;margin-top:-$arrowWidth;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000}
+.popover .arrow{position:absolute;width:0;height:0}
+.popover-inner{padding:3px;width:280px;overflow:hidden;background:#000;background:rgba(0,0,0,0.80);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.30);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.30);box-shadow:0 3px 7px rgba(0,0,0,0.30)}
+.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0}
+.popover-content{padding:14px;background-color:#fff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}
+.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0}
+.thumbnails{margin-left:-$gridGutterWidth;list-style:none;*zoom:1;}
+.thumbnails:before,.thumbnails:after{display:table;content:""}
+.thumbnails:after{clear:both}
+.thumbnails > li{float:left;margin:0 0 18px 20px}
+.thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.07);-moz-box-shadow:0 1px 1px rgba(0,0,0,0.07);box-shadow:0 1px 1px rgba(0,0,0,0.07)}
+a.thumbnail:hover{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-left:auto;margin-right:auto}
+.thumbnail .caption{padding:9px}
+.label{padding:2px 4px 3px;font-size:11.049999999999999px;font-weight:bold;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}
+.label:hover{color:#fff;text-decoration:none}
+.label-important{background-color:#b94a48}
+.label-important:hover{background-color:#a74240}
+.label-warning{background-color:#f89406}
+.label-warning:hover{background-color:#df8505}
+.label-success{background-color:#468847}
+.label-success:hover{background-color:#3f7a40}
+.label-info{background-color:#3a87ad}
+.label-info:hover{background-color:#347a9c}
+.progress{overflow:hidden;height:18px;margin-bottom:18px;background-color:#f6f6f6;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-ms-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(top,#f5f5f5,#f9f9f9);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)";-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.10);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.10);box-shadow:inset 0 1px 2px rgba(0,0,0,0.10);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}
+.progress .bar{width:0%;height:18px;color:#fff;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0d90d1;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-ms-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(top,#149bdf,#0480be);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, 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;-ms-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}
+.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,0.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,0.15)),color-stop(.75,rgba(255,255,255,0.15)),color-stop(.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:-ms-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;animation:progress-bar-stripes 2s linear infinite}
+.progress-danger .bar{background-color:#dd514b;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-ms-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(top,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)"}
+.progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,0.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,0.15)),color-stop(.75,rgba(255,255,255,0.15)),color-stop(.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:-ms-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{background-color:#5db95d;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-ms-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(top,#62c462,#57a957);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)"}
+.progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,0.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,0.15)),color-stop(.75,rgba(255,255,255,0.15)),color-stop(.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:-ms-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{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-ms-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(top,#5bc0de,#339bb9);background-repeat:repeat-x;filter:"progid:DXImageTransform.Microsoft$gradient(startColorstr=$startColor, endColorstr=$endColor, GradientType=0)"}
+.progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,0.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,0.15)),color-stop(.75,rgba(255,255,255,0.15)),color-stop(.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:-ms-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)}
+@-moz-keyframes progress-bar-stripes{0%{background-position:0 0}
+100%{background-position:40px 0}
+}@-webkit-keyframes progress-bar-stripes{0%{background-position:0 0}
+100%{background-position:40px 0}
+}@-o-keyframes progress-bar-stripes{0%{background-position:0 0}
+100%{background-position:40px 0}
+}@-ms-keyframes progress-bar-stripes{0%{background-position:0 0}
+100%{background-position:40px 0}
+}@keyframes progress-bar-stripes{0%{background-position:0 0}
+100%{background-position:40px 0}
+}.accordion{margin-bottom:18px}
+.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-inner{padding:9px 15px;border-top:1px solid #e5e5e5}
+.carousel{position:relative;margin-bottom:18px;line-height:1}
+.carousel-inner{overflow:hidden;width:100%;position:relative}
+.carousel .item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-ms-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}
+.carousel .item > img{display:block;line-height:1}
+.carousel .active,.carousel .next,.carousel .prev{display:block}
+.carousel .active{left:0}
+.carousel .next,.carousel .prev{position:absolute;top:0;width:100%}
+.carousel .next{left:100%}
+.carousel .prev{left:-100%}
+.carousel .next.left,.carousel .prev.right{left:0}
+.carousel .active.left{left:-100%}
+.carousel .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=$op)";}
+.carousel-control.right{left:auto;right:15px}
+.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:"alpha(opacity=$op)"}
+.carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:10px 15px 5px;background:#333;background:rgba(0,0,0,0.75)}
+.carousel-caption h4,.carousel-caption p{color:#fff}
+.hero-unit{padding:60px;margin-bottom:30px;background-color:#f5f5f5;-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}
+.hero-unit p{font-size:18px;font-weight:200;line-height:27px}
+.pull-right{float:right}
+.pull-left{float:left}
+.hide{display:none}
+.show{display:block}
+.invisible{visibility:hidden}
+

+ 3 - 0
admin/static/css/index.styl

@@ -0,0 +1,3 @@
+@import './bootstrap.css'
+@import './mixin'
+@import './theme'

+ 89 - 0
admin/static/css/mixin.styl

@@ -0,0 +1,89 @@
+border-radius()
+  -moz-border-radius: arguments
+  -webkit-border-radius: arguments
+  border-radius: arguments
+
+/* Vertical Background Gradient */
+vbg-gradient(fc = #FFF, tc = #FFF)
+  background: fc
+  background: -webkit-gradient(linear, left top, left bottom, from(fc), to(tc))
+  background: -moz-linear-gradient(top, fc, tc)
+  background: linear-gradient(top, fc, tc)
+
+/* Horizontal Background Gradient */
+hbg-gradient(fc = #FFF, tc = #FFF) 
+  background: fc
+  background: -webkit-gradient(linear, left top, right top, from(fc), to(tc))
+  background: -moz-linear-gradient(left, fc, tc)
+  background: linear-gradient(left, fc, tc)
+
+box-shadow()
+  -moz-box-shadow: arguments
+  -webkit-box-shadow: arguments
+  box-shadow: arguments
+
+inset-box-shadow()
+  -moz-box-shadow: inset arguments
+  -webkit-box-shadow: inset arguments
+  box-shadow: inset arguments
+
+box-flex(s = 0)
+  -webkit-box-flex: s
+  -moz-box-flex: s
+  box-flex: s
+
+hbox()
+  display: -webkit-box
+  -webkit-box-orient: horizontal
+  -webkit-box-align: stretch
+  -webkit-box-pack: start
+  
+  display: -moz-box
+  -moz-box-orient: horizontal
+  -moz-box-align: stretch
+  -moz-box-pack: start
+
+vbox()
+  display: -webkit-box
+  -webkit-box-orient: vertical
+  -webkit-box-align: stretch
+
+  display: -moz-box
+  -moz-box-orient: vertical
+  -moz-box-align: stretch
+
+border-box()
+  -webkit-box-sizing: border-box
+  -moz-box-sizing: border-box
+  box-sizing: border-box
+
+transition(s = 0.3s, o =  opacity, t = linear)
+  -webkit-transition: s o t
+  -moz-transition: s o t
+  transition: s o t
+
+ellipsis()
+  text-overflow: ellipsis
+  overflow: hidden
+  white-space:nowrap
+
+inset-line(opacity = 0.4, size = 1px)
+  inset-box-shadow(0, size, 0, rgba(255, 255, 255, opacity))
+
+outset-line(opacity = 0.4, size = 1px)
+  box-shadow(0, size, 0, rgba(255, 255, 255, opacity))
+
+box-pack(type = center)
+  -webkit-box-pack: type
+  -moz-box-pack: type
+  box-pack: type
+  
+transform(tr)
+  -webkit-transform: tr
+  -moz-transform: tr
+  -ms-transform: tr
+  -o-transform: tr
+  transform: tr
+  
+hacel()
+  transform(translate3d(0,0,0))

+ 0 - 0
admin/static/css/theme.styl


+ 1 - 0
admin/templates/404.html

@@ -0,0 +1 @@
+<h1>404 Not Found</h1>

+ 20 - 0
admin/templates/base.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+
+  <meta charset="utf-8">
+  <title>{{title}}</title>
+
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1, maximum-scale=1.0, user-scalable=0">
+  <meta name="apple-mobile-web-app-capable" content="yes">
+
+  <link rel="stylesheet" href="{{baseURL}}/static/css/index.css" type="text/css" media="screen" charset="utf-8">
+
+  <script src="{{baseURL}}/modules.js"></script>
+</head>
+<body>
+
+  {{{content}}}
+
+</body>
+</html>

+ 31 - 0
admin/templates/home.html

@@ -0,0 +1,31 @@
+<div class="row-fluid">
+  
+  <div class="span4">
+    <h3>Sites</h3>
+    <ul>
+      {{#each sites}}
+      <li>{{name}} ({{_id}})</li>
+      {{/each}}
+    </ul>
+  </div>
+
+
+  <div class="span4">
+    <h3>Collections</h3>
+    <ul>
+      {{#each collections}}
+      <li>{{name}} ({{_id}})</li>
+      {{/each}}
+    </ul>
+  </div>
+
+
+  <div class="span4">
+    <h3>Essays</h3>
+    <ul>
+      {{#each essays}}
+      <li>{{title}} ({{_id}})</li>
+      {{/each}}
+    </ul>
+  </div>
+</div>

+ 12 - 0
admin/templates/index.html

@@ -0,0 +1,12 @@
+<div id="app"></div>
+
+<script type="text/javascript">
+  var $ = require('jquery');
+  var exports = this;
+  $(function() {
+    var App = require('controllers/index');
+    exports.app = new App({
+      el: $("#app")
+    });
+  });
+</script>

+ 1 - 0
admin/templates/test.html

@@ -0,0 +1 @@
+<h1>ADMIN TEST PAGE</h1>

+ 35 - 0
site/kanso.json

@@ -0,0 +1,35 @@
+{
+  "name": "site",
+  "version": "0.0.1",
+  "description": "Kleks site application that renders each site.",
+  "load": "server/setup",
+  "modules": ["server","lib"],
+  "handlebars": {
+    "templates": "templates"
+  },
+  "attachments": ["static"],
+  "duality": { "base_template": "base.html" },
+  "coffee-script": {
+    "modules": ["server","lib"]
+  },
+  "stylus": {
+      "compress": true,
+      "compile": "static/css/index.styl",
+      "remove_from_attachments": true
+  },
+  "dependencies": {
+    "modules": null,
+    "settings": null,
+    "attachments": null,
+    "properties": null,
+    "db": null,
+    "coffee-script-precompiler": null,
+    "stylus-precompiler": null,
+    "duality": null,
+    "handlebars": null,
+    "handlebars-helpers": null,
+    "duality-handlebars": null,
+    "showdown": null,
+    "jquery": null
+  }
+}

+ 8 - 0
site/lib/app.coffee

@@ -0,0 +1,8 @@
+# App's main client script
+
+$ = require('jquery')
+
+exports.initialize = (config) ->
+  touch = Modernizr.touch
+
+  # ...

+ 2 - 0
site/server/filters.coffee

@@ -0,0 +1,2 @@
+exports.published = (doc, req) ->
+  return doc.published

+ 206 - 0
site/server/lists.coffee

@@ -0,0 +1,206 @@
+templates = require('duality/templates')
+dutils    = require('duality/utils')
+Showdown  = require('showdown')
+_         = require('underscore')._
+
+
+exports.home = (head, req) ->
+  # no need for double render on first hit
+  return if req.client and req.initial_hit
+  start code: 200, headers: {'Content-Type': 'text/html'}
+
+  converter = new Showdown.converter()
+  collections = []
+  blocks = {}
+  site = null
+
+  while row = getRow()
+    doc = row.value
+    collections.push(doc) if doc.type is 'collection'
+    blocks[doc.code] = doc if doc.type is 'block'
+    site ?= doc if doc.type is 'site'
+  
+  collections = _.map collections, (doc) ->
+    if doc.intro?
+      doc.intro_html = converter.makeHtml(
+        doc.intro.replace(/\{\{?baseURL\}?\}/g, dutils.getBaseURL(req))
+      )
+    doc.updated_at_html = new Date(doc.updated_at).toDateString()
+    return doc
+
+  return {
+    site: site
+    title: "#{site.name}"
+    content: templates.render "home.html", req,
+      collections: collections
+      blocks: blocks
+      nav: 'home'
+  }
+
+
+exports.collection = (head, req) ->
+  # no need for double render on first hit
+  return if req.client and req.initial_hit
+  start code: 200, headers: {'Content-Type': 'text/html'}
+
+  converter = new Showdown.converter()
+  essays = []
+  collection = null
+  sponsor = null
+  site = null
+
+  while row = getRow()
+    doc = row.doc
+    essays.push(doc) if doc.type is 'essay'
+    collection ?= doc if doc.type is 'collection'
+    sponsor ?= doc if doc.type is 'sponsor'
+    site ?= doc if doc.type is 'site'
+
+  essays = _.map essays, (doc) ->
+    if doc.intro?
+      doc.intro_html = converter.makeHtml(
+        doc.intro.replace(/\{\{?baseURL\}?\}/g, dutils.getBaseURL(req))
+      )
+    doc.published_at_html = new Date(doc.published_at).toDateString()
+    return doc
+
+  if sponsor
+    sponsor.text_format = sponsor.format is 'text'
+    sponsor.image_format = sponsor.format is 'image'
+    sponsor.video_format = sponsor.format is 'video'
+
+  return {
+    site: site
+    title: collection.name
+    content: templates.render 'collection.html', req,
+      collection: collection
+      essays: essays
+      sponsor: sponsor
+      nav: 'collection'
+  }
+
+
+exports.essays = (head, req) ->
+  # no need for double render on first hit
+  return if req.client and req.initial_hit
+  start code: 200, headers: {'Content-Type': 'text/html'}
+
+  converter = new Showdown.converter()
+  essays = []
+  site = null
+
+  while row = getRow()
+    doc = row.doc
+    if doc.type is 'essay'
+      doc.collection_docs = []
+      essays.push(doc)
+    else if doc.type is 'collection'
+      # Add the collection doc to the last essay doc pushed
+      essays[essays.length-1].collection_docs.push(doc)
+    site ?= doc if doc.type is 'site'
+
+  essays = _.map essays, (doc) ->
+    if doc.intro?
+      doc.intro_html = converter.makeHtml(
+        doc.intro.replace(/\{\{?baseURL\}?\}/g, dutils.getBaseURL(req))
+      )
+    doc.published_at_html = new Date(doc.published_at).toDateString()
+    doc.updated_at_html = new Date(doc.updated_at).toDateString()
+    return doc
+
+  return {
+    site: site
+    title: 'Essays List'
+    content: templates.render 'essays.html', req,
+      essays: essays
+      nav: 'essays'
+  }
+
+
+exports.essay = (head, req) ->
+  ###
+  This will render the Essay content along with a list of its
+  associated collections.
+  ###
+  # no need for double render on first hit
+  return if req.client and req.initial_hit
+  start code: 200, headers: {'Content-Type': 'text/html'}
+
+  converter = new Showdown.converter()
+  essay = null
+  collections = []
+  author = null
+  sponsor = null
+  site = null
+
+  while row = getRow()
+    doc = row.doc
+    essay ?= doc if doc.type is 'essay'
+    collections.push(doc) if doc.type is 'collection'
+    sponsor ?= doc if doc.type is 'sponsor'
+    author ?= doc if doc.type is 'author'
+    site ?= doc if doc.type is 'site'
+
+  transformEssay = (doc) ->
+    doc.intro_html = converter.makeHtml(
+      doc.intro.replace(/\{\{?baseURL\}?\}/g, dutils.getBaseURL(req))
+    )
+    doc.body_html = converter.makeHtml(
+      doc.body.replace(/\{\{?baseURL\}?\}/g, dutils.getBaseURL(req))
+    )
+    doc.published_at_html = new Date(doc.published_at).toDateString()
+    doc.updated_at_html = new Date(doc.updated_at).toDateString()
+    return doc
+
+  essay = transformEssay(essay)
+
+  collections = _.map collections, (doc) ->
+    if doc.intro?
+      doc.intro_html = converter.makeHtml(
+        doc.intro.replace(/\{\{?baseURL\}?\}/g, dutils.getBaseURL(req))
+      )
+    doc.updated_at_html = new Date(doc.updated_at).toDateString()
+    return doc
+
+  if sponsor
+    sponsor.text_format = sponsor.format is 'text'
+    sponsor.image_format = sponsor.format is 'image'
+    sponsor.video_format = sponsor.format is 'video'
+
+  return {
+    site: site
+    title: essay.title
+    content: templates.render 'essay.html', req,
+      essay: essay
+      collections: collections
+      author: author
+      sponsor: sponsor
+      nav: 'essay'
+  }
+
+
+###
+exports.rssfeed = function (head, req) {
+    start({code: 200, headers: {'Content-Type': 'application/rss+xml'}});
+
+    var converter = new Showdown.converter();
+
+    var rows = getRows(function (row) {
+        var doc = row.doc;
+        doc.markdown_html = converter.makeHtml(
+            doc.markdown.replace(/\{\{?baseURL\}?\}/g, dutils.getBaseURL(req))
+        );
+        doc.guid = 'http://caolanmcmahon.com' + (
+            doc.oldurl || '/posts/' + doc.slug
+        );
+        return row;
+    });
+
+    return templates.render('feed.xml', req, {
+        rows: rows,
+        published_at: rows[0].doc.published_at,
+        builddate: new Date()
+    });
+};
+
+###

+ 67 - 0
site/server/rewrites.coffee

@@ -0,0 +1,67 @@
+moved = (from, to) ->
+  { from: from, to: '_show/moved', query: {loc: to} }
+
+module.exports = [
+  # Static files from the root
+  { from: '/static/*', to: 'static/*' }
+
+  # Dynamic site rendering used with a virtual host like:
+  # www.evitaochel.com = /kleks/_design/site/_rewrite/render/evitaochel
+  {
+    from: '/render/:site',
+    to: '_list/home/docs_for_home',
+    query: {
+      startkey: [':site', {}],
+      endkey: [':site'],
+      descending: 'true'
+    }
+  }
+
+  # Some routes to static files needed under the dynamic site path
+  { from: '/render/:site/static/*',    to: 'static/*' }
+  { from: '/render/:site/modules.js',  to: 'modules.js' }
+  { from: '/render/:site/duality.js',  to: 'duality.js' }
+
+  # List of all Essays sorted by `updated_at`
+  {
+    from: '/render/:site/essays',
+    to: '_list/essays/essays_by_date',
+    query: {
+      startkey: [':site', {}],
+      endkey: [':site'],
+      descending: 'true',
+      include_docs: 'true'
+    }
+  }
+
+  # Collection's page - list of essays
+  # `:cid` is the collection's _id
+  {
+    from: '/render/:site/collection/:cid',
+    to: '_list/collection/essays_by_collection',
+    query: {
+      startkey: [':site', ':cid', {}],
+      endkey: [':site', ':cid'],
+      descending: 'true',
+      include_docs: 'true'
+    }
+  }
+
+  # Essay's content page
+  # `:slug` is the essay's slug
+  {
+    from: '/render/:site/essay/:slug',
+    to: '_list/essay/essays_by_slug',
+    query: {
+      startkey: [':site', ':slug'],
+      endkey: [':site', ':slug', {}],
+      include_docs: 'true'
+    }
+  }
+
+  # Redirected old URLs
+  # moved '/posts/some-old-path', '/some-new-path'
+
+  # Catch all route
+  { from: '*', to: '_show/not_found' }
+]

+ 6 - 0
site/server/setup.coffee

@@ -0,0 +1,6 @@
+module.exports =
+  shows: require("./shows")
+  views: require("./views") 
+  lists: require("./lists")
+  rewrites: require("./rewrites")
+  filters: require('./filters')

+ 9 - 0
site/server/shows.coffee

@@ -0,0 +1,9 @@
+templates = require("duality/templates") 
+
+exports.not_found = (doc, req) ->
+  title: "404 Not Found"
+  content: templates.render("404.html", req, {})
+
+exports.moved = (doc, req) ->
+  code: 301
+  headers: { location: req.query.loc }

+ 0 - 0
site/server/utils.coffee


+ 58 - 0
site/server/views.coffee

@@ -0,0 +1,58 @@
+exports.docs_for_home =
+  map: (doc) ->
+    # List of collections sorted by `pinned` then `updated_at`,
+    # plus a few blocks that are needed on home page,
+    # and the site configuration doc.
+    if doc.site and doc.type is 'collection' and doc.updated_at
+      pinned = if doc.pinned then 1 else 0
+      timestamp = new Date(doc.updated_at).getTime()
+      emit [doc.site, pinned, timestamp], doc
+    else if doc.type is 'block' and doc.code in ['site_intro','site_promo']
+      emit [doc.site], doc
+    else if doc.type is 'site'
+      # Also add the site doc
+      emit [doc._id], doc
+
+
+exports.essays_by_collection =
+  map: (doc) ->
+    if doc.site and doc.type is 'essay' and doc.collections and doc.updated_at and doc.published
+      timestamp = new Date(doc.updated_at).getTime()
+      for c, i in doc.collections
+        emit [doc.site, c.slug, timestamp], null
+    else if doc.site and doc.type is 'collection'
+      emit [doc.site, doc.slug, {}], null
+      # Also add the collection's sponsor doc
+      emit [doc.site, doc.slug, {}], { _id: doc.sponsor_id } if doc.sponsor_id
+      # Also add the site doc
+      emit [doc.site, doc.slug, {}], { _id: doc.site }
+
+
+exports.essays_by_date =
+  map: (doc) ->
+    # List of essays sorted by `updated_at` along with their collection references
+    if doc.site and doc.type is 'essay' and doc.updated_at and doc.published
+      timestamp = new Date(doc.updated_at).getTime()
+      emit [doc.site, timestamp, doc._id, {}], null
+      for c, i in doc.collections
+        # To get each collection's doc
+        emit [doc.site, timestamp, doc._id, i+1], {_id: c.id}
+    else if doc.type is 'site'
+      # Also add the site doc
+      emit [doc._id], null
+
+
+exports.essays_by_slug =
+  map: (doc) ->
+    # Essay key by slug followed with it's collection references
+    if doc.site and doc.type is 'essay' and doc.slug
+      emit [doc.site, doc.slug, 0], null
+      for c, i in doc.collections
+        # To get each collection's doc
+        emit [doc.site, doc.slug, i+1], {_id: c.id}
+      # Also add the essay's author doc
+      emit [doc.site, doc.slug, {}], { _id: doc.author_id } if doc.author_id
+      # Also add the essay's sponsor doc
+      emit [doc.site, doc.slug, {}], { _id: doc.sponsor_id } if doc.sponsor_id
+      # Also add the site doc
+      emit [doc.site, doc.slug, {}], { _id: doc.site }

+ 3 - 0
site/static/css/index.styl

@@ -0,0 +1,3 @@
+@import './mixin'
+@import './theme'
+@import './responsive'

+ 94 - 0
site/static/css/mixin.styl

@@ -0,0 +1,94 @@
+border-radius()
+  -moz-border-radius: arguments
+  -webkit-border-radius: arguments
+  border-radius: arguments
+
+/* Vertical Background Gradient */
+vbg-gradient(fc = #FFF, tc = #FFF)
+  background: fc
+  background: -webkit-gradient(linear, left top, left bottom, from(fc), to(tc))
+  background: -moz-linear-gradient(top, fc, tc)
+  background: linear-gradient(top, fc, tc)
+
+/* Horizontal Background Gradient */
+hbg-gradient(fc = #FFF, tc = #FFF) 
+  background: fc
+  background: -webkit-gradient(linear, left top, right top, from(fc), to(tc))
+  background: -moz-linear-gradient(left, fc, tc)
+  background: linear-gradient(left, fc, tc)
+
+box-shadow()
+  -moz-box-shadow: arguments
+  -webkit-box-shadow: arguments
+  box-shadow: arguments
+
+inset-box-shadow()
+  -moz-box-shadow: inset arguments
+  -webkit-box-shadow: inset arguments
+  box-shadow: inset arguments
+
+box-flex(s = 0)
+  -webkit-box-flex: s
+  -moz-box-flex: s
+  box-flex: s
+
+hbox()
+  display: -webkit-box
+  -webkit-box-orient: horizontal
+  -webkit-box-align: stretch
+  -webkit-box-pack: start
+  
+  display: -moz-box
+  -moz-box-orient: horizontal
+  -moz-box-align: stretch
+  -moz-box-pack: start
+
+vbox()
+  display: -webkit-box
+  -webkit-box-orient: vertical
+  -webkit-box-align: stretch
+
+  display: -moz-box
+  -moz-box-orient: vertical
+  -moz-box-align: stretch
+
+border-box()
+  -webkit-box-sizing: border-box
+  -moz-box-sizing: border-box
+  box-sizing: border-box
+
+content-box()
+  -webkit-box-sizing: content-box
+  -moz-box-sizing: content-box
+  box-sizing: content-box
+
+transition(s = 0.3s, o =  opacity, t = linear)
+  -webkit-transition: s o t
+  -moz-transition: s o t
+  transition: s o t
+
+ellipsis()
+  text-overflow: ellipsis
+  overflow: hidden
+  white-space:nowrap
+
+inset-line(opacity = 0.4, size = 1px)
+  inset-box-shadow(0, size, 0, rgba(255, 255, 255, opacity))
+
+outset-line(opacity = 0.4, size = 1px)
+  box-shadow(0, size, 0, rgba(255, 255, 255, opacity))
+
+box-pack(type = center)
+  -webkit-box-pack: type
+  -moz-box-pack: type
+  box-pack: type
+  
+transform(tr)
+  -webkit-transform: tr
+  -moz-transform: tr
+  -ms-transform: tr
+  -o-transform: tr
+  transform: tr
+  
+hacel()
+  transform(translate3d(0,0,0))

+ 65 - 0
site/static/css/responsive.styl

@@ -0,0 +1,65 @@
+/* Responsive styles */
+
+// Portrait phones and down
+// @media (max-width: 320px)
+
+
+// Larger phones to smaller landscape phones, and down
+@media (max-width: 480px)
+
+  body
+    font-size: 14px
+
+  .container
+    padding: 14px
+    border-left-width: 8px
+
+  h1
+    font-size: 2.5em
+  h2
+    font-size: 1.8em
+  h3
+    font-size: 1.3em
+  h4
+    font-size: 1.1em
+
+  .site-name
+    font-size: 2.8em
+
+// Odd one
+@media (max-width: 600px)
+  
+  article
+    
+    .sponsor
+      float: none
+      width: 100%
+      margin: 1em auto
+
+// Landscape on larger phone to smaller tablet
+@media (min-width: 481px) and (max-width: 767px)
+  
+  .container
+    padding: 20px
+    border-left-width: 14px
+
+  h1
+    font-size: 3em
+  h2
+    font-size: 2em
+  h3
+    font-size: 1.5em
+  h4
+    font-size: 1.2em
+
+  .site-name
+    font-size: 3.5em
+
+
+// Portrait tablet to landscape and desktop
+// @media (min-width: 768px) and (max-width: 979px)
+
+
+// Large desktop
+// @media (min-width: 1200px)
+

+ 274 - 0
site/static/css/theme.styl

@@ -0,0 +1,274 @@
+@import url('http://fonts.googleapis.com/css?family=Lato:300,400,700')
+
+$tealColor  = #61E0DF // #97E6D3
+$greenColor = #81C977
+$brownColor = #B4805B
+$blueColor  = #BAD0EF
+$greyColor  = #b4b4b4
+
+$primaryColor = $blueColor
+$lightGrey    = #c4c4c4
+$linkColor    = darken($primaryColor, 20%)
+$textColor    = #848484
+
+// apply a natural box layout model to all elements
+*
+  border-box()
+
+body
+  margin: 0
+  padding: 0
+  background: #fff
+  color: $textColor
+  font-family: 'Lato', 'Helvetica Neue', Helvetica, Arial, sans-serif
+  font-weight: 300
+  font-size: 16px
+  letter-spacing: 0em
+  word-spacing: 0.2em
+  line-height: 1.5em
+
+.container
+  max-width: 960px
+  margin: 0
+  padding: 40px
+  border-left: 20px solid $primaryColor
+
+h1, h2, h3, h4, h5, h6
+  color: darken($textColor, 4%)
+  font-weight: 300
+  line-height: 1.2em
+
+h1
+  font-size: 3.5em
+h2
+  font-size: 2.5em
+h3
+  font-size: 2em
+h4
+  font-size: 1.5em
+h5
+  font-size: 1.125em
+  font-weight: 400
+h6
+  font-size: 0.875em
+  font-weight: 400
+  line-height: 1.5em
+
+a
+  color: $linkColor
+  text-decoration: none
+  
+  &.button
+    display: inline-block
+    padding: 10px 20px
+    background: $primaryColor
+    color: #fff
+    font-weight: 400
+
+    &.large
+      font-size: 2em
+      line-height: 1.2em
+      padding: 14px 30px
+
+b
+  font-weight: 700
+
+strong
+ font-weight: 400 
+
+small
+  font-size: 0.875em
+  color: $lightGrey
+
+blockquote
+  position: relative
+  border-right: 10px solid $primaryColor
+  padding: 0 1.5em 0 2.5em
+  margin: 1.5em 0
+  text-align: right
+  font-size: 1.125em
+  font-weight: 300
+  &:before
+    content: '“'
+    position: absolute
+    top: 0.2em
+    left: 0
+    color: $primaryColor
+    font-size: 6em
+    font-weight: 700
+
+img
+  display: block
+  border: 0
+
+.site-name
+  margin: 0 0 0.8em -0.05em
+  font-size: 5.25em
+  line-height: 0.8em
+  font-weight: 300
+  color: $lightGrey
+  letter-spacing: -0.07em
+  word-spacing: 0em
+  white-space: nowrap
+  a
+    color: $lightGrey
+  b, strong
+    color: $primaryColor
+
+.site-promo
+  color: $primaryColor
+  font-size: 1.25em
+  font-weight: 400
+
+span.label
+  font-weight: 300
+  color: $lightGrey
+
+article
+
+  > .intro
+    margin-bottom: 2em
+    font-size: 1.125em
+    font-weight: 400
+    line-height: 1.6em
+    color: darken($textColor, 5%)
+
+  .sponsor
+    float: right
+    width: 300px
+    max-width: 300px
+    margin: 0 0 1em 1em
+    text-align: center
+    background: #f9f9f9
+    content-box()
+
+    .label
+      color: #fff
+      background: $primaryColor
+      font-size: 0.875em
+
+    .name
+      font-size: 1.125em
+      padding: 1em
+    
+    .content
+      padding: 0 1em 1em 1em
+      overflow: hidden
+
+    .image img
+      width: 100%
+      overflow: hidden
+
+    .video
+      overflow: hidden
+      iframe
+        display: block
+
+article.home
+
+  .collections
+    
+    > ul
+      list-style-type: none
+      margin: 0
+      padding: 0
+
+      > li
+        display: inline-block
+        position: relative
+        width: 48%
+        padding: 0
+        margin: 0.5em 0.5em 0 0
+        border: solid 1px $primaryColor
+
+        .name
+          margin: 0
+          a
+            display: block
+            color: inherit
+            padding: 1em
+
+        .updated
+          position: absolute
+          bottom: 0
+          right: 0
+          padding: 10px 20px
+          background: $primaryColor
+          color: #fff
+
+article.essay
+
+  .body
+    
+    ol, ul
+      margin: 0 0.8em
+      li
+        margin-bottom: 1em
+
+  .meta
+    font-size: 0.875em
+    line-height: 1.5em
+    margin: 2em 0
+    > div
+      display: inline-block
+      margin-right: 2em
+
+  .author
+    margin-top: 2em
+    padding-top: 2em
+    border-top: 1px solid $primaryColor
+
+    .photo
+      float: left
+      width: 10%
+      min-width: 30px
+      img
+        width: 100%
+        max-width: 100%
+
+    .content
+      display: inline-block
+      width: 88%
+      padding-left: 1em
+
+      .name
+        margin: 0 0 0.5em 0
+
+      .bio
+        font-size: 0.875em
+        line-height: 1.5em
+
+      .links
+        list-style-type: none
+        margin: 0
+        padding: 0
+        > li
+          display: inline-block
+          margin-right: 2em
+
+article.essays
+
+  > ul.list
+    list-style-type: none
+    margin: 0
+    padding: 0
+
+    li.item
+      margin-bottom: 1em
+      
+      .meta
+        font-size: 0.875em
+        > a
+          display: inline-block
+          margin-right: 2em
+
+footer
+  margin-top: 2em
+  padding-top: 2em
+  border-top: 1px solid $primaryColor
+  color: #aaa
+  clear: both
+
+  .copyright
+    font-size: 0.75em
+    line-height: 1.5em

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 3 - 0
site/static/js/modernizr.custom.js


+ 1 - 0
site/templates/404.html

@@ -0,0 +1 @@
+<h1>404 Not Found</h1>

+ 1 - 0
site/templates/area.html

@@ -0,0 +1 @@
+<h1>Site home for <u>{{site}}</u></h1>

+ 68 - 0
site/templates/base.html

@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+<head>
+  
+  <meta charset="utf-8">
+  <title>{{title}}</title>
+
+  <meta name="discription" content="{{site.seo_description}}">
+  <meta name="keywords" content="{{site.seo_keywords}}">
+  <meta name="developer" content="Markus Ochel at Markuso Web Solutions - http://www.markuso.com">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1, maximum-scale=3.0, user-scalable=1">
+  <meta name="apple-mobile-web-app-capable" content="yes">
+  
+  <!-- <link rel="shortcut icon" href="{{baseURL}}/static/img/favicon.ico">
+  <link rel="apple-touch-icon-precomposed" href="{{baseURL}}/static/img/apple-touch-icon-precomposed.png"> -->
+
+  <link rel="stylesheet" href="{{baseURL}}/static/css/index.css" type="text/css" media="screen" charset="utf-8">
+
+  <script src="{{baseURL}}/static/js/modernizr.custom.js"></script>
+
+  {{#if site.css}}<style>{{{site.css}}}</style>{{/if}}
+
+</head>
+<body class="theme-{{site.theme}}">
+
+  <div class="container">
+    <h1 class="site-name"><a href="{{baseURL}}/">{{{site.name_html}}}</a></h1>
+
+    <section class="site-promo">
+      {{{blocks.site_promo.content}}}
+    </section>
+
+    {{{content}}}
+
+    {{#if site.footer_html}}<footer>{{{site.footer_html}}}</footer>{{/if}}
+  </div>
+
+  <script src="{{baseURL}}/modules.js"></script>
+  <script type="text/javascript">
+    var $ = require('jquery');
+    var _gaq = { push: function(x){} };
+    $(function() {
+      var app = require('lib/app');
+      app.initialize({
+        site: {
+          id: '{{site._id}}',
+          name: '{{site.name}}'
+        }
+      });
+    });
+  </script>
+
+  {{#if site.google_analytics_code}}
+  <!-- <script type="text/javascript">
+    var _gaq = [];
+    _gaq.push(['_setAccount', '{{site.google_analytics_code}}']);
+    _gaq.push(['_setDomainName', '{{site._id}}']);
+    _gaq.push(['_trackPageview']);
+    (function() {
+      var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+      ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+      var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+    })();
+  </script> -->
+  {{/if}}
+
+</body>
+</html>

+ 44 - 0
site/templates/collection.html

@@ -0,0 +1,44 @@
+<article class="collection">
+  <h2 class="title">{{collection.name}}</h2>
+  
+  {{#if sponsor}}
+  <section class="sponsor collection-sponsor">
+    <div class="label">
+      {{#if sponsor.label}}
+        {{{sponsor.label}}}
+      {{else}}
+        Collection is sponsored by
+      {{/if}}
+    </div>
+
+    {{#if sponsor.text_format}}
+    <div class="name">
+      {{#if sponsor.url}}
+        <a href="{{sponsor.url}}">{{{sponsor.name}}}</a>
+      {{else}}
+        {{{sponsor.name}}}
+      {{/if}}
+    </div>
+    <div class="content">{{{sponsor.content}}}</div>
+    {{/if}}
+
+    {{#if sponsor.image_format}}
+    <div class="image">
+      {{#if sponsor.url}}
+        <a href="{{sponsor.url}}" target="_blank"><img src="{{sponsor.content}}" alt=""></a>
+      {{else}}
+        <img src="{{sponsor.content}}" alt="">
+      {{/if}}
+    </div>
+    {{/if}}
+
+    {{#if sponsor.video_format}}
+    <div class="video">{{{sponsor.content}}}</div>
+    {{/if}}
+  </section>
+  {{/if}}
+
+  {{#each essays}}
+    <h3><a href="{{baseURL}}/essay/{{slug}}">{{title}}</a></h3>
+  {{/each}}
+</article>

+ 14 - 0
site/templates/collections.html

@@ -0,0 +1,14 @@
+{{#if collections}}
+<section class="collections">
+  <h3><span class="label">Collections</span></h3>
+
+  <ul>
+  {{#each collections}}
+    <li class="collection">
+      <h4 class="name"><a href="{{baseURL}}/collection/{{slug}}">{{name}}</a></h4>
+      <div class="updated">{{{updated_at_html}}}</div>
+    </li>
+  {{/each}}
+  </ul>
+</section>
+{{/if}}

+ 71 - 0
site/templates/essay.html

@@ -0,0 +1,71 @@
+<article class="essay">
+  <h2 class="title">{{essay.title}}</h2>
+
+  <section class="intro">
+    {{{essay.intro_html}}}
+  </section>
+
+  {{#if sponsor}}
+  <section class="sponsor essay-sponsor">
+    <div class="label">
+      {{#if sponsor.label}}
+        {{{sponsor.label}}}
+      {{else}}
+        Essay is sponsored by
+      {{/if}}
+    </div>
+
+    {{#if sponsor.text_format}}
+    <div class="name">
+      {{#if sponsor.url}}
+        <a href="{{sponsor.url}}">{{{sponsor.name}}}</a>
+      {{else}}
+        {{{sponsor.name}}}
+      {{/if}}
+    </div>
+    <div class="content">{{{sponsor.content}}}</div>
+    {{/if}}
+
+    {{#if sponsor.image_format}}
+    <div class="image">
+      {{#if sponsor.url}}
+        <a href="{{sponsor.url}}" target="_blank"><img src="{{sponsor.content}}" alt=""></a>
+      {{else}}
+        <img src="{{sponsor.content}}" alt="">
+      {{/if}}
+    </div>
+    {{/if}}
+
+    {{#if sponsor.video_format}}
+    <div class="video">{{{sponsor.content}}}</div>
+    {{/if}}
+  </section>
+  {{/if}}
+
+  <section class="body">
+    {{{essay.body_html}}}
+  </section>
+
+  <section class="meta">
+    <div class="published"><span class="label">Published</span> {{{essay.published_at_html}}}</div>
+    <div class="updated"><span class="label">Updated</span> {{{essay.updated_at_html}}}</div>
+    {{#each collections}}
+    <div class="collection"><a href="{{baseURL}}/collection/{{slug}}">{{name}}</a></div>
+    {{/each}}
+  </section>
+
+  <section class="author">
+    {{#if author.photo_url}}
+    <div class="photo"><img src="{{author.photo_url}}" alt="{{author.name}}"></div>
+    {{/if}}
+    <div class="content">
+      <h5 class="name"><span class="label">Author</span> {{author.name}}</h5>
+      <div class="bio">{{{author.bio}}}</div>
+      <ul class="links">
+        {{#each author.links}}
+        <li><a href="{{url}}" target="_blank">{{label}}</a></li>
+        {{/each}}
+      </ul>
+    </div>
+  </section>
+</article>

+ 17 - 0
site/templates/essays.html

@@ -0,0 +1,17 @@
+<article class="essays">
+  <h2 class="title">Essays List</h2>
+
+  <ul class="list">
+    {{#each essays}}
+    <li class="item">
+      <h3 class="title"><a href="{{baseURL}}/essay/{{slug}}">{{title}}</a></h3>
+      <div class="intro">{{{intro_html}}}</div>
+      <div class="meta">
+        {{#each collection_docs}}
+        <a class="collection" href="{{baseURL}}/collection/{{slug}}">{{name}}</a>
+        {{/each}}
+      </div>
+    </li>
+    {{/each}}
+  </ul>
+</article>

+ 7 - 0
site/templates/home.html

@@ -0,0 +1,7 @@
+<article class="home">
+  <section class="intro">
+    {{{blocks.site_intro.content}}}
+  </section>
+
+  {{{include "collections.html"}}}
+</article>

+ 1 - 0
site/templates/test.html

@@ -0,0 +1 @@
+<h1>SITE TEST PAGE</h1>

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio