diff --git a/.gitignore b/.gitignore index 2e61390a9..9373d85ca 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,7 @@ node_modules/ *~ *.db tmp-crx/ -tmp-userjs/ tmp-userscript/ builds/4chan-X-Chrome.zip builds/4chan-X-Opera.nex -Gruntfile.js \ No newline at end of file +Gruntfile.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 558974413..3f25fd8b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ +**MayhemYDG**: +- Fix impossibility to create new threads when in dead threads. +- Drop Opera <15 support. +- Fix flag filtering on /sp/ and /int/. +- Minor fixes. + ### v1.2.17 *2013-06-17* - **seaweedchan**: - Fix full images being forced onto their own line diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..735b0841c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,49 @@ +## Reporting bugs and suggestions + +Reporting bugs: + +1. Make sure both your **browser** and **4chan X** are up to date. +2. Disable your other extensions & scripts to identify [conflicts](https://github.com/MayhemYDG/4chan-x/wiki/FAQ#known-conflicting-extensions). +3. If your issue persists, open a [new issue](https://github.com/MayhemYDG/4chan-x/issues) with the following information: + 1. Precise steps to reproduce the problem, with the expected and actual results. + 2. Console errors, if any. + 3. Browser version. + 4. Your exported settings. If your settings contains sensible information (e.g. personas), edit the text file manually. + +Open your console with: +- `Ctrl + Shift + J` on Chrome and Opera. +- `Ctrl + Shift + K` on Firefox. + +Respect these guidelines: +- Describe the issue clearly, put some effort into it. A one-liner isn't a good enough description. +- If you want to get your suggestion implemented sooner, make it convincing. +- If you want to criticize, make it convincing and constructive. +- Be mature. Act like an idiot and you will be blocked without warning. + +## Development & Contribution + +### Get started + +- Install [node.js](http://nodejs.org/). +- Install [Grunt's CLI](http://gruntjs.com/) with `npm install -g grunt-cli`. +- Clone 4chan X. +- `cd` into it. +- Install/Update 4chan X dependencies with `npm install`. + +### Build + +- Build with `grunt`. +- Continuously build with `grunt watch`. + +### Release + +- Update the version with `grunt patch`, `grunt minor` or `grunt major`. +- Release with `grunt release`. + +Note: this is only used to release new 4chan X versions, and is **not** needed or wanted in pull requests. + +### Contribute + +- Edit the CoffeeScript sources. +- If the edits affect regular users, edit the changelog. +- Open a pull request. diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 61387bb9d..8d07688c9 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -54,16 +54,6 @@ module.exports = (grunt) -> 'tmp-<%= pkg.type %>/script.js' ] - userjs: - options: concatOptions - src: [ - 'src/General/meta/botproc.js' - 'src/General/meta/metadata.js' - 'src/General/meta/banner.js' - 'tmp-<%= pkg.type %>/script.js' - ] - dest: 'builds/<%= pkg.name %>.js' - userscript: options: concatOptions files: @@ -94,7 +84,6 @@ module.exports = (grunt) -> build: [ 'concat:meta' 'build-crx' - 'build-userjs' 'build-userscript' ] @@ -137,7 +126,6 @@ module.exports = (grunt) -> clean: builds: 'builds' tmpcrx: 'tmp-crx' - tmpuserjs: 'tmp-userjs' tmpuserscript: 'tmp-userscript' grunt.loadNpmTasks 'grunt-bump' @@ -171,14 +159,6 @@ module.exports = (grunt) -> 'clean:tmpcrx' ] - grunt.registerTask 'build-userjs', [ - 'set-build:userjs' - 'concat:coffee' - 'coffee:script' - 'concat:userjs' - 'clean:tmpuserjs' - ] - grunt.registerTask 'build-userscript', [ 'set-build:userscript' 'concat:coffee' diff --git a/LICENSE b/LICENSE index 5e7ffd9a5..74617908e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.2.17 - 2013-06-18 +* 4chan X - Version 1.2.17 - 2013-07-21 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE diff --git a/README.md b/README.md index b8f376be3..0889c7217 100644 --- a/README.md +++ b/README.md @@ -41,4 +41,4 @@ Note: this is only used to release new 4chan X versions, and is **not** needed o - Edit the CoffeeScript sources. - If the edits affect regular users, edit the changelog. -- Open a pull request. \ No newline at end of file +- Open a pull request. diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index 12a7be632..d8ee74516 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -19,7 +19,7 @@ // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAgMAAAAqbBEUAAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAHFJREFUKFOt0LENACEIBdBv4Qju4wgWanEj3D6OcIVMKaitYHEU/jwTCQj8W75kiVCSBvdQ5/AvfVHBin11BgdRq3ysBgfwBDRrj3MCIA+oAQaku/Q1cNctrAmyDl577tOThYt/Y1RBM4DgOHzM0HFTAyLukH/cmRnqAAAAAElFTkSuQmCC // ==/UserScript== /* -* 4chan X - Version 1.2.17 - 2013-06-18 +* 4chan X - Version 1.2.17 - 2013-07-21 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -406,9 +406,9 @@ }; $.ready = function(fc) { - var cb, _ref; + var cb; - if ((_ref = d.readyState) === 'interactive' || _ref === 'complete') { + if (d.readyState !== 'loading') { $.queueTask(fc); return; } @@ -674,9 +674,9 @@ }; $.open = function(URL) { - return GM_openInTab(($.el('a', { - href: URL - })).href); + return $.open = function(URL) { + return GM_openInTab(URL); + }; }; $.debounce = function(wait, fn) { @@ -754,21 +754,6 @@ return (value < min ? min : value > max ? max : value); }; - $.syncing = {}; - - $.sync = (function() { - window.addEventListener('storage', function(e) { - var cb; - - if (cb = $.syncing[e.key]) { - return cb(JSON.parse(e.newValue)); - } - }, false); - return function(key, cb) { - return $.syncing[g.NAMESPACE + key] = cb; - }; - })(); - $.item = function(key, val) { var item; @@ -777,6 +762,21 @@ return item; }; + $.syncing = {}; + + $.sync = (function() { + $.on(window, 'storage', function(e) { + var cb; + + if (cb = $.syncing[e.key]) { + return cb(JSON.parse(e.newValue)); + } + }); + return function(key, cb) { + return $.syncing[g.NAMESPACE + key] = cb; + }; + })(); + $["delete"] = function(keys) { var key, _i, _len; @@ -866,8 +866,8 @@ }; function Thread(ID, board) { + this.ID = ID; this.board = board; - this.ID = +ID; this.fullID = "" + this.board + "." + this.ID; this.posts = {}; g.threads[this.fullID] = board.threads[this] = this; @@ -890,7 +890,7 @@ }; function Post(root, thread, board, that) { - var alt, anchor, capcode, date, email, file, fileInfo, flag, info, name, post, size, subject, thumb, tripcode, uniqueID, unit; + var capcode, date, email, flag, info, name, post, subject, tripcode, uniqueID; this.thread = thread; this.board = board; @@ -909,6 +909,11 @@ quotelinks: [], backlinks: info.getElementsByClassName('backlink') }; + if (!(this.isReply = $.hasClass(post, 'reply'))) { + this.thread.OP = this; + this.thread.isSticky = !!$('.stickyIcon', info); + this.thread.isClosed = !!$('.closedIcon', info); + } this.info = {}; if (subject = $('.subject', info)) { this.nodes.subject = subject; @@ -934,7 +939,7 @@ this.nodes.capcode = capcode; this.info.capcode = capcode.textContent.replace('## ', ''); } - if (flag = $('.countryFlag', info)) { + if (flag = $('.flag, .countryFlag', info)) { this.nodes.flag = flag; this.info.flag = flag.title; } @@ -951,36 +956,7 @@ } this.parseComment(); this.parseQuotes(); - if ((file = $('.file', post)) && (thumb = $('img[data-md5]', file))) { - alt = thumb.alt; - anchor = thumb.parentNode; - fileInfo = file.firstElementChild; - this.file = { - info: fileInfo, - text: fileInfo.firstElementChild, - thumb: thumb, - URL: anchor.href, - size: alt.match(/[\d.]+\s\w+/)[0], - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(anchor, 'imgspoiler') - }; - size = +this.file.size.match(/[\d.]+/)[0]; - unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); - while (unit-- > 0) { - size *= 1024; - } - this.file.sizeInBytes = size; - this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; - this.file.name = $('span[title]', fileInfo).title.replace(/%22/g, '"'); - if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { - this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; - } - } - if (!(this.isReply = $.hasClass(post, 'reply'))) { - this.thread.OP = this; - this.thread.isSticky = !!$('.stickyIcon', this.nodes.info); - this.thread.isClosed = !!$('.closedIcon', this.nodes.info); - } + this.parseFile(that); this.clones = []; g.posts[this.fullID] = thread.posts[this] = board.posts[this] = this; if (that.isArchived) { @@ -989,7 +965,7 @@ } Post.prototype.parseComment = function() { - var bq, data, i, node, nodes, text, _i, _len, _ref; + var bq, i, node, nodes, text, _i, _len, _ref; bq = this.nodes.comment.cloneNode(true); _ref = $$('.abbr, .capcodeReplies, .exif, b', bq); @@ -1001,7 +977,7 @@ nodes = d.evaluate('.//br|.//text()', bq, null, 7, null); i = 0; while (i < nodes.snapshotLength) { - text.push((data = nodes.snapshotItem(i++).data) ? data : '\n'); + text.push(nodes.snapshotItem(i++).data || '\n'); } return this.info.comment = text.join('').trim().replace(/\s+$/gm, ''); }; @@ -1025,7 +1001,7 @@ continue; } this.nodes.quotelinks.push(quotelink); - if (quotelink.parentNode.parentNode.className === 'capcodeReplies') { + if (!this.isReply && $.hasClass(quotelink.parentNode.parentNode, 'capcodeReplies')) { continue; } quotes["" + (pathname.split('/')[1]) + "." + hash.slice(2)] = true; @@ -1036,6 +1012,37 @@ return this.quotes = Object.keys(quotes); }; + Post.prototype.parseFile = function(that) { + var alt, anchor, fileEl, fileInfo, size, thumb, unit; + + if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) { + return; + } + alt = thumb.alt; + anchor = thumb.parentNode; + fileInfo = fileEl.firstElementChild; + this.file = { + info: fileInfo, + text: fileInfo.firstElementChild, + thumb: thumb, + URL: anchor.href, + size: alt.match(/[\d.]+\s\w+/)[0], + MD5: thumb.dataset.md5, + isSpoiler: $.hasClass(anchor, 'imgspoiler') + }; + size = +this.file.size.match(/[\d.]+/)[0]; + unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); + while (unit-- > 0) { + size *= 1024; + } + this.file.sizeInBytes = size; + this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + this.board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; + this.file.name = $('span[title]', fileInfo).title; + if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { + return this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; + } + }; + Post.prototype.kill = function(file, now) { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; @@ -1126,7 +1133,7 @@ _ref = this.clones.slice(index); for (_i = 0, _len = _ref.length; _i < _len; _i++) { clone = _ref[_i]; - clone.nodes.root.setAttribute('data-clone', index++); + clone.nodes.root.dataset.clone = index++; } }; @@ -1138,7 +1145,7 @@ __extends(Clone, _super); function Clone(origin, context) { - var file, index, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; + var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; this.origin = origin; this.context = context; @@ -1214,8 +1221,7 @@ this.isDead = true; } this.isClone = true; - index = origin.clones.push(this) - 1; - root.setAttribute('data-clone', index); + root.dataset.clone = origin.clones.push(this) - 1; } return Clone; @@ -1537,9 +1543,7 @@ return; } $.asap((function() { - var _ref; - - return $.id('boardNavMobile') || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); + return $.id('boardNavMobile') || d.readyState !== 'loading'; }), Header.setBoardList); $.prepend(d.body, _this.bar); $.add(d.body, Header.hover); @@ -1609,7 +1613,7 @@ if (!text) { return; } - as = $$('#full-board-list a', Header.bar); + as = $$('#full-board-list a[title]', Header.bar); nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map(function(t) { var a, board, m, _i, _len; @@ -1640,7 +1644,7 @@ a = a.cloneNode(true); a.textContent = /-title/.test(t) || /-replace/.test(t) && $.hasClass(a, 'current') ? a.title : /-full/.test(t) ? "/" + board + "/ - " + a.title : (m = t.match(/-text:"(.+)"/)) ? m[1] : a.textContent; if (m = t.match(/-(index|catalog)/)) { - a.setAttribute('data-only', m[1]); + a.dataset.only = m[1]; a.href = "//boards.4chan.org/" + board + "/"; if (m[1] === 'catalog') { a.href += 'catalog'; @@ -1907,7 +1911,7 @@ capcodeStart = ''; capcode = ''; } - flag = flagCode ? ("  + flagCode + ") : ''; + flag = !flagCode ? '' : boardID === 'pol' ? "  + flagCode + " : " "; if (file != null ? file.isDeleted : void 0) { fileHTML = isOP ? ("
") + ("File deleted.") + "
" : ("
") + ("File deleted.") + "
"; } else if (file) { @@ -1996,11 +2000,11 @@ postFromNode: function(root) { return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', root)); }, - contextFromLink: function(quotelink) { + contextFromNode: function(quotelink) { return Get.postFromRoot($.x('ancestor::div[parent::div[@class="thread"]][1]', quotelink)); }, postDataFromLink: function(link) { - var boardID, path, postID, threadID; + var boardID, path, postID, threadID, _ref; if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); @@ -2008,9 +2012,8 @@ threadID = path[3]; postID = link.hash.slice(2); } else { - boardID = link.dataset.boardid; - threadID = link.dataset.threadid || 0; - postID = link.dataset.postid; + _ref = link.dataset, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; + threadID || (threadID = 0); } return { boardID: boardID, @@ -2182,7 +2185,7 @@ } }); comment = bq.innerHTML.replace(/(^|>)(>[^<$]*)(<|$)/g, '$1$2$3').replace(/((>){2}(>\/[a-z\d]+\/)?\d+)/g, '$1'); - threadID = data.thread_num; + threadID = +data.thread_num; o = { postID: "" + postID, threadID: "" + threadID, @@ -2617,7 +2620,13 @@ if ($.x('ancestor::div[contains(@class,"inline")][1]', root)) { $.on(d, 'keydown', o.hoverend); } - return $.on(root, 'mousemove', o.hover); + $.on(root, 'mousemove', o.hover); + o.workaround = function(e) { + if (!root.contains(e.target)) { + return o.hoverend(); + } + }; + return $.on(doc, 'mousemove', o.workaround); }; hover = function(e) { var clientX, clientY, height, left, right, style, top, _ref; @@ -2641,6 +2650,7 @@ $.off(this.root, this.endEvents, this.hoverend); $.off(d, 'keydown', this.hoverend); $.off(this.root, 'mousemove', this.hover); + $.off(doc, 'mousemove', this.workaround); if (this.cb) { return this.cb.call(this); } @@ -2926,7 +2936,7 @@ href: 'javascript:;', textContent: text }); - el.setAttribute('data-type', type); + el.dataset.type = type; $.on(el, 'click', Filter.menu.makeFilter); return { el: el, @@ -3520,7 +3530,7 @@ innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", href: 'javascript:;' }); - a.setAttribute('data-fullid', thread.fullID); + a.dataset.fullID = thread.fullID; $.on(a, 'click', ThreadHiding.toggle); return a; }, @@ -3548,7 +3558,7 @@ }, toggle: function(thread) { if (!(thread instanceof Thread)) { - thread = g.threads[this.dataset.fullid]; + thread = g.threads[this.dataset.fullID]; } if (thread.isHidden) { ThreadHiding.show(thread); @@ -3775,7 +3785,7 @@ } e.preventDefault(); _ref = Get.postDataFromLink(this), boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; - context = Get.contextFromLink(this); + context = Get.contextFromNode(this); if ($.hasClass(this, 'inlined')) { QuoteInline.rm(this, boardID, threadID, postID, context); } else { @@ -3924,7 +3934,7 @@ className: 'dialog' }); $.add(Header.hover, qp); - Get.postClone(boardID, threadID, postID, qp, Get.contextFromLink(this)); + Get.postClone(boardID, threadID, postID, qp, Get.contextFromNode(this)); UI.hover({ root: this, el: qp, @@ -4248,9 +4258,11 @@ target: '_blank', textContent: "" + quote + "\u00A0(Dead)" }); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-threadid', post.thread.ID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + threadID: post.thread.ID, + postID: postID + }); } } else if (redirect = Redirect.to('thread', { boardID: boardID, @@ -4268,8 +4280,10 @@ postID: postID })) { $.addClass(a, 'quotelink'); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + postID: postID + }); } } if (!this.quotes.contains(quoteID)) { @@ -4743,7 +4757,7 @@ } }, close: function() { - var i, _i, _len, _ref; + var post, _i, _len, _ref; if (QR.req) { QR.abort(); @@ -4759,10 +4773,10 @@ if (Conf['QR Shortcut']) { $.toggleClass($('.qr-shortcut'), 'disabled'); } - _ref = QR.posts; + _ref = QR.posts.splice(0, QR.posts.length, new QR.post(true)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - i = _ref[_i]; - QR.posts[0].rm(); + post = _ref[_i]; + post["delete"](); } QR.cooldown.auto = false; return QR.status(); @@ -4828,12 +4842,13 @@ return QR.notifications = []; }, status: function() { - var disabled, status, value; + var disabled, status, thread, value; if (!QR.nodes) { return; } - if (g.DEAD) { + thread = QR.posts[0].thread; + if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) { value = 404; disabled = true; QR.cooldown.auto = false; @@ -5087,7 +5102,7 @@ } }, quote: function(e) { - var OP, caretPos, com, index, post, range, s, sel, selectionRoot, text, thread, _ref; + var caretPos, com, index, post, range, s, sel, text, thread, _ref; if (e != null) { e.preventDefault(); @@ -5096,11 +5111,9 @@ return; } sel = d.getSelection(); - selectionRoot = $.x('ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode); post = Get.postFromNode(this); - OP = Get.contextFromLink(this).thread.OP; text = ">>" + post + "\n"; - if ((s = sel.toString().trim()) && post.nodes.root === selectionRoot) { + if ((s = sel.toString().trim()) && post === Get.postFromNode(sel.anchorNode)) { s = s.replace(/\n/g, '\n>'); text += ">" + s + "\n"; } @@ -5113,7 +5126,7 @@ } _ref = QR.nodes, com = _ref.com, thread = _ref.thread; if (!com.value) { - thread.value = OP.ID; + thread.value = Get.contextFromNode(this).thread; } caretPos = com.selectionStart; com.value = com.value.slice(0, caretPos) + text + com.value.slice(com.selectionEnd); @@ -5186,7 +5199,7 @@ fileInput: function(files) { var file, length, max, post, _i, _len; - if (this instanceof Element) { + if (files instanceof Event) { files = __slice.call(this.files); QR.nodes.fileInput.value = null; } @@ -5295,7 +5308,7 @@ _Class.prototype.rm = function() { var index; - $.rm(this.nodes.el); + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { new QR.post(true); @@ -5304,9 +5317,11 @@ (QR.posts[index - 1] || QR.posts[index + 1]).select(); } QR.posts.splice(index, 1); - if (!window.URL) { - return; - } + return QR.status(); + }; + + _Class.prototype["delete"] = function() { + $.rm(this.nodes.el); return URL.revokeObjectURL(this.URL); }; @@ -5365,21 +5380,23 @@ }; _Class.prototype.save = function(input) { - var value, _ref; + var name, _ref; if (input.type === 'checkbox') { this.spoiler = input.checked; return; } - value = input.value; - this[input.dataset.name] = value; - if (input.nodeName !== 'TEXTAREA') { - return; - } - this.nodes.span.textContent = value; - QR.characterCount(); - if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { - return QR.cooldown.auto = false; + name = input.dataset.name; + this[name] = input.value; + switch (name) { + case 'thread': + return QR.status(); + case 'com': + this.nodes.span.textContent = this.com; + QR.characterCount(); + if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { + return QR.cooldown.auto = false; + } } }; @@ -5403,9 +5420,7 @@ if (QR.spoiler) { this.nodes.label.hidden = false; } - if (window.URL) { - URL.revokeObjectURL(this.URL); - } + URL.revokeObjectURL(this.URL); this.showFileData(); if (!/^image/.test(file.type)) { this.nodes.el.style.backgroundImage = null; @@ -5414,22 +5429,10 @@ return this.setThumbnail(); }; - _Class.prototype.setThumbnail = function(fileURL) { - var img, reader, + _Class.prototype.setThumbnail = function() { + var fileURL, img, _this = this; - if (!window.URL) { - if (!fileURL) { - reader = new FileReader(); - reader.onload = function(e) { - return _this.setThumbnail(e.target.result); - }; - reader.readAsDataURL(this.file); - return; - } - } else { - fileURL = URL.createObjectURL(this.file); - } img = $.el('img'); img.onload = function() { var applyBlob, cv, data, height, i, l, s, ui8a, width, _i; @@ -5440,9 +5443,7 @@ } height = img.height, width = img.width; if (height < s || width < s) { - if (window.URL) { - _this.URL = fileURL; - } + _this.URL = fileURL; _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; return; } @@ -5457,11 +5458,6 @@ cv.height = img.height = height; cv.width = img.width = width; cv.getContext('2d').drawImage(img, 0, 0, width, height); - if (!window.URL) { - _this.nodes.el.style.backgroundImage = "url(" + (cv.toDataURL()) + ")"; - delete _this.URL; - return; - } URL.revokeObjectURL(fileURL); applyBlob = function(blob) { _this.URL = URL.createObjectURL(blob); @@ -5481,6 +5477,7 @@ type: 'image/png' })); }; + fileURL = URL.createObjectURL(this.file); return img.src = fileURL; }; @@ -5493,9 +5490,6 @@ this.nodes.label.hidden = true; } this.showFileData(); - if (!window.URL) { - return; - } return URL.revokeObjectURL(this.URL); }; @@ -5556,12 +5550,11 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; - el = $('.drag', this.parentNode); - $.rmClass(el, 'drag'); $.rmClass(this, 'over'); if (!this.draggable) { return; } + el = $('.drag', this.parentNode); index = function(el) { return __slice.call(el.parentNode.children).indexOf(el); }; @@ -5569,7 +5562,8 @@ newIndex = index(this); (oldIndex < newIndex ? $.after : $.before)(this, el); post = QR.posts.splice(oldIndex, 1)[0]; - return QR.posts.splice(newIndex, 0, post); + QR.posts.splice(newIndex, 0, post); + return QR.status(); }; return _Class; @@ -5588,7 +5582,7 @@ }), this.ready.bind(this)); }, ready: function() { - var imgContainer, input, observer, setLifetime, + var imgContainer, input, setLifetime, _this = this; setLifetime = function(e) { @@ -5614,14 +5608,9 @@ img: imgContainer.firstChild, input: input }; - if (window.MutationObserver) { - observer = new MutationObserver(this.load.bind(this)); - observer.observe(this.nodes.challenge, { - childList: true - }); - } else { - $.on(this.nodes.challenge, 'DOMNodeInserted', this.load.bind(this)); - } + new MutationObserver(this.load.bind(this)).observe(this.nodes.challenge, { + childList: true + }); $.on(imgContainer, 'click', this.reload.bind(this)); $.on(input, 'keydown', this.keydown.bind(this)); $.on(input, 'focus', function() { @@ -5630,8 +5619,11 @@ $.on(input, 'blur', function() { return $.rmClass(QR.nodes.el, 'focus'); }); - $.get('captchas', [], function(item) { - return _this.sync(item['captchas']); + $.get('captchas', [], function(_arg) { + var captchas; + + captchas = _arg.captchas; + return _this.sync(captchas); }); $.sync('captchas', this.sync); this.reload(); @@ -5641,7 +5633,7 @@ return $.after(QR.nodes.com.parentNode, [imgContainer, input]); }, sync: function(captchas) { - this.captchas = captchas; + QR.captcha.captchas = captchas; return QR.captcha.count(); }, getOne: function() { @@ -5790,7 +5782,6 @@ QR.mimeTypes = mimeTypes.split(', '); QR.mimeTypes.push(''); nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value; - nodes.fileInput.accept = "text/*, " + mimeTypes; QR.spoiler = !!$('input[name=spoiler]'); if (QR.spoiler) { $.addClass(QR.nodes.el, 'has-spoiler'); @@ -6058,16 +6049,12 @@ post: post, isReply: isReply }); - if (threadID === postID) { - URL = "/" + g.BOARD + "/res/" + threadID; - } else if (g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab']) { - URL = "/" + g.BOARD + "/res/" + threadID + "#p" + postID; - } + URL = threadID === postID ? "/" + g.BOARD + "/res/" + threadID : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? "/" + g.BOARD + "/res/" + threadID + "#p" + postID : void 0; if (URL) { if (Conf['Open Post in New Tab']) { - $.open("/" + g.BOARD + "/res/" + threadID); + $.open(URL); } else { - window.location = "/" + g.BOARD + "/res/" + threadID; + window.location = URL; } } return QR.status(); @@ -6421,7 +6408,7 @@ id: 'ihover', src: post.file.URL }); - el.setAttribute('data-fullid', post.fullID); + el.dataset.fullID = post.fullID; $.add(Header.hover, el); UI.hover({ root: this, @@ -6441,7 +6428,7 @@ if (!doc.contains(this)) { return; } - post = g.posts[this.dataset.fullid]; + post = g.posts[this.dataset.fullID]; src = this.src.split('/'); if (src[2] === 'images.4chan.org') { URL = Redirect.to('file', { @@ -6571,6 +6558,74 @@ } }; + Sauce = { + init: function() { + var err, link, links, _i, _len, _ref; + + if (g.VIEW === 'catalog' || !Conf['Sauce']) { + return; + } + links = []; + _ref = Conf['sauces'].split('\n'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + try { + if (link[0] !== '#') { + links.push(this.createSauceLink(link.trim())); + } + } catch (_error) { + err = _error; + } + } + if (!links.length) { + return; + } + this.links = links; + this.link = $.el('a', { + target: '_blank' + }); + return Post.prototype.callbacks.push({ + name: 'Sauce', + cb: this.node + }); + }, + createSauceLink: function(link) { + var m, text; + + link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { + switch (parameter) { + case '%TURL': + return "' + encodeURIComponent(post.file.thumbURL) + '"; + case '%URL': + return "' + encodeURIComponent(post.file.URL) + '"; + case '%MD5': + return "' + encodeURIComponent(post.file.MD5) + '"; + case '%board': + return "' + encodeURIComponent(post.board) + '"; + default: + return parameter; + } + }); + text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; + link = link.replace(/;text:.+$/, ''); + return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); + }, + node: function() { + var link, nodes, _i, _len, _ref; + + if (this.isClone || !this.file) { + return; + } + nodes = []; + _ref = Sauce.links; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); + } + return $.add(this.file.info, nodes); + } + }; + ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; @@ -6711,8 +6766,8 @@ return; } $.off(this, 'click', DeleteLink["delete"]); - this.textContent = "Deleting " + this.textContent + "..."; fileOnly = $.hasClass(this, 'delete-file'); + this.textContent = "Deleting " + (fileOnly ? 'file' : 'post') + "..."; form = { mode: 'usrdel', onlyimgdel: fileOnly, @@ -6832,39 +6887,29 @@ node: function() { var button; - button = Menu.makeButton(this); if (this.isClone) { - $.replace($('.menu-button', this.nodes.info), button); - return; + button = $('.menu-button', this.nodes.info); + } else { + button = Menu.makeButton(this); + $.add(this.nodes.info, [$.tn('\u00A0'), button]); } - return $.add(this.nodes.info, [$.tn('\u00A0'), button]); + return $.on(button, 'click', Menu.toggle); }, makeButton: (function() { var a; a = null; - return function(post) { - var clone; - + return function() { a || (a = $.el('a', { className: 'menu-button fourchanx-link', innerHTML: '', href: 'javascript:;' })); - clone = a.cloneNode(true); - clone.setAttribute('data-postid', post.fullID); - if (post.isClone) { - clone.setAttribute('data-clone', true); - } - $.on(clone, 'click', Menu.toggle); - return clone; + return a.cloneNode(true); }; })(), toggle: function(e) { - var post; - - post = this.dataset.clone ? Get.postFromNode(this) : g.posts[this.dataset.postid]; - return Menu.menu.toggle(e, this, post); + return Menu.menu.toggle(e, this, Get.postFromNode(this)); } }; @@ -7285,7 +7330,7 @@ This saves bandwidth for both the user and the servers and avoid unnecessary computation. */ - _ref = [0, 304].contains(req.status) ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; + _ref = req.status === 304 ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; ThreadUpdater.set('status', text, klass); } if (ThreadUpdater.postID) { @@ -7703,23 +7748,21 @@ } }, scroll: function() { - var checkPosition, hash, onload, post, posts, prevID, root; + var checkPosition, hash, onload, post, posts, root; if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } if (Unread.posts.length) { - prevID = 0; - while (root = $.x('preceding-sibling::div[contains(@class,"postContainer")][1]', Unread.posts[0].nodes.root)) { - post = Get.postFromRoot(root); - if (prevID === post.ID) { - break; - } - prevID = post.ID; - if (!post.isHidden) { + post = Unread.posts[0]; + while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) { + if (!(post = Get.postFromRoot(root)).isHidden) { break; } } + if (!root) { + return; + } onload = function() { if (checkPosition(root)) { return root.scrollIntoView(false); @@ -7904,7 +7947,7 @@ post: {}, file: {}, init: function() { - var archive, arr, boardID, data, id, name, type, _i, _len, _ref, _ref1, _ref2, _ref3; + var archive, arr, boardID, data, id, name, type, _ref, _ref1, _ref2, _results; _ref = Conf['selectedArchives']; for (boardID in _ref) { @@ -7925,22 +7968,32 @@ } } _ref2 = Redirect.archives; + _results = []; for (name in _ref2) { archive = _ref2[name]; - _ref3 = archive.boards; - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - boardID = _ref3[_i]; - if (!(boardID in Redirect.thread)) { - Redirect.thread[boardID] = archive; + _results.push((function() { + var _i, _len, _ref3, _results1; + + _ref3 = archive.boards; + _results1 = []; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + boardID = _ref3[_i]; + if (!(boardID in Redirect.thread)) { + Redirect.thread[boardID] = archive; + } + if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { + Redirect.post[boardID] = archive; + } + if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { + _results1.push(Redirect.file[boardID] = archive); + } else { + _results1.push(void 0); + } } - if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { - Redirect.post[boardID] = archive; - } - if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { - Redirect.file[boardID] = archive; - } - } + return _results1; + })()); } + return _results; }, archives: { 'Foolz': { @@ -7948,7 +8001,7 @@ 'http': false, 'https': true, 'software': 'foolfuuka', - 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg'], + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vg', 'vp', 'vr', 'wsg'], 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg'] }, 'NSFW Foolz': { @@ -7982,14 +8035,6 @@ 'boards': ['c', 'w', 'wg'], 'files': ['c', 'w', 'wg'] }, - 'Love is Over': { - 'domain': 'loveisover.me', - 'http': true, - 'https': true, - 'software': 'foolfuuka', - 'boards': ['d', 'h', 'v'], - 'files': ['d', 'h', 'v'] - }, 'Foolz a Shit': { 'domain': 'archive.foolzashit.com', 'http': true, @@ -8001,7 +8046,7 @@ 'Install Gentoo': { 'domain': 'archive.installgentoo.net', 'http': true, - 'https': true, + 'https': false, 'software': 'fuuka', 'boards': ['diy', 'g', 'sci'], 'files': [] @@ -8028,6 +8073,14 @@ 'software': 'fuuka', 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'], 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr'] + }, + 'worldathleticproject': { + 'domain': 'fuuka.worldathleticproject.org', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + 'boards': ['e', 'h', 'p', 's', 'u'], + 'files': ['e', 'h', 'p', 's', 'u'] } }, to: function(dest, data) { @@ -8899,13 +8952,13 @@ } break; case Conf['Next thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(+1); break; case Conf['Previous thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(-1); @@ -9177,10 +9230,9 @@ _ref = Nav.getThread(true), threads = _ref[0], thread = _ref[1], i = _ref[2], rect = _ref[3], topMargin = _ref[4]; top = rect.top - topMargin; - if (!((delta === -1 && Math.ceil(top) < 0) || (delta === +1 && top > 1))) { - i += delta; + if ((delta === -1 && top > -5) || (delta === +1 && top < 5)) { + top = ((_ref1 = threads[i + delta]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; } - top = ((_ref1 = threads[i]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; return window.scrollBy(0, top); } }; @@ -9327,76 +9379,6 @@ } }; - Sauce = { - init: function() { - var err, link, links, _i, _len, _ref; - - if (g.VIEW === 'catalog' || !Conf['Sauce']) { - return; - } - links = []; - _ref = Conf['sauces'].split('\n'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link[0] === '#') { - continue; - } - try { - links.push(this.createSauceLink(link.trim())); - } catch (_error) { - err = _error; - continue; - } - } - if (!links.length) { - return; - } - this.links = links; - this.link = $.el('a', { - target: '_blank' - }); - return Post.prototype.callbacks.push({ - name: 'Sauce', - cb: this.node - }); - }, - createSauceLink: function(link) { - var m, text; - - link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { - switch (parameter) { - case '%TURL': - return "' + encodeURIComponent(post.file.thumbURL) + '"; - case '%URL': - return "' + encodeURIComponent(post.file.URL) + '"; - case '%MD5': - return "' + encodeURIComponent(post.file.MD5) + '"; - case '%board': - return "' + encodeURIComponent(post.board) + '"; - default: - return parameter; - } - }); - text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; - link = link.replace(/;text:.+$/, ''); - return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); - }, - node: function() { - var link, nodes, _i, _len, _ref; - - if (this.isClone || !this.file) { - return; - } - nodes = []; - _ref = Sauce.links; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); - } - return $.add(this.file.info, nodes); - } - }; - Time = { init: function() { if (g.VIEW === 'catalog' || !Conf['Time Formatting']) { @@ -9905,7 +9887,7 @@ $.add(div, ta); return; } - return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; + return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; }, sauce: function(section) { var ta; @@ -10190,9 +10172,7 @@ $.get(Conf, Main.initFeatures); $.on(d, '4chanMainInit', Main.initStyle); return $.asap((function() { - var _ref; - - return d.head && $('link[rel="shortcut icon"]', d.head) || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); + return d.head && $('link[rel="shortcut icon"]', d.head) || d.readyState !== 'loading'; }), Main.initStyle); }, initFeatures: function(items) { @@ -10318,7 +10298,7 @@ return $.ready(Main.initReady); }, initStyle: function() { - var mainStyleSheet, observer, setStyle, style, styleSheets, _ref; + var mainStyleSheet, setStyle, style, styleSheets, _ref; $.off(d, '4chanMainInit', Main.initStyle); if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) { @@ -10355,18 +10335,13 @@ if (!mainStyleSheet) { return; } - if (window.MutationObserver) { - observer = new MutationObserver(setStyle); - return observer.observe(mainStyleSheet, { - attributes: true, - attributeFilter: ['href'] - }); - } else { - return $.on(mainStyleSheet, 'DOMAttrModified', setStyle); - } + return new MutationObserver(setStyle).observe(mainStyleSheet, { + attributes: true, + attributeFilter: ['href'] + }); }, initReady: function() { - var board, boardChild, err, errors, href, passLink, posts, styleSelector, thread, threadChild, threads, _i, _j, _len, _len1, _ref, _ref1; + var board, err, errors, href, passLink, postRoot, posts, styleSelector, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1; if (d.title === '4chan - 404 Not Found') { if (Conf['404 Redirect'] && g.VIEW === 'thread') { @@ -10385,29 +10360,23 @@ if (board = $('.board')) { threads = []; posts = []; - _ref = board.children; + _ref = $$('.board > .thread', board); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - boardChild = _ref[_i]; - if (!$.hasClass(boardChild, 'thread')) { - continue; - } - thread = new Thread(boardChild.id.slice(1), g.BOARD); + threadRoot = _ref[_i]; + thread = new Thread(+threadRoot.id.slice(1), g.BOARD); threads.push(thread); - _ref1 = boardChild.children; + _ref1 = $$('.thread > .postContainer', threadRoot); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - threadChild = _ref1[_j]; - if (!$.hasClass(threadChild, 'postContainer')) { - continue; - } + postRoot = _ref1[_j]; try { - posts.push(new Post(threadChild, thread, g.BOARD)); + posts.push(new Post(postRoot, thread, g.BOARD)); } catch (_error) { err = _error; if (!errors) { errors = []; } errors.push({ - message: "Parsing of Post No." + (threadChild.id.match(/\d+/)) + " failed. Post will be skipped.", + message: "Parsing of Post No." + (postRoot.id.match(/\d+/)) + " failed. Post will be skipped.", error: err }); } @@ -10631,11 +10600,11 @@ var _ref; if (!('thisPageIsLegit' in Main)) { - Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error'); + Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error' && _ref !== '504 Gateway Time-out'); } return Main.thisPageIsLegit; }, - css: "/* General */\n.dialog {\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder: 1px solid;\ndisplay: block;\npadding: 0;\n}\n.captcha-img,\n.field {\nbackground-color: #FFF;\nborder: 1px solid #CCC;\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\ncolor: #333;\nfont: 13px sans-serif;\noutline: none;\ntransition: color .25s, border-color .25s;\ntransition: color .25s, border-color .25s;\n}\n.field::-moz-placeholder,\n.field:hover::-moz-placeholder {\ncolor: #AAA !important;\nfont-size: 13px !important;\nopacity: 1.0 !important;\n}\n.captch-img:hover,\n.field:hover {\nborder-color: #999;\n}\n.field:hover, .field:focus {\ncolor: #000;\n}\n.field[disabled] {\nbackground-color: #F2F2F2;\ncolor: #888;\n}\n.move {\ncursor: move;\noverflow: hidden;\n}\nlabel, .favicon {\ncursor: pointer;\n}\na[href=\"javascript:;\"] {\ntext-decoration: none;\n}\n.warning {\ncolor: red;\n}\n#boardNavDesktop {\ndisplay: none !important;\n}\na {\noutline: none !important;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\ndisplay: block !important;\noverflow: visible !important;\n}\n[hidden] {\ndisplay: none !important;\n}\n\n/* fixed, z-index */\n#overlay,\n#fourchanx-settings,\n#qp, #ihover,\n#navlinks, .fixed #header-bar,\n:root.float #updater,\n:root.float #thread-stats,\n#qr {\nposition: fixed;\n}\n#fourchanx-settings {\nz-index: 999;\n}\n#overlay {\nz-index: 900;\n}\n#notifications {\nz-index: 70;\n}\n#qp, #ihover {\nz-index: 60;\n}\n#menu {\nz-index: 50;\n}\n#navlinks, #updater, #thread-stats {\nz-index: 40;\n}\n.fixed #header-bar.autohide {\nz-index: 35;\n}\n#qr {\nz-index: 30;\n}\n#watcher {\nz-index: 8;\n}\n:root.fixed-watcher #watcher {\nz-index: 20;\n}\n.fixed #header-bar {\nz-index: 10;\n}\n/* Header */\n.fixed.top body {\npadding-top: 2em;\n}\n.fixed.bottom body {\npadding-bottom: 2em;\n}\n.fixed #header-bar {\nright: 0;\nleft: 0;\npadding: 3px 4px 4px;\n}\n.fixed.top #header-bar {\ntop: 0;\n}\n.fixed.bottom #header-bar {\nbottom: 0;\n}\n#header-bar {\nborder-width: 0;\ntransition: all .1s .05s ease-in-out;\n}\n:root.centered-links #shortcuts {\nwidth: 300px;\ntext-align: right;\n}\n:root.centered-links #header-bar {\ntext-align: center;\n}\n:root.centered-links #custom-board-list {\nposition: relative;\nleft: 150px;\n}\n.fixed.top #header-bar {\nborder-bottom-width: 1px;\n}\n.fixed.bottom #header-bar {\nbox-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\nborder-top-width: 1px;\n}\n.fixed.bottom #header-bar .menu-button i {\nborder-top: none;\nborder-bottom: 6px solid;\n}\n#board-list {\ntext-align: center;\n}\n.fixed #header-bar.autohide:not(:hover) {\nbox-shadow: none;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar.autohide:not(:hover) {\nmargin-bottom: -1em;\n-webkit-transform: translateY(-100%);\ntransform: translateY(-100%);\n}\n.fixed.bottom #header-bar.autohide:not(:hover) {\n-webkit-transform: translateY(100%);\ntransform: translateY(100%);\n}\n#scroll-marker {\nleft: 0;\nright: 0;\nheight: 10px;\nposition: absolute;\n}\n#header-bar #scroll-marker {\ndisplay: none;\n}\n.fixed #header-bar #scroll-marker {\ndisplay: block;\n}\n.fixed.top #header-bar #scroll-marker {\ntop: 100%;\n}\n.fixed.bottom #header-bar #scroll-marker {\nbottom: 100%;\n}\n#header-bar a:not(.entry):not(.close) {\ntext-decoration: none;\npadding: 1px;\n}\n#header-bar input {\nmargin: 0;\nvertical-align: bottom;\n}\n#shortcuts:empty {\ndisplay: none;\n}\n.brackets-wrap::before {\ncontent: \"\\00a0[\";\n}\n.brackets-wrap::after {\ncontent: \"]\\00a0\";\n}\n.disabled,\n.expand-all-shortcut {\nopacity: .45;\n}\n#shortcuts {\nfloat: right;\n}\n.shortcut {\nmargin-left: 3px;\n}\n#navbotright,\n#navtopright {\ndisplay: none;\n}\n#toggleMsgBtn {\ndisplay: none !important;\n}\n.current {\nfont-weight: bold;\n}\n/* 4chan X link brackets */\n.fourchanx-link::after {\ncontent: \"]\";\n}\n.fourchanx-link::before {\ncontent: \"[\";\n}\n/* Notifications */\n#notifications {\nposition: fixed;\ntop: 0;\nheight: 0;\ntext-align: center;\nright: 0;\nleft: 0;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar #notifications {\nposition: absolute;\ntop: 100%;\n}\n.notification {\ncolor: #FFF;\nfont-weight: 700;\ntext-shadow: 0 1px 2px rgba(0, 0, 0, .5);\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder-radius: 2px;\nmargin: 1px auto;\nwidth: 500px;\nmax-width: 100%;\nposition: relative;\ntransition: all .25s ease-in-out;\n}\n.notification.error {\nbackground-color: hsla(0, 100%, 38%, .9);\n}\n.notification.warning {\nbackground-color: hsla(36, 100%, 38%, .9);\n}\n.notification.info {\nbackground-color: hsla(200, 100%, 38%, .9);\n}\n.notification.success {\nbackground-color: hsla(104, 100%, 38%, .9);\n}\n.notification a {\ncolor: white;\n}\n.notification > .close {\npadding: 6px;\ntop: 0;\nright: 5px;\nposition: absolute;\n}\n.message {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\npadding: 6px 20px;\nmax-height: 200px;\nwidth: 100%;\noverflow: auto;\n}\n\n/* Settings */\n:root.fourchan-x body {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\n}\n#overlay {\nbackground-color: rgba(0, 0, 0, .5);\ntop: 0;\nleft: 0;\nheight: 100%;\nwidth: 100%;\n}\n#fourchanx-settings {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nbox-shadow: 0 0 15px rgba(0, 0, 0, .15);\nheight: 600px;\nmin-height: 0;\nmax-height: 100%;\nwidth: 900px;\nmin-width: 0;\nmax-width: 100%;\nmargin: auto;\npadding: 3px;\ntop: 50%;\nleft: 50%;\n-moz-transform: translate(-50%, -50%);\n-webkit-transform: translate(-50%, -50%);\n-o-transform: translate(-50%, -50%);\ntransform: translate(-50%, -50%);\n}\n#fourchanx-settings > nav {\npadding: 2px 2px 0;\nheight: 15px;\n}\n#fourchanx-settings > nav a {\ntext-decoration: underline;\n}\n#fourchanx-settings > nav a.close {\ntext-decoration: none;\npadding: 2px;\n}\n.section-container {\noverflow: auto;\nposition: absolute;\ntop: 2.1em;\nright: 5px;\nbottom: 5px;\nleft: 5px;\npadding-right: 5px;\n}\n.sections-list {\npadding: 0 3px;\nfloat: left;\n}\n.credits {\nfloat: right;\n}\n.tab-selected {\nfont-weight: 700;\n}\n.section-sauce ul,\n.section-advanced ul {\nlist-style: none;\nmargin: 0;\n}\n.section-sauce ul {\npadding: 8px;\n}\n.section-advanced ul {\npadding: 0px;\n}\n.section-sauce li,\n.section-advanced li {\npadding-left: 4px;\n}\n.section-main label {\ntext-decoration: underline;\n}\n.section-filter ul {\npadding: 0;\n}\n.section-filter li {\nmargin: 10px 40px;\n}\n.section-filter textarea {\nheight: 500px;\n}\n.section-sauce textarea {\nheight: 350px;\n}\n.section-advanced .field[name=\"boardnav\"] {\nwidth: 100%;\n}\n.section-advanced textarea {\nheight: 150px;\n}\n.section-advanced .archive-cell {\nmin-width: 160px;\ntext-align: center;\n}\n.section-advanced #archive-board-select {\nposition: absolute;\n}\n.section-advanced .note {\nfont-size: 0.8em; \nfont-style: italic; \nmargin-left: 10px;\n}\n.section-advanced .note code {\nfont-style: normal;\nfont-size: 11px;\n}\n#fourchanx-settings fieldset {\nborder: 1px solid;\nborder-radius: 3px;\n}\n#fourchanx-settings legend {\nfont-weight: 700;\n}\n#fourchanx-settings textarea {\nfont-family: monospace;\nmin-width: 100%;\nmax-width: 100%;\n}\n#fourchanx-settings code {\ncolor: #000;\nbackground-color: #FFF;\npadding: 0 2px;\n}\n.unscroll {\noverflow: hidden;\n}\n\n/* Announcement Hiding */\n:root.hide-announcement #globalMessage {\ndisplay: none;\n}\na.hide-announcement {\nfloat: left;\n}\n\n/* Unread */\n#unread-line {\nmargin: 0;\nborder-color: rgb(255,0,0);\n}\n\n/* Thread Updater */\n#updater {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n#updater > .move {\npadding: 5px 3px 0px;\nmargin-bottom: -3px;\n}\n#updater > div:last-child {\ntext-align: center;\n}\n#updater input[type=number] {\nwidth: 4em;\n}\n:root.float #updater {\npadding: 0px 3px;\n}\n.new {\ncolor: limegreen;\n}\n#update-status.new {\nmargin-right: 5px;\n}\n#update-timer {\ncursor: pointer;\n}\n\n/* Thread Watcher */\n#watcher {\nposition: absolute;\n}\n#watcher {\npadding-bottom: 3px;\noverflow: hidden;\nwhite-space: nowrap;\nmin-width: 120px;\nmax-height: 92%;\noverflow-y: auto;\n}\n:root.fixed-watcher #watcher {\nposition: fixed;\n}\n:root:not(.fixed-watcher) #watcher:not(:hover) {\nmax-height: 210px;\noverflow-y: hidden;\n}\n#watcher > .move {\npadding-top: 3px;\n}\n#watcher > div {\nmax-width: 250px;\noverflow: hidden;\npadding-left: 3px;\npadding-right: 3px;\ntext-overflow: ellipsis;\n}\n#watcher a {\ntext-decoration: none;\n}\n#watcher .move>.close {\nposition: absolute;\nright: 0px;\ntop: 0px;\npadding: 0px 4px;\n}\n.watch-thread-link {\npadding-top: 18px;\nwidth: 18px;\nheight: 0px;\ndisplay: inline-block;\nbackground-repeat: no-repeat;\nopacity: 0.2;\nposition: relative;\ntop: 1px;\n}\n.watch-thread-link.watched {\nopacity: 1;\n}\n\n/* Thread Stats */\n#thread-stats {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n:root.float #post-count, :root.float #file-count {\npointer-events: none;\n}\n:root.float #thread-stats {\npadding: 0px 3px;\n}\n\n/* Quote */\n.deadlink {\ntext-decoration: none !important;\n}\n.backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) {\ntext-decoration: underline !important;\n}\n.inlined {\nopacity: .5;\n}\n#qp input, .forwarded {\ndisplay: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\ntext-decoration: none;\nborder-bottom: 1px dashed;\n}\n.filtered {\ntext-decoration: underline line-through;\n}\n:root.hide-backlinks .backlink.filtered {\ndisplay: none;\n}\n.inline {\nborder: 1px solid;\ndisplay: table;\nmargin: 2px 0;\n}\n.inline .post {\nborder: 0 !important;\nbackground-color: transparent !important;\ndisplay: table !important;\nmargin: 0 !important;\npadding: 1px 2px !important;\n}\n#qp > .opContainer::after {\ncontent: '';\nclear: both;\ndisplay: table;\n}\n#qp .post {\nborder: none;\nmargin: 0;\npadding: 2px 2px 5px;\n}\n#qp img {\nmax-height: 300px;\nmax-width: 500px;\nmax-height: 80vh;\nmax-width: 50vw;\n}\n.qphl {\noutline: 2px solid rgba(216, 94, 49, .7);\n}\n:root.highlight-own .yourPost>.reply,\n:root.highlight-you .quotesYou>.reply {\nborder-left: 2px solid rgba(221,0,0,.5);\n}\n/* Quote Threading */\n.threadContainer {\nmargin-left: 20px;\nborder-left: 1px solid rgba(128,128,128,.3);\n}\n.threadOP {\nclear: both;\n} \n\n/* File */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull,\n.expanded-image > .post > .file > .fileThumb > img[data-md5],\n:not(.expanded-image) > .post > .file > .fileThumb > .full-image {\ndisplay: none;\n}\n.expanding {\nopacity: .5;\n}\n:root.fit-height .full-image {\nmax-height: 100vh;\n}\n:root.fit-width .full-image {\nmax-width: 100%;\n}\n:root.gecko.fit-width .full-image,\n:root.presto.fit-width .full-image {\nwidth: 100%;\n}\n#ihover {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nmax-height: 100%;\nmax-width: 75%;\npadding-bottom: 16px;\n}\n.fappeTyme .thread > .noFile,\n.fappeTyme .threadContainer > .noFile {\ndisplay: none;\n}\n\n/* Index/Reply Navigation */\n#navlinks {\nfont-size: 16px;\ntop: 25px;\nright: 10px;\n}\n\n/* Filter */\n.opContainer.filter-highlight {\nbox-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.filter-highlight > .reply {\nbox-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n\n/* Spoiler text */\n:root.reveal-spoilers s {\ncolor: white !important;\n}\n\n/* Thread & Reply Hiding */\n.hide-thread-button,\n.hide-reply-button {\nfloat: left;\nmargin-right: 2px;\n}\n.stub ~ * {\ndisplay: none !important;\n}\n.stub input {\ndisplay: inline-block;\n}\n\n/* QR */\n:root.hide-original-post-form #postForm,\n:root.hide-original-post-form .postingMode,\n:root.hide-original-post-form #togglePostForm,\n#qr.autohide:not(.has-focus):not(:hover) > form,\n.postingMode ~ #qr select,\n#file-n-submit:not(.has-file) #qr-filerm {\ndisplay: none;\n}\n#qr select, #dump-button, .remove, .captcha-img {\ncursor: pointer;\n}\n#qr {\nz-index: 20;\nposition: fixed;\npadding: 1px;\nborder: 1px solid transparent;\nmin-width: 300px;\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nmargin-bottom: 1px;\n}\n#qr .close {\nfloat: right;\npadding: 0 3px;\n}\n#qr .warning {\nmin-height: 1.6em;\nvertical-align: middle;\npadding: 0 1px;\nborder-width: 1px;\nborder-style: solid;\n}\n.qr-link-container {\ntext-align: center;\n}\n.persona {\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-button {\nwidth: 10%;\nmargin: 0;\nmargin-right: 4px;\nfont: 13px sans-serif;\npadding: 1px 0px 2px;\nopacity: 0.6;\n}\n.persona .field:not(#dump) {\nwidth: 95px;\nmin-width: 33.3%;\nmax-width: 33.3%;\n}\n#qr textarea.field {\nheight: 14.8em;\nmin-height: 9em;\n}\n#qr.has-captcha textarea.field {\nheight: 9em;\n}\ninput.field.tripped:not(:hover):not(:focus) {\ncolor: transparent !important; text-shadow: none !important;\n}\n#qr textarea {\nresize: both;\n}\n.captcha-img {\nmargin: 0px;\ntext-align: center;\nbackground-image: #fff;\nfont-size: 0px;\nmin-height: 59px;\nmin-width: 302px;\n}\n.captcha-input {\nwidth: 100%;\nmargin: 1px 0 0;\n}\n.captcha-input.error:focus {\nborder-color: rgb(255,0,0) !important;\n}\n.field {\n-moz-box-sizing: border-box;\nmargin: 0px;\npadding: 2px 4px 3px;\n}\n#qr textarea {\nmin-width: 100%;\n}\n#qr [type='submit'] {\nwidth: 25%;\nvertical-align: top;\n}\n:root.webkit #qr [type='submit'] {\nheight: 24px;\n}\n/* Fake File Input */\n#qr-filename,\n.has-file #qr-no-file {\ndisplay: none;\n}\n#qr-no-file,\n.has-file #qr-filename {\ndisplay: inline-block;\npadding: 0px 4px;\nmargin-bottom: 2px;\noverflow: hidden;\ntext-overflow: ellipsis;\nmax-width: 88%;\n}\n#qr-no-file {\ncolor: #AAA;\n}\n#qr-filename-container {\n-moz-box-sizing: border-box;\ndisplay: inline-block;\nposition: relative;\nwidth: 100px;\nmin-width: 74.6%;\nmax-width: 74.6%;\nmargin-right: 0.4%;\nmargin-top: 1px;\noverflow: hidden;\npadding: 2px 1px 0;\nheight: 22px;\n}\n#qr-filename-container:hover {\ncursor: text;\n}\n#qr-extras-container {\nposition: absolute;\nright: 0px;\n}\n#qr-filerm {\nmargin-right: 2px;\nz-index: 2;\n}\n#file-n-submit {\nheight: 23px;\n}\n#qr input[type=file] {\nvisibility: hidden;\nposition: absolute;\n}\n/* Thread Select / Spoiler Label */\n#qr select {\nfloat: right;\n}\n#qr.has-spoiler .has-file #qr-spoiler-label {\nwidth: 6.7%;\nmin-width: 6.7%;\nmax-width: 6.7%;\ndisplay: inline-block;\ntext-align: center;\nvertical-align: top;\n}\n#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\ndisplay: none;\n}\n#qr.has-spoiler .has-file #qr-filename-container {\nmax-width: 67.9%;\nmin-width: 67.9%;\n}\n#qr-spoiler-label input {\nposition: relative;\ntop: 3px;\n}\n/* Dumping UI */\n.dump #dump-list-container {\ndisplay: block;\n}\n#dump-list-container {\ndisplay: none;\nposition: relative;\noverflow-y: hidden;\nmargin-top: 1px;\n}\n#dump-list {\noverflow-x: auto;\noverflow-y: hidden;\nwhite-space: nowrap;\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-list:hover {\noverflow-x: auto;\n}\n.qr-preview {\n-moz-box-sizing: border-box;\ncounter-increment: thumbnails;\ncursor: move;\ndisplay: inline-block;\nheight: 90px;\nwidth: 90px;\npadding: 2px;\nopacity: .5;\noverflow: hidden;\nposition: relative;\ntext-shadow: 0 1px 1px #000;\n-moz-transition: opacity .25s ease-in-out;\nvertical-align: top;\nbackground-size: cover;\n}\n.qr-preview:hover,\n.qr-preview:focus {\nopacity: .9;\n}\n.qr-preview::before {\ncontent: counter(thumbnails);\ncolor: #fff;\nposition: absolute;\ntop: 3px;\nright: 3px;\ntext-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.qr-preview#selected {\nopacity: 1;\n}\n.qr-preview.drag {\nbox-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.qr-preview.over {\nborder-color: #fff;\n}\n.qr-preview > span {\ncolor: #fff;\n}\n.remove {\nbackground: none;\ncolor: #e00;\nfont-weight: 700;\npadding: 3px;\n}\na:only-of-type > .remove {\ndisplay: none;\n}\n.remove:hover::after {\ncontent: \" Remove\";\n}\n.qr-preview > label {\nbackground: rgba(0,0,0,.5);\ncolor: #fff;\nright: 0; bottom: 0; left: 0;\nposition: absolute;\ntext-align: center;\n}\n.qr-preview > label > input {\nmargin: 0;\n}\n#add-post {\ncursor: pointer;\nfont-size: 2em;\nposition: absolute;\ntop: 50%;\nright: 10px;\n-moz-transform: translateY(-50%);\n}\n.textarea {\nposition: relative;\n}\n:root.webkit .textarea {\nmargin-bottom: -2px;\n}\n#char-count {\ncolor: #000;\nbackground: hsla(0, 0%, 100%, .5);\nfont-size: 8pt;\nposition: absolute;\nbottom: 1px;\nright: 1px;\npointer-events: none;\n}\n\n/* Menu */\n.menu-button {\ndisplay: inline-block;\nposition: relative;\ncursor: pointer;\n}\n.menu-button i {\nborder-top: 6px solid;\nborder-right: 4px solid transparent;\nborder-left: 4px solid transparent;\ndisplay: inline-block;\nmargin: 2px;\nvertical-align: middle;\n}\n#menu {\nposition: fixed;\noutline: none;\n}\n.entry {\nborder-bottom: 1px solid rgba(0,0,0,.25);\ncursor: pointer;\ndisplay: block;\noutline: none;\npadding: 3px 7px;\nposition: relative;\ntext-decoration: none;\nwhite-space: nowrap;\n}\n.left>.entry.has-submenu {\npadding-right: 17px !important;\n}\n.entry:last-child {\nborder-bottom: 0;\n}\n.has-submenu::after {\ncontent: \"\";\nborder-left: .5em solid;\nborder-top: .3em solid transparent;\nborder-bottom: .3em solid transparent;\ndisplay: inline-block;\nmargin: .3em;\nposition: absolute;\nright: 3px;\n}\n.left .has-submenu::after {\nborder-left: 0;\nborder-right: .5em solid;\n}\n.submenu {\ndisplay: none;\nposition: absolute;\nleft: 100%;\ntop: -1px;\n}\n.focused .submenu {\ndisplay: block;\n}\n.imp-exp-result {\nposition: absolute;\ntext-align: center;\nmargin: auto;\nright: 0px;\nleft: 0px;\nwidth: 200px;\n}\n.export, .import {\ncursor: pointer;\ntext-decoration: none !important;\n}\n/* Link Title Favicons */\n.linkify.YouTube {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vimeo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAASJJREFUOE9jYAAC7ln7/pODQXrBmq333PvPu/YaSRikB6QXbACpmmHqsRoAMll7+20UQ0H8tmuv/pdffPFfZtNNuByGASBFIPDh5x+4IV6HHoDFYGDJgw+YBoBMBUkgA5BtIKduuvvy//svX+FSB+88wTTAc+/t/83bj/0HScLA5BPXwc7lKJ36f+L6XXDxhUfOYxrAPWUnWKFp9UQUm3iWQxSDXAEDSX3zcIcB96wD/x+8eA1XDNKMHAYg20GW4Y0FkCIYAAUqzEBQOIBciRzlWKMxZelOlMCEcVxq+jHSC1YDJPs3YBgA8jey0/F6ARRwsFAHORukmat9NdbUijMpg/wKcrJodDFOzSBXwA3Alh9AToZFI7a8Asu98BxJbnYGAJb5vYLDANzSAAAAAElFTkSuQmCC') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.SoundCloud {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.audio {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.LiveLeak {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAydJREFUOE9Nk1tIk2EYx79NyUNqTk0o6KYrnZeChodLDxfeZpCbJk4RXU5Nm7tYRYhiYXbQlaeGutyW2gxtpB1RIyKDEjKwA6Ti2dR5KNDn+fq/S6TBj/f93r3P732e53s/qfnkSdej4GB2SBLbwf+jmB+gUMgOheLg/z7EdCUnO6Ref392SpK8Hyh3I+gBwBo7lUp2xcbyQEoKD6alyQOpqd754/h4FjJXZCRJTl9ftmEzoK5/wdQJxPgkLY2WV1dpc2uLtnZ2eHNnhza3t2nd46GhjAzuValY6jx0iIfS03msoIDuQ9COQCtoUSjohU5HuwgaN5loeXycd3d3aW9vzwvW2K5SkdTi58fvzGb+3tdHFggA3QONEAzn59PvjQ1yqNX0zenkvX0B4ffWaGRraChJd/385JGqKvlzTw/fRqOaIGkEd1DjU52O/3g83BkTw5MOh7yJuUCUM2o0yi2hoSw1IIOhykr+YLNRHYKu4XQvyKA/N5c8yMCCDD7Z7bz26xcJ1rH2rKKCG0UJdRAMlJbyG6uVrkJQjWAB5tSbk0Nr2HwDgvcQiIYur6zQyvo6ucvLueHIEZKuQPBQr+dXra1kRuqXEOwFArtWSytra1QdFUVjNhvPLS3R3OIiLUDUD0F1WBhJJtwDW2Ehu5uaqBICI4IFlRB0QLCEzaboaHrd0cHzCBYsIIuesjK+LAQXkEFrXh676uupGCWcR6AeghLQptGQONUAwfOuLp6Zn6eZuTmaXVig7pISrhI90ENgQbdHhoep32JhFzLpu3WLio8epUYIfs7OUjF6UKJW88XERLqYkEBNej11oG8XhCAvMFAuOn5cNiclsTkhQTbhmpri4lgbEMANWi1DwC/xit3t7bK7rY0Fo4OD3G4wyEURESzloAdnceezlErK8vH5N4KzPj50PTOTfkxP0+THj/RlYoInJyZI8HVqim5qNFwQHk7SucBAPo2PKRMNPLM/4pnFszYkhJsNBu6uqWFHba1sr61lQSveQFZQkFx07BhJmhMnrLn4NLMPH/aSExR0QDbmWhwgyEapwDvXoDxdWBiXnjrV/Bdm2kYUxLwmEgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vocaroo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.pastebin {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAtZJREFUOE+NU91LWmEc7sJtQew/2MUY7INg7CLY3W5GMHazyzEQo9UmfYxZTbAiVlgRqLMSZ+XnDC3z2+Y0+8JGakKZTtR0Tl2wtgtLLQh29cz3ZZ3h3Q68vOc95zzP73l+z+/U1f292O09DRxubxOH23P//1bvtQts3dPnry7LZnXJhcUl5Avf8dHtwY+fv2AyW5DOfIXFakMm+w0G4wISyRRm55TQG0y/Wzv6mikJ52Xf9TmVBoFAAD6fDwqFAqFQCJubmzCbzZiensbp6SmkUikikQi0Wi0kEgm6ewVaStDCfXPDandifn6egoaGhrCzswO1Wg2Hw4HBwUGk02kIBAL4/X4IhUJMTk6ii8dfYggy2RwymQzOz88Rj8dRLpexv7+PSqWCYDCIQqGAra0tJBIJrK2t0XdVAjNDEIl+wfj4OEqlEq2wt7dHrchkMmrBYDCAz+fTIjweD7FYrJbgIJOlgLOzM8jlcip1eXmZ2rFarVAqlRCLxcjlchCJRFRljYJYPAG32418Pg+n04lsNouVlRUcHh7C4/FQIOlHNBqlezgcJgQWxkIgGMbExASVNjY2hvX1dVo9mUzS5wREFLhcLrqTcw2B//M2RkdHodPp4PV6oVKpqH+SCom3v7+fNnF4eJiJusbCJ6+PviSyScakiaR5RIHRaKQpmEwmbAdCeD8zB6vdhebHT8SMhcUlC83bbrdTJRsbG3RwiCVCRNJJpDIoVeNNJJJQzKryV+rrmxiCtyNCCmaz2VhdXQWXy6XDpNfrodFoYLXZUTw+pk222Z3lW3ca26rgSwzBwqIZAwMDlITMAVEwNTVFR5fEJpK8Qyp1AJvDVbrTeLenCmxgfiZ22+urCtWHyu7uLp2wVCpFKx0dHaFYLOLk5KT6Y9kgk89kb95ubK0BX7A8a+1qannRLeW0daj/rU51S3tn9dypfvDw0QiLxbpX/Z7FVK7e/AEj4Wf24/2f5AAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.gist {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqUkzuIE1EUhv955MnsbB6r4kYQLUQQFncV3SnCIqJsoWGDYOGjsIiCtY2Kla1sjLBIsFFcXJC1kaSwENQmXUQSRSUSjCQSTCbkbR4z47lXEgtBNwcu3DNzvvO8R8jlcj7LshKmaWqYQERRTAmCcEru9/sJr9er0QF92BJMAVGr1TQ6CeZAc7lcGAwGkyQAxpTLZU0eDoc8crfbRTgcRjAYRCQSYSmi1WpxY7fbjU6ng1gshmaziXg8zhnGIpVKWbquW9ls1mLZsaMoiqWq6lgnBxY55He/328Vi0XOMFZmqVMD4fF4QBAajcY48khY9JE4HA4enTGMFVkaTHmy+ZzD/5NSqYSNB484w1h55ODO3TVu4FXcWDywl24Cmp0e1WBhyuWELAtIf/qKUrWOONmev3Lpt4NRCXq1gplpBS/v3cDc0nGg9h1o1ZkfwO4Atu1B8cM7HLt8k37V/y5B2b4bJxf2Y+7oEbyJrkMvUjki0YYJ03LidfQxAt4dOHdCw5RdGZcgGobBlQtnV/BDr1GfDai7ZiHZZRi9PoY/e5SCCTUwC9gk1GmMh5YWOcNYkR4Sv1y9uAJbYB82N57h4OnDmN7phjQ0qUkWRJuB+TMaPn/5iFfvv+Ha7eucYey4iWw8q6tRJJNJ3Fp7ClUawEkViBTfkCR0YUNTVHD/4Tpm/P4/U2CeKpUKfD4fJDIMhUKEhP45St50XedZyLQY6Xw+v8AUemVb2oNqtYpCocCWKi2TLLfb7ReZTGZ+kmUi7i2VvfxLgAEAZChMriPcl+IAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.image {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.InstallGentoo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAklJREFUOE9jYEAAASBTCorZkcSRmTjVCDLziCwG4hfM3EIvGNm44oC6WNEM4WXi5FsEkmfhFX3BxMmfAJSHW9Qr55Px3aZp3X/btq3/hQydPzKysMcCFbBBDeFj4uBdqBJR/gskb1W34j+PmulLoJwbzBJJoMm7dNO7/ntMP/XfpW/v//SKvk+7tl7fvXfTpx5pCdWVSiHFv1wnHQbLi9sE/Wdk5SwBauaCGQB3gUPb5v+7Lr/8/+fvr/9fv/z+f+Pyr/9bV735l9Wy/79Dx/b/Nk0bsLoAHgbeAVHv/v77/f8f0IB7N7+cu3DuecK54z9+7lzz639e9pK/7HwSWMMA5BJwCJeXtOm/fvVj1fcfv369f//92cN7X6ZcPvf9x6Htv//vXP3r/+T245UEYgpskPTNq08LgN749/PH7/93rv/6f/rw7//nj//4f+bU0zQcUQwWBkdVbGz62y+fv3wHeeXrlz//H9798//qpY//M3KqfzGxc8djiWKwZnBUuWQ2/fr46fv/P39+///x/ff/d69//z97+s7fyMb5/+y7d2GLYriDZikFF/1qXXXj/4Pbv/8/f/jn/5MH316/eP6jVlBAaIt6VO1/jxmn/zv27P7Pp2HxEajLD90ra9Sj6/979O37X73w0n+vqOL/0lJyMVBFq0EGgDSD0oKAlu1/oHg4ugGzVCKqfouYuL1Xj676Iajr8AnJFricGqYc3Bw+Zi6BVUxsXLHAdL6QiYMPFNrwpIxHDsUhgtAMAopKDjQn4pPDF7P45QC4hSmc1eX8WgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n\n/* General */\n:root.yotsuba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.yotsuba #header-bar, :root.yotsuba #notifications {\nfont-size: 9pt;\ncolor: #B86;\n}\n:root.yotsuba #header-bar a, :root.yotsuba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.yotsuba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.yotsuba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.yotsuba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba #menu {\ncolor: #800000;\n}\n:root.yotsuba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 10pt;\n}\n:root.yotsuba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.yotsuba-b .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\nfont-size: 9pt;\ncolor: #89A;\n}\n:root.yotsuba-b #header-bar a, :root.yotsuba-b #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.yotsuba-b #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.yotsuba-b .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.yotsuba-b .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba-b #menu {\ncolor: #000;\n}\n:root.yotsuba-b .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 10pt;\n}\n:root.yotsuba-b .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba-b .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.futaba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.futaba #header-bar, :root.futaba #notifications {\nfont-size: 11pt;\ncolor: #B86;\n}\n:root.futaba #header-bar a, :root.futaba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.futaba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.futaba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.futaba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.futaba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.futaba #menu {\ncolor: #800000;\n}\n:root.futaba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 12pt;\n}\n:root.futaba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.futaba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.burichan .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.burichan #header-bar, :root.burichan #header-bar #notifications {\nfont-size: 11pt;\ncolor: #89A;\n}\n:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.burichan #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.burichan .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.burichan .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.burichan #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.burichan #menu {\ncolor: #000000;\n}\n:root.burichan .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 12pt;\n}\n:root.burichan .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.burichan .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.tomorrow .dialog {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n\n/* Header */\n:root.tomorrow #header-bar, :root.tomorrow #notifications {\nfont-size: 9pt;\ncolor: #C5C8C6;\n}\n:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\ncolor: #81A2BE;\n}\n\n/* Settings */\n:root.tomorrow #fourchanx-settings fieldset {\nborder-color: #111;\n}\n\n/* Quote */\n:root.tomorrow .backlink.deadlink {\ncolor: #81A2BE !important;\n}\n:root.tomorrow .inline {\nborder-color: #111;\nbackground-color: rgba(0, 0, 0, .14);\n}\n\n/* QR */\n.tomorrow #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n:root.tomorrow .qr-preview {\nbackground-color: rgba(255, 255, 255, .15);\n}\n:root.tomorrow #qr .field {\nbackground-color: rgb(26, 27, 29);\ncolor: rgb(197,200,198);\nborder-color: rgb(40, 41, 42);\n}\n:root.tomorrow #qr .field:focus {\nborder-color: rgb(129, 162, 190) !important;\nbackground-color: rgb(30,32,36);\n}\n\n/* Menu */\n:root.tomorrow #menu {\ncolor: #C5C8C6;\n}\n:root.tomorrow .entry {\nborder-bottom: 1px solid #111;\nfont-size: 10pt;\n}\n:root.tomorrow .focused.entry {\nbackground: rgba(0, 0, 0, .33);\n}\n\n/* Watcher Favicon */\n:root.tomorrow .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.photon .dialog {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.photon #header-bar, :root.photon #notifications {\nfont-size: 9pt;\ncolor: #333;\n}\n:root.photon #header-bar a, :root.photon #notifications a {\ncolor: #FF6600;\n}\n\n/* Settings */\n:root.photon #fourchanx-settings fieldset {\nborder-color: #CCC;\n}\n\n/* Quote */\n:root.photon .backlink.deadlink {\ncolor: #F60 !important;\n}\n:root.photon .inline {\nborder-color: #CCC;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.photon #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.photon #menu {\ncolor: #333;\n}\n:root.photon .entry {\nborder-bottom: 1px solid #CCC;\nfont-size: 10pt;\n}\n:root.photon .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.photon .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n" + css: "/* General */\n.dialog {\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder: 1px solid;\ndisplay: block;\npadding: 0;\n}\n.captcha-img,\n.field {\nbackground-color: #FFF;\nborder: 1px solid #CCC;\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\ncolor: #333;\nfont: 13px sans-serif;\noutline: none;\ntransition: color .25s, border-color .25s;\ntransition: color .25s, border-color .25s;\n}\n.field::-moz-placeholder,\n.field:hover::-moz-placeholder {\ncolor: #AAA !important;\nfont-size: 13px !important;\nopacity: 1.0 !important;\n}\n.captch-img:hover,\n.field:hover {\nborder-color: #999;\n}\n.field:hover, .field:focus {\ncolor: #000;\n}\n.field[disabled] {\nbackground-color: #F2F2F2;\ncolor: #888;\n}\n.move {\ncursor: move;\noverflow: hidden;\n}\nlabel, .favicon {\ncursor: pointer;\n}\na[href=\"javascript:;\"] {\ntext-decoration: none;\n}\n.warning {\ncolor: red;\n}\n#boardNavDesktop {\ndisplay: none !important;\n}\na {\noutline: none !important;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\ndisplay: block !important;\noverflow: visible !important;\n}\n[hidden] {\ndisplay: none !important;\n}\n\n/* fixed, z-index */\n#overlay,\n#fourchanx-settings,\n#qp, #ihover,\n#navlinks, .fixed #header-bar,\n:root.float #updater,\n:root.float #thread-stats,\n#qr {\nposition: fixed;\n}\n#fourchanx-settings {\nz-index: 999;\n}\n#overlay {\nz-index: 900;\n}\n#notifications {\nz-index: 70;\n}\n#qp, #ihover {\nz-index: 60;\n}\n#menu {\nz-index: 50;\n}\n#navlinks, #updater, #thread-stats {\nz-index: 40;\n}\n.fixed #header-bar.autohide {\nz-index: 35;\n}\n#qr {\nz-index: 30;\n}\n#watcher {\nz-index: 8;\n}\n:root.fixed-watcher #watcher {\nz-index: 20;\n}\n.fixed #header-bar {\nz-index: 10;\n}\n/* Header */\n.fixed.top body {\npadding-top: 2em;\n}\n.fixed.bottom body {\npadding-bottom: 2em;\n}\n.fixed #header-bar {\nright: 0;\nleft: 0;\npadding: 3px 4px 4px;\n}\n.fixed.top #header-bar {\ntop: 0;\n}\n.fixed.bottom #header-bar {\nbottom: 0;\n}\n#header-bar {\nborder-width: 0;\ntransition: all .1s .05s ease-in-out;\n}\n:root.centered-links #shortcuts {\nwidth: 300px;\ntext-align: right;\n}\n:root.centered-links #header-bar {\ntext-align: center;\n}\n:root.centered-links #custom-board-list {\nposition: relative;\nleft: 150px;\n}\n.fixed.top #header-bar {\nborder-bottom-width: 1px;\n}\n.fixed.bottom #header-bar {\nbox-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\nborder-top-width: 1px;\n}\n.fixed.bottom #header-bar .menu-button i {\nborder-top: none;\nborder-bottom: 6px solid;\n}\n#board-list {\ntext-align: center;\n}\n.fixed #header-bar.autohide:not(:hover) {\nbox-shadow: none;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar.autohide:not(:hover) {\nmargin-bottom: -1em;\n-webkit-transform: translateY(-100%);\ntransform: translateY(-100%);\n}\n.fixed.bottom #header-bar.autohide:not(:hover) {\n-webkit-transform: translateY(100%);\ntransform: translateY(100%);\n}\n#scroll-marker {\nleft: 0;\nright: 0;\nheight: 10px;\nposition: absolute;\n}\n#header-bar #scroll-marker {\ndisplay: none;\n}\n.fixed #header-bar #scroll-marker {\ndisplay: block;\n}\n.fixed.top #header-bar #scroll-marker {\ntop: 100%;\n}\n.fixed.bottom #header-bar #scroll-marker {\nbottom: 100%;\n}\n#header-bar a:not(.entry):not(.close) {\ntext-decoration: none;\npadding: 1px;\n}\n#header-bar input {\nmargin: 0;\nvertical-align: bottom;\n}\n#shortcuts:empty {\ndisplay: none;\n}\n.brackets-wrap::before {\ncontent: \"\\00a0[\";\n}\n.brackets-wrap::after {\ncontent: \"]\\00a0\";\n}\n.disabled,\n.expand-all-shortcut {\nopacity: .45;\n}\n#shortcuts {\nfloat: right;\n}\n.shortcut {\nmargin-left: 3px;\n}\n#navbotright,\n#navtopright {\ndisplay: none;\n}\n#toggleMsgBtn {\ndisplay: none !important;\n}\n.current {\nfont-weight: bold;\n}\n/* 4chan X link brackets */\n.fourchanx-link::after {\ncontent: \"]\";\n}\n.fourchanx-link::before {\ncontent: \"[\";\n}\n/* Notifications */\n#notifications {\nposition: fixed;\ntop: 0;\nheight: 0;\ntext-align: center;\nright: 0;\nleft: 0;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar #notifications {\nposition: absolute;\ntop: 100%;\n}\n.notification {\ncolor: #FFF;\nfont-weight: 700;\ntext-shadow: 0 1px 2px rgba(0, 0, 0, .5);\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder-radius: 2px;\nmargin: 1px auto;\nwidth: 500px;\nmax-width: 100%;\nposition: relative;\ntransition: all .25s ease-in-out;\n}\n.notification.error {\nbackground-color: hsla(0, 100%, 38%, .9);\n}\n.notification.warning {\nbackground-color: hsla(36, 100%, 38%, .9);\n}\n.notification.info {\nbackground-color: hsla(200, 100%, 38%, .9);\n}\n.notification.success {\nbackground-color: hsla(104, 100%, 38%, .9);\n}\n.notification a {\ncolor: white;\n}\n.notification > .close {\npadding: 6px;\ntop: 0;\nright: 5px;\nposition: absolute;\n}\n.message {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\npadding: 6px 20px;\nmax-height: 200px;\nwidth: 100%;\noverflow: auto;\n}\n\n/* Settings */\n:root.fourchan-x body {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\n}\n#overlay {\nbackground-color: rgba(0, 0, 0, .5);\ntop: 0;\nleft: 0;\nheight: 100%;\nwidth: 100%;\n}\n#fourchanx-settings {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nbox-shadow: 0 0 15px rgba(0, 0, 0, .15);\nheight: 600px;\nmax-height: 100%;\nwidth: 900px;\nmax-width: 100%;\nmargin: auto;\npadding: 3px;\ntop: 50%;\nleft: 50%;\n-moz-transform: translate(-50%, -50%);\n-webkit-transform: translate(-50%, -50%);\ntransform: translate(-50%, -50%);\n}\n#fourchanx-settings > nav {\npadding: 2px 2px 0;\nheight: 15px;\n}\n#fourchanx-settings > nav a {\ntext-decoration: underline;\n}\n#fourchanx-settings > nav a.close {\ntext-decoration: none;\npadding: 2px;\n}\n.section-container {\noverflow: auto;\nposition: absolute;\ntop: 2.1em;\nright: 5px;\nbottom: 5px;\nleft: 5px;\npadding-right: 5px;\n}\n.sections-list {\npadding: 0 3px;\nfloat: left;\n}\n.credits {\nfloat: right;\n}\n.tab-selected {\nfont-weight: 700;\n}\n.section-sauce ul,\n.section-advanced ul {\nlist-style: none;\nmargin: 0;\n}\n.section-sauce ul {\npadding: 8px;\n}\n.section-advanced ul {\npadding: 0px;\n}\n.section-sauce li,\n.section-advanced li {\npadding-left: 4px;\n}\n.section-main label {\ntext-decoration: underline;\n}\n.section-filter ul {\npadding: 0;\n}\n.section-filter li {\nmargin: 10px 40px;\n}\n.section-filter textarea {\nheight: 500px;\n}\n.section-sauce textarea {\nheight: 350px;\n}\n.section-advanced .field[name=\"boardnav\"] {\nwidth: 100%;\n}\n.section-advanced textarea {\nheight: 150px;\n}\n.section-advanced .archive-cell {\nmin-width: 160px;\ntext-align: center;\n}\n.section-advanced #archive-board-select {\nposition: absolute;\n}\n.section-advanced .note {\nfont-size: 0.8em;\nfont-style: italic;\nmargin-left: 10px;\n}\n.section-advanced .note code {\nfont-style: normal;\nfont-size: 11px;\n}\n.section-keybinds .field {\nfont-family: monospace;\n} \n#fourchanx-settings fieldset {\nborder: 1px solid;\nborder-radius: 3px;\n}\n#fourchanx-settings legend {\nfont-weight: 700;\n}\n#fourchanx-settings textarea {\nfont-family: monospace;\nmin-width: 100%;\nmax-width: 100%;\n}\n#fourchanx-settings code {\ncolor: #000;\nbackground-color: #FFF;\npadding: 0 2px;\n}\n.unscroll {\noverflow: hidden;\n}\n\n/* Announcement Hiding */\n:root.hide-announcement #globalMessage {\ndisplay: none;\n}\na.hide-announcement {\nfloat: left;\n}\n\n/* Unread */\n#unread-line {\nmargin: 0;\nborder-color: rgb(255,0,0);\n}\n\n/* Thread Updater */\n#updater {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n#updater > .move {\npadding: 5px 3px 0px;\nmargin-bottom: -3px;\n}\n#updater > div:last-child {\ntext-align: center;\n}\n#updater input[type=number] {\nwidth: 4em;\n}\n:root.float #updater {\npadding: 0px 3px;\n}\n.new {\ncolor: limegreen;\n}\n#update-status.new {\nmargin-right: 5px;\n}\n#update-timer {\ncursor: pointer;\n}\n\n/* Thread Watcher */\n#watcher {\nposition: absolute;\n}\n#watcher {\npadding-bottom: 3px;\noverflow: hidden;\nwhite-space: nowrap;\nmin-width: 120px;\nmax-height: 92%;\noverflow-y: auto;\n}\n:root.fixed-watcher #watcher {\nposition: fixed;\n}\n:root:not(.fixed-watcher) #watcher:not(:hover) {\nmax-height: 210px;\noverflow-y: hidden;\n}\n#watcher > .move {\npadding-top: 3px;\n}\n#watcher > div {\nmax-width: 250px;\noverflow: hidden;\npadding-left: 3px;\npadding-right: 3px;\ntext-overflow: ellipsis;\n}\n#watcher a {\ntext-decoration: none;\n}\n#watcher .move>.close {\nposition: absolute;\nright: 0px;\ntop: 0px;\npadding: 0px 4px;\n}\n.watch-thread-link {\npadding-top: 18px;\nwidth: 18px;\nheight: 0px;\ndisplay: inline-block;\nbackground-repeat: no-repeat;\nopacity: 0.2;\nposition: relative;\ntop: 1px;\n}\n.watch-thread-link.watched {\nopacity: 1;\n}\n\n/* Thread Stats */\n#thread-stats {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n:root.float #post-count, :root.float #file-count {\npointer-events: none;\n}\n:root.float #thread-stats {\npadding: 0px 3px;\n}\n\n/* Quote */\n.deadlink {\ntext-decoration: none !important;\n}\n.backlink.deadlink:not(.forwardlink),\n.quotelink.deadlink:not(.forwardlink) {\ntext-decoration: underline !important;\n}\n.inlined {\nopacity: .5;\n}\n#qp input, .forwarded {\ndisplay: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\ntext-decoration: none;\nborder-bottom: 1px dashed;\n}\n.filtered {\ntext-decoration: underline line-through;\n}\n:root.hide-backlinks .backlink.filtered {\ndisplay: none;\n}\n.inline {\nborder: 1px solid;\ndisplay: table;\nmargin: 2px 0;\n}\n.inline .post {\nborder: 0 !important;\nbackground-color: transparent !important;\ndisplay: table !important;\nmargin: 0 !important;\npadding: 1px 2px !important;\n}\n#qp > .opContainer::after {\ncontent: '';\nclear: both;\ndisplay: table;\n}\n#qp .post {\nborder: none;\nmargin: 0;\npadding: 2px 2px 5px;\n}\n#qp img {\nmax-height: 80vh;\nmax-width: 50vw;\n}\n.qphl {\noutline: 2px solid rgba(216, 94, 49, .7);\n}\n:root.highlight-own .yourPost>.reply,\n:root.highlight-you .quotesYou>.reply {\nborder-left: 2px solid rgba(221,0,0,.5);\n}\n/* Quote Threading */\n.threadContainer {\nmargin-left: 20px;\nborder-left: 1px solid rgba(128,128,128,.3);\n}\n.threadOP {\nclear: both;\n} \n\n/* File */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull,\n.expanded-image > .post > .file > .fileThumb > img[data-md5],\n:not(.expanded-image) > .post > .file > .fileThumb > .full-image {\ndisplay: none;\n}\n.expanding {\nopacity: .5;\n}\n:root.fit-height .full-image {\nmax-height: 100vh;\n}\n:root.fit-width .full-image {\nmax-width: 100%;\n}\n:root.gecko.fit-width .full-image {\nwidth: 100%;\n}\n#ihover {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nmax-height: 100%;\nmax-width: 75%;\npadding-bottom: 16px;\n}\n.fappeTyme .thread > .noFile,\n.fappeTyme .threadContainer > .noFile {\ndisplay: none;\n}\n\n/* Index/Reply Navigation */\n#navlinks {\nfont-size: 16px;\ntop: 25px;\nright: 10px;\n}\n\n/* Filter */\n.opContainer.filter-highlight {\nbox-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.filter-highlight > .reply {\nbox-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n\n/* Spoiler text */\n:root.reveal-spoilers s {\ncolor: white !important;\n}\n\n/* Thread & Reply Hiding */\n.hide-thread-button,\n.hide-reply-button {\nfloat: left;\nmargin-right: 2px;\n}\n.stub ~ * {\ndisplay: none !important;\n}\n.stub input {\ndisplay: inline-block;\n}\n\n/* QR */\n:root.hide-original-post-form #postForm,\n:root.hide-original-post-form .postingMode,\n:root.hide-original-post-form #togglePostForm,\n#qr.autohide:not(.has-focus):not(:hover) > form,\n.postingMode ~ #qr select,\n#file-n-submit:not(.has-file) #qr-filerm {\ndisplay: none;\n}\n#qr select,\n#dump-button,\n.remove,\n.captcha-img {\ncursor: pointer;\n}\n#qr {\nz-index: 20;\nposition: fixed;\npadding: 1px;\nborder: 1px solid transparent;\nmin-width: 300px;\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nmargin-bottom: 1px;\n}\n#qr .close {\nfloat: right;\npadding: 0 3px;\n}\n#qr .warning {\nmin-height: 1.6em;\nvertical-align: middle;\npadding: 0 1px;\nborder-width: 1px;\nborder-style: solid;\n}\n.qr-link-container {\ntext-align: center;\n}\n.persona {\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-button {\nwidth: 10%;\nmargin: 0;\nmargin-right: 4px;\nfont: 13px sans-serif;\npadding: 1px 0px 2px;\nopacity: 0.6;\n}\n.persona .field:not(#dump) {\nwidth: 95px;\nmin-width: 33.3%;\nmax-width: 33.3%;\n}\n#qr textarea.field {\nheight: 14.8em;\nmin-height: 9em;\n}\n#qr.has-captcha textarea.field {\nheight: 9em;\n}\ninput.field.tripped:not(:hover):not(:focus) {\ncolor: transparent !important;\ntext-shadow: none !important;\n}\n#qr textarea {\nresize: both;\n}\n.captcha-img {\nmargin: 0px;\ntext-align: center;\nbackground-image: #fff;\nfont-size: 0px;\nmin-height: 59px;\nmin-width: 302px;\n}\n.captcha-input {\nwidth: 100%;\nmargin: 1px 0 0;\n}\n.captcha-input.error:focus {\nborder-color: rgb(255,0,0) !important;\n}\n.field {\n-moz-box-sizing: border-box;\nmargin: 0px;\npadding: 2px 4px 3px;\n}\n#qr textarea {\nmin-width: 100%;\n}\n#qr [type='submit'] {\nwidth: 25%;\nvertical-align: top;\n}\n:root.webkit #qr [type='submit'] {\nheight: 24px;\n}\n/* Fake File Input */\n#qr-filename,\n.has-file #qr-no-file {\ndisplay: none;\n}\n#qr-no-file,\n.has-file #qr-filename {\ndisplay: inline-block;\npadding: 0px 4px;\nmargin-bottom: 2px;\noverflow: hidden;\ntext-overflow: ellipsis;\nmax-width: 88%;\n}\n#qr-no-file {\ncolor: #AAA;\n}\n#qr-filename-container {\n-moz-box-sizing: border-box;\ndisplay: inline-block;\nposition: relative;\nwidth: 100px;\nmin-width: 74.6%;\nmax-width: 74.6%;\nmargin-right: 0.4%;\nmargin-top: 1px;\noverflow: hidden;\npadding: 2px 1px 0;\nheight: 22px;\n}\n#qr-filename-container:hover {\ncursor: text;\n}\n#qr-extras-container {\nposition: absolute;\nright: 0px;\n}\n#qr-filerm {\nmargin-right: 2px;\nz-index: 2;\n}\n#file-n-submit {\nheight: 23px;\n}\n#qr input[type=file] {\nvisibility: hidden;\nposition: absolute;\n}\n/* Thread Select / Spoiler Label */\n#qr select {\nfloat: right;\n}\n#qr.has-spoiler .has-file #qr-spoiler-label {\nwidth: 6.7%;\nmin-width: 6.7%;\nmax-width: 6.7%;\ndisplay: inline-block;\ntext-align: center;\nvertical-align: top;\n}\n#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\ndisplay: none;\n}\n#qr.has-spoiler .has-file #qr-filename-container {\nmax-width: 67.9%;\nmin-width: 67.9%;\n}\n#qr-spoiler-label input {\nposition: relative;\ntop: 3px;\n}\n/* Dumping UI */\n.dump #dump-list-container {\ndisplay: block;\n}\n#dump-list-container {\ndisplay: none;\nposition: relative;\noverflow-y: hidden;\nmargin-top: 1px;\n}\n#dump-list {\noverflow-x: auto;\noverflow-y: hidden;\nwhite-space: nowrap;\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-list:hover {\noverflow-x: auto;\n}\n.qr-preview {\n-moz-box-sizing: border-box;\ncounter-increment: thumbnails;\ncursor: move;\ndisplay: inline-block;\nheight: 90px;\nwidth: 90px;\npadding: 2px;\nopacity: .5;\noverflow: hidden;\nposition: relative;\ntext-shadow: 0 1px 1px #000;\n-moz-transition: opacity .25s ease-in-out;\nvertical-align: top;\nbackground-size: cover;\n}\n.qr-preview:hover,\n.qr-preview:focus {\nopacity: .9;\n}\n.qr-preview::before {\ncontent: counter(thumbnails);\ncolor: #fff;\nposition: absolute;\ntop: 3px;\nright: 3px;\ntext-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.qr-preview#selected {\nopacity: 1;\n}\n.qr-preview.drag {\nbox-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.qr-preview.over {\nborder-color: #fff;\n}\n.qr-preview > span {\ncolor: #fff;\n}\n.remove {\nbackground: none;\ncolor: #e00;\nfont-weight: 700;\npadding: 3px;\n}\na:only-of-type > .remove {\ndisplay: none;\n}\n.remove:hover::after {\ncontent: \" Remove\";\n}\n.qr-preview > label {\nbackground: rgba(0,0,0,.5);\ncolor: #fff;\nright: 0;\nbottom: 0;\nleft: 0;\nposition: absolute;\ntext-align: center;\n}\n.qr-preview > label > input {\nmargin: 0;\n}\n#add-post {\ncursor: pointer;\nfont-size: 2em;\nposition: absolute;\ntop: 50%;\nright: 10px;\n-moz-transform: translateY(-50%);\n}\n.textarea {\nposition: relative;\n}\n:root.webkit .textarea {\nmargin-bottom: -2px;\n}\n#char-count {\ncolor: #000;\nbackground: hsla(0, 0%, 100%, .5);\nfont-size: 8pt;\nposition: absolute;\nbottom: 1px;\nright: 1px;\npointer-events: none;\n}\n\n/* Menu */\n.menu-button {\ndisplay: inline-block;\nposition: relative;\ncursor: pointer;\n}\n.menu-button i {\nborder-top: 6px solid;\nborder-right: 4px solid transparent;\nborder-left: 4px solid transparent;\ndisplay: inline-block;\nmargin: 2px;\nvertical-align: middle;\n}\n#menu {\nposition: fixed;\noutline: none;\n}\n.entry {\nborder-bottom: 1px solid rgba(0,0,0,.25);\ncursor: pointer;\ndisplay: block;\noutline: none;\npadding: 3px 7px;\nposition: relative;\ntext-decoration: none;\nwhite-space: nowrap;\n}\n.left>.entry.has-submenu {\npadding-right: 17px !important;\n}\n.entry:last-child {\nborder-bottom: 0;\n}\n.has-submenu::after {\ncontent: \"\";\nborder-left: .5em solid;\nborder-top: .3em solid transparent;\nborder-bottom: .3em solid transparent;\ndisplay: inline-block;\nmargin: .3em;\nposition: absolute;\nright: 3px;\n}\n.left .has-submenu::after {\nborder-left: 0;\nborder-right: .5em solid;\n}\n.submenu {\ndisplay: none;\nposition: absolute;\nleft: 100%;\ntop: -1px;\n}\n.focused .submenu {\ndisplay: block;\n}\n.imp-exp-result {\nposition: absolute;\ntext-align: center;\nmargin: auto;\nright: 0px;\nleft: 0px;\nwidth: 200px;\n}\n.export, .import {\ncursor: pointer;\ntext-decoration: none !important;\n}\n/* Link Title Favicons */\n.linkify.YouTube {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vimeo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAASJJREFUOE9jYAAC7ln7/pODQXrBmq333PvPu/YaSRikB6QXbACpmmHqsRoAMll7+20UQ0H8tmuv/pdffPFfZtNNuByGASBFIPDh5x+4IV6HHoDFYGDJgw+YBoBMBUkgA5BtIKduuvvy//svX+FSB+88wTTAc+/t/83bj/0HScLA5BPXwc7lKJ36f+L6XXDxhUfOYxrAPWUnWKFp9UQUm3iWQxSDXAEDSX3zcIcB96wD/x+8eA1XDNKMHAYg20GW4Y0FkCIYAAUqzEBQOIBciRzlWKMxZelOlMCEcVxq+jHSC1YDJPs3YBgA8jey0/F6ARRwsFAHORukmat9NdbUijMpg/wKcrJodDFOzSBXwA3Alh9AToZFI7a8Asu98BxJbnYGAJb5vYLDANzSAAAAAElFTkSuQmCC') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.SoundCloud {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.audio {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.LiveLeak {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAydJREFUOE9Nk1tIk2EYx79NyUNqTk0o6KYrnZeChodLDxfeZpCbJk4RXU5Nm7tYRYhiYXbQlaeGutyW2gxtpB1RIyKDEjKwA6Ti2dR5KNDn+fq/S6TBj/f93r3P732e53s/qfnkSdej4GB2SBLbwf+jmB+gUMgOheLg/z7EdCUnO6Ref392SpK8Hyh3I+gBwBo7lUp2xcbyQEoKD6alyQOpqd754/h4FjJXZCRJTl9ftmEzoK5/wdQJxPgkLY2WV1dpc2uLtnZ2eHNnhza3t2nd46GhjAzuValY6jx0iIfS03msoIDuQ9COQCtoUSjohU5HuwgaN5loeXycd3d3aW9vzwvW2K5SkdTi58fvzGb+3tdHFggA3QONEAzn59PvjQ1yqNX0zenkvX0B4ffWaGRraChJd/385JGqKvlzTw/fRqOaIGkEd1DjU52O/3g83BkTw5MOh7yJuUCUM2o0yi2hoSw1IIOhykr+YLNRHYKu4XQvyKA/N5c8yMCCDD7Z7bz26xcJ1rH2rKKCG0UJdRAMlJbyG6uVrkJQjWAB5tSbk0Nr2HwDgvcQiIYur6zQyvo6ucvLueHIEZKuQPBQr+dXra1kRuqXEOwFArtWSytra1QdFUVjNhvPLS3R3OIiLUDUD0F1WBhJJtwDW2Ehu5uaqBICI4IFlRB0QLCEzaboaHrd0cHzCBYsIIuesjK+LAQXkEFrXh676uupGCWcR6AeghLQptGQONUAwfOuLp6Zn6eZuTmaXVig7pISrhI90ENgQbdHhoep32JhFzLpu3WLio8epUYIfs7OUjF6UKJW88XERLqYkEBNej11oG8XhCAvMFAuOn5cNiclsTkhQTbhmpri4lgbEMANWi1DwC/xit3t7bK7rY0Fo4OD3G4wyEURESzloAdnceezlErK8vH5N4KzPj50PTOTfkxP0+THj/RlYoInJyZI8HVqim5qNFwQHk7SucBAPo2PKRMNPLM/4pnFszYkhJsNBu6uqWFHba1sr61lQSveQFZQkFx07BhJmhMnrLn4NLMPH/aSExR0QDbmWhwgyEapwDvXoDxdWBiXnjrV/Bdm2kYUxLwmEgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vocaroo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.pastebin {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAtZJREFUOE+NU91LWmEc7sJtQew/2MUY7INg7CLY3W5GMHazyzEQo9UmfYxZTbAiVlgRqLMSZ+XnDC3z2+Y0+8JGakKZTtR0Tl2wtgtLLQh29cz3ZZ3h3Q68vOc95zzP73l+z+/U1f292O09DRxubxOH23P//1bvtQts3dPnry7LZnXJhcUl5Avf8dHtwY+fv2AyW5DOfIXFakMm+w0G4wISyRRm55TQG0y/Wzv6mikJ52Xf9TmVBoFAAD6fDwqFAqFQCJubmzCbzZiensbp6SmkUikikQi0Wi0kEgm6ewVaStDCfXPDandifn6egoaGhrCzswO1Wg2Hw4HBwUGk02kIBAL4/X4IhUJMTk6ii8dfYggy2RwymQzOz88Rj8dRLpexv7+PSqWCYDCIQqGAra0tJBIJrK2t0XdVAjNDEIl+wfj4OEqlEq2wt7dHrchkMmrBYDCAz+fTIjweD7FYrJbgIJOlgLOzM8jlcip1eXmZ2rFarVAqlRCLxcjlchCJRFRljYJYPAG32418Pg+n04lsNouVlRUcHh7C4/FQIOlHNBqlezgcJgQWxkIgGMbExASVNjY2hvX1dVo9mUzS5wREFLhcLrqTcw2B//M2RkdHodPp4PV6oVKpqH+SCom3v7+fNnF4eJiJusbCJ6+PviSyScakiaR5RIHRaKQpmEwmbAdCeD8zB6vdhebHT8SMhcUlC83bbrdTJRsbG3RwiCVCRNJJpDIoVeNNJJJQzKryV+rrmxiCtyNCCmaz2VhdXQWXy6XDpNfrodFoYLXZUTw+pk222Z3lW3ca26rgSwzBwqIZAwMDlITMAVEwNTVFR5fEJpK8Qyp1AJvDVbrTeLenCmxgfiZ22+urCtWHyu7uLp2wVCpFKx0dHaFYLOLk5KT6Y9kgk89kb95ubK0BX7A8a+1qannRLeW0daj/rU51S3tn9dypfvDw0QiLxbpX/Z7FVK7e/AEj4Wf24/2f5AAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.gist {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqUkzuIE1EUhv955MnsbB6r4kYQLUQQFncV3SnCIqJsoWGDYOGjsIiCtY2Kla1sjLBIsFFcXJC1kaSwENQmXUQSRSUSjCQSTCbkbR4z47lXEgtBNwcu3DNzvvO8R8jlcj7LshKmaWqYQERRTAmCcEru9/sJr9er0QF92BJMAVGr1TQ6CeZAc7lcGAwGkyQAxpTLZU0eDoc8crfbRTgcRjAYRCQSYSmi1WpxY7fbjU6ng1gshmaziXg8zhnGIpVKWbquW9ls1mLZsaMoiqWq6lgnBxY55He/328Vi0XOMFZmqVMD4fF4QBAajcY48khY9JE4HA4enTGMFVkaTHmy+ZzD/5NSqYSNB484w1h55ODO3TVu4FXcWDywl24Cmp0e1WBhyuWELAtIf/qKUrWOONmev3Lpt4NRCXq1gplpBS/v3cDc0nGg9h1o1ZkfwO4Atu1B8cM7HLt8k37V/y5B2b4bJxf2Y+7oEbyJrkMvUjki0YYJ03LidfQxAt4dOHdCw5RdGZcgGobBlQtnV/BDr1GfDai7ZiHZZRi9PoY/e5SCCTUwC9gk1GmMh5YWOcNYkR4Sv1y9uAJbYB82N57h4OnDmN7phjQ0qUkWRJuB+TMaPn/5iFfvv+Ha7eucYey4iWw8q6tRJJNJ3Fp7ClUawEkViBTfkCR0YUNTVHD/4Tpm/P4/U2CeKpUKfD4fJDIMhUKEhP45St50XedZyLQY6Xw+v8AUemVb2oNqtYpCocCWKi2TLLfb7ReZTGZ+kmUi7i2VvfxLgAEAZChMriPcl+IAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.image {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.InstallGentoo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAklJREFUOE9jYEAAASBTCorZkcSRmTjVCDLziCwG4hfM3EIvGNm44oC6WNEM4WXi5FsEkmfhFX3BxMmfAJSHW9Qr55Px3aZp3X/btq3/hQydPzKysMcCFbBBDeFj4uBdqBJR/gskb1W34j+PmulLoJwbzBJJoMm7dNO7/ntMP/XfpW/v//SKvk+7tl7fvXfTpx5pCdWVSiHFv1wnHQbLi9sE/Wdk5SwBauaCGQB3gUPb5v+7Lr/8/+fvr/9fv/z+f+Pyr/9bV735l9Wy/79Dx/b/Nk0bsLoAHgbeAVHv/v77/f8f0IB7N7+cu3DuecK54z9+7lzz639e9pK/7HwSWMMA5BJwCJeXtOm/fvVj1fcfv369f//92cN7X6ZcPvf9x6Htv//vXP3r/+T245UEYgpskPTNq08LgN749/PH7/93rv/6f/rw7//nj//4f+bU0zQcUQwWBkdVbGz62y+fv3wHeeXrlz//H9798//qpY//M3KqfzGxc8djiWKwZnBUuWQ2/fr46fv/P39+///x/ff/d69//z97+s7fyMb5/+y7d2GLYriDZikFF/1qXXXj/4Pbv/8/f/jn/5MH316/eP6jVlBAaIt6VO1/jxmn/zv27P7Pp2HxEajLD90ra9Sj6/979O37X73w0n+vqOL/0lJyMVBFq0EGgDSD0oKAlu1/oHg4ugGzVCKqfouYuL1Xj676Iajr8AnJFricGqYc3Bw+Zi6BVUxsXLHAdL6QiYMPFNrwpIxHDsUhgtAMAopKDjQn4pPDF7P45QC4hSmc1eX8WgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n\n/* General */\n:root.yotsuba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.yotsuba #header-bar, :root.yotsuba #notifications {\nfont-size: 9pt;\ncolor: #B86;\n}\n:root.yotsuba #header-bar a, :root.yotsuba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.yotsuba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.yotsuba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.yotsuba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba #menu {\ncolor: #800000;\n}\n:root.yotsuba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 10pt;\n}\n:root.yotsuba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.yotsuba-b .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\nfont-size: 9pt;\ncolor: #89A;\n}\n:root.yotsuba-b #header-bar a, :root.yotsuba-b #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.yotsuba-b #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.yotsuba-b .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.yotsuba-b .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba-b #menu {\ncolor: #000;\n}\n:root.yotsuba-b .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 10pt;\n}\n:root.yotsuba-b .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba-b .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.futaba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.futaba #header-bar, :root.futaba #notifications {\nfont-size: 11pt;\ncolor: #B86;\n}\n:root.futaba #header-bar a, :root.futaba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.futaba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.futaba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.futaba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.futaba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.futaba #menu {\ncolor: #800000;\n}\n:root.futaba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 12pt;\n}\n:root.futaba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.futaba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.burichan .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.burichan #header-bar, :root.burichan #header-bar #notifications {\nfont-size: 11pt;\ncolor: #89A;\n}\n:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.burichan #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.burichan .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.burichan .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.burichan #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.burichan #menu {\ncolor: #000000;\n}\n:root.burichan .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 12pt;\n}\n:root.burichan .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.burichan .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.tomorrow .dialog {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n\n/* Header */\n:root.tomorrow #header-bar, :root.tomorrow #notifications {\nfont-size: 9pt;\ncolor: #C5C8C6;\n}\n:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\ncolor: #81A2BE;\n}\n\n/* Settings */\n:root.tomorrow #fourchanx-settings fieldset {\nborder-color: #111;\n}\n\n/* Quote */\n:root.tomorrow .backlink.deadlink {\ncolor: #81A2BE !important;\n}\n:root.tomorrow .inline {\nborder-color: #111;\nbackground-color: rgba(0, 0, 0, .14);\n}\n\n/* QR */\n.tomorrow #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n:root.tomorrow .qr-preview {\nbackground-color: rgba(255, 255, 255, .15);\n}\n:root.tomorrow #qr .field {\nbackground-color: rgb(26, 27, 29);\ncolor: rgb(197,200,198);\nborder-color: rgb(40, 41, 42);\n}\n:root.tomorrow #qr .field:focus {\nborder-color: rgb(129, 162, 190) !important;\nbackground-color: rgb(30,32,36);\n}\n\n/* Menu */\n:root.tomorrow #menu {\ncolor: #C5C8C6;\n}\n:root.tomorrow .entry {\nborder-bottom: 1px solid #111;\nfont-size: 10pt;\n}\n:root.tomorrow .focused.entry {\nbackground: rgba(0, 0, 0, .33);\n}\n\n/* Watcher Favicon */\n:root.tomorrow .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.photon .dialog {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.photon #header-bar, :root.photon #notifications {\nfont-size: 9pt;\ncolor: #333;\n}\n:root.photon #header-bar a, :root.photon #notifications a {\ncolor: #FF6600;\n}\n\n/* Settings */\n:root.photon #fourchanx-settings fieldset {\nborder-color: #CCC;\n}\n\n/* Quote */\n:root.photon .backlink.deadlink {\ncolor: #F60 !important;\n}\n:root.photon .inline {\nborder-color: #CCC;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.photon #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.photon #menu {\ncolor: #333;\n}\n:root.photon .entry {\nborder-bottom: 1px solid #CCC;\nfont-size: 10pt;\n}\n:root.photon .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.photon .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n" }; Main.init(); diff --git a/builds/crx/manifest.json b/builds/crx/manifest.json index a2cde2ba0..6770fe24c 100644 --- a/builds/crx/manifest.json +++ b/builds/crx/manifest.json @@ -15,7 +15,8 @@ "run_at": "document_start" }], "homepage_url": "http://seaweedchan.github.io/4chan-x/", - "minimum_chrome_version": "26", + "minimum_chrome_version": "27", + "minimum_opera_version": "15", "permissions": [ "storage" ] diff --git a/builds/crx/script.js b/builds/crx/script.js index 815cb2a97..c152e75c2 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.2.17 - 2013-06-18 +* 4chan X - Version 1.2.17 - 2013-07-21 * * Licensed under the MIT license. * https://github.com/seaweedchan/4chan-x/blob/master/LICENSE @@ -386,9 +386,9 @@ }; $.ready = function(fc) { - var cb, _ref; + var cb; - if ((_ref = d.readyState) === 'interactive' || _ref === 'complete') { + if (d.readyState !== 'loading') { $.queueTask(fc); return; } @@ -732,6 +732,14 @@ return (value < min ? min : value > max ? max : value); }; + $.item = function(key, val) { + var item; + + item = {}; + item[key] = val; + return item; + }; + $.syncing = {}; $.sync = (function() { @@ -749,14 +757,6 @@ }; })(); - $.item = function(key, val) { - var item; - - item = {}; - item[key] = val; - return item; - }; - $.localKeys = ['name', 'uniqueID', 'tripcode', 'capcode', 'email', 'subject', 'comment', 'flag', 'filename', 'dimensions', 'filesize', 'MD5', 'usercss']; $["delete"] = function(keys) { @@ -872,8 +872,8 @@ }; function Thread(ID, board) { + this.ID = ID; this.board = board; - this.ID = +ID; this.fullID = "" + this.board + "." + this.ID; this.posts = {}; g.threads[this.fullID] = board.threads[this] = this; @@ -896,7 +896,7 @@ }; function Post(root, thread, board, that) { - var alt, anchor, capcode, date, email, file, fileInfo, flag, info, name, post, size, subject, thumb, tripcode, uniqueID, unit; + var capcode, date, email, flag, info, name, post, subject, tripcode, uniqueID; this.thread = thread; this.board = board; @@ -915,6 +915,11 @@ quotelinks: [], backlinks: info.getElementsByClassName('backlink') }; + if (!(this.isReply = $.hasClass(post, 'reply'))) { + this.thread.OP = this; + this.thread.isSticky = !!$('.stickyIcon', info); + this.thread.isClosed = !!$('.closedIcon', info); + } this.info = {}; if (subject = $('.subject', info)) { this.nodes.subject = subject; @@ -940,7 +945,7 @@ this.nodes.capcode = capcode; this.info.capcode = capcode.textContent.replace('## ', ''); } - if (flag = $('.countryFlag', info)) { + if (flag = $('.flag, .countryFlag', info)) { this.nodes.flag = flag; this.info.flag = flag.title; } @@ -957,36 +962,7 @@ } this.parseComment(); this.parseQuotes(); - if ((file = $('.file', post)) && (thumb = $('img[data-md5]', file))) { - alt = thumb.alt; - anchor = thumb.parentNode; - fileInfo = file.firstElementChild; - this.file = { - info: fileInfo, - text: fileInfo.firstElementChild, - thumb: thumb, - URL: anchor.href, - size: alt.match(/[\d.]+\s\w+/)[0], - MD5: thumb.dataset.md5, - isSpoiler: $.hasClass(anchor, 'imgspoiler') - }; - size = +this.file.size.match(/[\d.]+/)[0]; - unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); - while (unit-- > 0) { - size *= 1024; - } - this.file.sizeInBytes = size; - this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; - this.file.name = $('span[title]', fileInfo).title.replace(/%22/g, '"'); - if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { - this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; - } - } - if (!(this.isReply = $.hasClass(post, 'reply'))) { - this.thread.OP = this; - this.thread.isSticky = !!$('.stickyIcon', this.nodes.info); - this.thread.isClosed = !!$('.closedIcon', this.nodes.info); - } + this.parseFile(that); this.clones = []; g.posts[this.fullID] = thread.posts[this] = board.posts[this] = this; if (that.isArchived) { @@ -995,7 +971,7 @@ } Post.prototype.parseComment = function() { - var bq, data, i, node, nodes, text, _i, _len, _ref; + var bq, i, node, nodes, text, _i, _len, _ref; bq = this.nodes.comment.cloneNode(true); _ref = $$('.abbr, .capcodeReplies, .exif, b', bq); @@ -1007,7 +983,7 @@ nodes = d.evaluate('.//br|.//text()', bq, null, 7, null); i = 0; while (i < nodes.snapshotLength) { - text.push((data = nodes.snapshotItem(i++).data) ? data : '\n'); + text.push(nodes.snapshotItem(i++).data || '\n'); } return this.info.comment = text.join('').trim().replace(/\s+$/gm, ''); }; @@ -1031,7 +1007,7 @@ continue; } this.nodes.quotelinks.push(quotelink); - if (quotelink.parentNode.parentNode.className === 'capcodeReplies') { + if (!this.isReply && $.hasClass(quotelink.parentNode.parentNode, 'capcodeReplies')) { continue; } quotes["" + (pathname.split('/')[1]) + "." + hash.slice(2)] = true; @@ -1042,6 +1018,38 @@ return this.quotes = Object.keys(quotes); }; + Post.prototype.parseFile = function(that) { + var alt, anchor, fileEl, fileInfo, size, thumb, unit; + + if (!((fileEl = $('.file', this.nodes.post)) && (thumb = $('img[data-md5]', fileEl)))) { + return; + } + alt = thumb.alt; + anchor = thumb.parentNode; + fileInfo = fileEl.firstElementChild; + this.file = { + info: fileInfo, + text: fileInfo.firstElementChild, + thumb: thumb, + URL: anchor.href, + size: alt.match(/[\d.]+\s\w+/)[0], + MD5: thumb.dataset.md5, + isSpoiler: $.hasClass(anchor, 'imgspoiler') + }; + size = +this.file.size.match(/[\d.]+/)[0]; + unit = ['B', 'KB', 'MB', 'GB'].indexOf(this.file.size.match(/\w+$/)[0]); + while (unit-- > 0) { + size *= 1024; + } + this.file.sizeInBytes = size; + this.file.thumbURL = that.isArchived ? thumb.src : "" + location.protocol + "//thumbs.4chan.org/" + this.board + "/thumb/" + (this.file.URL.match(/(\d+)\./)[1]) + "s.jpg"; + this.file.name = $('span[title]', fileInfo).title; + this.file.name = this.file.name.replace(/%22/g, '"'); + if (this.file.isImage = /(jpg|png|gif)$/i.test(this.file.name)) { + return this.file.dimensions = this.file.text.textContent.match(/\d+x\d+/)[0]; + } + }; + Post.prototype.kill = function(file, now) { var clone, quotelink, strong, _i, _j, _len, _len1, _ref, _ref1; @@ -1132,7 +1140,7 @@ _ref = this.clones.slice(index); for (_i = 0, _len = _ref.length; _i < _len; _i++) { clone = _ref[_i]; - clone.nodes.root.setAttribute('data-clone', index++); + clone.nodes.root.dataset.clone = index++; } }; @@ -1144,7 +1152,7 @@ __extends(Clone, _super); function Clone(origin, context) { - var file, index, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; + var file, info, inline, inlined, key, nodes, post, root, val, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _ref3; this.origin = origin; this.context = context; @@ -1220,8 +1228,7 @@ this.isDead = true; } this.isClone = true; - index = origin.clones.push(this) - 1; - root.setAttribute('data-clone', index); + root.dataset.clone = origin.clones.push(this) - 1; } return Clone; @@ -1543,9 +1550,7 @@ return; } $.asap((function() { - var _ref; - - return $.id('boardNavMobile') || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); + return $.id('boardNavMobile') || d.readyState !== 'loading'; }), Header.setBoardList); $.prepend(d.body, _this.bar); $.add(d.body, Header.hover); @@ -1615,7 +1620,7 @@ if (!text) { return; } - as = $$('#full-board-list a', Header.bar); + as = $$('#full-board-list a[title]', Header.bar); nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map(function(t) { var a, board, m, _i, _len; @@ -1646,7 +1651,7 @@ a = a.cloneNode(true); a.textContent = /-title/.test(t) || /-replace/.test(t) && $.hasClass(a, 'current') ? a.title : /-full/.test(t) ? "/" + board + "/ - " + a.title : (m = t.match(/-text:"(.+)"/)) ? m[1] : a.textContent; if (m = t.match(/-(index|catalog)/)) { - a.setAttribute('data-only', m[1]); + a.dataset.only = m[1]; a.href = "//boards.4chan.org/" + board + "/"; if (m[1] === 'catalog') { a.href += 'catalog'; @@ -1913,7 +1918,7 @@ capcodeStart = ''; capcode = ''; } - flag = flagCode ? ("  + flagCode + ") : ''; + flag = !flagCode ? '' : boardID === 'pol' ? "  + flagCode + " : " "; if (file != null ? file.isDeleted : void 0) { fileHTML = isOP ? ("
") + ("File deleted.") + "
" : ("
") + ("File deleted.") + "
"; } else if (file) { @@ -2002,11 +2007,11 @@ postFromNode: function(root) { return Get.postFromRoot($.x('ancestor::div[contains(@class,"postContainer")][1]', root)); }, - contextFromLink: function(quotelink) { + contextFromNode: function(quotelink) { return Get.postFromRoot($.x('ancestor::div[parent::div[@class="thread"]][1]', quotelink)); }, postDataFromLink: function(link) { - var boardID, path, postID, threadID; + var boardID, path, postID, threadID, _ref; if (link.hostname === 'boards.4chan.org') { path = link.pathname.split('/'); @@ -2014,9 +2019,8 @@ threadID = path[3]; postID = link.hash.slice(2); } else { - boardID = link.dataset.boardid; - threadID = link.dataset.threadid || 0; - postID = link.dataset.postid; + _ref = link.dataset, boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; + threadID || (threadID = 0); } return { boardID: boardID, @@ -2188,7 +2192,7 @@ } }); comment = bq.innerHTML.replace(/(^|>)(>[^<$]*)(<|$)/g, '$1$2$3').replace(/((>){2}(>\/[a-z\d]+\/)?\d+)/g, '$1'); - threadID = data.thread_num; + threadID = +data.thread_num; o = { postID: "" + postID, threadID: "" + threadID, @@ -2932,7 +2936,7 @@ href: 'javascript:;', textContent: text }); - el.setAttribute('data-type', type); + el.dataset.type = type; $.on(el, 'click', Filter.menu.makeFilter); return { el: el, @@ -3526,7 +3530,7 @@ innerHTML: " " + (type === 'hide' ? '-' : '+') + " ", href: 'javascript:;' }); - a.setAttribute('data-fullid', thread.fullID); + a.dataset.fullID = thread.fullID; $.on(a, 'click', ThreadHiding.toggle); return a; }, @@ -3554,7 +3558,7 @@ }, toggle: function(thread) { if (!(thread instanceof Thread)) { - thread = g.threads[this.dataset.fullid]; + thread = g.threads[this.dataset.fullID]; } if (thread.isHidden) { ThreadHiding.show(thread); @@ -3781,7 +3785,7 @@ } e.preventDefault(); _ref = Get.postDataFromLink(this), boardID = _ref.boardID, threadID = _ref.threadID, postID = _ref.postID; - context = Get.contextFromLink(this); + context = Get.contextFromNode(this); if ($.hasClass(this, 'inlined')) { QuoteInline.rm(this, boardID, threadID, postID, context); } else { @@ -3930,7 +3934,7 @@ className: 'dialog' }); $.add(Header.hover, qp); - Get.postClone(boardID, threadID, postID, qp, Get.contextFromLink(this)); + Get.postClone(boardID, threadID, postID, qp, Get.contextFromNode(this)); UI.hover({ root: this, el: qp, @@ -4254,9 +4258,11 @@ target: '_blank', textContent: "" + quote + "\u00A0(Dead)" }); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-threadid', post.thread.ID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + threadID: post.thread.ID, + postID: postID + }); } } else if (redirect = Redirect.to('thread', { boardID: boardID, @@ -4274,8 +4280,10 @@ postID: postID })) { $.addClass(a, 'quotelink'); - a.setAttribute('data-boardid', boardID); - a.setAttribute('data-postid', postID); + $.extend(a.dataset, { + boardID: boardID, + postID: postID + }); } } if (!this.quotes.contains(quoteID)) { @@ -4750,7 +4758,7 @@ } }, close: function() { - var i, _i, _len, _ref; + var post, _i, _len, _ref; if (QR.req) { QR.abort(); @@ -4766,10 +4774,10 @@ if (Conf['QR Shortcut']) { $.toggleClass($('.qr-shortcut'), 'disabled'); } - _ref = QR.posts; + _ref = QR.posts.splice(0, QR.posts.length, new QR.post(true)); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - i = _ref[_i]; - QR.posts[0].rm(); + post = _ref[_i]; + post["delete"](); } QR.cooldown.auto = false; return QR.status(); @@ -4835,12 +4843,13 @@ return QR.notifications = []; }, status: function() { - var disabled, status, value; + var disabled, status, thread, value; if (!QR.nodes) { return; } - if (g.DEAD) { + thread = QR.posts[0].thread; + if (thread !== 'new' && g.threads["" + g.BOARD + "." + thread].isDead) { value = 404; disabled = true; QR.cooldown.auto = false; @@ -5094,7 +5103,7 @@ } }, quote: function(e) { - var OP, caretPos, com, index, post, range, s, sel, selectionRoot, text, thread, _ref; + var caretPos, com, index, post, range, s, sel, text, thread, _ref; if (e != null) { e.preventDefault(); @@ -5103,11 +5112,9 @@ return; } sel = d.getSelection(); - selectionRoot = $.x('ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode); post = Get.postFromNode(this); - OP = Get.contextFromLink(this).thread.OP; text = ">>" + post + "\n"; - if ((s = sel.toString().trim()) && post.nodes.root === selectionRoot) { + if ((s = sel.toString().trim()) && post === Get.postFromNode(sel.anchorNode)) { s = s.replace(/\n/g, '\n>'); text += ">" + s + "\n"; } @@ -5120,7 +5127,7 @@ } _ref = QR.nodes, com = _ref.com, thread = _ref.thread; if (!com.value) { - thread.value = OP.ID; + thread.value = Get.contextFromNode(this).thread; } caretPos = com.selectionStart; com.value = com.value.slice(0, caretPos) + text + com.value.slice(com.selectionEnd); @@ -5193,7 +5200,7 @@ fileInput: function(files) { var file, length, max, post, _i, _len; - if (this instanceof Element) { + if (files instanceof Event) { files = __slice.call(this.files); QR.nodes.fileInput.value = null; } @@ -5296,7 +5303,7 @@ _Class.prototype.rm = function() { var index; - $.rm(this.nodes.el); + this["delete"](); index = QR.posts.indexOf(this); if (QR.posts.length === 1) { new QR.post(true); @@ -5305,9 +5312,11 @@ (QR.posts[index - 1] || QR.posts[index + 1]).select(); } QR.posts.splice(index, 1); - if (!window.URL) { - return; - } + return QR.status(); + }; + + _Class.prototype["delete"] = function() { + $.rm(this.nodes.el); return URL.revokeObjectURL(this.URL); }; @@ -5366,21 +5375,23 @@ }; _Class.prototype.save = function(input) { - var value, _ref; + var name, _ref; if (input.type === 'checkbox') { this.spoiler = input.checked; return; } - value = input.value; - this[input.dataset.name] = value; - if (input.nodeName !== 'TEXTAREA') { - return; - } - this.nodes.span.textContent = value; - QR.characterCount(); - if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { - return QR.cooldown.auto = false; + name = input.dataset.name; + this[name] = input.value; + switch (name) { + case 'thread': + return QR.status(); + case 'com': + this.nodes.span.textContent = this.com; + QR.characterCount(); + if (QR.cooldown.auto && this === QR.posts[0] && (0 < (_ref = QR.cooldown.seconds) && _ref <= 5)) { + return QR.cooldown.auto = false; + } } }; @@ -5404,9 +5415,7 @@ if (QR.spoiler) { this.nodes.label.hidden = false; } - if (window.URL) { - URL.revokeObjectURL(this.URL); - } + URL.revokeObjectURL(this.URL); this.showFileData(); if (!/^image/.test(file.type)) { this.nodes.el.style.backgroundImage = null; @@ -5415,22 +5424,10 @@ return this.setThumbnail(); }; - _Class.prototype.setThumbnail = function(fileURL) { - var img, reader, + _Class.prototype.setThumbnail = function() { + var fileURL, img, _this = this; - if (!window.URL) { - if (!fileURL) { - reader = new FileReader(); - reader.onload = function(e) { - return _this.setThumbnail(e.target.result); - }; - reader.readAsDataURL(this.file); - return; - } - } else { - fileURL = URL.createObjectURL(this.file); - } img = $.el('img'); img.onload = function() { var applyBlob, cv, data, height, i, l, s, ui8a, width, _i; @@ -5441,9 +5438,7 @@ } height = img.height, width = img.width; if (height < s || width < s) { - if (window.URL) { - _this.URL = fileURL; - } + _this.URL = fileURL; _this.nodes.el.style.backgroundImage = "url(" + _this.URL + ")"; return; } @@ -5458,11 +5453,6 @@ cv.height = img.height = height; cv.width = img.width = width; cv.getContext('2d').drawImage(img, 0, 0, width, height); - if (!window.URL) { - _this.nodes.el.style.backgroundImage = "url(" + (cv.toDataURL()) + ")"; - delete _this.URL; - return; - } URL.revokeObjectURL(fileURL); applyBlob = function(blob) { _this.URL = URL.createObjectURL(blob); @@ -5482,6 +5472,7 @@ type: 'image/png' })); }; + fileURL = URL.createObjectURL(this.file); return img.src = fileURL; }; @@ -5494,9 +5485,6 @@ this.nodes.label.hidden = true; } this.showFileData(); - if (!window.URL) { - return; - } return URL.revokeObjectURL(this.URL); }; @@ -5557,12 +5545,11 @@ _Class.prototype.drop = function() { var el, index, newIndex, oldIndex, post; - el = $('.drag', this.parentNode); - $.rmClass(el, 'drag'); $.rmClass(this, 'over'); if (!this.draggable) { return; } + el = $('.drag', this.parentNode); index = function(el) { return __slice.call(el.parentNode.children).indexOf(el); }; @@ -5570,7 +5557,8 @@ newIndex = index(this); (oldIndex < newIndex ? $.after : $.before)(this, el); post = QR.posts.splice(oldIndex, 1)[0]; - return QR.posts.splice(newIndex, 0, post); + QR.posts.splice(newIndex, 0, post); + return QR.status(); }; return _Class; @@ -5589,7 +5577,7 @@ }), this.ready.bind(this)); }, ready: function() { - var imgContainer, input, observer, setLifetime, + var imgContainer, input, setLifetime, _this = this; setLifetime = function(e) { @@ -5615,14 +5603,9 @@ img: imgContainer.firstChild, input: input }; - if (window.MutationObserver) { - observer = new MutationObserver(this.load.bind(this)); - observer.observe(this.nodes.challenge, { - childList: true - }); - } else { - $.on(this.nodes.challenge, 'DOMNodeInserted', this.load.bind(this)); - } + new MutationObserver(this.load.bind(this)).observe(this.nodes.challenge, { + childList: true + }); $.on(imgContainer, 'click', this.reload.bind(this)); $.on(input, 'keydown', this.keydown.bind(this)); $.on(input, 'focus', function() { @@ -5631,8 +5614,11 @@ $.on(input, 'blur', function() { return $.rmClass(QR.nodes.el, 'focus'); }); - $.get('captchas', [], function(item) { - return _this.sync(item['captchas']); + $.get('captchas', [], function(_arg) { + var captchas; + + captchas = _arg.captchas; + return _this.sync(captchas); }); $.sync('captchas', this.sync); this.reload(); @@ -5640,7 +5626,7 @@ return $.after(QR.nodes.com.parentNode, [imgContainer, input]); }, sync: function(captchas) { - this.captchas = captchas; + QR.captcha.captchas = captchas; return QR.captcha.count(); }, getOne: function() { @@ -5789,7 +5775,6 @@ QR.mimeTypes = mimeTypes.split(', '); QR.mimeTypes.push(''); nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value; - nodes.fileInput.accept = "text/*, " + mimeTypes; QR.spoiler = !!$('input[name=spoiler]'); if (QR.spoiler) { $.addClass(QR.nodes.el, 'has-spoiler'); @@ -6040,16 +6025,12 @@ post: post, isReply: isReply }); - if (threadID === postID) { - URL = "/" + g.BOARD + "/res/" + threadID; - } else if (g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab']) { - URL = "/" + g.BOARD + "/res/" + threadID + "#p" + postID; - } + URL = threadID === postID ? "/" + g.BOARD + "/res/" + threadID : g.VIEW === 'index' && !QR.cooldown.auto && Conf['Open Post in New Tab'] ? "/" + g.BOARD + "/res/" + threadID + "#p" + postID : void 0; if (URL) { if (Conf['Open Post in New Tab']) { - $.open("/" + g.BOARD + "/res/" + threadID); + $.open(URL); } else { - window.location = "/" + g.BOARD + "/res/" + threadID; + window.location = URL; } } return QR.status(); @@ -6403,7 +6384,7 @@ id: 'ihover', src: post.file.URL }); - el.setAttribute('data-fullid', post.fullID); + el.dataset.fullID = post.fullID; $.add(Header.hover, el); UI.hover({ root: this, @@ -6423,7 +6404,7 @@ if (!doc.contains(this)) { return; } - post = g.posts[this.dataset.fullid]; + post = g.posts[this.dataset.fullID]; src = this.src.split('/'); if (src[2] === 'images.4chan.org') { URL = Redirect.to('file', { @@ -6553,6 +6534,74 @@ } }; + Sauce = { + init: function() { + var err, link, links, _i, _len, _ref; + + if (g.VIEW === 'catalog' || !Conf['Sauce']) { + return; + } + links = []; + _ref = Conf['sauces'].split('\n'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + try { + if (link[0] !== '#') { + links.push(this.createSauceLink(link.trim())); + } + } catch (_error) { + err = _error; + } + } + if (!links.length) { + return; + } + this.links = links; + this.link = $.el('a', { + target: '_blank' + }); + return Post.prototype.callbacks.push({ + name: 'Sauce', + cb: this.node + }); + }, + createSauceLink: function(link) { + var m, text; + + link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { + switch (parameter) { + case '%TURL': + return "' + encodeURIComponent(post.file.thumbURL) + '"; + case '%URL': + return "' + encodeURIComponent(post.file.URL) + '"; + case '%MD5': + return "' + encodeURIComponent(post.file.MD5) + '"; + case '%board': + return "' + encodeURIComponent(post.board) + '"; + default: + return parameter; + } + }); + text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; + link = link.replace(/;text:.+$/, ''); + return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); + }, + node: function() { + var link, nodes, _i, _len, _ref; + + if (this.isClone || !this.file) { + return; + } + nodes = []; + _ref = Sauce.links; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); + } + return $.add(this.file.info, nodes); + } + }; + ArchiveLink = { init: function() { var div, entry, type, _i, _len, _ref; @@ -6693,8 +6742,8 @@ return; } $.off(this, 'click', DeleteLink["delete"]); - this.textContent = "Deleting " + this.textContent + "..."; fileOnly = $.hasClass(this, 'delete-file'); + this.textContent = "Deleting " + (fileOnly ? 'file' : 'post') + "..."; form = { mode: 'usrdel', onlyimgdel: fileOnly, @@ -6814,39 +6863,29 @@ node: function() { var button; - button = Menu.makeButton(this); if (this.isClone) { - $.replace($('.menu-button', this.nodes.info), button); - return; + button = $('.menu-button', this.nodes.info); + } else { + button = Menu.makeButton(this); + $.add(this.nodes.info, [$.tn('\u00A0'), button]); } - return $.add(this.nodes.info, [$.tn('\u00A0'), button]); + return $.on(button, 'click', Menu.toggle); }, makeButton: (function() { var a; a = null; - return function(post) { - var clone; - + return function() { a || (a = $.el('a', { className: 'menu-button fourchanx-link', innerHTML: '', href: 'javascript:;' })); - clone = a.cloneNode(true); - clone.setAttribute('data-postid', post.fullID); - if (post.isClone) { - clone.setAttribute('data-clone', true); - } - $.on(clone, 'click', Menu.toggle); - return clone; + return a.cloneNode(true); }; })(), toggle: function(e) { - var post; - - post = this.dataset.clone ? Get.postFromNode(this) : g.posts[this.dataset.postid]; - return Menu.menu.toggle(e, this, post); + return Menu.menu.toggle(e, this, Get.postFromNode(this)); } }; @@ -7267,7 +7306,7 @@ This saves bandwidth for both the user and the servers and avoid unnecessary computation. */ - _ref = [0, 304].contains(req.status) ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; + _ref = req.status === 304 ? [null, null] : ["" + req.statusText + " (" + req.status + ")", 'warning'], text = _ref[0], klass = _ref[1]; ThreadUpdater.set('status', text, klass); } if (ThreadUpdater.postID) { @@ -7685,23 +7724,21 @@ } }, scroll: function() { - var checkPosition, hash, onload, post, posts, prevID, root; + var checkPosition, hash, onload, post, posts, root; if ((hash = location.hash.match(/\d+/)) && hash[0] in Unread.thread.posts) { return; } if (Unread.posts.length) { - prevID = 0; - while (root = $.x('preceding-sibling::div[contains(@class,"postContainer")][1]', Unread.posts[0].nodes.root)) { - post = Get.postFromRoot(root); - if (prevID === post.ID) { - break; - } - prevID = post.ID; - if (!post.isHidden) { + post = Unread.posts[0]; + while (root = $.x('preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root)) { + if (!(post = Get.postFromRoot(root)).isHidden) { break; } } + if (!root) { + return; + } onload = function() { if (checkPosition(root)) { return root.scrollIntoView(false); @@ -7891,7 +7928,7 @@ post: {}, file: {}, init: function() { - var archive, arr, boardID, data, id, name, type, _i, _len, _ref, _ref1, _ref2, _ref3; + var archive, arr, boardID, data, id, name, type, _ref, _ref1, _ref2, _results; _ref = Conf['selectedArchives']; for (boardID in _ref) { @@ -7912,22 +7949,32 @@ } } _ref2 = Redirect.archives; + _results = []; for (name in _ref2) { archive = _ref2[name]; - _ref3 = archive.boards; - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - boardID = _ref3[_i]; - if (!(boardID in Redirect.thread)) { - Redirect.thread[boardID] = archive; + _results.push((function() { + var _i, _len, _ref3, _results1; + + _ref3 = archive.boards; + _results1 = []; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + boardID = _ref3[_i]; + if (!(boardID in Redirect.thread)) { + Redirect.thread[boardID] = archive; + } + if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { + Redirect.post[boardID] = archive; + } + if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { + _results1.push(Redirect.file[boardID] = archive); + } else { + _results1.push(void 0); + } } - if (!(boardID in Redirect.post || archive.software !== 'foolfuuka')) { - Redirect.post[boardID] = archive; - } - if (!(boardID in Redirect.file || !archive.files.contains(boardID))) { - Redirect.file[boardID] = archive; - } - } + return _results1; + })()); } + return _results; }, archives: { 'Foolz': { @@ -7935,7 +7982,7 @@ 'http': false, 'https': true, 'software': 'foolfuuka', - 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg'], + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vg', 'vp', 'vr', 'wsg'], 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg'] }, 'NSFW Foolz': { @@ -7969,14 +8016,6 @@ 'boards': ['c', 'w', 'wg'], 'files': ['c', 'w', 'wg'] }, - 'Love is Over': { - 'domain': 'loveisover.me', - 'http': true, - 'https': true, - 'software': 'foolfuuka', - 'boards': ['d', 'h', 'v'], - 'files': ['d', 'h', 'v'] - }, 'Foolz a Shit': { 'domain': 'archive.foolzashit.com', 'http': true, @@ -7988,7 +8027,7 @@ 'Install Gentoo': { 'domain': 'archive.installgentoo.net', 'http': true, - 'https': true, + 'https': false, 'software': 'fuuka', 'boards': ['diy', 'g', 'sci'], 'files': [] @@ -8015,6 +8054,14 @@ 'software': 'fuuka', 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'], 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr'] + }, + 'worldathleticproject': { + 'domain': 'fuuka.worldathleticproject.org', + 'http': true, + 'https': true, + 'software': 'foolfuuka', + 'boards': ['e', 'h', 'p', 's', 'u'], + 'files': ['e', 'h', 'p', 's', 'u'] } }, to: function(dest, data) { @@ -8886,13 +8933,13 @@ } break; case Conf['Next thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(+1); break; case Conf['Previous thread']: - if (g.VIEW === 'thread') { + if (g.VIEW !== 'index') { return; } Nav.scroll(-1); @@ -9164,10 +9211,9 @@ _ref = Nav.getThread(true), threads = _ref[0], thread = _ref[1], i = _ref[2], rect = _ref[3], topMargin = _ref[4]; top = rect.top - topMargin; - if (!((delta === -1 && Math.ceil(top) < 0) || (delta === +1 && top > 1))) { - i += delta; + if ((delta === -1 && top > -5) || (delta === +1 && top < 5)) { + top = ((_ref1 = threads[i + delta]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; } - top = ((_ref1 = threads[i]) != null ? _ref1.getBoundingClientRect().top : void 0) - topMargin; return window.scrollBy(0, top); } }; @@ -9314,76 +9360,6 @@ } }; - Sauce = { - init: function() { - var err, link, links, _i, _len, _ref; - - if (g.VIEW === 'catalog' || !Conf['Sauce']) { - return; - } - links = []; - _ref = Conf['sauces'].split('\n'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - if (link[0] === '#') { - continue; - } - try { - links.push(this.createSauceLink(link.trim())); - } catch (_error) { - err = _error; - continue; - } - } - if (!links.length) { - return; - } - this.links = links; - this.link = $.el('a', { - target: '_blank' - }); - return Post.prototype.callbacks.push({ - name: 'Sauce', - cb: this.node - }); - }, - createSauceLink: function(link) { - var m, text; - - link = link.replace(/%(T?URL|MD5|board)/ig, function(parameter) { - switch (parameter) { - case '%TURL': - return "' + encodeURIComponent(post.file.thumbURL) + '"; - case '%URL': - return "' + encodeURIComponent(post.file.URL) + '"; - case '%MD5': - return "' + encodeURIComponent(post.file.MD5) + '"; - case '%board': - return "' + encodeURIComponent(post.board) + '"; - default: - return parameter; - } - }); - text = (m = link.match(/;text:(.+)$/)) ? m[1] : link.match(/(\w+)\.\w+\//)[1]; - link = link.replace(/;text:.+$/, ''); - return Function('post', 'a', "a.href = '" + link + "';\na.textContent = '" + text + "';\nreturn a;"); - }, - node: function() { - var link, nodes, _i, _len, _ref; - - if (this.isClone || !this.file) { - return; - } - nodes = []; - _ref = Sauce.links; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - link = _ref[_i]; - nodes.push($.tn('\u00A0'), link(this, Sauce.link.cloneNode(true))); - } - return $.add(this.file.info, nodes); - } - }; - Time = { init: function() { if (g.VIEW === 'catalog' || !Conf['Time Formatting']) { @@ -9890,7 +9866,7 @@ $.add(div, ta); return; } - return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; + return div.innerHTML = "
Filter is disabled.

\nUse regular expressions, one per line.
\nLines starting with a # will be ignored.
\nFor example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
\nMD5 filtering uses exact string matching, not regular expressions.\n

"; }, sauce: function(section) { var ta; @@ -10175,9 +10151,7 @@ $.get(Conf, Main.initFeatures); $.on(d, '4chanMainInit', Main.initStyle); return $.asap((function() { - var _ref; - - return d.head && $('link[rel="shortcut icon"]', d.head) || ((_ref = d.readyState) === 'interactive' || _ref === 'complete'); + return d.head && $('link[rel="shortcut icon"]', d.head) || d.readyState !== 'loading'; }), Main.initStyle); }, initFeatures: function(items) { @@ -10303,7 +10277,7 @@ return $.ready(Main.initReady); }, initStyle: function() { - var mainStyleSheet, observer, setStyle, style, styleSheets, _ref; + var mainStyleSheet, setStyle, style, styleSheets, _ref; $.off(d, '4chanMainInit', Main.initStyle); if (!Main.isThisPageLegit() || $.hasClass(doc, 'fourchan-x')) { @@ -10341,18 +10315,13 @@ if (!mainStyleSheet) { return; } - if (window.MutationObserver) { - observer = new MutationObserver(setStyle); - return observer.observe(mainStyleSheet, { - attributes: true, - attributeFilter: ['href'] - }); - } else { - return $.on(mainStyleSheet, 'DOMAttrModified', setStyle); - } + return new MutationObserver(setStyle).observe(mainStyleSheet, { + attributes: true, + attributeFilter: ['href'] + }); }, initReady: function() { - var board, boardChild, err, errors, href, passLink, posts, styleSelector, thread, threadChild, threads, _i, _j, _len, _len1, _ref, _ref1; + var board, err, errors, href, passLink, postRoot, posts, styleSelector, thread, threadRoot, threads, _i, _j, _len, _len1, _ref, _ref1; if (d.title === '4chan - 404 Not Found') { if (Conf['404 Redirect'] && g.VIEW === 'thread') { @@ -10371,29 +10340,23 @@ if (board = $('.board')) { threads = []; posts = []; - _ref = board.children; + _ref = $$('.board > .thread', board); for (_i = 0, _len = _ref.length; _i < _len; _i++) { - boardChild = _ref[_i]; - if (!$.hasClass(boardChild, 'thread')) { - continue; - } - thread = new Thread(boardChild.id.slice(1), g.BOARD); + threadRoot = _ref[_i]; + thread = new Thread(+threadRoot.id.slice(1), g.BOARD); threads.push(thread); - _ref1 = boardChild.children; + _ref1 = $$('.thread > .postContainer', threadRoot); for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - threadChild = _ref1[_j]; - if (!$.hasClass(threadChild, 'postContainer')) { - continue; - } + postRoot = _ref1[_j]; try { - posts.push(new Post(threadChild, thread, g.BOARD)); + posts.push(new Post(postRoot, thread, g.BOARD)); } catch (_error) { err = _error; if (!errors) { errors = []; } errors.push({ - message: "Parsing of Post No." + (threadChild.id.match(/\d+/)) + " failed. Post will be skipped.", + message: "Parsing of Post No." + (postRoot.id.match(/\d+/)) + " failed. Post will be skipped.", error: err }); } @@ -10581,11 +10544,11 @@ var _ref; if (!('thisPageIsLegit' in Main)) { - Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error'); + Main.thisPageIsLegit = location.hostname === 'boards.4chan.org' && !$('link[href*="favicon-status.ico"]', d.head) && ((_ref = d.title) !== '4chan - Temporarily Offline' && _ref !== '4chan - Error' && _ref !== '504 Gateway Time-out'); } return Main.thisPageIsLegit; }, - css: "/* General */\n.dialog {\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder: 1px solid;\ndisplay: block;\npadding: 0;\n}\n.captcha-img,\n.field {\nbackground-color: #FFF;\nborder: 1px solid #CCC;\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\ncolor: #333;\nfont: 13px sans-serif;\noutline: none;\ntransition: color .25s, border-color .25s;\ntransition: color .25s, border-color .25s;\n}\n.field::-moz-placeholder,\n.field:hover::-moz-placeholder {\ncolor: #AAA !important;\nfont-size: 13px !important;\nopacity: 1.0 !important;\n}\n.captch-img:hover,\n.field:hover {\nborder-color: #999;\n}\n.field:hover, .field:focus {\ncolor: #000;\n}\n.field[disabled] {\nbackground-color: #F2F2F2;\ncolor: #888;\n}\n.move {\ncursor: move;\noverflow: hidden;\n}\nlabel, .favicon {\ncursor: pointer;\n}\na[href=\"javascript:;\"] {\ntext-decoration: none;\n}\n.warning {\ncolor: red;\n}\n#boardNavDesktop {\ndisplay: none !important;\n}\na {\noutline: none !important;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\ndisplay: block !important;\noverflow: visible !important;\n}\n[hidden] {\ndisplay: none !important;\n}\n\n/* fixed, z-index */\n#overlay,\n#fourchanx-settings,\n#qp, #ihover,\n#navlinks, .fixed #header-bar,\n:root.float #updater,\n:root.float #thread-stats,\n#qr {\nposition: fixed;\n}\n#fourchanx-settings {\nz-index: 999;\n}\n#overlay {\nz-index: 900;\n}\n#notifications {\nz-index: 70;\n}\n#qp, #ihover {\nz-index: 60;\n}\n#menu {\nz-index: 50;\n}\n#navlinks, #updater, #thread-stats {\nz-index: 40;\n}\n.fixed #header-bar.autohide {\nz-index: 35;\n}\n#qr {\nz-index: 30;\n}\n#watcher {\nz-index: 8;\n}\n:root.fixed-watcher #watcher {\nz-index: 20;\n}\n.fixed #header-bar {\nz-index: 10;\n}\n/* Header */\n.fixed.top body {\npadding-top: 2em;\n}\n.fixed.bottom body {\npadding-bottom: 2em;\n}\n.fixed #header-bar {\nright: 0;\nleft: 0;\npadding: 3px 4px 4px;\n}\n.fixed.top #header-bar {\ntop: 0;\n}\n.fixed.bottom #header-bar {\nbottom: 0;\n}\n#header-bar {\nborder-width: 0;\ntransition: all .1s .05s ease-in-out;\n}\n:root.centered-links #shortcuts {\nwidth: 300px;\ntext-align: right;\n}\n:root.centered-links #header-bar {\ntext-align: center;\n}\n:root.centered-links #custom-board-list {\nposition: relative;\nleft: 150px;\n}\n.fixed.top #header-bar {\nborder-bottom-width: 1px;\n}\n.fixed.bottom #header-bar {\nbox-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\nborder-top-width: 1px;\n}\n.fixed.bottom #header-bar .menu-button i {\nborder-top: none;\nborder-bottom: 6px solid;\n}\n#board-list {\ntext-align: center;\n}\n.fixed #header-bar.autohide:not(:hover) {\nbox-shadow: none;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar.autohide:not(:hover) {\nmargin-bottom: -1em;\n-webkit-transform: translateY(-100%);\ntransform: translateY(-100%);\n}\n.fixed.bottom #header-bar.autohide:not(:hover) {\n-webkit-transform: translateY(100%);\ntransform: translateY(100%);\n}\n#scroll-marker {\nleft: 0;\nright: 0;\nheight: 10px;\nposition: absolute;\n}\n#header-bar #scroll-marker {\ndisplay: none;\n}\n.fixed #header-bar #scroll-marker {\ndisplay: block;\n}\n.fixed.top #header-bar #scroll-marker {\ntop: 100%;\n}\n.fixed.bottom #header-bar #scroll-marker {\nbottom: 100%;\n}\n#header-bar a:not(.entry):not(.close) {\ntext-decoration: none;\npadding: 1px;\n}\n#header-bar input {\nmargin: 0;\nvertical-align: bottom;\n}\n#shortcuts:empty {\ndisplay: none;\n}\n.brackets-wrap::before {\ncontent: \"\\00a0[\";\n}\n.brackets-wrap::after {\ncontent: \"]\\00a0\";\n}\n.disabled,\n.expand-all-shortcut {\nopacity: .45;\n}\n#shortcuts {\nfloat: right;\n}\n.shortcut {\nmargin-left: 3px;\n}\n#navbotright,\n#navtopright {\ndisplay: none;\n}\n#toggleMsgBtn {\ndisplay: none !important;\n}\n.current {\nfont-weight: bold;\n}\n/* 4chan X link brackets */\n.fourchanx-link::after {\ncontent: \"]\";\n}\n.fourchanx-link::before {\ncontent: \"[\";\n}\n/* Notifications */\n#notifications {\nposition: fixed;\ntop: 0;\nheight: 0;\ntext-align: center;\nright: 0;\nleft: 0;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar #notifications {\nposition: absolute;\ntop: 100%;\n}\n.notification {\ncolor: #FFF;\nfont-weight: 700;\ntext-shadow: 0 1px 2px rgba(0, 0, 0, .5);\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder-radius: 2px;\nmargin: 1px auto;\nwidth: 500px;\nmax-width: 100%;\nposition: relative;\ntransition: all .25s ease-in-out;\n}\n.notification.error {\nbackground-color: hsla(0, 100%, 38%, .9);\n}\n.notification.warning {\nbackground-color: hsla(36, 100%, 38%, .9);\n}\n.notification.info {\nbackground-color: hsla(200, 100%, 38%, .9);\n}\n.notification.success {\nbackground-color: hsla(104, 100%, 38%, .9);\n}\n.notification a {\ncolor: white;\n}\n.notification > .close {\npadding: 6px;\ntop: 0;\nright: 5px;\nposition: absolute;\n}\n.message {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\npadding: 6px 20px;\nmax-height: 200px;\nwidth: 100%;\noverflow: auto;\n}\n\n/* Settings */\n:root.fourchan-x body {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\n}\n#overlay {\nbackground-color: rgba(0, 0, 0, .5);\ntop: 0;\nleft: 0;\nheight: 100%;\nwidth: 100%;\n}\n#fourchanx-settings {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nbox-shadow: 0 0 15px rgba(0, 0, 0, .15);\nheight: 600px;\nmin-height: 0;\nmax-height: 100%;\nwidth: 900px;\nmin-width: 0;\nmax-width: 100%;\nmargin: auto;\npadding: 3px;\ntop: 50%;\nleft: 50%;\n-moz-transform: translate(-50%, -50%);\n-webkit-transform: translate(-50%, -50%);\n-o-transform: translate(-50%, -50%);\ntransform: translate(-50%, -50%);\n}\n#fourchanx-settings > nav {\npadding: 2px 2px 0;\nheight: 15px;\n}\n#fourchanx-settings > nav a {\ntext-decoration: underline;\n}\n#fourchanx-settings > nav a.close {\ntext-decoration: none;\npadding: 2px;\n}\n.section-container {\noverflow: auto;\nposition: absolute;\ntop: 2.1em;\nright: 5px;\nbottom: 5px;\nleft: 5px;\npadding-right: 5px;\n}\n.sections-list {\npadding: 0 3px;\nfloat: left;\n}\n.credits {\nfloat: right;\n}\n.tab-selected {\nfont-weight: 700;\n}\n.section-sauce ul,\n.section-advanced ul {\nlist-style: none;\nmargin: 0;\n}\n.section-sauce ul {\npadding: 8px;\n}\n.section-advanced ul {\npadding: 0px;\n}\n.section-sauce li,\n.section-advanced li {\npadding-left: 4px;\n}\n.section-main label {\ntext-decoration: underline;\n}\n.section-filter ul {\npadding: 0;\n}\n.section-filter li {\nmargin: 10px 40px;\n}\n.section-filter textarea {\nheight: 500px;\n}\n.section-sauce textarea {\nheight: 350px;\n}\n.section-advanced .field[name=\"boardnav\"] {\nwidth: 100%;\n}\n.section-advanced textarea {\nheight: 150px;\n}\n.section-advanced .archive-cell {\nmin-width: 160px;\ntext-align: center;\n}\n.section-advanced #archive-board-select {\nposition: absolute;\n}\n.section-advanced .note {\nfont-size: 0.8em; \nfont-style: italic; \nmargin-left: 10px;\n}\n.section-advanced .note code {\nfont-style: normal;\nfont-size: 11px;\n}\n#fourchanx-settings fieldset {\nborder: 1px solid;\nborder-radius: 3px;\n}\n#fourchanx-settings legend {\nfont-weight: 700;\n}\n#fourchanx-settings textarea {\nfont-family: monospace;\nmin-width: 100%;\nmax-width: 100%;\n}\n#fourchanx-settings code {\ncolor: #000;\nbackground-color: #FFF;\npadding: 0 2px;\n}\n.unscroll {\noverflow: hidden;\n}\n\n/* Announcement Hiding */\n:root.hide-announcement #globalMessage {\ndisplay: none;\n}\na.hide-announcement {\nfloat: left;\n}\n\n/* Unread */\n#unread-line {\nmargin: 0;\nborder-color: rgb(255,0,0);\n}\n\n/* Thread Updater */\n#updater {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n#updater > .move {\npadding: 5px 3px 0px;\nmargin-bottom: -3px;\n}\n#updater > div:last-child {\ntext-align: center;\n}\n#updater input[type=number] {\nwidth: 4em;\n}\n:root.float #updater {\npadding: 0px 3px;\n}\n.new {\ncolor: limegreen;\n}\n#update-status.new {\nmargin-right: 5px;\n}\n#update-timer {\ncursor: pointer;\n}\n\n/* Thread Watcher */\n#watcher {\nposition: absolute;\n}\n#watcher {\npadding-bottom: 3px;\noverflow: hidden;\nwhite-space: nowrap;\nmin-width: 120px;\nmax-height: 92%;\noverflow-y: auto;\n}\n:root.fixed-watcher #watcher {\nposition: fixed;\n}\n:root:not(.fixed-watcher) #watcher:not(:hover) {\nmax-height: 210px;\noverflow-y: hidden;\n}\n#watcher > .move {\npadding-top: 3px;\n}\n#watcher > div {\nmax-width: 250px;\noverflow: hidden;\npadding-left: 3px;\npadding-right: 3px;\ntext-overflow: ellipsis;\n}\n#watcher a {\ntext-decoration: none;\n}\n#watcher .move>.close {\nposition: absolute;\nright: 0px;\ntop: 0px;\npadding: 0px 4px;\n}\n.watch-thread-link {\npadding-top: 18px;\nwidth: 18px;\nheight: 0px;\ndisplay: inline-block;\nbackground-repeat: no-repeat;\nopacity: 0.2;\nposition: relative;\ntop: 1px;\n}\n.watch-thread-link.watched {\nopacity: 1;\n}\n\n/* Thread Stats */\n#thread-stats {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n:root.float #post-count, :root.float #file-count {\npointer-events: none;\n}\n:root.float #thread-stats {\npadding: 0px 3px;\n}\n\n/* Quote */\n.deadlink {\ntext-decoration: none !important;\n}\n.backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) {\ntext-decoration: underline !important;\n}\n.inlined {\nopacity: .5;\n}\n#qp input, .forwarded {\ndisplay: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\ntext-decoration: none;\nborder-bottom: 1px dashed;\n}\n.filtered {\ntext-decoration: underline line-through;\n}\n:root.hide-backlinks .backlink.filtered {\ndisplay: none;\n}\n.inline {\nborder: 1px solid;\ndisplay: table;\nmargin: 2px 0;\n}\n.inline .post {\nborder: 0 !important;\nbackground-color: transparent !important;\ndisplay: table !important;\nmargin: 0 !important;\npadding: 1px 2px !important;\n}\n#qp > .opContainer::after {\ncontent: '';\nclear: both;\ndisplay: table;\n}\n#qp .post {\nborder: none;\nmargin: 0;\npadding: 2px 2px 5px;\n}\n#qp img {\nmax-height: 300px;\nmax-width: 500px;\nmax-height: 80vh;\nmax-width: 50vw;\n}\n.qphl {\noutline: 2px solid rgba(216, 94, 49, .7);\n}\n:root.highlight-own .yourPost>.reply,\n:root.highlight-you .quotesYou>.reply {\nborder-left: 2px solid rgba(221,0,0,.5);\n}\n/* Quote Threading */\n.threadContainer {\nmargin-left: 20px;\nborder-left: 1px solid rgba(128,128,128,.3);\n}\n.threadOP {\nclear: both;\n} \n\n/* File */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull,\n.expanded-image > .post > .file > .fileThumb > img[data-md5],\n:not(.expanded-image) > .post > .file > .fileThumb > .full-image {\ndisplay: none;\n}\n.expanding {\nopacity: .5;\n}\n:root.fit-height .full-image {\nmax-height: 100vh;\n}\n:root.fit-width .full-image {\nmax-width: 100%;\n}\n:root.gecko.fit-width .full-image,\n:root.presto.fit-width .full-image {\nwidth: 100%;\n}\n#ihover {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nmax-height: 100%;\nmax-width: 75%;\npadding-bottom: 16px;\n}\n.fappeTyme .thread > .noFile,\n.fappeTyme .threadContainer > .noFile {\ndisplay: none;\n}\n\n/* Index/Reply Navigation */\n#navlinks {\nfont-size: 16px;\ntop: 25px;\nright: 10px;\n}\n\n/* Filter */\n.opContainer.filter-highlight {\nbox-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.filter-highlight > .reply {\nbox-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n\n/* Spoiler text */\n:root.reveal-spoilers s {\ncolor: white !important;\n}\n\n/* Thread & Reply Hiding */\n.hide-thread-button,\n.hide-reply-button {\nfloat: left;\nmargin-right: 2px;\n}\n.stub ~ * {\ndisplay: none !important;\n}\n.stub input {\ndisplay: inline-block;\n}\n\n/* QR */\n:root.hide-original-post-form #postForm,\n:root.hide-original-post-form .postingMode,\n:root.hide-original-post-form #togglePostForm,\n#qr.autohide:not(.has-focus):not(:hover) > form,\n.postingMode ~ #qr select,\n#file-n-submit:not(.has-file) #qr-filerm {\ndisplay: none;\n}\n#qr select, #dump-button, .remove, .captcha-img {\ncursor: pointer;\n}\n#qr {\nz-index: 20;\nposition: fixed;\npadding: 1px;\nborder: 1px solid transparent;\nmin-width: 300px;\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nmargin-bottom: 1px;\n}\n#qr .close {\nfloat: right;\npadding: 0 3px;\n}\n#qr .warning {\nmin-height: 1.6em;\nvertical-align: middle;\npadding: 0 1px;\nborder-width: 1px;\nborder-style: solid;\n}\n.qr-link-container {\ntext-align: center;\n}\n.persona {\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-button {\nwidth: 10%;\nmargin: 0;\nmargin-right: 4px;\nfont: 13px sans-serif;\npadding: 1px 0px 2px;\nopacity: 0.6;\n}\n.persona .field:not(#dump) {\nwidth: 95px;\nmin-width: 33.3%;\nmax-width: 33.3%;\n}\n#qr textarea.field {\nheight: 14.8em;\nmin-height: 9em;\n}\n#qr.has-captcha textarea.field {\nheight: 9em;\n}\ninput.field.tripped:not(:hover):not(:focus) {\ncolor: transparent !important; text-shadow: none !important;\n}\n#qr textarea {\nresize: both;\n}\n.captcha-img {\nmargin: 0px;\ntext-align: center;\nbackground-image: #fff;\nfont-size: 0px;\nmin-height: 59px;\nmin-width: 302px;\n}\n.captcha-input {\nwidth: 100%;\nmargin: 1px 0 0;\n}\n.captcha-input.error:focus {\nborder-color: rgb(255,0,0) !important;\n}\n.field {\n-moz-box-sizing: border-box;\nmargin: 0px;\npadding: 2px 4px 3px;\n}\n#qr textarea {\nmin-width: 100%;\n}\n#qr [type='submit'] {\nwidth: 25%;\nvertical-align: top;\n}\n:root.webkit #qr [type='submit'] {\nheight: 24px;\n}\n/* Fake File Input */\n#qr-filename,\n.has-file #qr-no-file {\ndisplay: none;\n}\n#qr-no-file,\n.has-file #qr-filename {\ndisplay: inline-block;\npadding: 0px 4px;\nmargin-bottom: 2px;\noverflow: hidden;\ntext-overflow: ellipsis;\nmax-width: 88%;\n}\n#qr-no-file {\ncolor: #AAA;\n}\n#qr-filename-container {\n-moz-box-sizing: border-box;\ndisplay: inline-block;\nposition: relative;\nwidth: 100px;\nmin-width: 74.6%;\nmax-width: 74.6%;\nmargin-right: 0.4%;\nmargin-top: 1px;\noverflow: hidden;\npadding: 2px 1px 0;\nheight: 22px;\n}\n#qr-filename-container:hover {\ncursor: text;\n}\n#qr-extras-container {\nposition: absolute;\nright: 0px;\n}\n#qr-filerm {\nmargin-right: 2px;\nz-index: 2;\n}\n#file-n-submit {\nheight: 23px;\n}\n#qr input[type=file] {\nvisibility: hidden;\nposition: absolute;\n}\n/* Thread Select / Spoiler Label */\n#qr select {\nfloat: right;\n}\n#qr.has-spoiler .has-file #qr-spoiler-label {\nwidth: 6.7%;\nmin-width: 6.7%;\nmax-width: 6.7%;\ndisplay: inline-block;\ntext-align: center;\nvertical-align: top;\n}\n#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\ndisplay: none;\n}\n#qr.has-spoiler .has-file #qr-filename-container {\nmax-width: 67.9%;\nmin-width: 67.9%;\n}\n#qr-spoiler-label input {\nposition: relative;\ntop: 3px;\n}\n/* Dumping UI */\n.dump #dump-list-container {\ndisplay: block;\n}\n#dump-list-container {\ndisplay: none;\nposition: relative;\noverflow-y: hidden;\nmargin-top: 1px;\n}\n#dump-list {\noverflow-x: auto;\noverflow-y: hidden;\nwhite-space: nowrap;\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-list:hover {\noverflow-x: auto;\n}\n.qr-preview {\n-moz-box-sizing: border-box;\ncounter-increment: thumbnails;\ncursor: move;\ndisplay: inline-block;\nheight: 90px;\nwidth: 90px;\npadding: 2px;\nopacity: .5;\noverflow: hidden;\nposition: relative;\ntext-shadow: 0 1px 1px #000;\n-moz-transition: opacity .25s ease-in-out;\nvertical-align: top;\nbackground-size: cover;\n}\n.qr-preview:hover,\n.qr-preview:focus {\nopacity: .9;\n}\n.qr-preview::before {\ncontent: counter(thumbnails);\ncolor: #fff;\nposition: absolute;\ntop: 3px;\nright: 3px;\ntext-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.qr-preview#selected {\nopacity: 1;\n}\n.qr-preview.drag {\nbox-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.qr-preview.over {\nborder-color: #fff;\n}\n.qr-preview > span {\ncolor: #fff;\n}\n.remove {\nbackground: none;\ncolor: #e00;\nfont-weight: 700;\npadding: 3px;\n}\na:only-of-type > .remove {\ndisplay: none;\n}\n.remove:hover::after {\ncontent: \" Remove\";\n}\n.qr-preview > label {\nbackground: rgba(0,0,0,.5);\ncolor: #fff;\nright: 0; bottom: 0; left: 0;\nposition: absolute;\ntext-align: center;\n}\n.qr-preview > label > input {\nmargin: 0;\n}\n#add-post {\ncursor: pointer;\nfont-size: 2em;\nposition: absolute;\ntop: 50%;\nright: 10px;\n-moz-transform: translateY(-50%);\n}\n.textarea {\nposition: relative;\n}\n:root.webkit .textarea {\nmargin-bottom: -2px;\n}\n#char-count {\ncolor: #000;\nbackground: hsla(0, 0%, 100%, .5);\nfont-size: 8pt;\nposition: absolute;\nbottom: 1px;\nright: 1px;\npointer-events: none;\n}\n\n/* Menu */\n.menu-button {\ndisplay: inline-block;\nposition: relative;\ncursor: pointer;\n}\n.menu-button i {\nborder-top: 6px solid;\nborder-right: 4px solid transparent;\nborder-left: 4px solid transparent;\ndisplay: inline-block;\nmargin: 2px;\nvertical-align: middle;\n}\n#menu {\nposition: fixed;\noutline: none;\n}\n.entry {\nborder-bottom: 1px solid rgba(0,0,0,.25);\ncursor: pointer;\ndisplay: block;\noutline: none;\npadding: 3px 7px;\nposition: relative;\ntext-decoration: none;\nwhite-space: nowrap;\n}\n.left>.entry.has-submenu {\npadding-right: 17px !important;\n}\n.entry:last-child {\nborder-bottom: 0;\n}\n.has-submenu::after {\ncontent: \"\";\nborder-left: .5em solid;\nborder-top: .3em solid transparent;\nborder-bottom: .3em solid transparent;\ndisplay: inline-block;\nmargin: .3em;\nposition: absolute;\nright: 3px;\n}\n.left .has-submenu::after {\nborder-left: 0;\nborder-right: .5em solid;\n}\n.submenu {\ndisplay: none;\nposition: absolute;\nleft: 100%;\ntop: -1px;\n}\n.focused .submenu {\ndisplay: block;\n}\n.imp-exp-result {\nposition: absolute;\ntext-align: center;\nmargin: auto;\nright: 0px;\nleft: 0px;\nwidth: 200px;\n}\n.export, .import {\ncursor: pointer;\ntext-decoration: none !important;\n}\n/* Link Title Favicons */\n.linkify.YouTube {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vimeo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAASJJREFUOE9jYAAC7ln7/pODQXrBmq333PvPu/YaSRikB6QXbACpmmHqsRoAMll7+20UQ0H8tmuv/pdffPFfZtNNuByGASBFIPDh5x+4IV6HHoDFYGDJgw+YBoBMBUkgA5BtIKduuvvy//svX+FSB+88wTTAc+/t/83bj/0HScLA5BPXwc7lKJ36f+L6XXDxhUfOYxrAPWUnWKFp9UQUm3iWQxSDXAEDSX3zcIcB96wD/x+8eA1XDNKMHAYg20GW4Y0FkCIYAAUqzEBQOIBciRzlWKMxZelOlMCEcVxq+jHSC1YDJPs3YBgA8jey0/F6ARRwsFAHORukmat9NdbUijMpg/wKcrJodDFOzSBXwA3Alh9AToZFI7a8Asu98BxJbnYGAJb5vYLDANzSAAAAAElFTkSuQmCC') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.SoundCloud {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.audio {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.LiveLeak {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAydJREFUOE9Nk1tIk2EYx79NyUNqTk0o6KYrnZeChodLDxfeZpCbJk4RXU5Nm7tYRYhiYXbQlaeGutyW2gxtpB1RIyKDEjKwA6Ti2dR5KNDn+fq/S6TBj/f93r3P732e53s/qfnkSdej4GB2SBLbwf+jmB+gUMgOheLg/z7EdCUnO6Ref392SpK8Hyh3I+gBwBo7lUp2xcbyQEoKD6alyQOpqd754/h4FjJXZCRJTl9ftmEzoK5/wdQJxPgkLY2WV1dpc2uLtnZ2eHNnhza3t2nd46GhjAzuValY6jx0iIfS03msoIDuQ9COQCtoUSjohU5HuwgaN5loeXycd3d3aW9vzwvW2K5SkdTi58fvzGb+3tdHFggA3QONEAzn59PvjQ1yqNX0zenkvX0B4ffWaGRraChJd/385JGqKvlzTw/fRqOaIGkEd1DjU52O/3g83BkTw5MOh7yJuUCUM2o0yi2hoSw1IIOhykr+YLNRHYKu4XQvyKA/N5c8yMCCDD7Z7bz26xcJ1rH2rKKCG0UJdRAMlJbyG6uVrkJQjWAB5tSbk0Nr2HwDgvcQiIYur6zQyvo6ucvLueHIEZKuQPBQr+dXra1kRuqXEOwFArtWSytra1QdFUVjNhvPLS3R3OIiLUDUD0F1WBhJJtwDW2Ehu5uaqBICI4IFlRB0QLCEzaboaHrd0cHzCBYsIIuesjK+LAQXkEFrXh676uupGCWcR6AeghLQptGQONUAwfOuLp6Zn6eZuTmaXVig7pISrhI90ENgQbdHhoep32JhFzLpu3WLio8epUYIfs7OUjF6UKJW88XERLqYkEBNej11oG8XhCAvMFAuOn5cNiclsTkhQTbhmpri4lgbEMANWi1DwC/xit3t7bK7rY0Fo4OD3G4wyEURESzloAdnceezlErK8vH5N4KzPj50PTOTfkxP0+THj/RlYoInJyZI8HVqim5qNFwQHk7SucBAPo2PKRMNPLM/4pnFszYkhJsNBu6uqWFHba1sr61lQSveQFZQkFx07BhJmhMnrLn4NLMPH/aSExR0QDbmWhwgyEapwDvXoDxdWBiXnjrV/Bdm2kYUxLwmEgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vocaroo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.pastebin {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAtZJREFUOE+NU91LWmEc7sJtQew/2MUY7INg7CLY3W5GMHazyzEQo9UmfYxZTbAiVlgRqLMSZ+XnDC3z2+Y0+8JGakKZTtR0Tl2wtgtLLQh29cz3ZZ3h3Q68vOc95zzP73l+z+/U1f292O09DRxubxOH23P//1bvtQts3dPnry7LZnXJhcUl5Avf8dHtwY+fv2AyW5DOfIXFakMm+w0G4wISyRRm55TQG0y/Wzv6mikJ52Xf9TmVBoFAAD6fDwqFAqFQCJubmzCbzZiensbp6SmkUikikQi0Wi0kEgm6ewVaStDCfXPDandifn6egoaGhrCzswO1Wg2Hw4HBwUGk02kIBAL4/X4IhUJMTk6ii8dfYggy2RwymQzOz88Rj8dRLpexv7+PSqWCYDCIQqGAra0tJBIJrK2t0XdVAjNDEIl+wfj4OEqlEq2wt7dHrchkMmrBYDCAz+fTIjweD7FYrJbgIJOlgLOzM8jlcip1eXmZ2rFarVAqlRCLxcjlchCJRFRljYJYPAG32418Pg+n04lsNouVlRUcHh7C4/FQIOlHNBqlezgcJgQWxkIgGMbExASVNjY2hvX1dVo9mUzS5wREFLhcLrqTcw2B//M2RkdHodPp4PV6oVKpqH+SCom3v7+fNnF4eJiJusbCJ6+PviSyScakiaR5RIHRaKQpmEwmbAdCeD8zB6vdhebHT8SMhcUlC83bbrdTJRsbG3RwiCVCRNJJpDIoVeNNJJJQzKryV+rrmxiCtyNCCmaz2VhdXQWXy6XDpNfrodFoYLXZUTw+pk222Z3lW3ca26rgSwzBwqIZAwMDlITMAVEwNTVFR5fEJpK8Qyp1AJvDVbrTeLenCmxgfiZ22+urCtWHyu7uLp2wVCpFKx0dHaFYLOLk5KT6Y9kgk89kb95ubK0BX7A8a+1qannRLeW0daj/rU51S3tn9dypfvDw0QiLxbpX/Z7FVK7e/AEj4Wf24/2f5AAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.gist {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqUkzuIE1EUhv955MnsbB6r4kYQLUQQFncV3SnCIqJsoWGDYOGjsIiCtY2Kla1sjLBIsFFcXJC1kaSwENQmXUQSRSUSjCQSTCbkbR4z47lXEgtBNwcu3DNzvvO8R8jlcj7LshKmaWqYQERRTAmCcEru9/sJr9er0QF92BJMAVGr1TQ6CeZAc7lcGAwGkyQAxpTLZU0eDoc8crfbRTgcRjAYRCQSYSmi1WpxY7fbjU6ng1gshmaziXg8zhnGIpVKWbquW9ls1mLZsaMoiqWq6lgnBxY55He/328Vi0XOMFZmqVMD4fF4QBAajcY48khY9JE4HA4enTGMFVkaTHmy+ZzD/5NSqYSNB484w1h55ODO3TVu4FXcWDywl24Cmp0e1WBhyuWELAtIf/qKUrWOONmev3Lpt4NRCXq1gplpBS/v3cDc0nGg9h1o1ZkfwO4Atu1B8cM7HLt8k37V/y5B2b4bJxf2Y+7oEbyJrkMvUjki0YYJ03LidfQxAt4dOHdCw5RdGZcgGobBlQtnV/BDr1GfDai7ZiHZZRi9PoY/e5SCCTUwC9gk1GmMh5YWOcNYkR4Sv1y9uAJbYB82N57h4OnDmN7phjQ0qUkWRJuB+TMaPn/5iFfvv+Ha7eucYey4iWw8q6tRJJNJ3Fp7ClUawEkViBTfkCR0YUNTVHD/4Tpm/P4/U2CeKpUKfD4fJDIMhUKEhP45St50XedZyLQY6Xw+v8AUemVb2oNqtYpCocCWKi2TLLfb7ReZTGZ+kmUi7i2VvfxLgAEAZChMriPcl+IAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.image {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.InstallGentoo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAklJREFUOE9jYEAAASBTCorZkcSRmTjVCDLziCwG4hfM3EIvGNm44oC6WNEM4WXi5FsEkmfhFX3BxMmfAJSHW9Qr55Px3aZp3X/btq3/hQydPzKysMcCFbBBDeFj4uBdqBJR/gskb1W34j+PmulLoJwbzBJJoMm7dNO7/ntMP/XfpW/v//SKvk+7tl7fvXfTpx5pCdWVSiHFv1wnHQbLi9sE/Wdk5SwBauaCGQB3gUPb5v+7Lr/8/+fvr/9fv/z+f+Pyr/9bV735l9Wy/79Dx/b/Nk0bsLoAHgbeAVHv/v77/f8f0IB7N7+cu3DuecK54z9+7lzz639e9pK/7HwSWMMA5BJwCJeXtOm/fvVj1fcfv369f//92cN7X6ZcPvf9x6Htv//vXP3r/+T245UEYgpskPTNq08LgN749/PH7/93rv/6f/rw7//nj//4f+bU0zQcUQwWBkdVbGz62y+fv3wHeeXrlz//H9798//qpY//M3KqfzGxc8djiWKwZnBUuWQ2/fr46fv/P39+///x/ff/d69//z97+s7fyMb5/+y7d2GLYriDZikFF/1qXXXj/4Pbv/8/f/jn/5MH316/eP6jVlBAaIt6VO1/jxmn/zv27P7Pp2HxEajLD90ra9Sj6/979O37X73w0n+vqOL/0lJyMVBFq0EGgDSD0oKAlu1/oHg4ugGzVCKqfouYuL1Xj676Iajr8AnJFricGqYc3Bw+Zi6BVUxsXLHAdL6QiYMPFNrwpIxHDsUhgtAMAopKDjQn4pPDF7P45QC4hSmc1eX8WgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n\n/* General */\n:root.yotsuba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.yotsuba #header-bar, :root.yotsuba #notifications {\nfont-size: 9pt;\ncolor: #B86;\n}\n:root.yotsuba #header-bar a, :root.yotsuba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.yotsuba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.yotsuba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.yotsuba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba #menu {\ncolor: #800000;\n}\n:root.yotsuba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 10pt;\n}\n:root.yotsuba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.yotsuba-b .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\nfont-size: 9pt;\ncolor: #89A;\n}\n:root.yotsuba-b #header-bar a, :root.yotsuba-b #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.yotsuba-b #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.yotsuba-b .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.yotsuba-b .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba-b #menu {\ncolor: #000;\n}\n:root.yotsuba-b .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 10pt;\n}\n:root.yotsuba-b .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba-b .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.futaba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.futaba #header-bar, :root.futaba #notifications {\nfont-size: 11pt;\ncolor: #B86;\n}\n:root.futaba #header-bar a, :root.futaba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.futaba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.futaba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.futaba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.futaba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.futaba #menu {\ncolor: #800000;\n}\n:root.futaba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 12pt;\n}\n:root.futaba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.futaba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.burichan .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.burichan #header-bar, :root.burichan #header-bar #notifications {\nfont-size: 11pt;\ncolor: #89A;\n}\n:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.burichan #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.burichan .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.burichan .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.burichan #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.burichan #menu {\ncolor: #000000;\n}\n:root.burichan .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 12pt;\n}\n:root.burichan .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.burichan .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.tomorrow .dialog {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n\n/* Header */\n:root.tomorrow #header-bar, :root.tomorrow #notifications {\nfont-size: 9pt;\ncolor: #C5C8C6;\n}\n:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\ncolor: #81A2BE;\n}\n\n/* Settings */\n:root.tomorrow #fourchanx-settings fieldset {\nborder-color: #111;\n}\n\n/* Quote */\n:root.tomorrow .backlink.deadlink {\ncolor: #81A2BE !important;\n}\n:root.tomorrow .inline {\nborder-color: #111;\nbackground-color: rgba(0, 0, 0, .14);\n}\n\n/* QR */\n.tomorrow #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n:root.tomorrow .qr-preview {\nbackground-color: rgba(255, 255, 255, .15);\n}\n:root.tomorrow #qr .field {\nbackground-color: rgb(26, 27, 29);\ncolor: rgb(197,200,198);\nborder-color: rgb(40, 41, 42);\n}\n:root.tomorrow #qr .field:focus {\nborder-color: rgb(129, 162, 190) !important;\nbackground-color: rgb(30,32,36);\n}\n\n/* Menu */\n:root.tomorrow #menu {\ncolor: #C5C8C6;\n}\n:root.tomorrow .entry {\nborder-bottom: 1px solid #111;\nfont-size: 10pt;\n}\n:root.tomorrow .focused.entry {\nbackground: rgba(0, 0, 0, .33);\n}\n\n/* Watcher Favicon */\n:root.tomorrow .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.photon .dialog {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.photon #header-bar, :root.photon #notifications {\nfont-size: 9pt;\ncolor: #333;\n}\n:root.photon #header-bar a, :root.photon #notifications a {\ncolor: #FF6600;\n}\n\n/* Settings */\n:root.photon #fourchanx-settings fieldset {\nborder-color: #CCC;\n}\n\n/* Quote */\n:root.photon .backlink.deadlink {\ncolor: #F60 !important;\n}\n:root.photon .inline {\nborder-color: #CCC;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.photon #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.photon #menu {\ncolor: #333;\n}\n:root.photon .entry {\nborder-bottom: 1px solid #CCC;\nfont-size: 10pt;\n}\n:root.photon .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.photon .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n" + css: "/* General */\n.dialog {\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder: 1px solid;\ndisplay: block;\npadding: 0;\n}\n.captcha-img,\n.field {\nbackground-color: #FFF;\nborder: 1px solid #CCC;\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\ncolor: #333;\nfont: 13px sans-serif;\noutline: none;\ntransition: color .25s, border-color .25s;\ntransition: color .25s, border-color .25s;\n}\n.field::-moz-placeholder,\n.field:hover::-moz-placeholder {\ncolor: #AAA !important;\nfont-size: 13px !important;\nopacity: 1.0 !important;\n}\n.captch-img:hover,\n.field:hover {\nborder-color: #999;\n}\n.field:hover, .field:focus {\ncolor: #000;\n}\n.field[disabled] {\nbackground-color: #F2F2F2;\ncolor: #888;\n}\n.move {\ncursor: move;\noverflow: hidden;\n}\nlabel, .favicon {\ncursor: pointer;\n}\na[href=\"javascript:;\"] {\ntext-decoration: none;\n}\n.warning {\ncolor: red;\n}\n#boardNavDesktop {\ndisplay: none !important;\n}\na {\noutline: none !important;\n}\n\n/* 4chan style fixes */\n.opContainer, .op {\ndisplay: block !important;\noverflow: visible !important;\n}\n[hidden] {\ndisplay: none !important;\n}\n\n/* fixed, z-index */\n#overlay,\n#fourchanx-settings,\n#qp, #ihover,\n#navlinks, .fixed #header-bar,\n:root.float #updater,\n:root.float #thread-stats,\n#qr {\nposition: fixed;\n}\n#fourchanx-settings {\nz-index: 999;\n}\n#overlay {\nz-index: 900;\n}\n#notifications {\nz-index: 70;\n}\n#qp, #ihover {\nz-index: 60;\n}\n#menu {\nz-index: 50;\n}\n#navlinks, #updater, #thread-stats {\nz-index: 40;\n}\n.fixed #header-bar.autohide {\nz-index: 35;\n}\n#qr {\nz-index: 30;\n}\n#watcher {\nz-index: 8;\n}\n:root.fixed-watcher #watcher {\nz-index: 20;\n}\n.fixed #header-bar {\nz-index: 10;\n}\n/* Header */\n.fixed.top body {\npadding-top: 2em;\n}\n.fixed.bottom body {\npadding-bottom: 2em;\n}\n.fixed #header-bar {\nright: 0;\nleft: 0;\npadding: 3px 4px 4px;\n}\n.fixed.top #header-bar {\ntop: 0;\n}\n.fixed.bottom #header-bar {\nbottom: 0;\n}\n#header-bar {\nborder-width: 0;\ntransition: all .1s .05s ease-in-out;\n}\n:root.centered-links #shortcuts {\nwidth: 300px;\ntext-align: right;\n}\n:root.centered-links #header-bar {\ntext-align: center;\n}\n:root.centered-links #custom-board-list {\nposition: relative;\nleft: 150px;\n}\n.fixed.top #header-bar {\nborder-bottom-width: 1px;\n}\n.fixed.bottom #header-bar {\nbox-shadow: 0 -1px 2px rgba(0, 0, 0, .15);\nborder-top-width: 1px;\n}\n.fixed.bottom #header-bar .menu-button i {\nborder-top: none;\nborder-bottom: 6px solid;\n}\n#board-list {\ntext-align: center;\n}\n.fixed #header-bar.autohide:not(:hover) {\nbox-shadow: none;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar.autohide:not(:hover) {\nmargin-bottom: -1em;\n-webkit-transform: translateY(-100%);\ntransform: translateY(-100%);\n}\n.fixed.bottom #header-bar.autohide:not(:hover) {\n-webkit-transform: translateY(100%);\ntransform: translateY(100%);\n}\n#scroll-marker {\nleft: 0;\nright: 0;\nheight: 10px;\nposition: absolute;\n}\n#header-bar #scroll-marker {\ndisplay: none;\n}\n.fixed #header-bar #scroll-marker {\ndisplay: block;\n}\n.fixed.top #header-bar #scroll-marker {\ntop: 100%;\n}\n.fixed.bottom #header-bar #scroll-marker {\nbottom: 100%;\n}\n#header-bar a:not(.entry):not(.close) {\ntext-decoration: none;\npadding: 1px;\n}\n#header-bar input {\nmargin: 0;\nvertical-align: bottom;\n}\n#shortcuts:empty {\ndisplay: none;\n}\n.brackets-wrap::before {\ncontent: \"\\00a0[\";\n}\n.brackets-wrap::after {\ncontent: \"]\\00a0\";\n}\n.disabled,\n.expand-all-shortcut {\nopacity: .45;\n}\n#shortcuts {\nfloat: right;\n}\n.shortcut {\nmargin-left: 3px;\n}\n#navbotright,\n#navtopright {\ndisplay: none;\n}\n#toggleMsgBtn {\ndisplay: none !important;\n}\n.current {\nfont-weight: bold;\n}\n/* 4chan X link brackets */\n.fourchanx-link::after {\ncontent: \"]\";\n}\n.fourchanx-link::before {\ncontent: \"[\";\n}\n/* Notifications */\n#notifications {\nposition: fixed;\ntop: 0;\nheight: 0;\ntext-align: center;\nright: 0;\nleft: 0;\ntransition: all .8s .6s cubic-bezier(.55, .055, .675, .19);\n}\n.fixed.top #header-bar #notifications {\nposition: absolute;\ntop: 100%;\n}\n.notification {\ncolor: #FFF;\nfont-weight: 700;\ntext-shadow: 0 1px 2px rgba(0, 0, 0, .5);\nbox-shadow: 0 1px 2px rgba(0, 0, 0, .15);\nborder-radius: 2px;\nmargin: 1px auto;\nwidth: 500px;\nmax-width: 100%;\nposition: relative;\ntransition: all .25s ease-in-out;\n}\n.notification.error {\nbackground-color: hsla(0, 100%, 38%, .9);\n}\n.notification.warning {\nbackground-color: hsla(36, 100%, 38%, .9);\n}\n.notification.info {\nbackground-color: hsla(200, 100%, 38%, .9);\n}\n.notification.success {\nbackground-color: hsla(104, 100%, 38%, .9);\n}\n.notification a {\ncolor: white;\n}\n.notification > .close {\npadding: 6px;\ntop: 0;\nright: 5px;\nposition: absolute;\n}\n.message {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\npadding: 6px 20px;\nmax-height: 200px;\nwidth: 100%;\noverflow: auto;\n}\n\n/* Settings */\n:root.fourchan-x body {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\n}\n#overlay {\nbackground-color: rgba(0, 0, 0, .5);\ntop: 0;\nleft: 0;\nheight: 100%;\nwidth: 100%;\n}\n#fourchanx-settings {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nbox-shadow: 0 0 15px rgba(0, 0, 0, .15);\nheight: 600px;\nmax-height: 100%;\nwidth: 900px;\nmax-width: 100%;\nmargin: auto;\npadding: 3px;\ntop: 50%;\nleft: 50%;\n-moz-transform: translate(-50%, -50%);\n-webkit-transform: translate(-50%, -50%);\ntransform: translate(-50%, -50%);\n}\n#fourchanx-settings > nav {\npadding: 2px 2px 0;\nheight: 15px;\n}\n#fourchanx-settings > nav a {\ntext-decoration: underline;\n}\n#fourchanx-settings > nav a.close {\ntext-decoration: none;\npadding: 2px;\n}\n.section-container {\noverflow: auto;\nposition: absolute;\ntop: 2.1em;\nright: 5px;\nbottom: 5px;\nleft: 5px;\npadding-right: 5px;\n}\n.sections-list {\npadding: 0 3px;\nfloat: left;\n}\n.credits {\nfloat: right;\n}\n.tab-selected {\nfont-weight: 700;\n}\n.section-sauce ul,\n.section-advanced ul {\nlist-style: none;\nmargin: 0;\n}\n.section-sauce ul {\npadding: 8px;\n}\n.section-advanced ul {\npadding: 0px;\n}\n.section-sauce li,\n.section-advanced li {\npadding-left: 4px;\n}\n.section-main label {\ntext-decoration: underline;\n}\n.section-filter ul {\npadding: 0;\n}\n.section-filter li {\nmargin: 10px 40px;\n}\n.section-filter textarea {\nheight: 500px;\n}\n.section-sauce textarea {\nheight: 350px;\n}\n.section-advanced .field[name=\"boardnav\"] {\nwidth: 100%;\n}\n.section-advanced textarea {\nheight: 150px;\n}\n.section-advanced .archive-cell {\nmin-width: 160px;\ntext-align: center;\n}\n.section-advanced #archive-board-select {\nposition: absolute;\n}\n.section-advanced .note {\nfont-size: 0.8em;\nfont-style: italic;\nmargin-left: 10px;\n}\n.section-advanced .note code {\nfont-style: normal;\nfont-size: 11px;\n}\n.section-keybinds .field {\nfont-family: monospace;\n} \n#fourchanx-settings fieldset {\nborder: 1px solid;\nborder-radius: 3px;\n}\n#fourchanx-settings legend {\nfont-weight: 700;\n}\n#fourchanx-settings textarea {\nfont-family: monospace;\nmin-width: 100%;\nmax-width: 100%;\n}\n#fourchanx-settings code {\ncolor: #000;\nbackground-color: #FFF;\npadding: 0 2px;\n}\n.unscroll {\noverflow: hidden;\n}\n\n/* Announcement Hiding */\n:root.hide-announcement #globalMessage {\ndisplay: none;\n}\na.hide-announcement {\nfloat: left;\n}\n\n/* Unread */\n#unread-line {\nmargin: 0;\nborder-color: rgb(255,0,0);\n}\n\n/* Thread Updater */\n#updater {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n#updater > .move {\npadding: 5px 3px 0px;\nmargin-bottom: -3px;\n}\n#updater > div:last-child {\ntext-align: center;\n}\n#updater input[type=number] {\nwidth: 4em;\n}\n:root.float #updater {\npadding: 0px 3px;\n}\n.new {\ncolor: limegreen;\n}\n#update-status.new {\nmargin-right: 5px;\n}\n#update-timer {\ncursor: pointer;\n}\n\n/* Thread Watcher */\n#watcher {\nposition: absolute;\n}\n#watcher {\npadding-bottom: 3px;\noverflow: hidden;\nwhite-space: nowrap;\nmin-width: 120px;\nmax-height: 92%;\noverflow-y: auto;\n}\n:root.fixed-watcher #watcher {\nposition: fixed;\n}\n:root:not(.fixed-watcher) #watcher:not(:hover) {\nmax-height: 210px;\noverflow-y: hidden;\n}\n#watcher > .move {\npadding-top: 3px;\n}\n#watcher > div {\nmax-width: 250px;\noverflow: hidden;\npadding-left: 3px;\npadding-right: 3px;\ntext-overflow: ellipsis;\n}\n#watcher a {\ntext-decoration: none;\n}\n#watcher .move>.close {\nposition: absolute;\nright: 0px;\ntop: 0px;\npadding: 0px 4px;\n}\n.watch-thread-link {\npadding-top: 18px;\nwidth: 18px;\nheight: 0px;\ndisplay: inline-block;\nbackground-repeat: no-repeat;\nopacity: 0.2;\nposition: relative;\ntop: 1px;\n}\n.watch-thread-link.watched {\nopacity: 1;\n}\n\n/* Thread Stats */\n#thread-stats {\nbackground: none;\nborder: none;\nbox-shadow: none;\n}\n:root.float #post-count, :root.float #file-count {\npointer-events: none;\n}\n:root.float #thread-stats {\npadding: 0px 3px;\n}\n\n/* Quote */\n.deadlink {\ntext-decoration: none !important;\n}\n.backlink.deadlink:not(.forwardlink),\n.quotelink.deadlink:not(.forwardlink) {\ntext-decoration: underline !important;\n}\n.inlined {\nopacity: .5;\n}\n#qp input, .forwarded {\ndisplay: none;\n}\n.quotelink.forwardlink,\n.backlink.forwardlink {\ntext-decoration: none;\nborder-bottom: 1px dashed;\n}\n.filtered {\ntext-decoration: underline line-through;\n}\n:root.hide-backlinks .backlink.filtered {\ndisplay: none;\n}\n.inline {\nborder: 1px solid;\ndisplay: table;\nmargin: 2px 0;\n}\n.inline .post {\nborder: 0 !important;\nbackground-color: transparent !important;\ndisplay: table !important;\nmargin: 0 !important;\npadding: 1px 2px !important;\n}\n#qp > .opContainer::after {\ncontent: '';\nclear: both;\ndisplay: table;\n}\n#qp .post {\nborder: none;\nmargin: 0;\npadding: 2px 2px 5px;\n}\n#qp img {\nmax-height: 80vh;\nmax-width: 50vw;\n}\n.qphl {\noutline: 2px solid rgba(216, 94, 49, .7);\n}\n:root.highlight-own .yourPost>.reply,\n:root.highlight-you .quotesYou>.reply {\nborder-left: 2px solid rgba(221,0,0,.5);\n}\n/* Quote Threading */\n.threadContainer {\nmargin-left: 20px;\nborder-left: 1px solid rgba(128,128,128,.3);\n}\n.threadOP {\nclear: both;\n} \n\n/* File */\n.fileText:hover .fntrunc,\n.fileText:not(:hover) .fnfull,\n.expanded-image > .post > .file > .fileThumb > img[data-md5],\n:not(.expanded-image) > .post > .file > .fileThumb > .full-image {\ndisplay: none;\n}\n.expanding {\nopacity: .5;\n}\n:root.fit-height .full-image {\nmax-height: 100vh;\n}\n:root.fit-width .full-image {\nmax-width: 100%;\n}\n:root.gecko.fit-width .full-image {\nwidth: 100%;\n}\n#ihover {\n-moz-box-sizing: border-box;\nbox-sizing: border-box;\nmax-height: 100%;\nmax-width: 75%;\npadding-bottom: 16px;\n}\n.fappeTyme .thread > .noFile,\n.fappeTyme .threadContainer > .noFile {\ndisplay: none;\n}\n\n/* Index/Reply Navigation */\n#navlinks {\nfont-size: 16px;\ntop: 25px;\nright: 10px;\n}\n\n/* Filter */\n.opContainer.filter-highlight {\nbox-shadow: inset 5px 0 rgba(255, 0, 0, .5);\n}\n.filter-highlight > .reply {\nbox-shadow: -5px 0 rgba(255, 0, 0, .5);\n}\n\n/* Spoiler text */\n:root.reveal-spoilers s {\ncolor: white !important;\n}\n\n/* Thread & Reply Hiding */\n.hide-thread-button,\n.hide-reply-button {\nfloat: left;\nmargin-right: 2px;\n}\n.stub ~ * {\ndisplay: none !important;\n}\n.stub input {\ndisplay: inline-block;\n}\n\n/* QR */\n:root.hide-original-post-form #postForm,\n:root.hide-original-post-form .postingMode,\n:root.hide-original-post-form #togglePostForm,\n#qr.autohide:not(.has-focus):not(:hover) > form,\n.postingMode ~ #qr select,\n#file-n-submit:not(.has-file) #qr-filerm {\ndisplay: none;\n}\n#qr select,\n#dump-button,\n.remove,\n.captcha-img {\ncursor: pointer;\n}\n#qr {\nz-index: 20;\nposition: fixed;\npadding: 1px;\nborder: 1px solid transparent;\nmin-width: 300px;\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nborder-radius: 3px 3px 0 0;\n}\n#qrtab {\nmargin-bottom: 1px;\n}\n#qr .close {\nfloat: right;\npadding: 0 3px;\n}\n#qr .warning {\nmin-height: 1.6em;\nvertical-align: middle;\npadding: 0 1px;\nborder-width: 1px;\nborder-style: solid;\n}\n.qr-link-container {\ntext-align: center;\n}\n.persona {\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-button {\nwidth: 10%;\nmargin: 0;\nmargin-right: 4px;\nfont: 13px sans-serif;\npadding: 1px 0px 2px;\nopacity: 0.6;\n}\n.persona .field:not(#dump) {\nwidth: 95px;\nmin-width: 33.3%;\nmax-width: 33.3%;\n}\n#qr textarea.field {\nheight: 14.8em;\nmin-height: 9em;\n}\n#qr.has-captcha textarea.field {\nheight: 9em;\n}\ninput.field.tripped:not(:hover):not(:focus) {\ncolor: transparent !important;\ntext-shadow: none !important;\n}\n#qr textarea {\nresize: both;\n}\n.captcha-img {\nmargin: 0px;\ntext-align: center;\nbackground-image: #fff;\nfont-size: 0px;\nmin-height: 59px;\nmin-width: 302px;\n}\n.captcha-input {\nwidth: 100%;\nmargin: 1px 0 0;\n}\n.captcha-input.error:focus {\nborder-color: rgb(255,0,0) !important;\n}\n.field {\n-moz-box-sizing: border-box;\nmargin: 0px;\npadding: 2px 4px 3px;\n}\n#qr textarea {\nmin-width: 100%;\n}\n#qr [type='submit'] {\nwidth: 25%;\nvertical-align: top;\n}\n:root.webkit #qr [type='submit'] {\nheight: 24px;\n}\n/* Fake File Input */\n#qr-filename,\n.has-file #qr-no-file {\ndisplay: none;\n}\n#qr-no-file,\n.has-file #qr-filename {\ndisplay: inline-block;\npadding: 0px 4px;\nmargin-bottom: 2px;\noverflow: hidden;\ntext-overflow: ellipsis;\nmax-width: 88%;\n}\n#qr-no-file {\ncolor: #AAA;\n}\n#qr-filename-container {\n-moz-box-sizing: border-box;\ndisplay: inline-block;\nposition: relative;\nwidth: 100px;\nmin-width: 74.6%;\nmax-width: 74.6%;\nmargin-right: 0.4%;\nmargin-top: 1px;\noverflow: hidden;\npadding: 2px 1px 0;\nheight: 22px;\n}\n#qr-filename-container:hover {\ncursor: text;\n}\n#qr-extras-container {\nposition: absolute;\nright: 0px;\n}\n#qr-filerm {\nmargin-right: 2px;\nz-index: 2;\n}\n#file-n-submit {\nheight: 23px;\n}\n#qr input[type=file] {\nvisibility: hidden;\nposition: absolute;\n}\n/* Thread Select / Spoiler Label */\n#qr select {\nfloat: right;\n}\n#qr.has-spoiler .has-file #qr-spoiler-label {\nwidth: 6.7%;\nmin-width: 6.7%;\nmax-width: 6.7%;\ndisplay: inline-block;\ntext-align: center;\nvertical-align: top;\n}\n#qr.has-spoiler #file-n-submit:not(.has-file) #qr-spoiler-label {\ndisplay: none;\n}\n#qr.has-spoiler .has-file #qr-filename-container {\nmax-width: 67.9%;\nmin-width: 67.9%;\n}\n#qr-spoiler-label input {\nposition: relative;\ntop: 3px;\n}\n/* Dumping UI */\n.dump #dump-list-container {\ndisplay: block;\n}\n#dump-list-container {\ndisplay: none;\nposition: relative;\noverflow-y: hidden;\nmargin-top: 1px;\n}\n#dump-list {\noverflow-x: auto;\noverflow-y: hidden;\nwhite-space: nowrap;\nwidth: 248px;\nmax-width: 100%;\nmin-width: 100%;\n}\n#dump-list:hover {\noverflow-x: auto;\n}\n.qr-preview {\n-moz-box-sizing: border-box;\ncounter-increment: thumbnails;\ncursor: move;\ndisplay: inline-block;\nheight: 90px;\nwidth: 90px;\npadding: 2px;\nopacity: .5;\noverflow: hidden;\nposition: relative;\ntext-shadow: 0 1px 1px #000;\n-moz-transition: opacity .25s ease-in-out;\nvertical-align: top;\nbackground-size: cover;\n}\n.qr-preview:hover,\n.qr-preview:focus {\nopacity: .9;\n}\n.qr-preview::before {\ncontent: counter(thumbnails);\ncolor: #fff;\nposition: absolute;\ntop: 3px;\nright: 3px;\ntext-shadow: 0 0 3px #000, 0 0 8px #000;\n}\n.qr-preview#selected {\nopacity: 1;\n}\n.qr-preview.drag {\nbox-shadow: 0 0 10px rgba(0,0,0,.5);\n}\n.qr-preview.over {\nborder-color: #fff;\n}\n.qr-preview > span {\ncolor: #fff;\n}\n.remove {\nbackground: none;\ncolor: #e00;\nfont-weight: 700;\npadding: 3px;\n}\na:only-of-type > .remove {\ndisplay: none;\n}\n.remove:hover::after {\ncontent: \" Remove\";\n}\n.qr-preview > label {\nbackground: rgba(0,0,0,.5);\ncolor: #fff;\nright: 0;\nbottom: 0;\nleft: 0;\nposition: absolute;\ntext-align: center;\n}\n.qr-preview > label > input {\nmargin: 0;\n}\n#add-post {\ncursor: pointer;\nfont-size: 2em;\nposition: absolute;\ntop: 50%;\nright: 10px;\n-moz-transform: translateY(-50%);\n}\n.textarea {\nposition: relative;\n}\n:root.webkit .textarea {\nmargin-bottom: -2px;\n}\n#char-count {\ncolor: #000;\nbackground: hsla(0, 0%, 100%, .5);\nfont-size: 8pt;\nposition: absolute;\nbottom: 1px;\nright: 1px;\npointer-events: none;\n}\n\n/* Menu */\n.menu-button {\ndisplay: inline-block;\nposition: relative;\ncursor: pointer;\n}\n.menu-button i {\nborder-top: 6px solid;\nborder-right: 4px solid transparent;\nborder-left: 4px solid transparent;\ndisplay: inline-block;\nmargin: 2px;\nvertical-align: middle;\n}\n#menu {\nposition: fixed;\noutline: none;\n}\n.entry {\nborder-bottom: 1px solid rgba(0,0,0,.25);\ncursor: pointer;\ndisplay: block;\noutline: none;\npadding: 3px 7px;\nposition: relative;\ntext-decoration: none;\nwhite-space: nowrap;\n}\n.left>.entry.has-submenu {\npadding-right: 17px !important;\n}\n.entry:last-child {\nborder-bottom: 0;\n}\n.has-submenu::after {\ncontent: \"\";\nborder-left: .5em solid;\nborder-top: .3em solid transparent;\nborder-bottom: .3em solid transparent;\ndisplay: inline-block;\nmargin: .3em;\nposition: absolute;\nright: 3px;\n}\n.left .has-submenu::after {\nborder-left: 0;\nborder-right: .5em solid;\n}\n.submenu {\ndisplay: none;\nposition: absolute;\nleft: 100%;\ntop: -1px;\n}\n.focused .submenu {\ndisplay: block;\n}\n.imp-exp-result {\nposition: absolute;\ntext-align: center;\nmargin: auto;\nright: 0px;\nleft: 0px;\nwidth: 200px;\n}\n.export, .import {\ncursor: pointer;\ntext-decoration: none !important;\n}\n/* Link Title Favicons */\n.linkify.YouTube {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAABIklEQVQoz53LvUrDUBjG8bOoOammSf1IoBSvoCB4JeIqOHgBLt6AIMRBBQelWurQ2kERnMRBsBUcIp5FJSBI5oQsJVkkUHh8W0o5nhaFHvjBgef/Mq+Q46RJBMkI/vE+aOus956tnEswIZe1LV0QyJ5sE2GzgZfVMtRNIdiDpccEssdlB1mW4bvTwdvWJtRdErM7U+8S/FJykCRJX5qm+KpVce8UMNLRLbulz4iSjTAMh6Iowsd5BeNadp3nUF0VlxAEwZBotXC0Usa4ll3meZdA1iguwvf9vpvDA2wvmKgYGtSud8suDB4TyGr2PF49D/vra9jRZ1BVdknMzgwuCGSnZEObwu6sBnVTCHZiaC7BhFx2PKdxUidiAH/4lLo9Mv0DELVs9qsOHXwAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vimeo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAASJJREFUOE9jYAAC7ln7/pODQXrBmq333PvPu/YaSRikB6QXbACpmmHqsRoAMll7+20UQ0H8tmuv/pdffPFfZtNNuByGASBFIPDh5x+4IV6HHoDFYGDJgw+YBoBMBUkgA5BtIKduuvvy//svX+FSB+88wTTAc+/t/83bj/0HScLA5BPXwc7lKJ36f+L6XXDxhUfOYxrAPWUnWKFp9UQUm3iWQxSDXAEDSX3zcIcB96wD/x+8eA1XDNKMHAYg20GW4Y0FkCIYAAUqzEBQOIBciRzlWKMxZelOlMCEcVxq+jHSC1YDJPs3YBgA8jey0/F6ARRwsFAHORukmat9NdbUijMpg/wKcrJodDFOzSBXwA3Alh9AToZFI7a8Asu98BxJbnYGAJb5vYLDANzSAAAAAElFTkSuQmCC') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.SoundCloud {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsklEQVQ4y5WTy2pUQRCGv2rbzDjJeAlIBmOyipGIIJqFEBDElwh4yULGeRFXPoEIBl/AvQ/gC2RnxCAoxijiwks852S6+3dxzslcHJCpTXVX11/Xv0097gLPgVNMJxnQNfX4zsqleWbnpoMf/oa9d988MM9MC/rp+E0a+A0dsVobMNMCOO8B6McRoABJI+A6gJmN3D2A8jgEBCEkSEMBrcrsDAzDWWn3AjgKFaDMmgRqniGFgsaDp1jrLOngDf1XT1D+A1dFc4MKAkkiCVKjjVu7g9+4Rzx4i1u6hjXbuMWr0O5QPNvCu7IaCZwEKQukLGDrm5x8uI0tr6MkiGlkiv7yLfzN+6S5i6QsIMABkEfcxhbWWYMkVAOjxvYAjc3HNHrbKI9VBQBFwF25XQKSBjqIf1YBuAurEMrczgDygD6/x2LCpFLXLUyQ+PoldphhBhYfIX09XU1+Flaukz7uYqs3SHs7cG4BmTsmkBUF9mmXEwa28BNLPaQPLepuNcbGSWQquQC2/Kdcox1FUGkcB0ykck1nA2+wTzMs8stGnP4rbWGw74EuS/GFQWfK7/wF6P4F7fzIAYkdmdEAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.audio {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAitJREFUOE9jYCAWKJWwavr0KyXWb/FIbDtUFFyzJx6nVofE2Xo5nXsj0rqPNSR0nVkR2Hjmgmfd+U9Otdf+m5Vf/6+SfeU/R9ChVVgNYDRtlfJuuPA/rPfe/4QpD/6nznj0P27Kw/9unff/69Xf+69c/+C/SO7N/0z+OAxgMmmRCe++/r9i3ev/KWvf/vdY8PK/bt/9/wrNV3/IN5y/IVt1YqNg4pGTTP4HsbuA2bhZ2qvpyn+xjIObxAp3VwqlrgngLFyryVy5nhPmZJHANS2cwYexG8BmVC/pWn3hP4NZlzWuQDJI3dIiFnUUuwEsQAOcq87jNcC7fHeLUtJxHF4AGmBWeAavAWH1+1rUUk7giAWjOknllON4DXAs2NEiG4/DBQxAF/CFHfrPYI4jDFSLuJVjNrUJhB/B7gIGo1pJRt99GAZYJK7wLJ1z7Xzl4vu/7aqv/GRBj0bjqAX2qb0nJ7mXH17C4HcUxQA+hymWtSue/C5a9up/9Ozn/7Vr7v1nRY7GqMb91T3b3v6vWvPmf/S0p/9ZQk+DDLCBRSOz06Jqk+o7/21nvfqvsebDf7kZL/5zBaxphkezd+OFn7HzXvz3Wvjmv9a8N//5Ek//ZTBpVYUrMG2X5wjcdl68+uI/wa5Lr3hSNjczGFeywOVZ/bbcVGp//F9izfv/Ql03f3P4LC/HSEQquYwMFnUCDJ7dzBhyjGZNQpye89M5gpfnMvtNUyE2h4PUAQBovvT7lyNljwAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.LiveLeak {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAydJREFUOE9Nk1tIk2EYx79NyUNqTk0o6KYrnZeChodLDxfeZpCbJk4RXU5Nm7tYRYhiYXbQlaeGutyW2gxtpB1RIyKDEjKwA6Ti2dR5KNDn+fq/S6TBj/f93r3P732e53s/qfnkSdej4GB2SBLbwf+jmB+gUMgOheLg/z7EdCUnO6Ref392SpK8Hyh3I+gBwBo7lUp2xcbyQEoKD6alyQOpqd754/h4FjJXZCRJTl9ftmEzoK5/wdQJxPgkLY2WV1dpc2uLtnZ2eHNnhza3t2nd46GhjAzuValY6jx0iIfS03msoIDuQ9COQCtoUSjohU5HuwgaN5loeXycd3d3aW9vzwvW2K5SkdTi58fvzGb+3tdHFggA3QONEAzn59PvjQ1yqNX0zenkvX0B4ffWaGRraChJd/385JGqKvlzTw/fRqOaIGkEd1DjU52O/3g83BkTw5MOh7yJuUCUM2o0yi2hoSw1IIOhykr+YLNRHYKu4XQvyKA/N5c8yMCCDD7Z7bz26xcJ1rH2rKKCG0UJdRAMlJbyG6uVrkJQjWAB5tSbk0Nr2HwDgvcQiIYur6zQyvo6ucvLueHIEZKuQPBQr+dXra1kRuqXEOwFArtWSytra1QdFUVjNhvPLS3R3OIiLUDUD0F1WBhJJtwDW2Ehu5uaqBICI4IFlRB0QLCEzaboaHrd0cHzCBYsIIuesjK+LAQXkEFrXh676uupGCWcR6AeghLQptGQONUAwfOuLp6Zn6eZuTmaXVig7pISrhI90ENgQbdHhoep32JhFzLpu3WLio8epUYIfs7OUjF6UKJW88XERLqYkEBNej11oG8XhCAvMFAuOn5cNiclsTkhQTbhmpri4lgbEMANWi1DwC/xit3t7bK7rY0Fo4OD3G4wyEURESzloAdnceezlErK8vH5N4KzPj50PTOTfkxP0+THj/RlYoInJyZI8HVqim5qNFwQHk7SucBAPo2PKRMNPLM/4pnFszYkhJsNBu6uqWFHba1sr61lQSveQFZQkFx07BhJmhMnrLn4NLMPH/aSExR0QDbmWhwgyEapwDvXoDxdWBiXnjrV/Bdm2kYUxLwmEgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.Vocaroo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAw9JREFUOE9jYMABuMwYmCyTJKUCGlSnFSy02TTzeOyCiQcDViX26qVz2TAyYtWmEMwuoZ3M7V40LcB79pHkc0svpvzY8jD//87nxf+3Pyn8v/ZO8v+VNyP/2mZJumI1QCWSI8232Hjumitlfw5+qPp/9l8TCt76JP//xkdx/wsXWCzjtWFkwTCkbWFe9plPk/+ga4Txz/xt/D/hkN//gMXif21a+NbyWjIwoRiy6GDT5rP/mlFsPfyp5n/NpOj/22+0gMUXXIz/H7hC/L/bFKFbPDZMrHAD5H35OPt2J9zacDv/f3V7xv9FhwrBGubsT/1//Pjx/1GJ/mD+/nfl/1v3Ovy3KRJNQbHdOlXCvOO03/+pm1P/v3v37n90hhtYw9HPtf8Xb2v937cmHswHeWPRxYj/LvkK3igGKARwicTO07118H3V/5kbi/4vPZMJtK3s/6YH2f+Pfq1B8VbjWrdnMu5s4nAD9CNFhKwz5DTUvLl419zKvAcLtG1P84BRl/b/5M/6/6f/NPzf/qzo84yj0Uus0xUU4Zor54bm9+4OfZG02OCuoAMTb9ZkC9ull1Nvrr2Z+XvRpaRfc65H/68F+jl9svEhzyLFWoccWVc+eyTHq/twydjlKRln7jX9bNMkMJnbhoFRL1xCqmKx6/yi2fYXa/c5/e846PV/5fW0/7OPx/yfcjzop34ulxdGGvDuU8mMXaX507lBuiN6ueadmQeT/p/93vf/1O+G//sP5fw/eL3o/5JLif8zVxs+Tlir9S26UyeFQQvJGBE7FvaFZ9LfN+1y+WjbItSb3GmXvXd15v8zroH/HxgE/D+aGPx/18vi/z07PeZNPRKxe/Kh0Ae8toxscCO4zBkYXArk9C1SxJUYjBkYPPIVtbbuTftz3cz//2O9wP/75iSAXdO72/dt2HL5F6YlfBW4MiJYXMiBiW3t7azHBx+V/t89N+H/8a+1//e9K/9attDp5LQjYX8SuvVL8RoAkmxa65299Erq1FnHo0qrl7t4BddriIs4MrM3rfWcFd+pGwVSAwBZ0bKP8yrZPAAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.pastebin {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAtZJREFUOE+NU91LWmEc7sJtQew/2MUY7INg7CLY3W5GMHazyzEQo9UmfYxZTbAiVlgRqLMSZ+XnDC3z2+Y0+8JGakKZTtR0Tl2wtgtLLQh29cz3ZZ3h3Q68vOc95zzP73l+z+/U1f292O09DRxubxOH23P//1bvtQts3dPnry7LZnXJhcUl5Avf8dHtwY+fv2AyW5DOfIXFakMm+w0G4wISyRRm55TQG0y/Wzv6mikJ52Xf9TmVBoFAAD6fDwqFAqFQCJubmzCbzZiensbp6SmkUikikQi0Wi0kEgm6ewVaStDCfXPDandifn6egoaGhrCzswO1Wg2Hw4HBwUGk02kIBAL4/X4IhUJMTk6ii8dfYggy2RwymQzOz88Rj8dRLpexv7+PSqWCYDCIQqGAra0tJBIJrK2t0XdVAjNDEIl+wfj4OEqlEq2wt7dHrchkMmrBYDCAz+fTIjweD7FYrJbgIJOlgLOzM8jlcip1eXmZ2rFarVAqlRCLxcjlchCJRFRljYJYPAG32418Pg+n04lsNouVlRUcHh7C4/FQIOlHNBqlezgcJgQWxkIgGMbExASVNjY2hvX1dVo9mUzS5wREFLhcLrqTcw2B//M2RkdHodPp4PV6oVKpqH+SCom3v7+fNnF4eJiJusbCJ6+PviSyScakiaR5RIHRaKQpmEwmbAdCeD8zB6vdhebHT8SMhcUlC83bbrdTJRsbG3RwiCVCRNJJpDIoVeNNJJJQzKryV+rrmxiCtyNCCmaz2VhdXQWXy6XDpNfrodFoYLXZUTw+pk222Z3lW3ca26rgSwzBwqIZAwMDlITMAVEwNTVFR5fEJpK8Qyp1AJvDVbrTeLenCmxgfiZ22+urCtWHyu7uLp2wVCpFKx0dHaFYLOLk5KT6Y9kgk89kb95ubK0BX7A8a+1qannRLeW0daj/rU51S3tn9dypfvDw0QiLxbpX/Z7FVK7e/AEj4Wf24/2f5AAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.gist {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAk1JREFUeNqUkzuIE1EUhv955MnsbB6r4kYQLUQQFncV3SnCIqJsoWGDYOGjsIiCtY2Kla1sjLBIsFFcXJC1kaSwENQmXUQSRSUSjCQSTCbkbR4z47lXEgtBNwcu3DNzvvO8R8jlcj7LshKmaWqYQERRTAmCcEru9/sJr9er0QF92BJMAVGr1TQ6CeZAc7lcGAwGkyQAxpTLZU0eDoc8crfbRTgcRjAYRCQSYSmi1WpxY7fbjU6ng1gshmaziXg8zhnGIpVKWbquW9ls1mLZsaMoiqWq6lgnBxY55He/328Vi0XOMFZmqVMD4fF4QBAajcY48khY9JE4HA4enTGMFVkaTHmy+ZzD/5NSqYSNB484w1h55ODO3TVu4FXcWDywl24Cmp0e1WBhyuWELAtIf/qKUrWOONmev3Lpt4NRCXq1gplpBS/v3cDc0nGg9h1o1ZkfwO4Atu1B8cM7HLt8k37V/y5B2b4bJxf2Y+7oEbyJrkMvUjki0YYJ03LidfQxAt4dOHdCw5RdGZcgGobBlQtnV/BDr1GfDai7ZiHZZRi9PoY/e5SCCTUwC9gk1GmMh5YWOcNYkR4Sv1y9uAJbYB82N57h4OnDmN7phjQ0qUkWRJuB+TMaPn/5iFfvv+Ha7eucYey4iWw8q6tRJJNJ3Fp7ClUawEkViBTfkCR0YUNTVHD/4Tpm/P4/U2CeKpUKfD4fJDIMhUKEhP45St50XedZyLQY6Xw+v8AUemVb2oNqtYpCocCWKi2TLLfb7ReZTGZ+kmUi7i2VvfxLgAEAZChMriPcl+IAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.image {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAs5JREFUOE+lk/tvi1EYx98/xT8gW4REIpGFMEQWl2FiM9ZMZhm2xRAyOsmujFFmdFRHu0tWm87UypxStr69zPauN5e5rHVp3IYhbOvHy+wHEQlxkm+ek+d8nm9OznkeSfrfldmgJC7QyUlTymsJTfuTZ25z4HdWYwyLreYhtpgekGPw0+kKvo1Eo+IXRSIiEhkWZuc9tqnsJD9EqTUopCxjSGTpB0iueczSo1HyW8cpsExQ1DbxI2pt45j9cXpexul4FEd79RnZphAa/SD7WvuFtO6UItbU9LC+YQxNI2w0wwYT5LRAdhOU3oBTIXC9gXP3oUSGgz2vST3gYHejR0jptT1C332f8yrUEYHrz8CgxDnpm6DKCUfc0KnmXa/AEVPPwnDcD0cvetA2uYRk67Ive/lpjO7YBO1PPuF8Df3vwf4cbNE4tqdw7YVq8HYyHx6FvhE1hkMEg8HDUqvFkjT4aIjMqkqyqkswDSrcfBfH+Q561YLAZ/B+BLda6FXlU/cPv0AoEPhuoP1h4Av7Wbh9E/Py15NWWUjeSR3nZDfeN+N0DY9hG/7K1eGP3P0S5/EYRFUF/IOTBrUXHPm9fT6mr1xEwupkZqxbzLyiDJYUZ5NSnkdqdSHpxyrYdFpPgdmAsdfJwPMI/Yr65bf7tZLGGBQ7DNdJWFtIYvoOZmbuZE7OXpIKKli86zAr9p9gTVktWTVnKTI2U95uRWe3U2IJUDbVB5p6hVm5x5m9Vc/cnedZUNzC8lILaQesZBy6hEZ3maKzgvJWFzVWD9XtXvVGQbSWASFtMATVRlJIKbOTWtlJXaeXepuPM1f6MNp9GLt8mLvvYLmp0OhQ2Fwvk6m7xaqDTvY0eYWUVtcnllXfYlGpnfklVuraHHg8HjxuN+6fktUHlWWZPaZeUo/ILK0UKttBcbNbSB9GP0yLxWJJUxoZGUn80zD9C/vXQ/4NHY10h3M1zmQAAAAASUVORK5CYII=') center left no-repeat!important;\npadding-left: 18px;\n}\n.linkify.InstallGentoo {\nbackground: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAklJREFUOE9jYEAAASBTCorZkcSRmTjVCDLziCwG4hfM3EIvGNm44oC6WNEM4WXi5FsEkmfhFX3BxMmfAJSHW9Qr55Px3aZp3X/btq3/hQydPzKysMcCFbBBDeFj4uBdqBJR/gskb1W34j+PmulLoJwbzBJJoMm7dNO7/ntMP/XfpW/v//SKvk+7tl7fvXfTpx5pCdWVSiHFv1wnHQbLi9sE/Wdk5SwBauaCGQB3gUPb5v+7Lr/8/+fvr/9fv/z+f+Pyr/9bV735l9Wy/79Dx/b/Nk0bsLoAHgbeAVHv/v77/f8f0IB7N7+cu3DuecK54z9+7lzz639e9pK/7HwSWMMA5BJwCJeXtOm/fvVj1fcfv369f//92cN7X6ZcPvf9x6Htv//vXP3r/+T245UEYgpskPTNq08LgN749/PH7/93rv/6f/rw7//nj//4f+bU0zQcUQwWBkdVbGz62y+fv3wHeeXrlz//H9798//qpY//M3KqfzGxc8djiWKwZnBUuWQ2/fr46fv/P39+///x/ff/d69//z97+s7fyMb5/+y7d2GLYriDZikFF/1qXXXj/4Pbv/8/f/jn/5MH316/eP6jVlBAaIt6VO1/jxmn/zv27P7Pp2HxEajLD90ra9Sj6/979O37X73w0n+vqOL/0lJyMVBFq0EGgDSD0oKAlu1/oHg4ugGzVCKqfouYuL1Xj676Iajr8AnJFricGqYc3Bw+Zi6BVUxsXLHAdL6QiYMPFNrwpIxHDsUhgtAMAopKDjQn4pPDF7P45QC4hSmc1eX8WgAAAABJRU5ErkJggg==') center left no-repeat!important;\npadding-left: 18px;\n}\n\n/* General */\n:root.yotsuba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.yotsuba #header-bar, :root.yotsuba #notifications {\nfont-size: 9pt;\ncolor: #B86;\n}\n:root.yotsuba #header-bar a, :root.yotsuba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.yotsuba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.yotsuba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.yotsuba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.yotsuba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba #menu {\ncolor: #800000;\n}\n:root.yotsuba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 10pt;\n}\n:root.yotsuba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.yotsuba-b .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.yotsuba-b #header-bar, :root.yotsuba-b #notifications {\nfont-size: 9pt;\ncolor: #89A;\n}\n:root.yotsuba-b #header-bar a, :root.yotsuba-b #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.yotsuba-b #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.yotsuba-b .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.yotsuba-b .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.yotsuba-b #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.yotsuba-b .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.yotsuba-b #menu {\ncolor: #000;\n}\n:root.yotsuba-b .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 10pt;\n}\n:root.yotsuba-b .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.yotsuba-b .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.futaba .dialog {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.futaba #header-bar, :root.futaba #notifications {\nfont-size: 11pt;\ncolor: #B86;\n}\n:root.futaba #header-bar a, :root.futaba #notifications a {\ncolor: #800000;\n}\n\n/* Settings */\n:root.futaba #fourchanx-settings fieldset {\nborder-color: #D9BFB7;\n}\n\n/* Quote */\n:root.futaba .backlink.deadlink {\ncolor: #00E !important;\n}\n:root.futaba .inline {\nborder-color: #D9BFB7;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.futaba #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #F0E0D6;\nborder-color: #D9BFB7;\n}\n:root.futaba .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.futaba #menu {\ncolor: #800000;\n}\n:root.futaba .entry {\nborder-bottom: 1px solid #D9BFB7;\nfont-size: 12pt;\n}\n:root.futaba .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.futaba .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.burichan .dialog {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .field:focus {\nborder-color: #98E;\n}\n\n/* Header */\n:root.burichan #header-bar, :root.burichan #header-bar #notifications {\nfont-size: 11pt;\ncolor: #89A;\n}\n:root.burichan #header-bar a, :root.burichan #header-bar #notifications a {\ncolor: #34345C;\n}\n\n/* Settings */\n:root.burichan #fourchanx-settings fieldset {\nborder-color: #B7C5D9;\n}\n\n/* Quote */\n:root.burichan .backlink.deadlink {\ncolor: #34345C !important;\n}\n:root.burichan .inline {\nborder-color: #B7C5D9;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.burichan #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #D6DAF0;\nborder-color: #B7C5D9;\n}\n:root.burichan .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.burichan #menu {\ncolor: #000000;\n}\n:root.burichan .entry {\nborder-bottom: 1px solid #B7C5D9;\nfont-size: 12pt;\n}\n:root.burichan .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.burichan .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.tomorrow .dialog {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n\n/* Header */\n:root.tomorrow #header-bar, :root.tomorrow #notifications {\nfont-size: 9pt;\ncolor: #C5C8C6;\n}\n:root.tomorrow #header-bar a, :root.tomorrow #notifications a {\ncolor: #81A2BE;\n}\n\n/* Settings */\n:root.tomorrow #fourchanx-settings fieldset {\nborder-color: #111;\n}\n\n/* Quote */\n:root.tomorrow .backlink.deadlink {\ncolor: #81A2BE !important;\n}\n:root.tomorrow .inline {\nborder-color: #111;\nbackground-color: rgba(0, 0, 0, .14);\n}\n\n/* QR */\n.tomorrow #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #282A2E;\nborder-color: #111;\n}\n:root.tomorrow .qr-preview {\nbackground-color: rgba(255, 255, 255, .15);\n}\n:root.tomorrow #qr .field {\nbackground-color: rgb(26, 27, 29);\ncolor: rgb(197,200,198);\nborder-color: rgb(40, 41, 42);\n}\n:root.tomorrow #qr .field:focus {\nborder-color: rgb(129, 162, 190) !important;\nbackground-color: rgb(30,32,36);\n}\n\n/* Menu */\n:root.tomorrow #menu {\ncolor: #C5C8C6;\n}\n:root.tomorrow .entry {\nborder-bottom: 1px solid #111;\nfont-size: 10pt;\n}\n:root.tomorrow .focused.entry {\nbackground: rgba(0, 0, 0, .33);\n}\n\n/* Watcher Favicon */\n:root.tomorrow .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n\n/* General */\n:root.photon .dialog {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .field:focus {\nborder-color: #EA8;\n}\n\n/* Header */\n:root.photon #header-bar, :root.photon #notifications {\nfont-size: 9pt;\ncolor: #333;\n}\n:root.photon #header-bar a, :root.photon #notifications a {\ncolor: #FF6600;\n}\n\n/* Settings */\n:root.photon #fourchanx-settings fieldset {\nborder-color: #CCC;\n}\n\n/* Quote */\n:root.photon .backlink.deadlink {\ncolor: #F60 !important;\n}\n:root.photon .inline {\nborder-color: #CCC;\nbackground-color: rgba(255, 255, 255, .14);\n}\n\n/* QR */\n.photon #dump-list::-webkit-scrollbar-thumb {\nbackground-color: #DDD;\nborder-color: #CCC;\n}\n:root.photon .qr-preview {\nbackground-color: rgba(0, 0, 0, .15);\n}\n\n/* Menu */\n:root.photon #menu {\ncolor: #333;\n}\n:root.photon .entry {\nborder-bottom: 1px solid #CCC;\nfont-size: 10pt;\n}\n:root.photon .focused.entry {\nbackground: rgba(255, 255, 255, .33);\n}\n\n/* Watcher Favicon */\n:root.photon .watch-thread-link\n{\nbackground-image: url(\"data:image/svg+xml,\");\n}\n" }; Main.init(); diff --git a/changelog-old b/changelog-old new file mode 100644 index 000000000..598fa09a1 --- /dev/null +++ b/changelog-old @@ -0,0 +1,1327 @@ +master + +2.39.7 +- Mayhem + Update archive redirection for /pol/ and /vg/. + +2.39.6 +- Mayhem + Fix QR. + +2.39.5 +- Mayhem + Update archive redirection for even more boards. + +2.39.4 +- Mayhem + Update archive redirection for many boards. + +2.39.3 +- Mayhem + Add /fa/ and /s4s/ archive redirection. + +2.39.2 +- Mayhem + Fix importing settings containing unicode characters. + +2.39.1 +- Mayhem + Add /gd/, /out/, /vp/ and /vr/ archive redirection. + +2.39.0 +- Queue + Fix rare bug in Relative Post Dates. +- Mayhem + Add Import/Export settings. + +2.38.1 +- Mayhem + Fix a little regression introduced in 2.38.0 for webkit browsers. + +2.38.0 +- Queue + Add Relative Post Dates ("35 seconds ago"), disabled by default. +- Mayhem + Add /int/ archive redirection for threads, and post resurrection. + +2.37.6 +- Mayhem + Fix image expanding. + +2.37.5 +- Mayhem + Fix quoting inside inlined backlinks. + +2.37.4 +- James Campos + Don't expand pdfs +- Mayhem + Add /po/ archive redirection for threads, images and post resurrection. + Fix quoting. + +2.37.3 +- Mayhem + Fix successful posting causing errors. + Fix 4chan X trying to interact with >>>/board/rules links. + +2.37.2 +- aeosynth + Beep on new post to completely read thread +- Mayhem + Fix dead quotes. + +2.37.1 +- noface + Fix Anonymize not working on stubs. +- Mayhem + Fix selection quoting on Opera. + Fix history bug with Persistent QR enabled on Chrome. + Fix posting warning not displaying the reason. + Fix deadquotes showing up in code-tags. + +2.37.0 +- noface + Add Catalog Links toggle. + Fix Anonymize not working on hovered posts. +- Mayhem + Added catalog support. + Sync thread hiding between index and catalog. + Add /c/ archived thread and image redirection. + +2.36.3 +- Mayhem + Fix next/previous page keybinds. + +2.36.2 +- noface + Add tags support on /f/. +- Mayhem + Add /mu/ archived image redirection. + +2.36.1 +- noface + The Menu now has search links for Archivers. +- Mayhem + Added possibility to display unix timestamps with File Info Formatting. + +2.36.0 +- Mayhem + Added thread creation QR cooldown. + Fix QR cooldown timer between non-sage and sage posts. You can submit a non-sage post 30 seconds after a sage one. + Fix /q/ QR cooldowns for image and sage posts. + +2.35.4 +- Mayhem + Removed the obnoxious 4chan Pass ad in captcha errors when posting. + Fix 'Administrator/Moderator/Developer Replies' creating extra backlinks on /q/, again. + +2.35.3 +- Mayhem + Larger Comment text input by default for 4chan Pass users and on /f/ (no captcha). + +2.35.2 +- Mayhem + Fix 4chan Pass with QR on Firefox. + +2.35.1 +- Mayhem + Add support for 4chan Pass. + You can now use 'Enter' in keybind combinations. + +2.35.0 +- Mayhem + Use 4chan's API to fetch posts for: + - Thread Updater. + - Quote Inlining. + - Quote Previewing. + - Thread Expansion. + - Comment Expansion. + This will make fetching faster, and reduce bandwidth usage. + Add an option to disable 4chan's inline extension. Enabled by default. + Fix compatibility with Scriptish's auto-udpater. + +2.34.10 +- Mayhem + Fix 4chan X. Blame moot. + +2.34.9 +- Mayhem + Add /g/, /k/, /w/, /an/, /cgl/, /ck/, /lit/, /toy/ and /x/ archived image redirection. + One-word-captcha now works in the report window. + Fix duplicate file upload error link. + +2.34.8 +- Mayhem + One-word-captcha: you don't need to input an extra space anymore, the true word will be duplicated. + +2.34.7 +- Mayhem + Fix one-word-captcha, you'll need to leave a space for the fake word now. + +2.34.6 +- Mayhem + Fix error caused by change in 4chan's HTML about hidden filename in case of spoiler. + +2.34.5 +- Mayhem + Fix cooldown on /q/. + Fix thread creation with no file on /q/. + Fix 'Administrator/Moderator/Developer Replies' creating extra backlinks on /q/. + Add /mlp/ archive redirection. + +2.34.4 +- Mayhem + Add /q/ archive redirection. + +2.34.3 +- Mayhem + Update /k/ archive redirection. + +2.34.2 +- Mayhem + Adjust background tabs max update interval down to 5 minutes instead of 10. + Divide the Delete Link in the Menu into a Post and Image deletion links. + The Delete Links in the Menu now have a cooldown. + Add /fit/ archive redirection. + +2.34.1 +- Mayhem + Add /wsg/ archive redirection. + +2.34.0 +- Mayhem + New feature: Menu, which + - replaces and includes Report Button and Delete Button. + - add one-click Filter buttons. + - add download links to automatically save the file with its original filename. Chrome-only currently. + - add archive links. + - can integrate features from external userscripts/extensions, see https://github.com/MayhemYDG/4chan-x/wiki/Menu-API + The updater's refresh interval will now increase gradually in inactive threads: + - "Inactive thread" defines a thread that has not received any replies since its last refresh. + - Threads receiving a reply will have its updater interval reset to user's setting. + - The refresh interval will grow up to 90 seconds on visible tabs. + - Unfocused tabs will grow up to 120, 300, then 600 seconds. + - It takes at least 230 seconds to get to 120, at least 350 seconds to get to 300, and at least 650 seconds to get to 600. + - Focusing back to a tab will reset its inactivity state to normal. + - It basically changes nothing, but it salvages 4chan from being slaughtered by a massive amount of concurrent connections. + - see http://www.4chan.org/tmp/extensions.html + The updater's refresh interval is now limited to 5 seconds minimum. + Fix the Settings' window size on small screens, should be useable on Opera Mobile. + +2.33.8 +- Mayhem + Add Country filtering. + +2.33.7 +- Mayhem + Add /ck/ archive redirection. + +2.33.6 +- Mayhem + Update/fix archive redirection method. + +2.33.5 +- Mayhem + Add /sp/ archive redirection. + +2.33.4 +- Mayhem + Fix QR with the new captcha loading method. + The QR will now work on /f/ too. + +2.33.3 +- Mayhem + Revert changes that broke fetchers in Firefox. + +2.33.2 +- Mayhem + After 1000+ characters, a character counter will appear in the QR. + Add /soc/ archive redirection. + +2.33.1 +- Mayhem + Add /r9k/ archive redirection. + +2.33.0 +- btmcsweeney + Allow users to specify text for sauce links. +- Mayhem + Dead quotes can now be previewed or inlined with compatible archivers. + Opera fixes. + /f/ fixes. + +2.32.1 +- Mayhem + Fix images uploaded as spoilers. + +2.32.0 +- aeosynth + delete button +- Mayhem + Fix spoiler/code tag keybinds being ignored on post submission. + +2.31.6 +- Mayhem + Update captcha longevity to 5 minutes max, as according to 4chan's change. + +2.31.5 +- Mayhem + Fix spoiler and code tag keybinds regression. + +2.31.4 +- Mayhem + Add /an/ and /toy/ archive redirection. + +2.31.3 +- Mayhem + Add /cgl/, /e/, /mu/ and /w/ archive redirection. + +2.31.2 +- Mayhem + Add /x/ archive redirection. + +2.31.1 +- Mayhem + Fix some stub issues. + +2.31.0 +- Mayhem + Add a per filter stub setting. + +2.30.8 +- Mayhem + Fix quote previewing of forward hidden posts. + +2.30.7 +- aeosynth + Fix expanding comments. +- Mayhem + Fix file size info in case of spoiler image. + +2.30.6 +- Mayhem + Fix file size formatting always using integers. + +2.30.5 +- Mayhem + Fix syntax highlighting in code of fetched posts on /g/. + Add quick [code] tags keybind (alt+c). + +2.30.4 +- Mayhem + Add /co/ and /k/ archive redirection. + Fix quote resurrection of existing posts. + +2.30.3 +- Mayhem + Various bug fixes. + +2.30.2 +- Mayhem + Various bug fixes. + Add seconds as a supported Time Formatting specifier. + +2.30.1 +- Mayhem + Fix 4chan X not affecting fetched posts on Firefox Stable and Opera. + +2.30.0 +- Mayhem + Support 4chan's new HTML. + Add Spoiler indicator option in File Info Formatting + Remove archive.no-ip.org archive redirections. + +2.29.5 +- Mayhem + Fix QR filetype checking on /w/. + +2.29.4 +- Mayhem + Auto-GIF will not run in /gif/. + Fix QR filetype checking. + +2.29.3 +- Mayhem + Update Quick Reply posting method, this fixes compatibility for uncommon browsers such as + Opera Mobile 12 and Luakit for example. + +2.29.2 +- Mayhem + Add HTTPS support. + Ban support improvements and fixes. + +2.29.1 +- Mayhem + Update posting support to use https with sys.4chan.org according to 4chan's latest change. This fixes the 'referer' error. + Update redirection to installgentoo's archives. + +2.29.0 +- Mayhem + New feature: Quote Resurrection, automatically linkifying dead quotes to archives. + +2.28.1 +- Mayhem + General performance improvements. + Threads will now be updated instantly after posting through the QR. + Your own posts will not count toward the unread count after posting through the QR. + Performance issues are now lessened with QR thumbnails of high-res pictures. + You can now use Shift+Click on the file input to remove the selected reply's file. + Reply navigation keybinds will now scroll as you navigate. +- noface + Add unique ID to filter. + +2.28.0 +- ahodesuka + Reply/Thread File Info Formatting: + - Link: %l, %L (Original file names are shown inside threads). + - Size: %B (Bytes), %K (KB), %M (MB), %s (4chan default). + - Resolution/PDF: %r + - Original filename: %n, %N. +- noface + Update imagelimit for /mlp/. + Fix stubs if poster has unique ID. +- Mayhem + You can now filter or highlight admin/mod posts. + New sauce parameter. $4: Current board. + +2.27.1 +- Mayhem + Fix stubs with the new filter. + Fix mail filtering. + The MD5 will now check for exact string matching, it will not use regular expressions. + +2.27.0 +- aeosynth / ahodesuka + new option: expand images from current position +- ahodesuka + Add Open Reply in New Tab option for replies made from the main board (not dumping). + Scroll back up (top of anchor - 42px) when unexpanding images. +- Mayhem + The Filter now has per filter settings: + - Filter the OP only along its thread, replies only, or both. + - Per boards, or global. + - Highlight, or hide. + - Highlighted OPs will have their threads put on top of the board page by default. + New filter group: Image dimensions. + Fix posting on Safari. + Fix rare case where the QR would not accept certain image types. + +2.26.4 +- Mayhem + Add /vg/ archive redirection. + Update ban support with the QR. + Fix history issues on Chrome. + +2.26.3 +- Mayhem + Ensure fresh captcha on QR load. + There is now a reply counter in the QR dump list. + Fix unXXXifier on pages starting with not XXXed numbers. + Update image limit indicator for /vg/. + +2.26.2 +- Mayhem + New option to fix XXX'd post numbers. + Fix post number quoting on /b/ and /v/. + Update archive redirection for /v/. + +2.26.1 +- Mayhem + You can now drag replies in the dump list to reorder them. + Fix sauce links with spoiled thumbnails. + +2.26.0 +- desuwa + New option: remember the size of the QR on Firefox. +- aeosynth + prevent post form flicker +- Mayhem + Load QR's iframe to sys.4chan.org faster, unless you use Greasemonkey. Thanks desuwa. + Increase Sauce linking possibilites: + Thumbnails, full images, MD5 hashes. + New option: Recursive Filtering: Filter replies of filtered posts. + Unread Favicon is now optional, independent of Unread Count. + Fix some compatibility issues with file drag and drop, notably with QuickDrag extension. + +2.25.5 +- Mayhem + Hide the normal post form by default, optional. + +2.25.4 +- Mayhem + Fix text inputs not sent/saved correctly in the QR when pasted for example. + Revert hidding normal post form. + +2.25.3 +- Mayhem + Fix image spoiler always enabled, bug introduced in 2.25.2. + +2.25.2 +- Mayhem + Reverted updater's scrolling behavior. + Fix image posting on Firefox along with Unicode characters in the form. + Ghettofix Greasemonkey compatibility with the new QR. + Greasemonkey is still NOT RECOMMENDED, use Scriptish instead. + +2.25.1 +- Mayhem + Fix missing image filename uploads. Thanks desuwa. + +2.25.0 +- Mayhem + Fix 4chan X on /f/. + Support for the normal post form has been phased out in favor of the new QR. + New rewritten and redesigned Quick Reply. Highlights include: + - Easy dumping for image, text, or samefagging. + - Toggle auto-posting by trying to submit during the cooldown. + - Multiple file selection. + - Image thumbnails. + - Drag and drop files on the page will add these files to the QR. + - Cache captchas with Shift + Enter. + - Create new threads with the QR, will auto-noko. + - Also includes all the previous features: + - Cooldown and auto-posting. + - Posting error detection and prevention. + - Captcha reloading on backspace. + - Auto Watch on reply/thread creation. + - Text selection to quote. + - Etc... + CAUTION: + Images posted with the new QR on Firefox/Aurora/Nightly will have their filename missing. + see https://github.com/MayhemYDG/4chan-x/issues/137 + Greasemonkey is buggy, use Scriptish instead. + +2.24.5 +- Mayhem + Index Navigation and the See next/previous thread keybinds will not cycle through board pages anymore. + Fix archive redirection in Opera. + Opera support will now be temporarily on hold. + see https://github.com/MayhemYDG/4chan-x/issues/136 + +2.24.4 +- ahodesuka + Scroll back up when unexpanding images. +- e000 + Prevent absurd cooldown durations. +- Mayhem + Better image expanding reload, should fool CloudFlare's cache. +- seaweed + Prevent the hover image to be partially masked by the url preview/status bar. + +2.24.3 +- Mayhem + Set image limit in Thread Stats to 252 for /a/ and /v/, default to 152. + Fix 4chan X in locked threads. + +2.24.2 +- mayhem + fix options popping up everytime a page loads + +2.24.1 +- mayhem + fix Open thread in new tab keybind for Safari with Ninjakit + fix Index/Reply Navigation working in both cases when only one is enabled + +2.24.0 +- mayhem + redirect 404'd pictures to archives when possible + new keybind to open the options: ctrl+o + the unread count will decrease when inlining quotes of unread posts + the report button can open multiple popups again + add omploader to the list of optional flavors (http://ompldr.org/upload?url1=) + update archive redirections, add /lit/ and /u/ + fit horizontally for Image Hover + +2.23.7 +- mayhem + update archive redirections + +2.23.6 +- mayhem + fix empty sauce or all flavors commented out from breaking 4chan X + +2.23.5 +- mayhem + increase the thread updater retry timeout limit at each retry + fix selection to quote when selecting started from the end of a line on Firefox + +2.23.4 +- mayhem + thread updater network optimization + prevent regexp errors with the filter + +2.23.3 +- mayhem + fix 2.32.2 regression duplicating new posts in rare cases + +2.23.2 +- mayhem + hide original posts from inlined backlinks - optional + enable autoposting when submitting a captcha while on cooldown + fix caret position when quoting on Opera + +2.23.1 +- mayhem + fix favicon updating on Opera + fix compatibility with Tampermonkey + +2.23.0 +- mayhem + multiple unread favicons to chose in the options + quotes are now inserted at the caret position in the QR + quotes also replace the text selection in the QR + open QR focused when using the `Open QR without post number inserted` keybind + fix thread updater for Opera +- aeosynth + update the captcha caching expiration date to 30mins + +2.22.2 +- mayhem + indicate if the settings require a feature to be enabled + fix obscure and continuous prompts to auto update + +2.22.1 +- mayhem + change 'Duckroll' for 'Cross-thread' + fix image expanding fitness with an inlined backlink on Firefox + +2.22.0 +- mayhem + new Indicate Duckrolls feature + put regex.info sauce back - disabled by default + fix for auto image reloading in 404'd threads on Firefox + +2.21.4 +- mayhem + fix 4chan X version updater + +2.21.3 +- mayhem + fix locked thread icons with fit width/screen enabled on Firefox + fix fit width on Opera + for userstylers: you can use the rendering engine body class + +2.21.2 +- mayhem + fix time formatting year in Opera + fix QR keybinds + fix QR posts getting swallowed by sys.4chan.org + +2.21.1 +- mayhem + fix Opera + +2.21.0 +- mayhem + initiate 4chan X earlier + performance improvements + regular expressions based filter + remove image preloading + automatically reload expanded pictures on error + handle bans with the thread updater + use unread favicons by ferongr + +2.20.3 +- mayhem + fix DST for two days of the year + +2.20.2 +- mayhem + update archive redirection +- aeosynth + hopefully fix qr error / update messages + rm support throd link + +2.20.1 +- mayhem + fix regression: qr not preventing errors + +2.20.0 +- mayhem + do not display inlined quotes within the quote preview + fix cross threads quotes in expanded threads or inlined cross quotes + default post styling for quote previews +- aeosynth + script auto updating + +2.19.3 +- mayhem + quote inlining default styling (by xat) + add up/down/right/left keybinding support +- aeosynth + fixed bug that caused script to fail when time formatting enabled + +2.19.2 +- mayhem + update archives redirections +- aeosynth + change unread favicons (by xat-) + +2.19.1 +- mayhem + fix OP indication in expanded comments + fix no.id links within cross thread/board inlined quote + +2.19.0 +- mayhem + backlink formatting + distinguishable unread favicons on white backgrounds + fix updater refreshing 404'd threads + fix backlinks added into inlined quotes +- aeosynth + fix tab title for 404d threads + +2.18.3 +- mayhem + fix quote features in expanded comments + fix scrolling onto a quote not showing the preview + +2.18.2 +- aeosynth: + fix long thread watcher titles + fix normal form errors with an open empty QR + +2.18.1 +- mayhem: + fix persistent qr not cleaning the file input +- aeosynth: + updater: scroll background tabs + +2.18.0 +- mayhem: + back to normal versioning + bring back auto posting + don't start the cooldown on thread creation + limit the file upload dialog to the accepted file types (qr) +- aeosynth: + show linebreaks as spaces in title & watcher + auto posting fixes + option to remember qr spoiler state + +11.8.15 +- aeosynth: + convert qr from hidden iframes to ajax + derp, nevermind. ajaxing reverted, still working on it in dev branch + +11.8.11.1 +- aeosynth: + fix qr autohiding + +11.8.11.0 +- aeosynth: + - rm auto post checkbox + if (captcha filled or cached) and (text or file) + auto post after cooldown + - options updated immediately instead of requiring page refresh + +11.8.10.1 +- aeosynth: + - persistent captchas (expiring after 4 hours, 55 minutes) + - files upload in 'correct' order + - manually submitting will use cached captchas + +11.8.10.0 +- aeosynth: + - fix captcha caching on blank content + +11.8.9.0 +- aeosynth: + - change green oval archive to gentoomen + - validate filesize asap + - show correct captcha cache length when creating qr + - 1s delay when autoposting after errors to not look so automated + - cache captcha on blank text / file + +11.8.6.0 +- mayhem: + - fix post links in expanded threads + - fix 4chan X in closed threads +- aeosynth: + - only auto scroll focused tabs + - quote inlining: only work on unmodified left-click + - select multiple files (one at a time) + - captcha caching + - qr: optional auto hiding + - copy old textarea value + - scroll to bottom of page if post isn't found (thumbnail generation takes + time) + - only scroll focused tabs + - time: %e, %k, %l + - reverted hovering fix + +2.17.1 +- mayhem: + - fix updater when there is a hash in the url +- aeosynth: + - better hovering fix + +2.17.0 +- mayhem: + - Make updater's settings dynamic + - Multi-line quoting + - keybinds: z: reset unread count (useful when page is not scrollable) + - fix remember updater's interval settings + - fix wrong keybind input in options + - fix time preview + - fix backlink inlining removing its container + - fix options key/keybinds key variables. +- aeosynth: + - new imgur upload link commented out in the sauces + - link to dup file in the QR error + - fix bug with hovering elements not disappearing + +2.16.1 +- mayhem: + - fix updater's custom settings + +2.16.0 +- mayhem: + - Thread Stats performance fix, especially on long threads + - Sauce performance improvement + - fix Quote Inlining for a pattern + - other minor performance improvements and bug fixes +- aeosynth: + - fix an upgrading problem (1.x -> 2.x) + - fix minor bugs with auto-posting + - add updater scrolling + - enable auto-updating by default + - alphabetize option groups + +2.15.1 +- mayhem: + - prevent upload of too large files + - fix options height for netbooks + - /a/ is now archived on easymodo + +2.15.0 +- mayhem: + - custom hotkey binding + - image spoiler revealer + - optional auto noko + - add a class for reply stubs + - fix options centering on Opera + - fix append '#watch' only when auto watch is enabled + - fix cooldown with the normal post form + - fix `Select next reply` hotkey behaviour +- aeosynth: + - keep options dialog at constant size + - drop firefox 3.6 support (again...) + - comment out tineye + - trying to post during cooldown will enable auto-post + - fix errors w/ noscript + +2.14.0 +- mayhem: + - firstrun dialog + - fix backlinking future posts + - fix op non-backlinking + - fix thread expansion on /t/ + - fix sage cooldown + - fix extra link area around images + - fix persistent qr +- aeosynth: + - reply navigation + - fix time formatting of xhr posts + - fix %P time formatting + +2.13.0 +- mayhem: + - fix various bugs + - keybinds: 0: actually refresh page 0 + - auto posting + - add google sauce +- arbitrary time formatting +- rewrite options dialog, lightboxing +- various fixes + +2.12.0 +- revert the status bar blocking changes +- add a 5px padding-bottom to #qp + +2.11.4 +- fix another quoting bug + +2.11.3 +- really fix quoting + +2.11.2 +- fix quoting stuff + +2.11.1 +- work on firefox < 6.0 + +2.11.0 +mayhem: + - fix quote highlighting +- block status bar when hovering quotes / images (may break image leeching) + +2.10.0 +mayhem: + space between backlinks (to prevent them from spilling out of the page) + thread stats: fix wrong selector id when image limit reached + fix localized time + inlined quotes +- fix edge hovering (flip to left of mouse @ right screen edge) +- work on closed threads (some stickies) +- op backlinking option +- quote highlighting option +- (maybe) work on fx3 + +2.9.0 +- mayhem: + better placement of inlined backquotes + fix qr in expanded threads + inline quote fixes + fetch name, mail and pass in cookies at each qr opening + highlight quoted post during quote preview + add ' (OP)' to op quotes + am/pm localized time + give visual feedback on which quote has been inlined + fix paypal link + cooldown: alert only when posting from normal post form + fix cooldown + thread stats + auto noko + fix jumping hover dialogs +- forwardlinks +- rewrite image expansion/fitting +- image expansion option: fit height +- keybind: e - toggle thread expansion +- fix bug where x-board links on chrome are unclickable +- fix x-board / x-thread quoting + +2.8.1 +- tab over captcha + +2.8.0 +- mayhem: + redesigned options + don't backlink op on index pages + base64 donate button +- fix qr replying to wrong thread +- small tweaks + +2.7.0 +- mayhem: + add class to reply hider and report buttons + fix anonymizer +- inline quoting +- don't break on >>>/board/ links (links w/o an id) +- remove op backlinking +- fix qr on expanded posts +- image hover: fit height + +2.6.0 +- mayhem: + start backlinks + fix watcher refresh false positive +- backlinks +- cross-board previews +- fix menu for opera +- slightly bigger qr textarea + +2.5.0 +- mayhem: + qp: better cross-thread op quoting + qp: fix overflowing preview + qr: prevent email field from popping out + qr: fix cloning values +- keybinds: fix m + +2.4.2 +- fix nodeInserted (work on new posts) +- qr: remember name + +2.4.1 +- fix image expansion bug + +2.4.0 +- mayhem: + auto watch reply + fix report button splitting over two lines + start merging /b/ackwash +- quote previews +- qr remix + +2.3.0 +- mayhem: + refresh watcher list on un/watch + auto refresh watcher list + update no-ip.org archive + fix auto-watch +- flavor comments + +2.2.2 +- hopefully fix upgrading issues + +2.2.1 +- mayhem: + fix op image expansion bug + fix op comment expansion + +- fix /b/ackwash multiple links bug +- make cooldown timer optional, disabled by default + +2.2.0 +- mayhem: + - don't select text when moving dialogs + - fix thread watcher's padding + - remove captcha logos from quick reply + - post in title - show default title when no subject/comment + - update tab title on 404 + - chrome - fix favicons + - fix 404 favicon + - fix updater retrying + - set timer to 0 on manual update + - fix threading when op's file is deleted + +- fix navigating past hidden threads +- fix updater option - verbose +- only navigate to pages that exist +- use Greasemonkey api (sigh) +- rewrite, reenable cooldown +- better image resize algorithm + +2.1.0 +- added back the 0 keybind - go to board's front page + +2.0.0 +- [chrome] qr error notifications +- x-browser auto-watch +- image expansion w/o horizontal scrollbars +- removed reply nav +- floating thread nav +- fix /b/ thread nav +- ignore middle clicks on images +- smarter redirect +- remove all GM_ functions +- [chrome] fix slow scrolling w/ unread post count in titlebar +- keybind: x: hide thread +- qr: remove `auto` +- rewrite / reorganize code + +1.27.8 +- fix qr image posting +- fix thread hiding +- fix movement + +1.27.7 +- fix qr persist +- fix updater defaults + +1.27.6 +- fix 'update now' button + +1.27.5 +- fix regression - reload captcha after posting + +1.27.4 +- fix imageHover on chrome + +1.27.3 +- fix regression - movement + +1.27.2 +- fix regression - close / refresh qr on chrome +- add updateURL for scriptish + +1.27.1 +- fix regression - unhide qr when quoting + +1.27.0 +- x-browser qr error checking (except for batshit insane chrome - see + http://code.google.com/p/chromium/issues/detail?id=20773) +- fix opera movement, again +- bigger options button +- move updater to bottom-right by default + +1.26.3 +- don't enable reply nav by default +- reset file input after posting (persistent qr) +- remove restore ids +- check for dst + +1.26.2 +- fix thread watcher position; remember new position + +1.26.1 +- fix unread count for opera +- fix default thread watcher placement + +1.26.0 +- image hover +- support/donate + +1.25.0 +- auto gif +- only preload in threads +- fix autohide +- sage cooldown = 60s + +1.24.0 +- image preloading + +1.23.1 +- fix updater notifications + +1.23.0 +- 'verbose' updater option +- remove /new/, /r9k/ from archivers +- tweak 'fit width' to get rid of horizontal scrollbar, only partially working + +1.22.0 +- update archives +- tweak updater feedback/ui + +1.21.0 +- image expansion types +- move global auto update option to updater dialog + +1.20.4 +- fix options + +1.20.3 +- update archives +- fool the cache + +1.20.2 +- fix qr again + +1.20.1 +- fix disappearing updater bug +- only restore ids on /b/ and /v/ +- fix JK keybinds + +1.20.0 +- keybinds + - add u - update now + - remove hHlLjk, numerical prefixes + - use [vimus](http://userscripts.org/scripts/show/93187) for non-chan keybinds +- fix slow scrolling +- add replies in original order so backlinks resolve properly +- fix qr quoting + +1.19.0 +- restore ids +- thread updater + +1.18.4 +- fix qr quoting of selected text + +1.18.3 +- fix w / i / I keybinds +- git rid of body padding + +1.18.2 +- logic fail + +1.18.1 +- only adding padding when not in replies + +1.18.0 +- body { padding-bottom } when Thread Navigation +- keybinds + - insert mode + ^s - quick spoiler + escape - remove quick reply + - normal mode + h/l - scroll left/right, H/L - move pages + m/M - expand selected / all images + w - watch thread (changed from m) + +1.17.5 +- fix threading +- fix images + +1.17.4 +- yeah i guess margin is cool too + +1.17.3 +- a img { float: left; } + +1.17.2 +- expand images in new posts + +1.17.1 +- don't affect image clicks when ctrl | alt | shift held +- add .hide class so thumbnail hiding works + +1.17.0 +- image expansion + +1.16.0 +- I - open blank quick reply + +1.15.0 +- add archive at 173.74.0.45 + +1.14.1 +- fix thread nav + +1.14.0 +- reply keybinds: i, J, K + +1.13.0 +- localize time + +1.12.1 +- actually disable keybinds by default + +1.12.0 +- disable keybinds by default +- qr to replies +- J/K - select next / previous reply +- smarter scrolling + +1.11.1 +- fix reply mode switching (bringing up quick reply now correctly disables +keybinds) + +1.11.0 +- reply keybinds +- repeatable keybinds +- change keybinds: + - o = open thread in new tab + - i = enter insert mode and open quick reply + +1.10.1 +- fix kb thread nav +- hack to focus qr +- absolute positioning for `g` keybind + +1.10.0 +- keyboard actions: + - m to _mark (watch) threads + - t to open threads in _tabs + - o to _open quick reply +- better mode switching +- turn on keyboard actions + +1.9.1 +- add `count` for keynav +- disable keynav when quick replying +- make keynav disabled by default + +1.9.0 +- add keyboard navigation + +1.8.3 +- try to fix remaining bugs by making global variables explicitly global + +1.8.2 +- fix chromium + +1.8.1 +- fix bugs in 1.8.0 + +1.8.0 +- add backspace recaptcha refreshing to reports page + +1.7.4 +- fix thread watching + +1.7.3 +- fixed descriptions + +1.7.2 +- add option descriptions + +1.7.0 +- add auto in qr + +1.6.0 +- add cooldown timer + +1.5.0 +1.4.4 +- mirror options button on bottom of page +- add 4chan sauce +- add 404 redirect +- add post in title +- reload captcha on backspace + +1.4.3 +- clear captcha on submit + +1.4.2 +- fix for firefox 4.0b6 + +1.4.1 +- unhide qr when reply link clicked +- clear textarea on successful qr +- reload captcha AFTER removing qr + +1.4 +- add 'Persistent QR' +- QR autohiding + +1.3 +- auto reload captcha on success + +1.2 +- alert on no captcha + +1.1 +- re-add button to clear hidden posts. + +1.0 +- Complete rewrite (well, like 98%). +- Split off updater - 4chan x Updater + +0.26 +- Fix /b/ quick reply +- Add initial 'Auto Watch' implementation + +0.25 +- fix Opera 10.50 thread updater bug +- require Opera 10.50 +- remove 'Quick Post' (just use noko) +- remove / automate 'manual clear' +- make thread stubs clickable + +0.24 - Worksafe threads show the correct favicon. Thanks for the art, Ongpot! + +0.23 - Show post count for hidden threads + +0.22 - thread navigating now can navigate to previous pages, fixed opera issue + +0.21 - chrome compatibility + +0.20 - added selection quoting, quick post, unread reply count in title. + +0.19 - added quick reply error notifications + +0.17 - added 'Update Favicon' option. Thanks thisisanon! + +0.16 - added new reply notifications. scroll to end of thread to remove them. + +0.15 - added thread updater button + +0.14 - moved reply hiding to 4chan filter + +0.13 - added thread watcher close button, thread watcher toggle button + +0.12 - added Show Hidden (NOTE: not fully compatible w/ 4chan filter yet); thread updater works through connection problems + +0.11 - made hidden replies persistent, added Clear Hidden. + +0.10 - report button added + +0.9 - forced anon added + +0.8 - all watched threads visible all the time + +0.7 - added reply nav buttons + +0.6 - added thread updating + +0.4.1/0.5 - added options, quick reply shading + +0.4 - added quick reply + +0.3 - added thread watching + +0.2 - added post expanding + +0.1 - added post hiding + +0.0 - thread hiding, expanding, navigating diff --git a/html/Monitoring/ThreadStats.html b/html/Monitoring/ThreadStats.html new file mode 100644 index 000000000..f6d932e43 --- /dev/null +++ b/html/Monitoring/ThreadStats.html @@ -0,0 +1,3 @@ +
+ ... / ... / ... +
diff --git a/html/Posting/QR.html b/html/Posting/QR.html new file mode 100644 index 000000000..b34fb36b3 --- /dev/null +++ b/html/Posting/QR.html @@ -0,0 +1,38 @@ +
+ + + + × +
+
+
+ + + + +
+
+
+ + +
+
+ + +
+
+ + + + No selected file + + + × + +
+ +
+ + + diff --git a/package.json b/package.json index 6ccc779f7..73fe4b5b0 100644 --- a/package.json +++ b/package.json @@ -21,15 +21,15 @@ }, "devDependencies": { "grunt": "~0.4.1", - "grunt-bump": "~0.0.2", - "grunt-concurrent": "~0.2.0", - "grunt-contrib-clean": "~0.4.1", + "grunt-bump": "~0.0.11", + "grunt-concurrent": "~0.3.0", + "grunt-contrib-clean": "~0.5.0", "grunt-contrib-coffee": "~0.7.0", - "grunt-contrib-compress": "~0.5.1", + "grunt-contrib-compress": "~0.5.2", "grunt-contrib-concat": "~0.3.0", "grunt-contrib-copy": "~0.4.1", - "grunt-contrib-watch": "~0.4.4", - "grunt-shell": "~0.2.2" + "grunt-contrib-watch": "~0.5.0", + "grunt-shell": "~0.3.1" }, "repository": { "type": "git", diff --git a/src/Archive/Redirect.coffee b/src/Archive/Redirect.coffee index e9b5256b5..effc42e71 100644 --- a/src/Archive/Redirect.coffee +++ b/src/Archive/Redirect.coffee @@ -21,7 +21,6 @@ Redirect = Redirect.post[boardID] = archive unless boardID of Redirect.file or !archive.files.contains boardID Redirect.file[boardID] = archive - return archives: 'Foolz': @@ -29,7 +28,7 @@ Redirect = 'http': false 'https': true 'software': 'foolfuuka' - 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'v', 'vg', 'vp', 'vr', 'wsg'] + 'boards': ['a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vg', 'vp', 'vr', 'wsg'] 'files': ['a', 'gd', 'jp', 'm', 'q', 'tg', 'vg', 'vp', 'vr', 'wsg'] 'NSFW Foolz': @@ -63,14 +62,6 @@ Redirect = 'boards': ['c', 'w', 'wg'] 'files': ['c', 'w', 'wg'] - 'Love is Over': - 'domain': 'loveisover.me' - 'http': true - 'https': true - 'software': 'foolfuuka' - 'boards': ['d', 'h', 'v'] - 'files': ['d', 'h', 'v'] - 'Foolz a Shit': 'domain': 'archive.foolzashit.com' 'http': true @@ -82,7 +73,7 @@ Redirect = 'Install Gentoo': 'domain': 'archive.installgentoo.net' 'http': true - 'https': true + 'https': false 'software': 'fuuka' 'boards': ['diy', 'g', 'sci'] 'files': [] @@ -109,6 +100,14 @@ Redirect = 'software': 'fuuka' 'boards': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'tg', 'vr'] 'files': ['3', 'cgl', 'ck', 'fa', 'ic', 'jp', 'lit', 'q', 'vr'] + + 'worldathleticproject': + 'domain': 'fuuka.worldathleticproject.org' + 'http': true + 'https': true + 'software': 'foolfuuka' + 'boards': ['e', 'h', 'p', 's', 'u'] + 'files': ['e', 'h', 'p', 's', 'u'] to: (dest, data) -> archive = (if dest is 'search' then Redirect.thread else Redirect[dest])[data.boardID] diff --git a/src/Filtering/Filter.coffee b/src/Filtering/Filter.coffee index ca11455cb..3da882a11 100644 --- a/src/Filtering/Filter.coffee +++ b/src/Filtering/Filter.coffee @@ -209,7 +209,7 @@ Filter = el = $.el 'a', href: 'javascript:;' textContent: text - el.setAttribute 'data-type', type + el.dataset.type = type $.on el, 'click', Filter.menu.makeFilter return { diff --git a/src/Filtering/ThreadHiding.coffee b/src/Filtering/ThreadHiding.coffee index a760b24d1..a1d9a79f8 100644 --- a/src/Filtering/ThreadHiding.coffee +++ b/src/Filtering/ThreadHiding.coffee @@ -113,7 +113,7 @@ ThreadHiding = className: "#{type}-thread-button" innerHTML: " #{if type is 'hide' then '-' else '+'} " href: 'javascript:;' - a.setAttribute 'data-fullid', thread.fullID + a.dataset.fullID = thread.fullID $.on a, 'click', ThreadHiding.toggle a @@ -134,7 +134,7 @@ ThreadHiding = toggle: (thread) -> unless thread instanceof Thread - thread = g.threads[@dataset.fullid] + thread = g.threads[@dataset.fullID] if thread.isHidden ThreadHiding.show thread else diff --git a/src/General/Build.coffee b/src/General/Build.coffee index 6d87269a1..4f4453e6d 100644 --- a/src/General/Build.coffee +++ b/src/General/Build.coffee @@ -108,12 +108,12 @@ Build = capcodeStart = '' capcode = '' - flag = - if flagCode - " #{flagCode}" - else - '' + flag = unless flagCode + '' + else if boardID is 'pol' + " #{flagCode}" + else + " " if file?.isDeleted fileHTML = if isOP diff --git a/src/General/Get.coffee b/src/General/Get.coffee index a66bce292..a5c1a54c1 100644 --- a/src/General/Get.coffee +++ b/src/General/Get.coffee @@ -19,7 +19,7 @@ Get = if index then post.clones[index] else post postFromNode: (root) -> Get.postFromRoot $.x 'ancestor::div[contains(@class,"postContainer")][1]', root - contextFromLink: (quotelink) -> + contextFromNode: (quotelink) -> Get.postFromRoot $.x 'ancestor::div[parent::div[@class="thread"]][1]', quotelink postDataFromLink: (link) -> if link.hostname is 'boards.4chan.org' @@ -28,9 +28,8 @@ Get = threadID = path[3] postID = link.hash[2..] else # resurrected quote - boardID = link.dataset.boardid - threadID = link.dataset.threadid or 0 - postID = link.dataset.postid + {boardID, threadID, postID} = link.dataset + threadID or= 0 return { boardID: boardID threadID: +threadID @@ -185,7 +184,7 @@ Get = # quotes .replace /((>){2}(>\/[a-z\d]+\/)?\d+)/g, '$1' - threadID = data.thread_num + threadID = +data.thread_num o = # id postID: "#{postID}" diff --git a/src/General/Globals.coffee b/src/General/Globals.coffee index ad48281e4..d5d09eaa6 100644 --- a/src/General/Globals.coffee +++ b/src/General/Globals.coffee @@ -1,9 +1,3 @@ -<% if (type === 'userjs') { %> -# Opera doesn't support the @match metadata key, -# return 4chan X here if we're not on 4chan. -return unless /^(boards|images|sys)\.4chan\.org$/.test location.hostname -<% } %> - Conf = {} c = console d = document diff --git a/src/General/Header.coffee b/src/General/Header.coffee index 278e2ebc6..783b3f9fe 100644 --- a/src/General/Header.coffee +++ b/src/General/Header.coffee @@ -70,7 +70,7 @@ Header = return unless Main.isThisPageLegit() # Wait for #boardNavMobile instead of #boardNavDesktop, # it might be incomplete otherwise. - $.asap (-> $.id('boardNavMobile') or d.readyState in ['interactive', 'complete']), Header.setBoardList + $.asap (-> $.id('boardNavMobile') or d.readyState isnt 'loading'), Header.setBoardList $.prepend d.body, @bar $.add d.body, Header.hover @setBarPosition Conf['Bottom Header'] @@ -131,7 +131,7 @@ Header = list = $ '#custom-board-list', Header.bar $.rmAll list return unless text - as = $$('#full-board-list a', Header.bar) + as = $$ '#full-board-list a[title]', Header.bar nodes = text.match(/[\w@]+((-(all|title|replace|full|index|catalog|url:"[^"]+[^"]"|text:"[^"]+")|\,"[^"]+[^"]"))*|[^\w@]+/g).map (t) -> if /^[^\w@]/.test t return $.tn t @@ -166,7 +166,7 @@ Header = a.textContent if m = t.match /-(index|catalog)/ - a.setAttribute 'data-only', m[1] + a.dataset.only = m[1] a.href = "//boards.4chan.org/#{board}/" if m[1] is 'catalog' a.href += 'catalog' diff --git a/src/General/Main.coffee b/src/General/Main.coffee index bb661e8a5..4116ec1c7 100644 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -19,7 +19,7 @@ Main = $.get Conf, Main.initFeatures $.on d, '4chanMainInit', Main.initStyle - $.asap (-> d.head and $('link[rel="shortcut icon"]', d.head) or d.readyState in ['interactive', 'complete']), + $.asap (-> d.head and $('link[rel="shortcut icon"]', d.head) or d.readyState isnt 'loading'), Main.initStyle initFeatures: (items) -> @@ -141,8 +141,6 @@ Main = <% if (type === 'crx') { %> $.addClass doc, 'webkit' $.addClass doc, 'blink' - <% } else if (type === 'userjs') { %> - $.addClass doc, 'presto' <% } else { %> $.addClass doc, 'gecko' <% } %> @@ -166,13 +164,9 @@ Main = $.addClass doc, style setStyle() return unless mainStyleSheet - if window.MutationObserver - observer = new MutationObserver setStyle - observer.observe mainStyleSheet, - attributes: true - attributeFilter: ['href'] - else - $.on mainStyleSheet, 'DOMAttrModified', setStyle + new MutationObserver(setStyle).observe mainStyleSheet, + attributes: true + attributeFilter: ['href'] initReady: -> if d.title is '4chan - 404 Not Found' @@ -192,20 +186,18 @@ Main = threads = [] posts = [] - for boardChild in board.children - continue unless $.hasClass boardChild, 'thread' - thread = new Thread boardChild.id[1..], g.BOARD + for threadRoot in $$ '.board > .thread', board + thread = new Thread +threadRoot.id[1..], g.BOARD threads.push thread - for threadChild in boardChild.children - continue unless $.hasClass threadChild, 'postContainer' + for postRoot in $$ '.thread > .postContainer', threadRoot try - posts.push new Post threadChild, thread, g.BOARD + posts.push new Post postRoot, thread, g.BOARD catch err # Skip posts that we failed to parse. unless errors errors = [] errors.push - message: "Parsing of Post No.#{threadChild.id.match(/\d+/)} failed. Post will be skipped." + message: "Parsing of Post No.#{postRoot.id.match(/\d+/)} failed. Post will be skipped." error: err Main.handleErrors errors if errors @@ -373,7 +365,7 @@ Main = unless 'thisPageIsLegit' of Main Main.thisPageIsLegit = location.hostname is 'boards.4chan.org' and !$('link[href*="favicon-status.ico"]', d.head) and - d.title not in ['4chan - Temporarily Offline', '4chan - Error'] + d.title not in ['4chan - Temporarily Offline', '4chan - Error', '504 Gateway Time-out'] Main.thisPageIsLegit css: """ diff --git a/src/General/Settings.coffee b/src/General/Settings.coffee index 8f27bf2ed..3b85f7e29 100644 --- a/src/General/Settings.coffee +++ b/src/General/Settings.coffee @@ -466,7 +466,6 @@ Settings = $.cb.checked.call @ usercss: -> CustomCSS.update() - keybinds: (section) -> section.innerHTML = """ <%= grunt.file.read('src/General/html/Settings/Keybinds.html').replace(/>\s+<').trim() %> diff --git a/src/General/UI.coffee b/src/General/UI.coffee index fee438838..f4bbc30a8 100644 --- a/src/General/UI.coffee +++ b/src/General/UI.coffee @@ -306,12 +306,12 @@ UI = do -> hoverstart = ({root, el, latestEvent, endEvents, asapTest, cb}) -> o = { - root: root - el: el - style: el.style - cb: cb - endEvents: endEvents - latestEvent: latestEvent + root + el + style: el.style + cb + endEvents + latestEvent clientHeight: doc.clientHeight clientWidth: doc.clientWidth } @@ -327,6 +327,11 @@ UI = do -> if $.x 'ancestor::div[contains(@class,"inline")][1]', root $.on d, 'keydown', o.hoverend $.on root, 'mousemove', o.hover + <% if (type === 'userscript') { %> + # Workaround for https://github.com/MayhemYDG/4chan-x/issues/377 + o.workaround = (e) -> o.hoverend() unless root.contains e.target + $.on doc, 'mousemove', o.workaround + <% } %> hover = (e) -> @latestEvent = e @@ -357,6 +362,10 @@ UI = do -> $.off @root, @endEvents, @hoverend $.off d, 'keydown', @hoverend $.off @root, 'mousemove', @hover + <% if (type === 'userscript') { %> + # Workaround for https://github.com/MayhemYDG/4chan-x/issues/377 + $.off doc, 'mousemove', @workaround + <% } %> @cb.call @ if @cb diff --git a/src/General/css/style.css b/src/General/css/style.css index d6b579c60..b6e627c21 100644 --- a/src/General/css/style.css +++ b/src/General/css/style.css @@ -301,10 +301,8 @@ a { box-sizing: border-box; box-shadow: 0 0 15px rgba(0, 0, 0, .15); height: 600px; - min-height: 0; max-height: 100%; width: 900px; - min-width: 0; max-width: 100%; margin: auto; padding: 3px; @@ -312,7 +310,6 @@ a { left: 50%; -moz-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); - -o-transform: translate(-50%, -50%); transform: translate(-50%, -50%); } #fourchanx-settings > nav { @@ -389,14 +386,17 @@ a { position: absolute; } .section-advanced .note { - font-size: 0.8em; - font-style: italic; + font-size: 0.8em; + font-style: italic; margin-left: 10px; } .section-advanced .note code { font-style: normal; font-size: 11px; } +.section-keybinds .field { + font-family: monospace; +} #fourchanx-settings fieldset { border: 1px solid; border-radius: 3px; @@ -530,7 +530,8 @@ a.hide-announcement { .deadlink { text-decoration: none !important; } -.backlink.deadlink:not(.forwardlink), .quotelink.deadlink:not(.forwardlink) { +.backlink.deadlink:not(.forwardlink), +.quotelink.deadlink:not(.forwardlink) { text-decoration: underline !important; } .inlined { @@ -573,8 +574,6 @@ a.hide-announcement { padding: 2px 2px 5px; } #qp img { - max-height: 300px; - max-width: 500px; max-height: 80vh; max-width: 50vw; } @@ -610,8 +609,7 @@ a.hide-announcement { :root.fit-width .full-image { max-width: 100%; } -:root.gecko.fit-width .full-image, -:root.presto.fit-width .full-image { +:root.gecko.fit-width .full-image { width: 100%; } #ihover { @@ -668,7 +666,10 @@ a.hide-announcement { #file-n-submit:not(.has-file) #qr-filerm { display: none; } -#qr select, #dump-button, .remove, .captcha-img { +#qr select, +#dump-button, +.remove, +.captcha-img { cursor: pointer; } #qr { @@ -725,7 +726,8 @@ a.hide-announcement { height: 9em; } input.field.tripped:not(:hover):not(:focus) { - color: transparent !important; text-shadow: none !important; + color: transparent !important; + text-shadow: none !important; } #qr textarea { resize: both; @@ -907,7 +909,9 @@ a:only-of-type > .remove { .qr-preview > label { background: rgba(0,0,0,.5); color: #fff; - right: 0; bottom: 0; left: 0; + right: 0; + bottom: 0; + left: 0; position: absolute; text-align: center; } diff --git a/src/General/html/Settings/Filter-guide.html b/src/General/html/Settings/Filter-guide.html index 3e50d37e3..3e78003d2 100644 --- a/src/General/html/Settings/Filter-guide.html +++ b/src/General/html/Settings/Filter-guide.html @@ -1,6 +1,6 @@
Filter is disabled.

- Use regular expressions, one per line.
+ Use regular expressions, one per line.
Lines starting with a # will be ignored.
For example, /weeaboo/i will filter posts containing the string `weeaboo`, case-insensitive.
MD5 filtering uses exact string matching, not regular expressions. @@ -26,4 +26,4 @@ Highlighted OPs will have their threads put on top of board pages by default.
For example: top:yes; or top:no;. - \ No newline at end of file + diff --git a/src/General/lib/$.coffee b/src/General/lib/$.coffee index a09700461..c9d50c4ff 100644 --- a/src/General/lib/$.coffee +++ b/src/General/lib/$.coffee @@ -49,7 +49,7 @@ $.id = (id) -> d.getElementById id $.ready = (fc) -> - if d.readyState in ['interactive', 'complete'] + unless d.readyState is 'loading' $.queueTask fc return cb = -> @@ -221,9 +221,7 @@ $.event = (event, detail, root=d) -> $.open = (URL) -> <% if (type === 'userscript') { %> - # XXX fix GM opening file://// for protocol-less URLs. - # https://github.com/greasemonkey/greasemonkey/issues/1719 - GM_openInTab ($.el 'a', href: URL).href + $.open = (URL) -> GM_openInTab URL <% } else { %> window.open URL, '_blank' <% } %> @@ -298,29 +296,21 @@ $.minmax = (value, min, max) -> value ) -$.syncing = {} +$.item = (key, val) -> + item = {} + item[key] = val + item -$.sync = do -> +$.syncing = {} <% if (type === 'crx') { %> +$.sync = do -> chrome.storage.onChanged.addListener (changes) -> for key of changes if cb = $.syncing[key] cb changes[key].newValue return (key, cb) -> $.syncing[key] = cb -<% } else { %> - window.addEventListener 'storage', (e) -> - if cb = $.syncing[e.key] - cb JSON.parse e.newValue - , false - (key, cb) -> $.syncing[g.NAMESPACE + key] = cb -<% } %> -$.item = (key, val) -> - item = {} - item[key] = val - item -<% if (type === 'crx') { %> $.localKeys = [ # filters 'name', @@ -372,6 +362,7 @@ $.get = (key, val, cb) -> if syncItems count++ chrome.storage.sync.get syncItems, done + $.set = do -> items = {} localItems = {} @@ -396,54 +387,14 @@ $.set = do -> $.extend items, key set() -<% } else if (type === 'userjs') { %> -do -> - # http://www.opera.com/docs/userjs/specs/#scriptstorage - # http://www.opera.com/docs/userjs/using/#securepages - # The scriptStorage object is available only during - # the main User JavaScript thread, being therefore - # accessible only in the main body of the user script. - # To access the storage object later, keep a reference - # to the object. - {scriptStorage} = opera - $.delete = (keys) -> - unless keys instanceof Array - keys = [keys] - for key in keys - key = g.NAMESPACE + key - localStorage.removeItem key - delete scriptStorage[key] - return - $.get = (key, val, cb) -> - if typeof cb is 'function' - items = $.item key, val - else - items = key - cb = val - $.queueTask -> - for key of items - if val = scriptStorage[g.NAMESPACE + key] - items[key] = JSON.parse val - cb items - $.set = do -> - set = (key, val) -> - key = g.NAMESPACE + key - val = JSON.stringify val - if key of $.syncing - # for `storage` events - localStorage.setItem key, val - scriptStorage[key] = val - (keys, val) -> - if typeof keys is 'string' - set keys, val - return - for key, val of keys - set key, val - return - return <% } else { %> - # http://wiki.greasespot.net/Main_Page +$.sync = do -> + $.on window, 'storage', (e) -> + if cb = $.syncing[e.key] + cb JSON.parse e.newValue + (key, cb) -> $.syncing[g.NAMESPACE + key] = cb + $.delete = (keys) -> unless keys instanceof Array keys = [keys] diff --git a/src/General/lib/clone.class b/src/General/lib/clone.class index d05541491..547afe1db 100644 --- a/src/General/lib/clone.class +++ b/src/General/lib/clone.class @@ -59,5 +59,4 @@ class Clone extends Post @isDead = true if origin.isDead @isClone = true - index = origin.clones.push(@) - 1 - root.setAttribute 'data-clone', index \ No newline at end of file + root.dataset.clone = origin.clones.push(@) - 1 diff --git a/src/General/lib/post.class b/src/General/lib/post.class index ad15b902f..d823a8f93 100644 --- a/src/General/lib/post.class +++ b/src/General/lib/post.class @@ -16,29 +16,34 @@ class Post quotelinks: [] backlinks: info.getElementsByClassName 'backlink' + unless @isReply = $.hasClass post, 'reply' + @thread.OP = @ + @thread.isSticky = !!$ '.stickyIcon', info + @thread.isClosed = !!$ '.closedIcon', info + @info = {} - if subject = $ '.subject', info + if subject = $ '.subject', info @nodes.subject = subject @info.subject = subject.textContent - if name = $ '.name', info + if name = $ '.name', info @nodes.name = name @info.name = name.textContent - if email = $ '.useremail', info + if email = $ '.useremail', info @nodes.email = email @info.email = decodeURIComponent email.href[7..] - if tripcode = $ '.postertrip', info + if tripcode = $ '.postertrip', info @nodes.tripcode = tripcode @info.tripcode = tripcode.textContent - if uniqueID = $ '.posteruid', info + if uniqueID = $ '.posteruid', info @nodes.uniqueID = uniqueID @info.uniqueID = uniqueID.firstElementChild.textContent - if capcode = $ '.capcode.hand', info + if capcode = $ '.capcode.hand', info @nodes.capcode = capcode @info.capcode = capcode.textContent.replace '## ', '' - if flag = $ '.countryFlag', info + if flag = $ '.flag, .countryFlag', info @nodes.flag = flag @info.flag = flag.title - if date = $ '.dateTime', info + if date = $ '.dateTime', info @nodes.date = date @info.date = new Date date.dataset.utc * 1000 if Conf['Quick Reply'] @@ -50,43 +55,7 @@ class Post @parseComment() @parseQuotes() - - if (file = $ '.file', post) and thumb = $ 'img[data-md5]', file - # Supports JPG/PNG/GIF/PDF. - # Flash files are not supported. - alt = thumb.alt - anchor = thumb.parentNode - fileInfo = file.firstElementChild - @file = - info: fileInfo - text: fileInfo.firstElementChild - thumb: thumb - URL: anchor.href - size: alt.match(/[\d.]+\s\w+/)[0] - MD5: thumb.dataset.md5 - isSpoiler: $.hasClass anchor, 'imgspoiler' - size = +@file.size.match(/[\d.]+/)[0] - unit = ['B', 'KB', 'MB', 'GB'].indexOf @file.size.match(/\w+$/)[0] - size *= 1024 while unit-- > 0 - @file.sizeInBytes = size - @file.thumbURL = - if that.isArchived - thumb.src - else - "#{location.protocol}//thumbs.4chan.org/#{board}/thumb/#{@file.URL.match(/(\d+)\./)[1]}s.jpg" - # replace %22 with quotes, see: - # crbug.com/81193 - # webk.it/62107 - # https://www.w3.org/Bugs/Public/show_bug.cgi?id=16909 - # http://www.whatwg.org/specs/web-apps/current-work/#multipart-form-data - @file.name = $('span[title]', fileInfo).title.replace /%22/g, '"' - if @file.isImage = /(jpg|png|gif)$/i.test @file.name - @file.dimensions = @file.text.textContent.match(/\d+x\d+/)[0] - - unless @isReply = $.hasClass post, 'reply' - @thread.OP = @ - @thread.isSticky = !!$ '.stickyIcon', @nodes.info - @thread.isClosed = !!$ '.closedIcon', @nodes.info + @parseFile(that) @clones = [] g.posts[@fullID] = thread.posts[@] = board.posts[@] = @ @@ -110,18 +79,18 @@ class Post nodes = d.evaluate './/br|.//text()', bq, null, 7, null i = 0 while i < nodes.snapshotLength - text.push if data = nodes.snapshotItem(i++).data then data else '\n' + text.push nodes.snapshotItem(i++).data or '\n' @info.comment = text.join('').trim().replace /\s+$/gm, '' parseQuotes: -> quotes = {} for quotelink in $$ '.quotelink', @nodes.comment # Don't add board links. (>>>/b/) - hash = quotelink.hash + {hash} = quotelink continue unless hash # Don't add catalog links. (>>>/b/catalog or >>>/b/search) - pathname = quotelink.pathname + {pathname} = quotelink continue if /catalog$/.test pathname # Don't add rules links. (>>>/a/rules) @@ -130,14 +99,49 @@ class Post @nodes.quotelinks.push quotelink - # Don't count capcode replies as quotes. (Admin/Mod/Dev Replies: ...) - continue if quotelink.parentNode.parentNode.className is 'capcodeReplies' + # Don't count capcode replies as quotes in OPs. (Admin/Mod/Dev Replies: ...) + continue if !@isReply and $.hasClass quotelink.parentNode.parentNode, 'capcodeReplies' # Basically, only add quotes that link to posts on an imageboard. quotes["#{pathname.split('/')[1]}.#{hash[2..]}"] = true return if @isClone @quotes = Object.keys quotes + parseFile: (that) -> + return unless (fileEl = $ '.file', @nodes.post) and thumb = $ 'img[data-md5]', fileEl + # Supports JPG/PNG/GIF/PDF. + # Flash files are not supported. + alt = thumb.alt + anchor = thumb.parentNode + fileInfo = fileEl.firstElementChild + @file = + info: fileInfo + text: fileInfo.firstElementChild + thumb: thumb + URL: anchor.href + size: alt.match(/[\d.]+\s\w+/)[0] + MD5: thumb.dataset.md5 + isSpoiler: $.hasClass anchor, 'imgspoiler' + size = +@file.size.match(/[\d.]+/)[0] + unit = ['B', 'KB', 'MB', 'GB'].indexOf @file.size.match(/\w+$/)[0] + size *= 1024 while unit-- > 0 + @file.sizeInBytes = size + @file.thumbURL = if that.isArchived + thumb.src + else + "#{location.protocol}//thumbs.4chan.org/#{@board}/thumb/#{@file.URL.match(/(\d+)\./)[1]}s.jpg" + @file.name = $('span[title]', fileInfo).title + <% if (type === 'crx') { %> + # replace %22 with quotes, see: + # crbug.com/81193 + # webk.it/62107 + # https://www.w3.org/Bugs/Public/show_bug.cgi?id=16909 + # http://www.whatwg.org/specs/web-apps/current-work/#multipart-form-data + @file.name = @file.name.replace /%22/g, '"' + <% } %> + if @file.isImage = /(jpg|png|gif)$/i.test @file.name + @file.dimensions = @file.text.textContent.match(/\d+x\d+/)[0] + kill: (file, now) -> now or= new Date() if file @@ -192,10 +196,12 @@ class Post quotelink.textContent = quotelink.textContent.replace '\u00A0(Dead)', '' $.rmClass quotelink, 'deadlink' return + addClone: (context) -> new Clone @, context + rmClone: (index) -> @clones.splice index, 1 for clone in @clones[index..] - clone.nodes.root.setAttribute 'data-clone', index++ - return \ No newline at end of file + clone.nodes.root.dataset.clone = index++ + return diff --git a/src/General/lib/thread.class b/src/General/lib/thread.class index e8027a1c4..57d82a316 100644 --- a/src/General/lib/thread.class +++ b/src/General/lib/thread.class @@ -2,8 +2,7 @@ class Thread callbacks: [] toString: -> @ID - constructor: (ID, @board) -> - @ID = +ID + constructor: (@ID, @board) -> @fullID = "#{@board}.#{@ID}" @posts = {} @@ -11,4 +10,4 @@ class Thread kill: -> @isDead = true - @timeOfDeath = Date.now() \ No newline at end of file + @timeOfDeath = Date.now() diff --git a/src/General/meta/manifest.json b/src/General/meta/manifest.json index b9793bda3..fb8cfba4e 100644 --- a/src/General/meta/manifest.json +++ b/src/General/meta/manifest.json @@ -15,7 +15,8 @@ "run_at": "document_start" }], "homepage_url": "<%= meta.page %>", - "minimum_chrome_version": "26", + "minimum_chrome_version": "27", + "minimum_opera_version": "15", "permissions": [ "storage" ] diff --git a/src/Images/ImageExpand.coffee b/src/Images/ImageExpand.coffee index e2fc6f205..c33c04732 100644 --- a/src/Images/ImageExpand.coffee +++ b/src/Images/ImageExpand.coffee @@ -52,19 +52,6 @@ ImageExpand = return setFitness: -> (if @checked then $.addClass else $.rmClass) doc, @name.toLowerCase().replace /\s+/g, '-' -<% if (type === 'userjs') { %> -# XXX Opera doesn't support CSS vh. - return unless @name is 'Fit height' - if @checked - $.on window, 'resize', ImageExpand.resize - unless ImageExpand.style - ImageExpand.style = $.addStyle null - ImageExpand.resize() - else - $.off window, 'resize', ImageExpand.resize - resize: -> - ImageExpand.style.textContent = ":root.fit-height .full-image {max-height:#{doc.clientHeight}px}" -<% } %> toggle: (post) -> {thumb} = post.file diff --git a/src/Images/ImageHover.coffee b/src/Images/ImageHover.coffee index 082aa4625..5356f50c3 100644 --- a/src/Images/ImageHover.coffee +++ b/src/Images/ImageHover.coffee @@ -13,7 +13,7 @@ ImageHover = el = $.el 'img', id: 'ihover' src: post.file.URL - el.setAttribute 'data-fullid', post.fullID + el.dataset.fullID = post.fullID $.add Header.hover, el UI.hover root: @ @@ -24,7 +24,7 @@ ImageHover = $.on el, 'error', ImageHover.error error: -> return unless doc.contains @ - post = g.posts[@dataset.fullid] + post = g.posts[@dataset.fullID] src = @src.split '/' if src[2] is 'images.4chan.org' @@ -48,4 +48,4 @@ ImageHover = post.kill() else if postObj.filedeleted clearTimeout timeoutID - post.kill true \ No newline at end of file + post.kill true diff --git a/src/Miscellaneous/Sauce.coffee b/src/Images/Sauce.coffee similarity index 92% rename from src/Miscellaneous/Sauce.coffee rename to src/Images/Sauce.coffee index c34522f30..92abea063 100644 --- a/src/Miscellaneous/Sauce.coffee +++ b/src/Images/Sauce.coffee @@ -4,12 +4,10 @@ Sauce = links = [] for link in Conf['sauces'].split '\n' - continue if link[0] is '#' try - links.push @createSauceLink link.trim() + links.push @createSauceLink link.trim() if link[0] isnt '#' catch err # Don't add random text plz. - continue return unless links.length @links = links @link = $.el 'a', target: '_blank' diff --git a/src/Menu/DeleteLink.coffee b/src/Menu/DeleteLink.coffee index 9427d4076..7f71d7f6e 100644 --- a/src/Menu/DeleteLink.coffee +++ b/src/Menu/DeleteLink.coffee @@ -44,9 +44,8 @@ DeleteLink = return if DeleteLink.cooldown.counting is post $.off @, 'click', DeleteLink.delete - @textContent = "Deleting #{@textContent}..." - fileOnly = $.hasClass @, 'delete-file' + @textContent = "Deleting #{if fileOnly then 'file' else 'post'}..." form = mode: 'usrdel' diff --git a/src/Menu/Menu.coffee b/src/Menu/Menu.coffee index e652d88a6..98e8865ad 100644 --- a/src/Menu/Menu.coffee +++ b/src/Menu/Menu.coffee @@ -8,29 +8,21 @@ Menu = cb: @node node: -> - button = Menu.makeButton @ if @isClone - $.replace $('.menu-button', @nodes.info), button - return - $.add @nodes.info, [$.tn('\u00A0'), button] + button = $ '.menu-button', @nodes.info + else + button = Menu.makeButton @ + $.add @nodes.info, [$.tn('\u00A0'), button] + $.on button, 'click', Menu.toggle makeButton: do -> a = null - (post) -> + -> a or= $.el 'a', className: 'menu-button fourchanx-link' innerHTML: '' href: 'javascript:;' - clone = a.cloneNode true - clone.setAttribute 'data-postid', post.fullID - clone.setAttribute 'data-clone', true if post.isClone - $.on clone, 'click', Menu.toggle - clone + a.cloneNode true toggle: (e) -> - post = - if @dataset.clone - Get.postFromNode @ - else - g.posts[@dataset.postid] - Menu.menu.toggle e, @, post \ No newline at end of file + Menu.menu.toggle e, @, Get.postFromNode @ diff --git a/src/Miscellaneous/Keybinds.coffee b/src/Miscellaneous/Keybinds.coffee index 8a4923102..4832510e6 100644 --- a/src/Miscellaneous/Keybinds.coffee +++ b/src/Miscellaneous/Keybinds.coffee @@ -95,10 +95,10 @@ Keybinds = window.location = "/#{g.BOARD}/catalog" # Thread Navigation when Conf['Next thread'] - return if g.VIEW is 'thread' + return if g.VIEW isnt 'index' Nav.scroll +1 when Conf['Previous thread'] - return if g.VIEW is 'thread' + return if g.VIEW isnt 'index' Nav.scroll -1 when Conf['Expand thread'] ExpandThread.toggle thread diff --git a/src/Miscellaneous/Nav.coffee b/src/Miscellaneous/Nav.coffee index ac1fdc10d..cca467683 100644 --- a/src/Miscellaneous/Nav.coffee +++ b/src/Miscellaneous/Nav.coffee @@ -60,8 +60,7 @@ Nav = # unless we're not at the beginning of the current thread # (and thus wanting to move to beginning) # or we're above the first thread and don't want to skip it - unless (delta is -1 and Math.ceil(top) < 0) or (delta is +1 and top > 1) - i += delta + if (delta is -1 and top > -5) or (delta is +1 and top < 5) + top = threads[i + delta]?.getBoundingClientRect().top - topMargin - top = threads[i]?.getBoundingClientRect().top - topMargin window.scrollBy 0, top diff --git a/src/Monitoring/ThreadUpdater.coffee b/src/Monitoring/ThreadUpdater.coffee index 5a4fc92a3..165b498cb 100644 --- a/src/Monitoring/ThreadUpdater.coffee +++ b/src/Monitoring/ThreadUpdater.coffee @@ -157,8 +157,7 @@ ThreadUpdater = By sending the `If-Modified-Since` header we get a proper status code, and no response. This saves bandwidth for both the user and the servers and avoid unnecessary computation. ### - # XXX 304 -> 0 in Opera - [text, klass] = if [0, 304].contains req.status + [text, klass] = if req.status is 304 [null, null] else ["#{req.statusText} (#{req.status})", 'warning'] diff --git a/src/Monitoring/Unread.coffee b/src/Monitoring/Unread.coffee index 547d9a577..dd2b5347b 100644 --- a/src/Monitoring/Unread.coffee +++ b/src/Monitoring/Unread.coffee @@ -36,13 +36,11 @@ Unread = # Let the header's onload callback handle it. return if (hash = location.hash.match /\d+/) and hash[0] of Unread.thread.posts if Unread.posts.length - # Scroll to before the first unread post. - prevID = 0 - while root = $.x 'preceding-sibling::div[contains(@class,"postContainer")][1]', Unread.posts[0].nodes.root - post = Get.postFromRoot root - break if prevID is post.ID - prevID = post.ID - break unless post.isHidden + # Scroll to a non-hidden, non-OP post that's before the first unread post. + post = Unread.posts[0] + while root = $.x 'preceding-sibling::div[contains(@class,"replyContainer")][1]', post.nodes.root + break unless (post = Get.postFromRoot root).isHidden + return unless root onload = -> root.scrollIntoView false if checkPosition root else # Scroll to the last read post. @@ -188,9 +186,7 @@ Unread = else Favicon.default - <% if (type !== 'crx') { %> + <% if (type === 'userscript') { %> # `favicon.href = href` doesn't work on Firefox. - # `favicon.href = href` isn't enough on Opera. - # Opera won't always update the favicon if the href didn't change. $.add d.head, Favicon.el <% } %> diff --git a/src/Posting/QuickReply.coffee b/src/Posting/QuickReply.coffee index 2219c8fa7..5d08c46c1 100644 --- a/src/Posting/QuickReply.coffee +++ b/src/Posting/QuickReply.coffee @@ -101,8 +101,8 @@ QR = $.rmClass QR.captcha.nodes.input, 'error' if Conf['QR Shortcut'] $.toggleClass $('.qr-shortcut'), 'disabled' - for i in QR.posts - QR.posts[0].rm() + for post in QR.posts.splice 0, QR.posts.length, new QR.post true + post.delete() QR.cooldown.auto = false QR.status() focusin: -> @@ -150,7 +150,8 @@ QR = status: -> return unless QR.nodes - if g.DEAD + {thread} = QR.posts[0] + if thread isnt 'new' and g.threads["#{g.BOARD}.#{thread}"].isDead value = 404 disabled = true QR.cooldown.auto = false @@ -371,14 +372,10 @@ QR = e?.preventDefault() return unless QR.postingIsEnabled - sel = d.getSelection() - selectionRoot = $.x 'ancestor::div[contains(@class,"postContainer")][1]', sel.anchorNode - post = Get.postFromNode @ - {OP} = Get.contextFromLink(@).thread - - text = ">>#{post}\n" - if (s = sel.toString().trim()) and post.nodes.root is selectionRoot - # XXX Opera doesn't retain `\n`s? + sel = d.getSelection() + post = Get.postFromNode @ + text = ">>#{post}\n" + if (s = sel.toString().trim()) and post is Get.postFromNode sel.anchorNode s = s.replace /\n/g, '\n>' text += ">#{s}\n" @@ -389,7 +386,7 @@ QR = $.addClass QR.nodes.el, 'dump' QR.cooldown.auto = true {com, thread} = QR.nodes - thread.value = OP.ID unless com.value + thread.value = Get.contextFromNode(@).thread unless com.value caretPos = com.selectionStart # Replace selection for text. @@ -447,7 +444,7 @@ QR = QR.nodes.fileInput.click() fileInput: (files) -> - if @ instanceof Element #or files instanceof Event # file input + if files instanceof Event # file input files = [@files...] QR.nodes.fileInput.value = null # Don't hold the files from being modified on windows {length} = files @@ -504,7 +501,7 @@ QR = for elm in $$ '*', el $.on elm, 'blur', QR.focusout $.on elm, 'focus', QR.focusin - <% } %> + <% } %> $.on el, 'click', @select.bind @ $.on @nodes.rm, 'click', (e) => e.stopPropagation(); @rm() $.on @nodes.label, 'click', (e) => e.stopPropagation() @@ -553,7 +550,7 @@ QR = @unlock() rm: -> - $.rm @nodes.el + @delete() index = QR.posts.indexOf @ if QR.posts.length is 1 new QR.post true @@ -561,7 +558,9 @@ QR = else if @ is QR.selected (QR.posts[index-1] or QR.posts[index+1]).select() QR.posts.splice index, 1 - return unless window.URL + QR.status() + delete: -> + $.rm @nodes.el URL.revokeObjectURL @URL lock: (lock=true) -> @@ -603,15 +602,18 @@ QR = if input.type is 'checkbox' @spoiler = input.checked return - {value} = input - @[input.dataset.name] = value - return if input.nodeName isnt 'TEXTAREA' - @nodes.span.textContent = value - QR.characterCount() - # Disable auto-posting if you're typing in the first post - # during the last 5 seconds of the cooldown. - if QR.cooldown.auto and @ is QR.posts[0] and 0 < QR.cooldown.seconds <= 5 - QR.cooldown.auto = false + {name} = input.dataset + @[name] = input.value + switch name + when 'thread' + QR.status() + when 'com' + @nodes.span.textContent = @com + QR.characterCount() + # Disable auto-posting if you're typing in the first post + # during the last 5 seconds of the cooldown. + if QR.cooldown.auto and @ is QR.posts[0] and 0 < QR.cooldown.seconds <= 5 + QR.cooldown.auto = false forceSave: -> return unless @ is QR.selected @@ -625,26 +627,15 @@ QR = @filename = "#{file.name} (#{$.bytesToString file.size})" @nodes.el.title = @filename @nodes.label.hidden = false if QR.spoiler - URL.revokeObjectURL @URL if window.URL + URL.revokeObjectURL @URL @showFileData() unless /^image/.test file.type @nodes.el.style.backgroundImage = null return @setThumbnail() - setThumbnail: (fileURL) -> - # XXX Opera does not support blob URL + setThumbnail: -> # Create a redimensioned thumbnail. - unless window.URL - unless fileURL - reader = new FileReader() - reader.onload = (e) => - @setThumbnail e.target.result - reader.readAsDataURL @file - return - else - fileURL = URL.createObjectURL @file - img = $.el 'img' img.onload = => @@ -656,7 +647,7 @@ QR = s *= 3 if @file.type is 'image/gif' # let them animate {height, width} = img if height < s or width < s - @URL = fileURL if window.URL + @URL = fileURL @nodes.el.style.backgroundImage = "url(#{@URL})" return if height <= width @@ -669,10 +660,6 @@ QR = cv.height = img.height = height cv.width = img.width = width cv.getContext('2d').drawImage img, 0, 0, width, height - unless window.URL - @nodes.el.style.backgroundImage = "url(#{cv.toDataURL()})" - delete @URL - return URL.revokeObjectURL fileURL applyBlob = (blob) => @URL = URL.createObjectURL blob @@ -690,6 +677,7 @@ QR = applyBlob new Blob [ui8a], type: 'image/png' + fileURL = URL.createObjectURL @file img.src = fileURL rmFile: -> @@ -699,7 +687,6 @@ QR = @nodes.el.style.backgroundImage = null @nodes.label.hidden = true if QR.spoiler @showFileData() - return unless window.URL URL.revokeObjectURL @URL showFileData: -> @@ -724,33 +711,26 @@ QR = @nodes.span.textContent = @com reader.readAsText file - dragStart: -> - $.addClass @, 'drag' + dragStart: -> $.addClass @, 'drag' + dragEnd: -> $.rmClass @, 'drag' + dragEnter: -> $.addClass @, 'over' + dragLeave: -> $.rmClass @, 'over' - dragEnd: -> - $.rmClass @, 'drag' - - dragEnter: -> - $.addClass @, 'over' - - dragLeave: -> - $.rmClass @, 'over' - dragOver: (e) -> e.preventDefault() e.dataTransfer.dropEffect = 'move' drop: -> - el = $ '.drag', @parentNode - $.rmClass el, 'drag' # Opera doesn't fire dragEnd if we drop it on something else - $.rmClass @, 'over' + $.rmClass @, 'over' return unless @draggable + el = $ '.drag', @parentNode index = (el) -> [el.parentNode.children...].indexOf el oldIndex = index el newIndex = index @ (if oldIndex < newIndex then $.after else $.before) @, el post = QR.posts.splice(oldIndex, 1)[0] QR.posts.splice newIndex, 0, post + QR.status() captcha: init: -> @@ -779,19 +759,15 @@ QR = img: imgContainer.firstChild input: input - if window.MutationObserver - observer = new MutationObserver @load.bind @ - observer.observe @nodes.challenge, - childList: true - else - $.on @nodes.challenge, 'DOMNodeInserted', @load.bind @ + new MutationObserver(@load.bind @).observe @nodes.challenge, + childList: true $.on imgContainer, 'click', @reload.bind @ $.on input, 'keydown', @keydown.bind @ $.on input, 'focus', -> $.addClass QR.nodes.el, 'focus' $.on input, 'blur', -> $.rmClass QR.nodes.el, 'focus' - $.get 'captchas', [], (item) => - @sync item['captchas'] + $.get 'captchas', [], ({captchas}) => + @sync captchas $.sync 'captchas', @sync # start with an uncached captcha @reload() @@ -800,12 +776,13 @@ QR = # XXX Firefox lacks focusin/focusout support. $.on input, 'blur', QR.focusout $.on input, 'focus', QR.focusin - <% } %> + <% } %> $.addClass QR.nodes.el, 'has-captcha' $.after QR.nodes.com.parentNode, [imgContainer, input] - - sync: (@captchas) -> + + sync: (captchas) -> + QR.captcha.captchas = captchas QR.captcha.count() getOne: -> @@ -922,10 +899,6 @@ QR = # Add empty mimeType to avoid errors with URLs selected in Window's file dialog. QR.mimeTypes.push '' nodes.fileInput.max = $('input[name=MAX_FILE_SIZE]').value - <% if (type !== 'userjs') { %> - # Opera's accept attribute is fucked up - nodes.fileInput.accept = "text/*, #{mimeTypes}" - <% } %> QR.spoiler = !!$ 'input[name=spoiler]' if QR.spoiler @@ -960,7 +933,7 @@ QR = for elm in $$ '*', QR.nodes.el $.on elm, 'blur', QR.focusout $.on elm, 'focus', QR.focusin - <% } %> + <% } %> $.on dialog, 'focusin', QR.focusin $.on dialog, 'focusout', QR.focusout $.on nodes.autohide, 'change', QR.toggleHide @@ -1109,11 +1082,6 @@ QR = QR.status() response: -> - <% if (type === 'userjs') { %> - # The upload.onload callback is not called - # or at least not in time with Opera. - QR.req.upload.onload() - <% } %> {req} = QR delete QR.req @@ -1206,15 +1174,15 @@ QR = QR.cooldown.set {req, post, isReply} - if threadID is postID # new thread - URL = "/#{g.BOARD}/res/#{threadID}" + URL = if threadID is postID # new thread + "/#{g.BOARD}/res/#{threadID}" else if g.VIEW is 'index' and !QR.cooldown.auto and Conf['Open Post in New Tab'] # replying from the index - URL = "/#{g.BOARD}/res/#{threadID}#p#{postID}" + "/#{g.BOARD}/res/#{threadID}#p#{postID}" if URL if Conf['Open Post in New Tab'] - $.open "/#{g.BOARD}/res/#{threadID}" + $.open URL else - window.location = "/#{g.BOARD}/res/#{threadID}" + window.location = URL QR.status() diff --git a/src/Quotelinks/QuoteInline.coffee b/src/Quotelinks/QuoteInline.coffee index 4ea6b3b43..723f0c53b 100644 --- a/src/Quotelinks/QuoteInline.coffee +++ b/src/Quotelinks/QuoteInline.coffee @@ -35,7 +35,7 @@ QuoteInline = return if e.shiftKey or e.altKey or e.ctrlKey or e.metaKey or e.button isnt 0 e.preventDefault() {boardID, threadID, postID} = Get.postDataFromLink @ - context = Get.contextFromLink @ + context = Get.contextFromNode @ if $.hasClass @, 'inlined' QuoteInline.rm @, boardID, threadID, postID, context else @@ -107,4 +107,4 @@ QuoteInline = {boardID, threadID, postID} = Get.postDataFromLink inlined QuoteInline.rm inlined, boardID, threadID, postID, context $.rmClass inlined, 'inlined' - return \ No newline at end of file + return diff --git a/src/Quotelinks/QuotePreview.coffee b/src/Quotelinks/QuotePreview.coffee index 8301f623b..15fd65f64 100644 --- a/src/Quotelinks/QuotePreview.coffee +++ b/src/Quotelinks/QuotePreview.coffee @@ -22,8 +22,9 @@ QuotePreview = qp = $.el 'div', id: 'qp' className: 'dialog' + $.add Header.hover, qp - Get.postClone boardID, threadID, postID, qp, Get.contextFromLink @ + Get.postClone boardID, threadID, postID, qp, Get.contextFromNode @ UI.hover root: @ @@ -33,21 +34,6 @@ QuotePreview = cb: QuotePreview.mouseout asapTest: -> qp.firstElementChild - <% if (type === 'userjs') { %> - # XXX Opera workaround for "no mouseout fired" bug. - # Remove it once Opera uses Blink. - root = @ - workaround = (e) -> - if @ is root - e.stopPropagation() - return - $.event 'mouseout', null, root - $.off d, 'mousemove', workaround - $.off root, 'mousemove', workaround - $.on d, 'mousemove', workaround - $.on root, 'mousemove', workaround - <% } %> - return unless origin = g.posts["#{boardID}.#{postID}"] if Conf['Quote Highlighting'] diff --git a/src/Quotelinks/Quotify.coffee b/src/Quotelinks/Quotify.coffee index b537a7ae2..524f74f6c 100644 --- a/src/Quotelinks/Quotify.coffee +++ b/src/Quotelinks/Quotify.coffee @@ -21,6 +21,9 @@ Quotify = if deadlink.parentNode.className is 'prettyprint' # Don't quotify deadlinks inside code tags, # un-`span` them. + # This won't be necessary once 4chan + # stops quotifying inside code tags: + # https://github.com/4chan/4chan-JS/issues/77 $.replace deadlink, [deadlink.childNodes...] return @@ -48,9 +51,8 @@ Quotify = target: '_blank' textContent: "#{quote}\u00A0(Dead)" - a.setAttribute 'data-boardid', boardID - a.setAttribute 'data-threadid', post.thread.ID - a.setAttribute 'data-postid', postID + $.extend a.dataset, {boardID, threadID: post.thread.ID, postID} + else if redirect = Redirect.to 'thread', {boardID, threadID: 0, postID} # Replace the .deadlink span if we can redirect. a = $.el 'a', @@ -60,9 +62,8 @@ Quotify = textContent: "#{quote}\u00A0(Dead)" if Redirect.to 'post', {boardID, postID} # Make it function as a normal quote if we can fetch the post. - $.addClass a, 'quotelink' - a.setAttribute 'data-boardid', boardID - a.setAttribute 'data-postid', postID + $.addClass a, 'quotelink' + $.extend a.dataset, {boardID, postID} unless @quotes.contains quoteID @quotes.push quoteID @@ -73,4 +74,4 @@ Quotify = $.replace deadlink, a if $.hasClass a, 'quotelink' - @nodes.quotelinks.push a \ No newline at end of file + @nodes.quotelinks.push a