├── test
├── mocha.opts
├── unit
│ └── page
│ │ └── model.js
├── integration
│ └── process_rest_test.js
└── helpers
│ └── test_server.js
├── .travis.yml
├── .npmignore
├── .gitignore
├── ui
├── index.js
└── views
│ └── root.jsx
├── bin
└── bugger-daemon.js
├── .jshintrc
├── Makefile
├── public
├── index.html
├── bugger.min.css
├── pure.min.css
└── bugger.css
├── LICENSE
├── package.json
├── lib
├── page
│ ├── controller.js
│ ├── url.js
│ ├── model.js
│ └── index.js
├── api.js
├── agents-socket-transport.js
└── bugger-daemon.js
└── README.md
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --recursive
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.10"
4 | - "0.11"
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /test
2 | /build
3 | /ui
4 | .jshintrc
5 | .travis.yml
6 | Makefile
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /build
3 | npm-debug.log
4 | public/bugger.js
5 | public/vendor.js
6 |
--------------------------------------------------------------------------------
/ui/index.js:
--------------------------------------------------------------------------------
1 | /* jshint browser:true */
2 | 'use strict';
3 |
4 | var React = require('react');
5 | var Root = require('./views/root.jsx');
6 |
7 | React.renderComponent(
8 | new Root(), document.getElementById('root'));
9 |
--------------------------------------------------------------------------------
/bin/bugger-daemon.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | var createBuggerServer = require('../lib/bugger-daemon.js');
5 | createBuggerServer().httpServer
6 | .listen(8058, '127.0.0.1', function() {
7 | var address = this.address();
8 | console.log('bugger-daemon listening:', address);
9 | console.log('Press Ctrl+C to quit.');
10 | });
11 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "undef": true,
3 | "unused": true,
4 |
5 | "freeze": true,
6 | "forin": true,
7 | "eqeqeq": true,
8 | "strict": true,
9 |
10 | "newcap": true,
11 | "latedef": "nofunc",
12 | "immed": true,
13 |
14 | "camelcase": true,
15 | "maxlen": 80,
16 | "indent": 2,
17 | "trailing": true,
18 | "nonbsp": true,
19 |
20 | "node": true,
21 | "esnext": true
22 | }
23 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: default clean build
2 | default: build
3 |
4 | build: public/vendor.js public/bugger.js
5 |
6 | clean:
7 | rm -f public/vendor.js public/bugger.js
8 |
9 | public/vendor.js:
10 | ./node_modules/.bin/browserify \
11 | --require react \
12 | --require lodash \
13 | --outfile $@
14 |
15 | BUNDLE_OPTS := \
16 | --external react \
17 | --external lodash \
18 | --outfile public/bugger.js
19 |
20 | public/bugger.js:
21 | ./node_modules/.bin/browserify . $(BUNDLE_OPTS)
22 |
23 | watch:
24 | ./node_modules/.bin/watchify . $(BUNDLE_OPTS)
25 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bugger
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/test/unit/page/model.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var assert = require('assertive');
4 |
5 | var PageModel = require('../../../lib/page/model');
6 |
7 | describe('page/model', function() {
8 | beforeEach(function() {
9 | this.pages = PageModel();
10 | });
11 |
12 | describe('fromUrlSpec', function() {
13 | describe('valid url with cwd and script', function() {
14 | var pageUrl = 'bugger:///tmp/my-module:example/ok.js';
15 |
16 | beforeEach(function() {
17 | this.page = this.pages.fromUrlSpec(pageUrl);
18 | });
19 |
20 | it('assigns an id', function() {
21 | assert.hasType(String, this.page.id);
22 | });
23 |
24 | it('parses cwd', function() {
25 | assert.equal('/tmp/my-module', this.page.cwd);
26 | });
27 |
28 | it('parses script', function() {
29 | assert.equal('example/ok.js', this.page.script);
30 | });
31 |
32 | it('can re-generate the url', function() {
33 | assert.equal(pageUrl, this.page.url);
34 | });
35 | });
36 | });
37 | });
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2013 Jan Krems
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bugger-daemon",
3 | "version": "0.0.1",
4 | "description": "buggerd sources",
5 | "main": "lib/bugger-daemon.js",
6 | "browser": "ui/index.js",
7 | "scripts": {
8 | "test": "make test",
9 | "start": "node bin/bugger-daemon.js",
10 | "prepublish": "make clean build"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git://github.com/buggerjs/bugger-daemon.git"
15 | },
16 | "keywords": [
17 | "bugger",
18 | "devtools",
19 | "debugger",
20 | "chrome"
21 | ],
22 | "author": "Jan Krems ",
23 | "license": "MIT",
24 | "devDependencies": {
25 | "assertive": "^1.4.0",
26 | "browserify": "^5.12.1",
27 | "mocha": "~1.12.0",
28 | "react": "^0.11.2",
29 | "reactify": "^0.14.0",
30 | "watchify": "^1.0.6"
31 | },
32 | "dependencies": {
33 | "bluebird": "^2.3.4",
34 | "concat-stream": "~1.0.0",
35 | "debug": "^2.0.0",
36 | "lodash": "^2.4.1",
37 | "node-uuid": "^1.4.1",
38 | "quinn": "^2.3.0",
39 | "quinn-respond": "^2.0.1",
40 | "send": "^0.9.3",
41 | "websocket": "~1.0.8"
42 | },
43 | "browserify": {
44 | "transform": [
45 | [
46 | "reactify",
47 | {
48 | "es6": true
49 | }
50 | ]
51 | ]
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/page/controller.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 | 'use strict';
21 |
22 | var respond = require('quinn-respond');
23 |
24 | function PageController(pages) {
25 | this.pages = pages;
26 | }
27 |
28 | PageController.prototype.index = function(req) {
29 | return respond.json(this.pages.all());
30 | };
31 |
32 | PageController.prototype.create = function(req, params) {
33 | if (!params.url) {
34 | return respond
35 | .json({ message: 'Can not create page without url' })
36 | .status(400);
37 | }
38 | return this.pages.createFromUrl(params.url)
39 | .then(function(page) {
40 | return respond.json(page).status(201);
41 | });
42 | };
43 |
44 | module.exports = PageController;
45 |
--------------------------------------------------------------------------------
/lib/page/url.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 | 'use strict';
21 |
22 | var querystring = require('querystring');
23 |
24 | exports.pageFromUrl = function pageFromUrl(urlSpec) {
25 | // {pwd}:{script}
26 | var match = urlSpec.match(
27 | /^bugger:\/\/([^:?#]+):([^:?#]+)(\?[^:?#]+)?(#[^:?#]+)?$/
28 | );
29 | if (match) {
30 | var cwd = match[1];
31 | var script = match[2];
32 | var qs = match[3] ? match[3].substr(1) : '';
33 | var pid = match[4] ? parseInt(match[4].substr(1), 10) : null;
34 | return {
35 | cwd: cwd,
36 | script: script,
37 | pid: pid,
38 | args: []
39 | };
40 | } else {
41 | throw new Error('Invalid bugger:// url:' + urlSpec);
42 | }
43 | };
44 |
45 | exports.pageToUrl = function pageToUrl(page) {
46 | var urlSpec = 'bugger://' + page.cwd + ':' + page.script;
47 | var query = {};
48 | if (page.args.length) {
49 | query.args = JSON.stringify(page.args);
50 | }
51 | var qs = querystring.stringify(query);
52 | if (qs) urlSpec += '?' + qs;
53 | if (page.pid) urlSpec += '#' + page.pid;
54 |
55 | return urlSpec;
56 | };
57 |
--------------------------------------------------------------------------------
/lib/api.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 | 'use strict';
21 |
22 | var url = require('url');
23 |
24 | var respond = require('quinn-respond');
25 | var PROTOCOL_VERSION = require('bugger-agents/package.json').protocolVersion;
26 |
27 | var PageController = require('./page/controller');
28 |
29 | module.exports = function(buggerd) {
30 | var page = new PageController(buggerd.Pages);
31 |
32 | return function handleApiRequest(req) {
33 | var parsed = url.parse(req.url, true);
34 | var pathname = parsed.pathname.replace(/\/$/, '');
35 |
36 | // Simple string paths first
37 | switch (pathname) {
38 | case '/json':
39 | case '/json/list':
40 | return page.index(req);
41 |
42 | case '/json/new':
43 | return page.create(req, {
44 | url: parsed.search.substr(1) || null
45 | });
46 |
47 | case '/json/version':
48 | return respond.json({
49 | 'Browser': 'node/' + process.version.substr(1),
50 | 'Protocol-Version': PROTOCOL_VERSION
51 | });
52 | }
53 |
54 | return respond.text('Not implemented').status(501);
55 | };
56 | };
57 |
--------------------------------------------------------------------------------
/test/integration/process_rest_test.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | var expect = require('expect.js');
22 |
23 | var getTestServer = require('../helpers/test_server');
24 |
25 | describe('/processes resource', function() {
26 | var testServer = getTestServer();
27 |
28 | it('starts of with an empty process list', function(done) {
29 | testServer.request('/processes', function(err, json, res, body) {
30 | if (err != null) return done(err);
31 | expect(json).to.eql([]);
32 | done();
33 | }, done);
34 | });
35 |
36 | it('supports registering a process', function(done) {
37 | testServer.request({
38 | path: '/processes/42',
39 | method: 'PUT',
40 | data: {
41 | pid: 54,
42 | pwd: '/usr/local/my_app',
43 | script: 'app.js',
44 | params: [ '--port=8080' ]
45 | }
46 | }, function(err, json, res) {
47 | if (err != null) return done(err);
48 | expect(json).to.eql({ success: true });
49 |
50 | testServer.request('/processes', function(err, json, res, body) {
51 | if (err != null) return done(err);
52 | expect(json).to.be.an('object');
53 | expect(json.length).to.be(1);
54 | expect(json[0].pid).to.be(42);
55 | expect(json[0].pwd).to.be('/usr/local/my_app');
56 | expect(json[0].title).to.be('app.js --port=8080');
57 | expect(json[0].websocket).to.be('/processes/42');
58 | done();
59 | }, done);
60 | }, done);
61 | });
62 | });
63 |
--------------------------------------------------------------------------------
/ui/views/root.jsx:
--------------------------------------------------------------------------------
1 | /** @jsx React.DOM */
2 | 'use strict';
3 |
4 | var React = require('react');
5 |
6 | var Launcher = React.createClass({
7 | handleSubmit(e) {
8 | if (e) e.preventDefault();
9 | var cwd = this.refs.cwd.state.value;
10 | var script = this.refs.script.state.value;
11 | var buggerUrl = 'bugger://' + cwd + ':' + script;
12 |
13 | var xhr = new XMLHttpRequest(), self = this;
14 | xhr.addEventListener('load', function() {
15 | if (self.props.onLaunched) {
16 | self.props.onLaunched();
17 | }
18 | });
19 | xhr.addEventListener('error', function() {
20 | console.log('error!');
21 | });
22 | xhr.open('post', '/json/new?' + buggerUrl, true);
23 | xhr.send();
24 | },
25 |
26 | render() {
27 | return ;
32 | }
33 | });
34 |
35 | var ProcessList = React.createClass({
36 | renderProcess(proc) {
37 | var cwd = proc.url.replace('bugger://', '').split(':')[0];
38 | var pid = proc.url.split('#')[1] || '?';
39 | return
40 | {proc.title}{' - '}{pid}
41 | {'Open in DevTools'}
42 |
43 | {'$ cd ' + cwd + ' && \\\n node --debug-brk=' + (proc.port || 5858) + ' ' + proc.title}
44 |
45 | ;
46 | },
47 |
48 | render() {
49 | return {this.props.items.map(this.renderProcess)} ;
50 | }
51 | });
52 |
53 | var Root = React.createClass({
54 | getInitialState() {
55 | return { processes: [] };
56 | },
57 |
58 | updateProcessList() {
59 | var xhr = new XMLHttpRequest(), self = this;
60 | xhr.addEventListener('load', function() {
61 | if (xhr.statusText !== 'OK') {
62 | console.error(xhr.statusText);
63 | return;
64 | }
65 | self.setState({
66 | processes: JSON.parse(xhr.responseText)
67 | });
68 | });
69 | xhr.addEventListener('error', function() {
70 | console.log('error!');
71 | });
72 | xhr.open('get', '/json/list', true);
73 | xhr.send();
74 | },
75 |
76 | componentWillMount() {
77 | this.updateProcessList();
78 | },
79 |
80 | render() {
81 | var processes = this.state.processes;
82 |
83 | return
84 |
Running processes
85 |
86 |
87 |
;
88 | }
89 | });
90 |
91 | module.exports = Root;
92 |
--------------------------------------------------------------------------------
/test/helpers/test_server.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 |
21 | var ConcatStream = require('concat-stream');
22 | var http = require('http');
23 | var buggerd = require('../../lib/bugger-daemon');
24 |
25 | module.exports = function getTestServer() {
26 | function makeRequest(opts, cb, errCb) {
27 | if ('string' === typeof opts) {
28 | if (opts.indexOf('/') === 0) {
29 | opts = 'http://127.0.0.1:8050' + opts;
30 | }
31 | } else if (opts != null && 'object' === typeof opts) {
32 | if (opts.port == null) {
33 | opts.port = 8050;
34 | }
35 | }
36 |
37 | var req = http.request(opts, function(res) {
38 | res.pipe(new ConcatStream(function(body) {
39 | var json;
40 | try {
41 | json = JSON.parse(body);
42 | } catch (err) {
43 | // ignore
44 | }
45 | try {
46 | cb(null, json, res, body);
47 | } catch (err) {
48 | if (errCb) { errCb(err); }
49 | }
50 | })).on('error', function(err) { cb(err); });
51 | }).on('error', cb);
52 |
53 | if ('object' === typeof opts) {
54 | if (opts['data'] != null) {
55 | req.write(JSON.stringify(opts['data']));
56 | }
57 | }
58 | req.end();
59 |
60 | return req;
61 | };
62 |
63 | var server;
64 | beforeEach(function(done) {
65 | server = buggerd().httpServer
66 | .listen(8050, '127.0.0.1', function() {
67 | return done();
68 | });
69 | });
70 |
71 | afterEach(function(done) {
72 | server.on('close', done);
73 | server.close();
74 | });
75 |
76 | return {
77 | request: makeRequest
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/page/model.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 | 'use strict';
21 |
22 | var uuid = require('node-uuid');
23 | var _ = require('lodash');
24 |
25 | var pageToUrl = require('./url').pageToUrl;
26 |
27 | function generateId() {
28 | return uuid.v1().toUpperCase();
29 | }
30 |
31 | function PageModel(props) {
32 | props = props || {};
33 |
34 | this.id = props.id || generateId();
35 | this.pid = props.pid || null;
36 | this.port = props.port || null;
37 |
38 | this.cwd = props.cwd;
39 | this.script = props.script;
40 | this.args = Array.isArray(props.args) ? props.args : [];
41 |
42 | this.description = props.description || '';
43 | this.faviconUrl = props.faviconUrl || '';
44 |
45 | this.joinedAt = props.joinedAt || Date.now();
46 | this.lastUpdate = props.lastUpdate || Date.now();
47 |
48 | this.buggerPort = props.buggerPort;
49 | };
50 |
51 | Object.defineProperties(PageModel.prototype, {
52 | title: {
53 | get: function() {
54 | return [this.script].concat(this.args.map(function(el) {
55 | if (el.indexOf(' ') !== -1)
56 | return JSON.stringify(el);
57 | return el;
58 | })).join(' ');
59 | }
60 | },
61 |
62 | url: {
63 | get: function() {
64 | var urlSpec = pageToUrl(this);
65 | return urlSpec;
66 | }
67 | },
68 |
69 | devtoolsFrontendUrl: {
70 | get: function() {
71 | return '/devtools/devtools.html?' +
72 | this.webSocketDebuggerUrl.replace(/^ws:\/\//, 'ws=') +
73 | '&toolbarColor=rgba(230,230,230,1)&textColor=rgba(0,0,0,1)';
74 | }
75 | },
76 |
77 | webSocketDebuggerUrl: {
78 | get: function() {
79 | return 'ws://127.0.0.1:' + this.buggerPort + '/devtools/page/' + this.id;
80 | }
81 | }
82 | });
83 |
84 | PageModel.prototype.validate = function() {
85 | return true;
86 | };
87 |
88 | PageModel.prototype.toJSON = function() {
89 | return _.pick(this,
90 | 'description', 'devtoolsFrontendUrl',
91 | 'faviconUrl', 'id', 'title', 'type',
92 | 'url', 'webSocketDebuggerUrl');
93 | };
94 |
95 | PageModel.buggerPort = 8058;
96 |
97 | module.exports = PageModel;
98 |
--------------------------------------------------------------------------------
/lib/agents-socket-transport.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 | 'use strict';
21 |
22 | var Promise = require('bluebird');
23 | var _ = require('lodash');
24 |
25 | // client: A websocket client
26 | // page: A page model
27 | // page.agents: bugger-agents for the page
28 | function connectClientToPage(Pages, client, page) {
29 | var agents = page.agents;
30 |
31 | function setup() {
32 | client.on('message', handleMessage);
33 | client.on('close', handleClose);
34 | client.on('error', handleFatalError);
35 | agents.on('debugEvent', handleEvent);
36 | }
37 |
38 | var cleanupDone = false;
39 | function cleanup() {
40 | if (cleanupDone) return;
41 | client.removeListener('message', handleMessage);
42 | client.removeListener('close', handleClose);
43 | client.removeListener('error', handleFatalError);
44 | agents.removeListener('debugEvent', handleEvent);
45 | cleanupDone = true;
46 | }
47 |
48 | function handleFatalError(err) {
49 | if (err) console.error(err.stack);
50 | cleanup();
51 | }
52 |
53 | function handleClose() {
54 | cleanup();
55 | }
56 |
57 | function handleMessage(data) {
58 | try {
59 | handleRequest(JSON.parse(data.utf8Data));
60 | } catch (err) {
61 | console.error('Could not process message: ' +
62 | data.utf8Data + '\n' + err.stack);
63 | }
64 | }
65 |
66 | function handleRequest(req) {
67 | var method = req.method, params = req.params, id = req.id;
68 | params = params || {};
69 |
70 | agents.callMethod(method, params).then(
71 | _.partial(sendResponse, id, null),
72 | _.partial(sendResponse, id));
73 | }
74 |
75 | function sendResponse(id, error, result) {
76 | if (error) {
77 | writeJSON({ id: id, result: null,
78 | error: typeof error === 'string' ? error :
79 | error.stack || error.message
80 | });
81 | } else {
82 | writeJSON({ id: id, result: result, error: null });
83 | }
84 | }
85 |
86 | function handleEvent(e) {
87 | writeJSON(e);
88 | }
89 |
90 | function writeJSON(obj) {
91 | if (client && client.connected) {
92 | client.send(JSON.stringify(obj));
93 | } else {
94 | console.error('Cannot write, disconnected');
95 | cleanup();
96 | }
97 | }
98 |
99 | setup();
100 | }
101 |
102 | module.exports = connectClientToPage;
103 |
--------------------------------------------------------------------------------
/lib/bugger-daemon.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 | 'use strict';
21 |
22 | var url = require('url');
23 | var path = require('path');
24 | var EventEmitter = require('events').EventEmitter;
25 |
26 | var quinn = require('quinn');
27 | var respond = require('quinn-respond');
28 | var send = require('send');
29 | var devtools = require('bugger-devtools')();
30 |
31 | var API = require('./api');
32 | var connectClientToPage = require('./agents-socket-transport');
33 |
34 | function prefix(parsed, pre) {
35 | if (parsed.pathname === pre) return true;
36 | if (parsed.pathname.indexOf(pre + '/') === 0) return true;
37 | return false;
38 | }
39 |
40 | /**
41 | * Bugger daemon - bringing buggers together since 2013
42 | */
43 | var createHttpHandler = function(buggerd) {
44 | var publicFolder = path.join(__dirname, '..', 'public');
45 | var apiApp = quinn(API(buggerd));
46 |
47 | return function(req, res) {
48 | var parsed = url.parse(req.url, true);
49 | if (prefix(parsed, '/json')) return apiApp(req, res);
50 | if (prefix(parsed, '/devtools')) return devtools(req, res);
51 | send(req, parsed.pathname, {
52 | root: publicFolder,
53 | index: [ 'index.html' ]
54 | }).pipe(res);
55 | };
56 | };
57 |
58 | var createWebsocketHandler = function(buggerd, httpServer) {
59 | var WebSocketServer = require('websocket').server;
60 |
61 | var webSocket = new WebSocketServer({
62 | httpServer: buggerd.httpServer,
63 | autoAcceptConnections: false
64 | });
65 |
66 | webSocket.on('request', function(wsRequest) {
67 | var parsed = url.parse(wsRequest.httpRequest.url);
68 |
69 | // /devtools/page/{pageId}
70 | var match = parsed.pathname.match(/^\/devtools\/page\/([^/]+)$/);
71 | if (match === null) {
72 | return wsRequest.reject(404, "No handler is configured to accept the connection.");
73 | } else {
74 | var pageId = match[1], page;
75 | try {
76 | page = buggerd.Pages.get(pageId);
77 | } catch (err) {
78 | return wsRequest.reject(404, err.message);
79 | }
80 | wsRequest.socket.page = page;
81 | wsRequest.accept(wsRequest.requestedProtocols[0], wsRequest.origin);
82 | }
83 | });
84 |
85 | webSocket.on('connect', function(client) {
86 | var page = client.page = client.socket.page;
87 | connectClientToPage(buggerd.Pages, client, page);
88 | });
89 |
90 | return webSocket;
91 | };
92 |
93 | /**
94 | * Create an http server that just runs buggerd
95 | */
96 | module.exports = function createBuggerServer() {
97 | var buggerd = new EventEmitter();
98 |
99 | var Pages = buggerd.Pages = require('./page')();
100 |
101 | buggerd.httpServer = require('http').createServer(
102 | createHttpHandler(buggerd)
103 | );
104 |
105 | buggerd.webSocket = createWebsocketHandler(buggerd);
106 |
107 | buggerd.httpServer.on('listening', function() {
108 | buggerd.Pages.buggerPort = this.address().port;
109 | });
110 |
111 | return buggerd;
112 | };
113 |
--------------------------------------------------------------------------------
/lib/page/index.js:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2013 Jan Krems
2 | //
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | // this software and associated documentation files (the "Software"), to deal in
5 | // the Software without restriction, including without limitation the rights to
6 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | // of the Software, and to permit persons to whom the Software is furnished to do
8 | // so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all
11 | // copies or substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | // SOFTWARE.
20 | 'use strict';
21 |
22 | var execFile = require('child_process').execFile;
23 |
24 | var Promise = require('bluebird');
25 | var _ = require('lodash');
26 | var attachToPort = require('bugger-agents').attachToPort;
27 | var debug = require('debug')('bugger-daemon:page');
28 |
29 | var PageModel = require('./model');
30 | var pageFromUrl = require('./url').pageFromUrl;
31 |
32 | function verifyPortOpen(port) {
33 | return Promise.reject(new Error('Not implemented'));
34 | }
35 |
36 | function findOpenPort() {
37 | var net = require('net');
38 | return new Promise(function(resolve, reject) {
39 | var server = net.createServer();
40 | server.on('error', reject);
41 | server.listen(0, function() {
42 | var port = this.address().port;
43 | server.on('close', resolve.bind(null, port));
44 | server.close();
45 | });
46 | });
47 | }
48 |
49 | module.exports = function() {
50 | var store = {};
51 | var procByPid = {};
52 | var Pages = {};
53 |
54 | Pages.get = function(id) {
55 | if (!store[id]) {
56 | var err = new Error('Process not found');
57 | err.code = 404;
58 | throw err;
59 | }
60 | return store[id];
61 | };
62 |
63 | Pages.all = function all(skip, limit) {
64 | var acc = _.values(store);
65 |
66 | if (skip == null || isNaN(skip)) { skip = 0; }
67 | if (limit == null || isNaN(limit)) { limit = acc.length; }
68 |
69 | return acc.slice(skip, skip + limit);
70 | };
71 |
72 | Pages.remove = function(id) {
73 | delete store[id];
74 | };
75 |
76 | Pages.save = function(page) {
77 | if (!(page instanceof PageModel)) {
78 | page = new PageModel(page);
79 | }
80 | page.validate();
81 | if (store[page.id] != null) {
82 | page.joinedAt = store[page.id].joinedAt;
83 | }
84 | return store[page.id] = page;
85 | };
86 |
87 | Pages.launchAndConnect = function(page) {
88 | // 1. get available debug port
89 | function getAvailablePort() {
90 | debug('getAvailablePort', page.port);
91 | if (page.port !== null) {
92 | return verifyPortOpen(page.port);
93 | }
94 | return findOpenPort();
95 | }
96 |
97 | // 2. launch process
98 | function launchProcess(port) {
99 | debug('Found available port', port);
100 | page.port = port;
101 |
102 | var nodePath = process.execPath;
103 | var nodeArgs = [
104 | '--debug-brk=' + page.port, page.script
105 | ].concat(page.args);
106 | var childOptions = { cwd: page.cwd, env: process.env };
107 |
108 | return new Promise(function(resolve, reject) {
109 | var child =
110 | execFile(nodePath, nodeArgs, childOptions);
111 | if (process.env.BUGGER_PIPE_CHILD) {
112 | child.stdout.pipe(process.stdout);
113 | child.stderr.pipe(process.stderr);
114 | }
115 | var pid = child.pid;
116 | child.on('exit', function(exitCode) {
117 | if (page.pid === pid) page.pid = null;
118 | reject(new Error('Child exited with code ' + exitCode));
119 | });
120 |
121 | process.on('exit', function() {
122 | try { child.kill(); } catch (err) {}
123 | });
124 |
125 | process.on('uncaughtException', function() {
126 | try { child.kill(); } catch (err) {}
127 | });
128 |
129 | page.pid = child.pid;
130 | procByPid[page.pid] = child.pid;
131 | debug('Attaching debug client', page.port);
132 | attachToPort(page.port).then(function(agents) {
133 | debug('Attached');
134 | page.agents = agents
135 | resolve(page);
136 | });
137 | });
138 | }
139 |
140 | return getAvailablePort().then(launchProcess);
141 | };
142 |
143 | Pages.createFromUrl = function(urlSpec) {
144 | var page = new PageModel(_.defaults({
145 | buggerPort: Pages.buggerPort
146 | }, pageFromUrl(urlSpec)));
147 | return Pages.launchAndConnect(page).then(Pages.save);
148 | };
149 |
150 | Pages.buggerPort = 8058;
151 |
152 | return Pages;
153 | };
154 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bugger-daemon
2 |
3 | [](https://travis-ci.org/buggerjs/bugger-daemon)
4 |
5 | Main point of communication/integration between the many moving parts of
6 | bugger.
7 |
8 | * Any process being bugger'd will register with buggerd
9 | * Instrumentation code will communicate with buggerd
10 | * The Chrome extension will ask buggerd for information about running procs
11 | * All DevTools will communicate via websocket with buggerd
12 |
13 | ## ASCII art time
14 |
15 | ```
16 |
17 | --------------------------- Chrome ---------------------------
18 | | | | |
19 | | DevTools A | DevTools B | bugger.crx |
20 | | | | | | | |
21 | ---------|--------------------|--------------------|----------
22 | | | |
23 | | (I) | (I) | (II)
24 | | | |
25 | ---------|---------------- buggerd ----------------|----------
26 | | V | V | V |
27 | | Domain Agents A | Domain Agents B | Meta HTTP API |
28 | | | | \ | Δ |
29 | --------|----------------------------\-------------|----------
30 | | \ |
31 | | (III) | (III) |
32 | | _________________|__________/| (II)*
33 | V / V |
34 | ------- A.js ---/--- ------- B.js -|------
35 | | / | | | |
36 | | Instrumentation | | Instrumentation |
37 | | | | |
38 | -------------------- ---------------------
39 |
40 | (I) Chrome Remote Debugging Protocol // websocket
41 | https://developers.google.com/chrome-developer-tools/docs/protocol/1.0/
42 |
43 | (II) REST API for basic meta data about debugged processes (see below)
44 |
45 | (II)* The instrumentation code may also communicate directly with the domain
46 | agents if necessary.
47 |
48 | (III) v8 debugger protocol
49 | https://code.google.com/p/v8/wiki/DebuggerProtocol
50 | ```
51 |
52 | ## API
53 |
54 | This is meant to be (roughly) compatible with the API Chrome exposes.
55 |
56 |
57 | ### GET /json/version
58 |
59 | *Note: This endpoint works using any HTTP method to be compatible with Chrome.*
60 |
61 | ```json
62 | {
63 | Browser: "Chrome/37.0.2062.124",
64 | Protocol-Version: "1.1",
65 | User-Agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
66 | WebKit-Version: "537.36 (@181352)"
67 | }
68 | ```
69 |
70 |
71 | ### GET /json, GET /json/list
72 |
73 | *Note: This endpoint works using any HTTP method to be compatible with Chrome.*
74 |
75 | ```json
76 | [ {
77 | description: "",
78 | devtoolsFrontendUrl: "/devtools/devtools.html?ws=localhost:9222/devtools/page/961C1EB7-A0DA-2F42-F6D4-76B453E70DB5",
79 | faviconUrl: "https://s.yimg.com/rz/l/favicon.ico",
80 | id: "961C1EB7-A0DA-2F42-F6D4-76B453E70DB5",
81 | title: "Yahoo",
82 | type: "page",
83 | url: "https://www.yahoo.com/",
84 | webSocketDebuggerUrl: "ws://localhost:9222/devtools/page/961C1EB7-A0DA-2F42-F6D4-76B453E70DB5"
85 | } ]
86 | ```
87 |
88 |
89 | ### POST /json/new?{url}
90 |
91 | *Note: This endpoint works using any HTTP method to be compatible with Chrome.*
92 |
93 | It responds with a description of the newly spawned process.
94 | The format is the same as one element in the array returned by `/json`.
95 |
96 | The url is a "bugger url".
97 | Which obviously isn't *really* a thing but it's relatively straight-forward:
98 |
99 | bugger://{cwd}:{script}
100 |
101 | The working directory may be an absolute path (`/tmp/foo`)
102 | or anything that can be resolved globally (`~/Projects/xyz`).
103 | The script will be resolved relative to the working directory.
104 |
105 | In the future it might be good to also support arguments,
106 | either via query or via POST body.
107 |
108 |
109 | ### POST /json/activate/{pageId}
110 |
111 | *Note: This endpoint works using any HTTP method to be compatible with Chrome.*
112 |
113 | In Chrome this would bring a page into the foreground (activate a tab).
114 | Since this doesn't make a lot of sense for UI-less node processes,
115 | it's a noop.
116 |
117 | If the target is invalid, responds with 404 and a string like this:
118 |
119 | ```json
120 | "No such target id: {pageId}"
121 | ```
122 |
123 | For valid targets the response is 200, `"Target activated"`.
124 |
125 |
126 | ### POST /json/close/{pageId}
127 |
128 | *Note: This endpoint works using any HTTP method to be compatible with Chrome.*
129 |
130 | Removes the script identifed by `pageId`.
131 | If the process is running currently, it will be killed.
132 |
133 | If the target is invalid, responds with 404 and a string like this:
134 |
135 | ```json
136 | "No such target id: {pageId}"
137 | ```
138 |
139 | For valid targets the response is 200, `"Target is closing"`.
140 |
141 |
142 | ### Websocket /devtools/page/{pageId}
143 |
144 | This is where the devtools are connecting to.
145 |
146 |
147 | ### GET /devtools/*
148 |
149 | A copy of the devtools that ship with Chrome.
150 |
--------------------------------------------------------------------------------
/public/bugger.min.css:
--------------------------------------------------------------------------------
1 | body{background-color:#fff;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif}
2 | .content{margin:0 auto;max-width:800px;margin-bottom:50px}
3 | nav{background:#ededed}
4 | nav>.pure-menu{max-width:800px;margin:0 auto}
5 | dt{font-weight: bold} dd{margin: 0 0 10px 0}
6 | a{color:#b9410e}
7 | .pure-button{display:inline-block;*display:inline;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
8 | .pure-button::-moz-focus-inner{padding:0;border:0}
9 | .pure-button{font-size:100%;*font-size:90%;*overflow:visible;padding:.5em 1.5em .5em;color:#0f0f0f;border:1px solid #b6b4b4;border:none rgba(0,0,0,0);background-color:#c0bfbf;border-radius:2px;text-decoration:none;-webkit-font-smoothing:antialiased;-webkit-transition:.1s linear -webkit-box-shadow;-moz-transition:.1s linear -moz-box-shadow;-ms-transition:.1s linear box-shadow;-o-transition:.1s linear box-shadow;transition:.1s linear box-shadow}
10 | .pure-button-hover,.pure-button:hover{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#00000000',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,0.05)),to(rgba(0,0,0,0.05)));background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,0.05) 0,rgba(0,0,0,0.05));background-image:-ms-linear-gradient(transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.15));background-image:-o-linear-gradient(transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.05));background-image:linear-gradient(transparent,rgba(0,0,0,0.05) 40%,rgba(0,0,0,0.05))}
11 | .pure-button-active,.pure-button:active{box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.20) inset}
12 | .pure-button[disabled],.pure-button-disabled,.pure-button-disabled:hover,.pure-button-disabled:active{border:0;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);-khtml-opacity:.40;-moz-opacity:.40;opacity:.40;cursor:not-allowed;box-shadow:none}
13 | .pure-button-hidden{display:none}
14 | .pure-button::-moz-focus-inner{padding:0;border:0}
15 | .pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#b9410e;color:#fffcfa}
16 | .pure-button:-moz-focusring{outline-color:rgba(0,0,0,0.85)}
17 | /*! Copyright 2013 Yahoo! Inc. http://yuilibrary.com/license/ *//*! Copyright (c) Nicolas Gallagher and Jonathan Neal *//*! normalize.css v1.1.0 | MIT License | git.io/normalize */.pure-skin-bugger .pure-form{margin:0}
18 | .pure-skin-bugger .pure-form fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
19 | .pure-skin-bugger .pure-form legend{border:0;padding:0;white-space:normal;*margin-left:-7px}
20 | .pure-skin-bugger .pure-form button,.pure-skin-bugger .pure-form input,.pure-skin-bugger .pure-form select,.pure-skin-bugger .pure-form textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}
21 | .pure-skin-bugger .pure-form button,.pure-skin-bugger .pure-form input{line-height:normal}
22 | .pure-skin-bugger .pure-form button,.pure-skin-bugger .pure-form input[type="button"],.pure-skin-bugger .pure-form input[type="reset"],.pure-skin-bugger .pure-form input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}
23 | .pure-skin-bugger .pure-form button[disabled],.pure-skin-bugger .pure-form input[disabled]{cursor:default}
24 | .pure-skin-bugger .pure-form input[type="checkbox"],.pure-skin-bugger .pure-form input[type="radio"]{box-sizing:border-box;padding:0;*height:13px;*width:13px}
25 | .pure-skin-bugger .pure-form input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
26 | .pure-skin-bugger .pure-form input[type="search"]::-webkit-search-cancel-button,.pure-skin-bugger .pure-form input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
27 | .pure-skin-bugger .pure-form button::-moz-focus-inner,.pure-skin-bugger .pure-form input::-moz-focus-inner{border:0;padding:0}
28 | .pure-skin-bugger .pure-form textarea{overflow:auto;vertical-align:top}
29 | @media only screen and (max-width :480px){.pure-skin-bugger .pure-form button[type="submit"]{margin:.7em 0 0}
30 | .pure-skin-bugger .pure-form input[type="text"],.pure-skin-bugger .pure-form input[type="password"],.pure-skin-bugger .pure-form input[type="email"],.pure-skin-bugger .pure-form input[type="url"],.pure-skin-bugger .pure-form input[type="date"],.pure-skin-bugger .pure-form input[type="month"],.pure-skin-bugger .pure-form input[type="time"],.pure-skin-bugger .pure-form input[type="datetime"],.pure-skin-bugger .pure-form input[type="datetime-local"],.pure-skin-bugger .pure-form input[type="week"],.pure-skin-bugger .pure-form input[type="number"],.pure-skin-bugger .pure-form input[type="search"],.pure-skin-bugger .pure-form input[type="tel"],.pure-skin-bugger .pure-form input[type="color"],.pure-skin-bugger .pure-form label{margin-bottom:.3em;display:block}
31 | .pure-skin-bugger .pure-group input[type="text"],.pure-skin-bugger .pure-group input[type="password"],.pure-skin-bugger .pure-group input[type="email"],.pure-skin-bugger .pure-group input[type="url"],.pure-skin-bugger .pure-group input[type="date"],.pure-skin-bugger .pure-group input[type="month"],.pure-skin-bugger .pure-group input[type="time"],.pure-skin-bugger .pure-group input[type="datetime"],.pure-skin-bugger .pure-group input[type="datetime-local"],.pure-skin-bugger .pure-group input[type="week"],.pure-skin-bugger .pure-group input[type="number"],.pure-skin-bugger .pure-group input[type="search"],.pure-skin-bugger .pure-group input[type="tel"],.pure-skin-bugger .pure-group input[type="color"]{margin-bottom:0}
32 | .pure-skin-bugger .pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}
33 | .pure-skin-bugger .pure-form-aligned .pure-controls{margin:1.5em 0 0 0}
34 | .pure-skin-bugger .pure-form .pure-help-inline,.pure-skin-bugger .pure-form-message-inline,.pure-skin-bugger .pure-form-message{display:block;font-size:80%;padding:.2em 0 .8em}
35 | }
36 | .pure-skin-bugger .pure-form input[type="text"],.pure-skin-bugger .pure-form input[type="password"],.pure-skin-bugger .pure-form input[type="email"],.pure-skin-bugger .pure-form input[type="url"],.pure-skin-bugger .pure-form input[type="date"],.pure-skin-bugger .pure-form input[type="month"],.pure-skin-bugger .pure-form input[type="time"],.pure-skin-bugger .pure-form input[type="datetime"],.pure-skin-bugger .pure-form input[type="datetime-local"],.pure-skin-bugger .pure-form input[type="week"],.pure-skin-bugger .pure-form input[type="number"],.pure-skin-bugger .pure-form input[type="search"],.pure-skin-bugger .pure-form input[type="tel"],.pure-skin-bugger .pure-form input[type="color"],.pure-skin-bugger .pure-form select,.pure-skin-bugger .pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #e6e6e6;font-size:.8em;box-shadow:inset 0 1px 3px #e6e6e6;border-radius:4px;-webkit-transition:.3s linear border;-moz-transition:.3s linear border;-ms-transition:.3s linear border;-o-transition:.3s linear border;transition:.3s linear border;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-font-smoothing:antialiased}
37 | .pure-skin-bugger .pure-form input[type="text"]:focus,.pure-skin-bugger .pure-form input[type="password"]:focus,.pure-skin-bugger .pure-form input[type="email"]:focus,.pure-skin-bugger .pure-form input[type="url"]:focus,.pure-skin-bugger .pure-form input[type="date"]:focus,.pure-skin-bugger .pure-form input[type="month"]:focus,.pure-skin-bugger .pure-form input[type="time"]:focus,.pure-skin-bugger .pure-form input[type="datetime"]:focus,.pure-skin-bugger .pure-form input[type="datetime-local"]:focus,.pure-skin-bugger .pure-form input[type="week"]:focus,.pure-skin-bugger .pure-form input[type="number"]:focus,.pure-skin-bugger .pure-form input[type="search"]:focus,.pure-skin-bugger .pure-form input[type="tel"]:focus,.pure-skin-bugger .pure-form input[type="color"]:focus,.pure-skin-bugger .pure-form select:focus,.pure-skin-bugger .pure-form textarea:focus{outline:0;outline:thin dotted \9;border-color:#129fea}
38 | .pure-skin-bugger .pure-form input[type="file"]:focus,.pure-skin-bugger .pure-form input[type="radio"]:focus,.pure-skin-bugger .pure-form input[type="checkbox"]:focus{outline:thin dotted #333;outline:1px auto #129fea}
39 | .pure-skin-bugger .pure-form .pure-checkbox,.pure-skin-bugger .pure-form .pure-radio{margin:.5em 0;display:block}
40 | .pure-skin-bugger .pure-form input[type="text"][disabled],.pure-skin-bugger .pure-form input[type="password"][disabled],.pure-skin-bugger .pure-form input[type="email"][disabled],.pure-skin-bugger .pure-form input[type="url"][disabled],.pure-skin-bugger .pure-form input[type="date"][disabled],.pure-skin-bugger .pure-form input[type="month"][disabled],.pure-skin-bugger .pure-form input[type="time"][disabled],.pure-skin-bugger .pure-form input[type="datetime"][disabled],.pure-skin-bugger .pure-form input[type="datetime-local"][disabled],.pure-skin-bugger .pure-form input[type="week"][disabled],.pure-skin-bugger .pure-form input[type="number"][disabled],.pure-skin-bugger .pure-form input[type="search"][disabled],.pure-skin-bugger .pure-form input[type="tel"][disabled],.pure-skin-bugger .pure-form input[type="color"][disabled],.pure-skin-bugger .pure-form select[disabled],.pure-skin-bugger .pure-form textarea[disabled],.pure-skin-bugger .pure-form input[readonly],.pure-skin-bugger .pure-form select[readonly],.pure-skin-bugger .pure-form textarea[readonly]{cursor:not-allowed;box-shadow:inset 0 1px 10px #ededed;background-color:#fff;color:#adadad;border-color:#e6e6e6}
41 | .pure-skin-bugger .pure-form input:focus:invalid,.pure-skin-bugger .pure-form textarea:focus:invalid,.pure-skin-bugger .pure-form select:focus:invalid{color:#b94a48;border:1px solid #ee5f5b}
42 | .pure-skin-bugger .pure-form input:focus:invalid:focus,.pure-skin-bugger .pure-form textarea:focus:invalid:focus,.pure-skin-bugger .pure-form select:focus:invalid:focus{border-color:#e9322d}
43 | .pure-skin-bugger .pure-form input[type="file"]:focus:invalid:focus,.pure-skin-bugger .pure-form input[type="radio"]:focus:invalid:focus,.pure-skin-bugger .pure-form input[type="checkbox"]:focus:invalid:focus{outline-color:#e9322d}
44 | .pure-skin-bugger .pure-form select{border:1px solid #e6e6e6;background-color:white}
45 | .pure-skin-bugger .pure-form select[multiple]{height:auto}
46 | .pure-skin-bugger .pure-form label{margin:.5em 0 .2em;color:#4f4f4f;font-size:90%}
47 | .pure-skin-bugger .pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}
48 | .pure-skin-bugger .pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;font-size:125%;color:#262626;border-bottom:1px solid #ededed}
49 | .pure-skin-bugger .pure-form-stacked label{display:block}
50 | .pure-skin-bugger .pure-form-aligned input,.pure-skin-bugger .pure-form-aligned textarea,.pure-skin-bugger .pure-form-aligned select,.pure-skin-bugger .pure-form-aligned .pure-help-inline,.pure-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}
51 | .pure-skin-bugger .pure-form-aligned .pure-control-group{margin-bottom:.5em}
52 | .pure-skin-bugger .pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}
53 | .pure-skin-bugger .pure-form-aligned .pure-controls{margin:1.5em 0 0 10em}
54 | .pure-skin-bugger .pure-form .pure-input-rounded{border-radius:30px;padding-left:1em}
55 | .pure-skin-bugger .pure-form .pure-group fieldset{margin-bottom:10px}
56 | .pure-skin-bugger .pure-form .pure-group input{display:block;padding:.5em .6em;margin:0;border-radius:0;position:relative;top:-1px}
57 | .pure-skin-bugger .pure-form .pure-group input:focus{z-index:2}
58 | .pure-skin-bugger .pure-form .pure-group input:first-child{top:1px;border-radius:4px 4px 0 0}
59 | .pure-skin-bugger .pure-form .pure-group input:last-child{top:-2px;border-radius:0 0 4px 4px}
60 | .pure-skin-bugger .pure-form .pure-group button{margin:.35em 0}
61 | .pure-skin-bugger .pure-form .pure-input-1{width:100%}
62 | .pure-skin-bugger .pure-form .pure-input-2-3{width:66%}
63 | .pure-skin-bugger .pure-form .pure-input-1-2{width:50%}
64 | .pure-skin-bugger .pure-form .pure-input-1-3{width:33%}
65 | .pure-skin-bugger .pure-form .pure-input-1-4{width:25%}
66 | .pure-skin-bugger .pure-form .pure-help-inline,.pure-skin-bugger .pure-form-message-inline{display:inline-block;padding-left:.3em;color:#adadad;font-size:90%;vertical-align:middle}
67 | .pure-skin-bugger .pure-form-message{display:block;margin:.5em 0 .2em;color:#adadad;font-size:90%}
68 | .pure-skin-bugger .pure-table{border-collapse:separate;border-spacing:0;empty-cells:show;border:1px solid #dedede}
69 | .pure-skin-bugger .pure-table caption{color:#adadad;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}
70 | .pure-skin-bugger .pure-table td,.pure-skin-bugger .pure-table th{border-left:1px solid #dedede;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.3em .6em}
71 | .pure-skin-bugger .pure-table td:first-child,.pure-skin-bugger .pure-table th:first-child{border-left-width:0}
72 | .pure-skin-bugger .pure-table thead{background-color:#d7d6d6;color:#272626;text-align:left;vertical-align:bottom;white-space:nowrap}
73 | .pure-skin-bugger .pure-table td{background-color:#ededed;color:#404040}
74 | .pure-skin-bugger .pure-table-odd td{background-color:#dedede;color:#262626}
75 | .pure-skin-bugger .pure-table-bordered td{border-bottom:1px solid #dedede}
76 | .pure-skin-bugger .pure-table-bordered tbody>tr:last-child td,.pure-skin-bugger .pure-table-horizontal tbody>tr:last-child td{border-bottom-width:0}
77 | .pure-skin-bugger .pure-table-horizontal td,.pure-skin-bugger .pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #dedede}
78 | .pure-skin-bugger .pure-table-horizontal tbody>tr:last-child td{border-bottom-width:0}
79 | .pure-skin-bugger .pure-menu ul{position:absolute;visibility:hidden}
80 | .pure-skin-bugger .pure-menu.pure-menu-open{visibility:visible;z-index:2;width:100%}
81 | .pure-skin-bugger .pure-menu ul{left:-10000px;list-style:none;margin:0;padding:0;top:-10000px;z-index:1}
82 | .pure-skin-bugger .pure-menu>ul{position:relative}
83 | .pure-skin-bugger .pure-menu-open>ul{left:0;top:0;visibility:visible}
84 | .pure-skin-bugger .pure-menu-open>ul:focus{outline:0}
85 | .pure-skin-bugger .pure-menu li{position:relative}
86 | .pure-skin-bugger .pure-menu a,.pure-skin-bugger .pure-menu .pure-menu-heading{display:block;color:inherit;line-height:1.5em;padding:.35em 1.4em;text-decoration:none;white-space:nowrap}
87 | .pure-skin-bugger .pure-menu.pure-menu-horizontal>.pure-menu-heading{display:inline-block;*display:inline;zoom:1;margin:0;vertical-align:middle}
88 | .pure-skin-bugger .pure-menu.pure-menu-horizontal>ul{display:inline-block;*display:inline;zoom:1;vertical-align:middle;height:2.4em}
89 | .pure-skin-bugger .pure-menu li a{padding:.35em 1.4em}
90 | .pure-skin-bugger .pure-menu-can-have-children>.pure-menu-label:after{content:'\25B8';float:right;font-family:'Lucida Grande','Lucida Sans Unicode','DejaVu Sans',sans-serif;margin-right:-20px;margin-top:-1px}
91 | .pure-skin-bugger .pure-menu-can-have-children>.pure-menu-label{padding-right:30px}
92 | .pure-skin-bugger .pure-menu-separator{background-color:#dedede;display:block;height:1px;font-size:0;margin:7px 2px;overflow:hidden}
93 | .pure-skin-bugger .pure-menu-hidden{display:none}
94 | .pure-skin-bugger .pure-menu-fixed{position:fixed;top:0;left:0;width:100%}
95 | .pure-skin-bugger .pure-menu-horizontal li{display:inline-block;*display:inline;zoom:1;vertical-align:middle}
96 | .pure-skin-bugger .pure-menu-horizontal li li{display:block}
97 | .pure-skin-bugger .pure-menu-horizontal>.pure-menu-children>.pure-menu-can-have-children>.pure-menu-label:after{content:"\25BE"}
98 | .pure-skin-bugger .pure-menu-horizontal>.pure-menu-children>.pure-menu-can-have-children>.pure-menu-label{padding-right:30px}
99 | .pure-skin-bugger .pure-menu-horizontal li.pure-menu-separator{height:50%;width:1px;margin:0 7px}
100 | .pure-skin-bugger .pure-menu-horizontal li li.pure-menu-separator{height:1px;width:auto;margin:7px 2px}
101 | .pure-skin-bugger .pure-paginator{list-style:none;margin:0;padding:0}
102 | .pure-skin-bugger .pure-paginator li{display:inline-block;*display:inline;zoom:1;margin:0 -0.35em 0 0}
103 | .pure-skin-bugger .pure-paginator .pure-button{border-radius:0;padding:.8em 1.4em;vertical-align:top;height:1.1em}
104 | .pure-skin-bugger .pure-paginator .pure-button:focus{outline-style:none}
105 | .pure-skin-bugger .pure-paginator .prev{border-radius:4px 0 0 4px}
106 | .pure-skin-bugger .pure-paginator .next{border-radius:0 4px 4px 0}
107 | .pure-skin-bugger .pure-menu.pure-menu-open,.pure-skin-bugger .pure-menu.pure-menu-horizontal li .pure-menu-children{background:#ededed;border:1px solid #dedede}
108 | .pure-skin-bugger .pure-menu.pure-menu-horizontal,.pure-skin-bugger .pure-menu.pure-menu-horizontal .pure-menu-heading{border:0}
109 | .pure-skin-bugger .pure-menu a{border:1px solid transparent;border-left:0;border-right:0}
110 | .pure-skin-bugger .pure-menu a,.pure-skin-bugger .pure-menu .pure-menu-can-have-children>li:after{color:#404040}
111 | .pure-skin-bugger .pure-menu .pure-menu-can-have-children>li:hover:after{color:#262626}
112 | .pure-skin-bugger .pure-menu .pure-menu-open{background:#d6d6d6}
113 | .pure-skin-bugger .pure-menu li a:hover{background:#d6d6d6}
114 | .pure-skin-bugger .pure-menu li.pure-menu-disabled a:hover{background:#ededed;color:#9e9e9e}
115 | .pure-skin-bugger .pure-menu .pure-menu-disabled>a{background-image:none;border-color:transparent;cursor:default}
116 | .pure-skin-bugger .pure-menu .pure-menu-disabled>a,.pure-skin-bugger .pure-menu .pure-menu-can-have-children.pure-menu-disabled>a:after{color:#9e9e9e}
117 | .pure-skin-bugger .pure-menu .pure-menu-heading{color:#171717;text-transform:uppercase;font-size:90%;margin-top:.5em;border-bottom:solid 1px #dedede}
118 | .pure-skin-bugger .pure-menu li.pure-menu-selected a{background-color:#b9410e;color:#fffcfa}
119 | .pure-skin-bugger .pure-menu.pure-menu-open.pure-menu-fixed{border:0;border-bottom:1px solid #dedede}
120 | @media(max-width:480px){.pure-skin-bugger .pure-menu-horizontal{width:100%}
121 | .pure-skin-bugger .pure-menu-children li{display:block;border-bottom:1px solid #dedede}
122 | }
123 |
--------------------------------------------------------------------------------
/public/pure.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | Pure v0.2.1
3 | Copyright 2013 Yahoo! Inc. All rights reserved.
4 | Licensed under the BSD License.
5 | https://github.com/yui/pure/blob/master/LICENSE.md
6 | */
7 | /*!
8 | normalize.css v1.1.2 | MIT License | git.io/normalize
9 | Copyright (c) Nicolas Gallagher and Jonathan Neal
10 | */
11 | /*! normalize.css v1.1.2 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}h2{font-size:1.5em;margin:.83em 0}h3{font-size:1.17em;margin:1em 0}h4{font-size:1em;margin:1.33em 0}h5{font-size:.83em;margin:1.67em 0}h6{font-size:.67em;margin:2.33em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:1em 40px}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}p,pre{margin:1em 0}code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:'';content:none}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,menu,ol,ul{margin:1em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0;white-space:normal;*margin-left:-7px}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}
12 | .pure-button{display:inline-block;*display:inline;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button{font-size:100%;*font-size:90%;*overflow:visible;padding:.5em 1.5em;color:#444;color:rgba(0,0,0,.8);*color:#444;border:1px solid #999;border:0 rgba(0,0,0,0);background-color:#E6E6E6;text-decoration:none;border-radius:2px;-webkit-font-smoothing:antialiased;-webkit-transition:.1s linear -webkit-box-shadow;-moz-transition:.1s linear -moz-box-shadow;-ms-transition:.1s linear box-shadow;-o-transition:.1s linear box-shadow;transition:.1s linear box-shadow}.pure-button-hover,.pure-button:hover,.pure-button:focus{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#1a000000', GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:-moz-linear-gradient(top,rgba(0,0,0,.05) 0,rgba(0,0,0,.1));background-image:-ms-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:-o-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset}.pure-button[disabled],.pure-button-disabled,.pure-button-disabled:hover,.pure-button-disabled:focus,.pure-button-disabled:active{border:0;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);filter:alpha(opacity=40);-khtml-opacity:.4;-moz-opacity:.4;opacity:.4;cursor:not-allowed;box-shadow:none}.pure-button-hidden{display:none}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}
13 | .pure-form{margin:0}.pure-form fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}.pure-form legend{border:0;padding:0;white-space:normal;*margin-left:-7px}.pure-form button,.pure-form input,.pure-form select,.pure-form textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.pure-form button,.pure-form input{line-height:normal}.pure-form button,.pure-form input[type=button],.pure-form input[type=reset],.pure-form input[type=submit]{-webkit-appearance:button;cursor:pointer;*overflow:visible}.pure-form button[disabled],.pure-form input[disabled]{cursor:default}.pure-form input[type=checkbox],.pure-form input[type=radio]{box-sizing:border-box;padding:0;*height:13px;*width:13px}.pure-form input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}.pure-form input[type=search]::-webkit-search-cancel-button,.pure-form input[type=search]::-webkit-search-decoration{-webkit-appearance:none}.pure-form button::-moz-focus-inner,.pure-form input::-moz-focus-inner{border:0;padding:0}.pure-form textarea{overflow:auto;vertical-align:top}.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;font-size:.8em;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-transition:.3s linear border;-moz-transition:.3s linear border;-ms-transition:.3s linear border;-o-transition:.3s linear border;transition:.3s linear border;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-font-smoothing:antialiased}.pure-form input[type=text]:focus,.pure-form input[type=password]:focus,.pure-form input[type=email]:focus,.pure-form input[type=url]:focus,.pure-form input[type=date]:focus,.pure-form input[type=month]:focus,.pure-form input[type=time]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=week]:focus,.pure-form input[type=number]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=color]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;outline:thin dotted \9;border-color:#129FEA}.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus,.pure-form input[type=checkbox]:focus{outline:thin dotted #333;outline:1px auto #129FEA}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=text][disabled],.pure-form input[type=password][disabled],.pure-form input[type=email][disabled],.pure-form input[type=url][disabled],.pure-form input[type=date][disabled],.pure-form input[type=month][disabled],.pure-form input[type=time][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=week][disabled],.pure-form input[type=number][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=color][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly],.pure-form input[readonly]:focus,.pure-form select[readonly]:focus,.pure-form textarea[readonly]:focus{background:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form textarea:focus:invalid,.pure-form select:focus:invalid{color:#b94a48;border:1px solid #ee5f5b}.pure-form input:focus:invalid:focus,.pure-form textarea:focus:invalid:focus,.pure-form select:focus:invalid:focus{border-color:#e9322d}.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus,.pure-form input[type=checkbox]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em;font-size:90%}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;font-size:125%;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=text],.pure-form-stacked input[type=password],.pure-form-stacked input[type=email],.pure-form-stacked input[type=url],.pure-form-stacked input[type=date],.pure-form-stacked input[type=month],.pure-form-stacked input[type=time],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=week],.pure-form-stacked input[type=number],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=color],.pure-form-stacked select,.pure-form-stacked label,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned textarea,.pure-form-aligned select,.pure-form-aligned .pure-help-inline,.pure-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 10em}.pure-form input.pure-input-rounded,.pure-form .pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input{display:block;padding:10px;margin:0;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus{z-index:2}.pure-form .pure-group input:first-child{top:1px;border-radius:4px 4px 0 0}.pure-form .pure-group input:last-child{top:-2px;border-radius:0 0 4px 4px}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form .pure-help-inline,.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:90%}.pure-form-message{display:block;color:#666;font-size:90%}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form label{margin-bottom:.3em;display:block}.pure-group input[type=text],.pure-group input[type=password],.pure-group input[type=email],.pure-group input[type=url],.pure-group input[type=date],.pure-group input[type=month],.pure-group input[type=time],.pure-group input[type=datetime],.pure-group input[type=datetime-local],.pure-group input[type=week],.pure-group input[type=number],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=color]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0}.pure-form .pure-help-inline,.pure-form-message-inline,.pure-form-message{display:block;font-size:80%;padding:.2em 0 .8em}}
14 | .pure-g{letter-spacing:-.31em;*letter-spacing:normal;*word-spacing:-.43em;text-rendering:optimizespeed}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1,.pure-u-1-2,.pure-u-1-3,.pure-u-2-3,.pure-u-1-4,.pure-u-3-4,.pure-u-1-5,.pure-u-2-5,.pure-u-3-5,.pure-u-4-5,.pure-u-1-6,.pure-u-5-6,.pure-u-1-8,.pure-u-3-8,.pure-u-5-8,.pure-u-7-8,.pure-u-1-12,.pure-u-5-12,.pure-u-7-12,.pure-u-11-12,.pure-u-1-24,.pure-u-5-24,.pure-u-7-24,.pure-u-11-24,.pure-u-13-24,.pure-u-17-24,.pure-u-19-24,.pure-u-23-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1{width:100%}.pure-u-1-2{width:50%}.pure-u-1-3{width:33.33333%}.pure-u-2-3{width:66.66666%}.pure-u-1-4{width:25%}.pure-u-3-4{width:75%}.pure-u-1-5{width:20%}.pure-u-2-5{width:40%}.pure-u-3-5{width:60%}.pure-u-4-5{width:80%}.pure-u-1-6{width:16.666%}.pure-u-5-6{width:83.33%}.pure-u-1-8{width:12.5%}.pure-u-3-8{width:37.5%}.pure-u-5-8{width:62.5%}.pure-u-7-8{width:87.5%}.pure-u-1-12{width:8.3333%}.pure-u-5-12{width:41.6666%}.pure-u-7-12{width:58.3333%}.pure-u-11-12{width:91.6666%}.pure-u-1-24{width:4.1666%}.pure-u-5-24{width:20.8333%}.pure-u-7-24{width:29.1666%}.pure-u-11-24{width:45.8333%}.pure-u-13-24{width:54.1666%}.pure-u-17-24{width:70.8333%}.pure-u-19-24{width:79.1666%}.pure-u-23-24{width:95.8333%}.pure-g-r{letter-spacing:-.31em;*letter-spacing:normal;*word-spacing:-.43em}.opera-only :-o-prefocus,.pure-g-r{word-spacing:-.43em}.pure-g-r img{max-width:100%}@media (min-width:980px){.pure-visible-phone{display:none}.pure-visible-tablet{display:none}.pure-hidden-desktop{display:none}}@media (max-width:480px){.pure-g-r>.pure-u,.pure-g-r>[class *="pure-u-"]{width:100%}}@media (max-width:767px){.pure-g-r>.pure-u,.pure-g-r>[class *="pure-u-"]{width:100%}.pure-hidden-phone{display:none}.pure-visible-desktop{display:none}}@media (min-width:768px) and (max-width:979px){.pure-hidden-tablet{display:none}.pure-visible-desktop{display:none}}
15 | .pure-menu ul{position:absolute;visibility:hidden}.pure-menu.pure-menu-open{visibility:visible;z-index:2;width:100%}.pure-menu ul{left:-10000px;list-style:none;margin:0;padding:0;top:-10000px;z-index:1}.pure-menu>ul{position:relative}.pure-menu-open>ul{left:0;top:0;visibility:visible}.pure-menu-open>ul:focus{outline:0}.pure-menu li{position:relative}.pure-menu a,.pure-menu .pure-menu-heading{display:block;color:inherit;line-height:1.5em;padding:5px 20px;text-decoration:none;white-space:nowrap}.pure-menu.pure-menu-horizontal>.pure-menu-heading{display:inline-block;*display:inline;zoom:1;margin:0;vertical-align:middle}.pure-menu.pure-menu-horizontal>ul{display:inline-block;*display:inline;zoom:1;vertical-align:middle;height:2.4em}.pure-menu li a{padding:5px 20px}.pure-menu-can-have-children>.pure-menu-label:after{content:'\25B8';float:right;font-family:'Lucida Grande','Lucida Sans Unicode','DejaVu Sans',sans-serif;margin-right:-20px;margin-top:-1px}.pure-menu-can-have-children>.pure-menu-label{padding-right:30px}.pure-menu-separator{background-color:#dfdfdf;display:block;height:1px;font-size:0;margin:7px 2px;overflow:hidden}.pure-menu-hidden{display:none}.pure-menu-fixed{position:fixed;top:0;left:0;width:100%}.pure-menu-horizontal li{display:inline-block;*display:inline;zoom:1;vertical-align:middle}.pure-menu-horizontal li li{display:block}.pure-menu-horizontal>.pure-menu-children>.pure-menu-can-have-children>.pure-menu-label:after{content:"\25BE"}.pure-menu-horizontal>.pure-menu-children>.pure-menu-can-have-children>.pure-menu-label{padding-right:30px}.pure-menu-horizontal li.pure-menu-separator{height:50%;width:1px;margin:0 7px}.pure-menu-horizontal li li.pure-menu-separator{height:1px;width:auto;margin:7px 2px}.pure-menu.pure-menu-open,.pure-menu.pure-menu-horizontal li .pure-menu-children{background:#fff;border:1px solid #b7b7b7}.pure-menu.pure-menu-horizontal,.pure-menu.pure-menu-horizontal .pure-menu-heading{border:0}.pure-menu a{border:1px solid transparent;border-left:0;border-right:0}.pure-menu a,.pure-menu .pure-menu-can-have-children>li:after{color:#777}.pure-menu .pure-menu-can-have-children>li:hover:after{color:#fff}.pure-menu .pure-menu-open{background:#dedede}.pure-menu li a:hover,.pure-menu li a:focus{background:#eee}.pure-menu li.pure-menu-disabled a:hover,.pure-menu li.pure-menu-disabled a:focus{background:#fff;color:#bfbfbf}.pure-menu .pure-menu-disabled>a{background-image:none;border-color:transparent;cursor:default}.pure-menu .pure-menu-disabled>a,.pure-menu .pure-menu-can-have-children.pure-menu-disabled>a:after{color:#bfbfbf}.pure-menu .pure-menu-heading{color:#565d64;text-transform:uppercase;font-size:90%;margin-top:.5em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#dfdfdf}.pure-menu .pure-menu-selected a{color:#000}.pure-menu.pure-menu-open.pure-menu-fixed{border:0;border-bottom:1px solid #b7b7b7}.pure-paginator{letter-spacing:-.31em;*letter-spacing:normal;*word-spacing:-.43em;text-rendering:optimizespeed;list-style:none;margin:0;padding:0}.opera-only :-o-prefocus,.pure-paginator{word-spacing:-.43em}.pure-paginator li{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-paginator .pure-button{border-radius:0;padding:.8em 1.4em;vertical-align:top;height:1.1em}.pure-paginator .pure-button:focus,.pure-paginator .pure-button:active{outline-style:none}.pure-paginator .prev,.pure-paginator .next{color:#C0C1C3;text-shadow:0 -1px 0 rgba(0,0,0,.45)}.pure-paginator .prev{border-radius:2px 0 0 2px}.pure-paginator .next{border-radius:0 2px 2px 0}@media (max-width:480px){.pure-menu-horizontal{width:100%}.pure-menu-children li{display:block;border-bottom:1px solid #000}}
16 | .pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:6px 12px}.pure-table td:first-child,.pure-table th:first-child{border-left-width:0}.pure-table thead{background:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child td,.pure-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child td{border-bottom-width:0}
17 |
--------------------------------------------------------------------------------
/public/bugger.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #ffffff;
3 | }
4 |
5 | /* from YUICSS buttons-core.css */
6 | .pure-button {
7 | /* Structure */
8 | display: inline-block;
9 | *display: inline; /*IE 6/7*/
10 | zoom: 1;
11 | line-height: normal;
12 | white-space: nowrap;
13 | vertical-align: baseline;
14 | text-align: center;
15 | cursor: pointer;
16 | -webkit-user-drag: none;
17 | -webkit-user-select: none;
18 | -moz-user-select: none;
19 | -ms-user-select: none;
20 | user-select: none;
21 | }
22 |
23 | /* Firefox: Get rid of the inner focus border */
24 | .pure-button::-moz-focus-inner{
25 | padding: 0;
26 | border: 0;
27 | }
28 | /* end from YUICSS buttons-core.css */
29 | /* from YUICSS buttons.css */
30 | /*csslint unqualified-attributes:false*/
31 |
32 | .pure-button {
33 | font-size: 100%;
34 | *font-size: 90%; /*IE 6/7 - To reduce IE's oversized button text*/
35 | *overflow: visible; /*IE 6/7 - Because of IE's overly large left/right padding on buttons */
36 | padding: 0.5em 1.5em 0.5em;
37 | color: #0f0f0f; /* rgba not supported (IE 8) */
38 | /* color: rgba(0, 0, 0, 0.80); rgba supported */
39 | /* *color: #444; IE 6 & 7 */
40 | border: 1px solid #b6b4b4; /*IE 6/7/8*/
41 | border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
42 | background-color: #c0bfbf;
43 | border-radius: 2px;
44 | text-decoration: none;
45 | -webkit-font-smoothing: antialiased;
46 | /* Transitions */
47 | -webkit-transition: 0.1s linear -webkit-box-shadow;
48 | -moz-transition: 0.1s linear -moz-box-shadow;
49 | -ms-transition: 0.1s linear box-shadow;
50 | -o-transition: 0.1s linear box-shadow;
51 | transition: 0.1s linear box-shadow;
52 | }
53 |
54 | .pure-button-hover,
55 | .pure-button:hover {
56 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#00000000', GradientType=0);
57 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(transparent), color-stop(40%, rgba(0,0,0, 0.05)), to(rgba(0,0,0, 0.05)));
58 | background-image: -webkit-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.15));
59 | background-image: -moz-linear-gradient(top, rgba(0,0,0, 0.05) 0%, rgba(0,0,0, 0.05));
60 | background-image: -ms-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.15));
61 | background-image: -o-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.05));
62 | background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.05));
63 | }
64 |
65 | .pure-button-active,
66 | .pure-button:active {
67 | box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;
68 | }
69 |
70 | .pure-button[disabled],
71 | .pure-button-disabled,
72 | .pure-button-disabled:hover,
73 | .pure-button-disabled:active {
74 | border: none;
75 | background-image: none;
76 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
77 | filter: alpha(opacity=40);
78 | -khtml-opacity: 0.40;
79 | -moz-opacity: 0.40;
80 | opacity: 0.40;
81 | cursor: not-allowed;
82 | box-shadow: none;
83 | }
84 |
85 | .pure-button-hidden {
86 | display: none;
87 | }
88 |
89 | /* Firefox: Get rid of the inner focus border */
90 | .pure-button::-moz-focus-inner{
91 | padding: 0;
92 | border: 0;
93 | }
94 |
95 | .pure-button-primary,
96 | .pure-button-selected,
97 | a.pure-button-primary,
98 | a.pure-button-selected {
99 | background-color: #B9410E;
100 | color: #fffcfa;
101 | }
102 |
103 | .pure-button:-moz-focusring {
104 | outline-color: rgba(0, 0, 0, 0.85);
105 | }
106 |
107 |
108 | /*! Copyright 2013 Yahoo! Inc. http://yuilibrary.com/license/ */
109 | /* This page lists core form styles adopted from Normalize.css. */
110 | /*! Copyright (c) Nicolas Gallagher and Jonathan Neal */
111 |
112 | /*! normalize.css v1.1.0 | MIT License | git.io/normalize */
113 |
114 | /* This page has Normalize.css form-specific style rules applied to a .yui3-form context */
115 |
116 | /* ==========
117 | Forms Core
118 | =========*/
119 |
120 |
121 | /*
122 | * Corrects margin displayed oddly in IE 6/7.
123 | */
124 |
125 | .pure-skin-bugger .pure-form {
126 | margin: 0;
127 | }
128 |
129 | /* Define consistent border, margin, and padding.*/
130 |
131 |
132 | .pure-skin-bugger .pure-form fieldset {
133 | border: 1px solid #c0c0c0;
134 | margin: 0 2px;
135 | padding: 0.35em 0.625em 0.75em;
136 | }
137 |
138 | /*
139 | * 1. Corrects color not being inherited in IE 6/7/8/9.
140 | * 2. Corrects text not wrapping in Firefox 3.
141 | * 3. Corrects alignment displayed oddly in IE 6/7.
142 | */
143 |
144 | .pure-skin-bugger .pure-form legend {
145 | border: 0; /* 1 */
146 | padding: 0;
147 | white-space: normal; /* 2 */
148 | *margin-left: -7px; /* 3 */
149 | }
150 |
151 | /*
152 | * 1. Corrects font size not being inherited in all browsers.
153 | * 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5,
154 | * and Chrome.
155 | * 3. Improves appearance and consistency in all browsers.
156 | */
157 |
158 | .pure-skin-bugger .pure-form button,
159 | .pure-skin-bugger .pure-form input,
160 | .pure-skin-bugger .pure-form select,
161 | .pure-skin-bugger .pure-form textarea {
162 | font-size: 100%; /* 1 */
163 | margin: 0; /* 2 */
164 | vertical-align: baseline; /* 3 */
165 | *vertical-align: middle; /* 3 */
166 | }
167 |
168 | /*
169 | * Addresses Firefox 3+ setting `line-height` on `input` using `!important` in
170 | * the UA stylesheet.
171 | */
172 |
173 | .pure-skin-bugger .pure-form button,
174 | .pure-skin-bugger .pure-form input {
175 | line-height: normal;
176 | }
177 |
178 | /*
179 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
180 | * and `video` controls.
181 | * 2. Corrects inability to style clickable `input` types in iOS.
182 | * 3. Improves usability and consistency of cursor style between image-type
183 | * `input` and others.
184 | * 4. Removes inner spacing in IE 7 without affecting normal text inputs.
185 | * Known issue: inner spacing remains in IE 6.
186 | */
187 |
188 | .pure-skin-bugger .pure-form button,
189 | .pure-skin-bugger .pure-form input[type="button"], /* 1 */
190 | .pure-skin-bugger .pure-form input[type="reset"],
191 | .pure-skin-bugger .pure-form input[type="submit"] {
192 | -webkit-appearance: button; /* 2 */
193 | cursor: pointer; /* 3 */
194 | *overflow: visible; /* 4 */
195 | }
196 |
197 | /*
198 | * Re-set default cursor for disabled elements.
199 | */
200 |
201 | .pure-skin-bugger .pure-form button[disabled],
202 | .pure-skin-bugger .pure-form input[disabled] {
203 | cursor: default;
204 | }
205 |
206 | /*
207 | * 1. Addresses box sizing set to content-box in IE 8/9.
208 | * 2. Removes excess padding in IE 8/9.
209 | * 3. Removes excess padding in IE 7.
210 | * Known issue: excess padding remains in IE 6.
211 | */
212 |
213 | .pure-skin-bugger .pure-form input[type="checkbox"],
214 | .pure-skin-bugger .pure-form input[type="radio"] {
215 | box-sizing: border-box; /* 1 */
216 | padding: 0; /* 2 */
217 | *height: 13px; /* 3 */
218 | *width: 13px; /* 3 */
219 | }
220 |
221 | /*
222 | * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
223 | * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
224 | * (include `-moz` to future-proof).
225 | */
226 |
227 | .pure-skin-bugger .pure-form input[type="search"] {
228 | -webkit-appearance: textfield; /* 1 */
229 | -moz-box-sizing: content-box;
230 | -webkit-box-sizing: content-box; /* 2 */
231 | box-sizing: content-box;
232 | }
233 |
234 | /*
235 | * Removes inner padding and search cancel button in Safari 5 and Chrome
236 | * on OS X.
237 | */
238 |
239 | .pure-skin-bugger .pure-form input[type="search"]::-webkit-search-cancel-button,
240 | .pure-skin-bugger .pure-form input[type="search"]::-webkit-search-decoration {
241 | -webkit-appearance: none;
242 | }
243 |
244 | /*
245 | * Removes inner padding and border in Firefox 3+.
246 | */
247 |
248 | .pure-skin-bugger .pure-form button::-moz-focus-inner,
249 | .pure-skin-bugger .pure-form input::-moz-focus-inner {
250 | border: 0;
251 | padding: 0;
252 | }
253 |
254 | /*
255 | * 1. Removes default vertical scrollbar in IE 6/7/8/9.
256 | * 2. Improves readability and alignment in all browsers.
257 | */
258 |
259 | .pure-skin-bugger .pure-form textarea {
260 | overflow: auto; /* 1 */
261 | vertical-align: top; /* 2 */
262 | }
263 | /* =============== forms-responsive.css ================
264 |
265 | =========================================================*/
266 | @media only screen and (max-width : 480px) {
267 | .pure-skin-bugger .pure-form button[type="submit"] {
268 | margin: 0.7em 0 0;
269 | }
270 |
271 | .pure-skin-bugger .pure-form input[type="text"],
272 | .pure-skin-bugger .pure-form input[type="password"],
273 | .pure-skin-bugger .pure-form input[type="email"],
274 | .pure-skin-bugger .pure-form input[type="url"],
275 | .pure-skin-bugger .pure-form input[type="date"],
276 | .pure-skin-bugger .pure-form input[type="month"],
277 | .pure-skin-bugger .pure-form input[type="time"],
278 | .pure-skin-bugger .pure-form input[type="datetime"],
279 | .pure-skin-bugger .pure-form input[type="datetime-local"],
280 | .pure-skin-bugger .pure-form input[type="week"],
281 | .pure-skin-bugger .pure-form input[type="number"],
282 | .pure-skin-bugger .pure-form input[type="search"],
283 | .pure-skin-bugger .pure-form input[type="tel"],
284 | .pure-skin-bugger .pure-form input[type="color"],
285 | .pure-skin-bugger .pure-form label {
286 | margin-bottom: 0.3em;
287 | display: block;
288 | }
289 |
290 | .pure-skin-bugger .pure-group input[type="text"],
291 | .pure-skin-bugger .pure-group input[type="password"],
292 | .pure-skin-bugger .pure-group input[type="email"],
293 | .pure-skin-bugger .pure-group input[type="url"],
294 | .pure-skin-bugger .pure-group input[type="date"],
295 | .pure-skin-bugger .pure-group input[type="month"],
296 | .pure-skin-bugger .pure-group input[type="time"],
297 | .pure-skin-bugger .pure-group input[type="datetime"],
298 | .pure-skin-bugger .pure-group input[type="datetime-local"],
299 | .pure-skin-bugger .pure-group input[type="week"],
300 | .pure-skin-bugger .pure-group input[type="number"],
301 | .pure-skin-bugger .pure-group input[type="search"],
302 | .pure-skin-bugger .pure-group input[type="tel"],
303 | .pure-skin-bugger .pure-group input[type="color"] {
304 | margin-bottom: 0;
305 | }
306 |
307 | .pure-skin-bugger .pure-form-aligned .pure-control-group label {
308 | margin-bottom: 0.3em;
309 | text-align: left;
310 | display: block;
311 | width: 100%;
312 | }
313 |
314 | .pure-skin-bugger .pure-form-aligned .pure-controls {
315 | margin: 1.5em 0 0 0;
316 | }
317 |
318 | /* NOTE: pure-help-inline is deprecated. Use .pure-form-message-inline instead. */
319 | .pure-skin-bugger .pure-form .pure-help-inline,
320 | .pure-skin-bugger .pure-form-message-inline,
321 | .pure-skin-bugger .pure-form-message {
322 | display: block;
323 | font-size: 80%;
324 | /* increased bottom padding to make it group with its related input element */
325 | padding: 0.2em 0 0.8em;
326 | }
327 | }
328 |
329 | /* =============== forms.css ================
330 |
331 | =========================================================*/
332 | .pure-skin-bugger .pure-form input[type="text"],
333 | .pure-skin-bugger .pure-form input[type="password"],
334 | .pure-skin-bugger .pure-form input[type="email"],
335 | .pure-skin-bugger .pure-form input[type="url"],
336 | .pure-skin-bugger .pure-form input[type="date"],
337 | .pure-skin-bugger .pure-form input[type="month"],
338 | .pure-skin-bugger .pure-form input[type="time"],
339 | .pure-skin-bugger .pure-form input[type="datetime"],
340 | .pure-skin-bugger .pure-form input[type="datetime-local"],
341 | .pure-skin-bugger .pure-form input[type="week"],
342 | .pure-skin-bugger .pure-form input[type="number"],
343 | .pure-skin-bugger .pure-form input[type="search"],
344 | .pure-skin-bugger .pure-form input[type="tel"],
345 | .pure-skin-bugger .pure-form input[type="color"],
346 | .pure-skin-bugger .pure-form select,
347 | .pure-skin-bugger .pure-form textarea {
348 | padding: 0.5em 0.6em;
349 | display: inline-block;
350 | border: 1px solid #e6e6e6;
351 | font-size: 0.8em;
352 | box-shadow: inset 0 1px 3px #e6e6e6;
353 | border-radius: 4px;
354 | -webkit-transition: 0.3s linear border;
355 | -moz-transition: 0.3s linear border;
356 | -ms-transition: 0.3s linear border;
357 | -o-transition: 0.3s linear border;
358 | transition: 0.3s linear border;
359 | -webkit-box-sizing: border-box;
360 | -moz-box-sizing: border-box;
361 | box-sizing: border-box;
362 | -webkit-font-smoothing: antialiased;
363 | }
364 |
365 | .pure-skin-bugger .pure-form input[type="text"]:focus,
366 | .pure-skin-bugger .pure-form input[type="password"]:focus,
367 | .pure-skin-bugger .pure-form input[type="email"]:focus,
368 | .pure-skin-bugger .pure-form input[type="url"]:focus,
369 | .pure-skin-bugger .pure-form input[type="date"]:focus,
370 | .pure-skin-bugger .pure-form input[type="month"]:focus,
371 | .pure-skin-bugger .pure-form input[type="time"]:focus,
372 | .pure-skin-bugger .pure-form input[type="datetime"]:focus,
373 | .pure-skin-bugger .pure-form input[type="datetime-local"]:focus,
374 | .pure-skin-bugger .pure-form input[type="week"]:focus,
375 | .pure-skin-bugger .pure-form input[type="number"]:focus,
376 | .pure-skin-bugger .pure-form input[type="search"]:focus,
377 | .pure-skin-bugger .pure-form input[type="tel"]:focus,
378 | .pure-skin-bugger .pure-form input[type="color"]:focus,
379 | .pure-skin-bugger .pure-form select:focus,
380 | .pure-skin-bugger .pure-form textarea:focus {
381 | outline: 0;
382 | outline: thin dotted \9; /* IE6-9 */
383 | border-color: #129FEA;
384 | }
385 |
386 | .pure-skin-bugger .pure-form input[type="file"]:focus,
387 | .pure-skin-bugger .pure-form input[type="radio"]:focus,
388 | .pure-skin-bugger .pure-form input[type="checkbox"]:focus {
389 | outline: thin dotted #333;
390 | outline: 1px auto #129FEA;
391 | }
392 | .pure-skin-bugger .pure-form .pure-checkbox,
393 | .pure-skin-bugger .pure-form .pure-radio {
394 | margin: 0.5em 0;
395 | display: block;
396 | }
397 | .pure-skin-bugger .pure-form input[type="text"][disabled],
398 | .pure-skin-bugger .pure-form input[type="password"][disabled],
399 | .pure-skin-bugger .pure-form input[type="email"][disabled],
400 | .pure-skin-bugger .pure-form input[type="url"][disabled],
401 | .pure-skin-bugger .pure-form input[type="date"][disabled],
402 | .pure-skin-bugger .pure-form input[type="month"][disabled],
403 | .pure-skin-bugger .pure-form input[type="time"][disabled],
404 | .pure-skin-bugger .pure-form input[type="datetime"][disabled],
405 | .pure-skin-bugger .pure-form input[type="datetime-local"][disabled],
406 | .pure-skin-bugger .pure-form input[type="week"][disabled],
407 | .pure-skin-bugger .pure-form input[type="number"][disabled],
408 | .pure-skin-bugger .pure-form input[type="search"][disabled],
409 | .pure-skin-bugger .pure-form input[type="tel"][disabled],
410 | .pure-skin-bugger .pure-form input[type="color"][disabled],
411 | .pure-skin-bugger .pure-form select[disabled],
412 | .pure-skin-bugger .pure-form textarea[disabled],
413 | .pure-skin-bugger .pure-form input[readonly],
414 | .pure-skin-bugger .pure-form select[readonly],
415 | .pure-skin-bugger .pure-form textarea[readonly] {
416 | cursor: not-allowed;
417 | box-shadow: inset 0 1px 10px #ededed;
418 | background-color: #fff;
419 | color: #adadad;
420 | border-color: #e6e6e6;
421 | }
422 | .pure-skin-bugger .pure-form input:focus:invalid,
423 | .pure-skin-bugger .pure-form textarea:focus:invalid,
424 | .pure-skin-bugger .pure-form select:focus:invalid {
425 | color: #b94a48;
426 | border: 1px solid #ee5f5b;
427 | }
428 | .pure-skin-bugger .pure-form input:focus:invalid:focus,
429 | .pure-skin-bugger .pure-form textarea:focus:invalid:focus,
430 | .pure-skin-bugger .pure-form select:focus:invalid:focus {
431 | border-color: #e9322d;
432 | }
433 | .pure-skin-bugger .pure-form input[type="file"]:focus:invalid:focus,
434 | .pure-skin-bugger .pure-form input[type="radio"]:focus:invalid:focus,
435 | .pure-skin-bugger .pure-form input[type="checkbox"]:focus:invalid:focus {
436 | outline-color: #e9322d;
437 | }
438 | .pure-skin-bugger .pure-form select {
439 | border: 1px solid #e6e6e6;
440 | background-color: white;
441 | }
442 | .pure-skin-bugger .pure-form select[multiple] {
443 | height: auto;
444 | }
445 | .pure-skin-bugger .pure-form label {
446 | margin: 0.5em 0 0.2em;
447 | color: #4f4f4f;
448 | font-size:90%;
449 | }
450 | .pure-skin-bugger .pure-form fieldset {
451 | margin: 0;
452 | padding: 0.35em 0 0.75em;
453 | border: 0;
454 | }
455 | .pure-skin-bugger .pure-form legend {
456 | display: block;
457 | width: 100%;
458 | padding: 0.3em 0;
459 | margin-bottom: 0.3em;
460 | font-size: 125%;
461 | color: #262626;
462 | border-bottom: 1px solid #ededed;
463 | }
464 |
465 | .pure-skin-bugger .pure-form-stacked label {
466 | display: block;
467 | }
468 |
469 | .pure-skin-bugger .pure-form-aligned input,
470 | .pure-skin-bugger .pure-form-aligned textarea,
471 | .pure-skin-bugger .pure-form-aligned select,
472 | .pure-skin-bugger .pure-form-aligned .pure-help-inline, /* note: pure-help-inline is deprecated. Use .pure-form-message-inline instead */
473 | .pure-form-message-inline {
474 | display: inline-block;
475 | *display: inline; /* IE7 inline-block hack */
476 | *zoom: 1;
477 | vertical-align: middle;
478 | }
479 |
480 | /* aligned Forms */
481 | .pure-skin-bugger .pure-form-aligned .pure-control-group {
482 | margin-bottom: 0.5em;
483 | }
484 | .pure-skin-bugger .pure-form-aligned .pure-control-group label {
485 | text-align: right;
486 | display: inline-block;
487 | vertical-align: middle;
488 | width: 10em;
489 | margin: 0 1em 0 0;
490 | }
491 | .pure-skin-bugger .pure-form-aligned .pure-controls {
492 | margin: 1.5em 0 0 10em;
493 | }
494 |
495 | /* Rounded Inputs */
496 | .pure-skin-bugger .pure-form .pure-input-rounded {
497 | border-radius: 30px;
498 | padding-left: 1em;
499 | }
500 |
501 | /* Grouped Inputs */
502 | .pure-skin-bugger .pure-form .pure-group fieldset {
503 | margin-bottom: 10px;
504 | }
505 | .pure-skin-bugger .pure-form .pure-group input {
506 | display: block;
507 | padding: 0.5em 0.6em;
508 | margin: 0;
509 | border-radius: 0;
510 | position: relative;
511 | top: -1px;
512 | }
513 | .pure-skin-bugger .pure-form .pure-group input:focus {
514 | z-index: 2;
515 | }
516 | .pure-skin-bugger .pure-form .pure-group input:first-child {
517 | top: 1px;
518 | border-radius: 4px 4px 0px 0px;
519 | }
520 | .pure-skin-bugger .pure-form .pure-group input:last-child {
521 | top: -2px;
522 | border-radius: 0px 0px 4px 4px;
523 | }
524 | .pure-skin-bugger .pure-form .pure-group button {
525 | margin: 0.35em 0;
526 | }
527 |
528 | .pure-skin-bugger .pure-form .pure-input-1 {
529 | width: 100%;
530 | }
531 | .pure-skin-bugger .pure-form .pure-input-2-3 {
532 | width: 66%;
533 | }
534 | .pure-skin-bugger .pure-form .pure-input-1-2 {
535 | width: 50%;
536 | }
537 | .pure-skin-bugger .pure-form .pure-input-1-3 {
538 | width: 33%;
539 | }
540 | .pure-skin-bugger .pure-form .pure-input-1-4 {
541 | width: 25%;
542 | }
543 |
544 | /* Inline help for forms */
545 | /* Note: pure-help-inline is deprecated. Use .pure-form-message-inline instead */
546 | .pure-skin-bugger .pure-form .pure-help-inline,
547 | .pure-skin-bugger .pure-form-message-inline {
548 | display: inline-block;
549 | padding-left: 0.3em;
550 | color: #adadad;
551 | font-size: 90%;
552 | vertical-align: middle;
553 | }
554 |
555 | /* Block help for forms */
556 | .pure-skin-bugger .pure-form-message {
557 | display: block;
558 | margin: .5em 0 .2em;
559 | color: #adadad;
560 | font-size: 90%;
561 | }
562 |
563 | /* foundational CSS */
564 | .pure-skin-bugger .pure-table {
565 | /* Remove spacing between table cells (from Normalize.css) */
566 | border-collapse: separate;
567 | border-spacing: 0;
568 | empty-cells: show;
569 | border: 1px solid #dedede;
570 | }
571 |
572 | .pure-skin-bugger .pure-table caption {
573 | color: #adadad;
574 | font: italic 85%/1 arial, sans-serif;
575 | padding: 1em 0;
576 | text-align: center;
577 | }
578 |
579 | .pure-skin-bugger .pure-table td,
580 | .pure-skin-bugger .pure-table th {
581 | border-left: 1px solid #dedede;/* inner column border */
582 | border-width: 0 0 0 1px;
583 | font-size: inherit;
584 | margin: 0;
585 | overflow: visible; /*to make ths where the title is really long work*/
586 | padding: 0.3em 0.6em; /* cell padding */
587 | }
588 |
589 | .pure-skin-bugger .pure-table td:first-child,
590 | .pure-skin-bugger .pure-table th:first-child {
591 | border-left-width: 0;
592 | }
593 |
594 | .pure-skin-bugger .pure-table thead {
595 | background-color: #d7d6d6;
596 | color: #272626;
597 | text-align: left;
598 | vertical-align: bottom;
599 | white-space: nowrap;
600 | }
601 |
602 | /*
603 | striping:
604 | even - #fff (white)
605 | odd - #edf5ff (light blue)
606 | */
607 | .pure-skin-bugger .pure-table td {
608 | background-color: #ededed;
609 | color: #404040;
610 | }
611 | .pure-skin-bugger .pure-table-odd td {
612 | background-color: #dedede;
613 | color: #262626;
614 | }
615 |
616 | /* BORDERED TABLES */
617 | .pure-skin-bugger .pure-table-bordered td {
618 | border-bottom:1px solid #dedede;
619 | }
620 | .pure-skin-bugger .pure-table-bordered tbody > tr:last-child td,
621 | .pure-skin-bugger .pure-table-horizontal tbody > tr:last-child td {
622 | border-bottom-width: 0;
623 | }
624 |
625 | /* HORIZONTAL BORDERED TABLES */
626 | .pure-skin-bugger .pure-table-horizontal td,
627 | .pure-skin-bugger .pure-table-horizontal th {
628 | border-width: 0 0 1px 0;
629 | border-bottom:1px solid #dedede;
630 | }
631 | .pure-skin-bugger .pure-table-horizontal tbody > tr:last-child td {
632 | border-bottom-width: 0;
633 | }
634 |
635 | /* from YUICSS list-core.css */
636 | /*csslint adjoining-classes:false, outline-none:false*/
637 | /*TODO: Remove this lint rule override after a refactor of this code.*/
638 |
639 | .pure-skin-bugger .pure-menu ul {
640 | position: absolute;
641 | visibility: hidden;
642 | }
643 |
644 | .pure-skin-bugger .pure-menu.pure-menu-open {
645 | visibility: visible;
646 | z-index: 2;
647 | width: 100%;
648 | }
649 |
650 | .pure-skin-bugger .pure-menu ul {
651 | left: -10000px;
652 | list-style: none;
653 | margin: 0;
654 | padding: 0;
655 | top: -10000px;
656 | z-index: 1;
657 | }
658 |
659 | .pure-skin-bugger .pure-menu > ul { position: relative; }
660 |
661 | .pure-skin-bugger .pure-menu-open > ul {
662 | left: 0;
663 | top: 0;
664 | visibility: visible;
665 | }
666 |
667 | .pure-skin-bugger .pure-menu-open > ul:focus {
668 | outline: none;
669 | }
670 |
671 | .pure-skin-bugger .pure-menu li {
672 | position: relative;
673 | }
674 |
675 | .pure-skin-bugger .pure-menu a, .pure-skin-bugger .pure-menu .pure-menu-heading {
676 | display: block;
677 | color: inherit;
678 | line-height: 1.5em;
679 | padding: 0.35em 1.4em;
680 | text-decoration: none;
681 | white-space: nowrap;
682 | }
683 |
684 | .pure-skin-bugger .pure-menu.pure-menu-horizontal > .pure-menu-heading {
685 | display: inline-block;
686 | *display: inline;
687 | zoom: 1;
688 | margin: 0;
689 | vertical-align: middle;
690 | }
691 | .pure-skin-bugger .pure-menu.pure-menu-horizontal > ul {
692 | display: inline-block;
693 | *display: inline;
694 | zoom: 1;
695 | vertical-align: middle;
696 | height: 2.4em;
697 | }
698 |
699 | .pure-skin-bugger .pure-menu li a { padding: 0.35em 1.4em; }
700 |
701 | .pure-skin-bugger .pure-menu-can-have-children > .pure-menu-label:after {
702 | content: '\25B8';
703 | float: right;
704 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'DejaVu Sans', sans-serif; /* These specific fonts have the Unicode char we need. */
705 | margin-right: -20px;
706 | margin-top: -1px;
707 | }
708 |
709 | .pure-skin-bugger .pure-menu-can-have-children > .pure-menu-label {
710 | padding-right: 30px;
711 | }
712 |
713 | .pure-skin-bugger .pure-menu-separator {
714 | background-color: #dedede;
715 | display: block;
716 | height: 1px;
717 | font-size: 0;
718 | margin: 7px 2px;
719 | overflow: hidden;
720 | }
721 |
722 | .pure-skin-bugger .pure-menu-hidden {
723 | display: none;
724 | }
725 |
726 | /* FIXED MENU */
727 | .pure-skin-bugger .pure-menu-fixed {
728 | position: fixed;
729 | top:0;
730 | left:0;
731 | width: 100%;
732 | }
733 |
734 |
735 | /* HORIZONTAL MENU CODE */
736 |
737 | /* Initial menus should be inline-block so that they are horizontal */
738 | .pure-skin-bugger .pure-menu-horizontal li {
739 | display: inline-block;
740 | *display: inline;
741 | zoom: 1;
742 | vertical-align: middle;
743 | }
744 |
745 | /* Submenus should still be display:block; */
746 | .pure-skin-bugger .pure-menu-horizontal li li {
747 | display: block;
748 | }
749 |
750 | /* Content after should be down arrow */
751 | .pure-skin-bugger .pure-menu-horizontal > .pure-menu-children > .pure-menu-can-have-children > .pure-menu-label:after {
752 | content: "\25BE";
753 | }
754 | /*Add extra padding to elements that have the arrow so that the hover looks nice */
755 | .pure-skin-bugger .pure-menu-horizontal > .pure-menu-children > .pure-menu-can-have-children > .pure-menu-label {
756 | padding-right:30px;
757 | }
758 |
759 | /* Adjusting separator for vertical menus */
760 | .pure-skin-bugger .pure-menu-horizontal li.pure-menu-separator {
761 | height: 50%;
762 | width: 1px;
763 | margin: 0 7px;
764 | }
765 |
766 | /* Submenus should be horizontal separator again */
767 | .pure-skin-bugger .pure-menu-horizontal li li.pure-menu-separator {
768 | height: 1px;
769 | width: auto;
770 | margin: 7px 2px;
771 | }
772 |
773 |
774 | /* end from yuicss/list-core.css *******************************************/
775 | /* from yuicss list-paginator.css */
776 | /*csslint box-model:false*/
777 | /*TODO: Remove this lint rule override after a refactor of this code.*/
778 |
779 | .pure-skin-bugger .pure-paginator {
780 | list-style: none;
781 | margin: 0;
782 | padding: 0;
783 | }
784 | .pure-skin-bugger .pure-paginator li {
785 | display: inline-block;
786 | *display: inline;
787 | zoom: 1;
788 | margin: 0 -0.35em 0 0;
789 | }
790 | .pure-skin-bugger .pure-paginator .pure-button {
791 | border-radius: 0;
792 | padding: 0.8em 1.4em;
793 | vertical-align: top;
794 | height: 1.1em;
795 | }
796 | .pure-skin-bugger .pure-paginator .pure-button:focus {
797 | outline-style: none;
798 | }
799 | .pure-skin-bugger .pure-paginator .prev, .pure-skin-bugger .pure-paginator .next {
800 | /*color: #C0C1C3; allow .pure-button to color text*/
801 | }
802 | .pure-skin-bugger .pure-paginator .prev {
803 | border-radius: 4px 0px 0px 4px;
804 | }
805 | .pure-skin-bugger .pure-paginator .next {
806 | border-radius: 0px 4px 4px 0px;
807 | }
808 | /* end from YUICSS list-paginator.css ******************************/
809 | /* from YUICSS list.css *******************************************/
810 | /* MAIN MENU STYLING */
811 | /*csslint adjoining-classes:false*/
812 | /*TODO: Remove this lint rule override after a refactor of this code.*/
813 |
814 | .pure-skin-bugger .pure-menu.pure-menu-open,
815 | .pure-skin-bugger .pure-menu.pure-menu-horizontal li .pure-menu-children {
816 | background: #ededed; /* Old browsers */
817 | border: 1px solid #dedede;
818 | }
819 |
820 | /* remove borders for horizontal menus */
821 | .pure-skin-bugger .pure-menu.pure-menu-horizontal,
822 | .pure-skin-bugger .pure-menu.pure-menu-horizontal .pure-menu-heading {
823 | border: none;
824 | }
825 |
826 |
827 |
828 | /* LINK STYLES */
829 |
830 | .pure-skin-bugger .pure-menu a {
831 | border: 1px solid transparent;
832 | border-left: none;
833 | border-right: none;
834 |
835 | }
836 |
837 | .pure-skin-bugger .pure-menu a,
838 | .pure-skin-bugger .pure-menu .pure-menu-can-have-children > li:after {
839 | color: #404040;
840 | }
841 |
842 | .pure-skin-bugger .pure-menu .pure-menu-can-have-children > li:hover:after {
843 | color: #262626;
844 | }
845 |
846 | /* Focus style for a dropdown menu-item when the parent has been opened */
847 | .pure-skin-bugger .pure-menu .pure-menu-open {
848 | background: #d6d6d6;
849 | }
850 |
851 | /* HOVER STATES */
852 | .pure-skin-bugger .pure-menu li a:hover {
853 | background: #d6d6d6;
854 | }
855 |
856 | /* DISABLED STATES */
857 | .pure-skin-bugger .pure-menu li.pure-menu-disabled a:hover {
858 | background: #ededed;
859 | color: #9e9e9e;
860 | }
861 |
862 | .pure-skin-bugger .pure-menu .pure-menu-disabled > a {
863 | background-image: none;
864 | border-color: transparent;
865 | cursor: default;
866 | }
867 |
868 | .pure-skin-bugger .pure-menu .pure-menu-disabled > a,
869 | .pure-skin-bugger .pure-menu .pure-menu-can-have-children.pure-menu-disabled > a:after {
870 | color: #9e9e9e;
871 | }
872 |
873 | /* HEADINGS */
874 | .pure-skin-bugger .pure-menu .pure-menu-heading {
875 | color: #171717;
876 | text-transform: uppercase;
877 | font-size: 90%;
878 | margin-top: 0.5em;
879 | border-bottom: solid 1px #dedede;
880 | }
881 |
882 |
883 | /* SELECTED MENU ITEM */
884 | .pure-skin-bugger .pure-menu li.pure-menu-selected a {
885 | background-color: #B9410E;
886 | color: #fffcfa;
887 | }
888 |
889 | /* FIXED MENU */
890 | .pure-skin-bugger .pure-menu.pure-menu-open.pure-menu-fixed {
891 | border: none;
892 | border-bottom: 1px solid #dedede;
893 | }
894 | /* end from YUICSS list.css ***********************************/
895 | /* from YUICSS list-responsive.css ****************************/
896 | /* RESPONSIVE */
897 |
898 | @media (max-width: 480px) {
899 |
900 | .pure-skin-bugger .pure-menu-horizontal {
901 | width:100%;
902 | }
903 |
904 | .pure-skin-bugger .pure-menu-children li {
905 | display: block;
906 | border-bottom:1px solid #dedede;
907 | }
908 |
909 | }
910 | /* end from list-responsive.css ******************/
911 |
--------------------------------------------------------------------------------