(function(){
    "use strict";
    var ρσ_iterator_symbol = (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") ? Symbol.iterator : "iterator-Symbol-5d0927e5554349048cf0e3762a228256";
    var ρσ_kwargs_symbol = (typeof Symbol === "function") ? Symbol("kwargs-object") : "kwargs-object-Symbol-5d0927e5554349048cf0e3762a228256";
    var ρσ_cond_temp, ρσ_expr_temp, ρσ_last_exception;
    var ρσ_object_counter = 0;
var ρσ_len;
function ρσ_bool(val) {
    return !!val;
};
if (!ρσ_bool.__argnames__) Object.defineProperties(ρσ_bool, {
    __argnames__ : {value: ["val"]}
});

function ρσ_print() {
    var parts;
    if (typeof console === "object") {
        parts = [];
        for (var i = 0; i < arguments.length; i++) {
            parts.push(ρσ_str(arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i]));
        }
        console.log(parts.join(" "));
    }
};

function ρσ_int(val, base) {
    var ans;
    if (typeof val === "number") {
        ans = val | 0;
    } else {
        ans = parseInt(val, base || 10);
    }
    if (isNaN(ans)) {
        throw new ValueError("Invalid literal for int with base " + (base || 10) + ": " + val);
    }
    return ans;
};
if (!ρσ_int.__argnames__) Object.defineProperties(ρσ_int, {
    __argnames__ : {value: ["val", "base"]}
});

function ρσ_float(val) {
    var ans;
    if (typeof val === "number") {
        ans = val;
    } else {
        ans = parseFloat(val);
    }
    if (isNaN(ans)) {
        throw new ValueError("Could not convert string to float: " + arguments[0]);
    }
    return ans;
};
if (!ρσ_float.__argnames__) Object.defineProperties(ρσ_float, {
    __argnames__ : {value: ["val"]}
});

function ρσ_arraylike_creator() {
    var names;
    names = "Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" ");
    if (typeof HTMLCollection === "function") {
        names = names.concat("HTMLCollection NodeList NamedNodeMap TouchList".split(" "));
    }
    return (function() {
        var ρσ_anonfunc = function (x) {
            if (Array.isArray(x) || typeof x === "string" || names.indexOf(Object.prototype.toString.call(x).slice(8, -1)) > -1) {
                return true;
            }
            return false;
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["x"]}
        });
        return ρσ_anonfunc;
    })();
};

function options_object(f) {
    return function () {
        if (typeof arguments[arguments.length - 1] === "object") {
            arguments[ρσ_bound_index(arguments.length - 1, arguments)][ρσ_kwargs_symbol] = true;
        }
        return f.apply(this, arguments);
    };
};
if (!options_object.__argnames__) Object.defineProperties(options_object, {
    __argnames__ : {value: ["f"]}
});

function ρσ_id(x) {
    return x.ρσ_object_id;
};
if (!ρσ_id.__argnames__) Object.defineProperties(ρσ_id, {
    __argnames__ : {value: ["x"]}
});

function ρσ_dir(item) {
    var arr;
    arr = ρσ_list_decorate([]);
    for (var i in item) {
        arr.push(i);
    }
    return arr;
};
if (!ρσ_dir.__argnames__) Object.defineProperties(ρσ_dir, {
    __argnames__ : {value: ["item"]}
});

function ρσ_ord(x) {
    var ans, second;
    ans = x.charCodeAt(0);
    if (55296 <= ans && ans <= 56319) {
        second = x.charCodeAt(1);
        if (56320 <= second && second <= 57343) {
            return (ans - 55296) * 1024 + second - 56320 + 65536;
        }
        throw new TypeError("string is missing the low surrogate char");
    }
    return ans;
};
if (!ρσ_ord.__argnames__) Object.defineProperties(ρσ_ord, {
    __argnames__ : {value: ["x"]}
});

function ρσ_chr(code) {
    if (code <= 65535) {
        return String.fromCharCode(code);
    }
    code -= 65536;
    return String.fromCharCode(55296 + (code >> 10), 56320 + (code & 1023));
};
if (!ρσ_chr.__argnames__) Object.defineProperties(ρσ_chr, {
    __argnames__ : {value: ["code"]}
});

function ρσ_callable(x) {
    return typeof x === "function";
};
if (!ρσ_callable.__argnames__) Object.defineProperties(ρσ_callable, {
    __argnames__ : {value: ["x"]}
});

function ρσ_bin(x) {
    var ans;
    if (typeof x !== "number" || x % 1 !== 0) {
        throw new TypeError("integer required");
    }
    ans = x.toString(2);
    if (ans[0] === "-") {
        ans = "-" + "0b" + ans.slice(1);
    } else {
        ans = "0b" + ans;
    }
    return ans;
};
if (!ρσ_bin.__argnames__) Object.defineProperties(ρσ_bin, {
    __argnames__ : {value: ["x"]}
});

function ρσ_hex(x) {
    var ans;
    if (typeof x !== "number" || x % 1 !== 0) {
        throw new TypeError("integer required");
    }
    ans = x.toString(16);
    if (ans[0] === "-") {
        ans = "-" + "0x" + ans.slice(1);
    } else {
        ans = "0x" + ans;
    }
    return ans;
};
if (!ρσ_hex.__argnames__) Object.defineProperties(ρσ_hex, {
    __argnames__ : {value: ["x"]}
});

function ρσ_enumerate(iterable) {
    var ans, iterator;
    ans = {"_i":-1};
    ans[ρσ_iterator_symbol] = function () {
        return this;
    };
    if (ρσ_arraylike(iterable)) {
        ans["next"] = function () {
            this._i += 1;
            if (this._i < iterable.length) {
                return {'done':false, 'value':[this._i, iterable[this._i]]};
            }
            return {'done':true};
        };
        return ans;
    }
    if (typeof iterable[ρσ_iterator_symbol] === "function") {
        iterator = (typeof Map === "function" && iterable instanceof Map) ? iterable.keys() : iterable[ρσ_iterator_symbol]();
        ans["_iterator"] = iterator;
        ans["next"] = function () {
            var r;
            r = this._iterator.next();
            if (r.done) {
                return {'done':true};
            }
            this._i += 1;
            return {'done':false, 'value':[this._i, r.value]};
        };
        return ans;
    }
    return ρσ_enumerate(Object.keys(iterable));
};
if (!ρσ_enumerate.__argnames__) Object.defineProperties(ρσ_enumerate, {
    __argnames__ : {value: ["iterable"]}
});

function ρσ_reversed(iterable) {
    var ans;
    if (ρσ_arraylike(iterable)) {
        ans = {"_i": iterable.length};
        ans["next"] = function () {
            this._i -= 1;
            if (this._i > -1) {
                return {'done':false, 'value':iterable[this._i]};
            }
            return {'done':true};
        };
        ans[ρσ_iterator_symbol] = function () {
            return this;
        };
        return ans;
    }
    throw new TypeError("reversed() can only be called on arrays or strings");
};
if (!ρσ_reversed.__argnames__) Object.defineProperties(ρσ_reversed, {
    __argnames__ : {value: ["iterable"]}
});

function ρσ_iter(iterable) {
    var ans;
    if (typeof iterable[ρσ_iterator_symbol] === "function") {
        return (typeof Map === "function" && iterable instanceof Map) ? iterable.keys() : iterable[ρσ_iterator_symbol]();
    }
    if (ρσ_arraylike(iterable)) {
        ans = {"_i":-1};
        ans[ρσ_iterator_symbol] = function () {
            return this;
        };
        ans["next"] = function () {
            this._i += 1;
            if (this._i < iterable.length) {
                return {'done':false, 'value':iterable[this._i]};
            }
            return {'done':true};
        };
        return ans;
    }
    return ρσ_iter(Object.keys(iterable));
};
if (!ρσ_iter.__argnames__) Object.defineProperties(ρσ_iter, {
    __argnames__ : {value: ["iterable"]}
});

function ρσ_range_next(step, length) {
    var ρσ_unpack;
    this._i += step;
    this._idx += 1;
    if (this._idx >= length) {
        ρσ_unpack = [this.__i, -1];
        this._i = ρσ_unpack[0];
        this._idx = ρσ_unpack[1];
        return {'done':true};
    }
    return {'done':false, 'value':this._i};
};
if (!ρσ_range_next.__argnames__) Object.defineProperties(ρσ_range_next, {
    __argnames__ : {value: ["step", "length"]}
});

function ρσ_range(start, stop, step) {
    var length, ans;
    if (arguments.length <= 1) {
        stop = start || 0;
        start = 0;
    }
    step = arguments[2] || 1;
    length = Math.max(Math.ceil((stop - start) / step), 0);
    ans = {start:start, step:step, stop:stop};
    ans[ρσ_iterator_symbol] = function () {
        var it;
        it = {"_i": start - step, "_idx": -1};
        it.next = ρσ_range_next.bind(it, step, length);
        it[ρσ_iterator_symbol] = function () {
            return this;
        };
        return it;
    };
    ans.count = (function() {
        var ρσ_anonfunc = function (val) {
            if (!this._cached) {
                this._cached = list(this);
            }
            return this._cached.count(val);
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["val"]}
        });
        return ρσ_anonfunc;
    })();
    ans.index = (function() {
        var ρσ_anonfunc = function (val) {
            if (!this._cached) {
                this._cached = list(this);
            }
            return this._cached.index(val);
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["val"]}
        });
        return ρσ_anonfunc;
    })();
    if (typeof Proxy === "function") {
        ans = new Proxy(ans, (function(){
            var ρσ_d = {};
            ρσ_d["get"] = (function() {
                var ρσ_anonfunc = function (obj, prop) {
                    var iprop;
                    if (typeof prop === "string") {
                        iprop = parseInt(prop);
                        if (!isNaN(iprop)) {
                            prop = iprop;
                        }
                    }
                    if (typeof prop === "number") {
                        if (!obj._cached) {
                            obj._cached = list(obj);
                        }
                        return (ρσ_expr_temp = obj._cached)[(typeof prop === "number" && prop < 0) ? ρσ_expr_temp.length + prop : prop];
                    }
                    return obj[(typeof prop === "number" && prop < 0) ? obj.length + prop : prop];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["obj", "prop"]}
                });
                return ρσ_anonfunc;
            })();
            return ρσ_d;
        }).call(this));
    }
    return ans;
};
if (!ρσ_range.__argnames__) Object.defineProperties(ρσ_range, {
    __argnames__ : {value: ["start", "stop", "step"]}
});

function ρσ_getattr(obj, name, defval) {
    var ret;
    try {
        ret = obj[(typeof name === "number" && name < 0) ? obj.length + name : name];
    } catch (ρσ_Exception) {
        ρσ_last_exception = ρσ_Exception;
        if (ρσ_Exception instanceof TypeError) {
            if (defval === undefined) {
                throw new AttributeError("The attribute " + name + " is not present");
            }
            return defval;
        } else {
            throw ρσ_Exception;
        }
    }
    if (ret === undefined && !(name in obj)) {
        if (defval === undefined) {
            throw new AttributeError("The attribute " + name + " is not present");
        }
        ret = defval;
    }
    return ret;
};
if (!ρσ_getattr.__argnames__) Object.defineProperties(ρσ_getattr, {
    __argnames__ : {value: ["obj", "name", "defval"]}
});

function ρσ_setattr(obj, name, value) {
    obj[(typeof name === "number" && name < 0) ? obj.length + name : name] = value;
};
if (!ρσ_setattr.__argnames__) Object.defineProperties(ρσ_setattr, {
    __argnames__ : {value: ["obj", "name", "value"]}
});

function ρσ_hasattr(obj, name) {
    return name in obj;
};
if (!ρσ_hasattr.__argnames__) Object.defineProperties(ρσ_hasattr, {
    __argnames__ : {value: ["obj", "name"]}
});

ρσ_len = function () {
    function len(obj) {
        if (ρσ_arraylike(obj)) {
            return obj.length;
        }
        if (typeof obj.__len__ === "function") {
            return obj.__len__();
        }
        if (obj instanceof Set || obj instanceof Map) {
            return obj.size;
        }
        return Object.keys(obj).length;
    };
    if (!len.__argnames__) Object.defineProperties(len, {
        __argnames__ : {value: ["obj"]}
    });

    function len5(obj) {
        if (ρσ_arraylike(obj)) {
            return obj.length;
        }
        if (typeof obj.__len__ === "function") {
            return obj.__len__();
        }
        return Object.keys(obj).length;
    };
    if (!len5.__argnames__) Object.defineProperties(len5, {
        __argnames__ : {value: ["obj"]}
    });

    return (typeof Set === "function" && typeof Map === "function") ? len : len5;
}();
function ρσ_get_module(name) {
    return ρσ_modules[(typeof name === "number" && name < 0) ? ρσ_modules.length + name : name];
};
if (!ρσ_get_module.__argnames__) Object.defineProperties(ρσ_get_module, {
    __argnames__ : {value: ["name"]}
});

function ρσ_pow(x, y, z) {
    var ans;
    ans = Math.pow(x, y);
    if (z !== undefined) {
        ans %= z;
    }
    return ans;
};
if (!ρσ_pow.__argnames__) Object.defineProperties(ρσ_pow, {
    __argnames__ : {value: ["x", "y", "z"]}
});

function ρσ_type(x) {
    return x.constructor;
};
if (!ρσ_type.__argnames__) Object.defineProperties(ρσ_type, {
    __argnames__ : {value: ["x"]}
});

function ρσ_divmod(x, y) {
    var d;
    if (y === 0) {
        throw new ZeroDivisionError("integer division or modulo by zero");
    }
    d = Math.floor(x / y);
    return [d, x - d * y];
};
if (!ρσ_divmod.__argnames__) Object.defineProperties(ρσ_divmod, {
    __argnames__ : {value: ["x", "y"]}
});

function ρσ_max() {
    var kwargs = arguments[arguments.length-1];
    if (kwargs === null || typeof kwargs !== "object" || kwargs [ρσ_kwargs_symbol] !== true) kwargs = {};
    var args = Array.prototype.slice.call(arguments, 0);
    if (kwargs !== null && typeof kwargs === "object" && kwargs [ρσ_kwargs_symbol] === true) args.pop();
    var args, x;
    if (args.length === 0) {
        if (kwargs.defval !== undefined) {
            return kwargs.defval;
        }
        throw new TypeError("expected at least one argument");
    }
    if (args.length === 1) {
        args = args[0];
    }
    if (kwargs.key) {
        args = (function() {
            var ρσ_Iter = ρσ_Iterable(args), ρσ_Result = [], x;
            for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                x = ρσ_Iter[ρσ_Index];
                ρσ_Result.push(kwargs.key(x));
            }
            ρσ_Result = ρσ_list_constructor(ρσ_Result);
            return ρσ_Result;
        })();
    }
    if (!Array.isArray(args)) {
        args = list(args);
    }
    if (args.length) {
        return this.apply(null, args);
    }
    if (kwargs.defval !== undefined) {
        return kwargs.defval;
    }
    throw new TypeError("expected at least one argument");
};
if (!ρσ_max.__handles_kwarg_interpolation__) Object.defineProperties(ρσ_max, {
    __handles_kwarg_interpolation__ : {value: true}
});

var abs = Math.abs, max = ρσ_max.bind(Math.max), min = ρσ_max.bind(Math.min), bool = ρσ_bool, type = ρσ_type;
var float = ρσ_float, int = ρσ_int, arraylike = ρσ_arraylike_creator(), ρσ_arraylike = arraylike;
var print = ρσ_print, id = ρσ_id, get_module = ρσ_get_module, pow = ρσ_pow, divmod = ρσ_divmod;
var dir = ρσ_dir, ord = ρσ_ord, chr = ρσ_chr, bin = ρσ_bin, hex = ρσ_hex, callable = ρσ_callable;
var enumerate = ρσ_enumerate, iter = ρσ_iter, reversed = ρσ_reversed, len = ρσ_len;
var range = ρσ_range, getattr = ρσ_getattr, setattr = ρσ_setattr, hasattr = ρσ_hasattr;function ρσ_equals(a, b) {
    var ρσ_unpack, akeys, bkeys, key;
    if (a === b) {
        return true;
    }
    if (a && typeof a.__eq__ === "function") {
        return a.__eq__(b);
    }
    if (b && typeof b.__eq__ === "function") {
        return b.__eq__(a);
    }
    if (ρσ_arraylike(a) && ρσ_arraylike(b)) {
        if ((a.length !== b.length && (typeof a.length !== "object" || ρσ_not_equals(a.length, b.length)))) {
            return false;
        }
        for (var i=0; i < a.length; i++) {
            if (!((a[(typeof i === "number" && i < 0) ? a.length + i : i] === b[(typeof i === "number" && i < 0) ? b.length + i : i] || typeof a[(typeof i === "number" && i < 0) ? a.length + i : i] === "object" && ρσ_equals(a[(typeof i === "number" && i < 0) ? a.length + i : i], b[(typeof i === "number" && i < 0) ? b.length + i : i])))) {
                return false;
            }
        }
        return true;
    }
    if (typeof a === "object" && typeof b === "object" && a !== null && b !== null && (a.constructor === Object && b.constructor === Object || Object.getPrototypeOf(a) === null && Object.getPrototypeOf(b) === null)) {
        ρσ_unpack = [Object.keys(a), Object.keys(b)];
        akeys = ρσ_unpack[0];
        bkeys = ρσ_unpack[1];
        if (akeys.length !== bkeys.length) {
            return false;
        }
        for (var j=0; j < akeys.length; j++) {
            key = akeys[(typeof j === "number" && j < 0) ? akeys.length + j : j];
            if (!((a[(typeof key === "number" && key < 0) ? a.length + key : key] === b[(typeof key === "number" && key < 0) ? b.length + key : key] || typeof a[(typeof key === "number" && key < 0) ? a.length + key : key] === "object" && ρσ_equals(a[(typeof key === "number" && key < 0) ? a.length + key : key], b[(typeof key === "number" && key < 0) ? b.length + key : key])))) {
                return false;
            }
        }
        return true;
    }
    return false;
};
if (!ρσ_equals.__argnames__) Object.defineProperties(ρσ_equals, {
    __argnames__ : {value: ["a", "b"]}
});

function ρσ_not_equals(a, b) {
    if (a === b) {
        return false;
    }
    if (a && typeof a.__ne__ === "function") {
        return a.__ne__(b);
    }
    if (b && typeof b.__ne__ === "function") {
        return b.__ne__(a);
    }
    return !ρσ_equals(a, b);
};
if (!ρσ_not_equals.__argnames__) Object.defineProperties(ρσ_not_equals, {
    __argnames__ : {value: ["a", "b"]}
});

var equals = ρσ_equals;
function ρσ_list_extend(iterable) {
    var start, iterator, result;
    if (Array.isArray(iterable) || typeof iterable === "string") {
        start = this.length;
        this.length += iterable.length;
        for (var i = 0; i < iterable.length; i++) {
            (ρσ_expr_temp = this)[ρσ_bound_index(start + i, ρσ_expr_temp)] = iterable[(typeof i === "number" && i < 0) ? iterable.length + i : i];
        }
    } else {
        iterator = (typeof Map === "function" && iterable instanceof Map) ? iterable.keys() : iterable[ρσ_iterator_symbol]();
        result = iterator.next();
        while (!result.done) {
            this.push(result.value);
            result = iterator.next();
        }
    }
};
if (!ρσ_list_extend.__argnames__) Object.defineProperties(ρσ_list_extend, {
    __argnames__ : {value: ["iterable"]}
});

function ρσ_list_index(val, start, stop) {
    var idx;
    start = start || 0;
    if (start < 0) {
        start = this.length + start;
    }
    if (start < 0) {
        throw new ValueError(val + " is not in list");
    }
    if (stop === undefined) {
        idx = this.indexOf(val, start);
        if (idx === -1) {
            throw new ValueError(val + " is not in list");
        }
        return idx;
    }
    if (stop < 0) {
        stop = this.length + stop;
    }
    for (var i = start; i < stop; i++) {
        if (((ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] === val || typeof (ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] === "object" && ρσ_equals((ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i], val))) {
            return i;
        }
    }
    throw new ValueError(val + " is not in list");
};
if (!ρσ_list_index.__argnames__) Object.defineProperties(ρσ_list_index, {
    __argnames__ : {value: ["val", "start", "stop"]}
});

function ρσ_list_pop(index) {
    var ans;
    if (this.length === 0) {
        throw new IndexError("list is empty");
    }
    if (index === undefined) {
        index = -1;
    }
    ans = this.splice(index, 1);
    if (!ans.length) {
        throw new IndexError("pop index out of range");
    }
    return ans[0];
};
if (!ρσ_list_pop.__argnames__) Object.defineProperties(ρσ_list_pop, {
    __argnames__ : {value: ["index"]}
});

function ρσ_list_remove(value) {
    var idx;
    idx = this.indexOf(value);
    if (idx === -1) {
        throw new ValueError(value + " not in list");
    }
    this.splice(idx, 1);
};
if (!ρσ_list_remove.__argnames__) Object.defineProperties(ρσ_list_remove, {
    __argnames__ : {value: ["value"]}
});

function ρσ_list_to_string() {
    return "[" + this.join(", ") + "]";
};

function ρσ_list_insert(index, val) {
    if (index < 0) {
        index += this.length;
    }
    index = min(this.length, max(index, 0));
    if (index === 0) {
        this.unshift(val);
        return;
    }
    for (var i = this.length; i > index; i--) {
        (ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] = (ρσ_expr_temp = this)[ρσ_bound_index(i - 1, ρσ_expr_temp)];
    }
    (ρσ_expr_temp = this)[(typeof index === "number" && index < 0) ? ρσ_expr_temp.length + index : index] = val;
};
if (!ρσ_list_insert.__argnames__) Object.defineProperties(ρσ_list_insert, {
    __argnames__ : {value: ["index", "val"]}
});

function ρσ_list_copy() {
    return ρσ_list_constructor(this);
};

function ρσ_list_clear() {
    this.length = 0;
};

function ρσ_list_as_array() {
    return Array.prototype.slice.call(this);
};

function ρσ_list_count(value) {
    return this.reduce((function() {
        var ρσ_anonfunc = function (n, val) {
            return n + (val === value);
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["n", "val"]}
        });
        return ρσ_anonfunc;
    })(), 0);
};
if (!ρσ_list_count.__argnames__) Object.defineProperties(ρσ_list_count, {
    __argnames__ : {value: ["value"]}
});

function ρσ_list_sort_key(value) {
    var t;
    t = typeof value;
    if (t === "string" || t === "number") {
        return value;
    }
    return value.toString();
};
if (!ρσ_list_sort_key.__argnames__) Object.defineProperties(ρσ_list_sort_key, {
    __argnames__ : {value: ["value"]}
});

function ρσ_list_sort_cmp(a, b, ap, bp) {
    if (a < b) {
        return -1;
    }
    if (a > b) {
        return 1;
    }
    return ap - bp;
};
if (!ρσ_list_sort_cmp.__argnames__) Object.defineProperties(ρσ_list_sort_cmp, {
    __argnames__ : {value: ["a", "b", "ap", "bp"]}
});

function ρσ_list_sort() {
    var key = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ρσ_list_sort.__defaults__.key : arguments[0];
    var reverse = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ρσ_list_sort.__defaults__.reverse : arguments[1];
    var ρσ_kwargs_obj = arguments[arguments.length-1];
    if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
    if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "key")){
        key = ρσ_kwargs_obj.key;
    }
    if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "reverse")){
        reverse = ρσ_kwargs_obj.reverse;
    }
    var mult, keymap, posmap, k;
    key = key || ρσ_list_sort_key;
    mult = (reverse) ? -1 : 1;
    keymap = dict();
    posmap = dict();
    for (var i=0; i < this.length; i++) {
        k = (ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
        keymap.set(k, key(k));
        posmap.set(k, i);
    }
    this.sort((function() {
        var ρσ_anonfunc = function (a, b) {
            return mult * ρσ_list_sort_cmp(keymap.get(a), keymap.get(b), posmap.get(a), posmap.get(b));
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["a", "b"]}
        });
        return ρσ_anonfunc;
    })());
};
if (!ρσ_list_sort.__defaults__) Object.defineProperties(ρσ_list_sort, {
    __defaults__ : {value: {key:null, reverse:false}},
    __handles_kwarg_interpolation__ : {value: true},
    __argnames__ : {value: ["key", "reverse"]}
});

function ρσ_list_concat() {
    var ans;
    ans = Array.prototype.concat.apply(this, arguments);
    ρσ_list_decorate(ans);
    return ans;
};

function ρσ_list_slice() {
    var ans;
    ans = Array.prototype.slice.apply(this, arguments);
    ρσ_list_decorate(ans);
    return ans;
};

function ρσ_list_iterator(value) {
    var self;
    self = this;
    return (function(){
        var ρσ_d = {};
        ρσ_d["_i"] = -1;
        ρσ_d["_list"] = self;
        ρσ_d["next"] = function () {
            this._i += 1;
            if (this._i >= this._list.length) {
                return (function(){
                    var ρσ_d = {};
                    ρσ_d["done"] = true;
                    return ρσ_d;
                }).call(this);
            }
            return (function(){
                var ρσ_d = {};
                ρσ_d["done"] = false;
                ρσ_d["value"] = (ρσ_expr_temp = this._list)[ρσ_bound_index(this._i, ρσ_expr_temp)];
                return ρσ_d;
            }).call(this);
        };
        return ρσ_d;
    }).call(this);
};
if (!ρσ_list_iterator.__argnames__) Object.defineProperties(ρσ_list_iterator, {
    __argnames__ : {value: ["value"]}
});

function ρσ_list_len() {
    return this.length;
};

function ρσ_list_contains(val) {
    for (var i = 0; i < this.length; i++) {
        if (((ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] === val || typeof (ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] === "object" && ρσ_equals((ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i], val))) {
            return true;
        }
    }
    return false;
};
if (!ρσ_list_contains.__argnames__) Object.defineProperties(ρσ_list_contains, {
    __argnames__ : {value: ["val"]}
});

function ρσ_list_eq(other) {
    if (!ρσ_arraylike(other)) {
        return false;
    }
    if ((this.length !== other.length && (typeof this.length !== "object" || ρσ_not_equals(this.length, other.length)))) {
        return false;
    }
    for (var i = 0; i < this.length; i++) {
        if (!(((ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] === other[(typeof i === "number" && i < 0) ? other.length + i : i] || typeof (ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] === "object" && ρσ_equals((ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i], other[(typeof i === "number" && i < 0) ? other.length + i : i])))) {
            return false;
        }
    }
    return true;
};
if (!ρσ_list_eq.__argnames__) Object.defineProperties(ρσ_list_eq, {
    __argnames__ : {value: ["other"]}
});

function ρσ_list_decorate(ans) {
    ans.append = Array.prototype.push;
    ans.toString = ρσ_list_to_string;
    ans.inspect = ρσ_list_to_string;
    ans.extend = ρσ_list_extend;
    ans.index = ρσ_list_index;
    ans.pypop = ρσ_list_pop;
    ans.remove = ρσ_list_remove;
    ans.insert = ρσ_list_insert;
    ans.copy = ρσ_list_copy;
    ans.clear = ρσ_list_clear;
    ans.count = ρσ_list_count;
    ans.concat = ρσ_list_concat;
    ans.pysort = ρσ_list_sort;
    ans.slice = ρσ_list_slice;
    ans.as_array = ρσ_list_as_array;
    ans.__len__ = ρσ_list_len;
    ans.__contains__ = ρσ_list_contains;
    ans.__eq__ = ρσ_list_eq;
    ans.constructor = ρσ_list_constructor;
    if (typeof ans[ρσ_iterator_symbol] !== "function") {
        ans[ρσ_iterator_symbol] = ρσ_list_iterator;
    }
    return ans;
};
if (!ρσ_list_decorate.__argnames__) Object.defineProperties(ρσ_list_decorate, {
    __argnames__ : {value: ["ans"]}
});

function ρσ_list_constructor(iterable) {
    var ans, iterator, result;
    if (iterable === undefined) {
        ans = [];
    } else if (ρσ_arraylike(iterable)) {
        ans = new Array(iterable.length);
        for (var i = 0; i < iterable.length; i++) {
            ans[(typeof i === "number" && i < 0) ? ans.length + i : i] = iterable[(typeof i === "number" && i < 0) ? iterable.length + i : i];
        }
    } else if (typeof iterable[ρσ_iterator_symbol] === "function") {
        iterator = (typeof Map === "function" && iterable instanceof Map) ? iterable.keys() : iterable[ρσ_iterator_symbol]();
        ans = ρσ_list_decorate([]);
        result = iterator.next();
        while (!result.done) {
            ans.push(result.value);
            result = iterator.next();
        }
    } else if (typeof iterable === "number") {
        ans = new Array(iterable);
    } else {
        ans = Object.keys(iterable);
    }
    return ρσ_list_decorate(ans);
};
if (!ρσ_list_constructor.__argnames__) Object.defineProperties(ρσ_list_constructor, {
    __argnames__ : {value: ["iterable"]}
});

ρσ_list_constructor.__name__ = "list";
var list = ρσ_list_constructor, list_wrap = ρσ_list_decorate;
function sorted() {
    var iterable = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
    var key = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? sorted.__defaults__.key : arguments[1];
    var reverse = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? sorted.__defaults__.reverse : arguments[2];
    var ρσ_kwargs_obj = arguments[arguments.length-1];
    if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
    if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "key")){
        key = ρσ_kwargs_obj.key;
    }
    if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "reverse")){
        reverse = ρσ_kwargs_obj.reverse;
    }
    var ans;
    ans = ρσ_list_constructor(iterable);
    ans.pysort(key, reverse);
    return ans;
};
if (!sorted.__defaults__) Object.defineProperties(sorted, {
    __defaults__ : {value: {key:null, reverse:false}},
    __handles_kwarg_interpolation__ : {value: true},
    __argnames__ : {value: ["iterable", "key", "reverse"]}
});

var ρσ_global_object_id = 0, ρσ_set_implementation;
function ρσ_set_keyfor(x) {
    var t, ans;
    t = typeof x;
    if (t === "string" || t === "number" || t === "boolean") {
        return "_" + t[0] + x;
    }
    if (x === null) {
        return "__!@#$0";
    }
    ans = x.ρσ_hash_key_prop;
    if (ans === undefined) {
        ans = "_!@#$" + (++ρσ_global_object_id);
        Object.defineProperty(x, "ρσ_hash_key_prop", (function(){
            var ρσ_d = {};
            ρσ_d["value"] = ans;
            return ρσ_d;
        }).call(this));
    }
    return ans;
};
if (!ρσ_set_keyfor.__argnames__) Object.defineProperties(ρσ_set_keyfor, {
    __argnames__ : {value: ["x"]}
});

function ρσ_set_polyfill() {
    this._store = {};
    this.size = 0;
};

ρσ_set_polyfill.prototype.add = (function() {
    var ρσ_anonfunc = function (x) {
        var key;
        key = ρσ_set_keyfor(x);
        if (!Object.prototype.hasOwnProperty.call(this._store, key)) {
            this.size += 1;
            (ρσ_expr_temp = this._store)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key] = x;
        }
        return this;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set_polyfill.prototype.clear = (function() {
    var ρσ_anonfunc = function (x) {
        this._store = {};
        this.size = 0;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set_polyfill.prototype.delete = (function() {
    var ρσ_anonfunc = function (x) {
        var key;
        key = ρσ_set_keyfor(x);
        if (Object.prototype.hasOwnProperty.call(this._store, key)) {
            this.size -= 1;
            delete this._store[key];
            return true;
        }
        return false;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set_polyfill.prototype.has = (function() {
    var ρσ_anonfunc = function (x) {
        return Object.prototype.hasOwnProperty.call(this._store, ρσ_set_keyfor(x));
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set_polyfill.prototype.values = (function() {
    var ρσ_anonfunc = function (x) {
        var ans;
        ans = {'_keys': Object.keys(this._store), '_i':-1, '_s':this._store};
        ans[ρσ_iterator_symbol] = function () {
            return this;
        };
        ans["next"] = function () {
            this._i += 1;
            if (this._i >= this._keys.length) {
                return {'done': true};
            }
            return {'done':false, 'value':this._s[this._keys[this._i]]};
        };
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
if (typeof Set !== "function" || typeof Set.prototype.delete !== "function") {
    ρσ_set_implementation = ρσ_set_polyfill;
} else {
    ρσ_set_implementation = Set;
}
function ρσ_set(iterable) {
    var ans, s, iterator, result, keys;
    if (this instanceof ρσ_set) {
        this.jsset = new ρσ_set_implementation;
        ans = this;
        if (iterable === undefined) {
            return ans;
        }
        s = ans.jsset;
        if (ρσ_arraylike(iterable)) {
            for (var i = 0; i < iterable.length; i++) {
                s.add(iterable[(typeof i === "number" && i < 0) ? iterable.length + i : i]);
            }
        } else if (typeof iterable[ρσ_iterator_symbol] === "function") {
            iterator = (typeof Map === "function" && iterable instanceof Map) ? iterable.keys() : iterable[ρσ_iterator_symbol]();
            result = iterator.next();
            while (!result.done) {
                s.add(result.value);
                result = iterator.next();
            }
        } else {
            keys = Object.keys(iterable);
            for (var j=0; j < keys.length; j++) {
                s.add(keys[(typeof j === "number" && j < 0) ? keys.length + j : j]);
            }
        }
        return ans;
    } else {
        return new ρσ_set(iterable);
    }
};
if (!ρσ_set.__argnames__) Object.defineProperties(ρσ_set, {
    __argnames__ : {value: ["iterable"]}
});

ρσ_set.prototype.__name__ = "set";
Object.defineProperties(ρσ_set.prototype, (function(){
    var ρσ_d = {};
    ρσ_d["length"] = (function(){
        var ρσ_d = {};
        ρσ_d["get"] = function () {
            return this.jsset.size;
        };
        return ρσ_d;
    }).call(this);
    ρσ_d["size"] = (function(){
        var ρσ_d = {};
        ρσ_d["get"] = function () {
            return this.jsset.size;
        };
        return ρσ_d;
    }).call(this);
    return ρσ_d;
}).call(this));
ρσ_set.prototype.__len__ = function () {
    return this.jsset.size;
};
ρσ_set.prototype.has = ρσ_set.prototype.__contains__ = (function() {
    var ρσ_anonfunc = function (x) {
        return this.jsset.has(x);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype.add = (function() {
    var ρσ_anonfunc = function (x) {
        this.jsset.add(x);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype.clear = function () {
    this.jsset.clear();
};
ρσ_set.prototype.copy = function () {
    return ρσ_set(this);
};
ρσ_set.prototype.discard = (function() {
    var ρσ_anonfunc = function (x) {
        this.jsset.delete(x);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype[ρσ_iterator_symbol] = function () {
    return this.jsset.values();
};
ρσ_set.prototype.difference = function () {
    var ans, s, iterator, r, x, has;
    ans = new ρσ_set;
    s = ans.jsset;
    iterator = this.jsset.values();
    r = iterator.next();
    while (!r.done) {
        x = r.value;
        has = false;
        for (var i = 0; i < arguments.length; i++) {
            if (arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i].has(x)) {
                has = true;
                break;
            }
        }
        if (!has) {
            s.add(x);
        }
        r = iterator.next();
    }
    return ans;
};
ρσ_set.prototype.difference_update = function () {
    var s, remove, iterator, r, x;
    s = this.jsset;
    remove = [];
    iterator = s.values();
    r = iterator.next();
    while (!r.done) {
        x = r.value;
        for (var i = 0; i < arguments.length; i++) {
            if (arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i].has(x)) {
                remove.push(x);
                break;
            }
        }
        r = iterator.next();
    }
    for (var j = 0; j < remove.length; j++) {
        s.delete(remove[(typeof j === "number" && j < 0) ? remove.length + j : j]);
    }
};
ρσ_set.prototype.intersection = function () {
    var ans, s, iterator, r, x, has;
    ans = new ρσ_set;
    s = ans.jsset;
    iterator = this.jsset.values();
    r = iterator.next();
    while (!r.done) {
        x = r.value;
        has = true;
        for (var i = 0; i < arguments.length; i++) {
            if (!arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i].has(x)) {
                has = false;
                break;
            }
        }
        if (has) {
            s.add(x);
        }
        r = iterator.next();
    }
    return ans;
};
ρσ_set.prototype.intersection_update = function () {
    var s, remove, iterator, r, x;
    s = this.jsset;
    remove = [];
    iterator = s.values();
    r = iterator.next();
    while (!r.done) {
        x = r.value;
        for (var i = 0; i < arguments.length; i++) {
            if (!arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i].has(x)) {
                remove.push(x);
                break;
            }
        }
        r = iterator.next();
    }
    for (var j = 0; j < remove.length; j++) {
        s.delete(remove[(typeof j === "number" && j < 0) ? remove.length + j : j]);
    }
};
ρσ_set.prototype.isdisjoint = (function() {
    var ρσ_anonfunc = function (other) {
        var iterator, r, x;
        iterator = this.jsset.values();
        r = iterator.next();
        while (!r.done) {
            x = r.value;
            if (other.has(x)) {
                return false;
            }
            r = iterator.next();
        }
        return true;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["other"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype.issubset = (function() {
    var ρσ_anonfunc = function (other) {
        var iterator, r, x;
        iterator = this.jsset.values();
        r = iterator.next();
        while (!r.done) {
            x = r.value;
            if (!other.has(x)) {
                return false;
            }
            r = iterator.next();
        }
        return true;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["other"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype.issuperset = (function() {
    var ρσ_anonfunc = function (other) {
        var s, iterator, r, x;
        s = this.jsset;
        iterator = other.jsset.values();
        r = iterator.next();
        while (!r.done) {
            x = r.value;
            if (!s.has(x)) {
                return false;
            }
            r = iterator.next();
        }
        return true;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["other"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype.pop = function () {
    var iterator, r;
    iterator = this.jsset.values();
    r = iterator.next();
    if (r.done) {
        throw new KeyError("pop from an empty set");
    }
    this.jsset.delete(r.value);
    return r.value;
};
ρσ_set.prototype.remove = (function() {
    var ρσ_anonfunc = function (x) {
        if (!this.jsset.delete(x)) {
            throw new KeyError(x.toString());
        }
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype.symmetric_difference = (function() {
    var ρσ_anonfunc = function (other) {
        return this.union(other).difference(this.intersection(other));
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["other"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype.symmetric_difference_update = (function() {
    var ρσ_anonfunc = function (other) {
        var common;
        common = this.intersection(other);
        this.update(other);
        this.difference_update(common);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["other"]}
    });
    return ρσ_anonfunc;
})();
ρσ_set.prototype.union = function () {
    var ans;
    ans = ρσ_set(this);
    ans.update.apply(ans, arguments);
    return ans;
};
ρσ_set.prototype.update = function () {
    var s, iterator, r;
    s = this.jsset;
    for (var i=0; i < arguments.length; i++) {
        iterator = arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i][ρσ_iterator_symbol]();
        r = iterator.next();
        while (!r.done) {
            s.add(r.value);
            r = iterator.next();
        }
    }
};
ρσ_set.prototype.toString = ρσ_set.prototype.__repr__ = ρσ_set.prototype.__str__ = ρσ_set.prototype.inspect = function () {
    return "{" + list(this).join(", ") + "}";
};
ρσ_set.prototype.__eq__ = (function() {
    var ρσ_anonfunc = function (other) {
        var iterator, r;
        if (!other instanceof this.constructor) {
            return false;
        }
        if (other.size !== this.size) {
            return false;
        }
        if (other.size === 0) {
            return true;
        }
        iterator = other[ρσ_iterator_symbol]();
        r = iterator.next();
        while (!r.done) {
            if (!this.has(r.value)) {
                return false;
            }
            r = iterator.next();
        }
        return true;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["other"]}
    });
    return ρσ_anonfunc;
})();
function ρσ_set_wrap(x) {
    var ans;
    ans = new ρσ_set;
    ans.jsset = x;
    return ans;
};
if (!ρσ_set_wrap.__argnames__) Object.defineProperties(ρσ_set_wrap, {
    __argnames__ : {value: ["x"]}
});

var set = ρσ_set, set_wrap = ρσ_set_wrap;
var ρσ_dict_implementation;
function ρσ_dict_polyfill() {
    this._store = {};
    this.size = 0;
};

ρσ_dict_polyfill.prototype.set = (function() {
    var ρσ_anonfunc = function (x, value) {
        var key;
        key = ρσ_set_keyfor(x);
        if (!Object.prototype.hasOwnProperty.call(this._store, key)) {
            this.size += 1;
        }
        (ρσ_expr_temp = this._store)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key] = [x, value];
        return this;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x", "value"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict_polyfill.prototype.clear = (function() {
    var ρσ_anonfunc = function (x) {
        this._store = {};
        this.size = 0;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict_polyfill.prototype.delete = (function() {
    var ρσ_anonfunc = function (x) {
        var key;
        key = ρσ_set_keyfor(x);
        if (Object.prototype.hasOwnProperty.call(this._store, key)) {
            this.size -= 1;
            delete this._store[key];
            return true;
        }
        return false;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict_polyfill.prototype.has = (function() {
    var ρσ_anonfunc = function (x) {
        return Object.prototype.hasOwnProperty.call(this._store, ρσ_set_keyfor(x));
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict_polyfill.prototype.get = (function() {
    var ρσ_anonfunc = function (x) {
        try {
            return (ρσ_expr_temp = this._store)[ρσ_bound_index(ρσ_set_keyfor(x), ρσ_expr_temp)][1];
        } catch (ρσ_Exception) {
            ρσ_last_exception = ρσ_Exception;
            if (ρσ_Exception instanceof TypeError) {
                return undefined;
            } else {
                throw ρσ_Exception;
            }
        }
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict_polyfill.prototype.values = (function() {
    var ρσ_anonfunc = function (x) {
        var ans;
        ans = {'_keys': Object.keys(this._store), '_i':-1, '_s':this._store};
        ans[ρσ_iterator_symbol] = function () {
            return this;
        };
        ans["next"] = function () {
            this._i += 1;
            if (this._i >= this._keys.length) {
                return {'done': true};
            }
            return {'done':false, 'value':this._s[this._keys[this._i]][1]};
        };
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict_polyfill.prototype.keys = (function() {
    var ρσ_anonfunc = function (x) {
        var ans;
        ans = {'_keys': Object.keys(this._store), '_i':-1, '_s':this._store};
        ans[ρσ_iterator_symbol] = function () {
            return this;
        };
        ans["next"] = function () {
            this._i += 1;
            if (this._i >= this._keys.length) {
                return {'done': true};
            }
            return {'done':false, 'value':this._s[this._keys[this._i]][0]};
        };
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict_polyfill.prototype.entries = (function() {
    var ρσ_anonfunc = function (x) {
        var ans;
        ans = {'_keys': Object.keys(this._store), '_i':-1, '_s':this._store};
        ans[ρσ_iterator_symbol] = function () {
            return this;
        };
        ans["next"] = function () {
            this._i += 1;
            if (this._i >= this._keys.length) {
                return {'done': true};
            }
            return {'done':false, 'value':this._s[this._keys[this._i]]};
        };
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
if (typeof Map !== "function" || typeof Map.prototype.delete !== "function") {
    ρσ_dict_implementation = ρσ_dict_polyfill;
} else {
    ρσ_dict_implementation = Map;
}
function ρσ_dict() {
    var iterable = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
    var kw = arguments[arguments.length-1];
    if (kw === null || typeof kw !== "object" || kw [ρσ_kwargs_symbol] !== true) kw = {};
    if (this instanceof ρσ_dict) {
        this.jsmap = new ρσ_dict_implementation;
        if (iterable !== undefined) {
            this.update(iterable);
        }
        this.update(kw);
        return this;
    } else {
        return ρσ_interpolate_kwargs_constructor.call(Object.create(ρσ_dict.prototype), false, ρσ_dict, [iterable].concat([ρσ_desugar_kwargs(kw)]));
    }
};
if (!ρσ_dict.__handles_kwarg_interpolation__) Object.defineProperties(ρσ_dict, {
    __handles_kwarg_interpolation__ : {value: true},
    __argnames__ : {value: ["iterable"]}
});

ρσ_dict.prototype.__name__ = "dict";
Object.defineProperties(ρσ_dict.prototype, (function(){
    var ρσ_d = {};
    ρσ_d["length"] = (function(){
        var ρσ_d = {};
        ρσ_d["get"] = function () {
            return this.jsmap.size;
        };
        return ρσ_d;
    }).call(this);
    ρσ_d["size"] = (function(){
        var ρσ_d = {};
        ρσ_d["get"] = function () {
            return this.jsmap.size;
        };
        return ρσ_d;
    }).call(this);
    return ρσ_d;
}).call(this));
ρσ_dict.prototype.__len__ = function () {
    return this.jsmap.size;
};
ρσ_dict.prototype.has = ρσ_dict.prototype.__contains__ = (function() {
    var ρσ_anonfunc = function (x) {
        return this.jsmap.has(x);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["x"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.prototype.set = ρσ_dict.prototype.__setitem__ = (function() {
    var ρσ_anonfunc = function (key, value) {
        this.jsmap.set(key, value);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["key", "value"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.prototype.__delitem__ = (function() {
    var ρσ_anonfunc = function (key) {
        this.jsmap.delete(key);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["key"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.prototype.clear = function () {
    this.jsmap.clear();
};
ρσ_dict.prototype.copy = function () {
    return ρσ_dict(this);
};
ρσ_dict.prototype.keys = function () {
    return this.jsmap.keys();
};
ρσ_dict.prototype.values = function () {
    return this.jsmap.values();
};
ρσ_dict.prototype.items = ρσ_dict.prototype.entries = function () {
    return this.jsmap.entries();
};
ρσ_dict.prototype[ρσ_iterator_symbol] = function () {
    return this.jsmap.keys();
};
ρσ_dict.prototype.__getitem__ = (function() {
    var ρσ_anonfunc = function (key) {
        var ans;
        ans = this.jsmap.get(key);
        if (ans === undefined && !this.jsmap.has(key)) {
            throw new KeyError(key + "");
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["key"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.prototype.get = (function() {
    var ρσ_anonfunc = function (key, defval) {
        var ans;
        ans = this.jsmap.get(key);
        if (ans === undefined && !this.jsmap.has(key)) {
            return (defval === undefined) ? null : defval;
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["key", "defval"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.prototype.set_default = (function() {
    var ρσ_anonfunc = function (key, defval) {
        var j;
        j = this.jsmap;
        if (!j.has(key)) {
            j.set(key, defval);
            return defval;
        }
        return j.get(key);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["key", "defval"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.fromkeys = ρσ_dict.prototype.fromkeys = (function() {
    var ρσ_anonfunc = function () {
        var iterable = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
        var value = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ρσ_anonfunc.__defaults__.value : arguments[1];
        var ρσ_kwargs_obj = arguments[arguments.length-1];
        if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
        if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "value")){
            value = ρσ_kwargs_obj.value;
        }
        var ans, iterator, r;
        ans = ρσ_dict();
        iterator = iter(iterable);
        r = iterator.next();
        while (!r.done) {
            ans.set(r.value, value);
            r = iterator.next();
        }
        return ans;
    };
    if (!ρσ_anonfunc.__defaults__) Object.defineProperties(ρσ_anonfunc, {
        __defaults__ : {value: {value:null}},
        __handles_kwarg_interpolation__ : {value: true},
        __argnames__ : {value: ["iterable", "value"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.prototype.pop = (function() {
    var ρσ_anonfunc = function (key, defval) {
        var ans;
        ans = this.jsmap.get(key);
        if (ans === undefined && !this.jsmap.has(key)) {
            if (defval === undefined) {
                throw new KeyError(key);
            }
            return defval;
        }
        this.jsmap.delete(key);
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["key", "defval"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.prototype.popitem = function () {
    var r;
    r = this.jsmap.entries().next();
    if (r.done) {
        throw new KeyError("dict is empty");
    }
    this.jsmap.delete(r.value[0]);
    return r.value;
};
ρσ_dict.prototype.update = function () {
    var m, iterable, iterator, result, keys;
    if (arguments.length === 0) {
        return;
    }
    m = this.jsmap;
    iterable = arguments[0];
    if (Array.isArray(iterable)) {
        for (var i = 0; i < iterable.length; i++) {
            m.set(iterable[(typeof i === "number" && i < 0) ? iterable.length + i : i][0], iterable[(typeof i === "number" && i < 0) ? iterable.length + i : i][1]);
        }
    } else if (iterable instanceof ρσ_dict) {
        iterator = iterable.items();
        result = iterator.next();
        while (!result.done) {
            m.set(result.value[0], result.value[1]);
            result = iterator.next();
        }
    } else if (typeof Map === "function" && iterable instanceof Map) {
        iterator = iterable.entries();
        result = iterator.next();
        while (!result.done) {
            m.set(result.value[0], result.value[1]);
            result = iterator.next();
        }
    } else if (typeof iterable[ρσ_iterator_symbol] === "function") {
        iterator = iterable[ρσ_iterator_symbol]();
        result = iterator.next();
        while (!result.done) {
            m.set(result.value[0], result.value[1]);
            result = iterator.next();
        }
    } else {
        keys = Object.keys(iterable);
        for (var j=0; j < keys.length; j++) {
            if (keys[(typeof j === "number" && j < 0) ? keys.length + j : j] !== ρσ_iterator_symbol) {
                m.set(keys[(typeof j === "number" && j < 0) ? keys.length + j : j], iterable[ρσ_bound_index(keys[(typeof j === "number" && j < 0) ? keys.length + j : j], iterable)]);
            }
        }
    }
    if (arguments.length > 1) {
        ρσ_dict.prototype.update.call(this, arguments[1]);
    }
};
ρσ_dict.prototype.toString = ρσ_dict.prototype.inspect = ρσ_dict.prototype.__str__ = ρσ_dict.prototype.__repr__ = function () {
    var entries, iterator, r;
    entries = [];
    iterator = this.jsmap.entries();
    r = iterator.next();
    while (!r.done) {
        entries.push(ρσ_repr(r.value[0]) + ": " + ρσ_repr(r.value[1]));
        r = iterator.next();
    }
    return "{" + entries.join(", ") + "}";
};
ρσ_dict.prototype.__eq__ = (function() {
    var ρσ_anonfunc = function (other) {
        var iterator, r, x;
        if (!(other instanceof this.constructor)) {
            return false;
        }
        if (other.size !== this.size) {
            return false;
        }
        if (other.size === 0) {
            return true;
        }
        iterator = other.items();
        r = iterator.next();
        while (!r.done) {
            x = this.jsmap.get(r.value[0]);
            if (x === undefined && !this.jsmap.has(r.value[0]) || x !== r.value[1]) {
                return false;
            }
            r = iterator.next();
        }
        return true;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["other"]}
    });
    return ρσ_anonfunc;
})();
ρσ_dict.prototype.as_object = (function() {
    var ρσ_anonfunc = function (other) {
        var ans, iterator, r;
        ans = {};
        iterator = this.jsmap.entries();
        r = iterator.next();
        while (!r.done) {
            ans[ρσ_bound_index(r.value[0], ans)] = r.value[1];
            r = iterator.next();
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["other"]}
    });
    return ρσ_anonfunc;
})();
function ρσ_dict_wrap(x) {
    var ans;
    ans = new ρσ_dict;
    ans.jsmap = x;
    return ans;
};
if (!ρσ_dict_wrap.__argnames__) Object.defineProperties(ρσ_dict_wrap, {
    __argnames__ : {value: ["x"]}
});

var dict = ρσ_dict, dict_wrap = ρσ_dict_wrap;// }}}
var NameError;
NameError = ReferenceError;
function Exception() {
    if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
    Exception.prototype.__init__.apply(this, arguments);
}
ρσ_extends(Exception, Error);
Exception.prototype.__init__ = function __init__(message) {
    var self = this;
    self.message = message;
    self.stack = (new Error).stack;
    self.name = self.constructor.name;
};
if (!Exception.prototype.__init__.__argnames__) Object.defineProperties(Exception.prototype.__init__, {
    __argnames__ : {value: ["message"]}
});
Exception.__argnames__ = Exception.prototype.__init__.__argnames__;
Exception.__handles_kwarg_interpolation__ = Exception.prototype.__init__.__handles_kwarg_interpolation__;
Exception.prototype.__repr__ = function __repr__() {
    var self = this;
    return self.name + ": " + self.message;
};
Exception.prototype.__str__ = function __str__ () {
    if(Error.prototype.__str__) return Error.prototype.__str__.call(this);
return this.__repr__();
};
Object.defineProperty(Exception.prototype, "__bases__", {value: [Error]});

function AttributeError() {
    if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
    AttributeError.prototype.__init__.apply(this, arguments);
}
ρσ_extends(AttributeError, Exception);
AttributeError.prototype.__init__ = function __init__ () {
    Exception.prototype.__init__ && Exception.prototype.__init__.apply(this, arguments);
};
AttributeError.prototype.__repr__ = function __repr__ () {
    if(Exception.prototype.__repr__) return Exception.prototype.__repr__.call(this);
    return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
};
AttributeError.prototype.__str__ = function __str__ () {
    if(Exception.prototype.__str__) return Exception.prototype.__str__.call(this);
return this.__repr__();
};
Object.defineProperty(AttributeError.prototype, "__bases__", {value: [Exception]});


function IndexError() {
    if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
    IndexError.prototype.__init__.apply(this, arguments);
}
ρσ_extends(IndexError, Exception);
IndexError.prototype.__init__ = function __init__ () {
    Exception.prototype.__init__ && Exception.prototype.__init__.apply(this, arguments);
};
IndexError.prototype.__repr__ = function __repr__ () {
    if(Exception.prototype.__repr__) return Exception.prototype.__repr__.call(this);
    return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
};
IndexError.prototype.__str__ = function __str__ () {
    if(Exception.prototype.__str__) return Exception.prototype.__str__.call(this);
return this.__repr__();
};
Object.defineProperty(IndexError.prototype, "__bases__", {value: [Exception]});


function KeyError() {
    if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
    KeyError.prototype.__init__.apply(this, arguments);
}
ρσ_extends(KeyError, Exception);
KeyError.prototype.__init__ = function __init__ () {
    Exception.prototype.__init__ && Exception.prototype.__init__.apply(this, arguments);
};
KeyError.prototype.__repr__ = function __repr__ () {
    if(Exception.prototype.__repr__) return Exception.prototype.__repr__.call(this);
    return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
};
KeyError.prototype.__str__ = function __str__ () {
    if(Exception.prototype.__str__) return Exception.prototype.__str__.call(this);
return this.__repr__();
};
Object.defineProperty(KeyError.prototype, "__bases__", {value: [Exception]});


function ValueError() {
    if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
    ValueError.prototype.__init__.apply(this, arguments);
}
ρσ_extends(ValueError, Exception);
ValueError.prototype.__init__ = function __init__ () {
    Exception.prototype.__init__ && Exception.prototype.__init__.apply(this, arguments);
};
ValueError.prototype.__repr__ = function __repr__ () {
    if(Exception.prototype.__repr__) return Exception.prototype.__repr__.call(this);
    return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
};
ValueError.prototype.__str__ = function __str__ () {
    if(Exception.prototype.__str__) return Exception.prototype.__str__.call(this);
return this.__repr__();
};
Object.defineProperty(ValueError.prototype, "__bases__", {value: [Exception]});


function UnicodeDecodeError() {
    if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
    UnicodeDecodeError.prototype.__init__.apply(this, arguments);
}
ρσ_extends(UnicodeDecodeError, Exception);
UnicodeDecodeError.prototype.__init__ = function __init__ () {
    Exception.prototype.__init__ && Exception.prototype.__init__.apply(this, arguments);
};
UnicodeDecodeError.prototype.__repr__ = function __repr__ () {
    if(Exception.prototype.__repr__) return Exception.prototype.__repr__.call(this);
    return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
};
UnicodeDecodeError.prototype.__str__ = function __str__ () {
    if(Exception.prototype.__str__) return Exception.prototype.__str__.call(this);
return this.__repr__();
};
Object.defineProperty(UnicodeDecodeError.prototype, "__bases__", {value: [Exception]});


function AssertionError() {
    if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
    AssertionError.prototype.__init__.apply(this, arguments);
}
ρσ_extends(AssertionError, Exception);
AssertionError.prototype.__init__ = function __init__ () {
    Exception.prototype.__init__ && Exception.prototype.__init__.apply(this, arguments);
};
AssertionError.prototype.__repr__ = function __repr__ () {
    if(Exception.prototype.__repr__) return Exception.prototype.__repr__.call(this);
    return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
};
AssertionError.prototype.__str__ = function __str__ () {
    if(Exception.prototype.__str__) return Exception.prototype.__str__.call(this);
return this.__repr__();
};
Object.defineProperty(AssertionError.prototype, "__bases__", {value: [Exception]});


function ZeroDivisionError() {
    if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
    ZeroDivisionError.prototype.__init__.apply(this, arguments);
}
ρσ_extends(ZeroDivisionError, Exception);
ZeroDivisionError.prototype.__init__ = function __init__ () {
    Exception.prototype.__init__ && Exception.prototype.__init__.apply(this, arguments);
};
ZeroDivisionError.prototype.__repr__ = function __repr__ () {
    if(Exception.prototype.__repr__) return Exception.prototype.__repr__.call(this);
    return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
};
ZeroDivisionError.prototype.__str__ = function __str__ () {
    if(Exception.prototype.__str__) return Exception.prototype.__str__.call(this);
return this.__repr__();
};
Object.defineProperty(ZeroDivisionError.prototype, "__bases__", {value: [Exception]});

var ρσ_in, ρσ_desugar_kwargs, ρσ_exists;
function ρσ_eslice(arr, step, start, end) {
    var is_string;
    if (typeof arr === "string" || arr instanceof String) {
        is_string = true;
        arr = arr.split("");
    }
    if (step < 0) {
        step = -step;
        arr = arr.slice().reverse();
        if (typeof start !== "undefined") {
            start = arr.length - start - 1;
        }
        if (typeof end !== "undefined") {
            end = arr.length - end - 1;
        }
    }
    if (typeof start === "undefined") {
        start = 0;
    }
    if (typeof end === "undefined") {
        end = arr.length;
    }
    arr = arr.slice(start, end).filter((function() {
        var ρσ_anonfunc = function (e, i) {
            return i % step === 0;
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["e", "i"]}
        });
        return ρσ_anonfunc;
    })());
    if (is_string) {
        arr = arr.join("");
    }
    return arr;
};
if (!ρσ_eslice.__argnames__) Object.defineProperties(ρσ_eslice, {
    __argnames__ : {value: ["arr", "step", "start", "end"]}
});

function ρσ_delslice(arr, step, start, end) {
    var is_string, ρσ_unpack, indices;
    if (typeof arr === "string" || arr instanceof String) {
        is_string = true;
        arr = arr.split("");
    }
    if (step < 0) {
        if (typeof start === "undefined") {
            start = arr.length;
        }
        if (typeof end === "undefined") {
            end = 0;
        }
        ρσ_unpack = [end, start, -step];
        start = ρσ_unpack[0];
        end = ρσ_unpack[1];
        step = ρσ_unpack[2];
    }
    if (typeof start === "undefined") {
        start = 0;
    }
    if (typeof end === "undefined") {
        end = arr.length;
    }
    if (step === 1) {
        arr.splice(start, end - start);
    } else {
        if (end > start) {
            indices = [];
            for (var i = start; i < end; i += step) {
                indices.push(i);
            }
            for (var i = indices.length - 1; i >= 0; i--) {
                arr.splice(indices[(typeof i === "number" && i < 0) ? indices.length + i : i], 1);
            }
        }
    }
    if (is_string) {
        arr = arr.join("");
    }
    return arr;
};
if (!ρσ_delslice.__argnames__) Object.defineProperties(ρσ_delslice, {
    __argnames__ : {value: ["arr", "step", "start", "end"]}
});

function ρσ_flatten(arr) {
    var ans, value;
    ans = ρσ_list_decorate([]);
    for (var i=0; i < arr.length; i++) {
        value = arr[(typeof i === "number" && i < 0) ? arr.length + i : i];
        if (Array.isArray(value)) {
            ans = ans.concat(ρσ_flatten(value));
        } else {
            ans.push(value);
        }
    }
    return ans;
};
if (!ρσ_flatten.__argnames__) Object.defineProperties(ρσ_flatten, {
    __argnames__ : {value: ["arr"]}
});

function ρσ_unpack_asarray(num, iterable) {
    var ans, iterator, result;
    if (ρσ_arraylike(iterable)) {
        return iterable;
    }
    ans = [];
    if (typeof iterable[ρσ_iterator_symbol] === "function") {
        iterator = (typeof Map === "function" && iterable instanceof Map) ? iterable.keys() : iterable[ρσ_iterator_symbol]();
        result = iterator.next();
        while (!result.done && ans.length < num) {
            ans.push(result.value);
            result = iterator.next();
        }
    }
    return ans;
};
if (!ρσ_unpack_asarray.__argnames__) Object.defineProperties(ρσ_unpack_asarray, {
    __argnames__ : {value: ["num", "iterable"]}
});

function ρσ_extends(child, parent) {
    child.prototype = Object.create(parent.prototype);
    child.prototype.constructor = child;
};
if (!ρσ_extends.__argnames__) Object.defineProperties(ρσ_extends, {
    __argnames__ : {value: ["child", "parent"]}
});

ρσ_in = function () {
    if (typeof Map === "function" && typeof Set === "function") {
        return (function() {
            var ρσ_anonfunc = function (val, arr) {
                if (typeof arr === "string") {
                    return arr.indexOf(val) !== -1;
                }
                if (typeof arr.__contains__ === "function") {
                    return arr.__contains__(val);
                }
                if (arr instanceof Map || arr instanceof Set) {
                    return arr.has(val);
                }
                if (ρσ_arraylike(arr)) {
                    return ρσ_list_contains.call(arr, val);
                }
                return Object.prototype.hasOwnProperty.call(arr, val);
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["val", "arr"]}
            });
            return ρσ_anonfunc;
        })();
    }
    return (function() {
        var ρσ_anonfunc = function (val, arr) {
            if (typeof arr === "string") {
                return arr.indexOf(val) !== -1;
            }
            if (typeof arr.__contains__ === "function") {
                return arr.__contains__(val);
            }
            if (ρσ_arraylike(arr)) {
                return ρσ_list_contains.call(arr, val);
            }
            return Object.prototype.hasOwnProperty.call(arr, val);
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["val", "arr"]}
        });
        return ρσ_anonfunc;
    })();
}();
function ρσ_Iterable(iterable) {
    var iterator, ans, result;
    if (ρσ_arraylike(iterable)) {
        return iterable;
    }
    if (typeof iterable[ρσ_iterator_symbol] === "function") {
        iterator = (typeof Map === "function" && iterable instanceof Map) ? iterable.keys() : iterable[ρσ_iterator_symbol]();
        ans = ρσ_list_decorate([]);
        result = iterator.next();
        while (!result.done) {
            ans.push(result.value);
            result = iterator.next();
        }
        return ans;
    }
    return Object.keys(iterable);
};
if (!ρσ_Iterable.__argnames__) Object.defineProperties(ρσ_Iterable, {
    __argnames__ : {value: ["iterable"]}
});

ρσ_desugar_kwargs = function () {
    if (typeof Object.assign === "function") {
        return function () {
            var ans;
            ans = Object.create(null);
            ans[ρσ_kwargs_symbol] = true;
            for (var i = 0; i < arguments.length; i++) {
                Object.assign(ans, arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i]);
            }
            return ans;
        };
    }
    return function () {
        var ans, keys;
        ans = Object.create(null);
        ans[ρσ_kwargs_symbol] = true;
        for (var i = 0; i < arguments.length; i++) {
            keys = Object.keys(arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i]);
            for (var j = 0; j < keys.length; j++) {
                ans[ρσ_bound_index(keys[(typeof j === "number" && j < 0) ? keys.length + j : j], ans)] = (ρσ_expr_temp = arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i])[ρσ_bound_index(keys[(typeof j === "number" && j < 0) ? keys.length + j : j], ρσ_expr_temp)];
            }
        }
        return ans;
    };
}();
function ρσ_interpolate_kwargs(f, supplied_args) {
    var has_prop, kwobj, args, prop;
    if (!f.__argnames__) {
        return f.apply(this, supplied_args);
    }
    has_prop = Object.prototype.hasOwnProperty;
    kwobj = supplied_args.pop();
    if (f.__handles_kwarg_interpolation__) {
        args = new Array(Math.max(supplied_args.length, f.__argnames__.length) + 1);
        args[args.length-1] = kwobj;
        for (var i = 0; i < args.length - 1; i++) {
            if (i < f.__argnames__.length) {
                prop = (ρσ_expr_temp = f.__argnames__)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
                if (has_prop.call(kwobj, prop)) {
                    args[(typeof i === "number" && i < 0) ? args.length + i : i] = kwobj[(typeof prop === "number" && prop < 0) ? kwobj.length + prop : prop];
                    delete kwobj[prop];
                } else if (i < supplied_args.length) {
                    args[(typeof i === "number" && i < 0) ? args.length + i : i] = supplied_args[(typeof i === "number" && i < 0) ? supplied_args.length + i : i];
                }
            } else {
                args[(typeof i === "number" && i < 0) ? args.length + i : i] = supplied_args[(typeof i === "number" && i < 0) ? supplied_args.length + i : i];
            }
        }
        return f.apply(this, args);
    }
    for (var i = 0; i < f.__argnames__.length; i++) {
        prop = (ρσ_expr_temp = f.__argnames__)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
        if (has_prop.call(kwobj, prop)) {
            supplied_args[(typeof i === "number" && i < 0) ? supplied_args.length + i : i] = kwobj[(typeof prop === "number" && prop < 0) ? kwobj.length + prop : prop];
        }
    }
    return f.apply(this, supplied_args);
};
if (!ρσ_interpolate_kwargs.__argnames__) Object.defineProperties(ρσ_interpolate_kwargs, {
    __argnames__ : {value: ["f", "supplied_args"]}
});

function ρσ_interpolate_kwargs_constructor(apply, f, supplied_args) {
    if (apply) {
        f.apply(this, supplied_args);
    } else {
        ρσ_interpolate_kwargs.call(this, f, supplied_args);
    }
    return this;
};
if (!ρσ_interpolate_kwargs_constructor.__argnames__) Object.defineProperties(ρσ_interpolate_kwargs_constructor, {
    __argnames__ : {value: ["apply", "f", "supplied_args"]}
});

function ρσ_getitem(obj, key) {
    if (obj.__getitem__) {
        return obj.__getitem__(key);
    }
    if (typeof key === "number" && key < 0) {
        key += obj.length;
    }
    return obj[(typeof key === "number" && key < 0) ? obj.length + key : key];
};
if (!ρσ_getitem.__argnames__) Object.defineProperties(ρσ_getitem, {
    __argnames__ : {value: ["obj", "key"]}
});

function ρσ_setitem(obj, key, val) {
    if (obj.__setitem__) {
        obj.__setitem__(key, val);
    } else {
        if (typeof key === "number" && key < 0) {
            key += obj.length;
        }
        obj[(typeof key === "number" && key < 0) ? obj.length + key : key] = val;
    }
};
if (!ρσ_setitem.__argnames__) Object.defineProperties(ρσ_setitem, {
    __argnames__ : {value: ["obj", "key", "val"]}
});

function ρσ_delitem(obj, key) {
    if (obj.__delitem__) {
        obj.__delitem__(key);
    } else if (typeof obj.splice === "function") {
        obj.splice(key, 1);
    } else {
        if (typeof key === "number" && key < 0) {
            key += obj.length;
        }
        delete obj[key];
    }
};
if (!ρσ_delitem.__argnames__) Object.defineProperties(ρσ_delitem, {
    __argnames__ : {value: ["obj", "key"]}
});

function ρσ_bound_index(idx, arr) {
    if (typeof idx === "number" && idx < 0) {
        idx += arr.length;
    }
    return idx;
};
if (!ρσ_bound_index.__argnames__) Object.defineProperties(ρσ_bound_index, {
    __argnames__ : {value: ["idx", "arr"]}
});

function ρσ_splice(arr, val, start, end) {
    start = start || 0;
    if (start < 0) {
        start += arr.length;
    }
    if (end === undefined) {
        end = arr.length;
    }
    if (end < 0) {
        end += arr.length;
    }
    Array.prototype.splice.apply(arr, [start, end - start].concat(val));
};
if (!ρσ_splice.__argnames__) Object.defineProperties(ρσ_splice, {
    __argnames__ : {value: ["arr", "val", "start", "end"]}
});

ρσ_exists = (function(){
    var ρσ_d = {};
    ρσ_d["n"] = (function() {
        var ρσ_anonfunc = function (expr) {
            return expr !== undefined && expr !== null;
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["expr"]}
        });
        return ρσ_anonfunc;
    })();
    ρσ_d["d"] = (function() {
        var ρσ_anonfunc = function (expr) {
            if (expr === undefined || expr === null) {
                return Object.create(null);
            }
            return expr;
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["expr"]}
        });
        return ρσ_anonfunc;
    })();
    ρσ_d["c"] = (function() {
        var ρσ_anonfunc = function (expr) {
            if (typeof expr === "function") {
                return expr;
            }
            return function () {
                return undefined;
            };
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["expr"]}
        });
        return ρσ_anonfunc;
    })();
    ρσ_d["g"] = (function() {
        var ρσ_anonfunc = function (expr) {
            if (expr === undefined || expr === null || typeof expr.__getitem__ !== "function") {
                return (function(){
                    var ρσ_d = {};
                    ρσ_d["__getitem__"] = function () {
                        return undefined;
                    };
                    return ρσ_d;
                }).call(this);
            }
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["expr"]}
        });
        return ρσ_anonfunc;
    })();
    ρσ_d["e"] = (function() {
        var ρσ_anonfunc = function (expr, alt) {
            return (expr === undefined || expr === null) ? alt : expr;
        };
        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
            __argnames__ : {value: ["expr", "alt"]}
        });
        return ρσ_anonfunc;
    })();
    return ρσ_d;
}).call(this);
function ρσ_mixin() {
    var seen, resolved_props, p, target, props, name;
    seen = Object.create(null);
    seen.__argnames__ = seen.__handles_kwarg_interpolation__ = seen.__init__ = seen.__annotations__ = seen.__doc__ = seen.__bind_methods__ = seen.__bases__ = seen.constructor = seen.__class__ = true;
    resolved_props = {};
    p = target = arguments[0].prototype;
    while (p && p !== Object.prototype) {
        props = Object.getOwnPropertyNames(p);
        for (var i = 0; i < props.length; i++) {
            seen[ρσ_bound_index(props[(typeof i === "number" && i < 0) ? props.length + i : i], seen)] = true;
        }
        p = Object.getPrototypeOf(p);
    }
    for (var c = 1; c < arguments.length; c++) {
        p = arguments[(typeof c === "number" && c < 0) ? arguments.length + c : c].prototype;
        while (p && p !== Object.prototype) {
            props = Object.getOwnPropertyNames(p);
            for (var i = 0; i < props.length; i++) {
                name = props[(typeof i === "number" && i < 0) ? props.length + i : i];
                if (seen[(typeof name === "number" && name < 0) ? seen.length + name : name]) {
                    continue;
                }
                seen[(typeof name === "number" && name < 0) ? seen.length + name : name] = true;
                resolved_props[(typeof name === "number" && name < 0) ? resolved_props.length + name : name] = Object.getOwnPropertyDescriptor(p, name);
            }
            p = Object.getPrototypeOf(p);
        }
    }
    Object.defineProperties(target, resolved_props);
};

function ρσ_instanceof() {
    var obj, bases, q, cls, p;
    obj = arguments[0];
    bases = "";
    if (obj && obj.constructor && obj.constructor.prototype) {
        bases = obj.constructor.prototype.__bases__ || "";
    }
    for (var i = 1; i < arguments.length; i++) {
        q = arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i];
        if (obj instanceof q) {
            return true;
        }
        if ((q === Array || q === ρσ_list_constructor) && Array.isArray(obj)) {
            return true;
        }
        if (q === ρσ_str && (typeof obj === "string" || obj instanceof String)) {
            return true;
        }
        if (bases.length > 1) {
            for (var c = 1; c < bases.length; c++) {
                cls = bases[(typeof c === "number" && c < 0) ? bases.length + c : c];
                while (cls) {
                    if (q === cls) {
                        return true;
                    }
                    p = Object.getPrototypeOf(cls.prototype);
                    if (!p) {
                        break;
                    }
                    cls = p.constructor;
                }
            }
        }
    }
    return false;
};
function sum(iterable, start) {
    var ans, iterator, r;
    if (Array.isArray(iterable)) {
        return iterable.reduce((function() {
            var ρσ_anonfunc = function (prev, cur) {
                return prev + cur;
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["prev", "cur"]}
            });
            return ρσ_anonfunc;
        })(), start || 0);
    }
    ans = start || 0;
    iterator = iter(iterable);
    r = iterator.next();
    while (!r.done) {
        ans += r.value;
        r = iterator.next();
    }
    return ans;
};
if (!sum.__argnames__) Object.defineProperties(sum, {
    __argnames__ : {value: ["iterable", "start"]}
});

function map() {
    var iterators, func, args, ans;
    iterators = new Array(arguments.length - 1);
    func = arguments[0];
    args = new Array(arguments.length - 1);
    for (var i = 1; i < arguments.length; i++) {
        iterators[ρσ_bound_index(i - 1, iterators)] = iter(arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i]);
    }
    ans = {'_func':func, '_iterators':iterators, '_args':args};
    ans[ρσ_iterator_symbol] = function () {
        return this;
    };
    ans["next"] = function () {
        var r;
        for (var i = 0; i < this._iterators.length; i++) {
            r = (ρσ_expr_temp = this._iterators)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i].next();
            if (r.done) {
                return {'done':true};
            }
            (ρσ_expr_temp = this._args)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] = r.value;
        }
        return {'done':false, 'value':this._func.apply(undefined, this._args)};
    };
    return ans;
};

function filter(func_or_none, iterable) {
    var func, ans;
    func = (func_or_none === null) ? ρσ_bool : func_or_none;
    ans = {'_func':func, '_iterator':ρσ_iter(iterable)};
    ans[ρσ_iterator_symbol] = function () {
        return this;
    };
    ans["next"] = function () {
        var r;
        r = this._iterator.next();
        while (!r.done) {
            if (this._func(r.value)) {
                return r;
            }
            r = this._iterator.next();
        }
        return {'done':true};
    };
    return ans;
};
if (!filter.__argnames__) Object.defineProperties(filter, {
    __argnames__ : {value: ["func_or_none", "iterable"]}
});

function zip() {
    var iterators, ans;
    iterators = new Array(arguments.length);
    for (var i = 0; i < arguments.length; i++) {
        iterators[(typeof i === "number" && i < 0) ? iterators.length + i : i] = iter(arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i]);
    }
    ans = {'_iterators':iterators};
    ans[ρσ_iterator_symbol] = function () {
        return this;
    };
    ans["next"] = function () {
        var args, r;
        args = new Array(this._iterators.length);
        for (var i = 0; i < this._iterators.length; i++) {
            r = (ρσ_expr_temp = this._iterators)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i].next();
            if (r.done) {
                return {'done':true};
            }
            args[(typeof i === "number" && i < 0) ? args.length + i : i] = r.value;
        }
        return {'done':false, 'value':args};
    };
    return ans;
};

function any(iterable) {
    var i;
    var ρσ_Iter0 = ρσ_Iterable(iterable);
    for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
        i = ρσ_Iter0[ρσ_Index0];
        if (i) {
            return true;
        }
    }
    return false;
};
if (!any.__argnames__) Object.defineProperties(any, {
    __argnames__ : {value: ["iterable"]}
});

function all(iterable) {
    var i;
    var ρσ_Iter1 = ρσ_Iterable(iterable);
    for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
        i = ρσ_Iter1[ρσ_Index1];
        if (!i) {
            return false;
        }
    }
    return true;
};
if (!all.__argnames__) Object.defineProperties(all, {
    __argnames__ : {value: ["iterable"]}
});
var decimal_sep, define_str_func, ρσ_unpack, ρσ_orig_split, ρσ_orig_replace;
decimal_sep = 1.1.toLocaleString()[1];
function ρσ_repr_js_builtin(x, as_array) {
    var ans, b, keys, key;
    ans = [];
    b = "{}";
    if (as_array) {
        b = "[]";
        for (var i = 0; i < x.length; i++) {
            ans.push(ρσ_repr(x[(typeof i === "number" && i < 0) ? x.length + i : i]));
        }
    } else {
        keys = Object.keys(x);
        for (var k = 0; k < keys.length; k++) {
            key = keys[(typeof k === "number" && k < 0) ? keys.length + k : k];
            ans.push(JSON.stringify(key) + ":" + ρσ_repr(x[(typeof key === "number" && key < 0) ? x.length + key : key]));
        }
    }
    return b[0] + ans.join(", ") + b[1];
};
if (!ρσ_repr_js_builtin.__argnames__) Object.defineProperties(ρσ_repr_js_builtin, {
    __argnames__ : {value: ["x", "as_array"]}
});

function ρσ_html_element_to_string(elem) {
    var attrs, val, attr, ans;
    attrs = [];
    var ρσ_Iter0 = ρσ_Iterable(elem.attributes);
    for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
        attr = ρσ_Iter0[ρσ_Index0];
        if (attr.specified) {
            val = attr.value;
            if (val.length > 10) {
                val = val.slice(0, 15) + "...";
            }
            val = JSON.stringify(val);
            attrs.push("" + ρσ_str.format("{}", attr.name) + "=" + ρσ_str.format("{}", val) + "");
        }
    }
    attrs = (attrs.length) ? " " + attrs.join(" ") : "";
    ans = "<" + ρσ_str.format("{}", elem.tagName) + "" + ρσ_str.format("{}", attrs) + ">";
    return ans;
};
if (!ρσ_html_element_to_string.__argnames__) Object.defineProperties(ρσ_html_element_to_string, {
    __argnames__ : {value: ["elem"]}
});

function ρσ_repr(x) {
    var ans, name;
    if (x === null) {
        return "None";
    }
    if (x === undefined) {
        return "undefined";
    }
    ans = x;
    if (typeof x.__repr__ === "function") {
        ans = x.__repr__();
    } else if (x === true || x === false) {
        ans = (x) ? "True" : "False";
    } else if (Array.isArray(x)) {
        ans = ρσ_repr_js_builtin(x, true);
    } else if (typeof x === "function") {
        ans = x.toString();
    } else if (typeof x === "object" && !x.toString) {
        ans = ρσ_repr_js_builtin(x);
    } else {
        name = Object.prototype.toString.call(x).slice(8, -1);
        if (ρσ_not_equals("Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".indexOf(name), -1)) {
            return name + "([" + x.map((function() {
                var ρσ_anonfunc = function (i) {
                    return str.format("0x{:02x}", i);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["i"]}
                });
                return ρσ_anonfunc;
            })()).join(", ") + "])";
        }
        if (typeof HTMLElement !== "undefined" && x instanceof HTMLElement) {
            ans = ρσ_html_element_to_string(x);
        } else {
            ans = (typeof x.toString === "function") ? x.toString() : x;
        }
        if (ans === "[object Object]") {
            return ρσ_repr_js_builtin(x);
        }
        try {
            ans = JSON.stringify(x);
        } catch (ρσ_Exception) {
            ρσ_last_exception = ρσ_Exception;
            {
            } 
        }
    }
    return ans + "";
};
if (!ρσ_repr.__argnames__) Object.defineProperties(ρσ_repr, {
    __argnames__ : {value: ["x"]}
});

function ρσ_str(x) {
    var ans, name;
    if (x === null) {
        return "None";
    }
    if (x === undefined) {
        return "undefined";
    }
    ans = x;
    if (typeof x.__str__ === "function") {
        ans = x.__str__();
    } else if (typeof x.__repr__ === "function") {
        ans = x.__repr__();
    } else if (x === true || x === false) {
        ans = (x) ? "True" : "False";
    } else if (Array.isArray(x)) {
        ans = ρσ_repr_js_builtin(x, true);
    } else if (typeof x.toString === "function") {
        name = Object.prototype.toString.call(x).slice(8, -1);
        if (ρσ_not_equals("Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".indexOf(name), -1)) {
            return name + "([" + x.map((function() {
                var ρσ_anonfunc = function (i) {
                    return str.format("0x{:02x}", i);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["i"]}
                });
                return ρσ_anonfunc;
            })()).join(", ") + "])";
        }
        if (typeof HTMLElement !== "undefined" && x instanceof HTMLElement) {
            ans = ρσ_html_element_to_string(x);
        } else {
            ans = x.toString();
        }
        if (ans === "[object Object]") {
            ans = ρσ_repr_js_builtin(x);
        }
    } else if (typeof x === "object" && !x.toString) {
        ans = ρσ_repr_js_builtin(x);
    }
    return ans + "";
};
if (!ρσ_str.__argnames__) Object.defineProperties(ρσ_str, {
    __argnames__ : {value: ["x"]}
});

define_str_func = (function() {
    var ρσ_anonfunc = function (name, func) {
        var f;
        (ρσ_expr_temp = ρσ_str.prototype)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name] = func;
        ρσ_str[(typeof name === "number" && name < 0) ? ρσ_str.length + name : name] = f = func.call.bind(func);
        if (func.__argnames__) {
            Object.defineProperty(f, "__argnames__", (function(){
                var ρσ_d = {};
                ρσ_d["value"] = ['string'].concat(func.__argnames__);
                return ρσ_d;
            }).call(this));
        }
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["name", "func"]}
    });
    return ρσ_anonfunc;
})();
ρσ_unpack = [String.prototype.split.call.bind(String.prototype.split), String.prototype.replace.call.bind(String.prototype.replace)];
ρσ_orig_split = ρσ_unpack[0];
ρσ_orig_replace = ρσ_unpack[1];
define_str_func("format", function () {
    var template, args, kwargs, explicit, implicit, idx, split, ans, pos, in_brace, markup, ch;
    template = this;
    if (template === undefined) {
        throw new TypeError("Template is required");
    }
    args = Array.prototype.slice.call(arguments);
    kwargs = {};
    if (args[args.length-1] && args[args.length-1][ρσ_kwargs_symbol] !== undefined) {
        kwargs = args[args.length-1];
        args = args.slice(0, -1);
    }
    explicit = implicit = false;
    idx = 0;
    split = ρσ_orig_split;
    if (ρσ_str.format._template_resolve_pat === undefined) {
        ρσ_str.format._template_resolve_pat = /[.\[]/;
    }
    function resolve(arg, object) {
        var ρσ_unpack, first, key, rest, ans;
        if (!arg) {
            return object;
        }
        ρσ_unpack = [arg[0], arg.slice(1)];
        first = ρσ_unpack[0];
        arg = ρσ_unpack[1];
        key = split(arg, ρσ_str.format._template_resolve_pat, 1)[0];
        rest = arg.slice(key.length);
        ans = (first === "[") ? object[ρσ_bound_index(key.slice(0, -1), object)] : getattr(object, key);
        if (ans === undefined) {
            throw new KeyError((first === "[") ? key.slice(0, -1) : key);
        }
        return resolve(rest, ans);
    };
    if (!resolve.__argnames__) Object.defineProperties(resolve, {
        __argnames__ : {value: ["arg", "object"]}
    });

    function resolve_format_spec(format_spec) {
        if (ρσ_str.format._template_resolve_fs_pat === undefined) {
            ρσ_str.format._template_resolve_fs_pat = /[{]([a-zA-Z0-9_]+)[}]/g;
        }
        return format_spec.replace(ρσ_str.format._template_resolve_fs_pat, (function() {
            var ρσ_anonfunc = function (match, key) {
                if (!Object.prototype.hasOwnProperty.call(kwargs, key)) {
                    return "";
                }
                return "" + kwargs[(typeof key === "number" && key < 0) ? kwargs.length + key : key];
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["match", "key"]}
            });
            return ρσ_anonfunc;
        })());
    };
    if (!resolve_format_spec.__argnames__) Object.defineProperties(resolve_format_spec, {
        __argnames__ : {value: ["format_spec"]}
    });

    function set_comma(ans, comma) {
        var sep;
        if (comma !== ",") {
            sep = 1234;
            sep = sep.toLocaleString(undefined, {useGrouping: true})[1];
            ans = str.replace(ans, sep, comma);
        }
        return ans;
    };
    if (!set_comma.__argnames__) Object.defineProperties(set_comma, {
        __argnames__ : {value: ["ans", "comma"]}
    });

    function safe_comma(value, comma) {
        try {
            return set_comma(value.toLocaleString(undefined, {useGrouping: true}), comma);
        } catch (ρσ_Exception) {
            ρσ_last_exception = ρσ_Exception;
            {
                return value.toString(10);
            } 
        }
    };
    if (!safe_comma.__argnames__) Object.defineProperties(safe_comma, {
        __argnames__ : {value: ["value", "comma"]}
    });

    function safe_fixed(value, precision, comma) {
        if (!comma) {
            return value.toFixed(precision);
        }
        try {
            return set_comma(value.toLocaleString(undefined, {useGrouping: true, minimumFractionDigits: precision, maximumFractionDigits: precision}), comma);
        } catch (ρσ_Exception) {
            ρσ_last_exception = ρσ_Exception;
            {
                return value.toFixed(precision);
            } 
        }
    };
    if (!safe_fixed.__argnames__) Object.defineProperties(safe_fixed, {
        __argnames__ : {value: ["value", "precision", "comma"]}
    });

    function apply_formatting(value, format_spec) {
        var ρσ_unpack, fill, align, sign, fhash, zeropad, width, comma, precision, ftype, is_numeric, is_int, lftype, code, prec, exp, nval, is_positive, left, right;
        if (format_spec.indexOf("{") !== -1) {
            format_spec = resolve_format_spec(format_spec);
        }
        if (ρσ_str.format._template_format_pat === undefined) {
            ρσ_str.format._template_format_pat = /([^{}](?=[<>=^]))?([<>=^])?([-+\x20])?(\#)?(0)?(\d+)?([,_])?(?:\.(\d+))?([bcdeEfFgGnosxX%])?/;
        }
        try {
            ρσ_unpack = format_spec.match(ρσ_str.format._template_format_pat).slice(1);
ρσ_unpack = ρσ_unpack_asarray(9, ρσ_unpack);
            fill = ρσ_unpack[0];
            align = ρσ_unpack[1];
            sign = ρσ_unpack[2];
            fhash = ρσ_unpack[3];
            zeropad = ρσ_unpack[4];
            width = ρσ_unpack[5];
            comma = ρσ_unpack[6];
            precision = ρσ_unpack[7];
            ftype = ρσ_unpack[8];
        } catch (ρσ_Exception) {
            ρσ_last_exception = ρσ_Exception;
            if (ρσ_Exception instanceof TypeError) {
                return value;
            } else {
                throw ρσ_Exception;
            }
        }
        if (zeropad) {
            fill = fill || "0";
            align = align || "=";
        } else {
            fill = fill || " ";
            align = align || ">";
        }
        is_numeric = Number(value) === value;
        is_int = is_numeric && value % 1 === 0;
        precision = parseInt(precision, 10);
        lftype = (ftype || "").toLowerCase();
        if (ftype === "n") {
            is_numeric = true;
            if (is_int) {
                if (comma) {
                    throw new ValueError("Cannot specify ',' with 'n'");
                }
                value = parseInt(value, 10).toLocaleString();
            } else {
                value = parseFloat(value).toLocaleString();
            }
        } else if (['b', 'c', 'd', 'o', 'x'].indexOf(lftype) !== -1) {
            value = parseInt(value, 10);
            is_numeric = true;
            if (!isNaN(value)) {
                if (ftype === "b") {
                    value = (value >>> 0).toString(2);
                    if (fhash) {
                        value = "0b" + value;
                    }
                } else if (ftype === "c") {
                    if (value > 65535) {
                        code = value - 65536;
                        value = String.fromCharCode(55296 + (code >> 10), 56320 + (code & 1023));
                    } else {
                        value = String.fromCharCode(value);
                    }
                } else if (ftype === "d") {
                    if (comma) {
                        value = safe_comma(value, comma);
                    } else {
                        value = value.toString(10);
                    }
                } else if (ftype === "o") {
                    value = value.toString(8);
                    if (fhash) {
                        value = "0o" + value;
                    }
                } else if (lftype === "x") {
                    value = value.toString(16);
                    value = (ftype === "x") ? value.toLowerCase() : value.toUpperCase();
                    if (fhash) {
                        value = "0x" + value;
                    }
                }
            }
        } else if (['e','f','g','%'].indexOf(lftype) !== -1) {
            is_numeric = true;
            value = parseFloat(value);
            prec = (isNaN(precision)) ? 6 : precision;
            if (lftype === "e") {
                value = value.toExponential(prec);
                value = (ftype === "E") ? value.toUpperCase() : value.toLowerCase();
            } else if (lftype === "f") {
                value = safe_fixed(value, prec, comma);
                value = (ftype === "F") ? value.toUpperCase() : value.toLowerCase();
            } else if (lftype === "%") {
                value *= 100;
                value = safe_fixed(value, prec, comma) + "%";
            } else if (lftype === "g") {
                prec = max(1, prec);
                exp = parseInt(split(value.toExponential(prec - 1).toLowerCase(), "e")[1], 10);
                if (-4 <= exp && exp < prec) {
                    value = safe_fixed(value, prec - 1 - exp, comma);
                } else {
                    value = value.toExponential(prec - 1);
                }
                value = value.replace(/0+$/g, "");
                if (value[value.length-1] === decimal_sep) {
                    value = value.slice(0, -1);
                }
                if (ftype === "G") {
                    value = value.toUpperCase();
                }
            }
        } else {
            if (comma) {
                value = parseInt(value, 10);
                if (isNaN(value)) {
                    throw new ValueError("Must use numbers with , or _");
                }
                value = safe_comma(value, comma);
            }
            value += "";
            if (!isNaN(precision)) {
                value = value.slice(0, precision);
            }
        }
        value += "";
        if (is_numeric && sign) {
            nval = Number(value);
            is_positive = !isNaN(nval) && nval >= 0;
            if (is_positive && (sign === " " || sign === "+")) {
                value = sign + value;
            }
        }
        function repeat(char, num) {
            return (new Array(num+1)).join(char);
        };
        if (!repeat.__argnames__) Object.defineProperties(repeat, {
            __argnames__ : {value: ["char", "num"]}
        });

        if (is_numeric && width && width[0] === "0") {
            width = width.slice(1);
            ρσ_unpack = ["0", "="];
            fill = ρσ_unpack[0];
            align = ρσ_unpack[1];
        }
        width = parseInt(width || "-1", 10);
        if (isNaN(width)) {
            throw new ValueError("Invalid width specification: " + width);
        }
        if (fill && value.length < width) {
            if (align === "<") {
                value = value + repeat(fill, width - value.length);
            } else if (align === ">") {
                value = repeat(fill, width - value.length) + value;
            } else if (align === "^") {
                left = Math.floor((width - value.length) / 2);
                right = width - left - value.length;
                value = repeat(fill, left) + value + repeat(fill, right);
            } else if (align === "=") {
                if (ρσ_in(value[0], "+- ")) {
                    value = value[0] + repeat(fill, width - value.length) + value.slice(1);
                } else {
                    value = repeat(fill, width - value.length) + value;
                }
            } else {
                throw new ValueError("Unrecognized alignment: " + align);
            }
        }
        return value;
    };
    if (!apply_formatting.__argnames__) Object.defineProperties(apply_formatting, {
        __argnames__ : {value: ["value", "format_spec"]}
    });

    function parse_markup(markup) {
        var key, transformer, format_spec, pos, state, ch;
        key = transformer = format_spec = "";
        pos = 0;
        state = 0;
        while (pos < markup.length) {
            ch = markup[(typeof pos === "number" && pos < 0) ? markup.length + pos : pos];
            if (state === 0) {
                if (ch === "!") {
                    state = 1;
                } else if (ch === ":") {
                    state = 2;
                } else {
                    key += ch;
                }
            } else if (state === 1) {
                if (ch === ":") {
                    state = 2;
                } else {
                    transformer += ch;
                }
            } else {
                format_spec += ch;
            }
            pos += 1;
        }
        return [key, transformer, format_spec];
    };
    if (!parse_markup.__argnames__) Object.defineProperties(parse_markup, {
        __argnames__ : {value: ["markup"]}
    });

    function render_markup(markup) {
        var ρσ_unpack, key, transformer, format_spec, lkey, nvalue, object, ans;
        ρσ_unpack = parse_markup(markup);
ρσ_unpack = ρσ_unpack_asarray(3, ρσ_unpack);
        key = ρσ_unpack[0];
        transformer = ρσ_unpack[1];
        format_spec = ρσ_unpack[2];
        if (transformer && ['a', 'r', 's'].indexOf(transformer) === -1) {
            throw new ValueError("Unknown conversion specifier: " + transformer);
        }
        lkey = key.length && split(key, /[.\[]/, 1)[0];
        if (lkey) {
            explicit = true;
            if (implicit) {
                throw new ValueError("cannot switch from automatic field numbering to manual field specification");
            }
            nvalue = parseInt(lkey);
            object = (isNaN(nvalue)) ? kwargs[(typeof lkey === "number" && lkey < 0) ? kwargs.length + lkey : lkey] : args[(typeof nvalue === "number" && nvalue < 0) ? args.length + nvalue : nvalue];
            if (object === undefined) {
                if (isNaN(nvalue)) {
                    throw new KeyError(lkey);
                }
                throw new IndexError(lkey);
            }
            object = resolve(key.slice(lkey.length), object);
        } else {
            implicit = true;
            if (explicit) {
                throw new ValueError("cannot switch from manual field specification to automatic field numbering");
            }
            if (idx >= args.length) {
                throw new IndexError("Not enough arguments to match template: " + template);
            }
            object = args[(typeof idx === "number" && idx < 0) ? args.length + idx : idx];
            idx += 1;
        }
        if (typeof object === "function") {
            object = object();
        }
        ans = "" + object;
        if (format_spec) {
            ans = apply_formatting(ans, format_spec);
        }
        return ans;
    };
    if (!render_markup.__argnames__) Object.defineProperties(render_markup, {
        __argnames__ : {value: ["markup"]}
    });

    ans = "";
    pos = 0;
    in_brace = 0;
    markup = "";
    while (pos < template.length) {
        ch = template[(typeof pos === "number" && pos < 0) ? template.length + pos : pos];
        if (in_brace) {
            if (ch === "{") {
                in_brace += 1;
                markup += "{";
            } else if (ch === "}") {
                in_brace -= 1;
                if (in_brace > 0) {
                    markup += "}";
                } else {
                    ans += render_markup(markup);
                }
            } else {
                markup += ch;
            }
        } else {
            if (ch === "{") {
                if (template[ρσ_bound_index(pos + 1, template)] === "{") {
                    pos += 1;
                    ans += "{";
                } else {
                    in_brace = 1;
                    markup = "";
                }
            } else {
                ans += ch;
                if (ch === "}" && template[ρσ_bound_index(pos + 1, template)] === "}") {
                    pos += 1;
                }
            }
        }
        pos += 1;
    }
    if (in_brace) {
        throw new ValueError("expected '}' before end of string");
    }
    return ans;
});
define_str_func("capitalize", function () {
    var string;
    string = this;
    if (string) {
        string = string[0].toUpperCase() + string.slice(1).toLowerCase();
    }
    return string;
});
define_str_func("center", (function() {
    var ρσ_anonfunc = function (width, fill) {
        var left, right;
        left = Math.floor((width - this.length) / 2);
        right = width - left - this.length;
        fill = fill || " ";
        return new Array(left+1).join(fill) + this + new Array(right+1).join(fill);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["width", "fill"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("count", (function() {
    var ρσ_anonfunc = function (needle, start, end) {
        var string, ρσ_unpack, pos, step, ans;
        string = this;
        start = start || 0;
        end = end || string.length;
        if (start < 0 || end < 0) {
            string = string.slice(start, end);
            ρσ_unpack = [0, string.length];
            start = ρσ_unpack[0];
            end = ρσ_unpack[1];
        }
        pos = start;
        step = needle.length;
        if (!step) {
            return 0;
        }
        ans = 0;
        while (pos !== -1) {
            pos = string.indexOf(needle, pos);
            if (pos !== -1) {
                ans += 1;
                pos += step;
            }
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["needle", "start", "end"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("endswith", (function() {
    var ρσ_anonfunc = function (suffixes, start, end) {
        var string, q;
        string = this;
        start = start || 0;
        if (typeof suffixes === "string") {
            suffixes = [suffixes];
        }
        if (end !== undefined) {
            string = string.slice(0, end);
        }
        for (var i = 0; i < suffixes.length; i++) {
            q = suffixes[(typeof i === "number" && i < 0) ? suffixes.length + i : i];
            if (string.indexOf(q, Math.max(start, string.length - q.length)) !== -1) {
                return true;
            }
        }
        return false;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["suffixes", "start", "end"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("startswith", (function() {
    var ρσ_anonfunc = function (prefixes, start, end) {
        var prefix;
        start = start || 0;
        if (typeof prefixes === "string") {
            prefixes = [prefixes];
        }
        for (var i = 0; i < prefixes.length; i++) {
            prefix = prefixes[(typeof i === "number" && i < 0) ? prefixes.length + i : i];
            end = (end === undefined) ? this.length : end;
            if (end - start >= prefix.length && prefix === this.slice(start, start + prefix.length)) {
                return true;
            }
        }
        return false;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["prefixes", "start", "end"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("find", (function() {
    var ρσ_anonfunc = function (needle, start, end) {
        var ans;
        while (start < 0) {
            start += this.length;
        }
        ans = this.indexOf(needle, start);
        if (end !== undefined && ans !== -1) {
            while (end < 0) {
                end += this.length;
            }
            if (ans >= end - needle.length) {
                return -1;
            }
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["needle", "start", "end"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("rfind", (function() {
    var ρσ_anonfunc = function (needle, start, end) {
        var ans;
        while (end < 0) {
            end += this.length;
        }
        ans = this.lastIndexOf(needle, end - 1);
        if (start !== undefined && ans !== -1) {
            while (start < 0) {
                start += this.length;
            }
            if (ans < start) {
                return -1;
            }
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["needle", "start", "end"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("index", (function() {
    var ρσ_anonfunc = function (needle, start, end) {
        var ans;
        ans = ρσ_str.prototype.find.apply(this, arguments);
        if (ans === -1) {
            throw new ValueError("substring not found");
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["needle", "start", "end"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("rindex", (function() {
    var ρσ_anonfunc = function (needle, start, end) {
        var ans;
        ans = ρσ_str.prototype.rfind.apply(this, arguments);
        if (ans === -1) {
            throw new ValueError("substring not found");
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["needle", "start", "end"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("islower", function () {
    return this.length > 0 && this.toLowerCase() === this.toString();
});
define_str_func("isupper", function () {
    return this.length > 0 && this.toUpperCase() === this.toString();
});
define_str_func("isspace", function () {
    return this.length > 0 && /^\s+$/.test(this);
});
define_str_func("join", (function() {
    var ρσ_anonfunc = function (iterable) {
        var ans, r;
        if (Array.isArray(iterable)) {
            return iterable.join(this);
        }
        ans = "";
        r = iterable.next();
        while (!r.done) {
            if (ans) {
                ans += this;
            }
            ans += r.value;
            r = iterable.next();
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["iterable"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("ljust", (function() {
    var ρσ_anonfunc = function (width, fill) {
        var string;
        string = this;
        if (width > string.length) {
            fill = fill || " ";
            string += new Array(width - string.length + 1).join(fill);
        }
        return string;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["width", "fill"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("rjust", (function() {
    var ρσ_anonfunc = function (width, fill) {
        var string;
        string = this;
        if (width > string.length) {
            fill = fill || " ";
            string = new Array(width - string.length + 1).join(fill) + string;
        }
        return string;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["width", "fill"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("lower", function () {
    return this.toLowerCase();
});
define_str_func("upper", function () {
    return this.toUpperCase();
});
define_str_func("lstrip", (function() {
    var ρσ_anonfunc = function (chars) {
        var string, pos;
        string = this;
        pos = 0;
        chars = chars || ρσ_str.whitespace;
        while (chars.indexOf(string[(typeof pos === "number" && pos < 0) ? string.length + pos : pos]) !== -1) {
            pos += 1;
        }
        if (pos) {
            string = string.slice(pos);
        }
        return string;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["chars"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("rstrip", (function() {
    var ρσ_anonfunc = function (chars) {
        var string, pos;
        string = this;
        pos = string.length - 1;
        chars = chars || ρσ_str.whitespace;
        while (chars.indexOf(string[(typeof pos === "number" && pos < 0) ? string.length + pos : pos]) !== -1) {
            pos -= 1;
        }
        if (pos < string.length - 1) {
            string = string.slice(0, pos + 1);
        }
        return string;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["chars"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("strip", (function() {
    var ρσ_anonfunc = function (chars) {
        return ρσ_str.prototype.lstrip.call(ρσ_str.prototype.rstrip.call(this, chars), chars);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["chars"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("partition", (function() {
    var ρσ_anonfunc = function (sep) {
        var idx;
        idx = this.indexOf(sep);
        if (idx === -1) {
            return [this, "", ""];
        }
        return [this.slice(0, idx), sep, this.slice(idx + sep.length)];
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["sep"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("rpartition", (function() {
    var ρσ_anonfunc = function (sep) {
        var idx;
        idx = this.lastIndexOf(sep);
        if (idx === -1) {
            return ["", "", this];
        }
        return [this.slice(0, idx), sep, this.slice(idx + sep.length)];
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["sep"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("replace", (function() {
    var ρσ_anonfunc = function (old, repl, count) {
        var string, pos, idx;
        string = this;
        if (count === 1) {
            return ρσ_orig_replace(string, old, repl);
        }
        if (count < 1) {
            return string;
        }
        count = count || Number.MAX_VALUE;
        pos = 0;
        while (count > 0) {
            count -= 1;
            idx = string.indexOf(old, pos);
            if (idx === -1) {
                break;
            }
            pos = idx + repl.length;
            string = string.slice(0, idx) + repl + string.slice(idx + old.length);
        }
        return string;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["old", "repl", "count"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("split", (function() {
    var ρσ_anonfunc = function (sep, maxsplit) {
        var split, ans, extra, parts;
        if (maxsplit === 0) {
            return ρσ_list_decorate([ this ]);
        }
        split = ρσ_orig_split;
        if (sep === undefined || sep === null) {
            if (maxsplit > 0) {
                ans = split(this, /(\s+)/);
                extra = "";
                parts = [];
                for (var i = 0; i < ans.length; i++) {
                    if (parts.length >= maxsplit + 1) {
                        extra += ans[(typeof i === "number" && i < 0) ? ans.length + i : i];
                    } else if (i % 2 === 0) {
                        parts.push(ans[(typeof i === "number" && i < 0) ? ans.length + i : i]);
                    }
                }
                parts[parts.length-1] += extra;
                ans = parts;
            } else {
                ans = split(this, /\s+/);
            }
        } else {
            if (sep === "") {
                throw new ValueError("empty separator");
            }
            ans = split(this, sep);
            if (maxsplit > 0 && ans.length > maxsplit) {
                extra = ans.slice(maxsplit).join(sep);
                ans = ans.slice(0, maxsplit);
                ans.push(extra);
            }
        }
        return ρσ_list_decorate(ans);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["sep", "maxsplit"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("rsplit", (function() {
    var ρσ_anonfunc = function (sep, maxsplit) {
        var split, ans, is_space, pos, current, spc, ch, end, idx;
        if (!maxsplit) {
            return ρσ_str.prototype.split.call(this, sep);
        }
        split = ρσ_orig_split;
        if (sep === undefined || sep === null) {
            if (maxsplit > 0) {
                ans = [];
                is_space = /\s/;
                pos = this.length - 1;
                current = "";
                while (pos > -1 && maxsplit > 0) {
                    spc = false;
                    ch = (ρσ_expr_temp = this)[(typeof pos === "number" && pos < 0) ? ρσ_expr_temp.length + pos : pos];
                    while (pos > -1 && is_space.test(ch)) {
                        spc = true;
                        ch = this[--pos];
                    }
                    if (spc) {
                        if (current) {
                            ans.push(current);
                            maxsplit -= 1;
                        }
                        current = ch;
                    } else {
                        current += ch;
                    }
                    pos -= 1;
                }
                ans.push(this.slice(0, pos + 1) + current);
                ans.reverse();
            } else {
                ans = split(this, /\s+/);
            }
        } else {
            if (sep === "") {
                throw new ValueError("empty separator");
            }
            ans = [];
            pos = end = this.length;
            while (pos > -1 && maxsplit > 0) {
                maxsplit -= 1;
                idx = this.lastIndexOf(sep, pos);
                if (idx === -1) {
                    break;
                }
                ans.push(this.slice(idx + sep.length, end));
                pos = idx - 1;
                end = idx;
            }
            ans.push(this.slice(0, end));
            ans.reverse();
        }
        return ρσ_list_decorate(ans);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["sep", "maxsplit"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("splitlines", (function() {
    var ρσ_anonfunc = function (keepends) {
        var split, parts, ans;
        split = ρσ_orig_split;
        if (keepends) {
            parts = split(this, /((?:\r?\n)|\r)/);
            ans = [];
            for (var i = 0; i < parts.length; i++) {
                if (i % 2 === 0) {
                    ans.push(parts[(typeof i === "number" && i < 0) ? parts.length + i : i]);
                } else {
                    ans[ans.length-1] += parts[(typeof i === "number" && i < 0) ? parts.length + i : i];
                }
            }
        } else {
            ans = split(this, /(?:\r?\n)|\r/);
        }
        return ρσ_list_decorate(ans);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["keepends"]}
    });
    return ρσ_anonfunc;
})());
define_str_func("swapcase", function () {
    var ans, a, b;
    ans = new Array(this.length);
    for (var i = 0; i < ans.length; i++) {
        a = (ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
        b = a.toLowerCase();
        if (a === b) {
            b = a.toUpperCase();
        }
        ans[(typeof i === "number" && i < 0) ? ans.length + i : i] = b;
    }
    return ans.join("");
});
define_str_func("zfill", (function() {
    var ρσ_anonfunc = function (width) {
        var string;
        string = this;
        if (width > string.length) {
            string = new Array(width - string.length + 1).join("0") + string;
        }
        return string;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["width"]}
    });
    return ρσ_anonfunc;
})());
ρσ_str.uchrs = (function() {
    var ρσ_anonfunc = function (string, with_positions) {
        return (function(){
            var ρσ_d = {};
            ρσ_d["_string"] = string;
            ρσ_d["_pos"] = 0;
            ρσ_d[ρσ_iterator_symbol] = function () {
                return this;
            };
            ρσ_d["next"] = function () {
                var length, pos, value, ans, extra;
                length = this._string.length;
                if (this._pos >= length) {
                    return (function(){
                        var ρσ_d = {};
                        ρσ_d["done"] = true;
                        return ρσ_d;
                    }).call(this);
                }
                pos = this._pos;
                value = this._string.charCodeAt(this._pos++);
                ans = "\ufffd";
                if (55296 <= value && value <= 56319) {
                    if (this._pos < length) {
                        extra = this._string.charCodeAt(this._pos++);
                        if ((extra & 56320) === 56320) {
                            ans = String.fromCharCode(value, extra);
                        }
                    }
                } else if ((value & 56320) !== 56320) {
                    ans = String.fromCharCode(value);
                }
                if (with_positions) {
                    return (function(){
                        var ρσ_d = {};
                        ρσ_d["done"] = false;
                        ρσ_d["value"] = ρσ_list_decorate([ pos, ans ]);
                        return ρσ_d;
                    }).call(this);
                } else {
                    return (function(){
                        var ρσ_d = {};
                        ρσ_d["done"] = false;
                        ρσ_d["value"] = ans;
                        return ρσ_d;
                    }).call(this);
                }
            };
            return ρσ_d;
        }).call(this);
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["string", "with_positions"]}
    });
    return ρσ_anonfunc;
})();
ρσ_str.uslice = (function() {
    var ρσ_anonfunc = function (string, start, end) {
        var items, iterator, r;
        items = [];
        iterator = ρσ_str.uchrs(string);
        r = iterator.next();
        while (!r.done) {
            items.push(r.value);
            r = iterator.next();
        }
        return items.slice(start || 0, (end === undefined) ? items.length : end).join("");
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["string", "start", "end"]}
    });
    return ρσ_anonfunc;
})();
ρσ_str.ulen = (function() {
    var ρσ_anonfunc = function (string) {
        var iterator, r, ans;
        iterator = ρσ_str.uchrs(string);
        r = iterator.next();
        ans = 0;
        while (!r.done) {
            r = iterator.next();
            ans += 1;
        }
        return ans;
    };
    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
        __argnames__ : {value: ["string"]}
    });
    return ρσ_anonfunc;
})();
ρσ_str.ascii_lowercase = "abcdefghijklmnopqrstuvwxyz";
ρσ_str.ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
ρσ_str.ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
ρσ_str.digits = "0123456789";
ρσ_str.punctuation = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
ρσ_str.printable = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\u000b\f";
ρσ_str.whitespace = " \t\n\r\u000b\f";
define_str_func = undefined;
var str = ρσ_str, repr = ρσ_repr;;
    var ρσ_modules = {};
    ρσ_modules.traceback = {};
    ρσ_modules.elementmaker = {};
    ρσ_modules.gettext = {};
    ρσ_modules.pythonize = {};
    ρσ_modules.initialize = {};
    ρσ_modules.ajax = {};
    ρσ_modules.book_list = {};
    ρσ_modules["book_list.globals"] = {};
    ρσ_modules.lru_cache = {};
    ρσ_modules.encodings = {};
    ρσ_modules.uuid = {};
    ρσ_modules.session = {};
    ρσ_modules["book_list.theme"] = {};
    ρσ_modules.utils = {};
    ρσ_modules["book_list.library_data"] = {};
    ρσ_modules.dom = {};
    ρσ_modules.popups = {};
    ρσ_modules.modals = {};
    ρσ_modules.qt = {};
    ρσ_modules.read_book = {};
    ρσ_modules["book_list.constants"] = {};
    ρσ_modules["book_list.router"] = {};
    ρσ_modules["read_book.db"] = {};
    ρσ_modules.aes = {};
    ρσ_modules.iframe_comm = {};
    ρσ_modules["read_book.globals"] = {};
    ρσ_modules["read_book.settings"] = {};
    ρσ_modules["read_book.resources"] = {};
    ρσ_modules["read_book.footnotes"] = {};
    ρσ_modules["read_book.viewport"] = {};
    ρσ_modules["read_book.cfi"] = {};
    ρσ_modules["read_book.extract"] = {};
    ρσ_modules.select = {};
    ρσ_modules["read_book.flow_mode"] = {};
    ρσ_modules["read_book.mathjax"] = {};
    ρσ_modules["read_book.paged_mode"] = {};
    ρσ_modules["read_book.shortcuts"] = {};
    ρσ_modules.complete = {};
    ρσ_modules.widgets = {};
    ρσ_modules["read_book.toc"] = {};
    ρσ_modules["read_book.touch"] = {};
    ρσ_modules["read_book.iframe"] = {};
    ρσ_modules["read_book.content_popup"] = {};
    ρσ_modules["read_book.scrollbar"] = {};
    ρσ_modules["book_list.item_list"] = {};
    ρσ_modules["read_book.goto"] = {};
    ρσ_modules["read_book.open_book"] = {};
    ρσ_modules["book_list.top_bar"] = {};
    ρσ_modules["book_list.ui"] = {};
    ρσ_modules.file_uploads = {};
    ρσ_modules["book_list.add"] = {};
    ρσ_modules["book_list.delete_book"] = {};
    ρσ_modules["book_list.cover_grid"] = {};
    ρσ_modules["book_list.details_list"] = {};
    ρσ_modules.date = {};
    ρσ_modules["book_list.custom_list"] = {};
    ρσ_modules["book_list.prefs"] = {};
    ρσ_modules["book_list.search"] = {};
    ρσ_modules["book_list.views"] = {};
    ρσ_modules["book_list.book_details"] = {};
    ρσ_modules["read_book.prefs"] = {};
    ρσ_modules["read_book.prefs.font_size"] = {};
    ρσ_modules["read_book.prefs.utils"] = {};
    ρσ_modules["read_book.prefs.colors"] = {};
    ρσ_modules["read_book.prefs.fonts"] = {};
    ρσ_modules["read_book.prefs.head_foot"] = {};
    ρσ_modules["read_book.prefs.keyboard"] = {};
    ρσ_modules["read_book.prefs.scrolling"] = {};
    ρσ_modules["read_book.prefs.layout"] = {};
    ρσ_modules["read_book.prefs.misc"] = {};
    ρσ_modules.viewer = {};
    ρσ_modules["viewer.constants"] = {};
    ρσ_modules["read_book.prefs.user_stylesheet"] = {};
    ρσ_modules["read_book.prefs.main"] = {};
    ρσ_modules["read_book.word_actions"] = {};
    ρσ_modules["read_book.overlay"] = {};
    ρσ_modules["read_book.search"] = {};
    ρσ_modules["read_book.timers"] = {};
    ρσ_modules["read_book.view"] = {};

    (function(){
        var __name__ = "traceback";
        function _get_internal_traceback(err) {
            var lines, line, ρσ_unpack, i;
            if (ρσ_instanceof(err, Exception) && err.stack) {
                lines = ρσ_str.splitlines(err.stack);
                var ρσ_Iter0 = ρσ_Iterable(enumerate(lines));
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    ρσ_unpack = ρσ_Iter0[ρσ_Index0];
                    i = ρσ_unpack[0];
                    line = ρσ_unpack[1];
                    line = ρσ_str.strip(line);
                    if (line.startsWith("at new " + err.name) || line.startsWith(err.name + "@")) {
                        return err.__repr__() + "\n" + lines.slice(i + 1).join("\n");
                    }
                }
            }
            return err && err.stack;
        };
        if (!_get_internal_traceback.__argnames__) Object.defineProperties(_get_internal_traceback, {
            __argnames__ : {value: ["err"]}
        });

        function format_exception(exc, limit) {
            var tb, lines, e, l;
            if (!(ρσ_instanceof(exc, Error))) {
                if (exc && exc.toString) {
                    return ρσ_list_decorate([ exc.toString() ]);
                }
                return ρσ_list_decorate([]);
            }
            tb = _get_internal_traceback(exc);
            if (tb) {
                lines = ρσ_str.splitlines(tb);
                e = lines[0];
                lines = (function() {
                    var ρσ_Iter = ρσ_Iterable(lines.slice(1)), ρσ_Result = [], l;
                    for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                        l = ρσ_Iter[ρσ_Index];
                        ρσ_Result.push(l);
                    }
                    ρσ_Result = ρσ_list_constructor(ρσ_Result);
                    return ρσ_Result;
                })();
                if (limit) {
                    lines = (limit > 0) ? lines.slice(0, limit + 1) : lines.slice(limit);
                }
                lines.reverse();
                lines.push(e);
                lines.insert(0, "Traceback (most recent call last):");
                return (function() {
                    var ρσ_Iter = ρσ_Iterable(lines), ρσ_Result = [], l;
                    for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                        l = ρσ_Iter[ρσ_Index];
                        ρσ_Result.push(l + "\n");
                    }
                    ρσ_Result = ρσ_list_constructor(ρσ_Result);
                    return ρσ_Result;
                })();
            }
            return ρσ_list_decorate([ exc.toString() ]);
        };
        if (!format_exception.__argnames__) Object.defineProperties(format_exception, {
            __argnames__ : {value: ["exc", "limit"]}
        });

        function format_exc(limit) {
            return format_exception(ρσ_last_exception, limit).join("");
        };
        if (!format_exc.__argnames__) Object.defineProperties(format_exc, {
            __argnames__ : {value: ["limit"]}
        });

        function print_exc(limit) {
            print(format_exc(limit));
        };
        if (!print_exc.__argnames__) Object.defineProperties(print_exc, {
            __argnames__ : {value: ["limit"]}
        });

        function format_stack(limit) {
            var stack, lines;
            stack = (new Error).stack;
            if (!stack) {
                return ρσ_list_decorate([]);
            }
            lines = str.splitlines(stack).slice(2);
            lines.reverse();
            if (limit) {
                lines = (limit > 0) ? lines.slice(0, limit + 1) : lines.slice(limit);
            }
            return (function() {
                var ρσ_Iter = ρσ_Iterable(lines), ρσ_Result = [], l;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    l = ρσ_Iter[ρσ_Index];
                    ρσ_Result.push(l + "\n");
                }
                ρσ_Result = ρσ_list_constructor(ρσ_Result);
                return ρσ_Result;
            })();
        };
        if (!format_stack.__argnames__) Object.defineProperties(format_stack, {
            __argnames__ : {value: ["limit"]}
        });

        function print_stack(limit) {
            print(format_stack(limit).join(""));
        };
        if (!print_stack.__argnames__) Object.defineProperties(print_stack, {
            __argnames__ : {value: ["limit"]}
        });

        ρσ_modules.traceback._get_internal_traceback = _get_internal_traceback;
        ρσ_modules.traceback.format_exception = format_exception;
        ρσ_modules.traceback.format_exc = format_exc;
        ρσ_modules.traceback.print_exc = print_exc;
        ρσ_modules.traceback.format_stack = format_stack;
        ρσ_modules.traceback.print_stack = print_stack;
    })();

    (function(){
        var __name__ = "elementmaker";
        var html_elements, mathml_elements, svg_elements, html5_tags, E;
        html_elements = (function(){
            var s = ρσ_set();
            s.jsset.add("a");
            s.jsset.add("abbr");
            s.jsset.add("acronym");
            s.jsset.add("address");
            s.jsset.add("area");
            s.jsset.add("article");
            s.jsset.add("aside");
            s.jsset.add("audio");
            s.jsset.add("b");
            s.jsset.add("big");
            s.jsset.add("body");
            s.jsset.add("blockquote");
            s.jsset.add("br");
            s.jsset.add("button");
            s.jsset.add("canvas");
            s.jsset.add("caption");
            s.jsset.add("center");
            s.jsset.add("cite");
            s.jsset.add("code");
            s.jsset.add("col");
            s.jsset.add("colgroup");
            s.jsset.add("command");
            s.jsset.add("datagrid");
            s.jsset.add("datalist");
            s.jsset.add("dd");
            s.jsset.add("del");
            s.jsset.add("details");
            s.jsset.add("dfn");
            s.jsset.add("dialog");
            s.jsset.add("dir");
            s.jsset.add("div");
            s.jsset.add("dl");
            s.jsset.add("dt");
            s.jsset.add("em");
            s.jsset.add("event-source");
            s.jsset.add("fieldset");
            s.jsset.add("figcaption");
            s.jsset.add("figure");
            s.jsset.add("footer");
            s.jsset.add("font");
            s.jsset.add("form");
            s.jsset.add("header");
            s.jsset.add("h1");
            s.jsset.add("h2");
            s.jsset.add("h3");
            s.jsset.add("h4");
            s.jsset.add("h5");
            s.jsset.add("h6");
            s.jsset.add("hr");
            s.jsset.add("head");
            s.jsset.add("i");
            s.jsset.add("iframe");
            s.jsset.add("img");
            s.jsset.add("input");
            s.jsset.add("ins");
            s.jsset.add("keygen");
            s.jsset.add("kbd");
            s.jsset.add("label");
            s.jsset.add("legend");
            s.jsset.add("li");
            s.jsset.add("m");
            s.jsset.add("map");
            s.jsset.add("menu");
            s.jsset.add("meter");
            s.jsset.add("multicol");
            s.jsset.add("nav");
            s.jsset.add("nextid");
            s.jsset.add("ol");
            s.jsset.add("output");
            s.jsset.add("optgroup");
            s.jsset.add("option");
            s.jsset.add("p");
            s.jsset.add("pre");
            s.jsset.add("progress");
            s.jsset.add("q");
            s.jsset.add("s");
            s.jsset.add("samp");
            s.jsset.add("script");
            s.jsset.add("section");
            s.jsset.add("select");
            s.jsset.add("small");
            s.jsset.add("sound");
            s.jsset.add("source");
            s.jsset.add("spacer");
            s.jsset.add("span");
            s.jsset.add("strike");
            s.jsset.add("strong");
            s.jsset.add("style");
            s.jsset.add("sub");
            s.jsset.add("sup");
            s.jsset.add("table");
            s.jsset.add("tbody");
            s.jsset.add("td");
            s.jsset.add("textarea");
            s.jsset.add("time");
            s.jsset.add("tfoot");
            s.jsset.add("th");
            s.jsset.add("thead");
            s.jsset.add("tr");
            s.jsset.add("tt");
            s.jsset.add("u");
            s.jsset.add("ul");
            s.jsset.add("var");
            s.jsset.add("video");
            return s;
        })();
        mathml_elements = (function(){
            var s = ρσ_set();
            s.jsset.add("maction");
            s.jsset.add("math");
            s.jsset.add("merror");
            s.jsset.add("mfrac");
            s.jsset.add("mi");
            s.jsset.add("mmultiscripts");
            s.jsset.add("mn");
            s.jsset.add("mo");
            s.jsset.add("mover");
            s.jsset.add("mpadded");
            s.jsset.add("mphantom");
            s.jsset.add("mprescripts");
            s.jsset.add("mroot");
            s.jsset.add("mrow");
            s.jsset.add("mspace");
            s.jsset.add("msqrt");
            s.jsset.add("mstyle");
            s.jsset.add("msub");
            s.jsset.add("msubsup");
            s.jsset.add("msup");
            s.jsset.add("mtable");
            s.jsset.add("mtd");
            s.jsset.add("mtext");
            s.jsset.add("mtr");
            s.jsset.add("munder");
            s.jsset.add("munderover");
            s.jsset.add("none");
            return s;
        })();
        svg_elements = (function(){
            var s = ρσ_set();
            s.jsset.add("a");
            s.jsset.add("animate");
            s.jsset.add("animateColor");
            s.jsset.add("animateMotion");
            s.jsset.add("animateTransform");
            s.jsset.add("clipPath");
            s.jsset.add("circle");
            s.jsset.add("defs");
            s.jsset.add("desc");
            s.jsset.add("ellipse");
            s.jsset.add("font-face");
            s.jsset.add("font-face-name");
            s.jsset.add("font-face-src");
            s.jsset.add("g");
            s.jsset.add("glyph");
            s.jsset.add("hkern");
            s.jsset.add("linearGradient");
            s.jsset.add("line");
            s.jsset.add("marker");
            s.jsset.add("metadata");
            s.jsset.add("missing-glyph");
            s.jsset.add("mpath");
            s.jsset.add("path");
            s.jsset.add("polygon");
            s.jsset.add("polyline");
            s.jsset.add("radialGradient");
            s.jsset.add("rect");
            s.jsset.add("set");
            s.jsset.add("stop");
            s.jsset.add("svg");
            s.jsset.add("switch");
            s.jsset.add("text");
            s.jsset.add("title");
            s.jsset.add("tspan");
            s.jsset.add("use");
            return s;
        })();
        html5_tags = html_elements.union(mathml_elements).union(svg_elements);
        function _makeelement() {
            var tag = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var kwargs = arguments[arguments.length-1];
            if (kwargs === null || typeof kwargs !== "object" || kwargs [ρσ_kwargs_symbol] !== true) kwargs = {};
            var args = Array.prototype.slice.call(arguments, 1);
            if (kwargs !== null && typeof kwargs === "object" && kwargs [ρσ_kwargs_symbol] === true) args.pop();
            var ans, vattr, val, attr, arg;
            ans = this.createElement(tag);
            var ρσ_Iter0 = ρσ_Iterable(kwargs);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                attr = ρσ_Iter0[ρσ_Index0];
                vattr = str.replace(str.rstrip(attr, "_"), "_", "-");
                val = kwargs[(typeof attr === "number" && attr < 0) ? kwargs.length + attr : attr];
                if (callable(val)) {
                    if (str.startswith(attr, "on")) {
                        attr = attr.slice(2);
                    }
                    ans.addEventListener(attr, val);
                } else if (val === true) {
                    ans.setAttribute(vattr, vattr);
                } else if (typeof val === "string") {
                    ans.setAttribute(vattr, val);
                }
            }
            var ρσ_Iter1 = ρσ_Iterable(args);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                arg = ρσ_Iter1[ρσ_Index1];
                if (typeof arg === "string") {
                    arg = this.createTextNode(arg);
                }
                ans.appendChild(arg);
            }
            return ans;
        };
        if (!_makeelement.__handles_kwarg_interpolation__) Object.defineProperties(_makeelement, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["tag"]}
        });

        function maker_for_document(document) {
            var E;
            E = _makeelement.bind(document);
            Object.defineProperties(E, (function() {
                var ρσ_Iter = ρσ_Iterable(html5_tags), ρσ_Result = {}, tag;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    tag = ρσ_Iter[ρσ_Index];
                    ρσ_Result[tag] = ((function(){
                        var ρσ_d = {};
                        ρσ_d["value"] = _makeelement.bind(document, tag);
                        return ρσ_d;
                    }).call(this));
                }
                return ρσ_Result;
            })());
            return E;
        };
        if (!maker_for_document.__argnames__) Object.defineProperties(maker_for_document, {
            __argnames__ : {value: ["document"]}
        });

        if (typeof document === "undefined") {
            E = maker_for_document((function(){
                var ρσ_d = {};
                ρσ_d["createTextNode"] = (function() {
                    var ρσ_anonfunc = function (value) {
                        return value;
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["value"]}
                    });
                    return ρσ_anonfunc;
                })();
                ρσ_d["createElement"] = (function() {
                    var ρσ_anonfunc = function (name) {
                        return (function(){
                            var ρσ_d = {};
                            ρσ_d["name"] = name;
                            ρσ_d["children"] = ρσ_list_decorate([]);
                            ρσ_d["attributes"] = {};
                            ρσ_d["setAttribute"] = (function() {
                                var ρσ_anonfunc = function (name, val) {
                                    (ρσ_expr_temp = this.attributes)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name] = val;
                                };
                                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                                    __argnames__ : {value: ["name", "val"]}
                                });
                                return ρσ_anonfunc;
                            })();
                            ρσ_d["appendChild"] = (function() {
                                var ρσ_anonfunc = function (child) {
                                    this.children.push(child);
                                };
                                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                                    __argnames__ : {value: ["child"]}
                                });
                                return ρσ_anonfunc;
                            })();
                            return ρσ_d;
                        }).call(this);
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["name"]}
                    });
                    return ρσ_anonfunc;
                })();
                return ρσ_d;
            }).call(this));
        } else {
            E = maker_for_document(document);
        }
        ρσ_modules.elementmaker.html_elements = html_elements;
        ρσ_modules.elementmaker.mathml_elements = mathml_elements;
        ρσ_modules.elementmaker.svg_elements = svg_elements;
        ρσ_modules.elementmaker.html5_tags = html5_tags;
        ρσ_modules.elementmaker.E = E;
        ρσ_modules.elementmaker._makeelement = _makeelement;
        ρσ_modules.elementmaker.maker_for_document = maker_for_document;
    })();

    (function(){
        var __name__ = "gettext";
        var Jed, plural_forms_parser, _gettext, _ngettext, has_prop, empty_translation_data;
        Jed = {};
        
  Jed.PF = {};

  Jed.PF.parse = function ( p ) {
    var plural_str = Jed.PF.extractPluralExpr( p );
    return Jed.PF.parser.parse.call(Jed.PF.parser, plural_str);
  };

  Jed.PF.compile = function ( p ) {
    // Handle trues and falses as 0 and 1
    function imply( val ) {
      return (val === true ? 1 : val ? val : 0);
    }

    var ast = Jed.PF.parse( p );
    return function ( n ) {
      return imply( Jed.PF.interpreter( ast )( n ) );
    };
  };

  Jed.PF.interpreter = function ( ast ) {
    return function ( n ) {
      var res;
      switch ( ast.type ) {
        case 'GROUP':
          return Jed.PF.interpreter( ast.expr )( n );
        case 'TERNARY':
          if ( Jed.PF.interpreter( ast.expr )( n ) ) {
            return Jed.PF.interpreter( ast.truthy )( n );
          }
          return Jed.PF.interpreter( ast.falsey )( n );
        case 'OR':
          return Jed.PF.interpreter( ast.left )( n ) || Jed.PF.interpreter( ast.right )( n );
        case 'AND':
          return Jed.PF.interpreter( ast.left )( n ) && Jed.PF.interpreter( ast.right )( n );
        case 'LT':
          return Jed.PF.interpreter( ast.left )( n ) < Jed.PF.interpreter( ast.right )( n );
        case 'GT':
          return Jed.PF.interpreter( ast.left )( n ) > Jed.PF.interpreter( ast.right )( n );
        case 'LTE':
          return Jed.PF.interpreter( ast.left )( n ) <= Jed.PF.interpreter( ast.right )( n );
        case 'GTE':
          return Jed.PF.interpreter( ast.left )( n ) >= Jed.PF.interpreter( ast.right )( n );
        case 'EQ':
          return Jed.PF.interpreter( ast.left )( n ) == Jed.PF.interpreter( ast.right )( n );
        case 'NEQ':
          return Jed.PF.interpreter( ast.left )( n ) != Jed.PF.interpreter( ast.right )( n );
        case 'MOD':
          return Jed.PF.interpreter( ast.left )( n ) % Jed.PF.interpreter( ast.right )( n );
        case 'VAR':
          return n;
        case 'NUM':
          return ast.val;
        default:
          throw new Error("Invalid Token found.");
      }
    };
  };

  Jed.PF.extractPluralExpr = function ( p ) {
    // trim first
    p = p.replace(/^\s\s*/, '').replace(/\s\s*$/, '');

    if (! /;\s*$/.test(p)) {
      p = p.concat(';');
    }

    var nplurals_re = /nplurals\=(\d+);/,
        plural_re = /plural\=(.*);/,
        nplurals_matches = p.match( nplurals_re ),
        res = {},
        plural_matches;

    // Find the nplurals number
    if ( nplurals_matches.length > 1 ) {
      res.nplurals = nplurals_matches[1];
    }
    else {
      throw new Error('nplurals not found in plural_forms string: ' + p );
    }

    // remove that data to get to the formula
    p = p.replace( nplurals_re, "" );
    plural_matches = p.match( plural_re );

    if (!( plural_matches && plural_matches.length > 1 ) ) {
      throw new Error('`plural` expression not found: ' + p);
    }
    return plural_matches[ 1 ];
  };

  /* Jison generated parser */
  Jed.PF.parser = (function(){

var parser = {trace: function trace() { },
yy: {},
symbols_: {"error":2,"expressions":3,"e":4,"EOF":5,"?":6,":":7,"||":8,"&&":9,"<":10,"<=":11,">":12,">=":13,"!=":14,"==":15,"%":16,"(":17,")":18,"n":19,"NUMBER":20,"$accept":0,"$end":1},
terminals_: {2:"error",5:"EOF",6:"?",7:":",8:"||",9:"&&",10:"<",11:"<=",12:">",13:">=",14:"!=",15:"==",16:"%",17:"(",18:")",19:"n",20:"NUMBER"},
productions_: [0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]],
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {

var $0 = $$.length - 1;
switch (yystate) {
case 1: return { type : 'GROUP', expr: $$[$0-1] };
case 2:this.$ = { type: 'TERNARY', expr: $$[$0-4], truthy : $$[$0-2], falsey: $$[$0] };
break;
case 3:this.$ = { type: "OR", left: $$[$0-2], right: $$[$0] };
break;
case 4:this.$ = { type: "AND", left: $$[$0-2], right: $$[$0] };
break;
case 5:this.$ = { type: 'LT', left: $$[$0-2], right: $$[$0] };
break;
case 6:this.$ = { type: 'LTE', left: $$[$0-2], right: $$[$0] };
break;
case 7:this.$ = { type: 'GT', left: $$[$0-2], right: $$[$0] };
break;
case 8:this.$ = { type: 'GTE', left: $$[$0-2], right: $$[$0] };
break;
case 9:this.$ = { type: 'NEQ', left: $$[$0-2], right: $$[$0] };
break;
case 10:this.$ = { type: 'EQ', left: $$[$0-2], right: $$[$0] };
break;
case 11:this.$ = { type: 'MOD', left: $$[$0-2], right: $$[$0] };
break;
case 12:this.$ = { type: 'GROUP', expr: $$[$0-1] };
break;
case 13:this.$ = { type: 'VAR' };
break;
case 14:this.$ = { type: 'NUM', val: Number(yytext) };
break;
}
},
table: [{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}],
defaultActions: {6:[2,1]},
parseError: function parseError(str, hash) {
    throw new Error(str);
},
parse: function parse(input) {
    var self = this,
        stack = [0],
        vstack = [null], // semantic value stack
        lstack = [], // location stack
        table = this.table,
        yytext = '',
        yylineno = 0,
        yyleng = 0,
        recovering = 0,
        TERROR = 2,
        EOF = 1;

    //this.reductionCount = this.shiftCount = 0;

    this.lexer.setInput(input);
    this.lexer.yy = this.yy;
    this.yy.lexer = this.lexer;
    if (typeof this.lexer.yylloc == 'undefined')
        this.lexer.yylloc = {};
    var yyloc = this.lexer.yylloc;
    lstack.push(yyloc);

    if (typeof this.yy.parseError === 'function')
        this.parseError = this.yy.parseError;

    function popStack (n) {
        stack.length = stack.length - 2*n;
        vstack.length = vstack.length - n;
        lstack.length = lstack.length - n;
    }

    function lex() {
        var token;
        token = self.lexer.lex() || 1; // $end = 1
        // if token isn't its numeric value, convert
        if (typeof token !== 'number') {
            token = self.symbols_[token] || token;
        }
        return token;
    }

    var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected, errStr;
    while (true) {
        // retreive state number from top of stack
        state = stack[stack.length-1];

        // use default actions if available
        if (this.defaultActions[state]) {
            action = this.defaultActions[state];
        } else {
            if (symbol === null || symbol === undefined)
                symbol = lex();
            // read action for current state and first input
            action = table[state] && table[state][symbol];
        }

        // handle parse error
        _handle_error:
        if (typeof action === 'undefined' || !action.length || !action[0]) {

            if (!recovering) {
                // Report error
                expected = [];
                for (p in table[state]) if (this.terminals_[p] && p > 2) {
                    expected.push("'"+this.terminals_[p]+"'");
                }
                errStr = '';
                if (this.lexer.showPosition) {
                    errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
                } else {
                    errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
                                  (symbol == 1 /*EOF*/ ? "end of input" :
                                              ("'"+(this.terminals_[symbol] || symbol)+"'"));
                }
                this.parseError(errStr,
                    {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
            }

            // just recovered from another error
            if (recovering == 3) {
                if (symbol == EOF) {
                    throw new Error(errStr || 'Parsing halted.');
                }

                // discard current lookahead and grab another
                yyleng = this.lexer.yyleng;
                yytext = this.lexer.yytext;
                yylineno = this.lexer.yylineno;
                yyloc = this.lexer.yylloc;
                symbol = lex();
            }

            // try to recover from error
            while (1) {
                // check for error recovery rule in this state
                if ((TERROR.toString()) in table[state]) {
                    break;
                }
                if (state === 0) {
                    throw new Error(errStr || 'Parsing halted.');
                }
                popStack(1);
                state = stack[stack.length-1];
            }

            preErrorSymbol = symbol; // save the lookahead token
            symbol = TERROR;         // insert generic error symbol as new lookahead
            state = stack[stack.length-1];
            action = table[state] && table[state][TERROR];
            recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
        }

        // this shouldn't happen, unless resolve defaults are off
        if (action[0] instanceof Array && action.length > 1) {
            throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
        }

        switch (action[0]) {

            case 1: // shift
                //this.shiftCount++;

                stack.push(symbol);
                vstack.push(this.lexer.yytext);
                lstack.push(this.lexer.yylloc);
                stack.push(action[1]); // push state
                symbol = null;
                if (!preErrorSymbol) { // normal execution/no error
                    yyleng = this.lexer.yyleng;
                    yytext = this.lexer.yytext;
                    yylineno = this.lexer.yylineno;
                    yyloc = this.lexer.yylloc;
                    if (recovering > 0)
                        recovering--;
                } else { // error just occurred, resume old lookahead f/ before error
                    symbol = preErrorSymbol;
                    preErrorSymbol = null;
                }
                break;

            case 2: // reduce
                //this.reductionCount++;

                len = this.productions_[action[1]][1];

                // perform semantic action
                yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
                // default location, uses first token for firsts, last for lasts
                yyval._$ = {
                    first_line: lstack[lstack.length-(len||1)].first_line,
                    last_line: lstack[lstack.length-1].last_line,
                    first_column: lstack[lstack.length-(len||1)].first_column,
                    last_column: lstack[lstack.length-1].last_column
                };
                r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);

                if (typeof r !== 'undefined') {
                    return r;
                }

                // pop off stack
                if (len) {
                    stack = stack.slice(0,-1*len*2);
                    vstack = vstack.slice(0, -1*len);
                    lstack = lstack.slice(0, -1*len);
                }

                stack.push(this.productions_[action[1]][0]);    // push nonterminal (reduce)
                vstack.push(yyval.$);
                lstack.push(yyval._$);
                // goto new state = table[STATE][NONTERMINAL]
                newState = table[stack[stack.length-2]][stack[stack.length-1]];
                stack.push(newState);
                break;

            case 3: // accept
                return true;
        }

    }

    return true;
}};/* Jison generated lexer */
var lexer = (function(){

var lexer = ({EOF:1,
parseError:function parseError(str, hash) {
        if (this.yy.parseError) {
            this.yy.parseError(str, hash);
        } else {
            throw new Error(str);
        }
    },
setInput:function (input) {
        this._input = input;
        this._more = this._less = this.done = false;
        this.yylineno = this.yyleng = 0;
        this.yytext = this.matched = this.match = '';
        this.conditionStack = ['INITIAL'];
        this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
        return this;
    },
input:function () {
        var ch = this._input[0];
        this.yytext+=ch;
        this.yyleng++;
        this.match+=ch;
        this.matched+=ch;
        var lines = ch.match(/\n/);
        if (lines) this.yylineno++;
        this._input = this._input.slice(1);
        return ch;
    },
unput:function (ch) {
        this._input = ch + this._input;
        return this;
    },
more:function () {
        this._more = true;
        return this;
    },
pastInput:function () {
        var past = this.matched.substr(0, this.matched.length - this.match.length);
        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
    },
upcomingInput:function () {
        var next = this.match;
        if (next.length < 20) {
            next += this._input.substr(0, 20-next.length);
        }
        return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
    },
showPosition:function () {
        var pre = this.pastInput();
        var c = new Array(pre.length + 1).join("-");
        return pre + this.upcomingInput() + "\n" + c+"^";
    },
next:function () {
        if (this.done) {
            return this.EOF;
        }
        if (!this._input) this.done = true;

        var token,
            match,
            col,
            lines;
        if (!this._more) {
            this.yytext = '';
            this.match = '';
        }
        var rules = this._currentRules();
        for (var i=0;i < rules.length; i++) {
            match = this._input.match(this.rules[rules[i]]);
            if (match) {
                lines = match[0].match(/\n.*/g);
                if (lines) this.yylineno += lines.length;
                this.yylloc = {first_line: this.yylloc.last_line,
                               last_line: this.yylineno+1,
                               first_column: this.yylloc.last_column,
                               last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length};
                this.yytext += match[0];
                this.match += match[0];
                this.matches = match;
                this.yyleng = this.yytext.length;
                this._more = false;
                this._input = this._input.slice(match[0].length);
                this.matched += match[0];
                token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);
                if (token) return token;
                else return;
            }
        }
        if (this._input === "") {
            return this.EOF;
        } else {
            this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
                    {text: "", token: null, line: this.yylineno});
        }
    },
lex:function lex() {
        var r = this.next();
        if (typeof r !== 'undefined') {
            return r;
        } else {
            return this.lex();
        }
    },
begin:function begin(condition) {
        this.conditionStack.push(condition);
    },
popState:function popState() {
        return this.conditionStack.pop();
    },
_currentRules:function _currentRules() {
        return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
    },
topState:function () {
        return this.conditionStack[this.conditionStack.length-2];
    },
pushState:function begin(condition) {
        this.begin(condition);
    }});
lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {

var YYSTATE=YY_START;
switch($avoiding_name_collisions) {
case 0:/* skip whitespace */
break;
case 1:return 20
break;
case 2:return 19
break;
case 3:return 8
break;
case 4:return 9
break;
case 5:return 6
break;
case 6:return 7
break;
case 7:return 11
break;
case 8:return 13
break;
case 9:return 10
break;
case 10:return 12
break;
case 11:return 14
break;
case 12:return 15
break;
case 13:return 16
break;
case 14:return 17
break;
case 15:return 18
break;
case 16:return 5
break;
case 17:return 'INVALID'
break;
}
};
lexer.rules = [/^\s+/,/^[0-9]+(\.[0-9]+)?\b/,/^n\b/,/^\|\|/,/^&&/,/^\?/,/^:/,/^<=/,/^>=/,/^</,/^>/,/^!=/,/^==/,/^%/,/^\(/,/^\)/,/^$/,/^./];
lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"inclusive":true}};return lexer;})()
parser.lexer = lexer;
return parser;
})();
;
        plural_forms_parser = Jed.PF;
        function _get_plural_forms_function(plural_forms_string) {
            return plural_forms_parser.compile(plural_forms_string || "nplurals=2; plural=(n != 1);");
        };
        if (!_get_plural_forms_function.__argnames__) Object.defineProperties(_get_plural_forms_function, {
            __argnames__ : {value: ["plural_forms_string"]}
        });

        _gettext = (function() {
            var ρσ_anonfunc = function (text) {
                return text;
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["text"]}
            });
            return ρσ_anonfunc;
        })();
        _ngettext = (function() {
            var ρσ_anonfunc = function (text, plural, n) {
                return (n === 1) ? text : plural;
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["text", "plural", "n"]}
            });
            return ρσ_anonfunc;
        })();
        function gettext(text) {
            return _gettext(text);
        };
        if (!gettext.__argnames__) Object.defineProperties(gettext, {
            __argnames__ : {value: ["text"]}
        });

        function ngettext(text, plural, n) {
            return _ngettext(text, plural, n);
        };
        if (!ngettext.__argnames__) Object.defineProperties(ngettext, {
            __argnames__ : {value: ["text", "plural", "n"]}
        });

        function install(translation_data) {
            var t, func;
            t = new Translations(translation_data);
            t.install();
            var ρσ_Iter0 = ρσ_Iterable(register_callback.install_callbacks);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                func = ρσ_Iter0[ρσ_Index0];
                try {
                    func(t);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                    } 
                }
            }
            return t;
        };
        if (!install.__argnames__) Object.defineProperties(install, {
            __argnames__ : {value: ["translation_data"]}
        });

        has_prop = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
        function register_callback(func) {
            register_callback.install_callbacks.push(func);
        };
        if (!register_callback.__argnames__) Object.defineProperties(register_callback, {
            __argnames__ : {value: ["func"]}
        });

        register_callback.install_callbacks = [];
        empty_translation_data = (function(){
            var ρσ_d = {};
            ρσ_d["entries"] = {};
            return ρσ_d;
        }).call(this);
        function Translations() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            Translations.prototype.__init__.apply(this, arguments);
        }
        Translations.prototype.__init__ = function __init__(translation_data) {
            var self = this;
            var func;
            translation_data = translation_data || empty_translation_data;
            func = _get_plural_forms_function(translation_data.plural_forms);
            self.translations = ρσ_list_decorate([ ρσ_list_decorate([ translation_data, func ]) ]);
            self.language = translation_data["language"];
        };
        if (!Translations.prototype.__init__.__argnames__) Object.defineProperties(Translations.prototype.__init__, {
            __argnames__ : {value: ["translation_data"]}
        });
        Translations.__argnames__ = Translations.prototype.__init__.__argnames__;
        Translations.__handles_kwarg_interpolation__ = Translations.prototype.__init__.__handles_kwarg_interpolation__;
        Translations.prototype.add_fallback = function add_fallback(fallback) {
            var self = this;
            var func;
            fallback = fallback || empty_translation_data;
            func = _get_plural_forms_function(fallback.plural_forms);
            self.translations.push(ρσ_list_decorate([ fallback, func ]));
        };
        if (!Translations.prototype.add_fallback.__argnames__) Object.defineProperties(Translations.prototype.add_fallback, {
            __argnames__ : {value: ["fallback"]}
        });
        Translations.prototype.gettext = function gettext(text) {
            var self = this;
            var m, t;
            var ρσ_Iter1 = ρσ_Iterable(self.translations);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                t = ρσ_Iter1[ρσ_Index1];
                m = t[0].entries;
                if (has_prop(m, text)) {
                    return m[(typeof text === "number" && text < 0) ? m.length + text : text][0];
                }
            }
            return text;
        };
        if (!Translations.prototype.gettext.__argnames__) Object.defineProperties(Translations.prototype.gettext, {
            __argnames__ : {value: ["text"]}
        });
        Translations.prototype.ngettext = function ngettext(text, plural, n) {
            var self = this;
            var m, idx, t;
            var ρσ_Iter2 = ρσ_Iterable(self.translations);
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                t = ρσ_Iter2[ρσ_Index2];
                m = t[0].entries;
                if (has_prop(m, text)) {
                    idx = t[1](n);
                    return (ρσ_expr_temp = m[(typeof text === "number" && text < 0) ? m.length + text : text])[(typeof idx === "number" && idx < 0) ? ρσ_expr_temp.length + idx : idx] || ((n === 1) ? text : plural);
                }
            }
            return (n === 1) ? text : plural;
        };
        if (!Translations.prototype.ngettext.__argnames__) Object.defineProperties(Translations.prototype.ngettext, {
            __argnames__ : {value: ["text", "plural", "n"]}
        });
        Translations.prototype.install = function install() {
            var self = this;
            _gettext = function () {
                return self.gettext.apply(self, arguments);
            };
            _ngettext = function () {
                return self.ngettext.apply(self, arguments);
            };
        };
        Translations.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        Translations.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(Translations.prototype, "__bases__", {value: []});

        ρσ_modules.gettext.Jed = Jed;
        ρσ_modules.gettext.plural_forms_parser = plural_forms_parser;
        ρσ_modules.gettext._gettext = _gettext;
        ρσ_modules.gettext._ngettext = _ngettext;
        ρσ_modules.gettext.has_prop = has_prop;
        ρσ_modules.gettext.empty_translation_data = empty_translation_data;
        ρσ_modules.gettext._get_plural_forms_function = _get_plural_forms_function;
        ρσ_modules.gettext.gettext = gettext;
        ρσ_modules.gettext.ngettext = ngettext;
        ρσ_modules.gettext.install = install;
        ρσ_modules.gettext.register_callback = register_callback;
        ρσ_modules.gettext.Translations = Translations;
    })();

    (function(){
        var __name__ = "pythonize";
        function strings() {
            var string_funcs, exclude, name;
            string_funcs = set("capitalize strip lstrip rstrip islower isupper isspace lower upper swapcase center count endswith startswith find rfind index rindex format join ljust rjust partition rpartition replace split rsplit splitlines zfill".split(" "));
            if (!arguments.length) {
                exclude = (function(){
                    var s = ρσ_set();
                    s.jsset.add("split");
                    s.jsset.add("replace");
                    return s;
                })();
            } else if (arguments[0]) {
                exclude = Array.prototype.slice.call(arguments);
            } else {
                exclude = null;
            }
            if (exclude) {
                string_funcs = string_funcs.difference(set(exclude));
            }
            var ρσ_Iter0 = ρσ_Iterable(string_funcs);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                name = ρσ_Iter0[ρσ_Index0];
                (ρσ_expr_temp = String.prototype)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name] = (ρσ_expr_temp = ρσ_str.prototype)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name];
            }
        };

        ρσ_modules.pythonize.strings = strings;
    })();

    (function(){
        var __name__ = "initialize";
        var strings = ρσ_modules.pythonize.strings;

        strings();
    })();

    (function(){
        var __name__ = "ajax";
        var default_timeout;
        var _ = ρσ_modules.gettext.gettext;

        default_timeout = 60;
        function set_default_timeout(val) {
            default_timeout = val;
        };
        if (!set_default_timeout.__argnames__) Object.defineProperties(set_default_timeout, {
            __argnames__ : {value: ["val"]}
        });

        function encode_query_component(x) {
            var ans;
            ans = encodeURIComponent(x);
            ans = ans.replace(/%2[fF]/g, "/");
            ans = ans.replace(/%40/g, "@");
            ans = ans.replace(/%5[bB]/g, "[");
            ans = ans.replace(/%5[dD]/g, "]");
            ans = ans.replace(/%5[eE]/g, "^");
            ans = ans.replace(/%3[aA]/g, ":");
            return ans;
        };
        if (!encode_query_component.__argnames__) Object.defineProperties(encode_query_component, {
            __argnames__ : {value: ["x"]}
        });

        function encode_query(query, qchar) {
            var keys, ans, val, k;
            if (!query) {
                return "";
            }
            qchar = qchar || "?";
            keys = Object.keys(query).sort();
            ans = "";
            if (keys.length) {
                var ρσ_Iter0 = ρσ_Iterable(keys);
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    k = ρσ_Iter0[ρσ_Index0];
                    val = query[(typeof k === "number" && k < 0) ? query.length + k : k];
                    if (val === undefined || val === null || val === "") {
                        continue;
                    }
                    ans += qchar + encodeURIComponent(k) + "=" + encode_query_component(val.toString());
                    qchar = "&";
                }
            }
            return ans;
        };
        if (!encode_query.__argnames__) Object.defineProperties(encode_query, {
            __argnames__ : {value: ["query", "qchar"]}
        });

        function absolute_path(path) {
            var slash;
            if (path[0] !== "/") {
                slash = ((ρσ_expr_temp = window.location.pathname)[ρσ_expr_temp.length-1] === "/") ? "" : "/";
                path = window.location.pathname + slash + path;
            }
            return path;
        };
        if (!absolute_path.__argnames__) Object.defineProperties(absolute_path, {
            __argnames__ : {value: ["path"]}
        });

        function ajax() {
            var path = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var on_complete = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var on_progress = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax.__defaults__.on_progress : arguments[2];
            var bypass_cache = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax.__defaults__.bypass_cache : arguments[3];
            var method = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax.__defaults__.method : arguments[4];
            var query = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax.__defaults__.query : arguments[5];
            var timeout = (arguments[6] === undefined || ( 6 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax.__defaults__.timeout : arguments[6];
            var ok_code = (arguments[7] === undefined || ( 7 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax.__defaults__.ok_code : arguments[7];
            var progress_totals_needed = (arguments[8] === undefined || ( 8 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax.__defaults__.progress_totals_needed : arguments[8];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_progress")){
                on_progress = ρσ_kwargs_obj.on_progress;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "bypass_cache")){
                bypass_cache = ρσ_kwargs_obj.bypass_cache;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "method")){
                method = ρσ_kwargs_obj.method;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "query")){
                query = ρσ_kwargs_obj.query;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "timeout")){
                timeout = ρσ_kwargs_obj.timeout;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "ok_code")){
                ok_code = ρσ_kwargs_obj.ok_code;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "progress_totals_needed")){
                progress_totals_needed = ρσ_kwargs_obj.progress_totals_needed;
            }
            var xhr, eq, has_query;
            if (timeout === null) {
                timeout = default_timeout;
            }
            query = query || Object.create(null);
            xhr = new XMLHttpRequest;
            eq = encode_query(query);
            has_query = eq.length > 0;
            path = absolute_path(path) + eq;
            if (bypass_cache) {
                path += ((has_query) ? "&" : "?") + (new Date).getTime();
            }
            xhr.request_path = path;
            xhr.error_html = "";
            function set_error(event, is_network_error) {
                var rtext;
                if (is_network_error) {
                    xhr.error_html = str.format(_("Failed to communicate with \"{}\", network error, is the server running and accessible?"), xhr.request_path);
                } else if (event === "timeout") {
                    xhr.error_html = str.format(_("Failed to communicate with \"{}\", timed out after: {} seconds"), xhr.request_path, timeout);
                } else if (event === "abort") {
                    xhr.error_html = str.format(_("Failed to communicate with \"{}\", aborted"), xhr.request_path);
                } else {
                    try {
                        rtext = xhr.responseText || "";
                    } catch (ρσ_Exception) {
                        ρσ_last_exception = ρσ_Exception;
                        {
                            rtext = "";
                        } 
                    }
                    xhr.error_html = str.format(_("Failed to communicate with \"{}\", with status: [{}] {}<br><br>{}"), xhr.request_path, xhr.status, xhr.statusText, rtext.slice(0, 200));
                }
            };
            if (!set_error.__argnames__) Object.defineProperties(set_error, {
                __argnames__ : {value: ["event", "is_network_error"]}
            });

            function progress_callback(ev) {
                var ul;
                if (ev.lengthComputable) {
                    on_progress(ev.loaded, ev.total, xhr);
                } else if (ev.loaded) {
                    if (!progress_totals_needed) {
                        on_progress(ev.loaded, undefined, xhr);
                        return;
                    }
                    ul = xhr.getResponseHeader("Calibre-Uncompressed-Length");
                    if (ul) {
                        try {
                            ul = int(ul);
                        } catch (ρσ_Exception) {
                            ρσ_last_exception = ρσ_Exception;
                            if (ρσ_Exception instanceof Error) {
                                return;
                            } else {
                                throw ρσ_Exception;
                            }
                        }
                        on_progress(ev.loaded, ul, xhr);
                    }
                }
            };
            if (!progress_callback.__argnames__) Object.defineProperties(progress_callback, {
                __argnames__ : {value: ["ev"]}
            });

            function complete_callback(end_type, ev) {
                var is_network_error;
                is_network_error = (end_type === "error") ? ev : false;
                if (xhr.status !== ok_code && end_type === "load") {
                    end_type = "error";
                }
                if (end_type !== "load") {
                    set_error(end_type, is_network_error);
                }
                on_complete(end_type, xhr, ev);
            };
            if (!complete_callback.__argnames__) Object.defineProperties(complete_callback, {
                __argnames__ : {value: ["end_type", "ev"]}
            });

            if (on_progress) {
                xhr.addEventListener("progress", progress_callback);
            }
            xhr.addEventListener("abort", (function() {
                var ρσ_anonfunc = function (ev) {
                    complete_callback("abort", ev);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })());
            xhr.addEventListener("error", (function() {
                var ρσ_anonfunc = function (ev) {
                    complete_callback("error", ev);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })());
            xhr.addEventListener("load", (function() {
                var ρσ_anonfunc = function (ev) {
                    complete_callback("load", ev);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })());
            xhr.addEventListener("timeout", (function() {
                var ρσ_anonfunc = function (ev) {
                    complete_callback("timeout", ev);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })());
            xhr.open(method, path);
            xhr.timeout = timeout * 1e3;
            return xhr;
        };
        if (!ajax.__defaults__) Object.defineProperties(ajax, {
            __defaults__ : {value: {on_progress:null, bypass_cache:true, method:"GET", query:null, timeout:null, ok_code:200, progress_totals_needed:true}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["path", "on_complete", "on_progress", "bypass_cache", "method", "query", "timeout", "ok_code", "progress_totals_needed"]}
        });

        function ajax_send() {
            var path = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var data = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var on_complete = ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[2];
            var on_progress = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax_send.__defaults__.on_progress : arguments[3];
            var query = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax_send.__defaults__.query : arguments[4];
            var timeout = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax_send.__defaults__.timeout : arguments[5];
            var ok_code = (arguments[6] === undefined || ( 6 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax_send.__defaults__.ok_code : arguments[6];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_progress")){
                on_progress = ρσ_kwargs_obj.on_progress;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "query")){
                query = ρσ_kwargs_obj.query;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "timeout")){
                timeout = ρσ_kwargs_obj.timeout;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "ok_code")){
                ok_code = ρσ_kwargs_obj.ok_code;
            }
            var xhr;
            xhr = ajax(path, on_complete, on_progress, false, "POST", query, timeout, ok_code);
            xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
            xhr.send(JSON.stringify(data));
            return xhr;
        };
        if (!ajax_send.__defaults__) Object.defineProperties(ajax_send, {
            __defaults__ : {value: {on_progress:null, query:null, timeout:null, ok_code:200}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["path", "data", "on_complete", "on_progress", "query", "timeout", "ok_code"]}
        });

        function ajax_send_file() {
            var path = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var file = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var on_complete = ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[2];
            var on_progress = ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[3];
            var timeout = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax_send_file.__defaults__.timeout : arguments[4];
            var ok_code = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax_send_file.__defaults__.ok_code : arguments[5];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "timeout")){
                timeout = ρσ_kwargs_obj.timeout;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "ok_code")){
                ok_code = ρσ_kwargs_obj.ok_code;
            }
            var xhr;
            xhr = ajax(path, on_complete, on_progress, false, "POST", timeout, ok_code);
            if (file.type) {
                xhr.overrideMimeType(file.type);
            }
            xhr.send(file);
            return xhr;
        };
        if (!ajax_send_file.__defaults__) Object.defineProperties(ajax_send_file, {
            __defaults__ : {value: {timeout:null, ok_code:200}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["path", "file", "on_complete", "on_progress", "timeout", "ok_code"]}
        });

        function console_print() {
            var args = Array.prototype.slice.call(arguments, 0);
            if (arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) args.pop();
            var data, xhr;
            ρσ_print.apply(this, args);
            data = " ".join(map(str, args)) + "\n";
            xhr = ρσ_interpolate_kwargs.call(this, ajax, ["console-print", function () {
            }].concat([ρσ_desugar_kwargs({method: "POST", progress_totals_needed: false})]));
            xhr.send(data);
        };
        if (!console_print.__handles_kwarg_interpolation__) Object.defineProperties(console_print, {
            __handles_kwarg_interpolation__ : {value: true}
        });

        ρσ_modules.ajax.default_timeout = default_timeout;
        ρσ_modules.ajax.set_default_timeout = set_default_timeout;
        ρσ_modules.ajax.encode_query_component = encode_query_component;
        ρσ_modules.ajax.encode_query = encode_query;
        ρσ_modules.ajax.absolute_path = absolute_path;
        ρσ_modules.ajax.ajax = ajax;
        ρσ_modules.ajax.ajax_send = ajax_send;
        ρσ_modules.ajax.ajax_send_file = ajax_send_file;
        ρσ_modules.ajax.console_print = console_print;
    })();

    (function(){
        var __name__ = "book_list";

    })();

    (function(){
        var __name__ = "book_list.globals";
        var session_data;
        session_data = null;
        function set_session_data(sd) {
            session_data = sd;
            return session_data;
        };
        if (!set_session_data.__argnames__) Object.defineProperties(set_session_data, {
            __argnames__ : {value: ["sd"]}
        });

        function get_session_data() {
            return session_data;
        };

        function main_js(newval) {
            if (newval !== undefined) {
                main_js.ans = newval;
            }
            return main_js.ans;
        };
        if (!main_js.__argnames__) Object.defineProperties(main_js, {
            __argnames__ : {value: ["newval"]}
        });

        function get_current_query(newval) {
            if (newval) {
                get_current_query.ans = newval;
            }
            return get_current_query.ans;
        };
        if (!get_current_query.__argnames__) Object.defineProperties(get_current_query, {
            __argnames__ : {value: ["newval"]}
        });

        function get_db(db) {
            if (db) {
                get_db.db = db;
            }
            return get_db.db;
        };
        if (!get_db.__argnames__) Object.defineProperties(get_db, {
            __argnames__ : {value: ["db"]}
        });

        function get_translations(val) {
            if (val) {
                get_translations.ans = val;
            }
            return get_translations.ans;
        };
        if (!get_translations.__argnames__) Object.defineProperties(get_translations, {
            __argnames__ : {value: ["val"]}
        });

        ρσ_modules["book_list.globals"].session_data = session_data;
        ρσ_modules["book_list.globals"].set_session_data = set_session_data;
        ρσ_modules["book_list.globals"].get_session_data = get_session_data;
        ρσ_modules["book_list.globals"].main_js = main_js;
        ρσ_modules["book_list.globals"].get_current_query = get_current_query;
        ρσ_modules["book_list.globals"].get_db = get_db;
        ρσ_modules["book_list.globals"].get_translations = get_translations;
    })();

    (function(){
        var __name__ = "lru_cache";
        function lru_node(key, val) {
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["key"] = key;
                ρσ_d["val"] = val;
                ρσ_d["prev"] = null;
                ρσ_d["next"] = null;
                return ρσ_d;
            }).call(this);
        };
        if (!lru_node.__argnames__) Object.defineProperties(lru_node, {
            __argnames__ : {value: ["key", "val"]}
        });

        function LRUCache() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            LRUCache.prototype.__bind_methods__.call(this);
            LRUCache.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(LRUCache.prototype, "__bind_methods__", {value: function () {
            this.set_head = LRUCache.prototype.set_head.bind(this);
            this.pop = LRUCache.prototype.pop.bind(this);
            this.set = LRUCache.prototype.set.bind(this);
            this.get = LRUCache.prototype.get.bind(this);
            this.clear = LRUCache.prototype.clear.bind(this);
        }});
        LRUCache.prototype.__init__ = function __init__(size) {
            var self = this;
            self.limit = 200;
            self.clear(size);
        };
        if (!LRUCache.prototype.__init__.__argnames__) Object.defineProperties(LRUCache.prototype.__init__, {
            __argnames__ : {value: ["size"]}
        });
        LRUCache.__argnames__ = LRUCache.prototype.__init__.__argnames__;
        LRUCache.__handles_kwarg_interpolation__ = LRUCache.prototype.__init__.__handles_kwarg_interpolation__;
        LRUCache.prototype.set_head = function set_head(node) {
            var self = this;
            node.next = self.head;
            node.prev = null;
            if (self.head !== null) {
                self.head.prev = node;
            }
            self.head = node;
            if (self.tail === null) {
                self.tail = node;
            }
            self.size += 1;
            (ρσ_expr_temp = self.map)[ρσ_bound_index(node.key, ρσ_expr_temp)] = node;
        };
        if (!LRUCache.prototype.set_head.__argnames__) Object.defineProperties(LRUCache.prototype.set_head, {
            __argnames__ : {value: ["node"]}
        });
        LRUCache.prototype.pop = function pop(key) {
            var self = this;
            var node;
            node = (ρσ_expr_temp = self.map)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
            if (!node) {
                return;
            }
            if (node.prev !== null) {
                node.prev.next = node.next;
            } else {
                self.head = node.next;
            }
            if (node.next !== null) {
                node.next.prev = node.prev;
            } else {
                self.tail = node.prev;
            }
            delete self.map[key];
            self.size -= 1;
        };
        if (!LRUCache.prototype.pop.__argnames__) Object.defineProperties(LRUCache.prototype.pop, {
            __argnames__ : {value: ["key"]}
        });
        LRUCache.prototype.set = function set(key, val) {
            var self = this;
            var node, existing;
            node = lru_node(key, val);
            existing = (ρσ_expr_temp = self.map)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
            if (existing) {
                existing.value = node.value;
                self.pop(node.key);
            } else if (self.size > self.limit) {
                delete self.map[self.tail.key];
                self.size -= 1;
                self.tail = self.tail.prev;
                self.tail.next = null;
            }
            self.set_head(node);
        };
        if (!LRUCache.prototype.set.__argnames__) Object.defineProperties(LRUCache.prototype.set, {
            __argnames__ : {value: ["key", "val"]}
        });
        LRUCache.prototype.get = function get(key, defval) {
            var self = this;
            var existing, val, node;
            existing = (ρσ_expr_temp = self.map)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
            if (!existing) {
                return (defval === undefined) ? null : defval;
            }
            val = existing.value;
            node = lru_node(key, val);
            self.pop(key);
            self.set_head(node);
            return val;
        };
        if (!LRUCache.prototype.get.__argnames__) Object.defineProperties(LRUCache.prototype.get, {
            __argnames__ : {value: ["key", "defval"]}
        });
        LRUCache.prototype.clear = function clear(size) {
            var self = this;
            self.size = 0;
            self.map = Object.create(null);
            self.head = self.tail = null;
            if (typeof size === "number") {
                self.limit = size;
            }
        };
        if (!LRUCache.prototype.clear.__argnames__) Object.defineProperties(LRUCache.prototype.clear, {
            __argnames__ : {value: ["size"]}
        });
        LRUCache.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        LRUCache.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(LRUCache.prototype, "__bases__", {value: []});

        ρσ_modules.lru_cache.lru_node = lru_node;
        ρσ_modules.lru_cache.LRUCache = LRUCache;
    })();

    (function(){
        var __name__ = "encodings";
        var utf8_decoder_table, _u8enc, utf8_encode;
        function base64encode(bytes, altchars, pad_char) {
            var l, remainder, main_length, encodings, ans, chunk;
            l = bytes.length;
            remainder = l % 3;
            main_length = l - remainder;
            encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + (altchars || "+/");
            pad_char = (pad_char === undefined) ? "=" : pad_char;
            ans = [];
            for (var i = 0; i < main_length; i += 3) {
                chunk = bytes[(typeof i === "number" && i < 0) ? bytes.length + i : i] << 16 | bytes[ρσ_bound_index(i + 1, bytes)] << 8 | bytes[ρσ_bound_index(i + 2, bytes)];
                ans.push(encodings[ρσ_bound_index((chunk & 16515072) >> 18, encodings)], encodings[ρσ_bound_index((chunk & 258048) >> 12, encodings)], encodings[ρσ_bound_index((chunk & 4032) >> 6, encodings)], encodings[ρσ_bound_index(chunk & 63, encodings)]);
            }
            if (remainder === 1) {
                chunk = bytes[(typeof main_length === "number" && main_length < 0) ? bytes.length + main_length : main_length];
                ans.push(encodings[ρσ_bound_index((chunk & 252) >> 2, encodings)], encodings[ρσ_bound_index((chunk & 3) << 4, encodings)], pad_char, pad_char);
            } else if (remainder === 2) {
                chunk = bytes[(typeof main_length === "number" && main_length < 0) ? bytes.length + main_length : main_length] << 8 | bytes[ρσ_bound_index(main_length + 1, bytes)];
                ans.push(encodings[ρσ_bound_index((chunk & 64512) >> 10, encodings)], encodings[ρσ_bound_index((chunk & 1008) >> 4, encodings)], encodings[ρσ_bound_index((chunk & 15) << 2, encodings)], pad_char);
            }
            return ans.join("");
        };
        if (!base64encode.__argnames__) Object.defineProperties(base64encode, {
            __argnames__ : {value: ["bytes", "altchars", "pad_char"]}
        });

        function base64decode(string) {
            var chars, ans, i;
            if (typeof window !== "undefined") {
                chars = window.atob(string);
            } else {
                chars = new Buffer(string, "base64").toString("binary");
            }
            ans = new Uint8Array(chars.length);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ans.length; ρσ_Index0++) {
                i = ρσ_Index0;
                ans[(typeof i === "number" && i < 0) ? ans.length + i : i] = chars.charCodeAt(i);
            }
            return ans;
        };
        if (!base64decode.__argnames__) Object.defineProperties(base64decode, {
            __argnames__ : {value: ["string"]}
        });

        function urlsafe_b64encode(bytes, pad_char) {
            return base64encode(bytes, "-_", pad_char);
        };
        if (!urlsafe_b64encode.__argnames__) Object.defineProperties(urlsafe_b64encode, {
            __argnames__ : {value: ["bytes", "pad_char"]}
        });

        function urlsafe_b64decode(string) {
            string = String.prototype.replace.call(string, /[_-]/g, (function() {
                var ρσ_anonfunc = function (m) {
                    return (m === "-") ? "+" : "/";
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["m"]}
                });
                return ρσ_anonfunc;
            })());
            return base64decode(string);
        };
        if (!urlsafe_b64decode.__argnames__) Object.defineProperties(urlsafe_b64decode, {
            __argnames__ : {value: ["string"]}
        });

        function hexlify(bytes) {
            var ans, x;
            ans = [];
            for (var i = 0; i < bytes.length; i++) {
                x = bytes[(typeof i === "number" && i < 0) ? bytes.length + i : i].toString(16);
                if (x.length === 1) {
                    x = "0" + x;
                }
                ans.push(x);
            }
            return ans.join("");
        };
        if (!hexlify.__argnames__) Object.defineProperties(hexlify, {
            __argnames__ : {value: ["bytes"]}
        });

        function unhexlify(string) {
            var num, ans, x;
            num = Math.floor(string.length / 2);
            if (num * 2 !== string.length) {
                throw new ValueError("string length is not a multiple of two");
            }
            ans = new Uint8Array(num);
            for (var i = 0; i < num; i++) {
                x = parseInt(string.slice(i * 2, i * 2 + 2), 16);
                if (isNaN(x)) {
                    throw new ValueError("string is not hex-encoded");
                }
                ans[(typeof i === "number" && i < 0) ? ans.length + i : i] = x;
            }
            return ans;
        };
        if (!unhexlify.__argnames__) Object.defineProperties(unhexlify, {
            __argnames__ : {value: ["string"]}
        });

        utf8_decoder_table = [
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
  8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
  0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
  0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
  0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
  1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
  1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
  1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
];
        function _from_code_point(x) {
            if (x <= 65535) {
                return String.fromCharCode(x);
            }
            x -= 65536;
            return String.fromCharCode((x >> 10) + 55296, x % 1024 + 56320);
        };
        if (!_from_code_point.__argnames__) Object.defineProperties(_from_code_point, {
            __argnames__ : {value: ["x"]}
        });

        function utf8_decode(bytes, errors, replacement) {
            var state, ans, byte, typ, codep;
            state = 0;
            ans = [];
            for (var i = 0, l = bytes.length; i < l; i++) {
                byte = bytes[(typeof i === "number" && i < 0) ? bytes.length + i : i];
                typ = utf8_decoder_table[(typeof byte === "number" && byte < 0) ? utf8_decoder_table.length + byte : byte];
                codep = (state !== 0) ? byte & 63 | codep << 6 : 255 >> typ & byte;
                state = utf8_decoder_table[ρσ_bound_index(256 + state * 16 + typ, utf8_decoder_table)];
                if (state === 0) {
                    ans.push(_from_code_point(codep));
                } else if (state === 1) {
                    if (!errors || errors === "strict") {
                        throw new UnicodeDecodeError(str.format("The byte 0x{:02x} at position {} is not valid UTF-8", byte, i));
                    } else if (errors === "replace") {
                        ans.push(replacement || "?");
                    }
                }
            }
            return ans.join("");
        };
        if (!utf8_decode.__argnames__) Object.defineProperties(utf8_decode, {
            __argnames__ : {value: ["bytes", "errors", "replacement"]}
        });

        function utf8_encode_js(string) {
            var escstr, ans, ch, i;
            escstr = encodeURIComponent(string);
            ans = [];
            for (var i = 0; i < escstr.length; i++) {
                ch = escstr[(typeof i === "number" && i < 0) ? escstr.length + i : i];
                if (ch === "%") {
                    ans.push(parseInt(escstr.slice(i + 1, i + 3), 16));
                    i += 2;
                } else {
                    ans.push(ch.charCodeAt(0));
                }
            }
            return new Uint8Array(ans);
        };
        if (!utf8_encode_js.__argnames__) Object.defineProperties(utf8_encode_js, {
            __argnames__ : {value: ["string"]}
        });

        if (typeof TextEncoder === "function") {
            _u8enc = new TextEncoder("utf-8");
            utf8_encode = _u8enc.encode.bind(_u8enc);
            _u8enc = undefined;
        } else {
            utf8_encode = utf8_encode_js;
        }
        function utf8_encode_native(string) {
            return _u8enc.encode(string);
        };
        if (!utf8_encode_native.__argnames__) Object.defineProperties(utf8_encode_native, {
            __argnames__ : {value: ["string"]}
        });

        ρσ_modules.encodings.utf8_decoder_table = utf8_decoder_table;
        ρσ_modules.encodings._u8enc = _u8enc;
        ρσ_modules.encodings.utf8_encode = utf8_encode;
        ρσ_modules.encodings.base64encode = base64encode;
        ρσ_modules.encodings.base64decode = base64decode;
        ρσ_modules.encodings.urlsafe_b64encode = urlsafe_b64encode;
        ρσ_modules.encodings.urlsafe_b64decode = urlsafe_b64decode;
        ρσ_modules.encodings.hexlify = hexlify;
        ρσ_modules.encodings.unhexlify = unhexlify;
        ρσ_modules.encodings._from_code_point = _from_code_point;
        ρσ_modules.encodings.utf8_decode = utf8_decode;
        ρσ_modules.encodings.utf8_encode_js = utf8_encode_js;
        ρσ_modules.encodings.utf8_encode_native = utf8_encode_native;
    })();

    (function(){
        var __name__ = "uuid";
        var RFC_4122, random_bytes;
        var hexlify = ρσ_modules.encodings.hexlify;
        var urlsafe_b64decode = ρσ_modules.encodings.urlsafe_b64decode;
        var urlsafe_b64encode = ρσ_modules.encodings.urlsafe_b64encode;

        RFC_4122 = 1;
        if (typeof crypto === "object" && crypto.getRandomValues) {
            random_bytes = (function() {
                var ρσ_anonfunc = function (num) {
                    var ans;
                    ans = new Uint8Array(num || 16);
                    crypto.getRandomValues(ans);
                    return ans;
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["num"]}
                });
                return ρσ_anonfunc;
            })();
        } else {
            random_bytes = (function() {
                var ρσ_anonfunc = function (num) {
                    var ans, i;
                    ans = new Uint8Array(num || 16);
                    for (var ρσ_Index0 = 0; ρσ_Index0 < ans.length; ρσ_Index0++) {
                        i = ρσ_Index0;
                        ans[(typeof i === "number" && i < 0) ? ans.length + i : i] = Math.floor(Math.random() * 256);
                    }
                    return ans;
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["num"]}
                });
                return ρσ_anonfunc;
            })();
        }
        function uuid4_bytes() {
            var data;
            data = random_bytes();
            data[6] = 64 | data[6] & 15;
            data[8] = (data[8] >> 4 & 3 | 8) << 4 | data[8] & 15;
            return data;
        };

        function as_str() {
            var h;
            h = this.hex;
            return h.slice(0, 8) + "-" + h.slice(8, 12) + "-" + h.slice(12, 16) + "-" + h.slice(16, 20) + "-" + h.slice(20);
        };

        function uuid4() {
            var b;
            b = uuid4_bytes();
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["hex"] = hexlify(b);
                ρσ_d["bytes"] = b;
                ρσ_d["variant"] = RFC_4122;
                ρσ_d["version"] = 4;
                ρσ_d["__str__"] = as_str;
                ρσ_d["toString"] = as_str;
                return ρσ_d;
            }).call(this);
        };

        function num_to_string(numbers, alphabet, pad_to_length) {
            var ans, alphabet_len, x, number;
            ans = [];
            alphabet_len = alphabet.length;
            numbers = Array.prototype.slice.call(numbers);
            for (var i = 0; i < numbers.length - 1; i++) {
                x = divmod(numbers[(typeof i === "number" && i < 0) ? numbers.length + i : i], alphabet_len);
                numbers[(typeof i === "number" && i < 0) ? numbers.length + i : i] = x[0];
                numbers[ρσ_bound_index(i + 1, numbers)] += x[1];
            }
            for (var i = 0; i < numbers.length; i++) {
                number = numbers[(typeof i === "number" && i < 0) ? numbers.length + i : i];
                while (number) {
                    x = divmod(number, alphabet_len);
                    number = x[0];
                    ans.push(alphabet[ρσ_bound_index(x[1], alphabet)]);
                }
            }
            if (pad_to_length && pad_to_length > ans.length) {
                ans.push(alphabet[0].repeat(pad_to_length - ans.length));
            }
            return ans.join("");
        };
        if (!num_to_string.__argnames__) Object.defineProperties(num_to_string, {
            __argnames__ : {value: ["numbers", "alphabet", "pad_to_length"]}
        });

        function short_uuid() {
            return urlsafe_b64encode(random_bytes(), "");
        };

        function short_uuid4() {
            return urlsafe_b64encode(uuid4_bytes(), "");
        };

        function decode_short_uuid(val) {
            return urlsafe_b64decode(val + "==");
        };
        if (!decode_short_uuid.__argnames__) Object.defineProperties(decode_short_uuid, {
            __argnames__ : {value: ["val"]}
        });

        ρσ_modules.uuid.RFC_4122 = RFC_4122;
        ρσ_modules.uuid.random_bytes = random_bytes;
        ρσ_modules.uuid.uuid4_bytes = uuid4_bytes;
        ρσ_modules.uuid.as_str = as_str;
        ρσ_modules.uuid.uuid4 = uuid4;
        ρσ_modules.uuid.num_to_string = num_to_string;
        ρσ_modules.uuid.short_uuid = short_uuid;
        ρσ_modules.uuid.short_uuid4 = short_uuid4;
        ρσ_modules.uuid.decode_short_uuid = decode_short_uuid;
    })();

    (function(){
        var __name__ = "session";
        var defaults, is_local_setting, default_interface_data;
        var short_uuid = ρσ_modules.uuid.short_uuid;

        var ajax_send = ρσ_modules.ajax.ajax_send;

        defaults = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["view_mode"] = "cover_grid";
            ρσ_d["sort"] = "timestamp.desc";
            ρσ_d["last_sort_order"] = Object.create(null);
            ρσ_d["show_all_metadata"] = false;
            ρσ_d["copy_to_library_dupes"] = "add;overwrite";
            ρσ_d["partition_method"] = "first letter";
            ρσ_d["collapse_at"] = 25;
            ρσ_d["dont_collapse"] = "";
            ρσ_d["sort_tags_by"] = "name";
            ρσ_d["hide_empty_categories"] = "no";
            ρσ_d["and_search_terms"] = false;
            ρσ_d["margin_right"] = 20;
            ρσ_d["margin_left"] = 20;
            ρσ_d["margin_top"] = 20;
            ρσ_d["margin_bottom"] = 20;
            ρσ_d["read_mode"] = "paged";
            ρσ_d["cover_preserve_aspect_ratio"] = true;
            ρσ_d["max_text_height"] = 0;
            ρσ_d["max_text_width"] = 0;
            ρσ_d["columns_per_screen"] = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["portrait"] = 0;
                ρσ_d["landscape"] = 0;
                return ρσ_d;
            }).call(this);
            ρσ_d["user_stylesheet"] = "";
            ρσ_d["background_image"] = null;
            ρσ_d["background_image_style"] = "scaled";
            ρσ_d["background_image_fade"] = 0;
            ρσ_d["current_color_scheme"] = "white";
            ρσ_d["user_color_schemes"] = Object.create(null);
            ρσ_d["base_font_size"] = 16;
            ρσ_d["controls_help_shown_count"] = 0;
            ρσ_d["header"] = Object.create(null);
            ρσ_d["footer"] = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["right"] = "progress";
                return ρσ_d;
            }).call(this);
            ρσ_d["word_actions"] = [];
            ρσ_d["hide_tooltips"] = false;
            ρσ_d["keyboard_shortcuts"] = Object.create(null);
            ρσ_d["book_scrollbar"] = false;
            ρσ_d["standalone_font_settings"] = Object.create(null);
            ρσ_d["standalone_misc_settings"] = Object.create(null);
            ρσ_d["standalone_recently_opened"] = [];
            ρσ_d["paged_wheel_scrolls_by_screen"] = false;
            ρσ_d["paged_margin_clicks_scroll_by_screen"] = true;
            return ρσ_d;
        }).call(this);
        is_local_setting = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["margin_right"] = true;
            ρσ_d["margin_left"] = true;
            ρσ_d["margin_top"] = true;
            ρσ_d["margin_bottom"] = true;
            ρσ_d["read_mode"] = "paged";
            ρσ_d["max_text_height"] = true;
            ρσ_d["max_text_width"] = true;
            ρσ_d["columns_per_screen"] = true;
            ρσ_d["user_stylesheet"] = true;
            ρσ_d["background_image"] = true;
            ρσ_d["background_image_style"] = true;
            ρσ_d["background_image_fade"] = true;
            ρσ_d["current_color_scheme"] = true;
            ρσ_d["base_font_size"] = true;
            ρσ_d["controls_help_shown_count"] = true;
            ρσ_d["standalone_font_settings"] = true;
            ρσ_d["standalone_misc_settings"] = true;
            ρσ_d["standalone_recently_opened"] = true;
            return ρσ_d;
        }).call(this);
        function session_defaults() {
            return defaults;
        };

        function storage_available(which) {
            var storage, x;
            which = which || "localStorage";
            try {
                storage = window[(typeof which === "number" && which < 0) ? window.length + which : which];
                x = "__storage__test__";
                storage.setItem(x, x);
                storage.removeItem(x);
                return true;
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                {
                    return false;
                } 
            }
        };
        if (!storage_available.__argnames__) Object.defineProperties(storage_available, {
            __argnames__ : {value: ["which"]}
        });

        function FakeStorage() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            FakeStorage.prototype.__bind_methods__.call(this);
            FakeStorage.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(FakeStorage.prototype, "__bind_methods__", {value: function () {
            this.getItem = FakeStorage.prototype.getItem.bind(this);
            this.setItem = FakeStorage.prototype.setItem.bind(this);
            this.clear = FakeStorage.prototype.clear.bind(this);
        }});
        FakeStorage.prototype.__init__ = function __init__() {
            var self = this;
            self.data = Object.create(null);
        };
        FakeStorage.__argnames__ = FakeStorage.prototype.__init__.__argnames__;
        FakeStorage.__handles_kwarg_interpolation__ = FakeStorage.prototype.__init__.__handles_kwarg_interpolation__;
        FakeStorage.prototype.getItem = function getItem(key) {
            var self = this;
            return (ρσ_expr_temp = self.data)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
        };
        if (!FakeStorage.prototype.getItem.__argnames__) Object.defineProperties(FakeStorage.prototype.getItem, {
            __argnames__ : {value: ["key"]}
        });
        FakeStorage.prototype.setItem = function setItem(key, value) {
            var self = this;
            if (typeof value !== "string") {
                value = JSON.stringify(value);
            }
            (ρσ_expr_temp = self.data)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key] = value;
        };
        if (!FakeStorage.prototype.setItem.__argnames__) Object.defineProperties(FakeStorage.prototype.setItem, {
            __argnames__ : {value: ["key", "value"]}
        });
        FakeStorage.prototype.clear = function clear() {
            var self = this;
            self.data = Object.create(null);
        };
        FakeStorage.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        FakeStorage.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(FakeStorage.prototype, "__bases__", {value: []});

        function get_session_storage() {
            if (!get_session_storage.ans) {
                if (storage_available("localStorage")) {
                    get_session_storage.ans = window.localStorage;
                } else if (storage_available("sessionStorage")) {
                    get_session_storage.ans = window.sessionStorage;
                    console.error("localStorage not available using sessionStorage instead");
                } else {
                    get_session_storage.ans = new FakeStorage;
                    console.error("sessionStorage and localStorage not available using a temp cache instead");
                }
            }
            return get_session_storage.ans;
        };

        function SessionData() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            SessionData.prototype.__bind_methods__.call(this);
            SessionData.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(SessionData.prototype, "__bind_methods__", {value: function () {
            this.get = SessionData.prototype.get.bind(this);
            this.set = SessionData.prototype.set.bind(this);
            this.clear = SessionData.prototype.clear.bind(this);
        }});
        SessionData.prototype.__init__ = function __init__() {
            var self = this;
            var global_prefix = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.global_prefix : arguments[0];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "global_prefix")){
                global_prefix = ρσ_kwargs_obj.global_prefix;
            }
            self.global_prefix = global_prefix || "calibre-session-";
            self.storage = get_session_storage();
            self.overflow_storage = Object.create(null);
            self.has_overflow = false;
        };
        if (!SessionData.prototype.__init__.__defaults__) Object.defineProperties(SessionData.prototype.__init__, {
            __defaults__ : {value: {global_prefix:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["global_prefix"]}
        });
        SessionData.__argnames__ = SessionData.prototype.__init__.__argnames__;
        SessionData.__handles_kwarg_interpolation__ = SessionData.prototype.__init__.__handles_kwarg_interpolation__;
        SessionData.prototype.get = function get(key, defval) {
            var self = this;
            var ans;
            key = self.global_prefix + key;
            if (self.has_overflow) {
                ans = (ρσ_expr_temp = self.overflow_storage)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
                if (ans === undefined) {
                    ans = self.storage.getItem(key);
                }
            } else {
                ans = self.storage.getItem(key);
            }
            if (ans === undefined || ans === null) {
                if (defval === undefined) {
                    defval = null;
                }
                return defval;
            }
            return JSON.parse(ans);
        };
        if (!SessionData.prototype.get.__argnames__) Object.defineProperties(SessionData.prototype.get, {
            __argnames__ : {value: ["key", "defval"]}
        });
        SessionData.prototype.set = function set(key, value) {
            var self = this;
            key = self.global_prefix + key;
            if (value === null) {
                self.storage.removeItem(key);
                delete self.overflow_storage[key];
                return true;
            }
            value = JSON.stringify(value);
            try {
                self.storage.setItem(key, value);
                delete self.overflow_storage[key];
                return true;
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                {
                    (ρσ_expr_temp = self.overflow_storage)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key] = value;
                    self.has_overflow = true;
                    console.error("session storage has overflowed, using a temp cache instead");
                } 
            }
            return false;
        };
        if (!SessionData.prototype.set.__argnames__) Object.defineProperties(SessionData.prototype.set, {
            __argnames__ : {value: ["key", "value"]}
        });
        SessionData.prototype.clear = function clear() {
            var self = this;
            self.storage.clear();
            self.overflow_storage = Object.create(null);
            self.has_overflow = false;
        };
        SessionData.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        SessionData.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(SessionData.prototype, "__bases__", {value: []});

        function local_storage() {
            if (!local_storage.storage) {
                local_storage.storage = new SessionData("calibre-local-");
            }
            return local_storage.storage;
        };

        function get_device_uuid() {
            var s, ans;
            if (!get_device_uuid.ans) {
                s = local_storage();
                ans = s.get("device_uuid");
                if (!ans) {
                    ans = short_uuid();
                    s.set("device_uuid", ans);
                }
                get_device_uuid.ans = ans;
            }
            return get_device_uuid.ans;
        };

        default_interface_data = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["username"] = null;
            ρσ_d["output_format"] = "EPUB";
            ρσ_d["input_formats"] = (function(){
                var s = ρσ_set();
                s.jsset.add("EPUB");
                s.jsset.add("MOBI");
                s.jsset.add("AZW3");
                return s;
            })();
            ρσ_d["gui_pubdate_display_format"] = "MMM yyyy";
            ρσ_d["gui_timestamp_display_format"] = "dd MMM yyyy";
            ρσ_d["gui_last_modified_display_format"] = "dd MMM yyyy";
            ρσ_d["use_roman_numerals_for_series_number"] = true;
            ρσ_d["default_library_id"] = null;
            ρσ_d["default_book_list_mode"] = defaults.view_mode;
            ρσ_d["library_map"] = null;
            ρσ_d["search_the_net_urls"] = ρσ_list_decorate([]);
            ρσ_d["donate_link"] = "https://calibre-ebook.com/donate";
            ρσ_d["icon_map"] = Object.create(null);
            ρσ_d["icon_path"] = "";
            ρσ_d["custom_list_template"] = null;
            ρσ_d["num_per_page"] = 50;
            return ρσ_d;
        }).call(this);
        function get_interface_data() {
            var ans, k;
            if (!get_interface_data.storage) {
                get_interface_data.storage = new SessionData("calibre-interface-data-");
            }
            ans = get_interface_data.storage.get("current");
            if (ans) {
                ans.is_default = false;
            } else {
                ans = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["is_default"] = true;
                    return ρσ_d;
                }).call(this);
                var ρσ_Iter0 = ρσ_Iterable(default_interface_data);
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    k = ρσ_Iter0[ρσ_Index0];
                    ans[(typeof k === "number" && k < 0) ? ans.length + k : k] = default_interface_data[(typeof k === "number" && k < 0) ? default_interface_data.length + k : k];
                }
            }
            return ans;
        };

        function update_interface_data(new_data) {
            var data, nval, k;
            data = get_interface_data();
            var ρσ_Iter1 = ρσ_Iterable(default_interface_data);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                k = ρσ_Iter1[ρσ_Index1];
                nval = new_data[(typeof k === "number" && k < 0) ? new_data.length + k : k];
                if (k !== undefined) {
                    data[(typeof k === "number" && k < 0) ? data.length + k : k] = nval;
                }
            }
            if (!get_interface_data.storage) {
                get_interface_data.storage = new SessionData("calibre-interface-data-");
            }
            get_interface_data.storage.set("current", data);
        };
        if (!update_interface_data.__argnames__) Object.defineProperties(update_interface_data, {
            __argnames__ : {value: ["new_data"]}
        });

        function get_translations(newval) {
            if (!get_translations.storage) {
                get_translations.storage = new SessionData("calibre-translations-");
            }
            if ((typeof newval !== "undefined" && newval !== null)) {
                get_translations.storage.set("current", newval);
            } else {
                return get_translations.storage.get("current");
            }
        };
        if (!get_translations.__argnames__) Object.defineProperties(get_translations, {
            __argnames__ : {value: ["newval"]}
        });

        function UserSessionData() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            UserSessionData.prototype.__bind_methods__.call(this);
            UserSessionData.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(UserSessionData, SessionData);
        Object.defineProperty(UserSessionData.prototype, "__bind_methods__", {value: function () {
            SessionData.prototype.__bind_methods__ && SessionData.prototype.__bind_methods__.call(this);
            this.defval = UserSessionData.prototype.defval.bind(this);
            this.get = UserSessionData.prototype.get.bind(this);
            this.get_library_option = UserSessionData.prototype.get_library_option.bind(this);
            this.set = UserSessionData.prototype.set.bind(this);
            this.set_library_option = UserSessionData.prototype.set_library_option.bind(this);
            this.push_to_server = UserSessionData.prototype.push_to_server.bind(this);
        }});
        UserSessionData.prototype.__init__ = function __init__(username, saved_data) {
            var self = this;
            var key;
            self.prefix = (username || "") + "-";
            self.has_user = bool(username);
            self.username = username;
            SessionData.prototype.__init__.call(self);
            self.echo_changes = false;
            self.changes = Object.create(null);
            self.has_changes = false;
            self.push_timer_id = null;
            if (saved_data) {
                var ρσ_Iter2 = ρσ_Iterable(saved_data);
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    key = ρσ_Iter2[ρσ_Index2];
                    if (!is_local_setting[(typeof key === "number" && key < 0) ? is_local_setting.length + key : key]) {
                        self.set(key, saved_data[(typeof key === "number" && key < 0) ? saved_data.length + key : key]);
                    }
                }
            }
            self.echo_changes = true;
        };
        if (!UserSessionData.prototype.__init__.__argnames__) Object.defineProperties(UserSessionData.prototype.__init__, {
            __argnames__ : {value: ["username", "saved_data"]}
        });
        UserSessionData.__argnames__ = UserSessionData.prototype.__init__.__argnames__;
        UserSessionData.__handles_kwarg_interpolation__ = UserSessionData.prototype.__init__.__handles_kwarg_interpolation__;
        UserSessionData.prototype.defval = function defval(key) {
            var self = this;
            return defaults[(typeof key === "number" && key < 0) ? defaults.length + key : key];
        };
        if (!UserSessionData.prototype.defval.__argnames__) Object.defineProperties(UserSessionData.prototype.defval, {
            __argnames__ : {value: ["key"]}
        });
        UserSessionData.prototype.get = function get(key, defval) {
            var self = this;
            if (defval === undefined) {
                defval = defaults[(typeof key === "number" && key < 0) ? defaults.length + key : key];
            }
            return SessionData.prototype.get.call(self, self.prefix + key, defval);
        };
        if (!UserSessionData.prototype.get.__argnames__) Object.defineProperties(UserSessionData.prototype.get, {
            __argnames__ : {value: ["key", "defval"]}
        });
        UserSessionData.prototype.get_library_option = function get_library_option(library_id, key, defval) {
            var self = this;
            var lkey;
            if (!library_id) {
                return self.get(key, defval);
            }
            lkey = key + "-||-" + library_id;
            if (defval === undefined) {
                defval = defaults[(typeof key === "number" && key < 0) ? defaults.length + key : key];
            }
            return self.get(lkey, defval);
        };
        if (!UserSessionData.prototype.get_library_option.__argnames__) Object.defineProperties(UserSessionData.prototype.get_library_option, {
            __argnames__ : {value: ["library_id", "key", "defval"]}
        });
        UserSessionData.prototype.set = function set(key, value) {
            var self = this;
            if (self.echo_changes && self.has_user && !is_local_setting[(typeof key === "number" && key < 0) ? is_local_setting.length + key : key]) {
                (ρσ_expr_temp = self.changes)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key] = value;
                self.has_changes = true;
                if (self.push_timer_id !== null) {
                    clearTimeout(self.push_timer_id);
                }
                self.push_timer_id = setTimeout(self.push_to_server.bind(self), 1e3);
            }
            return SessionData.prototype.set.call(self, self.prefix + key, value);
        };
        if (!UserSessionData.prototype.set.__argnames__) Object.defineProperties(UserSessionData.prototype.set, {
            __argnames__ : {value: ["key", "value"]}
        });
        UserSessionData.prototype.set_library_option = function set_library_option(library_id, key, value) {
            var self = this;
            if (library_id) {
                key = key + "-||-" + library_id;
            }
            return self.set(key, value);
        };
        if (!UserSessionData.prototype.set_library_option.__argnames__) Object.defineProperties(UserSessionData.prototype.set_library_option, {
            __argnames__ : {value: ["library_id", "key", "value"]}
        });
        UserSessionData.prototype.push_to_server = function push_to_server() {
            var self = this;
            if (self.has_changes) {
                ajax_send("interface-data/set-session-data", self.changes, (function() {
                    var ρσ_anonfunc = function (end_type, xhr, ev) {
                        if (end_type !== "load") {
                            console.error("Failed to send session data to server: " + xhr.error_html);
                        }
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["end_type", "xhr", "ev"]}
                    });
                    return ρσ_anonfunc;
                })());
                self.changes = Object.create(null);
                self.has_changes = false;
            }
        };
        UserSessionData.prototype.__repr__ = function __repr__ () {
            if(SessionData.prototype.__repr__) return SessionData.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        UserSessionData.prototype.__str__ = function __str__ () {
            if(SessionData.prototype.__str__) return SessionData.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(UserSessionData.prototype, "__bases__", {value: [SessionData]});

        ρσ_modules.session.defaults = defaults;
        ρσ_modules.session.is_local_setting = is_local_setting;
        ρσ_modules.session.default_interface_data = default_interface_data;
        ρσ_modules.session.session_defaults = session_defaults;
        ρσ_modules.session.storage_available = storage_available;
        ρσ_modules.session.FakeStorage = FakeStorage;
        ρσ_modules.session.get_session_storage = get_session_storage;
        ρσ_modules.session.SessionData = SessionData;
        ρσ_modules.session.local_storage = local_storage;
        ρσ_modules.session.get_device_uuid = get_device_uuid;
        ρσ_modules.session.get_interface_data = get_interface_data;
        ρσ_modules.session.update_interface_data = update_interface_data;
        ρσ_modules.session.get_translations = get_translations;
        ρσ_modules.session.UserSessionData = UserSessionData;
    })();

    (function(){
        var __name__ = "book_list.theme";
        var DARK, LIGHT, LIGHT_DARKER, LIGHT_GRADIENT, DEFAULT_COLORS, DEFAULT_SIZES, DEFAULT_FONTS;
        DARK = "#39322B";
        LIGHT = "#F6F3E9";
        LIGHT_DARKER = "#b6b3a8";
        LIGHT_GRADIENT = "linear-gradient(to bottom, {}, {})".format(LIGHT, LIGHT_DARKER);
        DEFAULT_COLORS = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["window-background"] = LIGHT;
            ρσ_d["window-background2"] = LIGHT_DARKER;
            ρσ_d["window-foreground"] = DARK;
            ρσ_d["window-error-foreground"] = "red";
            ρσ_d["window-hover-foreground"] = "red";
            ρσ_d["link-foreground"] = "blue";
            ρσ_d["bar-background"] = DARK;
            ρσ_d["bar-foreground"] = LIGHT;
            ρσ_d["bar-highlight"] = "yellow";
            ρσ_d["heart"] = "#B92111";
            ρσ_d["list-hover-background"] = DARK;
            ρσ_d["list-hover-foreground"] = LIGHT;
            ρσ_d["tree-highlight-item"] = LIGHT_DARKER;
            ρσ_d["button-start"] = DARK;
            ρσ_d["button-end"] = "#49423B";
            ρσ_d["button-text"] = LIGHT;
            ρσ_d["dialog-background"] = LIGHT;
            ρσ_d["dialog-background-image"] = LIGHT_GRADIENT;
            ρσ_d["dialog-foreground"] = DARK;
            return ρσ_d;
        }).call(this);
        DEFAULT_SIZES = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["title"] = "1.4rem";
            ρσ_d["item-list-title"] = "1.1rem";
            ρσ_d["item-list-subtitle"] = "0.8rem";
            return ρσ_d;
        }).call(this);
        DEFAULT_FONTS = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["main"] = "sans-serif";
            return ρσ_d;
        }).call(this);
        function get_color(name) {
            return DEFAULT_COLORS[(typeof name === "number" && name < 0) ? DEFAULT_COLORS.length + name : name];
        };
        if (!get_color.__argnames__) Object.defineProperties(get_color, {
            __argnames__ : {value: ["name"]}
        });

        function color_to_rgba(color) {
            var cvs, ctx;
            cvs = document.createElement("canvas");
            cvs.height = 1;
            cvs.width = 1;
            ctx = cvs.getContext("2d");
            ctx.fillStyle = color;
            ctx.fillRect(0, 0, 1, 1);
            return ctx.getImageData(0, 0, 1, 1).data;
        };
        if (!color_to_rgba.__argnames__) Object.defineProperties(color_to_rgba, {
            __argnames__ : {value: ["color"]}
        });

        function cached_color_to_rgba(color) {
            var cache;
            cache = cached_color_to_rgba.cache;
            if (!cache[(typeof color === "number" && color < 0) ? cache.length + color : color]) {
                cache[(typeof color === "number" && color < 0) ? cache.length + color : color] = color_to_rgba(color);
            }
            return cache[(typeof color === "number" && color < 0) ? cache.length + color : color];
        };
        if (!cached_color_to_rgba.__argnames__) Object.defineProperties(cached_color_to_rgba, {
            __argnames__ : {value: ["color"]}
        });

        cached_color_to_rgba.cache = Object.create(null);
        function get_color_as_rgba(name) {
            var cache;
            cache = get_color_as_rgba.cache;
            if (!cache[(typeof name === "number" && name < 0) ? cache.length + name : name]) {
                cache[(typeof name === "number" && name < 0) ? cache.length + name : name] = color_to_rgba(get_color(name));
            }
            return cache[(typeof name === "number" && name < 0) ? cache.length + name : name];
        };
        if (!get_color_as_rgba.__argnames__) Object.defineProperties(get_color_as_rgba, {
            __argnames__ : {value: ["name"]}
        });

        get_color_as_rgba.cache = Object.create(null);
        function get_font_size(name) {
            return DEFAULT_SIZES[(typeof name === "number" && name < 0) ? DEFAULT_SIZES.length + name : name];
        };
        if (!get_font_size.__argnames__) Object.defineProperties(get_font_size, {
            __argnames__ : {value: ["name"]}
        });

        function get_font_family(name) {
            name = name || "main";
            return DEFAULT_FONTS[(typeof name === "number" && name < 0) ? DEFAULT_FONTS.length + name : name];
        };
        if (!get_font_family.__argnames__) Object.defineProperties(get_font_family, {
            __argnames__ : {value: ["name"]}
        });

        ρσ_modules["book_list.theme"].DARK = DARK;
        ρσ_modules["book_list.theme"].LIGHT = LIGHT;
        ρσ_modules["book_list.theme"].LIGHT_DARKER = LIGHT_DARKER;
        ρσ_modules["book_list.theme"].LIGHT_GRADIENT = LIGHT_GRADIENT;
        ρσ_modules["book_list.theme"].DEFAULT_COLORS = DEFAULT_COLORS;
        ρσ_modules["book_list.theme"].DEFAULT_SIZES = DEFAULT_SIZES;
        ρσ_modules["book_list.theme"].DEFAULT_FONTS = DEFAULT_FONTS;
        ρσ_modules["book_list.theme"].get_color = get_color;
        ρσ_modules["book_list.theme"].color_to_rgba = color_to_rgba;
        ρσ_modules["book_list.theme"].cached_color_to_rgba = cached_color_to_rgba;
        ρσ_modules["book_list.theme"].get_color_as_rgba = get_color_as_rgba;
        ρσ_modules["book_list.theme"].get_font_size = get_font_size;
        ρσ_modules["book_list.theme"].get_font_family = get_font_family;
    })();

    (function(){
        var __name__ = "utils";
        var is_ios, copy_hash, _roman, _data_ns;
        var encode_query = ρσ_modules.ajax.encode_query;

        var hexlify = ρσ_modules.encodings.hexlify;

        var get_font_family = ρσ_modules["book_list.theme"].get_font_family;

        is_ios = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
        function debounce() {
            var func = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var wait = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var immediate = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? debounce.__defaults__.immediate : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "immediate")){
                immediate = ρσ_kwargs_obj.immediate;
            }
            var timeout;
            timeout = null;
            return function debounce_inner() {
                var ρσ_unpack, context, args, call_now;
                ρσ_unpack = [this, arguments];
                context = ρσ_unpack[0];
                args = ρσ_unpack[1];
                function later() {
                    timeout = null;
                    if (!immediate) {
                        func.apply(context, args);
                    }
                };

                call_now = immediate && !timeout;
                window.clearTimeout(timeout);
                timeout = window.setTimeout(later, wait);
                if (call_now) {
                    func.apply(context, args);
                }
            };
        };
        if (!debounce.__defaults__) Object.defineProperties(debounce, {
            __defaults__ : {value: {immediate:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["func", "wait", "immediate"]}
        });

        if (Object.assign) {
            copy_hash = (function() {
                var ρσ_anonfunc = function (obj) {
                    return Object.assign(Object.create(null), obj);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["obj"]}
                });
                return ρσ_anonfunc;
            })();
        } else {
            copy_hash = (function() {
                var ρσ_anonfunc = function (obj) {
                    return (function() {
                        var ρσ_Iter = ρσ_Iterable(Object.keys(obj)), ρσ_Result = Object.create(null), k;
                        for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                            k = ρσ_Iter[ρσ_Index];
                            ρσ_Result[k] = (obj[(typeof k === "number" && k < 0) ? obj.length + k : k]);
                        }
                        return ρσ_Result;
                    })();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["obj"]}
                });
                return ρσ_anonfunc;
            })();
        }
        function parse_url_params() {
            var url = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? parse_url_params.__defaults__.url : arguments[0];
            var allow_multiple = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? parse_url_params.__defaults__.allow_multiple : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "url")){
                url = ρσ_kwargs_obj.url;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "allow_multiple")){
                allow_multiple = ρσ_kwargs_obj.allow_multiple;
            }
            var cache, qs, ans, q, pairs, ρσ_unpack, key, val, pair;
            cache = parse_url_params.cache;
            url = url || window.location.href;
            if (cache[(typeof url === "number" && url < 0) ? cache.length + url : url]) {
                return copy_hash((ρσ_expr_temp = parse_url_params.cache)[(typeof url === "number" && url < 0) ? ρσ_expr_temp.length + url : url]);
            }
            qs = url.indexOf("#");
            ans = Object.create(null);
            if (qs < 0) {
                cache[(typeof url === "number" && url < 0) ? cache.length + url : url] = ans;
                return copy_hash(ans);
            }
            q = url.slice(qs + 1, url.length + 1);
            if (!q) {
                cache[(typeof url === "number" && url < 0) ? cache.length + url : url] = ans;
                return copy_hash(ans);
            }
            pairs = q.replace(/\+/g, " ").split("&");
            var ρσ_Iter0 = ρσ_Iterable(pairs);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                pair = ρσ_Iter0[ρσ_Index0];
                ρσ_unpack = ρσ_eslice(pair.partition("="), 2);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                key = ρσ_unpack[0];
                val = ρσ_unpack[1];
                ρσ_unpack = [decodeURIComponent(key), decodeURIComponent(val)];
                key = ρσ_unpack[0];
                val = ρσ_unpack[1];
                if (allow_multiple) {
                    if (ans[(typeof key === "number" && key < 0) ? ans.length + key : key] === undefined) {
                        ans[(typeof key === "number" && key < 0) ? ans.length + key : key] = [];
                    }
                    ans[(typeof key === "number" && key < 0) ? ans.length + key : key].append(val);
                } else {
                    ans[(typeof key === "number" && key < 0) ? ans.length + key : key] = val;
                }
            }
            cache[(typeof url === "number" && url < 0) ? cache.length + url : url] = ans;
            return copy_hash(ans);
        };
        if (!parse_url_params.__defaults__) Object.defineProperties(parse_url_params, {
            __defaults__ : {value: {url:null, allow_multiple:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["url", "allow_multiple"]}
        });

        parse_url_params.cache = Object.create(null);
        function encode_query_with_path(query, path) {
            path = path || window.location.pathname;
            return path + encode_query(query, "#");
        };
        if (!encode_query_with_path.__argnames__) Object.defineProperties(encode_query_with_path, {
            __argnames__ : {value: ["query", "path"]}
        });

        function request_full_screen(elem) {
            var options;
            elem = elem || document.documentElement;
            options = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["navigationUI"] = "hide";
                return ρσ_d;
            }).call(this);
            if (elem.requestFullScreen) {
                elem.requestFullScreen(options);
            } else if (elem.webkitRequestFullScreen) {
                elem.webkitRequestFullScreen();
            } else if (elem.mozRequestFullScreen) {
                elem.mozRequestFullScreen();
            }
        };
        if (!request_full_screen.__argnames__) Object.defineProperties(request_full_screen, {
            __argnames__ : {value: ["elem"]}
        });

        function full_screen_element() {
            return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
        };

        _roman = list(zip(ρσ_list_decorate([ 1e3, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ]), ρσ_list_decorate([ "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" ])));
        function roman(num) {
            var result, ρσ_unpack, d, r;
            if (num <= 0 || num >= 4e3 || int(num) !== num) {
                return num + "";
            }
            result = ρσ_list_decorate([]);
            var ρσ_Iter1 = ρσ_Iterable(_roman);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                ρσ_unpack = ρσ_Iter1[ρσ_Index1];
                d = ρσ_unpack[0];
                r = ρσ_unpack[1];
                while (num >= d) {
                    result.append(r);
                    num -= d;
                }
            }
            return result.join("");
        };
        if (!roman.__argnames__) Object.defineProperties(roman, {
            __argnames__ : {value: ["num"]}
        });

        function fmt_sidx() {
            var val = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var fmt = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? fmt_sidx.__defaults__.fmt : arguments[1];
            var use_roman = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? fmt_sidx.__defaults__.use_roman : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "fmt")){
                fmt = ρσ_kwargs_obj.fmt;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "use_roman")){
                use_roman = ρσ_kwargs_obj.use_roman;
            }
            if (val === undefined || val === null || val === "") {
                return "1";
            }
            if (int(val) === float(val)) {
                if (use_roman) {
                    return roman(val);
                }
                return int(val) + "";
            }
            return fmt.format(float(val));
        };
        if (!fmt_sidx.__defaults__) Object.defineProperties(fmt_sidx, {
            __defaults__ : {value: {fmt:"{:.2f}", use_roman:true}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["val", "fmt", "use_roman"]}
        });

        function rating_to_stars() {
            var value = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var allow_half_stars = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? rating_to_stars.__defaults__.allow_half_stars : arguments[1];
            var star = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? rating_to_stars.__defaults__.star : arguments[2];
            var half = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? rating_to_stars.__defaults__.half : arguments[3];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "allow_half_stars")){
                allow_half_stars = ρσ_kwargs_obj.allow_half_stars;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "star")){
                star = ρσ_kwargs_obj.star;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "half")){
                half = ρσ_kwargs_obj.half;
            }
            var r, ans;
            r = max(0, min(int(value || 0), 10));
            if (allow_half_stars) {
                ans = star.repeat(Math.floor(r / 2));
                if (r % 2) {
                    ans += half;
                }
            } else {
                ans = star.repeat(int(r / 2));
            }
            return ans;
        };
        if (!rating_to_stars.__defaults__) Object.defineProperties(rating_to_stars, {
            __defaults__ : {value: {allow_half_stars:false, star:"★", half:"½"}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["value", "allow_half_stars", "star", "half"]}
        });

        function human_readable() {
            var size = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var sep = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? human_readable.__defaults__.sep : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "sep")){
                sep = ρσ_kwargs_obj.sep;
            }
            var ρσ_unpack, divisor, suffix, i, candidate, pos;
            ρσ_unpack = [1, "B"];
            divisor = ρσ_unpack[0];
            suffix = ρσ_unpack[1];
            var ρσ_Iter2 = ρσ_Iterable(enumerate(["B", "KB", "MB", "GB", "TB", "PB", "EB"]));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                ρσ_unpack = ρσ_Iter2[ρσ_Index2];
                i = ρσ_unpack[0];
                candidate = ρσ_unpack[1];
                if (size < 1 << (i + 1) * 10) {
                    ρσ_unpack = [1 << i * 10, candidate];
                    divisor = ρσ_unpack[0];
                    suffix = ρσ_unpack[1];
                    break;
                }
            }
            size = float(size) / divisor + "";
            pos = size.find(".");
            if (pos > -1) {
                size = size.slice(0, pos + 2);
            }
            if (size.endswith(".0")) {
                size = size.slice(0, -2);
            }
            return size + sep + suffix;
        };
        if (!human_readable.__defaults__) Object.defineProperties(human_readable, {
            __defaults__ : {value: {sep:" "}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["size", "sep"]}
        });

        function document_height() {
            var html;
            html = document.documentElement;
            return max(document.body.scrollHeight, document.body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
        };

        function document_width() {
            var html;
            html = document.documentElement;
            return max(document.body.scrollWidth, document.body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
        };

        _data_ns = null;
        function data_ns(name) {
            var rand;
            if (_data_ns === null) {
                rand = new Uint8Array(12);
                window.crypto.getRandomValues(rand);
                _data_ns = "data-" + hexlify(rand) + "-";
            }
            return _data_ns + name;
        };
        if (!data_ns.__argnames__) Object.defineProperties(data_ns, {
            __argnames__ : {value: ["name"]}
        });

        function get_elem_data(elem, name, defval) {
            var ans;
            ans = elem.getAttribute(data_ns(name));
            if (ans === null) {
                return (typeof defval !== "undefined" && defval !== null ? defval : null);
            }
            return JSON.parse(ans);
        };
        if (!get_elem_data.__argnames__) Object.defineProperties(get_elem_data, {
            __argnames__ : {value: ["elem", "name", "defval"]}
        });

        function set_elem_data(elem, name, val) {
            elem.setAttribute(data_ns(name), JSON.stringify(val));
        };
        if (!set_elem_data.__argnames__) Object.defineProperties(set_elem_data, {
            __argnames__ : {value: ["elem", "name", "val"]}
        });

        function viewport_to_document(x, y, doc) {
            var topdoc, frame, rect, win, ρσ_unpack, wx, wy;
            doc = doc || window.document;
            topdoc = window.document;
            while (doc !== topdoc) {
                frame = doc.defaultView.frameElement;
                rect = frame.getBoundingClientRect();
                x += rect.left;
                y += rect.top;
                doc = frame.ownerDocument;
            }
            win = doc.defaultView;
            ρσ_unpack = [win.pageXOffset, win.pageYOffset];
            wx = ρσ_unpack[0];
            wy = ρσ_unpack[1];
            x += wx;
            y += wy;
            return [x, y];
        };
        if (!viewport_to_document.__argnames__) Object.defineProperties(viewport_to_document, {
            __argnames__ : {value: ["x", "y", "doc"]}
        });

        function username_key(username) {
            return ((username) ? "u" : "n") + username;
        };
        if (!username_key.__argnames__) Object.defineProperties(username_key, {
            __argnames__ : {value: ["username"]}
        });

        function html_escape(text) {
            var repl;
            repl = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["&"] = "&amp;";
                ρσ_d["\""] = "&quot;";
                ρσ_d["<"] = "&lt;";
                ρσ_d[">"] = "&gt;";
                return ρσ_d;
            }).call(this);
            return String.prototype.replace.call(text, /[&"<>]/g, (function() {
                var ρσ_anonfunc = function (c) {
                    return repl[(typeof c === "number" && c < 0) ? repl.length + c : c];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["c"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!html_escape.__argnames__) Object.defineProperties(html_escape, {
            __argnames__ : {value: ["text"]}
        });

        function uniq(vals) {
            var ans, seen, x;
            ans = [];
            seen = Object.create(null);
            var ρσ_Iter3 = ρσ_Iterable(vals);
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                x = ρσ_Iter3[ρσ_Index3];
                if (!seen[(typeof x === "number" && x < 0) ? seen.length + x : x]) {
                    seen[(typeof x === "number" && x < 0) ? seen.length + x : x] = true;
                    ans.push(x);
                }
            }
            return ans;
        };
        if (!uniq.__argnames__) Object.defineProperties(uniq, {
            __argnames__ : {value: ["vals"]}
        });

        function conditional_timeout(elem_id, timeout, func) {
            function ct_impl() {
                var elem;
                elem = document.getElementById(elem_id);
                if (elem) {
                    func.call(elem);
                }
            };

            window.setTimeout(ct_impl, timeout);
        };
        if (!conditional_timeout.__argnames__) Object.defineProperties(conditional_timeout, {
            __argnames__ : {value: ["elem_id", "timeout", "func"]}
        });

        function simple_markup(html) {
            var div;
            html = (html || "").replace(/\uffff/g, "").replace(/<\s*(\/?[a-zA-Z1-6]+)[^>]*>/g, (function() {
                var ρσ_anonfunc = function (match, tag) {
                    var is_closing;
                    tag = tag.toLowerCase();
                    is_closing = (tag[0] === "/") ? "/" : "";
                    if (is_closing) {
                        tag = tag.slice(1);
                    }
                    if (simple_markup.allowed_tags.indexOf(tag) < 0) {
                        tag = "span";
                    }
                    return "\uffff" + ρσ_str.format("{}", is_closing) + "" + ρσ_str.format("{}", tag) + "\uffff";
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["match", "tag"]}
                });
                return ρσ_anonfunc;
            })());
            div = document.createElement("b");
            div.textContent = html;
            html = div.innerHTML;
            return html.replace(/\uffff(\/?[a-z1-6]+)\uffff/g, "<$1>");
        };
        if (!simple_markup.__argnames__) Object.defineProperties(simple_markup, {
            __argnames__ : {value: ["html"]}
        });

        simple_markup.allowed_tags = 'a|b|i|br|hr|h1|h2|h3|h4|h5|h6|div|em|strong|span'.split('|');
        function safe_set_inner_html(elem, html) {
            elem.innerHTML = simple_markup(html);
            return elem;
        };
        if (!safe_set_inner_html.__argnames__) Object.defineProperties(safe_set_inner_html, {
            __argnames__ : {value: ["elem", "html"]}
        });

        function sandboxed_html(html, style, sandbox) {
            var ans, css, final_html;
            ans = document.createElement("iframe");
            ans.setAttribute("sandbox", sandbox || "");
            ans.setAttribute("seamless", "");
            ans.style.width = "100%";
            html = html || "";
            css = "html, body { margin: 0; padding: 0; font-family: __FONT__ } p:first-child { margin-top: 0; padding-top: 0; -webkit-margin-before: 0 }".replace("__FONT__", get_font_family());
            css += style || "";
            final_html = "<!DOCTYPE html><html><head><style>" + ρσ_str.format("{}", css) + "</style></head><body>" + ρσ_str.format("{}", html) + "</body></html>";
            ans.srcdoc = final_html;
            return ans;
        };
        if (!sandboxed_html.__argnames__) Object.defineProperties(sandboxed_html, {
            __argnames__ : {value: ["html", "style", "sandbox"]}
        });

        if (__name__ === "__main__") {
            var strings = ρσ_modules.pythonize.strings;

            strings();
            print(rating_to_stars(3, true));
            print(fmt_sidx(10), fmt_sidx(1.2));
            print(list(map(human_readable, ρσ_list_decorate([ 1, 1024, 1025, 1024 * 1024 * 2.3 ]))));
        }
        ρσ_modules.utils.is_ios = is_ios;
        ρσ_modules.utils.copy_hash = copy_hash;
        ρσ_modules.utils._roman = _roman;
        ρσ_modules.utils._data_ns = _data_ns;
        ρσ_modules.utils.debounce = debounce;
        ρσ_modules.utils.parse_url_params = parse_url_params;
        ρσ_modules.utils.encode_query_with_path = encode_query_with_path;
        ρσ_modules.utils.request_full_screen = request_full_screen;
        ρσ_modules.utils.full_screen_element = full_screen_element;
        ρσ_modules.utils.roman = roman;
        ρσ_modules.utils.fmt_sidx = fmt_sidx;
        ρσ_modules.utils.rating_to_stars = rating_to_stars;
        ρσ_modules.utils.human_readable = human_readable;
        ρσ_modules.utils.document_height = document_height;
        ρσ_modules.utils.document_width = document_width;
        ρσ_modules.utils.data_ns = data_ns;
        ρσ_modules.utils.get_elem_data = get_elem_data;
        ρσ_modules.utils.set_elem_data = set_elem_data;
        ρσ_modules.utils.viewport_to_document = viewport_to_document;
        ρσ_modules.utils.username_key = username_key;
        ρσ_modules.utils.html_escape = html_escape;
        ρσ_modules.utils.uniq = uniq;
        ρσ_modules.utils.conditional_timeout = conditional_timeout;
        ρσ_modules.utils.simple_markup = simple_markup;
        ρσ_modules.utils.safe_set_inner_html = safe_set_inner_html;
        ρσ_modules.utils.sandboxed_html = sandboxed_html;
    })();

    (function(){
        var __name__ = "book_list.library_data";
        var load_status, library_data, thumbnail_cache;
        var _ = ρσ_modules.gettext.gettext;

        var absolute_path = ρσ_modules.ajax.absolute_path;
        var ajax = ρσ_modules.ajax.ajax;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var LRUCache = ρσ_modules.lru_cache.LRUCache;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        var parse_url_params = ρσ_modules.utils.parse_url_params;

        load_status = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["loading"] = true;
            ρσ_d["ok"] = false;
            ρσ_d["error_html"] = null;
            ρσ_d["current_fetch"] = null;
            ρσ_d["http_error_code"] = 0;
            return ρσ_d;
        }).call(this);
        library_data = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["metadata"] = Object.create(null);
            ρσ_d["previous_book_ids"] = [];
            ρσ_d["force_refresh"] = false;
            return ρσ_d;
        }).call(this);
        function current_library_id() {
            var q;
            q = parse_url_params();
            return q.library_id || get_interface_data().default_library_id;
        };

        function all_libraries() {
            var interface_data, lids;
            interface_data = get_interface_data();
            lids = ρσ_interpolate_kwargs.call(this, sorted, [interface_data.library_map].concat([ρσ_desugar_kwargs({key: (function() {
                var ρσ_anonfunc = function (x) {
                    return (ρσ_expr_temp = interface_data.library_map)[(typeof x === "number" && x < 0) ? ρσ_expr_temp.length + x : x];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["x"]}
                });
                return ρσ_anonfunc;
            })()})]));
            return (function() {
                var ρσ_Iter = ρσ_Iterable(lids), ρσ_Result = [], lid;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    lid = ρσ_Iter[ρσ_Index];
                    ρσ_Result.push([lid, (ρσ_expr_temp = interface_data.library_map)[(typeof lid === "number" && lid < 0) ? ρσ_expr_temp.length + lid : lid]]);
                }
                ρσ_Result = ρσ_list_constructor(ρσ_Result);
                return ρσ_Result;
            })();
        };

        function current_virtual_library() {
            var q;
            q = parse_url_params();
            return q.vl || "";
        };

        function last_virtual_library_for(library_id) {
            if (last_virtual_library_for.library_id === library_id) {
                return last_virtual_library_for.vl || "";
            }
            return "";
        };
        if (!last_virtual_library_for.__argnames__) Object.defineProperties(last_virtual_library_for, {
            __argnames__ : {value: ["library_id"]}
        });

        function url_books_query(sd) {
            var q, lid;
            q = parse_url_params();
            sd = sd || get_session_data();
            lid = current_library_id();
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["library_id"] = lid;
                ρσ_d["sort"] = q.sort || sd.get_library_option(lid, "sort");
                ρσ_d["search"] = q.search;
                ρσ_d["vl"] = current_virtual_library();
                return ρσ_d;
            }).call(this);
        };
        if (!url_books_query.__argnames__) Object.defineProperties(url_books_query, {
            __argnames__ : {value: ["sd"]}
        });

        function loaded_books_query() {
            var sr, sort;
            sr = library_data.search_result;
            sort = null;
            if (sr) {
                sort = (function() {
                    var ρσ_Iter = ρσ_Iterable(zip(sr.sort.split(","), sr.sort_order.split(","))), ρσ_Result = [], s, o;
                    for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                        ρσ_unpack = ρσ_Iter[ρσ_Index];
                        s = ρσ_unpack[0];
                        o = ρσ_unpack[1];
                        ρσ_Result.push(s + "." + o);
                    }
                    ρσ_Result = ρσ_list_constructor(ρσ_Result);
                    return ρσ_Result;
                })().join(",");
            }
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["library_id"] = (sr) ? sr.library_id : null;
                ρσ_d["sort"] = sort;
                ρσ_d["search"] = (typeof sr !== "undefined" && sr !== null ? sr : Object.create(null)).query;
                ρσ_d["vl"] = (typeof sr !== "undefined" && sr !== null ? sr : Object.create(null)).vl;
                return ρσ_d;
            }).call(this);
        };

        function current_sorted_field() {
            var sort, csf, csfo;
            if (library_data.search_result) {
                return [library_data.search_result.sort, library_data.search_result.sort_order];
            }
            sort = url_books_query().sort.partition(",")[0];
            csf = sort.partition(".")[0];
            csfo = sort.partition(".")[2] || "asc";
            return [csf, csfo];
        };

        function all_virtual_libraries() {
            return library_data.virtual_libraries || Object.create(null);
        };

        function update_library_data(data) {
            var key, sr;
            load_status.loading = false;
            load_status.ok = true;
            load_status.error_html = null;
            load_status.http_error_code = 0;
            library_data.previous_book_ids = [];
            if (library_data.for_library !== current_library_id()) {
                library_data.field_names = Object.create(null);
            }
            library_data.for_library = current_library_id();
            var ρσ_Iter0 = ρσ_Iterable("search_result sortable_fields field_metadata metadata virtual_libraries book_display_fields".split(" "));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                key = ρσ_Iter0[ρσ_Index0];
                library_data[(typeof key === "number" && key < 0) ? library_data.length + key : key] = data[(typeof key === "number" && key < 0) ? data.length + key : key];
            }
            sr = library_data.search_result;
            if (sr) {
                last_virtual_library_for.library_id = sr.library_id;
                last_virtual_library_for.vl = sr.vl;
            } else {
                last_virtual_library_for.library_id = null;
                last_virtual_library_for.vl = null;
            }
        };
        if (!update_library_data.__argnames__) Object.defineProperties(update_library_data, {
            __argnames__ : {value: ["data"]}
        });

        function add_more_books(data) {
            var key, sr;
            var ρσ_Iter1 = ρσ_Iterable(data.metadata);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                key = ρσ_Iter1[ρσ_Index1];
                (ρσ_expr_temp = library_data.metadata)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key] = (ρσ_expr_temp = data.metadata)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
            }
            sr = library_data.search_result;
            if (sr && sr.book_ids && sr.book_ids.length > 0) {
                library_data.previous_book_ids = library_data.previous_book_ids.concat(sr.book_ids);
            }
            library_data.search_result = data.search_result;
        };
        if (!add_more_books.__argnames__) Object.defineProperties(add_more_books, {
            __argnames__ : {value: ["data"]}
        });

        function current_book_ids() {
            return library_data.previous_book_ids.concat(library_data.search_result.book_ids);
        };

        function book_after(book_id, delta) {
            var ids, idx, new_idx;
            if (!delta) {
                delta = 1;
            }
            ids = current_book_ids();
            idx = ids.indexOf(int(book_id));
            if (idx > -1) {
                new_idx = (idx + ids.length + delta) % ids.length;
                return ids[(typeof new_idx === "number" && new_idx < 0) ? ids.length + new_idx : new_idx];
            }
        };
        if (!book_after.__argnames__) Object.defineProperties(book_after, {
            __argnames__ : {value: ["book_id", "delta"]}
        });

        function on_data_loaded(end_type, xhr, ev) {
            var data, sd, q;
            load_status.current_fetch = null;
            function bad_load(msg) {
                load_status.ok = false;
                load_status.loading = false;
                load_status.error_html = msg || xhr.error_html;
                load_status.http_error_code = xhr.status;
            };
            if (!bad_load.__argnames__) Object.defineProperties(bad_load, {
                __argnames__ : {value: ["msg"]}
            });

            if (end_type === "load") {
                data = JSON.parse(xhr.responseText);
                if (data.bad_restriction) {
                    bad_load(_("The library restriction for the current user is invalid: {}").format(data.bad_restriction));
                } else {
                    update_library_data(data);
                    sd = get_session_data();
                    q = loaded_books_query();
                    sd.set_library_option(q.library_id, "sort", q.sort);
                }
            } else if (end_type === "abort") {
            } else {
                bad_load();
            }
        };
        if (!on_data_loaded.__argnames__) Object.defineProperties(on_data_loaded, {
            __argnames__ : {value: ["end_type", "xhr", "ev"]}
        });

        function fetch_init_data() {
            var query;
            if (load_status.current_fetch) {
                load_status.current_fetch.abort();
            }
            query = url_books_query();
            load_status.loading = true;
            load_status.ok = false;
            load_status.error_html = null;
            load_status.http_error_code = 0;
            load_status.current_fetch = ρσ_interpolate_kwargs.call(this, ajax, ["interface-data/books-init", on_data_loaded].concat([ρσ_desugar_kwargs({query: query})]));
            load_status.current_fetch.send();
        };

        function field_names_received(library_id, field, proceed, end_type, xhr, event) {
            var names;
            if (library_id !== current_library_id()) {
                return;
            }
            if (end_type !== "load") {
                if (end_type !== "abort") {
                    proceed(false, field, xhr.error_html);
                }
                return;
            }
            try {
                names = JSON.parse(xhr.responseText);
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                if (ρσ_Exception instanceof Error) {
                    var traceback = ρσ_modules.traceback;

                    traceback.print_exc();
                    proceed(false, field, "Invalid JSON from server");
                    return;
                } else {
                    throw ρσ_Exception;
                }
            }
            (ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field] = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["loading"] = false;
                ρσ_d["loaded"] = true;
                ρσ_d["last_updated_at"] = Date.now();
                ρσ_d["names"] = names;
                return ρσ_d;
            }).call(this);
            proceed(true, field, names);
        };
        if (!field_names_received.__argnames__) Object.defineProperties(field_names_received, {
            __argnames__ : {value: ["library_id", "field", "proceed", "end_type", "xhr", "event"]}
        });

        function field_names_for(field, proceed) {
            if ((ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field] && (ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field].loaded) {
                proceed(true, field, (ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field].names);
            }
            if (!(ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field] || !(ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field].loading && Date.now() - (ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field].last_updated_at > 3600 * 1e3) {
                ρσ_interpolate_kwargs.call(this, ajax, ["interface-data/field-names/" + ρσ_str.format("{}", encodeURIComponent(field)) + "", field_names_received.bind(null, current_library_id(), field, proceed)].concat([ρσ_desugar_kwargs({query: (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["library_id"] = current_library_id();
                    return ρσ_d;
                }).call(this)})])).send();
                if (!(ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field]) {
                    (ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field] = (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["last_updated_at"] = 0;
                        ρσ_d["loaded"] = false;
                        ρσ_d["names"] = [];
                        return ρσ_d;
                    }).call(this);
                }
                (ρσ_expr_temp = library_data.field_names)[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field].loading = true;
            }
        };
        if (!field_names_for.__argnames__) Object.defineProperties(field_names_for, {
            __argnames__ : {value: ["field", "proceed"]}
        });

        function thumbnail_url(book_id, width, height) {
            return absolute_path("get/thumb/{}/{}?sz={}x{}".format(book_id, loaded_books_query().library_id, Math.ceil(width * window.devicePixelRatio), Math.ceil(height * window.devicePixelRatio)));
        };
        if (!thumbnail_url.__argnames__) Object.defineProperties(thumbnail_url, {
            __argnames__ : {value: ["book_id", "width", "height"]}
        });

        function cover_url(book_id) {
            var lid;
            lid = current_library_id();
            return absolute_path("get/cover/" + ρσ_str.format("{}", book_id) + "/" + ρσ_str.format("{}", lid) + "");
        };
        if (!cover_url.__argnames__) Object.defineProperties(cover_url, {
            __argnames__ : {value: ["book_id"]}
        });

        function download_url(book_id, fmt) {
            var lid;
            lid = current_library_id();
            return absolute_path("get/" + ρσ_str.format("{}", fmt) + "/" + ρσ_str.format("{}", book_id) + "/" + ρσ_str.format("{}", lid) + "");
        };
        if (!download_url.__argnames__) Object.defineProperties(download_url, {
            __argnames__ : {value: ["book_id", "fmt"]}
        });

        function book_metadata(book_id) {
            return (ρσ_expr_temp = library_data.metadata)[(typeof book_id === "number" && book_id < 0) ? ρσ_expr_temp.length + book_id : book_id];
        };
        if (!book_metadata.__argnames__) Object.defineProperties(book_metadata, {
            __argnames__ : {value: ["book_id"]}
        });

        function set_book_metadata(book_id, value) {
            (ρσ_expr_temp = library_data.metadata)[(typeof book_id === "number" && book_id < 0) ? ρσ_expr_temp.length + book_id : book_id] = value;
        };
        if (!set_book_metadata.__argnames__) Object.defineProperties(set_book_metadata, {
            __argnames__ : {value: ["book_id", "value"]}
        });

        function loaded_book_ids() {
            return Object.keys(library_data.metadata);
        };

        function force_refresh_on_next_load() {
            library_data.force_refresh = true;
        };

        function ensure_current_library_data() {
            var fr, matches, q, loaded, key;
            fr = library_data.force_refresh;
            library_data.force_refresh = false;
            function is_same(a, b) {
                if (!a && !b) {
                    return true;
                }
                return a === b;
            };
            if (!is_same.__argnames__) Object.defineProperties(is_same, {
                __argnames__ : {value: ["a", "b"]}
            });

            if (fr) {
                matches = false;
            } else {
                q = url_books_query();
                loaded = loaded_books_query();
                matches = true;
                var ρσ_Iter2 = ρσ_Iterable(q);
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    key = ρσ_Iter2[ρσ_Index2];
                    if (!is_same(q[(typeof key === "number" && key < 0) ? q.length + key : key], loaded[(typeof key === "number" && key < 0) ? loaded.length + key : key])) {
                        matches = false;
                        break;
                    }
                }
            }
            if (!matches) {
                fetch_init_data();
            }
        };

        function ThumbnailCache() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            ThumbnailCache.prototype.__bind_methods__.call(this);
            ThumbnailCache.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(ThumbnailCache.prototype, "__bind_methods__", {value: function () {
            this.get = ThumbnailCache.prototype.get.bind(this);
            this.load_finished = ThumbnailCache.prototype.load_finished.bind(this);
        }});
        ThumbnailCache.prototype.__init__ = function __init__() {
            var self = this;
            var size = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.size : arguments[0];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "size")){
                size = ρσ_kwargs_obj.size;
            }
            self.cache = new LRUCache(size);
        };
        if (!ThumbnailCache.prototype.__init__.__defaults__) Object.defineProperties(ThumbnailCache.prototype.__init__, {
            __defaults__ : {value: {size:250}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["size"]}
        });
        ThumbnailCache.__argnames__ = ThumbnailCache.prototype.__init__.__argnames__;
        ThumbnailCache.__handles_kwarg_interpolation__ = ThumbnailCache.prototype.__init__.__handles_kwarg_interpolation__;
        ThumbnailCache.prototype.get = function get(book_id, width, height, callback) {
            var self = this;
            var url, item, img;
            url = thumbnail_url(book_id, width, height);
            item = self.cache.get(url);
            if (!item) {
                img = new Image;
                item = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["img"] = img;
                    ρσ_d["load_type"] = null;
                    ρσ_d["callbacks"] = [callback];
                    return ρσ_d;
                }).call(this);
                img.onerror = self.load_finished.bind(null, item, "error");
                img.onload = self.load_finished.bind(null, item, "load");
                img.onabort = self.load_finished.bind(null, item, "abort");
                img.dataset.bookId = str(book_id);
                img.src = url;
                self.cache.set(url, item);
                return img;
            }
            if (item.load_type === null) {
                if (item.callbacks.indexOf(callback) < 0) {
                    item.callbacks.push(callback);
                }
            } else {
                callback(item.img, item.load_type);
            }
            return item.img;
        };
        if (!ThumbnailCache.prototype.get.__argnames__) Object.defineProperties(ThumbnailCache.prototype.get, {
            __argnames__ : {value: ["book_id", "width", "height", "callback"]}
        });
        ThumbnailCache.prototype.load_finished = function load_finished(item, load_type) {
            var self = this;
            var img, callback;
            item.load_type = load_type;
            img = item.img;
            img.onload = img.onerror = img.onabort = null;
            var ρσ_Iter3 = ρσ_Iterable(item.callbacks);
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                callback = ρσ_Iter3[ρσ_Index3];
                callback(img, load_type);
            }
        };
        if (!ThumbnailCache.prototype.load_finished.__argnames__) Object.defineProperties(ThumbnailCache.prototype.load_finished, {
            __argnames__ : {value: ["item", "load_type"]}
        });
        ThumbnailCache.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        ThumbnailCache.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(ThumbnailCache.prototype, "__bases__", {value: []});

        thumbnail_cache = new ThumbnailCache;
        function sync_library_books(library_id, to_sync, callback) {
            var url, which, lrmap, ρσ_unpack, book_id, fmt, key, last_read;
            url = "book-get-last-read-position/" + ρσ_str.format("{}", library_id) + "/";
            which = [];
            lrmap = Object.create(null);
            var ρσ_Iter4 = ρσ_Iterable(to_sync);
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                ρσ_unpack = ρσ_Iter4[ρσ_Index4];
                key = ρσ_unpack[0];
                last_read = ρσ_unpack[1];
                ρσ_unpack = key;
ρσ_unpack = ρσ_unpack_asarray(3, ρσ_unpack);
                library_id = ρσ_unpack[0];
                book_id = ρσ_unpack[1];
                fmt = ρσ_unpack[2];
                fmt = fmt.upper();
                which.push("" + ρσ_str.format("{}", book_id) + "-" + ρσ_str.format("{}", fmt) + "");
                lrmap[ρσ_bound_index("" + ρσ_str.format("{}", book_id) + ":" + ρσ_str.format("{}", fmt) + "", lrmap)] = last_read;
            }
            url += which.join("_");
            ajax(url, callback.bind(null, library_id, lrmap)).send();
        };
        if (!sync_library_books.__argnames__) Object.defineProperties(sync_library_books, {
            __argnames__ : {value: ["library_id", "to_sync", "callback"]}
        });

        ρσ_modules["book_list.library_data"].load_status = load_status;
        ρσ_modules["book_list.library_data"].library_data = library_data;
        ρσ_modules["book_list.library_data"].thumbnail_cache = thumbnail_cache;
        ρσ_modules["book_list.library_data"].current_library_id = current_library_id;
        ρσ_modules["book_list.library_data"].all_libraries = all_libraries;
        ρσ_modules["book_list.library_data"].current_virtual_library = current_virtual_library;
        ρσ_modules["book_list.library_data"].last_virtual_library_for = last_virtual_library_for;
        ρσ_modules["book_list.library_data"].url_books_query = url_books_query;
        ρσ_modules["book_list.library_data"].loaded_books_query = loaded_books_query;
        ρσ_modules["book_list.library_data"].current_sorted_field = current_sorted_field;
        ρσ_modules["book_list.library_data"].all_virtual_libraries = all_virtual_libraries;
        ρσ_modules["book_list.library_data"].update_library_data = update_library_data;
        ρσ_modules["book_list.library_data"].add_more_books = add_more_books;
        ρσ_modules["book_list.library_data"].current_book_ids = current_book_ids;
        ρσ_modules["book_list.library_data"].book_after = book_after;
        ρσ_modules["book_list.library_data"].on_data_loaded = on_data_loaded;
        ρσ_modules["book_list.library_data"].fetch_init_data = fetch_init_data;
        ρσ_modules["book_list.library_data"].field_names_received = field_names_received;
        ρσ_modules["book_list.library_data"].field_names_for = field_names_for;
        ρσ_modules["book_list.library_data"].thumbnail_url = thumbnail_url;
        ρσ_modules["book_list.library_data"].cover_url = cover_url;
        ρσ_modules["book_list.library_data"].download_url = download_url;
        ρσ_modules["book_list.library_data"].book_metadata = book_metadata;
        ρσ_modules["book_list.library_data"].set_book_metadata = set_book_metadata;
        ρσ_modules["book_list.library_data"].loaded_book_ids = loaded_book_ids;
        ρσ_modules["book_list.library_data"].force_refresh_on_next_load = force_refresh_on_next_load;
        ρσ_modules["book_list.library_data"].ensure_current_library_data = ensure_current_library_data;
        ρσ_modules["book_list.library_data"].ThumbnailCache = ThumbnailCache;
        ρσ_modules["book_list.library_data"].sync_library_books = sync_library_books;
    })();

    (function(){
        var __name__ = "dom";
        var simple_vendor_prefixes, extra_css;
        simple_vendor_prefixes = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["animation"] = ['webkit', 'moz', 'o'];
            ρσ_d["animation-name"] = ['webkit', 'moz', 'o'];
            ρσ_d["animation-duration"] = ['webkit', 'moz', 'o'];
            ρσ_d["animation-timing-function"] = ['webkit', 'moz', 'o'];
            ρσ_d["animation-delay"] = ['webkit', 'moz', 'o'];
            ρσ_d["animation-iteration-count"] = ['webkit', 'moz', 'o'];
            ρσ_d["animation-direction"] = ['webkit', 'moz', 'o'];
            ρσ_d["animation-fill-mode"] = ['webkit', 'moz', 'o'];
            ρσ_d["animation-play-state"] = ['webkit', 'moz', 'o'];
            ρσ_d["hyphens"] = ['webkit', 'moz', 'ms'];
            ρσ_d["transform"] = ['webkit', 'ms', 'moz', 'o'];
            ρσ_d["transform-origin"] = ['webkit', 'ms', 'moz', 'o'];
            ρσ_d["transition"] = ['webkit', 'moz', 'o'];
            ρσ_d["filter"] = ['webkit'];
            ρσ_d["user-select"] = ['webkit', 'moz', 'ms'];
            ρσ_d["break-before"] = ['webkit-column'];
            ρσ_d["break-after"] = ['webkit-column'];
            ρσ_d["break-inside"] = ['webkit-column'];
            ρσ_d["column-gap"] = ['webkit', 'moz'];
            ρσ_d["column-width"] = ['webkit', 'moz'];
            ρσ_d["column-rule"] = ['webkit', 'moz'];
            ρσ_d["column-fill"] = ['moz'];
            return ρσ_d;
        }).call(this);
        function set_css() {
            var elem = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var kw = arguments[arguments.length-1];
            if (kw === null || typeof kw !== "object" || kw [ρσ_kwargs_symbol] !== true) kw = {};
            var s, ρσ_unpack, name, val, prefixes, prefix, prop;
            if (typeof elem === "string") {
                elem = document.querySelector(elem);
            }
            s = elem.style;
            if (s) {
                var ρσ_Iter0 = ρσ_Iterable(kw);
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    prop = ρσ_Iter0[ρσ_Index0];
                    ρσ_unpack = [str.replace(str.rstrip(prop, "_"), "_", "-"), kw[(typeof prop === "number" && prop < 0) ? kw.length + prop : prop]];
                    name = ρσ_unpack[0];
                    val = ρσ_unpack[1];
                    if (val === null || val === undefined) {
                        s.removeProperty(name);
                    } else {
                        s.setProperty(name, val);
                    }
                    prefixes = simple_vendor_prefixes[(typeof name === "number" && name < 0) ? simple_vendor_prefixes.length + name : name];
                    if (prefixes) {
                        var ρσ_Iter1 = ρσ_Iterable(prefixes);
                        for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                            prefix = ρσ_Iter1[ρσ_Index1];
                            if (val === null || val === undefined) {
                                s.removeProperty("-" + prefix + "-" + name);
                            } else {
                                s.setProperty("-" + prefix + "-" + name, val);
                            }
                        }
                    }
                }
            }
            return elem;
        };
        if (!set_css.__handles_kwarg_interpolation__) Object.defineProperties(set_css, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["elem"]}
        });

        function build_rule() {
            var selector = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var kw = arguments[arguments.length-1];
            if (kw === null || typeof kw !== "object" || kw [ρσ_kwargs_symbol] !== true) kw = {};
            var ans, ρσ_unpack, name, val, prefixes, prefix, prop;
            ans = [selector + " { "];
            var ρσ_Iter2 = ρσ_Iterable(kw);
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                prop = ρσ_Iter2[ρσ_Index2];
                ρσ_unpack = [str.replace(str.rstrip(prop, "_"), "_", "-"), kw[(typeof prop === "number" && prop < 0) ? kw.length + prop : prop]];
                name = ρσ_unpack[0];
                val = ρσ_unpack[1];
                ans.push(name + ":" + val + ";");
                prefixes = simple_vendor_prefixes[(typeof name === "number" && name < 0) ? simple_vendor_prefixes.length + name : name];
                if (prefixes) {
                    var ρσ_Iter3 = ρσ_Iterable(prefixes);
                    for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                        prefix = ρσ_Iter3[ρσ_Index3];
                        ans.push("-" + prefix + "-" + name + ":" + val + ";");
                    }
                }
            }
            ans.push("}");
            return ans.join("\n") + "\n";
        };
        if (!build_rule.__handles_kwarg_interpolation__) Object.defineProperties(build_rule, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["selector"]}
        });

        function clear() {
            var node;
            for (var i = 0; i < arguments.length; i++) {
                node = arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i];
                while (node.firstChild) {
                    node.removeChild(node.firstChild);
                }
            }
        };

        function remove_all_attributes() {
            var node;
            for (var i = 0; i < arguments.length; i++) {
                node = arguments[(typeof i === "number" && i < 0) ? arguments.length + i : i];
                while (node.attributes.length > 0) {
                    node.removeAttribute(node.attributes[0].name);
                }
            }
        };

        function create_keyframes() {
            var animation_name = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var frames = Array.prototype.slice.call(arguments, 1);
            if (arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) frames.pop();
            var ans, frame, prefix;
            ans = [];
            var ρσ_Iter4 = ρσ_Iterable(ρσ_list_decorate([ "-webkit-", "-moz-", "-o-", "" ]));
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                prefix = ρσ_Iter4[ρσ_Index4];
                ans.push("@" + prefix + "keyframes " + animation_name + " {");
                var ρσ_Iter5 = ρσ_Iterable(frames);
                for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                    frame = ρσ_Iter5[ρσ_Index5];
                    ans.push(frame);
                }
                ans.push("}");
            }
            return ans.join("\n") + "\n";
        };
        if (!create_keyframes.__handles_kwarg_interpolation__) Object.defineProperties(create_keyframes, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["animation_name"]}
        });

        function change_icon_image(icon_element, new_name) {
            if (new_name) {
                icon_element.firstChild.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#icon-" + new_name);
            } else {
                icon_element.firstChild.removeAttributeNS("http://www.w3.org/1999/xlink", "xlink:href");
            }
        };
        if (!change_icon_image.__argnames__) Object.defineProperties(change_icon_image, {
            __argnames__ : {value: ["icon_element", "new_name"]}
        });

        function svgicon(name, height, width) {
            var ans, u;
            ans = document.createElementNS("http://www.w3.org/2000/svg", "svg");
            ans.setAttribute("style", "fill: currentColor; height: {}; width: {}; vertical-align: text-top".format((typeof height !== "undefined" && height !== null ? height : "2ex"), (typeof width !== "undefined" && width !== null ? width : "2ex")));
            u = document.createElementNS("http://www.w3.org/2000/svg", "use");
            ans.appendChild(u);
            if (name) {
                ans.firstChild.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#icon-" + name);
            }
            return ans;
        };
        if (!svgicon.__argnames__) Object.defineProperties(svgicon, {
            __argnames__ : {value: ["name", "height", "width"]}
        });

        function element(elem_id, child_selector) {
            var ans;
            ans = (elem_id) ? document.getElementById(elem_id) : document.body;
            if (child_selector) {
                ans = ans.querySelector(child_selector);
            }
            return ans;
        };
        if (!element.__argnames__) Object.defineProperties(element, {
            __argnames__ : {value: ["elem_id", "child_selector"]}
        });

        function selector() {
            var id_selector = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var args = Array.prototype.slice.call(arguments, 1);
            if (arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) args.pop();
            var ans, x;
            ans = "#" + id_selector;
            var ρσ_Iter6 = ρσ_Iterable(args);
            for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                x = ρσ_Iter6[ρσ_Index6];
                ans += " " + x;
            }
            return ans;
        };
        if (!selector.__handles_kwarg_interpolation__) Object.defineProperties(selector, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["id_selector"]}
        });

        function rule() {
            var id_selector = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var kw = arguments[arguments.length-1];
            if (kw === null || typeof kw !== "object" || kw [ρσ_kwargs_symbol] !== true) kw = {};
            var args = Array.prototype.slice.call(arguments, 1);
            if (kw !== null && typeof kw === "object" && kw [ρσ_kwargs_symbol] === true) args.pop();
            return ρσ_interpolate_kwargs.call(this, build_rule, [selector.apply(this, [id_selector].concat(args))].concat([ρσ_desugar_kwargs(kw)]));
        };
        if (!rule.__handles_kwarg_interpolation__) Object.defineProperties(rule, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["id_selector"]}
        });

        function unique_id(prefix) {
            var num;
            prefix = prefix || "auto-id";
            (ρσ_expr_temp = unique_id.counts)[(typeof prefix === "number" && prefix < 0) ? ρσ_expr_temp.length + prefix : prefix] = num = ((ρσ_expr_temp = unique_id.counts)[(typeof prefix === "number" && prefix < 0) ? ρσ_expr_temp.length + prefix : prefix] || 0) + 1;
            return prefix + "-" + num;
        };
        if (!unique_id.__argnames__) Object.defineProperties(unique_id, {
            __argnames__ : {value: ["prefix"]}
        });

        unique_id.counts = Object.create(null);
        function ensure_id(w, prefix) {
            var ans;
            ans = w.getAttribute("id");
            if (!ans) {
                ans = unique_id(prefix);
                w.setAttribute("id", ans);
            }
            return ans;
        };
        if (!ensure_id.__argnames__) Object.defineProperties(ensure_id, {
            __argnames__ : {value: ["w", "prefix"]}
        });

        extra_css = [];
        function add_extra_css(func) {
            extra_css.push(func());
        };
        if (!add_extra_css.__argnames__) Object.defineProperties(add_extra_css, {
            __argnames__ : {value: ["func"]}
        });

        function get_widget_css() {
            return extra_css.join("\n");
        };

        ρσ_modules.dom.simple_vendor_prefixes = simple_vendor_prefixes;
        ρσ_modules.dom.extra_css = extra_css;
        ρσ_modules.dom.set_css = set_css;
        ρσ_modules.dom.build_rule = build_rule;
        ρσ_modules.dom.clear = clear;
        ρσ_modules.dom.remove_all_attributes = remove_all_attributes;
        ρσ_modules.dom.create_keyframes = create_keyframes;
        ρσ_modules.dom.change_icon_image = change_icon_image;
        ρσ_modules.dom.svgicon = svgicon;
        ρσ_modules.dom.element = element;
        ρσ_modules.dom.selector = selector;
        ρσ_modules.dom.rule = rule;
        ρσ_modules.dom.unique_id = unique_id;
        ρσ_modules.dom.ensure_id = ensure_id;
        ρσ_modules.dom.add_extra_css = add_extra_css;
        ρσ_modules.dom.get_widget_css = get_widget_css;
    })();

    (function(){
        var __name__ = "popups";
        var MODAL_Z_INDEX, POPUP_Z_INDEX, popup_count, shown_popups, associated_widgets;
        var get_color = ρσ_modules["book_list.theme"].get_color;

        var set_css = ρσ_modules.dom.set_css;
        var ensure_id = ρσ_modules.dom.ensure_id;
        var clear = ρσ_modules.dom.clear;
        var build_rule = ρσ_modules.dom.build_rule;
        var add_extra_css = ρσ_modules.dom.add_extra_css;

        var E = ρσ_modules.elementmaker.E;

        MODAL_Z_INDEX = 1e3;
        POPUP_Z_INDEX = MODAL_Z_INDEX + 1;
        popup_count = 0;
        shown_popups = set();
        associated_widgets = Object.create(null);
        function element_contains_click_event(element, event) {
            var r;
            r = element.getBoundingClientRect();
            return r.left <= (ρσ_cond_temp = event.clientX) && ρσ_cond_temp <= r.right && r.top <= (ρσ_cond_temp = event.clientY) && ρσ_cond_temp <= r.bottom;
        };
        if (!element_contains_click_event.__argnames__) Object.defineProperties(element_contains_click_event, {
            __argnames__ : {value: ["element", "event"]}
        });

        function click_in_popup(event) {
            var popup, w, widget, wid, popup_id;
            var ρσ_Iter0 = ρσ_Iterable(shown_popups);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                popup_id = ρσ_Iter0[ρσ_Index0];
                popup = document.getElementById(popup_id);
                if (popup && element_contains_click_event(popup, event)) {
                    return true;
                }
                w = associated_widgets[(typeof popup_id === "number" && popup_id < 0) ? associated_widgets.length + popup_id : popup_id];
                if (w && w.length) {
                    var ρσ_Iter1 = ρσ_Iterable(w);
                    for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                        wid = ρσ_Iter1[ρσ_Index1];
                        widget = document.getElementById(wid);
                        if (widget && element_contains_click_event(widget, event)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        };
        if (!click_in_popup.__argnames__) Object.defineProperties(click_in_popup, {
            __argnames__ : {value: ["event"]}
        });

        function filter_clicks(event) {
            var popup_id;
            if (shown_popups.length) {
                if (!click_in_popup(event)) {
                    var ρσ_Iter2 = ρσ_Iterable(shown_popups);
                    for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                        popup_id = ρσ_Iter2[ρσ_Index2];
                        hide_popup(popup_id);
                    }
                    shown_popups.clear();
                    [event.stopPropagation(), event.preventDefault()];
                }
            }
        };
        if (!filter_clicks.__argnames__) Object.defineProperties(filter_clicks, {
            __argnames__ : {value: ["event"]}
        });

        function install_event_filters() {
            window.addEventListener("click", filter_clicks, true);
        };

        function create_popup(parent, idprefix) {
            var pid, div;
            popup_count += 1;
            pid = (idprefix || "popup") + "-" + popup_count;
            div = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: pid, style: "display: none; position: fixed; z-index: {}".format(POPUP_Z_INDEX)})]);
            parent = parent || document.body;
            parent.appendChild(div);
            return div;
        };
        if (!create_popup.__argnames__) Object.defineProperties(create_popup, {
            __argnames__ : {value: ["parent", "idprefix"]}
        });

        function show_popup() {
            var popup_id = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var associated_widget_ids = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_popup.__defaults__.associated_widget_ids : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "associated_widget_ids")){
                associated_widget_ids = ρσ_kwargs_obj.associated_widget_ids;
            }
            var elem;
            elem = document.getElementById(popup_id);
            elem.style.display = "block";
            shown_popups.add(popup_id);
            associated_widgets[(typeof popup_id === "number" && popup_id < 0) ? associated_widgets.length + popup_id : popup_id] = associated_widget_ids;
        };
        if (!show_popup.__defaults__) Object.defineProperties(show_popup, {
            __defaults__ : {value: {associated_widget_ids:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["popup_id", "associated_widget_ids"]}
        });

        function hide_popup(popup_id) {
            var elem;
            elem = document.getElementById(popup_id);
            if (elem) {
                elem.style.display = "none";
            }
            delete associated_widgets[popup_id];
        };
        if (!hide_popup.__argnames__) Object.defineProperties(hide_popup, {
            __argnames__ : {value: ["popup_id"]}
        });

        function CompletionPopup() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            CompletionPopup.prototype.__bind_methods__.call(this);
            CompletionPopup.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(CompletionPopup.prototype, "__bind_methods__", {value: function () {
            this.set_all_items = CompletionPopup.prototype.set_all_items.bind(this);
            this.add_associated_widget = CompletionPopup.prototype.add_associated_widget.bind(this);
            this.popup = CompletionPopup.prototype.popup.bind(this);
            this.show_at_widget = CompletionPopup.prototype.show_at_widget.bind(this);
            this.set_query = CompletionPopup.prototype.set_query.bind(this);
            this.hide = CompletionPopup.prototype.hide.bind(this);
            this.handle_keydown = CompletionPopup.prototype.handle_keydown.bind(this);
            this.move_highlight = CompletionPopup.prototype.move_highlight.bind(this);
            this._show_at = CompletionPopup.prototype._show_at.bind(this);
            this._apply_query = CompletionPopup.prototype._apply_query.bind(this);
            this._render_matches = CompletionPopup.prototype._render_matches.bind(this);
            this.onmouseenter = CompletionPopup.prototype.onmouseenter.bind(this);
            this.onclick = CompletionPopup.prototype.onclick.bind(this);
        }});
        Object.defineProperties(CompletionPopup.prototype,  {
            "container": {
                "enumerable": true, 
                "get": function container() {
                    var self = this;
                    return document.getElementById(self.container_id);
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "is_visible": {
                "enumerable": true, 
                "get": function is_visible() {
                    var self = this;
                    return self.container.style.display !== "none";
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "current_item": {
                "enumerable": true, 
                "get": function current_item() {
                    var self = this;
                    var c;
                    c = self.container;
                    return c.querySelector("div.{} > div.{}".format(self.CLASS, self.CURRENT_ITEM_CLASS));
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "current_text": {
                "enumerable": true, 
                "get": function current_text() {
                    var self = this;
                    return ρσ_exists.d(self.current_item).textContent;
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        CompletionPopup.prototype.__init__ = function __init__() {
            var self = this;
            var parent = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.parent : arguments[0];
            var max_items = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.max_items : arguments[1];
            var onselect = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.onselect : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "parent")){
                parent = ρσ_kwargs_obj.parent;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "max_items")){
                max_items = ρσ_kwargs_obj.max_items;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "onselect")){
                onselect = ρσ_kwargs_obj.onselect;
            }
            var c, ρσ_unpack;
            self.max_items = max_items;
            c = create_popup(parent);
            ρσ_interpolate_kwargs.call(this, set_css, [c].concat([ρσ_desugar_kwargs({user_select: "none"})]));
            self.container_id = c.getAttribute("id");
            self.onselect = onselect;
            self.items = ρσ_list_decorate([]);
            self.matches = ρσ_list_decorate([]);
            c.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: self.CLASS})]));
            self.associated_widget_ids = set();
            ρσ_unpack = ["", false];
            self.current_query = ρσ_unpack[0];
            self.is_upwards = ρσ_unpack[1];
            self.applied_query = self.current_query;
        };
        if (!CompletionPopup.prototype.__init__.__defaults__) Object.defineProperties(CompletionPopup.prototype.__init__, {
            __defaults__ : {value: {parent:null, max_items:25, onselect:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["parent", "max_items", "onselect"]}
        });
        CompletionPopup.__argnames__ = CompletionPopup.prototype.__init__.__argnames__;
        CompletionPopup.__handles_kwarg_interpolation__ = CompletionPopup.prototype.__init__.__handles_kwarg_interpolation__;
        CompletionPopup.prototype.set_all_items = function set_all_items(items) {
            var self = this;
            self.items = list(items);
            self.matches = ρσ_list_decorate([]);
            self.applied_query = "";
        };
        if (!CompletionPopup.prototype.set_all_items.__argnames__) Object.defineProperties(CompletionPopup.prototype.set_all_items, {
            __argnames__ : {value: ["items"]}
        });
        CompletionPopup.prototype.add_associated_widget = function add_associated_widget(widget_or_id) {
            var self = this;
            if (typeof widget_or_id !== "string") {
                widget_or_id = ensure_id(widget_or_id);
            }
            self.associated_widget_ids.add(widget_or_id);
        };
        if (!CompletionPopup.prototype.add_associated_widget.__argnames__) Object.defineProperties(CompletionPopup.prototype.add_associated_widget, {
            __argnames__ : {value: ["widget_or_id"]}
        });
        CompletionPopup.prototype.popup = function popup(widget) {
            var self = this;
            if (!self.is_visible) {
                if (self.applied_query !== self.current_query) {
                    self._apply_query();
                }
                if (self.matches.length) {
                    self.show_at_widget(widget);
                }
            }
        };
        if (!CompletionPopup.prototype.popup.__argnames__) Object.defineProperties(CompletionPopup.prototype.popup, {
            __argnames__ : {value: ["widget"]}
        });
        CompletionPopup.prototype.show_at_widget = function show_at_widget(w) {
            var self = this;
            var br, ρσ_unpack, y, upwards;
            br = w.getBoundingClientRect();
            if (br.top > window.innerHeight - br.bottom) {
                ρσ_unpack = [br.top, true];
                y = ρσ_unpack[0];
                upwards = ρσ_unpack[1];
            } else {
                ρσ_unpack = [br.bottom, false];
                y = ρσ_unpack[0];
                upwards = ρσ_unpack[1];
            }
            self._show_at(br.left, y, br.width, upwards);
        };
        if (!CompletionPopup.prototype.show_at_widget.__argnames__) Object.defineProperties(CompletionPopup.prototype.show_at_widget, {
            __argnames__ : {value: ["w"]}
        });
        CompletionPopup.prototype.set_query = function set_query(query) {
            var self = this;
            self.current_query = query;
            if (self.is_visible && self.applied_query !== self.current_query) {
                self._apply_query();
                if (!self.matches.length) {
                    self.hide();
                }
            }
        };
        if (!CompletionPopup.prototype.set_query.__argnames__) Object.defineProperties(CompletionPopup.prototype.set_query, {
            __argnames__ : {value: ["query"]}
        });
        CompletionPopup.prototype.hide = function hide() {
            var self = this;
            var c;
            self.container.style.display = "none";
            c = self.current_item;
            if (c) {
                c.classList.remove(self.CURRENT_ITEM_CLASS);
            }
        };
        CompletionPopup.prototype.handle_keydown = function handle_keydown(event) {
            var self = this;
            var key;
            key = event.key;
            if (key === "Escape" || key === "Esc") {
                self.hide();
                return true;
            }
            if (key === "ArrowUp") {
                self.move_highlight(true);
                return true;
            }
            if (key === "ArrowDown") {
                self.move_highlight(false);
                return true;
            }
            return false;
        };
        if (!CompletionPopup.prototype.handle_keydown.__argnames__) Object.defineProperties(CompletionPopup.prototype.handle_keydown, {
            __argnames__ : {value: ["event"]}
        });
        CompletionPopup.prototype.move_highlight = function move_highlight() {
            var self = this;
            var up = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? move_highlight.__defaults__.up : arguments[0];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "up")){
                up = ρσ_kwargs_obj.up;
            }
            var ans, div, c;
            if (up === null) {
                up = self.is_upwards;
            }
            ans = null;
            div = self.current_item;
            if (div) {
                div.classList.remove(self.CURRENT_ITEM_CLASS);
                ans = (up) ? div.previousSibling : div.nextSibling;
            }
            if (!ans) {
                c = self.container.firstChild;
                ans = (up) ? c.lastChild : c.firstChild;
            }
            if (ans) {
                ans.classList.add(self.CURRENT_ITEM_CLASS);
            }
        };
        if (!CompletionPopup.prototype.move_highlight.__defaults__) Object.defineProperties(CompletionPopup.prototype.move_highlight, {
            __defaults__ : {value: {up:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["up"]}
        });
        CompletionPopup.prototype._show_at = function _show_at(x, y, width, upwards) {
            var self = this;
            var c, cs;
            self.is_upwards = upwards;
            c = self.container;
            cs = c.style;
            cs.left = x + "px";
            cs.top = (upwards) ? "auto" : y + "px";
            cs.bottom = (upwards) ? window.innerHeight - y + "px" : "auto";
            cs.width = width + "px";
            cs.maxHeight = ((upwards) ? y : window.innerHeight - y) - 10 + "px";
            show_popup(self.container_id, self.associated_widget_ids);
        };
        if (!CompletionPopup.prototype._show_at.__argnames__) Object.defineProperties(CompletionPopup.prototype._show_at, {
            __argnames__ : {value: ["x", "y", "width", "upwards"]}
        });
        CompletionPopup.prototype._apply_query = function _apply_query() {
            var self = this;
            var q, i;
            q = self.current_query.toLowerCase();
            self.matches.clear();
            self.applied_query = self.current_query;
            if (!q) {
                self.matches = list(self.items.slice(0, self.max_items + 1));
            } else {
                i = 0;
                while (self.matches.length < self.max_items && i < self.items.length) {
                    if ((ρσ_expr_temp = self.items)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i].toLowerCase().startswith(q)) {
                        self.matches.push((ρσ_expr_temp = self.items)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i]);
                    }
                    i += 1;
                }
            }
            self._render_matches();
        };
        CompletionPopup.prototype._render_matches = function _render_matches() {
            var self = this;
            var c, items, m;
            c = self.container;
            clear(c.firstChild);
            items = self.matches;
            if (self.is_upwards) {
                items = reversed(items);
            }
            var ρσ_Iter3 = ρσ_Iterable(items);
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                m = ρσ_Iter3[ρσ_Index3];
                c.firstChild.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [m].concat([ρσ_desugar_kwargs({onmouseenter: self.onmouseenter, onclick: self.onclick})])));
            }
        };
        CompletionPopup.prototype.onmouseenter = function onmouseenter(event) {
            var self = this;
            var div;
            div = self.current_item;
            if (div) {
                div.classList.remove(self.CURRENT_ITEM_CLASS);
            }
            event.currentTarget.classList.add(self.CURRENT_ITEM_CLASS);
        };
        if (!CompletionPopup.prototype.onmouseenter.__argnames__) Object.defineProperties(CompletionPopup.prototype.onmouseenter, {
            __argnames__ : {value: ["event"]}
        });
        CompletionPopup.prototype.onclick = function onclick(event) {
            var self = this;
            self.onmouseenter(event);
            try {
                if (self.onselect) {
                    self.onselect(self.current_text);
                }
            } finally {
                self.hide();
            }
        };
        if (!CompletionPopup.prototype.onclick.__argnames__) Object.defineProperties(CompletionPopup.prototype.onclick, {
            __argnames__ : {value: ["event"]}
        });
        CompletionPopup.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        CompletionPopup.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(CompletionPopup.prototype, "__bases__", {value: []});
        CompletionPopup.prototype.CLASS = "popup-completion-items";
        CompletionPopup.prototype.CURRENT_ITEM_CLASS = "popup-completion-current-item";
        
        
        
        

        add_extra_css(function () {
            var sel, style;
            sel = "div." + CompletionPopup.prototype.CLASS;
            style = ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({overflow: "hidden", text_align: "left", background_color: get_color("window-background"), border: "solid 1px " + get_color("window-foreground")})]));
            sel += " > div";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({cursor: "pointer", padding: "1ex 1rem", white_space: "nowrap", text_overflow: "ellipsis", overflow: "hidden"})]));
            sel += "." + CompletionPopup.prototype.CURRENT_ITEM_CLASS;
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({color: get_color("list-hover-foreground"), background_color: get_color("list-hover-background")})]));
            return style;
        });
        ρσ_modules.popups.MODAL_Z_INDEX = MODAL_Z_INDEX;
        ρσ_modules.popups.POPUP_Z_INDEX = POPUP_Z_INDEX;
        ρσ_modules.popups.popup_count = popup_count;
        ρσ_modules.popups.shown_popups = shown_popups;
        ρσ_modules.popups.associated_widgets = associated_widgets;
        ρσ_modules.popups.element_contains_click_event = element_contains_click_event;
        ρσ_modules.popups.click_in_popup = click_in_popup;
        ρσ_modules.popups.filter_clicks = filter_clicks;
        ρσ_modules.popups.install_event_filters = install_event_filters;
        ρσ_modules.popups.create_popup = create_popup;
        ρσ_modules.popups.show_popup = show_popup;
        ρσ_modules.popups.hide_popup = hide_popup;
        ρσ_modules.popups.CompletionPopup = CompletionPopup;
    })();

    (function(){
        var __name__ = "modals";
        var modal_container, modal_count;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var ajax = ρσ_modules.ajax.ajax;
        var ajax_send = ρσ_modules.ajax.ajax_send;

        var get_color = ρσ_modules["book_list.theme"].get_color;
        var get_font_size = ρσ_modules["book_list.theme"].get_font_size;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var set_css = ρσ_modules.dom.set_css;
        var svgicon = ρσ_modules.dom.svgicon;

        var MODAL_Z_INDEX = ρσ_modules.popups.MODAL_Z_INDEX;

        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;

        modal_container = null;
        modal_count = 0;
        add_extra_css(function () {
            var style;
            style = ρσ_interpolate_kwargs.call(this, build_rule, ["#modal-container > div > a:hover"].concat([ρσ_desugar_kwargs({color: get_color("dialog-foreground") + " !important", background_color: get_color("dialog-background") + " !important"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, ["#modal-container a.dialog-simple-link:hover"].concat([ρσ_desugar_kwargs({color: "red !important"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [".button-box"].concat([ρσ_desugar_kwargs({display: "flex", justify_content: "flex-end", padding: "1rem 0rem", overflow: "hidden"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [".button-box .calibre-push-button"].concat([ρσ_desugar_kwargs({transform_origin: "right"})]));
            return style;
        });
        function Modal() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            Modal.prototype.__init__.apply(this, arguments);
        }
        Modal.prototype.__init__ = function __init__(create_func, on_close, show_close) {
            var self = this;
            var ρσ_unpack;
            ρσ_unpack = [create_func, on_close, show_close];
            self.create_func = ρσ_unpack[0];
            self.on_close = ρσ_unpack[1];
            self.show_close = ρσ_unpack[2];
            modal_count += 1;
            self.id = modal_count;
        };
        if (!Modal.prototype.__init__.__argnames__) Object.defineProperties(Modal.prototype.__init__, {
            __argnames__ : {value: ["create_func", "on_close", "show_close"]}
        });
        Modal.__argnames__ = Modal.prototype.__init__.__argnames__;
        Modal.__handles_kwarg_interpolation__ = Modal.prototype.__init__.__handles_kwarg_interpolation__;
        Modal.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        Modal.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(Modal.prototype, "__bases__", {value: []});

        function ModalContainer() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            ModalContainer.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperties(ModalContainer.prototype,  {
            "modal_container": {
                "enumerable": true, 
                "get": function modal_container() {
                    var self = this;
                    return document.getElementById("modal-container");
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        ModalContainer.prototype.__init__ = function __init__() {
            var self = this;
            var div;
            div = ρσ_interpolate_kwargs.call(E, E.div, [E.div(E.div(), ρσ_interpolate_kwargs.call(E, E.a, [svgicon("close")].concat([ρσ_desugar_kwargs({title: _("Close")})])))].concat([ρσ_desugar_kwargs({id: "modal-container", tabindex: "0"})]));
            div.addEventListener("keydown", self.onkeydown.bind(self), (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["passive"] = false;
                return ρσ_d;
            }).call(this));
            document.body.appendChild(div);
            ρσ_interpolate_kwargs.call(this, set_css, [div].concat([ρσ_desugar_kwargs({position: "fixed", top: "0", right: "0", bottom: "0", left: "0", background_color: "rgba(0,0,0,0.8)", z_index: MODAL_Z_INDEX + "", display: "none", text_align: "center", user_select: "none"})]));
            ρσ_interpolate_kwargs.call(this, set_css, [div.firstChild, get_color("dialog-background"), get_color("dialog-background2")].concat([ρσ_desugar_kwargs({position: "relative", display: "inline-block", top: "50vh", transform: "translateY(-50%)", min_width: "25vw", max_width: "70vw", border_radius: "1em", padding: "1em 2em", margin_right: "1em", margin_left: "1em", background: get_color("dialog-background"), color: get_color("dialog-foreground"), background_image: get_color("dialog-background-image")})]));
            ρσ_interpolate_kwargs.call(this, set_css, [div.firstChild.lastChild].concat([ρσ_desugar_kwargs({font_size: "1.5em", line_height: "100%", cursor: "pointer", position: "absolute", right: "-0.5em", top: "-0.5em", width: "1em", height: "1em", background_color: get_color("window-foreground"), color: get_color("window-background"), display: "inline-box", border_radius: "50%", padding: "4px", text_align: "center", box_shadow: "1px 1px 3px black"})]));
            div.firstChild.lastChild.addEventListener("click", (function() {
                var ρσ_anonfunc = function (event) {
                    [event.preventDefault(), self.close_current_modal(event)];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })());
            ρσ_interpolate_kwargs.call(this, set_css, [div.firstChild.firstChild].concat([ρσ_desugar_kwargs({user_select: "text", max_height: "60vh", overflow: "auto"})]));
            self.modals = [];
            self.current_modal = null;
            self.hide = self.close_current_modal.bind(self);
        };
        ModalContainer.__argnames__ = ModalContainer.prototype.__init__.__argnames__;
        ModalContainer.__handles_kwarg_interpolation__ = ModalContainer.prototype.__init__.__handles_kwarg_interpolation__;
        ModalContainer.prototype.show_modal = function show_modal() {
            var self = this;
            var create_func = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var on_close = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_modal.__defaults__.on_close : arguments[1];
            var show_close = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_modal.__defaults__.show_close : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_close")){
                on_close = ρσ_kwargs_obj.on_close;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "show_close")){
                show_close = ρσ_kwargs_obj.show_close;
            }
            var modal_id;
            self.modals.push(new Modal(create_func, on_close, show_close));
            modal_id = (ρσ_expr_temp = self.modals)[ρσ_expr_temp.length-1].id;
            self.update();
            self.modal_container.focus();
            return modal_id;
        };
        if (!ModalContainer.prototype.show_modal.__defaults__) Object.defineProperties(ModalContainer.prototype.show_modal, {
            __defaults__ : {value: {on_close:null, show_close:true}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["create_func", "on_close", "show_close"]}
        });
        ModalContainer.prototype.hide_modal = function hide_modal(modal_id) {
            var self = this;
            var doomed_modal, ρσ_unpack, i, modal;
            if (self.current_modal !== null && self.current_modal.id === modal_id) {
                self.clear_current_modal();
            } else {
                doomed_modal = null;
                var ρσ_Iter0 = ρσ_Iterable(enumerate(self.modals));
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    ρσ_unpack = ρσ_Iter0[ρσ_Index0];
                    i = ρσ_unpack[0];
                    modal = ρσ_unpack[1];
                    if (modal.id === modal_id) {
                        doomed_modal = i;
                        break;
                    }
                }
                if (doomed_modal !== null) {
                    self.modals.splice(doomed_modal, 1);
                }
            }
        };
        if (!ModalContainer.prototype.hide_modal.__argnames__) Object.defineProperties(ModalContainer.prototype.hide_modal, {
            __argnames__ : {value: ["modal_id"]}
        });
        ModalContainer.prototype.update = function update() {
            var self = this;
            var c;
            if (self.current_modal === null && self.modals) {
                self.current_modal = self.modals.shift();
                c = self.modal_container;
                try {
                    self.current_modal.create_func(c.firstChild.firstChild, self.hide);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        self.current_modal = null;
                        throw ρσ_Exception;
                    } 
                }
                if (c.style.display === "none") {
                    ρσ_interpolate_kwargs.call(this, set_css, [c].concat([ρσ_desugar_kwargs({display: "block"})]));
                }
                c.firstChild.lastChild.style.visibility = (self.current_modal.show_close) ? "visible" : "hidden";
            }
        };
        ModalContainer.prototype.clear_current_modal = function clear_current_modal() {
            var self = this;
            var c;
            self.current_modal = null;
            c = self.modal_container;
            clear(c.firstChild.firstChild);
            if (self.modals.length === 0) {
                ρσ_interpolate_kwargs.call(this, set_css, [c].concat([ρσ_desugar_kwargs({display: "none"})]));
            } else {
                self.update();
            }
        };
        ModalContainer.prototype.close_current_modal = function close_current_modal(event) {
            var self = this;
            if (self.current_modal !== null) {
                if (self.current_modal.on_close !== null && self.current_modal.on_close(event) === true) {
                    return;
                }
                self.clear_current_modal();
            }
        };
        if (!ModalContainer.prototype.close_current_modal.__argnames__) Object.defineProperties(ModalContainer.prototype.close_current_modal, {
            __argnames__ : {value: ["event"]}
        });
        ModalContainer.prototype.close_all_modals = function close_all_modals() {
            var self = this;
            while (self.current_modal !== null) {
                self.close_current_modal();
            }
        };
        ModalContainer.prototype.onkeydown = function onkeydown(event) {
            var self = this;
            if ((event.key === "Escape" || event.key === "Esc") && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey) {
                [event.preventDefault(), event.stopPropagation()];
                self.close_current_modal(event);
            }
        };
        if (!ModalContainer.prototype.onkeydown.__argnames__) Object.defineProperties(ModalContainer.prototype.onkeydown, {
            __argnames__ : {value: ["event"]}
        });
        ModalContainer.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        ModalContainer.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(ModalContainer.prototype, "__bases__", {value: []});
        

        function create_simple_dialog_markup(title, msg, details, icon, prefix, parent) {
            var show_details, is_html_msg, html_container, details_container;
            details = details || "";
            show_details = ρσ_interpolate_kwargs.call(E, E.a, [_("Show details")].concat([ρσ_desugar_kwargs({class_: "dialog-simple-link", style: "cursor:pointer; color: blue; padding-top:1em; display:inline-block; margin-left: auto"})]));
            show_details.addEventListener("click", function () {
                show_details.style.display = "none";
                show_details.nextSibling.style.display = "block";
            });
            is_html_msg = /<[a-zA-Z]/.test(msg);
            html_container = E.div();
            if (is_html_msg) {
                safe_set_inner_html(html_container, msg);
            }
            details_container = E.span();
            if (/<[a-zA-Z]/.test(details)) {
                safe_set_inner_html(details_container, details);
            } else {
                details_container.textContent = details;
            }
            if (prefix) {
                prefix = ρσ_interpolate_kwargs.call(E, E.span, [" " + prefix + " "].concat([ρσ_desugar_kwargs({style: "white-space:pre; font-variant: small-caps"})]));
            } else {
                prefix = " ";
            }
            parent.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.h2, [ρσ_interpolate_kwargs.call(E, E.span, [svgicon(icon)].concat([ρσ_desugar_kwargs({style: "color:red"})])), prefix, title].concat([ρσ_desugar_kwargs({style: "font-weight: bold; font-size: " + get_font_size("title")})])), ρσ_interpolate_kwargs.call(E, E.div, [(is_html_msg) ? html_container : msg].concat([ρσ_desugar_kwargs({style: "padding-top: 1em; margin-top: 1em; border-top: 1px solid currentColor"})])), ρσ_interpolate_kwargs.call(E, E.div, [show_details, ρσ_interpolate_kwargs.call(E, E.div, [details_container].concat([ρσ_desugar_kwargs({style: "display:none; white-space:pre-wrap; font-size: smaller; margin-top: 1em; border-top: solid 1px currentColor; padding-top: 1em"})]))].concat([ρσ_desugar_kwargs({style: "display: " + ((details) ? "block" : "none")})]))].concat([ρσ_desugar_kwargs({style: "max-width:40em; text-align: left"})])));
        };
        if (!create_simple_dialog_markup.__argnames__) Object.defineProperties(create_simple_dialog_markup, {
            __argnames__ : {value: ["title", "msg", "details", "icon", "prefix", "parent"]}
        });

        function create_simple_dialog() {
            var title = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var msg = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var details = ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[2];
            var icon = ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[3];
            var prefix = ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[4];
            var on_close = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_simple_dialog.__defaults__.on_close : arguments[5];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_close")){
                on_close = ρσ_kwargs_obj.on_close;
            }
            ρσ_interpolate_kwargs.call(this, show_modal, [create_simple_dialog_markup.bind(null, title, msg, details, icon, prefix)].concat([ρσ_desugar_kwargs({on_close: on_close})]));
        };
        if (!create_simple_dialog.__defaults__) Object.defineProperties(create_simple_dialog, {
            __defaults__ : {value: {on_close:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["title", "msg", "details", "icon", "prefix", "on_close"]}
        });

        function create_custom_dialog(title, content_generator_func) {
            function create_func(parent, close_modal) {
                var content_div;
                content_div = E.div();
                content_generator_func(content_div, close_modal);
                parent.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.h2, [title].concat([ρσ_desugar_kwargs({style: "font-weight: bold; font-size: " + get_font_size("title")})])), ρσ_interpolate_kwargs.call(E, E.div, [content_div].concat([ρσ_desugar_kwargs({style: "padding-top: 1em; margin-top: 1em; border-top: 1px solid currentColor"})]))].concat([ρσ_desugar_kwargs({style: "max-width:60em; text-align: left"})])));
            };
            if (!create_func.__argnames__) Object.defineProperties(create_func, {
                __argnames__ : {value: ["parent", "close_modal"]}
            });

            show_modal(create_func);
        };
        if (!create_custom_dialog.__argnames__) Object.defineProperties(create_custom_dialog, {
            __argnames__ : {value: ["title", "content_generator_func"]}
        });

        function create_progress_dialog(msg, on_close) {
            var ρσ_unpack, pbar, msg_div, show_close, modal_id;
            msg = msg || _("Loading, please wait...");
            ρσ_unpack = [ρσ_interpolate_kwargs.call(E, E.progress, [ρσ_desugar_kwargs({style: "display:inline-block"})]), 
            ρσ_interpolate_kwargs.call(E, E.div, [msg].concat([ρσ_desugar_kwargs({style: "text-align:center; padding-top:1ex"})]))];
            pbar = ρσ_unpack[0];
            msg_div = ρσ_unpack[1];
            function create_func(parent) {
                parent.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [pbar, msg_div].concat([ρσ_desugar_kwargs({style: "text-align: center"})])));
            };
            if (!create_func.__argnames__) Object.defineProperties(create_func, {
                __argnames__ : {value: ["parent"]}
            });

            show_close = on_close !== null;
            modal_id = show_modal(create_func, on_close, show_close);
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["close"] = function () {
                    modal_container.hide_modal(modal_id);
                };
                ρσ_d["update_progress"] = (function() {
                    var ρσ_anonfunc = function (amount, total) {
                        var ρσ_unpack;
                        ρσ_unpack = [total, amount];
                        pbar.max = ρσ_unpack[0];
                        pbar.value = ρσ_unpack[1];
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["amount", "total"]}
                    });
                    return ρσ_anonfunc;
                })();
                ρσ_d["set_msg"] = (function() {
                    var ρσ_anonfunc = function (new_msg) {
                        safe_set_inner_html(msg_div, new_msg);
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["new_msg"]}
                    });
                    return ρσ_anonfunc;
                })();
                return ρσ_d;
            }).call(this);
        };
        if (!create_progress_dialog.__argnames__) Object.defineProperties(create_progress_dialog, {
            __argnames__ : {value: ["msg", "on_close"]}
        });

        function create_modal_container() {
            if (modal_container === null) {
                modal_container = new ModalContainer;
            }
            return modal_container;
        };

        function show_modal() {
            var create_func = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var on_close = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_modal.__defaults__.on_close : arguments[1];
            var show_close = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_modal.__defaults__.show_close : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_close")){
                on_close = ρσ_kwargs_obj.on_close;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "show_close")){
                show_close = ρσ_kwargs_obj.show_close;
            }
            return modal_container.show_modal(create_func, on_close, show_close);
        };
        if (!show_modal.__defaults__) Object.defineProperties(show_modal, {
            __defaults__ : {value: {on_close:null, show_close:true}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["create_func", "on_close", "show_close"]}
        });

        function close_all_modals() {
            return modal_container.close_all_modals();
        };

        function error_dialog() {
            var title = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var msg = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var details = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? error_dialog.__defaults__.details : arguments[2];
            var on_close = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? error_dialog.__defaults__.on_close : arguments[3];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "details")){
                details = ρσ_kwargs_obj.details;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_close")){
                on_close = ρσ_kwargs_obj.on_close;
            }
            create_simple_dialog(title, msg, details, "bug", _("Error:"), on_close);
        };
        if (!error_dialog.__defaults__) Object.defineProperties(error_dialog, {
            __defaults__ : {value: {details:null, on_close:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["title", "msg", "details", "on_close"]}
        });

        function warning_dialog() {
            var title = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var msg = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var details = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? warning_dialog.__defaults__.details : arguments[2];
            var on_close = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? warning_dialog.__defaults__.on_close : arguments[3];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "details")){
                details = ρσ_kwargs_obj.details;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_close")){
                on_close = ρσ_kwargs_obj.on_close;
            }
            create_simple_dialog(title, msg, details, "warning", _("Warning:"), on_close);
        };
        if (!warning_dialog.__defaults__) Object.defineProperties(warning_dialog, {
            __defaults__ : {value: {details:null, on_close:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["title", "msg", "details", "on_close"]}
        });

        function progress_dialog() {
            var msg = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var on_close = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? progress_dialog.__defaults__.on_close : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_close")){
                on_close = ρσ_kwargs_obj.on_close;
            }
            return create_progress_dialog(msg, on_close);
        };
        if (!progress_dialog.__defaults__) Object.defineProperties(progress_dialog, {
            __defaults__ : {value: {on_close:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["msg", "on_close"]}
        });

        function ajax_progress_dialog() {
            var path = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var on_complete = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var msg = ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[2];
            var extra_data_for_callback = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? ajax_progress_dialog.__defaults__.extra_data_for_callback : arguments[3];
            var kw = arguments[arguments.length-1];
            if (kw === null || typeof kw !== "object" || kw [ρσ_kwargs_symbol] !== true) kw = {};
            if (Object.prototype.hasOwnProperty.call(kw, "extra_data_for_callback")){
                extra_data_for_callback = kw.extra_data_for_callback;
                delete kw.extra_data_for_callback;
            }
            var pd, xhr;
            pd = null;
            function on_complete_callback(event_type, xhr, ev) {
                pd.close();
                pd = undefined;
                return on_complete(event_type, xhr, ev);
            };
            if (!on_complete_callback.__argnames__) Object.defineProperties(on_complete_callback, {
                __argnames__ : {value: ["event_type", "xhr", "ev"]}
            });

            function on_progress_callback(loaded, total, xhr) {
                pd.update_progress(loaded, total);
            };
            if (!on_progress_callback.__argnames__) Object.defineProperties(on_progress_callback, {
                __argnames__ : {value: ["loaded", "total", "xhr"]}
            });

            xhr = ρσ_interpolate_kwargs.call(this, ajax, [path, on_complete_callback].concat([ρσ_desugar_kwargs(kw, {on_progress: on_progress_callback})]));
            xhr.extra_data_for_callback = extra_data_for_callback;
            pd = progress_dialog(msg, xhr.abort.bind(xhr));
            xhr.send();
            return [xhr, pd];
        };
        if (!ajax_progress_dialog.__defaults__) Object.defineProperties(ajax_progress_dialog, {
            __defaults__ : {value: {extra_data_for_callback:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["path", "on_complete", "msg", "extra_data_for_callback"]}
        });

        function ajax_send_progress_dialog() {
            var path = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var data = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var on_complete = ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[2];
            var msg = ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[3];
            var kw = arguments[arguments.length-1];
            if (kw === null || typeof kw !== "object" || kw [ρσ_kwargs_symbol] !== true) kw = {};
            var pd, xhr;
            pd = null;
            function on_complete_callback(event_type, xhr, ev) {
                pd.close();
                pd = undefined;
                return on_complete(event_type, xhr, ev);
            };
            if (!on_complete_callback.__argnames__) Object.defineProperties(on_complete_callback, {
                __argnames__ : {value: ["event_type", "xhr", "ev"]}
            });

            function on_progress_callback(loaded, total, xhr) {
                pd.update_progress(loaded, total);
            };
            if (!on_progress_callback.__argnames__) Object.defineProperties(on_progress_callback, {
                __argnames__ : {value: ["loaded", "total", "xhr"]}
            });

            xhr = ρσ_interpolate_kwargs.call(this, ajax_send, [path, data, on_complete_callback].concat([ρσ_desugar_kwargs(kw, {on_progress: on_progress_callback})]));
            pd = progress_dialog(msg, xhr.abort.bind(xhr));
            return [xhr, pd];
        };
        if (!ajax_send_progress_dialog.__handles_kwarg_interpolation__) Object.defineProperties(ajax_send_progress_dialog, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["path", "data", "on_complete", "msg"]}
        });

        ρσ_modules.modals.modal_container = modal_container;
        ρσ_modules.modals.modal_count = modal_count;
        ρσ_modules.modals.Modal = Modal;
        ρσ_modules.modals.ModalContainer = ModalContainer;
        ρσ_modules.modals.create_simple_dialog_markup = create_simple_dialog_markup;
        ρσ_modules.modals.create_simple_dialog = create_simple_dialog;
        ρσ_modules.modals.create_custom_dialog = create_custom_dialog;
        ρσ_modules.modals.create_progress_dialog = create_progress_dialog;
        ρσ_modules.modals.create_modal_container = create_modal_container;
        ρσ_modules.modals.show_modal = show_modal;
        ρσ_modules.modals.close_all_modals = close_all_modals;
        ρσ_modules.modals.error_dialog = error_dialog;
        ρσ_modules.modals.warning_dialog = warning_dialog;
        ρσ_modules.modals.progress_dialog = progress_dialog;
        ρσ_modules.modals.ajax_progress_dialog = ajax_progress_dialog;
        ρσ_modules.modals.ajax_send_progress_dialog = ajax_send_progress_dialog;
    })();

    (function(){
        var __name__ = "qt";
        var special_title, slots, to_python;
        special_title = "__webengine_messages_pending__";
        slots = Object.create(null);
        function ping(suffix) {
            document.title = special_title + suffix;
        };
        if (!ping.__argnames__) Object.defineProperties(ping, {
            __argnames__ : {value: ["suffix"]}
        });

        function signal() {
            var args;
            args = Array.from(arguments);
            to_python._queue_message((function(){
                var ρσ_d = Object.create(null);
                ρσ_d["type"] = "signal";
                ρσ_d["name"] = this;
                ρσ_d["args"] = args;
                return ρσ_d;
            }).call(this));
        };

        function ToPython() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            ToPython.prototype.__bind_methods__.call(this);
            ToPython.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(ToPython.prototype, "__bind_methods__", {value: function () {
            this._ping = ToPython.prototype._ping.bind(this);
            this._queue_message = ToPython.prototype._queue_message.bind(this);
            this._register_signals = ToPython.prototype._register_signals.bind(this);
            this._poll = ToPython.prototype._poll.bind(this);
            this._from_python = ToPython.prototype._from_python.bind(this);
        }});
        ToPython.prototype.__init__ = function __init__() {
            var self = this;
            self._messages = [];
            self._last_ping_value = 0;
            self._ping_timer_id = -1;
            self._queue_message((function(){
                var ρσ_d = Object.create(null);
                ρσ_d["type"] = "qt-ready";
                return ρσ_d;
            }).call(this));
        };
        ToPython.__argnames__ = ToPython.prototype.__init__.__argnames__;
        ToPython.__handles_kwarg_interpolation__ = ToPython.prototype.__init__.__handles_kwarg_interpolation__;
        ToPython.prototype._ping = function _ping() {
            var self = this;
            if (self._ping_timer_id < 0) {
                self._last_ping_value = (self._last_ping_value) ? 0 : 1;
                self._ping_timer_id = setTimeout(function () {
                    ping(self._last_ping_value);
                    self._ping_timer_id = -1;
                }, 0);
            }
        };
        ToPython.prototype._queue_message = function _queue_message(msg) {
            var self = this;
            self._messages.push(msg);
            self._ping();
        };
        if (!ToPython.prototype._queue_message.__argnames__) Object.defineProperties(ToPython.prototype._queue_message, {
            __argnames__ : {value: ["msg"]}
        });
        ToPython.prototype._register_signals = function _register_signals(signals) {
            var self = this;
            var signal_name;
            var ρσ_Iter0 = ρσ_Iterable(signals);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                signal_name = ρσ_Iter0[ρσ_Index0];
                self[(typeof signal_name === "number" && signal_name < 0) ? self.length + signal_name : signal_name] = signal.bind(signal_name);
            }
        };
        if (!ToPython.prototype._register_signals.__argnames__) Object.defineProperties(ToPython.prototype._register_signals, {
            __argnames__ : {value: ["signals"]}
        });
        ToPython.prototype._poll = function _poll() {
            var self = this;
            var ans;
            ans = self._messages;
            self._messages = [];
            return ans;
        };
        ToPython.prototype._from_python = function _from_python(name, args) {
            var self = this;
            var callback;
            callback = slots[(typeof name === "number" && name < 0) ? slots.length + name : name];
            if (callback) {
                callback.apply(null, args);
            } else {
                console.warn("Attempt to call non-existent python-to-js slot named: " + ρσ_str.format("{}", name) + "");
            }
        };
        if (!ToPython.prototype._from_python.__argnames__) Object.defineProperties(ToPython.prototype._from_python, {
            __argnames__ : {value: ["name", "args"]}
        });
        ToPython.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        ToPython.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(ToPython.prototype, "__bases__", {value: []});

        to_python = null;
        if (window === window.top) {
            window.python_comm = to_python = new ToPython;
        }
        function from_python(func) {
            slots[ρσ_bound_index(func.name, slots)] = func;
        };
        if (!from_python.__argnames__) Object.defineProperties(from_python, {
            __argnames__ : {value: ["func"]}
        });

        ρσ_modules.qt.special_title = special_title;
        ρσ_modules.qt.slots = slots;
        ρσ_modules.qt.to_python = to_python;
        ρσ_modules.qt.ping = ping;
        ρσ_modules.qt.signal = signal;
        ρσ_modules.qt.ToPython = ToPython;
        ρσ_modules.qt.from_python = from_python;
    })();

    (function(){
        var __name__ = "read_book";

    })();

    (function(){
        var __name__ = "book_list.constants";
        var book_list_container_id, read_book_container_id, INIT_ENDPOINT;
        book_list_container_id = "book-list-container";
        read_book_container_id = "read-book-container";
        INIT_ENDPOINT = "interface-data/init";
        function has_offline_support(val) {
            if (val !== undefined) {
                has_offline_support.ans = val;
            }
            return has_offline_support.ans;
        };
        if (!has_offline_support.__argnames__) Object.defineProperties(has_offline_support, {
            __argnames__ : {value: ["val"]}
        });

        ρσ_modules["book_list.constants"].book_list_container_id = book_list_container_id;
        ρσ_modules["book_list.constants"].read_book_container_id = read_book_container_id;
        ρσ_modules["book_list.constants"].INIT_ENDPOINT = INIT_ENDPOINT;
        ρσ_modules["book_list.constants"].has_offline_support = has_offline_support;
    })();

    (function(){
        var __name__ = "book_list.router";
        var mode_handlers, default_mode_handler, read_book_mode;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var book_list_container_id = ρσ_modules["book_list.constants"].book_list_container_id;
        var read_book_container_id = ρσ_modules["book_list.constants"].read_book_container_id;

        var get_current_query = ρσ_modules["book_list.globals"].get_current_query;

        var current_library_id = ρσ_modules["book_list.library_data"].current_library_id;

        var close_all_modals = ρσ_modules.modals.close_all_modals;

        var encode_query_with_path = ρσ_modules.utils.encode_query_with_path;
        var parse_url_params = ρσ_modules.utils.parse_url_params;
        var request_full_screen = ρσ_modules.utils.request_full_screen;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;

        mode_handlers = Object.create(null);
        default_mode_handler = null;
        read_book_mode = "read_book";
        function set_mode_handler(mode, handler) {
            mode_handlers[(typeof mode === "number" && mode < 0) ? mode_handlers.length + mode : mode] = handler;
        };
        if (!set_mode_handler.__argnames__) Object.defineProperties(set_mode_handler, {
            __argnames__ : {value: ["mode", "handler"]}
        });

        function set_default_mode_handler(handler) {
            default_mode_handler = handler;
        };
        if (!set_default_mode_handler.__argnames__) Object.defineProperties(set_default_mode_handler, {
            __argnames__ : {value: ["handler"]}
        });

        function update_window_title() {
            var subtitle = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var title = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? update_window_title.__defaults__.title : arguments[1];
            var sep = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? update_window_title.__defaults__.sep : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "title")){
                title = ρσ_kwargs_obj.title;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "sep")){
                sep = ρσ_kwargs_obj.sep;
            }
            var extra;
            extra = (subtitle) ? sep + subtitle : "";
            document.title = title + extra;
        };
        if (!update_window_title.__defaults__) Object.defineProperties(update_window_title, {
            __defaults__ : {value: {title:"calibre", sep:" :: "}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["subtitle", "title", "sep"]}
        });

        function is_reading_book() {
            var cq;
            cq = get_current_query();
            return cq && cq.mode === read_book_mode;
        };

        function apply_mode() {
            var divid, div;
            divid = (is_reading_book()) ? read_book_container_id : book_list_container_id;
            var ρσ_Iter0 = ρσ_Iterable(document.getElementById(divid).parentNode.childNodes);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                div = ρσ_Iter0[ρσ_Index0];
                div.style.display = (div.id === divid) ? "block" : "none";
            }
        };

        function apply_url(ignore_handler) {
            var data, handler;
            close_all_modals();
            data = parse_url_params();
            data.mode = data.mode || "book_list";
            get_current_query(data);
            apply_mode();
            if (!ignore_handler) {
                handler = mode_handlers[ρσ_bound_index(data.mode, mode_handlers)] || default_mode_handler;
                handler(data);
            }
        };
        if (!apply_url.__argnames__) Object.defineProperties(apply_url, {
            __argnames__ : {value: ["ignore_handler"]}
        });

        function open_book() {
            var book_id = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var fmt = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var library_id = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? open_book.__defaults__.library_id : arguments[2];
            var replace = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? open_book.__defaults__.replace : arguments[3];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "library_id")){
                library_id = ρσ_kwargs_obj.library_id;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "replace")){
                replace = ρσ_kwargs_obj.replace;
            }
            request_full_screen();
            library_id = library_id || current_library_id();
            ρσ_interpolate_kwargs.call(this, push_state, [(function(){
                var ρσ_d = Object.create(null);
                ρσ_d["book_id"] = book_id;
                ρσ_d["fmt"] = fmt;
                ρσ_d["library_id"] = library_id;
                return ρσ_d;
            }).call(this)].concat([ρσ_desugar_kwargs({replace: replace, mode: read_book_mode})]));
        };
        if (!open_book.__defaults__) Object.defineProperties(open_book, {
            __defaults__ : {value: {library_id:null, replace:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["book_id", "fmt", "library_id", "replace"]}
        });

        function push_state() {
            var query = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var replace = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? push_state.__defaults__.replace : arguments[1];
            var mode = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? push_state.__defaults__.mode : arguments[2];
            var call_handler = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? push_state.__defaults__.call_handler : arguments[3];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "replace")){
                replace = ρσ_kwargs_obj.replace;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "mode")){
                mode = ρσ_kwargs_obj.mode;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "call_handler")){
                call_handler = ρσ_kwargs_obj.call_handler;
            }
            var k;
            query = (function() {
                var ρσ_Iter = ρσ_Iterable(query), ρσ_Result = Object.create(null), k;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    k = ρσ_Iter[ρσ_Index];
                    if (query[(typeof k === "number" && k < 0) ? query.length + k : k]) {
                        ρσ_Result[k] = (query[(typeof k === "number" && k < 0) ? query.length + k : k]);
                    }
                }
                return ρσ_Result;
            })();
            if (mode !== "book_list") {
                query.mode = mode;
            }
            query = encode_query_with_path(query);
            if (replace) {
                window.history.replaceState(null, "", query);
            } else {
                window.history.pushState(null, "", query);
                push_state.history_count += 1;
            }
            apply_url(!call_handler);
        };
        if (!push_state.__defaults__) Object.defineProperties(push_state, {
            __defaults__ : {value: {replace:false, mode:"book_list", call_handler:true}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["query", "replace", "mode", "call_handler"]}
        });

        push_state.history_count = 0;
        function on_pop_state(ev) {
            push_state.history_count = max(0, push_state.history_count - 1);
            apply_url();
        };
        if (!on_pop_state.__argnames__) Object.defineProperties(on_pop_state, {
            __argnames__ : {value: ["ev"]}
        });

        function back() {
            var cq, handler, q;
            if (push_state.history_count > 0) {
                window.history.back();
            } else {
                cq = get_current_query();
                handler = mode_handlers[ρσ_bound_index(cq.mode, mode_handlers)] || default_mode_handler;
                if (handler.back_from_current) {
                    q = handler.back_from_current(cq);
                } else {
                    q = Object.create(null);
                }
                ρσ_interpolate_kwargs.call(this, push_state, [q].concat([ρσ_desugar_kwargs({replace: true})]));
            }
        };

        function home() {
            var replace = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? home.__defaults__.replace : arguments[0];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "replace")){
                replace = ρσ_kwargs_obj.replace;
            }
            push_state(Object.create(null));
        };
        if (!home.__defaults__) Object.defineProperties(home, {
            __defaults__ : {value: {replace:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["replace"]}
        });

        function report_a_load_failure(container, msg, error_html) {
            var err;
            err = E.div();
            safe_set_inner_html(err, error_html);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.div(msg), err, ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.a, [_("Go back to the home page")].concat([ρσ_desugar_kwargs({onclick: function () {
                ρσ_interpolate_kwargs.call(this, home, [ρσ_desugar_kwargs({replace: true})]);
            }, href: "javascript: void(0)", class_: "blue-link"})]))].concat([ρσ_desugar_kwargs({style: "margin-top: 1em; border-top: solid 1px currentColor; padding-top: 1ex;"})]))].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])));
        };
        if (!report_a_load_failure.__argnames__) Object.defineProperties(report_a_load_failure, {
            __argnames__ : {value: ["container", "msg", "error_html"]}
        });

        ρσ_modules["book_list.router"].mode_handlers = mode_handlers;
        ρσ_modules["book_list.router"].default_mode_handler = default_mode_handler;
        ρσ_modules["book_list.router"].read_book_mode = read_book_mode;
        ρσ_modules["book_list.router"].set_mode_handler = set_mode_handler;
        ρσ_modules["book_list.router"].set_default_mode_handler = set_default_mode_handler;
        ρσ_modules["book_list.router"].update_window_title = update_window_title;
        ρσ_modules["book_list.router"].is_reading_book = is_reading_book;
        ρσ_modules["book_list.router"].apply_mode = apply_mode;
        ρσ_modules["book_list.router"].apply_url = apply_url;
        ρσ_modules["book_list.router"].open_book = open_book;
        ρσ_modules["book_list.router"].push_state = push_state;
        ρσ_modules["book_list.router"].on_pop_state = on_pop_state;
        ρσ_modules["book_list.router"].back = back;
        ρσ_modules["book_list.router"].home = home;
        ρσ_modules["book_list.router"].report_a_load_failure = report_a_load_failure;
    })();

    (function(){
        var __name__ = "read_book.db";
        var DB_NAME, DB_VERSION;
        var base64decode = ρσ_modules.encodings.base64decode;
        var base64encode = ρσ_modules.encodings.base64encode;

        var _ = ρσ_modules.gettext.gettext;

        var is_reading_book = ρσ_modules["book_list.router"].is_reading_book;

        var error_dialog = ρσ_modules.modals.error_dialog;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        var username_key = ρσ_modules.utils.username_key;

        function upgrade_schema(idb, old_version, new_version, transaction) {
            var books_store;
            print("upgrade_schema:", old_version, new_version);
            if (!idb.objectStoreNames.contains("books")) {
                idb.createObjectStore("books", (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["keyPath"] = "key";
                    return ρσ_d;
                }).call(this));
            }
            if (!idb.objectStoreNames.contains("files")) {
                idb.createObjectStore("files");
            }
            if (!idb.objectStoreNames.contains("mathjax")) {
                idb.createObjectStore("mathjax");
            }
            if (!idb.objectStoreNames.contains("objects")) {
                idb.createObjectStore("objects", (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["keyPath"] = "key";
                    return ρσ_d;
                }).call(this));
            }
            books_store = transaction.objectStore("books");
            if (!books_store.indexNames.contains("recent_index")) {
                books_store.createIndex("recent_index", "recent_date");
            }
        };
        if (!upgrade_schema.__argnames__) Object.defineProperties(upgrade_schema, {
            __argnames__ : {value: ["idb", "old_version", "new_version", "transaction"]}
        });

        function file_store_name(book, name) {
            return book.book_hash + " " + name;
        };
        if (!file_store_name.__argnames__) Object.defineProperties(file_store_name, {
            __argnames__ : {value: ["book", "name"]}
        });

        function get_error_details(event) {
            var desc;
            desc = event.target;
            if (desc.error && desc.error.toString) {
                desc = desc.error.toString();
            } else if (desc.errorCode) {
                desc = desc.errorCode;
            } else if (desc.error) {
                desc = desc.error;
                if (desc.name === "QuotaExceededError") {
                    desc = _("Offline storage quota exceeded! Try deleting some stored books first.");
                } else if (desc.name) {
                    desc = desc.name;
                }
            }
            return desc || "Unknown Error";
        };
        if (!get_error_details.__argnames__) Object.defineProperties(get_error_details, {
            __argnames__ : {value: ["event"]}
        });

        function new_book(key, metadata) {
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["key"] = key;
                ρσ_d["is_complete"] = false;
                ρσ_d["stored_files"] = Object.create(null);
                ρσ_d["book_hash"] = null;
                ρσ_d["metadata"] = metadata;
                ρσ_d["manifest"] = null;
                ρσ_d["cover_width"] = null;
                ρσ_d["cover_height"] = null;
                ρσ_d["cover_name"] = null;
                ρσ_d["recent_date"] = new Date;
                ρσ_d["last_read"] = Object.create(null);
                ρσ_d["last_read_position"] = Object.create(null);
                return ρσ_d;
            }).call(this);
        };
        if (!new_book.__argnames__) Object.defineProperties(new_book, {
            __argnames__ : {value: ["key", "metadata"]}
        });

        DB_NAME = "calibre";
        DB_VERSION = 1;
        function DB() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            DB.prototype.__bind_methods__.call(this);
            DB.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(DB.prototype, "__bind_methods__", {value: function () {
            this.show_error = DB.prototype.show_error.bind(this);
            this.initialize_stage1 = DB.prototype.initialize_stage1.bind(this);
            this.initialize_stage2 = DB.prototype.initialize_stage2.bind(this);
            this.display_error = DB.prototype.display_error.bind(this);
            this.do_op = DB.prototype.do_op.bind(this);
            this.get_book = DB.prototype.get_book.bind(this);
            this.get_mathjax_info = DB.prototype.get_mathjax_info.bind(this);
            this.save_manifest = DB.prototype.save_manifest.bind(this);
            this.store_file = DB.prototype.store_file.bind(this);
            this.store_cover = DB.prototype.store_cover.bind(this);
            this.store_file_stage2 = DB.prototype.store_file_stage2.bind(this);
            this.clear_mathjax = DB.prototype.clear_mathjax.bind(this);
            this.store_mathjax_file = DB.prototype.store_mathjax_file.bind(this);
            this.finish_book = DB.prototype.finish_book.bind(this);
            this.finish_mathjax = DB.prototype.finish_mathjax.bind(this);
            this.update_last_read_time = DB.prototype.update_last_read_time.bind(this);
            this.update_last_read_data_from_key = DB.prototype.update_last_read_data_from_key.bind(this);
            this.get_file = DB.prototype.get_file.bind(this);
            this.get_mathjax_files = DB.prototype.get_mathjax_files.bind(this);
            this.get_recently_read_books = DB.prototype.get_recently_read_books.bind(this);
            this.has_book_matching = DB.prototype.has_book_matching.bind(this);
            this.delete_book = DB.prototype.delete_book.bind(this);
            this.delete_books_matching = DB.prototype.delete_books_matching.bind(this);
        }});
        DB.prototype.__init__ = function __init__(callback, show_read_book_error) {
            var self = this;
            self.initialized = false;
            self.is_ok = false;
            self.initialize_error_msg = null;
            self.callback = callback;
            self.show_read_book_error = show_read_book_error;
            self.initialize_stage1();
        };
        if (!DB.prototype.__init__.__argnames__) Object.defineProperties(DB.prototype.__init__, {
            __argnames__ : {value: ["callback", "show_read_book_error"]}
        });
        DB.__argnames__ = DB.prototype.__init__.__argnames__;
        DB.__handles_kwarg_interpolation__ = DB.prototype.__init__.__handles_kwarg_interpolation__;
        DB.prototype.show_error = function show_error(title, msg, det_msg) {
            var self = this;
            if (is_reading_book()) {
                self.show_read_book_error(title, msg, det_msg);
            } else {
                error_dialog(title, msg, det_msg);
            }
        };
        if (!DB.prototype.show_error.__argnames__) Object.defineProperties(DB.prototype.show_error, {
            __argnames__ : {value: ["title", "msg", "det_msg"]}
        });
        DB.prototype.initialize_stage1 = function initialize_stage1() {
            var self = this;
            var request;
            if (!window.indexedDB) {
                self.initialize_error_msg = _("Your browser does not support IndexedDB. Cannot read books. Consider using a modern browser, such as Chrome or Firefox.");
                self.initialized = true;
                window.setTimeout(self.callback, 0);
                return;
            }
            request = window.indexedDB.open(DB_NAME, DB_VERSION);
            request.onupgradeneeded = (function() {
                var ρσ_anonfunc = function (event) {
                    upgrade_schema(event.target.result, event.oldVersion, event.newVersion, event.target.transaction);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            request.onblocked = (function() {
                var ρσ_anonfunc = function (event) {
                    self.initialize_error_msg = _("Please close all other browser tabs with calibre open");
                    self.initialized = true;
                    console.log(event);
                    self.callback();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            request.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    self.initialize_error_msg = _("You must allow calibre to use IndexedDB storage in your browser to read books");
                    self.initialized = true;
                    console.log(event);
                    self.callback();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            request.onsuccess = (function() {
                var ρσ_anonfunc = function (event) {
                    var blob, idb, store, req;
                    blob = new Blob(ρσ_list_decorate([ "test" ]), (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["type"] = "text/plain";
                        return ρσ_d;
                    }).call(this));
                    idb = event.target.result;
                    store = idb.transaction(ρσ_list_decorate([ "files" ]), "readwrite").objectStore("files");
                    try {
                        req = store.put(blob, ":-test-blob-:");
                    } catch (ρσ_Exception) {
                        ρσ_last_exception = ρσ_Exception;
                        {
                            self.initialize_stage2(idb, false);
                            return;
                        } 
                    }
                    req.onsuccess = (function() {
                        var ρσ_anonfunc = function (event) {
                            self.initialize_stage2(idb, true);
                        };
                        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                            __argnames__ : {value: ["event"]}
                        });
                        return ρσ_anonfunc;
                    })();
                    req.onerror = (function() {
                        var ρσ_anonfunc = function (event) {
                            setTimeout(self.initialize_stage2.bind(null, idb, false), 0);
                        };
                        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                            __argnames__ : {value: ["event"]}
                        });
                        return ρσ_anonfunc;
                    })();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
        };
        DB.prototype.initialize_stage2 = function initialize_stage2(idb, supports_blobs) {
            var self = this;
            self.idb = idb;
            self.supports_blobs = supports_blobs;
            self.initialized = true;
            self.is_ok = true;
            if (!supports_blobs) {
                print("WARNING: browser does not support blob storage, calibre falling back to base64 encoding");
            }
            idb.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    self.display_error(null, event);
                    if (console.dir) {
                        console.dir(event);
                    } else {
                        console.log(event);
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            idb.onversionchange = (function() {
                var ρσ_anonfunc = function (event) {
                    idb.close();
                    self.show_error(_("Database upgraded!"), _("A newer version of calibre is available, please click the reload button in your browser."));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            self.callback();
        };
        if (!DB.prototype.initialize_stage2.__argnames__) Object.defineProperties(DB.prototype.initialize_stage2, {
            __argnames__ : {value: ["idb", "supports_blobs"]}
        });
        DB.prototype.display_error = function display_error(msg, event) {
            var self = this;
            if (event.already_displayed_by_calibre) {
                return;
            }
            event.already_displayed_by_calibre = true;
            msg = msg || _("There was an error while interacting with the database used to store books for offline reading. Click \"Show details\" for more information.");
            self.show_error(_("Cannot read book"), msg, get_error_details(event));
        };
        if (!DB.prototype.display_error.__argnames__) Object.defineProperties(DB.prototype.display_error, {
            __argnames__ : {value: ["msg", "event"]}
        });
        DB.prototype.do_op = function do_op() {
            var self = this;
            var stores = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var data = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var error_msg = ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[2];
            var proceed = ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[3];
            var op = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? do_op.__defaults__.op : arguments[4];
            var store = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? do_op.__defaults__.store : arguments[5];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "op")){
                op = ρσ_kwargs_obj.op;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "store")){
                store = ρσ_kwargs_obj.store;
            }
            var transaction, req;
            store = store || stores[0];
            if (op === "get") {
                transaction = self.idb.transaction(stores);
                try {
                    req = transaction.objectStore(store).get(data);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        if (/Edge\/\d+/.test(window.navigator.userAgent)) {
                            self.show_error(_("Cannot read book"), _("Reading of books is not supported on Microsoft Edge. Use a better browser such as Google Chrome or Mozilla Firefox"));
                            return;
                        }
                        throw ρσ_Exception;
                    } 
                }
                req.onsuccess = (function() {
                    var ρσ_anonfunc = function (event) {
                        proceed(req.result);
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["event"]}
                    });
                    return ρσ_anonfunc;
                })();
            } else if (op === "put") {
                transaction = self.idb.transaction(stores, "readwrite");
                req = transaction.objectStore(store).put(data);
                req.onsuccess = proceed;
            }
            req.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    self.display_error(error_msg, event);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!DB.prototype.do_op.__defaults__) Object.defineProperties(DB.prototype.do_op, {
            __defaults__ : {value: {op:"get", store:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["stores", "data", "error_msg", "proceed", "op", "store"]}
        });
        DB.prototype.get_book = function get_book(library_id, book_id, fmt, metadata, proceed) {
            var self = this;
            var key;
            fmt = fmt.toUpperCase();
            book_id = int(book_id);
            key = [library_id, book_id, fmt];
            self.do_op(ρσ_list_decorate([ "books" ]), key, _("Failed to read from the books database"), (function() {
                var ρσ_anonfunc = function (result) {
                    proceed(result || new_book(key, metadata));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["result"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!DB.prototype.get_book.__argnames__) Object.defineProperties(DB.prototype.get_book, {
            __argnames__ : {value: ["library_id", "book_id", "fmt", "metadata", "proceed"]}
        });
        DB.prototype.get_mathjax_info = function get_mathjax_info(proceed) {
            var self = this;
            self.do_op(ρσ_list_decorate([ "objects" ]), "mathjax-info", _("Failed to read from the objects database"), (function() {
                var ρσ_anonfunc = function (result) {
                    proceed(result || (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["key"] = "mathjax-info";
                        return ρσ_d;
                    }).call(this));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["result"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!DB.prototype.get_mathjax_info.__argnames__) Object.defineProperties(DB.prototype.get_mathjax_info, {
            __argnames__ : {value: ["proceed"]}
        });
        DB.prototype.save_manifest = function save_manifest(book, manifest, proceed) {
            var self = this;
            var newest_epoch, newest_pos, pos, unkey;
            book.manifest = manifest;
            book.metadata = manifest.metadata;
            book.book_hash = manifest.book_hash.hash;
            book.stored_files = Object.create(null);
            book.is_complete = false;
            if (get_interface_data().username) {
                newest_epoch = newest_pos = null;
                var ρσ_Iter0 = ρσ_Iterable(manifest.last_read_positions);
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    pos = ρσ_Iter0[ρσ_Index0];
                    if (newest_epoch === null || pos.epoch > newest_epoch) {
                        newest_epoch = pos.epoch;
                        newest_pos = pos.cfi;
                    }
                }
                if (newest_pos) {
                    unkey = username_key(get_interface_data().username);
                    (ρσ_expr_temp = book.last_read)[(typeof unkey === "number" && unkey < 0) ? ρσ_expr_temp.length + unkey : unkey] = new Date(newest_epoch * 1e3);
                    (ρσ_expr_temp = book.last_read_position)[(typeof unkey === "number" && unkey < 0) ? ρσ_expr_temp.length + unkey : unkey] = newest_pos;
                }
            }
            delete manifest["metadata"];
            delete manifest["last_read_positions"];
            ρσ_interpolate_kwargs.call(self, self.do_op, [ρσ_list_decorate([ "books" ]), book, _("Failed to write to the books database"), proceed].concat([ρσ_desugar_kwargs({op: "put"})]));
        };
        if (!DB.prototype.save_manifest.__argnames__) Object.defineProperties(DB.prototype.save_manifest, {
            __argnames__ : {value: ["book", "manifest", "proceed"]}
        });
        DB.prototype.store_file = function store_file(book, name, xhr, proceed, is_cover) {
            var self = this;
            var store_as_text, fname, needs_encoding;
            store_as_text = xhr.responseType === "text" || !xhr.responseType;
            fname = file_store_name(book, name);
            needs_encoding = !store_as_text && !self.supports_blobs;
            (ρσ_expr_temp = book.stored_files)[(typeof fname === "number" && fname < 0) ? ρσ_expr_temp.length + fname : fname] = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["encoded"] = needs_encoding;
                ρσ_d["mimetype"] = (ρσ_expr_temp = book.manifest.files)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name].mimetype;
                ρσ_d["store_as_text"] = store_as_text;
                return ρσ_d;
            }).call(this);
            if (is_cover) {
                self.store_cover(book, needs_encoding, xhr.response, name, fname, proceed);
            } else {
                self.store_file_stage2(needs_encoding, xhr.response, name, fname, proceed);
            }
        };
        if (!DB.prototype.store_file.__argnames__) Object.defineProperties(DB.prototype.store_file, {
            __argnames__ : {value: ["book", "name", "xhr", "proceed", "is_cover"]}
        });
        DB.prototype.store_cover = function store_cover(book, needs_encoding, data, name, fname, proceed) {
            var self = this;
            var blob, url, img, proceeded;
            blob = data;
            if (needs_encoding) {
                blob = new Blob(ρσ_list_decorate([ data ]), (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["type"] = "image/jpeg";
                    return ρσ_d;
                }).call(this));
            }
            url = window.URL.createObjectURL(blob);
            img = new Image;
            book.cover_name = name;
            proceeded = false;
            function done() {
                if (!proceeded) {
                    proceeded = true;
                    window.URL.revokeObjectURL(url);
                    self.store_file_stage2(needs_encoding, data, name, fname, proceed);
                }
            };

            img.onload = function () {
                book.cover_width = this.width;
                book.cover_height = this.height;
                done();
            };
            img.onerror = function () {
                print("WARNING: Failed to read dimensions of cover");
                done();
            };
            img.src = url;
        };
        if (!DB.prototype.store_cover.__argnames__) Object.defineProperties(DB.prototype.store_cover, {
            __argnames__ : {value: ["book", "needs_encoding", "data", "name", "fname", "proceed"]}
        });
        DB.prototype.store_file_stage2 = function store_file_stage2(needs_encoding, data, name, fname, proceed) {
            var self = this;
            var req;
            if (needs_encoding) {
                data = base64encode(new Uint8Array(data));
            }
            req = self.idb.transaction(ρσ_list_decorate([ "files" ]), "readwrite").objectStore("files").put(data, fname);
            req.onsuccess = (function() {
                var ρσ_anonfunc = function (event) {
                    proceed();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            req.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    proceed(_("Failed to store book data ({0}) with error: {1}").format(name, get_error_details(event)));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!DB.prototype.store_file_stage2.__argnames__) Object.defineProperties(DB.prototype.store_file_stage2, {
            __argnames__ : {value: ["needs_encoding", "data", "name", "fname", "proceed"]}
        });
        DB.prototype.clear_mathjax = function clear_mathjax(proceed) {
            var self = this;
            self.idb.transaction(ρσ_list_decorate([ "mathjax" ]), "readwrite").objectStore("mathjax").clear().onsuccess = proceed;
        };
        if (!DB.prototype.clear_mathjax.__argnames__) Object.defineProperties(DB.prototype.clear_mathjax, {
            __argnames__ : {value: ["proceed"]}
        });
        DB.prototype.store_mathjax_file = function store_mathjax_file(name, xhr, proceed) {
            var self = this;
            var data, req;
            data = xhr.response;
            if (!self.supports_blobs) {
                data = base64encode(new Uint8Array(data));
            }
            req = self.idb.transaction(ρσ_list_decorate([ "mathjax" ]), "readwrite").objectStore("mathjax").put(data, name);
            req.onsuccess = (function() {
                var ρσ_anonfunc = function (event) {
                    proceed();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            req.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    proceed(_("Failed to store mathjax file ({0}) with error: {1}").format(name, get_error_details(event)));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!DB.prototype.store_mathjax_file.__argnames__) Object.defineProperties(DB.prototype.store_mathjax_file, {
            __argnames__ : {value: ["name", "xhr", "proceed"]}
        });
        DB.prototype.finish_book = function finish_book(book, proceed) {
            var self = this;
            book.is_complete = true;
            ρσ_interpolate_kwargs.call(self, self.do_op, [ρσ_list_decorate([ "books" ]), book, _("Failed to write to the books database"), proceed].concat([ρσ_desugar_kwargs({op: "put"})]));
        };
        if (!DB.prototype.finish_book.__argnames__) Object.defineProperties(DB.prototype.finish_book, {
            __argnames__ : {value: ["book", "proceed"]}
        });
        DB.prototype.finish_mathjax = function finish_mathjax(mathjax_info, proceed) {
            var self = this;
            ρσ_interpolate_kwargs.call(self, self.do_op, [ρσ_list_decorate([ "objects" ]), mathjax_info, _("Failed to write to the objects database"), proceed].concat([ρσ_desugar_kwargs({op: "put"})]));
        };
        if (!DB.prototype.finish_mathjax.__argnames__) Object.defineProperties(DB.prototype.finish_mathjax, {
            __argnames__ : {value: ["mathjax_info", "proceed"]}
        });
        DB.prototype.update_last_read_time = function update_last_read_time(book) {
            var self = this;
            var unkey, now;
            unkey = username_key(get_interface_data().username);
            now = new Date;
            (ρσ_expr_temp = book.last_read)[(typeof unkey === "number" && unkey < 0) ? ρσ_expr_temp.length + unkey : unkey] = book.recent_date = now;
            ρσ_interpolate_kwargs.call(self, self.do_op, [ρσ_list_decorate([ "books" ]), book, _("Failed to write to the books database")].concat([ρσ_desugar_kwargs({op: "put"})]));
        };
        if (!DB.prototype.update_last_read_time.__argnames__) Object.defineProperties(DB.prototype.update_last_read_time, {
            __argnames__ : {value: ["book"]}
        });
        DB.prototype.update_last_read_data_from_key = function update_last_read_data_from_key(library_id, book_id, fmt, last_read, last_read_position) {
            var self = this;
            var unkey;
            unkey = username_key(get_interface_data().username);
            self.get_book(library_id, book_id, fmt, null, (function() {
                var ρσ_anonfunc = function (book) {
                    if (book.metadata) {
                        (ρσ_expr_temp = book.last_read)[(typeof unkey === "number" && unkey < 0) ? ρσ_expr_temp.length + unkey : unkey] = book.recent_date = last_read;
                        (ρσ_expr_temp = book.last_read_position)[(typeof unkey === "number" && unkey < 0) ? ρσ_expr_temp.length + unkey : unkey] = last_read_position;
                        ρσ_interpolate_kwargs.call(self, self.do_op, [ρσ_list_decorate([ "books" ]), book, _("Failed to write to the books database")].concat([ρσ_desugar_kwargs({op: "put"})]));
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["book"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!DB.prototype.update_last_read_data_from_key.__argnames__) Object.defineProperties(DB.prototype.update_last_read_data_from_key, {
            __argnames__ : {value: ["library_id", "book_id", "fmt", "last_read", "last_read_position"]}
        });
        DB.prototype.get_file = function get_file(book, name, proceed) {
            var self = this;
            var key, err;
            key = file_store_name(book, name);
            err = _("Failed to read the file {0} for the book {1} from the browser offline cache.").format(name, book.metadata.title);
            self.do_op(ρσ_list_decorate([ "files" ]), key, err, (function() {
                var ρσ_anonfunc = function (result) {
                    var bad, fdata, mt;
                    if (!result) {
                        bad = err + _(" This usually means the cache is close to full. Clear the browser cache from the browser settings.");
                        self.show_error(_("Cannot read file from book"), bad);
                        return;
                    }
                    fdata = (ρσ_expr_temp = book.stored_files)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
                    mt = fdata.mimetype || "application/octet-stream";
                    if (fdata.encoded) {
                        result = new Blob(ρσ_list_decorate([ base64decode(result) ]), (function(){
                            var ρσ_d = Object.create(null);
                            ρσ_d["type"] = mt;
                            return ρσ_d;
                        }).call(this));
                    }
                    proceed(result, name, mt, book);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["result"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!DB.prototype.get_file.__argnames__) Object.defineProperties(DB.prototype.get_file, {
            __argnames__ : {value: ["book", "name", "proceed"]}
        });
        DB.prototype.get_mathjax_files = function get_mathjax_files(proceed) {
            var self = this;
            var c, data;
            c = self.idb.transaction("mathjax").objectStore("mathjax").openCursor();
            c.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    var err;
                    err = _("Failed to read the MathJax files from the browser offline cache.");
                    self.display_error(err, event);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            data = Object.create(null);
            c.onsuccess = (function() {
                var ρσ_anonfunc = function (event) {
                    var cursor, ρσ_unpack, name, result, mt;
                    cursor = event.target.result;
                    if (cursor) {
                        ρσ_unpack = [cursor.key, cursor.value];
                        name = ρσ_unpack[0];
                        result = ρσ_unpack[1];
                        if (!(ρσ_instanceof(result, Blob))) {
                            mt = (name.endswith(".woff")) ? "application/x-font-woff" : "text/javascript";
                            result = new Blob(ρσ_list_decorate([ base64decode(result) ]), (function(){
                                var ρσ_d = Object.create(null);
                                ρσ_d["type"] = mt;
                                return ρσ_d;
                            }).call(this));
                        }
                        data[(typeof name === "number" && name < 0) ? data.length + name : name] = result;
                        cursor.continue();
                    } else {
                        proceed(data);
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!DB.prototype.get_mathjax_files.__argnames__) Object.defineProperties(DB.prototype.get_mathjax_files, {
            __argnames__ : {value: ["proceed"]}
        });
        DB.prototype.get_recently_read_books = function get_recently_read_books(proceed, limit) {
            var self = this;
            var c, books;
            limit = limit || 3;
            c = self.idb.transaction(ρσ_list_decorate([ "books" ]), "readonly").objectStore("books").index("recent_index").openCursor(null, "prev");
            books = [];
            c.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    var err;
                    err = _("Failed to read recent books from local storage");
                    self.display_error(err, event);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            c.onsuccess = (function() {
                var ρσ_anonfunc = function (ev) {
                    var cursor;
                    cursor = ev.target.result;
                    if (cursor) {
                        books.push(cursor.value);
                    }
                    if (books.length >= limit || !cursor) {
                        proceed(books);
                        return;
                    }
                    if (cursor) {
                        cursor.continue();
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!DB.prototype.get_recently_read_books.__argnames__) Object.defineProperties(DB.prototype.get_recently_read_books, {
            __argnames__ : {value: ["proceed", "limit"]}
        });
        DB.prototype.has_book_matching = function has_book_matching(library_id, book_id, proceed) {
            var self = this;
            var c;
            c = self.idb.transaction(ρσ_list_decorate([ "books" ]), "readonly").objectStore("books").index("recent_index").openCursor(null, "prev");
            c.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    proceed(false);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            book_id = int(book_id);
            c.onsuccess = (function() {
                var ρσ_anonfunc = function (ev) {
                    var cursor, book;
                    cursor = ev.target.result;
                    if (cursor) {
                        book = cursor.value;
                        if (book.key[0] === library_id && book.key[1] === book_id) {
                            proceed(true);
                            return;
                        }
                        cursor.continue();
                    } else {
                        proceed(false);
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!DB.prototype.has_book_matching.__argnames__) Object.defineProperties(DB.prototype.has_book_matching, {
            __argnames__ : {value: ["library_id", "book_id", "proceed"]}
        });
        DB.prototype.delete_book = function delete_book(book, proceed) {
            var self = this;
            var c, files, books, filenames;
            c = self.idb.transaction(ρσ_list_decorate([ "books", "files" ]), "readwrite");
            files = c.objectStore("files");
            books = c.objectStore("books");
            filenames = Object.keys(book.stored_files);
            c.oncomplete = (function() {
                var ρσ_anonfunc = function (event) {
                    proceed(book);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            c.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                    proceed(book, c.error.toString());
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            function next_step() {
                var r;
                if (filenames.length) {
                    r = files.delete(filenames.pop());
                    r.onsuccess = next_step;
                } else {
                    books.delete(book.key);
                }
            };

            next_step();
        };
        if (!DB.prototype.delete_book.__argnames__) Object.defineProperties(DB.prototype.delete_book, {
            __argnames__ : {value: ["book", "proceed"]}
        });
        DB.prototype.delete_books_matching = function delete_books_matching(library_id, book_id, proceed) {
            var self = this;
            var c, matches;
            c = self.idb.transaction(ρσ_list_decorate([ "books" ]), "readonly").objectStore("books").index("recent_index").openCursor(null, "prev");
            c.onerror = (function() {
                var ρσ_anonfunc = function (event) {
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })();
            book_id = int(book_id);
            matches = [];
            function delete_all() {
                var book;
                if (matches.length) {
                    book = matches.pop();
                    self.delete_book(book, delete_all);
                } else {
                    if (proceed) {
                        proceed();
                    }
                }
            };

            c.onsuccess = (function() {
                var ρσ_anonfunc = function (ev) {
                    var cursor, book;
                    cursor = ev.target.result;
                    if (cursor) {
                        book = cursor.value;
                        if (book.key[0] === library_id && book.key[1] === book_id) {
                            matches.push(book);
                        }
                        cursor.continue();
                    } else {
                        delete_all();
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!DB.prototype.delete_books_matching.__argnames__) Object.defineProperties(DB.prototype.delete_books_matching, {
            __argnames__ : {value: ["library_id", "book_id", "proceed"]}
        });
        DB.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        DB.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(DB.prototype, "__bases__", {value: []});

        function get_db(callback, show_read_book_error) {
            if (!get_db.ans) {
                get_db.ans = new DB(callback, show_read_book_error);
            }
            return get_db.ans;
        };
        if (!get_db.__argnames__) Object.defineProperties(get_db, {
            __argnames__ : {value: ["callback", "show_read_book_error"]}
        });

        ρσ_modules["read_book.db"].DB_NAME = DB_NAME;
        ρσ_modules["read_book.db"].DB_VERSION = DB_VERSION;
        ρσ_modules["read_book.db"].upgrade_schema = upgrade_schema;
        ρσ_modules["read_book.db"].file_store_name = file_store_name;
        ρσ_modules["read_book.db"].get_error_details = get_error_details;
        ρσ_modules["read_book.db"].new_book = new_book;
        ρσ_modules["read_book.db"].DB = DB;
        ρσ_modules["read_book.db"].get_db = get_db;
    })();

    (function(){
        var __name__ = "aes";
        var string_to_bytes, bytes_to_string, number_of_rounds, rcon, S, Si, T1, T2, T3, T4, T5, T6, T7, T8, U1, U2, U3, U4, random_bytes, noderandom;
        function string_to_bytes_encoder(string) {
            return new TextEncoder("utf-8").encode(string + "");
        };
        if (!string_to_bytes_encoder.__argnames__) Object.defineProperties(string_to_bytes_encoder, {
            __argnames__ : {value: ["string"]}
        });

        function string_to_bytes_slow(string) {
            var escstr, binstr, ua, ρσ_unpack, i, ch;
            escstr = encodeURIComponent(string);
            binstr = escstr.replace(/%([0-9A-F]{2})/g, (function() {
                var ρσ_anonfunc = function (match, p1) {
                    return String.fromCharCode("0x" + p1);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["match", "p1"]}
                });
                return ρσ_anonfunc;
            })());
            ua = new Uint8Array(binstr.length);
            var ρσ_Iter0 = ρσ_Iterable(enumerate(binstr));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                ρσ_unpack = ρσ_Iter0[ρσ_Index0];
                i = ρσ_unpack[0];
                ch = ρσ_unpack[1];
                ua[(typeof i === "number" && i < 0) ? ua.length + i : i] = ch.charCodeAt(0);
            }
            return ua;
        };
        if (!string_to_bytes_slow.__argnames__) Object.defineProperties(string_to_bytes_slow, {
            __argnames__ : {value: ["string"]}
        });

        function as_hex() {
            var array = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var sep = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? as_hex.__defaults__.sep : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "sep")){
                sep = ρσ_kwargs_obj.sep;
            }
            var num, fmt;
            num = array.BYTES_PER_ELEMENT || 1;
            fmt = "{:0" + num * 2 + "x}";
            return (function() {
                var ρσ_Iter = ρσ_Iterable(array), ρσ_Result = [], x;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    x = ρσ_Iter[ρσ_Index];
                    ρσ_Result.push(str.format(fmt, x));
                }
                ρσ_Result = ρσ_list_constructor(ρσ_Result);
                return ρσ_Result;
            })().join(sep);
        };
        if (!as_hex.__defaults__) Object.defineProperties(as_hex, {
            __defaults__ : {value: {sep:""}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["array", "sep"]}
        });

        function bytes_to_string_decoder(bytes, offset) {
            offset = offset || 0;
            if (offset) {
                bytes = bytes.subarray(offset);
            }
            return new TextDecoder("utf-8").decode(bytes);
        };
        if (!bytes_to_string_decoder.__argnames__) Object.defineProperties(bytes_to_string_decoder, {
            __argnames__ : {value: ["bytes", "offset"]}
        });

        function bytes_to_string_slow(bytes, offset) {
            var ans, i, c;
            ans = [];
            i = offset || 0;
            while (i < bytes.length) {
                c = bytes[(typeof i === "number" && i < 0) ? bytes.length + i : i];
                if (c < 128) {
                    ans.push(String.fromCharCode(c));
                    i += 1;
                } else if (191 < c && c < 224) {
                    ans.push(String.fromCharCode((c & 31) << 6 | bytes[ρσ_bound_index(i + 1, bytes)] & 63));
                    i += 2;
                } else {
                    ans.push(String.fromCharCode((c & 15) << 12 | (bytes[ρσ_bound_index(i + 1, bytes)] & 63) << 6 | bytes[ρσ_bound_index(i + 2, bytes)] & 63));
                    i += 3;
                }
            }
            return ans.join("");
        };
        if (!bytes_to_string_slow.__argnames__) Object.defineProperties(bytes_to_string_slow, {
            __argnames__ : {value: ["bytes", "offset"]}
        });

        string_to_bytes = (typeof TextEncoder === "function") ? string_to_bytes_encoder : string_to_bytes_slow;
        bytes_to_string = (typeof TextDecoder === "function") ? bytes_to_string_decoder : bytes_to_string_slow;
        function increment_counter(c) {
            for (var i = 15; i >= 12; i--) {
                if (c[(typeof i === "number" && i < 0) ? c.length + i : i] === 255) {
                    c[(typeof i === "number" && i < 0) ? c.length + i : i] = 0;
                } else {
                    c[(typeof i === "number" && i < 0) ? c.length + i : i] += 1;
                    break;
                }
            }
        };
        if (!increment_counter.__argnames__) Object.defineProperties(increment_counter, {
            __argnames__ : {value: ["c"]}
        });

        function convert_to_int32(bytes, output, offset, length) {
            offset = offset || 0;
            length = length || bytes.length;
            for (var i = offset, j = 0; i < offset + length; i += 4, j++) {
                output[(typeof j === "number" && j < 0) ? output.length + j : j] = bytes[(typeof i === "number" && i < 0) ? bytes.length + i : i] << 24 | bytes[ρσ_bound_index(i + 1, bytes)] << 16 | bytes[ρσ_bound_index(i + 2, bytes)] << 8 | bytes[ρσ_bound_index(i + 3, bytes)];
            }
        };
        if (!convert_to_int32.__argnames__) Object.defineProperties(convert_to_int32, {
            __argnames__ : {value: ["bytes", "output", "offset", "length"]}
        });

        function convert_to_int32_pad(bytes) {
            var extra, t, ans;
            extra = bytes.length % 4;
            if (extra) {
                t = new Uint8Array(bytes.length + 4 - extra);
                t.set(bytes);
                bytes = t;
            }
            ans = new Uint32Array(bytes.length / 4);
            convert_to_int32(bytes, ans);
            return ans;
        };
        if (!convert_to_int32_pad.__argnames__) Object.defineProperties(convert_to_int32_pad, {
            __argnames__ : {value: ["bytes"]}
        });

        if (!Uint8Array.prototype.fill) {
            Uint8Array.prototype.fill = Uint32Array.prototype.fill = (function() {
                var ρσ_anonfunc = function (val, start, end) {
                    start = start || 0;
                    if (end === undefined) {
                        end = this.length;
                    }
                    if (start < 0) {
                        start += this.length;
                    }
                    if (end < 0) {
                        end += this.length;
                    }
                    for (var i = start; i < end; i++) {
                        (ρσ_expr_temp = this)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] = val;
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["val", "start", "end"]}
                });
                return ρσ_anonfunc;
            })();
        }
        function from_64_to_32(num) {
            var ans;
            ans = new Uint32Array(2);
            ans[0] = num / 4294967296 | 0;
            ans[1] = num & 4294967295;
            return ans;
        };
        if (!from_64_to_32.__argnames__) Object.defineProperties(from_64_to_32, {
            __argnames__ : {value: ["num"]}
        });

        number_of_rounds = (function(){
            var ρσ_d = {};
            ρσ_d[16] = 10;
            ρσ_d[24] = 12;
            ρσ_d[32] = 14;
            return ρσ_d;
        }).call(this);
        rcon = new Uint32Array([0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91]);
        S = new Uint32Array([0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]);
        Si = new Uint32Array([0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]);
        T1 = new Uint32Array([0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a]);
        T2 = new Uint32Array([0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616]);
        T3 = new Uint32Array([0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16]);
        T4 = new Uint32Array([0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c]);
        T5 = new Uint32Array([0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742]);
        T6 = new Uint32Array([0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857]);
        T7 = new Uint32Array([0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8]);
        T8 = new Uint32Array([0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0]);
        U1 = new Uint32Array([0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
        U2 = new Uint32Array([0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697]);
        U3 = new Uint32Array([0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46]);
        U4 = new Uint32Array([0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d]);
        function AES() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            AES.prototype.__init__.apply(this, arguments);
        }
        AES.prototype.__init__ = function __init__(key) {
            var self = this;
            var rounds, round_key_count, KC, tk, index, rconpointer, t, tt, i, r, c;
            self.working_mem = ρσ_list_decorate([ new Uint32Array(4), new Uint32Array(4) ]);
            rounds = number_of_rounds[ρσ_bound_index(key.length, number_of_rounds)];
            if (!rounds) {
                throw new ValueError("invalid key size (must be length 16, 24 or 32)");
            }
            self._Ke = [];
            self._Kd = [];
            for (var i = 0; i <= rounds; i++) {
                self._Ke.push(new Uint32Array(4));
                self._Kd.push(new Uint32Array(4));
            }
            round_key_count = (rounds + 1) * 4;
            KC = key.length / 4;
            tk = new Uint32Array(KC);
            convert_to_int32(key, tk);
            index = 0;
            for (var i = 0; i < KC; i++) {
                index = i >> 2;
                (ρσ_expr_temp = (ρσ_expr_temp = self._Ke)[(typeof index === "number" && index < 0) ? ρσ_expr_temp.length + index : index])[ρσ_bound_index(i % 4, ρσ_expr_temp)] = tk[(typeof i === "number" && i < 0) ? tk.length + i : i];
                (ρσ_expr_temp = (ρσ_expr_temp = self._Kd)[ρσ_bound_index(rounds - index, ρσ_expr_temp)])[ρσ_bound_index(i % 4, ρσ_expr_temp)] = tk[(typeof i === "number" && i < 0) ? tk.length + i : i];
            }
            rconpointer = 0;
            t = KC;
            while (t < round_key_count) {
                tt = tk[ρσ_bound_index(KC - 1, tk)];
                tk[0] ^= S[ρσ_bound_index(tt >> 16 & 255, S)] << 24 ^ S[ρσ_bound_index(tt >> 8 & 255, S)] << 16 ^ S[ρσ_bound_index(tt & 255, S)] << 8 ^ S[ρσ_bound_index(tt >> 24 & 255, S)] ^ rcon[(typeof rconpointer === "number" && rconpointer < 0) ? rcon.length + rconpointer : rconpointer] << 24;
                rconpointer += 1;
                if ((KC !== 8 && (typeof KC !== "object" || ρσ_not_equals(KC, 8)))) {
                    for (var i = 1; i < KC; i++) {
                        tk[(typeof i === "number" && i < 0) ? tk.length + i : i] ^= tk[ρσ_bound_index(i - 1, tk)];
                    }
                } else {
                    for (var i = 1; i < (KC / 2); i++) {
                        tk[(typeof i === "number" && i < 0) ? tk.length + i : i] ^= tk[ρσ_bound_index(i - 1, tk)];
                    }
                    tt = tk[ρσ_bound_index(KC / 2 - 1, tk)];
                    tk[ρσ_bound_index(KC / 2, tk)] ^= S[ρσ_bound_index(tt & 255, S)] ^ S[ρσ_bound_index(tt >> 8 & 255, S)] << 8 ^ S[ρσ_bound_index(tt >> 16 & 255, S)] << 16 ^ S[ρσ_bound_index(tt >> 24 & 255, S)] << 24;
                    for (var i = (KC / 2) + 1; i < KC; i++) {
                        tk[(typeof i === "number" && i < 0) ? tk.length + i : i] ^= tk[ρσ_bound_index(i - 1, tk)];
                    }
                }
                i = 0;
                while (i < KC && t < round_key_count) {
                    r = t >> 2;
                    c = t % 4;
                    (ρσ_expr_temp = (ρσ_expr_temp = self._Ke)[(typeof r === "number" && r < 0) ? ρσ_expr_temp.length + r : r])[(typeof c === "number" && c < 0) ? ρσ_expr_temp.length + c : c] = tk[(typeof i === "number" && i < 0) ? tk.length + i : i];
                    (ρσ_expr_temp = (ρσ_expr_temp = self._Kd)[ρσ_bound_index(rounds - r, ρσ_expr_temp)])[(typeof c === "number" && c < 0) ? ρσ_expr_temp.length + c : c] = tk[ρσ_bound_index(i++, tk)];
                    t += 1;
                }
            }
            for (var r = 1; r < rounds; r++) {
                for (var c = 0; c < 4; c++) {
                    tt = (ρσ_expr_temp = (ρσ_expr_temp = self._Kd)[(typeof r === "number" && r < 0) ? ρσ_expr_temp.length + r : r])[(typeof c === "number" && c < 0) ? ρσ_expr_temp.length + c : c];
                    (ρσ_expr_temp = (ρσ_expr_temp = self._Kd)[(typeof r === "number" && r < 0) ? ρσ_expr_temp.length + r : r])[(typeof c === "number" && c < 0) ? ρσ_expr_temp.length + c : c] = U1[ρσ_bound_index(tt >> 24 & 255, U1)] ^ U2[ρσ_bound_index(tt >> 16 & 255, U2)] ^ U3[ρσ_bound_index(tt >> 8 & 255, U3)] ^ U4[ρσ_bound_index(tt & 255, U4)];
                }
            }
        };
        if (!AES.prototype.__init__.__argnames__) Object.defineProperties(AES.prototype.__init__, {
            __argnames__ : {value: ["key"]}
        });
        AES.__argnames__ = AES.prototype.__init__.__argnames__;
        AES.__handles_kwarg_interpolation__ = AES.prototype.__init__.__handles_kwarg_interpolation__;
        AES.prototype._crypt = function _crypt(ciphertext, offset, encrypt) {
            var self = this;
            var R1, R2, R3, R4, o1, o3, SB, K, rounds, a, t, tt;
            if (encrypt) {
                R1 = T1;
                R2 = T2;
                R3 = T3;
                R4 = T4;
                o1 = 1;
                o3 = 3;
                SB = S;
                K = self._Ke;
            } else {
                R1 = T5;
                R2 = T6;
                R3 = T7;
                R4 = T8;
                o1 = 3;
                o3 = 1;
                SB = Si;
                K = self._Kd;
            }
            rounds = K.length - 1;
            a = self.working_mem[0];
            t = self.working_mem[1];
            for (var i = 0; i < 4; i++) {
                t[(typeof i === "number" && i < 0) ? t.length + i : i] ^= (ρσ_expr_temp = K[0])[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
            }
            for (var r = 1; r < rounds; r++) {
                for (var i = 0; i < 4; i++) {
                    a[(typeof i === "number" && i < 0) ? a.length + i : i] = R1[ρσ_bound_index(t[(typeof i === "number" && i < 0) ? t.length + i : i] >> 24 & 255, R1)] ^ R2[ρσ_bound_index(t[ρσ_bound_index((i + o1) % 4, t)] >> 16 & 255, R2)] ^ R3[ρσ_bound_index(t[ρσ_bound_index((i + 2) % 4, t)] >> 8 & 255, R3)] ^ R4[ρσ_bound_index(t[ρσ_bound_index((i + o3) % 4, t)] & 255, R4)] ^ (ρσ_expr_temp = K[(typeof r === "number" && r < 0) ? K.length + r : r])[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
                }
                t.set(a);
            }
            for (var i = 0; i < 4; i++) {
                tt = (ρσ_expr_temp = K[(typeof rounds === "number" && rounds < 0) ? K.length + rounds : rounds])[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
                ciphertext[ρσ_bound_index(offset + 4 * i, ciphertext)] = (SB[ρσ_bound_index(t[(typeof i === "number" && i < 0) ? t.length + i : i] >> 24 & 255, SB)] ^ tt >> 24) & 255;
                ciphertext[ρσ_bound_index(offset + 4 * i + 1, ciphertext)] = (SB[ρσ_bound_index(t[ρσ_bound_index((i + o1) % 4, t)] >> 16 & 255, SB)] ^ tt >> 16) & 255;
                ciphertext[ρσ_bound_index(offset + 4 * i + 2, ciphertext)] = (SB[ρσ_bound_index(t[ρσ_bound_index((i + 2) % 4, t)] >> 8 & 255, SB)] ^ tt >> 8) & 255;
                ciphertext[ρσ_bound_index(offset + 4 * i + 3, ciphertext)] = (SB[ρσ_bound_index(t[ρσ_bound_index((i + o3) % 4, t)] & 255, SB)] ^ tt) & 255;
            }
        };
        if (!AES.prototype._crypt.__argnames__) Object.defineProperties(AES.prototype._crypt, {
            __argnames__ : {value: ["ciphertext", "offset", "encrypt"]}
        });
        AES.prototype.encrypt = function encrypt(plaintext, ciphertext, offset) {
            var self = this;
            convert_to_int32(plaintext, self.working_mem[1], offset, 16);
            return self._crypt(ciphertext, offset, true);
        };
        if (!AES.prototype.encrypt.__argnames__) Object.defineProperties(AES.prototype.encrypt, {
            __argnames__ : {value: ["plaintext", "ciphertext", "offset"]}
        });
        AES.prototype.encrypt32 = function encrypt32(plaintext, ciphertext, offset) {
            var self = this;
            self.working_mem[1].set(plaintext);
            return self._crypt(ciphertext, offset, true);
        };
        if (!AES.prototype.encrypt32.__argnames__) Object.defineProperties(AES.prototype.encrypt32, {
            __argnames__ : {value: ["plaintext", "ciphertext", "offset"]}
        });
        AES.prototype.decrypt = function decrypt(ciphertext, plaintext, offset) {
            var self = this;
            convert_to_int32(ciphertext, self.working_mem[1], offset, 16);
            return self._crypt(plaintext, offset, false);
        };
        if (!AES.prototype.decrypt.__argnames__) Object.defineProperties(AES.prototype.decrypt, {
            __argnames__ : {value: ["ciphertext", "plaintext", "offset"]}
        });
        AES.prototype.decrypt32 = function decrypt32(ciphertext, plaintext, offset) {
            var self = this;
            self.working_mem[1].set(ciphertext);
            return self._crypt(plaintext, offset, false);
        };
        if (!AES.prototype.decrypt32.__argnames__) Object.defineProperties(AES.prototype.decrypt32, {
            __argnames__ : {value: ["ciphertext", "plaintext", "offset"]}
        });
        AES.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        AES.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(AES.prototype, "__bases__", {value: []});

        function random_bytes_insecure(sz) {
            var ans;
            ans = new Uint8Array(sz);
            for (var i = 0; i < sz; i++) {
                ans[(typeof i === "number" && i < 0) ? ans.length + i : i] = Math.floor(Math.random() * 256);
            }
            return ans;
        };
        if (!random_bytes_insecure.__argnames__) Object.defineProperties(random_bytes_insecure, {
            __argnames__ : {value: ["sz"]}
        });

        function random_bytes_secure(sz) {
            var ans;
            ans = new Uint8Array(sz);
            crypto.getRandomValues(ans);
            return ans;
        };
        if (!random_bytes_secure.__argnames__) Object.defineProperties(random_bytes_secure, {
            __argnames__ : {value: ["sz"]}
        });

        random_bytes = (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") ? random_bytes_secure : random_bytes_insecure;
        if (random_bytes === random_bytes_insecure) {
            try {
                noderandom = require("crypto").randomBytes;
                random_bytes = (function() {
                    var ρσ_anonfunc = function (sz) {
                        return new Uint8Array(noderandom(sz));
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["sz"]}
                    });
                    return ρσ_anonfunc;
                })();
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                {
                    print("WARNING: Using insecure RNG for AES");
                } 
            }
        }
        function ModeOfOperation() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            ModeOfOperation.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperties(ModeOfOperation.prototype,  {
            "key_as_js": {
                "enumerable": true, 
                "get": function key_as_js() {
                    var self = this;
                    return typed_array_as_js(self.key);
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        ModeOfOperation.prototype.__init__ = function __init__(key) {
            var self = this;
            self.key = key || generate_key(32);
            self.aes = new AES(self.key);
        };
        if (!ModeOfOperation.prototype.__init__.__argnames__) Object.defineProperties(ModeOfOperation.prototype.__init__, {
            __argnames__ : {value: ["key"]}
        });
        ModeOfOperation.__argnames__ = ModeOfOperation.prototype.__init__.__argnames__;
        ModeOfOperation.__handles_kwarg_interpolation__ = ModeOfOperation.prototype.__init__.__handles_kwarg_interpolation__;
        ModeOfOperation.prototype.tag_as_bytes = function tag_as_bytes(tag) {
            var self = this;
            if (ρσ_instanceof(tag, Uint8Array)) {
                return tag;
            }
            if (!tag) {
                return new Uint8Array(0);
            }
            if (typeof tag === "string") {
                return string_to_bytes(tag);
            }
            throw new TypeError("Invalid tag, must be a string or a Uint8Array");
        };
        if (!ModeOfOperation.prototype.tag_as_bytes.__argnames__) Object.defineProperties(ModeOfOperation.prototype.tag_as_bytes, {
            __argnames__ : {value: ["tag"]}
        });
        ModeOfOperation.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        ModeOfOperation.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(ModeOfOperation.prototype, "__bases__", {value: []});
        

        function GaloisField() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            GaloisField.prototype.__init__.apply(this, arguments);
        }
        GaloisField.prototype.__init__ = function __init__(sub_key) {
            var self = this;
            var k32;
            k32 = new Uint32Array(4);
            convert_to_int32(sub_key, k32, 0);
            self.m = self.generate_hash_table(k32);
            self.wmem = new Uint32Array(4);
        };
        if (!GaloisField.prototype.__init__.__argnames__) Object.defineProperties(GaloisField.prototype.__init__, {
            __argnames__ : {value: ["sub_key"]}
        });
        GaloisField.__argnames__ = GaloisField.prototype.__init__.__argnames__;
        GaloisField.__handles_kwarg_interpolation__ = GaloisField.prototype.__init__.__handles_kwarg_interpolation__;
        GaloisField.prototype.power = function power(x, out) {
            var self = this;
            var lsb;
            lsb = x[3] & 1;
            for (var i = 3; i > 0; --i) {
                out[(typeof i === "number" && i < 0) ? out.length + i : i] = x[(typeof i === "number" && i < 0) ? x.length + i : i] >>> 1 | (x[ρσ_bound_index(i - 1, x)] & 1) << 31;
            }
            out[0] = x[0] >>> 1;
            if (lsb) {
                out[0] ^= 3774873600;
            }
        };
        if (!GaloisField.prototype.power.__argnames__) Object.defineProperties(GaloisField.prototype.power, {
            __argnames__ : {value: ["x", "out"]}
        });
        GaloisField.prototype.multiply = function multiply(x, y) {
            var self = this;
            var z_i, v_i, x_i;
            z_i = new Uint32Array(4);
            v_i = new Uint32Array(y);
            for (var i = 0; i < 128; ++i) {
                x_i = x[ρσ_bound_index(i / 32 | 0, x)] & 1 << 31 - i % 32;
                if (x_i) {
                    z_i[0] ^= v_i[0];
                    z_i[1] ^= v_i[1];
                    z_i[2] ^= v_i[2];
                    z_i[3] ^= v_i[3];
                }
                self.power(v_i, v_i);
            }
            return z_i;
        };
        if (!GaloisField.prototype.multiply.__argnames__) Object.defineProperties(GaloisField.prototype.multiply, {
            __argnames__ : {value: ["x", "y"]}
        });
        GaloisField.prototype.generate_sub_hash_table = function generate_sub_hash_table(mid) {
            var self = this;
            var bits, size, half, m, i, m_i, m_j, x, y;
            bits = mid.length;
            size = 1 << bits;
            half = size >>> 1;
            m = new Array(size);
            m[(typeof half === "number" && half < 0) ? m.length + half : half] = new Uint32Array(mid);
            i = half >>> 1;
            while (i > 0) {
                m[(typeof i === "number" && i < 0) ? m.length + i : i] = new Uint32Array(4);
                self.power(m[ρσ_bound_index(2 * i, m)], m[(typeof i === "number" && i < 0) ? m.length + i : i]);
                i >>= 1;
            }
            i = 2;
            while (i < half) {
                for (var j = 1; j < i; ++j) {
                    m_i = m[(typeof i === "number" && i < 0) ? m.length + i : i];
                    m_j = m[(typeof j === "number" && j < 0) ? m.length + j : j];
                    m[ρσ_bound_index(i + j, m)] = x = new Uint32Array(4);
                    for (var c = 0; c < 4; c++) {
                        x[(typeof c === "number" && c < 0) ? x.length + c : c] = m_i[(typeof c === "number" && c < 0) ? m_i.length + c : c] ^ m_j[(typeof c === "number" && c < 0) ? m_j.length + c : c];
                    }
                }
                i *= 2;
            }
            m[0] = new Uint32Array(4);
            for (i = half + 1; i < size; ++i) {
                x = m[ρσ_bound_index(i ^ half, m)];
                m[(typeof i === "number" && i < 0) ? m.length + i : i] = y = new Uint32Array(4);
                for (var c = 0; c < 4; c++) {
                    y[(typeof c === "number" && c < 0) ? y.length + c : c] = mid[(typeof c === "number" && c < 0) ? mid.length + c : c] ^ x[(typeof c === "number" && c < 0) ? x.length + c : c];
                }
            }
            return m;
        };
        if (!GaloisField.prototype.generate_sub_hash_table.__argnames__) Object.defineProperties(GaloisField.prototype.generate_sub_hash_table, {
            __argnames__ : {value: ["mid"]}
        });
        GaloisField.prototype.generate_hash_table = function generate_hash_table(key_as_int32_array) {
            var self = this;
            var bits, multiplier, per_int, size, ans, tmp, idx, shft;
            bits = key_as_int32_array.length;
            multiplier = 8 / bits;
            per_int = 4 * multiplier;
            size = 16 * multiplier;
            ans = new Array(size);
            for (var i =0; i < size; ++i) {
                tmp = new Uint32Array(4);
                idx = i / per_int | 0;
                shft = (per_int - 1 - i % per_int) * bits;
                tmp[(typeof idx === "number" && idx < 0) ? tmp.length + idx : idx] = 1 << bits - 1 << shft;
                ans[(typeof i === "number" && i < 0) ? ans.length + i : i] = self.generate_sub_hash_table(self.multiply(tmp, key_as_int32_array));
            }
            return ans;
        };
        if (!GaloisField.prototype.generate_hash_table.__argnames__) Object.defineProperties(GaloisField.prototype.generate_hash_table, {
            __argnames__ : {value: ["key_as_int32_array"]}
        });
        GaloisField.prototype.table_multiply = function table_multiply(x) {
            var self = this;
            var z, idx, x_i, ah;
            z = new Uint32Array(4);
            for (var i = 0; i < 32; ++i) {
                idx = i / 8 | 0;
                x_i = x[(typeof idx === "number" && idx < 0) ? x.length + idx : idx] >>> (7 - i % 8) * 4 & 15;
                ah = (ρσ_expr_temp = (ρσ_expr_temp = self.m)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i])[(typeof x_i === "number" && x_i < 0) ? ρσ_expr_temp.length + x_i : x_i];
                z[0] ^= ah[0];
                z[1] ^= ah[1];
                z[2] ^= ah[2];
                z[3] ^= ah[3];
            }
            return z;
        };
        if (!GaloisField.prototype.table_multiply.__argnames__) Object.defineProperties(GaloisField.prototype.table_multiply, {
            __argnames__ : {value: ["x"]}
        });
        GaloisField.prototype.ghash = function ghash(x, y) {
            var self = this;
            var z;
            z = self.wmem;
            z[0] = y[0] ^ x[0];
            z[1] = y[1] ^ x[1];
            z[2] = y[2] ^ x[2];
            z[3] = y[3] ^ x[3];
            return self.table_multiply(z);
        };
        if (!GaloisField.prototype.ghash.__argnames__) Object.defineProperties(GaloisField.prototype.ghash, {
            __argnames__ : {value: ["x", "y"]}
        });
        GaloisField.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        GaloisField.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(GaloisField.prototype, "__bases__", {value: []});

        function generate_key(sz) {
            if (!number_of_rounds[(typeof sz === "number" && sz < 0) ? number_of_rounds.length + sz : sz]) {
                throw new ValueError("Invalid key size, must be: 16, 24 or 32");
            }
            return random_bytes(sz);
        };
        if (!generate_key.__argnames__) Object.defineProperties(generate_key, {
            __argnames__ : {value: ["sz"]}
        });

        function generate_tag(sz) {
            return random_bytes(sz || 32);
        };
        if (!generate_tag.__argnames__) Object.defineProperties(generate_tag, {
            __argnames__ : {value: ["sz"]}
        });

        function typed_array_as_js(x) {
            var name;
            name = x.constructor.name || "Uint8Array";
            return "(new " + name + "(" + JSON.stringify(Array.prototype.slice.call(x)) + "))";
        };
        if (!typed_array_as_js.__argnames__) Object.defineProperties(typed_array_as_js, {
            __argnames__ : {value: ["x"]}
        });

        function CBC() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            CBC.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(CBC, ModeOfOperation);
        CBC.prototype.__init__ = function __init__ () {
            ModeOfOperation.prototype.__init__ && ModeOfOperation.prototype.__init__.apply(this, arguments);
        };
        CBC.prototype.encrypt_bytes = function encrypt_bytes(bytes, tag_bytes, iv) {
            var self = this;
            var first_iv, mlen, padsz, inputbytes, offset, outputbytes, ρσ_unpack;
            iv = first_iv = iv || random_bytes(16);
            mlen = bytes.length + tag_bytes.length;
            padsz = (16 - mlen % 16) % 16;
            inputbytes = new Uint8Array(mlen + padsz);
            if (tag_bytes.length) {
                inputbytes.set(tag_bytes);
            }
            inputbytes.set(bytes, tag_bytes.length);
            offset = 0;
            outputbytes = new Uint8Array(inputbytes.length);
            for (var block = 0; block < inputbytes.length; block += 16) {
                if (block > 0) {
                    ρσ_unpack = [outputbytes, block - 16];
                    iv = ρσ_unpack[0];
                    offset = ρσ_unpack[1];
                }
                for (var i = 0; i < 16; i++) {
                    inputbytes[ρσ_bound_index(block + i, inputbytes)] ^= iv[ρσ_bound_index(offset + i, iv)];
                }
                self.aes.encrypt(inputbytes, outputbytes, block);
            }
            return (function(){
                var ρσ_d = {};
                ρσ_d["iv"] = first_iv;
                ρσ_d["cipherbytes"] = outputbytes;
                return ρσ_d;
            }).call(this);
        };
        if (!CBC.prototype.encrypt_bytes.__argnames__) Object.defineProperties(CBC.prototype.encrypt_bytes, {
            __argnames__ : {value: ["bytes", "tag_bytes", "iv"]}
        });
        CBC.prototype.encrypt = function encrypt(plaintext, tag) {
            var self = this;
            return self.encrypt_bytes(string_to_bytes(plaintext), self.tag_as_bytes(tag));
        };
        if (!CBC.prototype.encrypt.__argnames__) Object.defineProperties(CBC.prototype.encrypt, {
            __argnames__ : {value: ["plaintext", "tag"]}
        });
        CBC.prototype.decrypt_bytes = function decrypt_bytes(inputbytes, tag_bytes, iv) {
            var self = this;
            var offset, outputbytes, ρσ_unpack;
            offset = 0;
            outputbytes = new Uint8Array(inputbytes.length);
            for (var block = 0; block < inputbytes.length; block += 16) {
                self.aes.decrypt(inputbytes, outputbytes, block);
                if (block > 0) {
                    ρσ_unpack = [inputbytes, block - 16];
                    iv = ρσ_unpack[0];
                    offset = ρσ_unpack[1];
                }
                for (var i = 0; i < 16; i++) {
                    outputbytes[ρσ_bound_index(block + i, outputbytes)] ^= iv[ρσ_bound_index(offset + i, iv)];
                }
            }
            for (var i = 0; i < tag_bytes.length; i++) {
                if ((tag_bytes[(typeof i === "number" && i < 0) ? tag_bytes.length + i : i] !== outputbytes[(typeof i === "number" && i < 0) ? outputbytes.length + i : i] && (typeof tag_bytes[(typeof i === "number" && i < 0) ? tag_bytes.length + i : i] !== "object" || ρσ_not_equals(tag_bytes[(typeof i === "number" && i < 0) ? tag_bytes.length + i : i], outputbytes[(typeof i === "number" && i < 0) ? outputbytes.length + i : i])))) {
                    throw new ValueError("Corrupt message");
                }
            }
            outputbytes = outputbytes.subarray(tag_bytes.length);
            return outputbytes;
        };
        if (!CBC.prototype.decrypt_bytes.__argnames__) Object.defineProperties(CBC.prototype.decrypt_bytes, {
            __argnames__ : {value: ["inputbytes", "tag_bytes", "iv"]}
        });
        CBC.prototype.decrypt = function decrypt(output_from_encrypt, tag) {
            var self = this;
            var ans;
            ans = self.decrypt_bytes(output_from_encrypt.cipherbytes, self.tag_as_bytes(tag), output_from_encrypt.iv);
            return str.rstrip(bytes_to_string(ans), "\u0000");
        };
        if (!CBC.prototype.decrypt.__argnames__) Object.defineProperties(CBC.prototype.decrypt, {
            __argnames__ : {value: ["output_from_encrypt", "tag"]}
        });
        CBC.prototype.__repr__ = function __repr__ () {
            if(ModeOfOperation.prototype.__repr__) return ModeOfOperation.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        CBC.prototype.__str__ = function __str__ () {
            if(ModeOfOperation.prototype.__str__) return ModeOfOperation.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(CBC.prototype, "__bases__", {value: [ModeOfOperation]});

        function CTR() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            CTR.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(CTR, ModeOfOperation);
        CTR.prototype.__init__ = function __init__(key, iv) {
            var self = this;
            ModeOfOperation.prototype.__init__.call(self, key);
            self.wmem = new Uint8Array(16);
            self.counter_block = new Uint8Array(iv || 16);
            if ((self.counter_block.length !== 16 && (typeof self.counter_block.length !== "object" || ρσ_not_equals(self.counter_block.length, 16)))) {
                throw new ValueError("iv must be 16 bytes long");
            }
            self.counter_index = 16;
        };
        if (!CTR.prototype.__init__.__argnames__) Object.defineProperties(CTR.prototype.__init__, {
            __argnames__ : {value: ["key", "iv"]}
        });
        CTR.__argnames__ = CTR.prototype.__init__.__argnames__;
        CTR.__handles_kwarg_interpolation__ = CTR.prototype.__init__.__handles_kwarg_interpolation__;
        CTR.prototype._crypt = function _crypt(bytes) {
            var self = this;
            for (var i = 0; i < bytes.length; i++, self.counter_index++) {
                if (self.counter_index === 16) {
                    self.counter_index = 0;
                    self.aes.encrypt(self.counter_block, self.wmem, 0);
                    increment_counter(self.counter_block);
                }
                bytes[(typeof i === "number" && i < 0) ? bytes.length + i : i] ^= (ρσ_expr_temp = self.wmem)[ρσ_bound_index(self.counter_index, ρσ_expr_temp)];
            }
            self.counter_index = 16;
        };
        if (!CTR.prototype._crypt.__argnames__) Object.defineProperties(CTR.prototype._crypt, {
            __argnames__ : {value: ["bytes"]}
        });
        CTR.prototype.encrypt = function encrypt(plaintext, tag) {
            var self = this;
            var outbytes, counterbytes, tag_bytes, t;
            outbytes = string_to_bytes(plaintext);
            counterbytes = new Uint8Array(self.counter_block);
            if (tag) {
                tag_bytes = self.tag_as_bytes(tag);
                t = new Uint8Array(outbytes.length + tag_bytes.length);
                t.set(tag_bytes);
                t.set(outbytes, tag_bytes.length);
                outbytes = t;
            }
            self._crypt(outbytes);
            return (function(){
                var ρσ_d = {};
                ρσ_d["cipherbytes"] = outbytes;
                ρσ_d["counterbytes"] = counterbytes;
                return ρσ_d;
            }).call(this);
        };
        if (!CTR.prototype.encrypt.__argnames__) Object.defineProperties(CTR.prototype.encrypt, {
            __argnames__ : {value: ["plaintext", "tag"]}
        });
        CTR.prototype.__enter__ = function __enter__() {
            var self = this;
            self.before_index = self.counter_index;
            self.before_counter = new Uint8Array(self.counter_block);
        };
        CTR.prototype.__exit__ = function __exit__() {
            var self = this;
            self.counter_index = self.before_index;
            self.counter_block = self.before_counter;
        };
        CTR.prototype.decrypt = function decrypt(output_from_encrypt, tag) {
            var self = this;
            var b, ρσ_with_exception, ρσ_with_suppress, offset, tag_bytes;
            b = new Uint8Array(output_from_encrypt.cipherbytes);
            ρσ_with_exception = undefined;
            var ρσ_with_clause_1 = self;
            ρσ_with_clause_1.__enter__();
            try {
                {
                    self.counter_block = output_from_encrypt.counterbytes;
                    self.counter_index = 16;
                    self._crypt(b);
                }
            } catch(e){
                ρσ_with_exception = e;
            }
            if (ρσ_with_exception === undefined){
                ρσ_with_clause_1.__exit__();
            } else {
                ρσ_with_suppress = false;
                ρσ_with_suppress |= ρσ_bool(ρσ_with_clause_1.__exit__(ρσ_with_exception.constructor, ρσ_with_exception, ρσ_with_exception.stack));
                if (!ρσ_with_suppress) throw ρσ_with_exception;
            }
            offset = 0;
            if (tag) {
                tag_bytes = self.tag_as_bytes(tag);
                for (var i = 0; i < tag_bytes.length; i++) {
                    if ((tag_bytes[(typeof i === "number" && i < 0) ? tag_bytes.length + i : i] !== b[(typeof i === "number" && i < 0) ? b.length + i : i] && (typeof tag_bytes[(typeof i === "number" && i < 0) ? tag_bytes.length + i : i] !== "object" || ρσ_not_equals(tag_bytes[(typeof i === "number" && i < 0) ? tag_bytes.length + i : i], b[(typeof i === "number" && i < 0) ? b.length + i : i])))) {
                        throw new ValueError("Corrupted message");
                    }
                }
                offset = tag_bytes.length;
            }
            return bytes_to_string(b, offset);
        };
        if (!CTR.prototype.decrypt.__argnames__) Object.defineProperties(CTR.prototype.decrypt, {
            __argnames__ : {value: ["output_from_encrypt", "tag"]}
        });
        CTR.prototype.__repr__ = function __repr__ () {
            if(ModeOfOperation.prototype.__repr__) return ModeOfOperation.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        CTR.prototype.__str__ = function __str__ () {
            if(ModeOfOperation.prototype.__str__) return ModeOfOperation.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(CTR.prototype, "__bases__", {value: [ModeOfOperation]});

        function GCM() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            GCM.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(GCM, ModeOfOperation);
        GCM.prototype.__init__ = function __init__() {
            var self = this;
            var key = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var random_iv = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.random_iv : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "random_iv")){
                random_iv = ρσ_kwargs_obj.random_iv;
            }
            var H;
            ModeOfOperation.prototype.__init__.call(self, key);
            self.random_iv = random_iv;
            if (!random_iv) {
                self.current_iv = new Uint8Array(12);
            }
            H = new Uint8Array(16);
            self.aes.encrypt(new Uint8Array(16), H, 0);
            self.galois = new GaloisField(H);
            self.J0 = new Uint32Array(4);
            self.wmem = new Uint32Array(4);
            self.byte_block = new Uint8Array(16);
        };
        if (!GCM.prototype.__init__.__defaults__) Object.defineProperties(GCM.prototype.__init__, {
            __defaults__ : {value: {random_iv:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["key", "random_iv"]}
        });
        GCM.__argnames__ = GCM.prototype.__init__.__argnames__;
        GCM.__handles_kwarg_interpolation__ = GCM.prototype.__init__.__handles_kwarg_interpolation__;
        GCM.prototype.increment_iv = function increment_iv() {
            var self = this;
            var c;
            c = self.current_iv;
            for (var i = 11; i >=0; i--) {
                if (c[(typeof i === "number" && i < 0) ? c.length + i : i] === 255) {
                    if (i === 0) {
                        throw new ValueError("The GCM IV space is exhausted, cannot encrypt anymore messages with this key as doing so would cause the IV to repeat");
                    }
                    c[(typeof i === "number" && i < 0) ? c.length + i : i] = 0;
                } else {
                    c[(typeof i === "number" && i < 0) ? c.length + i : i] += 1;
                    break;
                }
            }
        };
        GCM.prototype._create_j0 = function _create_j0(iv) {
            var self = this;
            var J0, tmp;
            J0 = self.J0;
            if (iv.length === 12) {
                convert_to_int32(iv, J0);
                J0[3] = 1;
            } else {
                J0.fill(0);
                tmp = convert_to_int32_pad(iv);
                while (tmp.length) {
                    J0 = self.galois.ghash(J0, tmp);
                    tmp = tmp.subarray(4);
                }
                tmp = new Uint32Array(4);
                tmp.set(from_64_to_32(iv.length * 8), 2);
                J0 = self.galois.ghash(J0, tmp);
            }
            return J0;
        };
        if (!GCM.prototype._create_j0.__argnames__) Object.defineProperties(GCM.prototype._create_j0, {
            __argnames__ : {value: ["iv"]}
        });
        GCM.prototype._start = function _start(iv, additional_data) {
            var self = this;
            var J0, in_block, S, overflow;
            J0 = self._create_j0(iv);
            in_block = new Uint32Array(J0);
            in_block[3] = in_block[3] + 1 & 4294967295;
            S = new Uint32Array(4);
            overflow = additional_data.length % 16;
            for (var i = 0; i < additional_data.length - overflow; i += 16) {
                convert_to_int32(additional_data, self.wmem, i, 16);
                S = self.galois.ghash(S, self.wmem);
            }
            if (overflow) {
                self.byte_block.fill(0);
                self.byte_block.set(additional_data.subarray(additional_data.length - overflow));
                convert_to_int32(self.byte_block, self.wmem);
                S = self.galois.ghash(S, self.wmem);
            }
            return [J0, in_block, S];
        };
        if (!GCM.prototype._start.__argnames__) Object.defineProperties(GCM.prototype._start, {
            __argnames__ : {value: ["iv", "additional_data"]}
        });
        GCM.prototype._finish = function _finish(iv, J0, adata_len, S, outbytes) {
            var self = this;
            var lengths, tag;
            lengths = new Uint32Array(4);
            lengths.set(from_64_to_32(adata_len * 8));
            lengths.set(from_64_to_32(outbytes.length * 8), 2);
            S = self.galois.ghash(S, lengths);
            self.aes.encrypt32(J0, self.byte_block, 0);
            convert_to_int32(self.byte_block, self.wmem);
            tag = new Uint32Array(4);
            for (var i = 0; i < S.length; i++) {
                tag[(typeof i === "number" && i < 0) ? tag.length + i : i] = S[(typeof i === "number" && i < 0) ? S.length + i : i] ^ (ρσ_expr_temp = self.wmem)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
            }
            return (function(){
                var ρσ_d = {};
                ρσ_d["iv"] = iv;
                ρσ_d["cipherbytes"] = outbytes;
                ρσ_d["tag"] = tag;
                return ρσ_d;
            }).call(this);
        };
        if (!GCM.prototype._finish.__argnames__) Object.defineProperties(GCM.prototype._finish, {
            __argnames__ : {value: ["iv", "J0", "adata_len", "S", "outbytes"]}
        });
        GCM.prototype._crypt = function _crypt(iv, bytes, additional_data, decrypt) {
            var self = this;
            var ghash, outbytes, ρσ_unpack, J0, in_block, S, bb, enc, hash_bytes, counter_index, overflow;
            ghash = self.galois.ghash.bind(self.galois);
            outbytes = new Uint8Array(bytes.length);
            ρσ_unpack = self._start(iv, additional_data);
ρσ_unpack = ρσ_unpack_asarray(3, ρσ_unpack);
            J0 = ρσ_unpack[0];
            in_block = ρσ_unpack[1];
            S = ρσ_unpack[2];
            bb = self.byte_block;
            enc = self.aes.encrypt32.bind(self.aes);
            hash_bytes = (decrypt) ? bytes : outbytes;
            for (var i = 0, counter_index = 16; i < bytes.length; i++, counter_index++) {
                if (counter_index === 16) {
                    enc(in_block, bb, 0);
                    in_block[3] = in_block[3] + 1 & 4294967295;
                    counter_index = 0;
                }
                outbytes[(typeof i === "number" && i < 0) ? outbytes.length + i : i] = bytes[(typeof i === "number" && i < 0) ? bytes.length + i : i] ^ bb[(typeof counter_index === "number" && counter_index < 0) ? bb.length + counter_index : counter_index];
                if (counter_index === 15) {
                    convert_to_int32(hash_bytes, self.wmem, i - 15, 16);
                    S = ghash(S, self.wmem);
                }
            }
            overflow = outbytes.length % 16;
            if (overflow) {
                bb.fill(0);
                bb.set(hash_bytes.subarray(hash_bytes.length - overflow));
                convert_to_int32(bb, self.wmem);
                S = ghash(S, self.wmem);
            }
            return self._finish(iv, J0, additional_data.length, S, outbytes);
        };
        if (!GCM.prototype._crypt.__argnames__) Object.defineProperties(GCM.prototype._crypt, {
            __argnames__ : {value: ["iv", "bytes", "additional_data", "decrypt"]}
        });
        GCM.prototype.encrypt = function encrypt(plaintext, tag) {
            var self = this;
            var iv;
            if (self.random_iv) {
                iv = random_bytes(12);
            } else {
                self.increment_iv();
                iv = self.current_iv;
            }
            return self._crypt(iv, string_to_bytes(plaintext), self.tag_as_bytes(tag), false);
        };
        if (!GCM.prototype.encrypt.__argnames__) Object.defineProperties(GCM.prototype.encrypt, {
            __argnames__ : {value: ["plaintext", "tag"]}
        });
        GCM.prototype.decrypt = function decrypt(output_from_encrypt, tag) {
            var self = this;
            var ans;
            if ((output_from_encrypt.tag.length !== 4 && (typeof output_from_encrypt.tag.length !== "object" || ρσ_not_equals(output_from_encrypt.tag.length, 4)))) {
                throw new ValueError("Corrupted message");
            }
            ans = self._crypt(output_from_encrypt.iv, output_from_encrypt.cipherbytes, self.tag_as_bytes(tag), true);
            if ((ans.tag !== output_from_encrypt.tag && (typeof ans.tag !== "object" || ρσ_not_equals(ans.tag, output_from_encrypt.tag)))) {
                throw new ValueError("Corrupted message");
            }
            return bytes_to_string(ans.cipherbytes);
        };
        if (!GCM.prototype.decrypt.__argnames__) Object.defineProperties(GCM.prototype.decrypt, {
            __argnames__ : {value: ["output_from_encrypt", "tag"]}
        });
        GCM.prototype.__repr__ = function __repr__ () {
            if(ModeOfOperation.prototype.__repr__) return ModeOfOperation.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        GCM.prototype.__str__ = function __str__ () {
            if(ModeOfOperation.prototype.__str__) return ModeOfOperation.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(GCM.prototype, "__bases__", {value: [ModeOfOperation]});

        ρσ_modules.aes.string_to_bytes = string_to_bytes;
        ρσ_modules.aes.bytes_to_string = bytes_to_string;
        ρσ_modules.aes.number_of_rounds = number_of_rounds;
        ρσ_modules.aes.rcon = rcon;
        ρσ_modules.aes.S = S;
        ρσ_modules.aes.Si = Si;
        ρσ_modules.aes.T1 = T1;
        ρσ_modules.aes.T2 = T2;
        ρσ_modules.aes.T3 = T3;
        ρσ_modules.aes.T4 = T4;
        ρσ_modules.aes.T5 = T5;
        ρσ_modules.aes.T6 = T6;
        ρσ_modules.aes.T7 = T7;
        ρσ_modules.aes.T8 = T8;
        ρσ_modules.aes.U1 = U1;
        ρσ_modules.aes.U2 = U2;
        ρσ_modules.aes.U3 = U3;
        ρσ_modules.aes.U4 = U4;
        ρσ_modules.aes.random_bytes = random_bytes;
        ρσ_modules.aes.noderandom = noderandom;
        ρσ_modules.aes.string_to_bytes_encoder = string_to_bytes_encoder;
        ρσ_modules.aes.string_to_bytes_slow = string_to_bytes_slow;
        ρσ_modules.aes.as_hex = as_hex;
        ρσ_modules.aes.bytes_to_string_decoder = bytes_to_string_decoder;
        ρσ_modules.aes.bytes_to_string_slow = bytes_to_string_slow;
        ρσ_modules.aes.increment_counter = increment_counter;
        ρσ_modules.aes.convert_to_int32 = convert_to_int32;
        ρσ_modules.aes.convert_to_int32_pad = convert_to_int32_pad;
        ρσ_modules.aes.from_64_to_32 = from_64_to_32;
        ρσ_modules.aes.AES = AES;
        ρσ_modules.aes.random_bytes_insecure = random_bytes_insecure;
        ρσ_modules.aes.random_bytes_secure = random_bytes_secure;
        ρσ_modules.aes.ModeOfOperation = ModeOfOperation;
        ρσ_modules.aes.GaloisField = GaloisField;
        ρσ_modules.aes.generate_key = generate_key;
        ρσ_modules.aes.generate_tag = generate_tag;
        ρσ_modules.aes.typed_array_as_js = typed_array_as_js;
        ρσ_modules.aes.CBC = CBC;
        ρσ_modules.aes.CTR = CTR;
        ρσ_modules.aes.GCM = GCM;
    })();

    (function(){
        var __name__ = "iframe_comm";
        var LOADING_DOC;
        var traceback = ρσ_modules.traceback;

        var GCM = ρσ_modules.aes.GCM;

        var _ = ρσ_modules.gettext.gettext;
        var install = ρσ_modules.gettext.install;

        var get_translations = ρσ_modules["book_list.globals"].get_translations;
        var main_js = ρσ_modules["book_list.globals"].main_js;

        var get_font_family = ρσ_modules["book_list.theme"].get_font_family;

        var ensure_id = ρσ_modules.dom.ensure_id;

        LOADING_DOC = "\n<!DOCTYPE html>\n<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<script type=\"text/javascript\" id=\"bootstrap\">\nwindow.iframe_entry_point = '__ENTRY_POINT__';  // different in different iframes\nwindow.default_font_family = '__FONT__';  // from the theme\n__SCRIPT__\nend_script\n</head>\n<body>\n<div style=\"font-size:larger; font-weight: bold; margin-top:48vh; text-align:center\">\n__BS__\n</div>\n</body>\n</html>\n".replace("end_script", "<" + "/script>");
        function iframe_js() {
            if (!iframe_js.ans) {
                iframe_js.ans = main_js().replace(/is_running_in_iframe\s*=\s*false/, "is_running_in_iframe = true");
                main_js(null);
            }
            return iframe_js.ans;
        };

        function Messenger() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            Messenger.prototype.__bind_methods__.call(this);
            Messenger.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(Messenger.prototype, "__bind_methods__", {value: function () {
            this.reset = Messenger.prototype.reset.bind(this);
            this.encrypt = Messenger.prototype.encrypt.bind(this);
            this.decrypt = Messenger.prototype.decrypt.bind(this);
        }});
        Messenger.prototype.__init__ = function __init__() {
            var self = this;
            self.secret = new Uint8Array(64);
        };
        Messenger.__argnames__ = Messenger.prototype.__init__.__argnames__;
        Messenger.__handles_kwarg_interpolation__ = Messenger.prototype.__init__.__handles_kwarg_interpolation__;
        Messenger.prototype.reset = function reset() {
            var self = this;
            window.crypto.getRandomValues(self.secret);
            self.gcm_to_iframe = new GCM(self.secret.subarray(0, 32));
            self.gcm_from_iframe = new GCM(self.secret.subarray(32));
        };
        Messenger.prototype.encrypt = function encrypt(data) {
            var self = this;
            return self.gcm_to_iframe.encrypt(JSON.stringify(data));
        };
        if (!Messenger.prototype.encrypt.__argnames__) Object.defineProperties(Messenger.prototype.encrypt, {
            __argnames__ : {value: ["data"]}
        });
        Messenger.prototype.decrypt = function decrypt(data) {
            var self = this;
            return JSON.parse(self.gcm_from_iframe.decrypt(data));
        };
        if (!Messenger.prototype.decrypt.__argnames__) Object.defineProperties(Messenger.prototype.decrypt, {
            __argnames__ : {value: ["data"]}
        });
        Messenger.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        Messenger.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(Messenger.prototype, "__bases__", {value: []});

        function IframeWrapper() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            IframeWrapper.prototype.__bind_methods__.call(this);
            IframeWrapper.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(IframeWrapper.prototype, "__bind_methods__", {value: function () {
            this.destroy = IframeWrapper.prototype.destroy.bind(this);
            this.create_srcdoc = IframeWrapper.prototype.create_srcdoc.bind(this);
            this.init = IframeWrapper.prototype.init.bind(this);
            this.reset = IframeWrapper.prototype.reset.bind(this);
            this._send_message = IframeWrapper.prototype._send_message.bind(this);
            this.send_message = IframeWrapper.prototype.send_message.bind(this);
            this.send_unencrypted_message = IframeWrapper.prototype.send_unencrypted_message.bind(this);
            this.handle_message = IframeWrapper.prototype.handle_message.bind(this);
            this.on_iframe_ready = IframeWrapper.prototype.on_iframe_ready.bind(this);
        }});
        Object.defineProperties(IframeWrapper.prototype,  {
            "iframe": {
                "enumerable": true, 
                "get": function iframe() {
                    var self = this;
                    return document.getElementById(self.iframe_id);
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        IframeWrapper.prototype.__init__ = function __init__(handlers, iframe, entry_point, bootstrap_text, srcdoc) {
            var self = this;
            var k;
            self.messenger = new Messenger;
            self.iframe_id = ensure_id(iframe, "content-iframe");
            self.needs_init = true;
            self.ready = false;
            self.encrypted_communications = false;
            self.srcdoc_created = false;
            self.constructor_srcdoc = srcdoc;
            self.entry_point = entry_point;
            self.bootstrap_text = bootstrap_text;
            self.handlers = (function() {
                var ρσ_Iter = ρσ_Iterable(handlers), ρσ_Result = Object.create(null), k;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    k = ρσ_Iter[ρσ_Index];
                    ρσ_Result[k] = (handlers[(typeof k === "number" && k < 0) ? handlers.length + k : k]);
                }
                return ρσ_Result;
            })();
            self.on_ready_handler = self.handlers.ready;
            self.handlers.ready = self.on_iframe_ready;
            window.addEventListener("message", self.handle_message, false);
        };
        if (!IframeWrapper.prototype.__init__.__argnames__) Object.defineProperties(IframeWrapper.prototype.__init__, {
            __argnames__ : {value: ["handlers", "iframe", "entry_point", "bootstrap_text", "srcdoc"]}
        });
        IframeWrapper.__argnames__ = IframeWrapper.prototype.__init__.__argnames__;
        IframeWrapper.__handles_kwarg_interpolation__ = IframeWrapper.prototype.__init__.__handles_kwarg_interpolation__;
        IframeWrapper.prototype.destroy = function destroy() {
            var self = this;
            window.removeEventListener("message", self.handle_message, false);
        };
        IframeWrapper.prototype.create_srcdoc = function create_srcdoc() {
            var self = this;
            var r, data;
            r = /__([A-Z][A-Z_0-9]*[A-Z0-9])__/g;
            if (self.entry_point) {
                data = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["BS"] = self.bootstrap_text;
                    ρσ_d["SCRIPT"] = iframe_js();
                    ρσ_d["FONT"] = get_font_family();
                    ρσ_d["ENTRY_POINT"] = self.entry_point;
                    return ρσ_d;
                }).call(this);
                self.iframe.srcdoc = LOADING_DOC.replace(r, (function() {
                    var ρσ_anonfunc = function (match, field) {
                        return data[(typeof field === "number" && field < 0) ? data.length + field : field];
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["match", "field"]}
                    });
                    return ρσ_anonfunc;
                })());
            } else {
                self.iframe.srcdoc = self.constructor_srcdoc || "<div> </div>";
            }
            self.srcdoc_created = true;
        };
        IframeWrapper.prototype.init = function init() {
            var self = this;
            var iframe, sdoc;
            if (!self.needs_init) {
                return;
            }
            self.needs_init = false;
            iframe = self.iframe;
            if (self.srcdoc_created) {
                sdoc = iframe.srcdoc;
                iframe.srcdoc = "<p>&nbsp;</p>";
                iframe.srcdoc = sdoc;
            } else {
                self.create_srcdoc();
            }
        };
        IframeWrapper.prototype.reset = function reset() {
            var self = this;
            self.ready = false;
            self.needs_init = true;
            self.encrypted_communications = false;
        };
        IframeWrapper.prototype._send_message = function _send_message(action, encrypted, data) {
            var self = this;
            var msg;
            data.action = action;
            msg = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["data"] = data;
                ρσ_d["encrypted"] = encrypted;
                return ρσ_d;
            }).call(this);
            if (encrypted) {
                msg.data = self.messenger.encrypt(data);
            }
            self.iframe.contentWindow.postMessage(msg, "*");
        };
        if (!IframeWrapper.prototype._send_message.__argnames__) Object.defineProperties(IframeWrapper.prototype._send_message, {
            __argnames__ : {value: ["action", "encrypted", "data"]}
        });
        IframeWrapper.prototype.send_message = function send_message() {
            var self = this;
            var action = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var data = arguments[arguments.length-1];
            if (data === null || typeof data !== "object" || data [ρσ_kwargs_symbol] !== true) data = {};
            self._send_message(action, self.encrypted_communications, data);
        };
        if (!IframeWrapper.prototype.send_message.__handles_kwarg_interpolation__) Object.defineProperties(IframeWrapper.prototype.send_message, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["action"]}
        });
        IframeWrapper.prototype.send_unencrypted_message = function send_unencrypted_message() {
            var self = this;
            var action = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var data = arguments[arguments.length-1];
            if (data === null || typeof data !== "object" || data [ρσ_kwargs_symbol] !== true) data = {};
            self._send_message(action, false, data);
        };
        if (!IframeWrapper.prototype.send_unencrypted_message.__handles_kwarg_interpolation__) Object.defineProperties(IframeWrapper.prototype.send_unencrypted_message, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["action"]}
        });
        IframeWrapper.prototype.handle_message = function handle_message(event) {
            var self = this;
            var data, func;
            if (event.source !== ρσ_exists.d(self.iframe).contentWindow) {
                return;
            }
            data = event.data;
            if (self.encrypted_communications) {
                try {
                    data = self.messenger.decrypt(data);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        var e = ρσ_Exception;
                        print("Could not process message from iframe:");
                        console.log(e);
                        return;
                    } else {
                        throw ρσ_Exception;
                    }
                }
            }
            if (!data.action) {
                return;
            }
            func = (ρσ_expr_temp = self.handlers)[ρσ_bound_index(data.action, ρσ_expr_temp)];
            if (func) {
                func(data);
            } else {
                print("Unknown action in message from iframe to parent:", data.action);
            }
        };
        if (!IframeWrapper.prototype.handle_message.__argnames__) Object.defineProperties(IframeWrapper.prototype.handle_message, {
            __argnames__ : {value: ["event"]}
        });
        IframeWrapper.prototype.on_iframe_ready = function on_iframe_ready(data) {
            var self = this;
            var msg, callback;
            self.messenger.reset();
            msg = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["secret"] = self.messenger.secret;
                ρσ_d["translations"] = get_translations();
                return ρσ_d;
            }).call(this);
            self.ready = true;
            callback = null;
            if (self.on_ready_handler) {
                callback = self.on_ready_handler(msg);
            }
            self._send_message("initialize", false, msg);
            self.encrypted_communications = true;
            if (callback) {
                callback();
            }
        };
        if (!IframeWrapper.prototype.on_iframe_ready.__argnames__) Object.defineProperties(IframeWrapper.prototype.on_iframe_ready, {
            __argnames__ : {value: ["data"]}
        });
        IframeWrapper.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        IframeWrapper.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(IframeWrapper.prototype, "__bases__", {value: []});
        

        function IframeClient() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            IframeClient.prototype.__bind_methods__.call(this);
            IframeClient.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(IframeClient.prototype, "__bind_methods__", {value: function () {
            this.initialize = IframeClient.prototype.initialize.bind(this);
            this.print_to_parent = IframeClient.prototype.print_to_parent.bind(this);
            this.handle_message = IframeClient.prototype.handle_message.bind(this);
            this.send_message = IframeClient.prototype.send_message.bind(this);
        }});
        IframeClient.prototype.__init__ = function __init__(handlers) {
            var self = this;
            var k;
            self.encrypted_communications = false;
            self.handlers = (function() {
                var ρσ_Iter = ρσ_Iterable(handlers), ρσ_Result = Object.create(null), k;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    k = ρσ_Iter[ρσ_Index];
                    ρσ_Result[k] = (handlers[(typeof k === "number" && k < 0) ? handlers.length + k : k]);
                }
                return ρσ_Result;
            })();
            self.initialize_handler = handlers.initialize;
            self.handlers.initialize = self.initialize;
            self.ready_sent = false;
            window.addEventListener("message", self.handle_message, false);
            window.addEventListener("load", function () {
                if (!self.ready_sent) {
                    self.send_message("ready", Object.create(null));
                    self.ready_sent = true;
                }
            });
        };
        if (!IframeClient.prototype.__init__.__argnames__) Object.defineProperties(IframeClient.prototype.__init__, {
            __argnames__ : {value: ["handlers"]}
        });
        IframeClient.__argnames__ = IframeClient.prototype.__init__.__argnames__;
        IframeClient.__handles_kwarg_interpolation__ = IframeClient.prototype.__init__.__handles_kwarg_interpolation__;
        IframeClient.prototype.initialize = function initialize(data) {
            var self = this;
            var ρσ_unpack;
            ρσ_unpack = [new GCM(data.secret.subarray(0, 32)), new GCM(data.secret.subarray(32))];
            self.gcm_from_parent = ρσ_unpack[0];
            self.gcm_to_parent = ρσ_unpack[1];
            if (data.translations) {
                install(data.translations);
            }
            print = self.print_to_parent;
            self.encrypted_communications = true;
            if (self.initialize_handler) {
                self.initialize_handler(data);
            }
        };
        if (!IframeClient.prototype.initialize.__argnames__) Object.defineProperties(IframeClient.prototype.initialize, {
            __argnames__ : {value: ["data"]}
        });
        IframeClient.prototype.print_to_parent = function print_to_parent() {
            var self = this;
            var args = Array.prototype.slice.call(arguments, 0);
            if (arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) args.pop();
            ρσ_interpolate_kwargs.call(self, self.send_message, ["print"].concat([ρσ_desugar_kwargs({string: " ".join(map(str, args))})]));
        };
        if (!IframeClient.prototype.print_to_parent.__handles_kwarg_interpolation__) Object.defineProperties(IframeClient.prototype.print_to_parent, {
            __handles_kwarg_interpolation__ : {value: true}
        });
        IframeClient.prototype.handle_message = function handle_message(event) {
            var self = this;
            var msg, data, func;
            if (event.source !== window.parent) {
                return;
            }
            msg = event.data;
            data = msg.data;
            if (msg.encrypted) {
                try {
                    data = JSON.parse(self.gcm_from_parent.decrypt(data));
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        var e = ρσ_Exception;
                        print("Could not process message from parent:");
                        console.log(e);
                        return;
                    } else {
                        throw ρσ_Exception;
                    }
                }
            }
            func = (ρσ_expr_temp = self.handlers)[ρσ_bound_index(data.action, ρσ_expr_temp)];
            if (func) {
                try {
                    func(data);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        var e = ρσ_Exception;
                        console.log("Error in iframe message handler:");
                        console.log(e);
                        ρσ_interpolate_kwargs.call(self, self.send_message, ["error"].concat([ρσ_desugar_kwargs({title: _("Error in message handler"), details: traceback.format_exc(), msg: e.toString()})]));
                    } else {
                        throw ρσ_Exception;
                    }
                }
            } else {
                print("Unknown action in message to iframe from parent: " + data.action);
            }
        };
        if (!IframeClient.prototype.handle_message.__argnames__) Object.defineProperties(IframeClient.prototype.handle_message, {
            __argnames__ : {value: ["event"]}
        });
        IframeClient.prototype.send_message = function send_message(action, data) {
            var self = this;
            data.action = action;
            if (self.encrypted_communications) {
                data = self.gcm_to_parent.encrypt(JSON.stringify(data));
            }
            window.parent.postMessage(data, "*");
        };
        if (!IframeClient.prototype.send_message.__argnames__) Object.defineProperties(IframeClient.prototype.send_message, {
            __argnames__ : {value: ["action", "data"]}
        });
        IframeClient.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        IframeClient.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(IframeClient.prototype, "__bases__", {value: []});

        ρσ_modules.iframe_comm.LOADING_DOC = LOADING_DOC;
        ρσ_modules.iframe_comm.iframe_js = iframe_js;
        ρσ_modules.iframe_comm.Messenger = Messenger;
        ρσ_modules.iframe_comm.IframeWrapper = IframeWrapper;
        ρσ_modules.iframe_comm.IframeClient = IframeClient;
    })();

    (function(){
        var __name__ = "read_book.globals";
        var _boss, uid, default_color_schemes, runtime, ui_operations;
        var random_bytes = ρσ_modules.aes.random_bytes;

        var hexlify = ρσ_modules.encodings.hexlify;

        var _ = ρσ_modules.gettext.gettext;
        var register_callback = ρσ_modules.gettext.register_callback;
        var gt = ρσ_modules.gettext.gettext;

        _boss = null;
        function set_boss(b) {
            _boss = b;
        };
        if (!set_boss.__argnames__) Object.defineProperties(set_boss, {
            __argnames__ : {value: ["b"]}
        });

        function get_boss() {
            return _boss;
        };

        function current_book() {
            return current_book.book;
        };

        current_book.book = null;
        uid = "calibre-" + hexlify(random_bytes(12));
        function viewport_mode_changer(val) {
            if (val) {
                viewport_mode_changer.val = val;
            }
            return viewport_mode_changer.val;
        };
        if (!viewport_mode_changer.__argnames__) Object.defineProperties(viewport_mode_changer, {
            __argnames__ : {value: ["val"]}
        });

        function current_layout_mode() {
            return current_layout_mode.value;
        };

        current_layout_mode.value = "flow";
        function set_layout_mode(val) {
            current_layout_mode.value = val;
            viewport_mode_changer()(val);
        };
        if (!set_layout_mode.__argnames__) Object.defineProperties(set_layout_mode, {
            __argnames__ : {value: ["val"]}
        });

        function current_spine_item() {
            return current_spine_item.value;
        };

        current_spine_item.value = null;
        function set_current_spine_item(val) {
            current_spine_item.value = val;
        };
        if (!set_current_spine_item.__argnames__) Object.defineProperties(set_current_spine_item, {
            __argnames__ : {value: ["val"]}
        });

        function toc_anchor_map() {
            return toc_anchor_map.value;
        };

        function set_toc_anchor_map(val) {
            toc_anchor_map.value = val;
        };
        if (!set_toc_anchor_map.__argnames__) Object.defineProperties(set_toc_anchor_map, {
            __argnames__ : {value: ["val"]}
        });

        default_color_schemes = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["white"] = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["foreground"] = "#000000";
                ρσ_d["background"] = "#ffffff";
                ρσ_d["name"] = _("White");
                return ρσ_d;
            }).call(this);
            ρσ_d["black"] = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["foreground"] = "#ffffff";
                ρσ_d["background"] = "#000000";
                ρσ_d["link"] = "#4f81bd";
                ρσ_d["name"] = _("Black");
                return ρσ_d;
            }).call(this);
            ρσ_d["sepia-light"] = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["foreground"] = "#39322B";
                ρσ_d["background"] = "#F6F3E9";
                ρσ_d["name"] = _("Sepia light");
                return ρσ_d;
            }).call(this);
            ρσ_d["sepia-dark"] = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["background"] = "#39322B";
                ρσ_d["foreground"] = "#F6F3E9";
                ρσ_d["link"] = "#4f81bd";
                ρσ_d["name"] = _("Sepia dark");
                return ρσ_d;
            }).call(this);
            return ρσ_d;
        }).call(this);
        register_callback(function () {
            var scheme, key;
            var ρσ_Iter0 = ρσ_Iterable(default_color_schemes);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                key = ρσ_Iter0[ρσ_Index0];
                scheme = default_color_schemes[(typeof key === "number" && key < 0) ? default_color_schemes.length + key : key];
                scheme.name = gt(scheme.name);
            }
        });
        runtime = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["is_standalone_viewer"] = false;
            ρσ_d["viewer_in_full_screen"] = false;
            return ρσ_d;
        }).call(this);
        ui_operations = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["get_file"] = null;
            ρσ_d["get_mathjax_files"] = null;
            ρσ_d["update_url_state"] = null;
            ρσ_d["update_last_read_time"] = null;
            ρσ_d["show_error"] = null;
            ρσ_d["redisplay_book"] = null;
            ρσ_d["reload_book"] = null;
            ρσ_d["forward_gesture"] = null;
            ρσ_d["update_color_scheme"] = null;
            ρσ_d["update_font_size"] = null;
            ρσ_d["goto_bookpos"] = null;
            ρσ_d["delete_book"] = null;
            ρσ_d["focus_iframe"] = null;
            ρσ_d["toggle_toc"] = null;
            ρσ_d["toggle_full_screen"] = null;
            return ρσ_d;
        }).call(this);
        ρσ_modules["read_book.globals"]._boss = _boss;
        ρσ_modules["read_book.globals"].uid = uid;
        ρσ_modules["read_book.globals"].default_color_schemes = default_color_schemes;
        ρσ_modules["read_book.globals"].runtime = runtime;
        ρσ_modules["read_book.globals"].ui_operations = ui_operations;
        ρσ_modules["read_book.globals"].set_boss = set_boss;
        ρσ_modules["read_book.globals"].get_boss = get_boss;
        ρσ_modules["read_book.globals"].current_book = current_book;
        ρσ_modules["read_book.globals"].viewport_mode_changer = viewport_mode_changer;
        ρσ_modules["read_book.globals"].current_layout_mode = current_layout_mode;
        ρσ_modules["read_book.globals"].set_layout_mode = set_layout_mode;
        ρσ_modules["read_book.globals"].current_spine_item = current_spine_item;
        ρσ_modules["read_book.globals"].set_current_spine_item = set_current_spine_item;
        ρσ_modules["read_book.globals"].toc_anchor_map = toc_anchor_map;
        ρσ_modules["read_book.globals"].set_toc_anchor_map = set_toc_anchor_map;
    })();

    (function(){
        var __name__ = "read_book.settings";
        var opts;
        var E = ρσ_modules.elementmaker.E;

        var runtime = ρσ_modules["read_book.globals"].runtime;

        opts = Object.create(null);
        function update_settings(settings) {
            settings = settings || Object.create(null);
            opts.columns_per_screen = settings.columns_per_screen || (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["portrait"] = 0;
                ρσ_d["landscape"] = 0;
                return ρσ_d;
            }).call(this);
            opts.margin_left = max(0, settings.margin_left || 0);
            opts.margin_right = max(0, settings.margin_right || 0);
            opts.color_scheme = settings.color_scheme;
            opts.base_font_size = max(8, min(settings.base_font_size || 16, 64));
            opts.user_stylesheet = settings.user_stylesheet || "";
            opts.hide_tooltips = settings.hide_tooltips;
            opts.cover_preserve_aspect_ratio = !!settings.cover_preserve_aspect_ratio;
            opts.bg_image_fade = settings.bg_image_fade || "transparent";
            opts.paged_wheel_scrolls_by_screen = !!settings.paged_wheel_scrolls_by_screen;
        };
        if (!update_settings.__argnames__) Object.defineProperties(update_settings, {
            __argnames__ : {value: ["settings"]}
        });

        update_settings();
        function apply_font_size() {
            if (!runtime.is_standalone_viewer) {
                document.documentElement.style.fontSize = "{}px".format(opts.base_font_size);
            }
        };

        function apply_colors() {
            var elem, ss, c, text;
            var ρσ_Iter0 = ρσ_Iterable(ρσ_list_decorate([ document.documentElement, document.body ]));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                elem = ρσ_Iter0[ρσ_Index0];
                elem.style.color = opts.color_scheme.foreground;
                elem.style.backgroundColor = "transparent";
            }
            document.documentElement.style.backgroundColor = opts.bg_image_fade;
            ss = document.getElementById("calibre-color-scheme-style-overrides");
            if (!ss) {
                ss = ρσ_interpolate_kwargs.call(E, E.style, [ρσ_desugar_kwargs({id: "calibre-color-scheme-style-overrides", type: "text/css"})]);
                document.documentElement.appendChild(ss);
            }
            if (opts.color_scheme.link) {
                c = opts.color_scheme.link;
                text = ":link, :link * { color: " + ρσ_str.format("{}", c) + " !important } :visited, :visited * { color: " + ρσ_str.format("{}", c) + " !important }";
            } else {
                text = "";
            }
            ss.textContent = text;
        };

        function apply_stylesheet() {
            var sid, style;
            if (opts.user_stylesheet) {
                sid = "calibre-browser-viewer-user-stylesheet";
                style = document.getElementById(sid);
                if (!style) {
                    style = ρσ_interpolate_kwargs.call(E, E.style, [ρσ_desugar_kwargs({type: "text/css", id: sid})]);
                    document.documentElement.appendChild(style);
                }
                style.textContent = opts.user_stylesheet;
            }
        };

        function apply_settings() {
            apply_font_size();
            apply_colors();
            apply_stylesheet();
        };

        ρσ_modules["read_book.settings"].opts = opts;
        ρσ_modules["read_book.settings"].update_settings = update_settings;
        ρσ_modules["read_book.settings"].apply_font_size = apply_font_size;
        ρσ_modules["read_book.settings"].apply_colors = apply_colors;
        ρσ_modules["read_book.settings"].apply_stylesheet = apply_stylesheet;
        ρσ_modules["read_book.settings"].apply_settings = apply_settings;
    })();

    (function(){
        var __name__ = "read_book.resources";
        var JSON_XHTML_MIMETYPE, mathjax_data, js_types, k, resource_tag_names, ns_rmap, ns_count, hide_tooltips;
        var E = ρσ_modules.elementmaker.E;

        var base64decode = ρσ_modules.encodings.base64decode;
        var utf8_decode = ρσ_modules.encodings.utf8_decode;

        var clear = ρσ_modules.dom.clear;
        var remove_all_attributes = ρσ_modules.dom.remove_all_attributes;

        var runtime = ρσ_modules["read_book.globals"].runtime;
        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var opts = ρσ_modules["read_book.settings"].opts;

        JSON_XHTML_MIMETYPE = "application/calibre+xhtml+json";
        function decode_component(x) {
            return utf8_decode(base64decode(x));
        };
        if (!decode_component.__argnames__) Object.defineProperties(decode_component, {
            __argnames__ : {value: ["x"]}
        });

        function decode_url(x) {
            var parts;
            parts = x.split("#", 1);
            return [decode_component(parts[0]), parts[1] || ""];
        };
        if (!decode_url.__argnames__) Object.defineProperties(decode_url, {
            __argnames__ : {value: ["x"]}
        });

        function create_link_pat(book) {
            return new RegExp(book.manifest.link_uid + "\\|([^|]+)\\|", "g");
        };
        if (!create_link_pat.__argnames__) Object.defineProperties(create_link_pat, {
            __argnames__ : {value: ["book"]}
        });

        function load_resources(book, root_name, previous_resources, proceed) {
            var ans, pending_resources, link_pat;
            ans = Object.create(null);
            pending_resources = [root_name];
            link_pat = create_link_pat(book);
            function do_one() {
                var k, name, data;
                if (!pending_resources.length) {
                    var ρσ_Iter0 = ρσ_Iterable(previous_resources);
                    for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                        k = ρσ_Iter0[ρσ_Index0];
                        delete previous_resources[k];
                    }
                    if ((ρσ_expr_temp = book.manifest.files)[(typeof root_name === "number" && root_name < 0) ? ρσ_expr_temp.length + root_name : root_name].has_maths) {
                        return load_mathjax(book, ans, proceed);
                    }
                    return proceed(ans);
                }
                name = pending_resources.shift();
                if (ans[(typeof name === "number" && name < 0) ? ans.length + name : name]) {
                    return setTimeout(do_one, 0);
                }
                if (previous_resources[(typeof name === "number" && name < 0) ? previous_resources.length + name : name]) {
                    ans[(typeof name === "number" && name < 0) ? ans.length + name : name] = data = previous_resources[(typeof name === "number" && name < 0) ? previous_resources.length + name : name];
                    if (typeof data[0] === "string") {
                        find_virtualized_resources(data[0]);
                    }
                    return setTimeout(do_one, 0);
                }
                ui_operations.get_file(book, name, got_one);
            };

            function got_one(data, name, mimetype) {
                if (false && name === book.manifest.title_page_name) {
                    data = data.replace("width: auto; height: auto", "width: 100vw; height: 100vh");
                }
                ans[(typeof name === "number" && name < 0) ? ans.length + name : name] = [data, mimetype];
                if (typeof data === "string") {
                    find_virtualized_resources(data);
                }
                return setTimeout(do_one, 0);
            };
            if (!got_one.__argnames__) Object.defineProperties(got_one, {
                __argnames__ : {value: ["data", "name", "mimetype"]}
            });

            function find_virtualized_resources(text) {
                var seen, already_pending, x, m, name;
                seen = set();
                already_pending = (function() {
                    var ρσ_Iter = ρσ_Iterable(pending_resources), ρσ_Result = ρσ_set(), x;
                    for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                        x = ρσ_Iter[ρσ_Index];
                        ρσ_Result.add(x.name);
                    }
                    return ρσ_Result;
                })();
                link_pat.lastIndex = 0;
                while (true) {
                    m = link_pat.exec(text);
                    if (!m) {
                        break;
                    }
                    name = decode_url(m[1])[0];
                    if (ρσ_in(name, seen) || ρσ_in(name, already_pending)) {
                        continue;
                    }
                    seen.add(name);
                    pending_resources.push(name);
                }
            };
            if (!find_virtualized_resources.__argnames__) Object.defineProperties(find_virtualized_resources, {
                __argnames__ : {value: ["text"]}
            });

            do_one();
        };
        if (!load_resources.__argnames__) Object.defineProperties(load_resources, {
            __argnames__ : {value: ["book", "root_name", "previous_resources", "proceed"]}
        });

        mathjax_data = null;
        function load_mathjax(book, resource_data, proceed) {
            if (mathjax_data === null) {
                ui_operations.get_mathjax_files((function() {
                    var ρσ_anonfunc = function (data) {
                        mathjax_data = data;
                        resource_data["..mathjax-files.."] = data;
                        proceed(resource_data);
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["data"]}
                    });
                    return ρσ_anonfunc;
                })());
            } else {
                resource_data["..mathjax-files.."] = mathjax_data;
                proceed(resource_data);
            }
        };
        if (!load_mathjax.__argnames__) Object.defineProperties(load_mathjax, {
            __argnames__ : {value: ["book", "resource_data", "proceed"]}
        });

        function finalize_resources(book, root_name, resource_data) {
            var blob_url_map, root_data, link_pat, mathjax, ρσ_unpack, data, mimetype, name, unresolved_deps_map, resolved, num, text, unresolved_deps, unresolved;
            blob_url_map = Object.create(null);
            root_data = null;
            link_pat = create_link_pat(book);
            mathjax = resource_data["..mathjax-files.."];
            delete resource_data["..mathjax-files.."];
            var ρσ_Iter1 = ρσ_Iterable(resource_data);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                name = ρσ_Iter1[ρσ_Index1];
                ρσ_unpack = resource_data[(typeof name === "number" && name < 0) ? resource_data.length + name : name];
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                data = ρσ_unpack[0];
                mimetype = ρσ_unpack[1];
                if (typeof data !== "string") {
                    blob_url_map[(typeof name === "number" && name < 0) ? blob_url_map.length + name : name] = window.URL.createObjectURL(data);
                }
            }
            var ρσ_Iter2 = ρσ_Iterable(blob_url_map);
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                name = ρσ_Iter2[ρσ_Index2];
                delete resource_data[name];
            }
            function add_virtualized_resource(name, text, mimetype) {
                if (name === root_name) {
                    root_data = JSON.parse(text);
                } else {
                    blob_url_map[(typeof name === "number" && name < 0) ? blob_url_map.length + name : name] = window.URL.createObjectURL(new Blob(ρσ_list_decorate([ text ]), (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["type"] = mimetype;
                        return ρσ_d;
                    }).call(this)));
                }
            };
            if (!add_virtualized_resource.__argnames__) Object.defineProperties(add_virtualized_resource, {
                __argnames__ : {value: ["name", "text", "mimetype"]}
            });

            function replace_deps(text) {
                var replacements, unresolved_deps, m, ρσ_unpack, dname, frag, rtext, index, sz, repl;
                replacements = [];
                unresolved_deps = set();
                link_pat.lastIndex = 0;
                while (true) {
                    m = link_pat.exec(text);
                    if (!m) {
                        break;
                    }
                    ρσ_unpack = decode_url(m[1]);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    dname = ρσ_unpack[0];
                    frag = ρσ_unpack[1];
                    if (blob_url_map[(typeof dname === "number" && dname < 0) ? blob_url_map.length + dname : dname]) {
                        rtext = blob_url_map[(typeof dname === "number" && dname < 0) ? blob_url_map.length + dname : dname];
                        if (frag) {
                            rtext += "#" + frag;
                        }
                        replacements.push([m.index, m[0].length, rtext]);
                    } else {
                        unresolved_deps.add(dname);
                    }
                }
                var ρσ_Iter3 = ρσ_Iterable(reversed(replacements));
                for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                    ρσ_unpack = ρσ_flatten(ρσ_Iter3[ρσ_Index3]);
                    index = ρσ_unpack[0];
                    sz = ρσ_unpack[1];
                    repl = ρσ_unpack[2];
                    text = text.slice(0, index) + repl + text.slice(index + sz);
                }
                return [unresolved_deps, text];
            };
            if (!replace_deps.__argnames__) Object.defineProperties(replace_deps, {
                __argnames__ : {value: ["text"]}
            });

            unresolved_deps_map = Object.create(null);
            function has_unresolvable_deps(name) {
                var deps, x;
                deps = unresolved_deps_map[(typeof name === "number" && name < 0) ? unresolved_deps_map.length + name : name];
                if (!deps || !deps.length) {
                    return false;
                }
                var ρσ_Iter4 = ρσ_Iterable(deps);
                for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                    x = ρσ_Iter4[ρσ_Index4];
                    if (!blob_url_map[(typeof x === "number" && x < 0) ? blob_url_map.length + x : x]) {
                        return true;
                    }
                }
                return false;
            };
            if (!has_unresolvable_deps.__argnames__) Object.defineProperties(has_unresolvable_deps, {
                __argnames__ : {value: ["name"]}
            });

            while (true) {
                resolved = [];
                num = 0;
                var ρσ_Iter5 = ρσ_Iterable(resource_data);
                for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                    name = ρσ_Iter5[ρσ_Index5];
                    if (!blob_url_map[(typeof name === "number" && name < 0) ? blob_url_map.length + name : name]) {
                        num += 1;
                        ρσ_unpack = resource_data[(typeof name === "number" && name < 0) ? resource_data.length + name : name];
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                        text = ρσ_unpack[0];
                        mimetype = ρσ_unpack[1];
                        if (!has_unresolvable_deps(name)) {
                            ρσ_unpack = replace_deps(text);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                            unresolved_deps = ρσ_unpack[0];
                            text = ρσ_unpack[1];
                            unresolved_deps_map[(typeof name === "number" && name < 0) ? unresolved_deps_map.length + name : name] = unresolved_deps;
                            if (!unresolved_deps.length) {
                                add_virtualized_resource(name, text, mimetype);
                                resolved.push(name);
                            }
                        }
                    }
                }
                if (!num) {
                    break;
                }
                if (!resolved.length) {
                    unresolved = (function() {
                        var ρσ_Iter = ρσ_Iterable(resource_data), ρσ_Result = [], name;
                        for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                            name = ρσ_Iter[ρσ_Index];
                            if (!blob_url_map[(typeof name === "number" && name < 0) ? blob_url_map.length + name : name]) {
                                ρσ_Result.push(name);
                            }
                        }
                        ρσ_Result = ρσ_list_constructor(ρσ_Result);
                        return ρσ_Result;
                    })();
                    print("ERROR: Could not resolve all dependencies of {} because of a cyclic dependency. Remaining deps: {}".format(root_name, unresolved));
                    var ρσ_Iter6 = ρσ_Iterable(resource_data);
                    for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                        name = ρσ_Iter6[ρσ_Index6];
                        if (!blob_url_map[(typeof name === "number" && name < 0) ? blob_url_map.length + name : name]) {
                            ρσ_unpack = resource_data[(typeof name === "number" && name < 0) ? resource_data.length + name : name];
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                            text = ρσ_unpack[0];
                            mimetype = ρσ_unpack[1];
                            text = replace_deps(text)[1];
                            add_virtualized_resource(name, text, mimetype);
                        }
                    }
                    break;
                }
                var ρσ_Iter7 = ρσ_Iterable(resolved);
                for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                    name = ρσ_Iter7[ρσ_Index7];
                    delete resource_data[name];
                }
            }
            return [root_data, mathjax, blob_url_map];
        };
        if (!finalize_resources.__argnames__) Object.defineProperties(finalize_resources, {
            __argnames__ : {value: ["book", "root_name", "resource_data"]}
        });

        js_types = (function() {
            var ρσ_Iter = ρσ_Iterable("text/javascript text/ecmascript application/javascript application/ecmascript".split(" ")), ρσ_Result = Object.create(null), k;
            for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                k = ρσ_Iter[ρσ_Index];
                ρσ_Result[k] = (true);
            }
            return ρσ_Result;
        })();
        resource_tag_names = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["script"] = "src";
            ρσ_d["link"] = "href";
            ρσ_d["img"] = "src";
            ρσ_d["image"] = "xlink:href";
            return ρσ_d;
        }).call(this);
        ns_rmap = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["http://www.w3.org/2000/svg"] = "svg";
            ρσ_d["http://www.w3.org/1999/xlink"] = "xlink";
            ρσ_d["http://www.w3.org/1998/Math/MathML"] = "math";
            ρσ_d["http://www.w3.org/XML/1998/namespace"] = "xml";
            return ρσ_d;
        }).call(this);
        ns_count = 0;
        hide_tooltips = false;
        function get_prefix(ns) {
            var ans;
            ans = ns_rmap[(typeof ns === "number" && ns < 0) ? ns_rmap.length + ns : ns];
            if (!ans) {
                ns_rmap[(typeof ns === "number" && ns < 0) ? ns_rmap.length + ns : ns] = ans = "ns" + ns_count;
                ns_count += 1;
            }
            return ans + ":";
        };
        if (!get_prefix.__argnames__) Object.defineProperties(get_prefix, {
            __argnames__ : {value: ["ns"]}
        });

        function apply_attributes(src, elem, ns_map) {
            var attributes, ns, a;
            attributes = src.a;
            if (!attributes) {
                return;
            }
            var ρσ_Iter8 = ρσ_Iterable(attributes);
            for (var ρσ_Index8 = 0; ρσ_Index8 < ρσ_Iter8.length; ρσ_Index8++) {
                a = ρσ_Iter8[ρσ_Index8];
                if (a[2]) {
                    ns = ns_map[ρσ_bound_index(a[2], ns_map)];
                    elem.setAttributeNS(ns, get_prefix(ns) + a[0], a[1]);
                } else {
                    if (hide_tooltips && (a[0] === "title" || a[0] === "alt")) {
                        continue;
                    }
                    elem.setAttribute(a[0], a[1]);
                }
            }
        };
        if (!apply_attributes.__argnames__) Object.defineProperties(apply_attributes, {
            __argnames__ : {value: ["src", "elem", "ns_map"]}
        });

        function process_stack(stack, tag_map, ns_map, load_required, onload, resource_urls) {
            var ρσ_unpack, node, parent, src, elem, loadable, attr, a;
            while (stack.length) {
                ρσ_unpack = stack.pop();
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                node = ρσ_unpack[0];
                parent = ρσ_unpack[1];
                src = tag_map[ρσ_bound_index(node[0], tag_map)];
                if (src.s) {
                    elem = document.createElementNS(ns_map[ρσ_bound_index(src.s, ns_map)], src.n);
                } else {
                    elem = document.createElement(src.n);
                }
                loadable = false;
                attr = resource_tag_names[ρσ_bound_index(src.n, resource_tag_names)];
                if (attr) {
                    if (ρσ_not_equals(attr.indexOf(":"), -1)) {
                        attr = attr.replace("xlink:", "");
                    }
                    if (src.a) {
                        var ρσ_Iter9 = ρσ_Iterable(src.a);
                        for (var ρσ_Index9 = 0; ρσ_Index9 < ρσ_Iter9.length; ρσ_Index9++) {
                            a = ρσ_Iter9[ρσ_Index9];
                            if (a[0] === attr) {
                                loadable = a[1].startswith("blob:");
                                resource_urls[ρσ_bound_index(a[1], resource_urls)] = true;
                                break;
                            }
                        }
                    }
                }
                if (loadable) {
                    load_required.add(node[0]);
                    elem.addEventListener("load", onload.bind(node[0]));
                    elem.addEventListener("error", onload.bind(node[0]));
                }
                apply_attributes(src, elem, ns_map);
                parent.appendChild(elem);
                if (src.x) {
                    if (src.n === "script" && js_types[ρσ_bound_index((elem.getAttribute("type") || "text/javascript").toLowerCase(), js_types)] === true) {
                        elem.text = src.x;
                    } else {
                        elem.appendChild(document.createTextNode(src.x));
                    }
                }
                if (src.l) {
                    parent.appendChild(document.createTextNode(src.l));
                }
                for (var i = node.length - 1; i >= 1; i--) {
                    stack.push([node[i], elem]);
                }
            }
        };
        if (!process_stack.__argnames__) Object.defineProperties(process_stack, {
            __argnames__ : {value: ["stack", "tag_map", "ns_map", "load_required", "onload", "resource_urls"]}
        });

        function unserialize_html(serialized_data, proceed, postprocess_dom) {
            var tag_map, tree, ns_map, html, ρσ_unpack, head, body, resource_urls, load_required, proceeded, hang_timeout, stack, bnode, ev;
            tag_map = serialized_data.tag_map;
            tree = serialized_data.tree;
            ns_map = serialized_data.ns_map;
            html = tag_map[0];
            remove_all_attributes(document.documentElement);
            apply_attributes(html, document.documentElement, ns_map);
            ρσ_unpack = [tree[1], tree[2]];
            head = ρσ_unpack[0];
            body = ρσ_unpack[1];
            clear(document.head, document.body);
            remove_all_attributes(document.head, document.body);
            document.head.appendChild(ρσ_interpolate_kwargs.call(E, E.style, ["html::-webkit-scrollbar, body::-webkit-scrollbar { display: none !important }"].concat([ρσ_desugar_kwargs({type: "text/css"})])));
            if (!runtime.is_standalone_viewer) {
                document.head.appendChild(ρσ_interpolate_kwargs.call(E, E.style, ["html {{ font-family: {} }}".format(window.default_font_family || "sans-serif")].concat([ρσ_desugar_kwargs({type: "text/css"})])));
            }
            resource_urls = Object.create(null);
            load_required = set();
            proceeded = false;
            hang_timeout = 5;
            hide_tooltips = opts.hide_tooltips;
            function hangcheck() {
                if (!proceeded) {
                    proceeded = true;
                    print("WARNING: All resources did not load in {} seconds, proceeding anyway ({} resources left)".format(hang_timeout, load_required.length));
                    proceed();
                }
            };

            function onload() {
                load_required.discard(this);
                if (!load_required.length) {
                    proceeded = true;
                    proceed();
                }
            };

            stack = [];
            for (var i = head.length - 1; i >= 1; i--) {
                stack.push([head[i], document.head]);
            }
            process_stack(stack, tag_map, ns_map, load_required, onload, resource_urls);
            bnode = tag_map[ρσ_bound_index(body[0], tag_map)];
            apply_attributes(bnode, document.body, ns_map);
            if (bnode.x) {
                document.body.appendChild(document.createTextNode(bnode.x));
            }
            for (var i = body.length - 1; i >= 1; i--) {
                stack.push([body[i], document.body]);
            }
            process_stack(stack, tag_map, ns_map, load_required, onload, resource_urls);
            if (postprocess_dom) {
                postprocess_dom();
            }
            ev = document.createEvent("Event");
            ev.initEvent("DOMContentLoaded", true, true);
            document.dispatchEvent(ev);
            if (load_required.length) {
                setTimeout(hangcheck, hang_timeout * 1e3);
            } else {
                proceeded = true;
                proceed();
            }
            return resource_urls;
        };
        if (!unserialize_html.__argnames__) Object.defineProperties(unserialize_html, {
            __argnames__ : {value: ["serialized_data", "proceed", "postprocess_dom"]}
        });

        function text_from_serialized_html(data) {
            var serialized_data, tag_map, ans, stack, ignore_text, node, src;
            serialized_data = JSON.parse(data);
            tag_map = serialized_data.tag_map;
            ans = [];
            stack = [serialized_data.tree[2]];
            ignore_text = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["script"] = true;
                ρσ_d["style"] = true;
                return ρσ_d;
            }).call(this);
            while (stack.length) {
                node = stack.pop();
                if (typeof node === "string") {
                    ans.push(node);
                    continue;
                }
                src = tag_map[ρσ_bound_index(node[0], tag_map)];
                if (!ignore_text[ρσ_bound_index(src.n, ignore_text)] && src.x) {
                    ans.push(src.x);
                }
                if (src.l) {
                    stack.push(src.l);
                }
                for (var i = node.length - 1; i >= 1; i--) {
                    stack.push(node[(typeof i === "number" && i < 0) ? node.length + i : i]);
                }
            }
            return ans.join("");
        };
        if (!text_from_serialized_html.__argnames__) Object.defineProperties(text_from_serialized_html, {
            __argnames__ : {value: ["data"]}
        });

        ρσ_modules["read_book.resources"].JSON_XHTML_MIMETYPE = JSON_XHTML_MIMETYPE;
        ρσ_modules["read_book.resources"].mathjax_data = mathjax_data;
        ρσ_modules["read_book.resources"].js_types = js_types;
        ρσ_modules["read_book.resources"].k = k;
        ρσ_modules["read_book.resources"].resource_tag_names = resource_tag_names;
        ρσ_modules["read_book.resources"].ns_rmap = ns_rmap;
        ρσ_modules["read_book.resources"].ns_count = ns_count;
        ρσ_modules["read_book.resources"].hide_tooltips = hide_tooltips;
        ρσ_modules["read_book.resources"].decode_component = decode_component;
        ρσ_modules["read_book.resources"].decode_url = decode_url;
        ρσ_modules["read_book.resources"].create_link_pat = create_link_pat;
        ρσ_modules["read_book.resources"].load_resources = load_resources;
        ρσ_modules["read_book.resources"].load_mathjax = load_mathjax;
        ρσ_modules["read_book.resources"].finalize_resources = finalize_resources;
        ρσ_modules["read_book.resources"].get_prefix = get_prefix;
        ρσ_modules["read_book.resources"].apply_attributes = apply_attributes;
        ρσ_modules["read_book.resources"].process_stack = process_stack;
        ρσ_modules["read_book.resources"].unserialize_html = unserialize_html;
        ρσ_modules["read_book.resources"].text_from_serialized_html = text_from_serialized_html;
    })();

    (function(){
        var __name__ = "read_book.footnotes";
        var block_names, block_display_styles, ok_list_types;
        var clear = ρσ_modules.dom.clear;

        var IframeClient = ρσ_modules.iframe_comm.IframeClient;

        var finalize_resources = ρσ_modules["read_book.resources"].finalize_resources;
        var unserialize_html = ρσ_modules["read_book.resources"].unserialize_html;

        var apply_settings = ρσ_modules["read_book.settings"].apply_settings;
        var update_settings = ρσ_modules["read_book.settings"].update_settings;

        block_names = dict.fromkeys(['p', 'div', 'li', 'td', 'h1', 'h2', 'h2', 'h3', 'h4', 'h5', 'h6', 'body'], true).as_object();
        block_display_styles = dict.fromkeys(['block', 'list-item', 'table-cell', 'table'], true).as_object();
        function elem_roles(elem) {
            return (function() {
                var ρσ_Iter = ρσ_Iterable((elem.getAttribute("role") || "").split(" ")), ρσ_Result = Object.create(null), k;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    k = ρσ_Iter[ρσ_Index];
                    ρσ_Result[k.toLowerCase()] = (true);
                }
                return ρσ_Result;
            })();
        };
        if (!elem_roles.__argnames__) Object.defineProperties(elem_roles, {
            __argnames__ : {value: ["elem"]}
        });

        function get_containing_block(node) {
            while (node && node.tagName && block_names[ρσ_bound_index(node.tagName.toLowerCase(), block_names)] !== true) {
                node = node.parentNode;
            }
            return node;
        };
        if (!get_containing_block.__argnames__) Object.defineProperties(get_containing_block, {
            __argnames__ : {value: ["node"]}
        });

        function is_footnote_link(a, dest_name, dest_frag, src_name, link_to_map) {
            var roles, ρσ_unpack, x, num, style, children, text_children, eid, files_linking_to_self, files_linking_to_anchor, cb, ltext, ctext;
            roles = elem_roles(a);
            if (roles["doc-noteref"]) {
                return true;
            }
            if (roles["doc-link"]) {
                return false;
            }
            ρσ_unpack = [a, 3];
            x = ρσ_unpack[0];
            num = ρσ_unpack[1];
            while (x && num > 0) {
                style = window.getComputedStyle(x);
                if (!(ρσ_expr_temp = is_footnote_link.inline_displays)[ρσ_bound_index(style.display, ρσ_expr_temp)]) {
                    break;
                }
                if ((ρσ_expr_temp = is_footnote_link.vert_aligns)[ρσ_bound_index(style.verticalAlign, ρσ_expr_temp)]) {
                    return true;
                }
                x = x.parentNode;
                num -= 1;
            }
            children = (function() {
                var ρσ_Iter = ρσ_Iterable(a.childNodes), ρσ_Result = [], x;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    x = ρσ_Iter[ρσ_Index];
                    if (x.nodeType === Node.ELEMENT_NODE) {
                        ρσ_Result.push(x);
                    }
                }
                ρσ_Result = ρσ_list_constructor(ρσ_Result);
                return ρσ_Result;
            })();
            if ((children.length === 1 || typeof children.length === "object" && ρσ_equals(children.length, 1))) {
                style = window.getComputedStyle(children[0]);
                if ((ρσ_expr_temp = is_footnote_link.inline_displays)[ρσ_bound_index(style.display, ρσ_expr_temp)] && (ρσ_expr_temp = is_footnote_link.vert_aligns)[ρσ_bound_index(style.verticalAlign, ρσ_expr_temp)]) {
                    text_children = (function() {
                        var ρσ_Iter = ρσ_Iterable(a.childNodes), ρσ_Result = [], x;
                        for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                            x = ρσ_Iter[ρσ_Index];
                            if (x.nodeType === Node.TEXT_NODE && x.nodeValue && /\S+/.test(x.nodeValue)) {
                                ρσ_Result.push(x);
                            }
                        }
                        ρσ_Result = ρσ_list_constructor(ρσ_Result);
                        return ρσ_Result;
                    })();
                    if (!text_children.length) {
                        return true;
                    }
                }
            }
            eid = a.getAttribute("id") || a.getAttribute("name");
            files_linking_to_self = link_to_map[(typeof src_name === "number" && src_name < 0) ? link_to_map.length + src_name : src_name];
            if (eid && files_linking_to_self) {
                files_linking_to_anchor = files_linking_to_self[(typeof eid === "number" && eid < 0) ? files_linking_to_self.length + eid : eid];
                if (files_linking_to_anchor.length > 1 || (files_linking_to_anchor.length === 1 || typeof files_linking_to_anchor.length === "object" && ρσ_equals(files_linking_to_anchor.length, 1)) && files_linking_to_anchor[0] !== src_name) {
                    cb = get_containing_block(a);
                    if (!cb || ρσ_equals(cb.tagName.toLowerCase(), "body")) {
                        return false;
                    }
                    ltext = a.textContent;
                    if (!ltext) {
                        return false;
                    }
                    ctext = cb.textContent;
                    if (!ctext) {
                        return false;
                    }
                    if (ctext.strip() === ltext.strip()) {
                        return false;
                    }
                    return true;
                }
            }
            return false;
        };
        if (!is_footnote_link.__argnames__) Object.defineProperties(is_footnote_link, {
            __argnames__ : {value: ["a", "dest_name", "dest_frag", "src_name", "link_to_map"]}
        });

        is_footnote_link.inline_displays = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["inline"] = true;
            ρσ_d["inline-block"] = true;
            return ρσ_d;
        }).call(this);
        is_footnote_link.vert_aligns = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["sub"] = true;
            ρσ_d["super"] = true;
            ρσ_d["top"] = true;
            ρσ_d["bottom"] = true;
            return ρσ_d;
        }).call(this);
        function is_epub_footnote(node) {
            var roles;
            roles = elem_roles(node);
            if (roles["doc-note"] || roles["doc-footnote"] || roles["doc-rearnote"]) {
                return true;
            }
            return false;
        };
        if (!is_epub_footnote.__argnames__) Object.defineProperties(is_epub_footnote, {
            __argnames__ : {value: ["node"]}
        });

        function get_note_container(node) {
            while (node && block_names[ρσ_bound_index(node.tagName.toLowerCase(), block_names)] !== true && block_display_styles[ρσ_bound_index(window.getComputedStyle(node).display, block_display_styles)] !== true) {
                node = node.parentNode;
            }
            return node;
        };
        if (!get_note_container.__argnames__) Object.defineProperties(get_note_container, {
            __argnames__ : {value: ["node"]}
        });

        function get_parents_and_self(node) {
            var ans;
            ans = [];
            while (node && node !== document.body) {
                ans.push(node);
                node = node.parentNode;
            }
            return ans;
        };
        if (!get_parents_and_self.__argnames__) Object.defineProperties(get_parents_and_self, {
            __argnames__ : {value: ["node"]}
        });

        function get_page_break(node) {
            var style;
            style = window.getComputedStyle(node);
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["before"] = (ρσ_expr_temp = get_page_break.on)[ρσ_bound_index(style.getPropertyValue("page-break-before"), ρσ_expr_temp)] === true;
                ρσ_d["after"] = (ρσ_expr_temp = get_page_break.on)[ρσ_bound_index(style.getPropertyValue("page-break-after"), ρσ_expr_temp)] === true;
                return ρσ_d;
            }).call(this);
        };
        if (!get_page_break.__argnames__) Object.defineProperties(get_page_break, {
            __argnames__ : {value: ["node"]}
        });

        get_page_break.on = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["always"] = true;
            ρσ_d["left"] = true;
            ρσ_d["right"] = true;
            return ρσ_d;
        }).call(this);
        function hide_children(node) {
            var child;
            var ρσ_Iter0 = ρσ_Iterable(node.childNodes);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                child = ρσ_Iter0[ρσ_Index0];
                if (child.nodeType === Node.ELEMENT_NODE) {
                    if (child.do_not_hide) {
                        hide_children(child);
                        delete child.do_not_hide;
                    } else {
                        child.style.display = "none";
                    }
                }
            }
        };
        if (!hide_children.__argnames__) Object.defineProperties(hide_children, {
            __argnames__ : {value: ["node"]}
        });

        function unhide_tree(elem) {
            var c;
            elem.do_not_hide = true;
            var ρσ_Iter1 = ρσ_Iterable(elem.getElementsByTagName("*"));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                c = ρσ_Iter1[ρσ_Index1];
                c.do_not_hide = true;
            }
        };
        if (!unhide_tree.__argnames__) Object.defineProperties(unhide_tree, {
            __argnames__ : {value: ["elem"]}
        });

        ok_list_types = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["disc"] = true;
            ρσ_d["circle"] = true;
            ρσ_d["square"] = true;
            return ρσ_d;
        }).call(this);
        function show_footnote(target, known_anchors) {
            var start_elem, style, elem, found_note_start, eid, pb;
            if (!target) {
                return;
            }
            start_elem = document.getElementById(target);
            if (!start_elem) {
                return;
            }
            start_elem = get_note_container(start_elem);
            var ρσ_Iter2 = ρσ_Iterable(get_parents_and_self(start_elem));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                elem = ρσ_Iter2[ρσ_Index2];
                elem.do_not_hide = true;
                style = window.getComputedStyle(elem);
                if (style.display === "list-item" && ok_list_types[ρσ_bound_index(style.listStyleType, ok_list_types)] !== true) {
                    elem.style.listStyleType = "none";
                }
            }
            if (is_epub_footnote(start_elem)) {
                unhide_tree(start_elem);
            } else {
                found_note_start = false;
                var ρσ_Iter3 = ρσ_Iterable(document.body.getElementsByTagName("*"));
                for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                    elem = ρσ_Iter3[ρσ_Index3];
                    if (found_note_start) {
                        eid = elem.getAttribute("id");
                        if (eid !== target && known_anchors[(typeof eid === "number" && eid < 0) ? known_anchors.length + eid : eid] && get_note_container(elem) !== start_elem) {
                            delete get_note_container(elem).do_not_hide;
                            break;
                        }
                        pb = get_page_break(elem);
                        if (pb.before) {
                            break;
                        }
                        if (pb.after) {
                            unhide_tree(elem);
                            break;
                        }
                        elem.do_not_hide = true;
                    } else if (elem === start_elem) {
                        found_note_start = true;
                    }
                }
            }
            hide_children(document.body);
            window.location.hash = "#" + target;
        };
        if (!show_footnote.__argnames__) Object.defineProperties(show_footnote, {
            __argnames__ : {value: ["target", "known_anchors"]}
        });

        function PopupIframeBoss() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            PopupIframeBoss.prototype.__bind_methods__.call(this);
            PopupIframeBoss.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(PopupIframeBoss.prototype, "__bind_methods__", {value: function () {
            this.initialize = PopupIframeBoss.prototype.initialize.bind(this);
            this.onerror = PopupIframeBoss.prototype.onerror.bind(this);
            this.display = PopupIframeBoss.prototype.display.bind(this);
            this.on_clear = PopupIframeBoss.prototype.on_clear.bind(this);
            this.show_only_footnote = PopupIframeBoss.prototype.show_only_footnote.bind(this);
            this.content_loaded = PopupIframeBoss.prototype.content_loaded.bind(this);
        }});
        PopupIframeBoss.prototype.__init__ = function __init__() {
            var self = this;
            var handlers;
            handlers = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["initialize"] = self.initialize;
                ρσ_d["clear"] = self.on_clear;
                ρσ_d["display"] = self.display;
                return ρσ_d;
            }).call(this);
            self.comm = new IframeClient(handlers);
            self.blob_url_map = Object.create(null);
            self.name = null;
            self.frag = null;
        };
        PopupIframeBoss.__argnames__ = PopupIframeBoss.prototype.__init__.__argnames__;
        PopupIframeBoss.__handles_kwarg_interpolation__ = PopupIframeBoss.prototype.__init__.__handles_kwarg_interpolation__;
        PopupIframeBoss.prototype.initialize = function initialize(data) {
            var self = this;
            window.onerror = self.onerror;
        };
        if (!PopupIframeBoss.prototype.initialize.__argnames__) Object.defineProperties(PopupIframeBoss.prototype.initialize, {
            __argnames__ : {value: ["data"]}
        });
        PopupIframeBoss.prototype.onerror = function onerror(msg, script_url, line_number, column_number, error_object) {
            var self = this;
            if (error_object === null) {
                console.log("Unhandled error from external javascript, ignoring: " + ρσ_str.format("{}", msg) + " " + ρσ_str.format("{}", script_url) + " " + ρσ_str.format("{}", line_number) + "");
            } else {
                console.log(error_object);
            }
        };
        if (!PopupIframeBoss.prototype.onerror.__argnames__) Object.defineProperties(PopupIframeBoss.prototype.onerror, {
            __argnames__ : {value: ["msg", "script_url", "line_number", "column_number", "error_object"]}
        });
        PopupIframeBoss.prototype.display = function display(data) {
            var self = this;
            var name, ρσ_unpack, root_data;
            self.book = data.book;
            self.name = data.name;
            self.frag = data.frag;
            var ρσ_Iter4 = ρσ_Iterable(self.blob_url_map);
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                name = ρσ_Iter4[ρσ_Index4];
                window.URL.revokeObjectURL((ρσ_expr_temp = self.blob_url_map)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name]);
            }
            document.body.style.removeProperty("font-family");
            ρσ_unpack = finalize_resources(self.book, data.name, data.resource_data);
ρσ_unpack = ρσ_unpack_asarray(3, ρσ_unpack);
            root_data = ρσ_unpack[0];
            self.mathjax = ρσ_unpack[1];
            self.blob_url_map = ρσ_unpack[2];
            self.resource_urls = unserialize_html(root_data, self.content_loaded, self.show_only_footnote);
            update_settings(data.settings);
        };
        if (!PopupIframeBoss.prototype.display.__argnames__) Object.defineProperties(PopupIframeBoss.prototype.display, {
            __argnames__ : {value: ["data"]}
        });
        PopupIframeBoss.prototype.on_clear = function on_clear(data) {
            var self = this;
            clear(document.head);
            clear(document.body);
            document.body.textContent = data.text;
            self.name = null;
            self.frag = null;
        };
        if (!PopupIframeBoss.prototype.on_clear.__argnames__) Object.defineProperties(PopupIframeBoss.prototype.on_clear, {
            __argnames__ : {value: ["data"]}
        });
        PopupIframeBoss.prototype.show_only_footnote = function show_only_footnote() {
            var self = this;
            var known_anchors, ltm, k;
            known_anchors = Object.create(null);
            ltm = (ρσ_expr_temp = ρσ_exists.d(self.book.manifest.link_to_map))[ρσ_bound_index(self.name, ρσ_expr_temp)];
            if (ltm) {
                known_anchors = (function() {
                    var ρσ_Iter = ρσ_Iterable(Object.keys(ltm)), ρσ_Result = Object.create(null), k;
                    for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                        k = ρσ_Iter[ρσ_Index];
                        ρσ_Result[k] = (true);
                    }
                    return ρσ_Result;
                })();
            }
            show_footnote(self.frag, known_anchors);
        };
        PopupIframeBoss.prototype.content_loaded = function content_loaded() {
            var self = this;
            apply_settings();
            ρσ_interpolate_kwargs.call(self.comm, self.comm.send_message, ["content_loaded"].concat([ρσ_desugar_kwargs({height: document.documentElement.scrollHeight + 25})]));
        };
        PopupIframeBoss.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        PopupIframeBoss.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(PopupIframeBoss.prototype, "__bases__", {value: []});

        function main() {
            main.boss = new PopupIframeBoss;
        };

        ρσ_modules["read_book.footnotes"].block_names = block_names;
        ρσ_modules["read_book.footnotes"].block_display_styles = block_display_styles;
        ρσ_modules["read_book.footnotes"].ok_list_types = ok_list_types;
        ρσ_modules["read_book.footnotes"].elem_roles = elem_roles;
        ρσ_modules["read_book.footnotes"].get_containing_block = get_containing_block;
        ρσ_modules["read_book.footnotes"].is_footnote_link = is_footnote_link;
        ρσ_modules["read_book.footnotes"].is_epub_footnote = is_epub_footnote;
        ρσ_modules["read_book.footnotes"].get_note_container = get_note_container;
        ρσ_modules["read_book.footnotes"].get_parents_and_self = get_parents_and_self;
        ρσ_modules["read_book.footnotes"].get_page_break = get_page_break;
        ρσ_modules["read_book.footnotes"].hide_children = hide_children;
        ρσ_modules["read_book.footnotes"].unhide_tree = unhide_tree;
        ρσ_modules["read_book.footnotes"].show_footnote = show_footnote;
        ρσ_modules["read_book.footnotes"].PopupIframeBoss = PopupIframeBoss;
        ρσ_modules["read_book.footnotes"].main = main;
    })();

    (function(){
        var __name__ = "read_book.viewport";
        var FUNCTIONS, scroll_viewport, attr;
        FUNCTIONS = "x y scroll_to scroll_into_view reset_globals reset_transforms".split(" ");
        var get_boss = ρσ_modules["read_book.globals"].get_boss;
        var viewport_mode_changer = ρσ_modules["read_book.globals"].viewport_mode_changer;

        var is_ios = ρσ_modules.utils.is_ios;

        function ScrollViewport() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            ScrollViewport.prototype.__bind_methods__.call(this);
            ScrollViewport.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(ScrollViewport.prototype, "__bind_methods__", {value: function () {
            this.set_mode = ScrollViewport.prototype.set_mode.bind(this);
            this.flow_x = ScrollViewport.prototype.flow_x.bind(this);
            this.flow_y = ScrollViewport.prototype.flow_y.bind(this);
            this.paged_y = ScrollViewport.prototype.paged_y.bind(this);
            this.flow_scroll_to = ScrollViewport.prototype.flow_scroll_to.bind(this);
            this.flow_scroll_into_view = ScrollViewport.prototype.flow_scroll_into_view.bind(this);
            this.flow_reset_globals = ScrollViewport.prototype.flow_reset_globals.bind(this);
            this.flow_reset_transforms = ScrollViewport.prototype.flow_reset_transforms.bind(this);
            this.paged_content_width = ScrollViewport.prototype.paged_content_width.bind(this);
            this.update_window_size = ScrollViewport.prototype.update_window_size.bind(this);
            this.width = ScrollViewport.prototype.width.bind(this);
            this.height = ScrollViewport.prototype.height.bind(this);
        }});
        ScrollViewport.prototype.__init__ = function __init__() {
            var self = this;
            self.set_mode("flow");
            self.window_width_from_parent = self.window_height_from_parent = null;
        };
        ScrollViewport.__argnames__ = ScrollViewport.prototype.__init__.__argnames__;
        ScrollViewport.__handles_kwarg_interpolation__ = ScrollViewport.prototype.__init__.__handles_kwarg_interpolation__;
        ScrollViewport.prototype.set_mode = function set_mode(mode) {
            var self = this;
            var prefix, attr;
            prefix = ((mode === "flow") ? "flow" : "paged") + "_";
            var ρσ_Iter0 = ρσ_Iterable(FUNCTIONS);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                attr = ρσ_Iter0[ρσ_Index0];
                self[(typeof attr === "number" && attr < 0) ? self.length + attr : attr] = self[ρσ_bound_index(prefix + attr, self)];
            }
        };
        if (!ScrollViewport.prototype.set_mode.__argnames__) Object.defineProperties(ScrollViewport.prototype.set_mode, {
            __argnames__ : {value: ["mode"]}
        });
        ScrollViewport.prototype.flow_x = function flow_x() {
            var self = this;
            return window.pageXOffset;
        };
        ScrollViewport.prototype.flow_y = function flow_y() {
            var self = this;
            return window.pageYOffset;
        };
        ScrollViewport.prototype.paged_y = function paged_y() {
            var self = this;
            return 0;
        };
        ScrollViewport.prototype.flow_scroll_to = function flow_scroll_to(x, y) {
            var self = this;
            window.scrollTo(x, y);
        };
        if (!ScrollViewport.prototype.flow_scroll_to.__argnames__) Object.defineProperties(ScrollViewport.prototype.flow_scroll_to, {
            __argnames__ : {value: ["x", "y"]}
        });
        ScrollViewport.prototype.flow_scroll_into_view = function flow_scroll_into_view(elem) {
            var self = this;
            elem.scrollIntoView();
        };
        if (!ScrollViewport.prototype.flow_scroll_into_view.__argnames__) Object.defineProperties(ScrollViewport.prototype.flow_scroll_into_view, {
            __argnames__ : {value: ["elem"]}
        });
        ScrollViewport.prototype.flow_reset_globals = function flow_reset_globals() {
            var self = this;
        };
        ScrollViewport.prototype.flow_reset_transforms = function flow_reset_transforms() {
            var self = this;
        };
        ScrollViewport.prototype.paged_content_width = function paged_content_width() {
            var self = this;
            return document.documentElement.scrollWidth;
        };
        ScrollViewport.prototype.update_window_size = function update_window_size(w, h) {
            var self = this;
            self.window_width_from_parent = w;
            self.window_height_from_parent = h;
        };
        if (!ScrollViewport.prototype.update_window_size.__argnames__) Object.defineProperties(ScrollViewport.prototype.update_window_size, {
            __argnames__ : {value: ["w", "h"]}
        });
        ScrollViewport.prototype.width = function width() {
            var self = this;
            return window.innerWidth;
        };
        ScrollViewport.prototype.height = function height() {
            var self = this;
            return window.innerHeight;
        };
        ScrollViewport.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        ScrollViewport.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(ScrollViewport.prototype, "__bases__", {value: []});

        function IOSScrollViewport() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            IOSScrollViewport.prototype.__bind_methods__.call(this);
            IOSScrollViewport.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(IOSScrollViewport, ScrollViewport);
        Object.defineProperty(IOSScrollViewport.prototype, "__bind_methods__", {value: function () {
            ScrollViewport.prototype.__bind_methods__ && ScrollViewport.prototype.__bind_methods__.call(this);
            this.width = IOSScrollViewport.prototype.width.bind(this);
            this.height = IOSScrollViewport.prototype.height.bind(this);
            this._scroll_implementation = IOSScrollViewport.prototype._scroll_implementation.bind(this);
            this.paged_scroll_to = IOSScrollViewport.prototype.paged_scroll_to.bind(this);
            this.paged_x = IOSScrollViewport.prototype.paged_x.bind(this);
            this.paged_scroll_into_view = IOSScrollViewport.prototype.paged_scroll_into_view.bind(this);
            this.paged_reset_transforms = IOSScrollViewport.prototype.paged_reset_transforms.bind(this);
            this.paged_reset_globals = IOSScrollViewport.prototype.paged_reset_globals.bind(this);
        }});
        IOSScrollViewport.prototype.__init__ = function __init__ () {
            ScrollViewport.prototype.__init__ && ScrollViewport.prototype.__init__.apply(this, arguments);
        };
        IOSScrollViewport.prototype.width = function width() {
            var self = this;
            return self.window_width_from_parent || window.innerWidth;
        };
        IOSScrollViewport.prototype.height = function height() {
            var self = this;
            return self.window_height_from_parent || window.innerHeight;
        };
        IOSScrollViewport.prototype._scroll_implementation = function _scroll_implementation(x) {
            var self = this;
            if (x === 0) {
                document.documentElement.style.transform = "none";
            } else {
                x *= -1;
                document.documentElement.style.transform = "translateX(" + ρσ_str.format("{}", x) + "px)";
            }
        };
        if (!IOSScrollViewport.prototype._scroll_implementation.__argnames__) Object.defineProperties(IOSScrollViewport.prototype._scroll_implementation, {
            __argnames__ : {value: ["x"]}
        });
        IOSScrollViewport.prototype.paged_scroll_to = function paged_scroll_to(x, y) {
            var self = this;
            var boss;
            self._scroll_implementation(x);
            boss = get_boss();
            if (boss) {
                boss.onscroll();
            }
        };
        if (!IOSScrollViewport.prototype.paged_scroll_to.__argnames__) Object.defineProperties(IOSScrollViewport.prototype.paged_scroll_to, {
            __argnames__ : {value: ["x", "y"]}
        });
        IOSScrollViewport.prototype.paged_x = function paged_x() {
            var self = this;
            var raw, ans;
            raw = document.documentElement.style.transform;
            if (!raw || raw === "none") {
                return 0;
            }
            raw = raw.slice(raw.indexOf("(") + 1);
            ans = parseInt(raw);
            if (isNaN(ans)) {
                return 0;
            }
            ans *= -1;
            return ans;
        };
        IOSScrollViewport.prototype.paged_scroll_into_view = function paged_scroll_into_view(elem) {
            var self = this;
            var left, p;
            left = elem.offsetLeft;
            if (left === null) {
                return;
            }
            elem.scrollIntoView();
            window.scrollTo(0, 0);
            p = elem.offsetParent;
            while (p) {
                left += p.offsetLeft;
                p = p.offsetParent;
            }
            self._scroll_implementation(max(0, left));
        };
        if (!IOSScrollViewport.prototype.paged_scroll_into_view.__argnames__) Object.defineProperties(IOSScrollViewport.prototype.paged_scroll_into_view, {
            __argnames__ : {value: ["elem"]}
        });
        IOSScrollViewport.prototype.paged_reset_transforms = function paged_reset_transforms() {
            var self = this;
            document.documentElement.style.transform = "none";
        };
        IOSScrollViewport.prototype.paged_reset_globals = function paged_reset_globals() {
            var self = this;
            self.paged_reset_transforms();
        };
        IOSScrollViewport.prototype.__repr__ = function __repr__ () {
            if(ScrollViewport.prototype.__repr__) return ScrollViewport.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        IOSScrollViewport.prototype.__str__ = function __str__ () {
            if(ScrollViewport.prototype.__str__) return ScrollViewport.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(IOSScrollViewport.prototype, "__bases__", {value: [ScrollViewport]});

        if (is_ios) {
            scroll_viewport = new IOSScrollViewport;
        } else {
            scroll_viewport = new ScrollViewport;
        }
        var ρσ_Iter1 = ρσ_Iterable(FUNCTIONS);
        for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
            attr = ρσ_Iter1[ρσ_Index1];
            if (!scroll_viewport[ρσ_bound_index("paged_" + attr, scroll_viewport)]) {
                scroll_viewport[ρσ_bound_index("paged_" + attr, scroll_viewport)] = scroll_viewport[(typeof attr === "number" && attr < 0) ? scroll_viewport.length + attr : attr];
            }
        }
        viewport_mode_changer(scroll_viewport.set_mode);
        ρσ_modules["read_book.viewport"].FUNCTIONS = FUNCTIONS;
        ρσ_modules["read_book.viewport"].scroll_viewport = scroll_viewport;
        ρσ_modules["read_book.viewport"].attr = attr;
        ρσ_modules["read_book.viewport"].ScrollViewport = ScrollViewport;
        ρσ_modules["read_book.viewport"].IOSScrollViewport = IOSScrollViewport;
    })();

    (function(){
        var __name__ = "read_book.cfi";
        var escape_pat, unescape_pat, t;
        var scroll_viewport = ρσ_modules["read_book.viewport"].scroll_viewport;

        escape_pat = /[\[\],^();~@!-]/g;
        unescape_pat = /[\^](.)/g;
        function escape_for_cfi(raw) {
            return (raw || "").replace(escape_pat, "^$&");
        };
        if (!escape_for_cfi.__argnames__) Object.defineProperties(escape_for_cfi, {
            __argnames__ : {value: ["raw"]}
        });

        function unescape_from_cfi(raw) {
            return (raw || "").replace(unescape_pat, "$1");
        };
        if (!unescape_from_cfi.__argnames__) Object.defineProperties(unescape_from_cfi, {
            __argnames__ : {value: ["raw"]}
        });

        function fstr(d) {
            var ans, n;
            ans = "";
            if (d < 0) {
                ans = "-";
                d = -d;
            }
            n = Math.floor(d);
            ans += n;
            n = Math.round((d - n) * 100);
            if (n !== 0) {
                ans += "." + ((n % 10 === 0) ? n / 10 : n);
            }
            return ans;
        };
        if (!fstr.__argnames__) Object.defineProperties(fstr, {
            __argnames__ : {value: ["d"]}
        });

        function get_current_time(target) {
            return fstr(target.currentTime || 0);
        };
        if (!get_current_time.__argnames__) Object.defineProperties(get_current_time, {
            __argnames__ : {value: ["target"]}
        });

        function window_scroll_pos(w) {
            w = w || window;
            return [w.pageXOffset, w.pageYOffset];
        };
        if (!window_scroll_pos.__argnames__) Object.defineProperties(window_scroll_pos, {
            __argnames__ : {value: ["w"]}
        });

        function viewport_to_document(x, y, doc) {
            var frame, rect, ρσ_unpack, wx, wy;
            doc = doc || window.document;
            while (doc !== window.document) {
                frame = doc.defaultView.frameElement;
                rect = frame.getBoundingClientRect();
                x += rect.left;
                y += rect.top;
                doc = frame.ownerDocument;
            }
            ρσ_unpack = window_scroll_pos(doc.defaultView);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            wx = ρσ_unpack[0];
            wy = ρσ_unpack[1];
            x += wx;
            y += wy;
            return [x, y];
        };
        if (!viewport_to_document.__argnames__) Object.defineProperties(viewport_to_document, {
            __argnames__ : {value: ["x", "y", "doc"]}
        });

        function range_has_point(range_, x, y) {
            var rects, rect;
            rects = range_.getClientRects();
            for (var i = 0; i < rects.length; i++) {
                rect = rects[(typeof i === "number" && i < 0) ? rects.length + i : i];
                if (rect.left <= x && x <= rect.right && rect.top <= y && y <= rect.bottom) {
                    return true;
                }
            }
            return false;
        };
        if (!range_has_point.__argnames__) Object.defineProperties(range_has_point, {
            __argnames__ : {value: ["range_", "x", "y"]}
        });

        function offset_in_text_node(node, range_, x, y) {
            var limits, pivot, lr, rr;
            limits = [0, node.nodeValue.length];
            while (limits[0] !== limits[1]) {
                pivot = Math.floor((limits[0] + limits[1]) / 2);
                lr = [limits[0], pivot];
                rr = [pivot+1, limits[1]];
                range_.setStart(node, pivot);
                range_.setEnd(node, pivot + 1);
                if (range_has_point(range_, x, y)) {
                    return pivot;
                }
                range_.setStart(node, rr[0]);
                range_.setEnd(node, rr[1]);
                if (range_has_point(range_, x, y)) {
                    limits = rr;
                    continue;
                }
                range_.setStart(node, lr[0]);
                range_.setEnd(node, lr[1]);
                if (range_has_point(range_, x, y)) {
                    limits = lr;
                    continue;
                }
                break;
            }
            return limits[0];
        };
        if (!offset_in_text_node.__argnames__) Object.defineProperties(offset_in_text_node, {
            __argnames__ : {value: ["node", "range_", "x", "y"]}
        });

        function find_offset_for_point(x, y, node, cdoc) {
            var range_, child;
            range_ = cdoc.createRange();
            child = node.firstChild;
            while (child) {
                if (Node.TEXT_NODE <= (ρσ_cond_temp = child.nodeType) && ρσ_cond_temp <= Node.ENTITY_NODE && child.nodeValue && child.nodeValue.length) {
                    range_.setStart(child, 0);
                    range_.setEnd(child, child.nodeValue.length);
                    if (range_has_point(range_, x, y)) {
                        return [child, offset_in_text_node(child, range_, x, y)];
                    }
                }
                child = child.nextSibling;
            }
            throw new ValueError(str.format("Point ({}, {}) is in the padding/border of the node, so cannot calculate offset", x, y));
        };
        if (!find_offset_for_point.__argnames__) Object.defineProperties(find_offset_for_point, {
            __argnames__ : {value: ["x", "y", "node", "cdoc"]}
        });

        function set_current_time(target, val) {
            if (target.currentTime === undefined) {
                return;
            }
            if (target.readyState === 4 || target.readyState === "complete") {
                target.currentTime = val + 0;
            } else {
                target.addEventListener("canplay", function () {
                    target.currentTime = val;
                }, false);
            }
        };
        if (!set_current_time.__argnames__) Object.defineProperties(set_current_time, {
            __argnames__ : {value: ["target", "val"]}
        });

        function encode(doc, node, offset, tail) {
            var cfi, p, win, index, child, id, idspec;
            cfi = tail || "";
            if (node.nodeType === Node.ELEMENT_NODE) {
                if (typeof offset === "number") {
                    node = node.childNodes.item(offset);
                }
            } else if (Node.TEXT_NODE <= (ρσ_cond_temp = node.nodeType) && ρσ_cond_temp <= Node.ENTITY_NODE) {
                offset = offset || 0;
                while (true) {
                    p = node.previousSibling;
                    if (!p || p.nodeType > Node.COMMENT_NODE) {
                        break;
                    }
                    if (!ρσ_in(p.nodeType, [Node.ATTRIBUTE_NODE, Node.COMMENT_NODE]) && p.nodeValue && p.nodeValue.length) {
                        offset += p.nodeValue.length;
                    }
                    node = p;
                }
                cfi = ":" + offset + cfi;
            } else {
                print(str.format("Offsets for nodes of type {} are not handled", node.nodeType));
            }
            while (node !== doc) {
                p = node.parentNode;
                if (!p) {
                    if ((node.nodeType === Node.DOCUMENT_NODE || typeof node.nodeType === "object" && ρσ_equals(node.nodeType, Node.DOCUMENT_NODE))) {
                        win = node.defaultView;
                        if (win.frameElement) {
                            node = win.frameElement;
                            cfi = "!" + cfi;
                            continue;
                        }
                    }
                    break;
                }
                index = 0;
                child = p.firstChild;
                while (true) {
                    index |= 1;
                    if (child.nodeType === Node.ELEMENT_NODE) {
                        index += 1;
                    }
                    if (child === node) {
                        break;
                    }
                    child = child.nextSibling;
                }
                id = (node.getAttribute) ? node.getAttribute("id") : null;
                idspec = (id) ? "[" + escape_for_cfi(id) + "]" : "";
                cfi = "/" + index + idspec + cfi;
                node = p;
            }
            return cfi;
        };
        if (!encode.__argnames__) Object.defineProperties(encode, {
            __argnames__ : {value: ["doc", "node", "offset", "tail"]}
        });

        function decode(cfi, doc) {
            var simple_node_regex, error, node, r, target, assertion, index, child, point, offset, l, next, nn;
            doc = doc || window.document;
            simple_node_regex = /^\/(\d+)(\[[^\]]*\])?/;
            error = null;
            node = doc;
            while (cfi.length > 0 && !error) {
                r = cfi.match(simple_node_regex);
                if (r) {
                    target = parseInt(r[1]);
                    assertion = r[2];
                    if (assertion) {
                        assertion = unescape_from_cfi(assertion.slice(1, assertion.length - 1));
                    }
                    index = 0;
                    child = node.firstChild;
                    while (true) {
                        if (!child) {
                            if (assertion) {
                                child = doc.getElementById(assertion);
                                if (child) {
                                    node = child;
                                }
                            }
                            if (!child) {
                                error = "No matching child found for CFI: " + cfi;
                            }
                            cfi = cfi.substr(r[0].length);
                            break;
                        }
                        index |= 1;
                        if (child.nodeType === 1) {
                            index += 1;
                        }
                        if (index === target) {
                            cfi = cfi.substr(r[0].length);
                            node = child;
                            if (assertion && node.id !== assertion) {
                                child = doc.getElementById(assertion);
                                if (child) {
                                    node = child;
                                }
                            }
                            break;
                        }
                        child = child.nextSibling;
                    }
                } else if (cfi[0] === "!") {
                    if (node.contentDocument) {
                        node = node.contentDocument;
                        cfi = cfi.substr(1);
                    } else {
                        error = "Cannot reference " + node.nodeName + "'s content: " + cfi;
                    }
                } else {
                    break;
                }
            }
            if (error) {
                print(error);
                return null;
            }
            point = Object.create(null);
            error = null;
            offset = null;
            r = cfi.match(/^:(\d+)/);
            if (r) {
                offset = parseInt(r[1]);
                cfi = cfi.substr(r[0].length);
            }
            r = cfi.match(/^~(-?\d+(\.\d+)?)/);
            if (r) {
                point.time = r[1] - 0;
                cfi = cfi.substr(r[0].length);
            }
            r = cfi.match(/^@(-?\d+(\.\d+)?):(-?\d+(\.\d+)?)/);
            if (r) {
                point.x = r[1] - 0;
                point.y = r[3] - 0;
                cfi = cfi.substr(r[0].length);
            }
            r = cfi.match(/^\[([^\]]+)\]/);
            if (r) {
                assertion = r[1];
                cfi = cfi.substr(r[0].length);
                r = assertion.match(/;s=([ab])$/);
                if (r) {
                    if (r.index > 0 && assertion[ρσ_bound_index(r.index - 1, assertion)] !== "^") {
                        assertion = assertion.substr(0, r.index);
                        point.forward = r[1] === "a";
                    }
                    assertion = unescape_from_cfi(assertion);
                }
            }
            if (node && node.parentNode) {
                node.parentNode.normalize();
            }
            if (offset !== null) {
                while (true) {
                    l = node.nodeValue.length;
                    if (offset < l || !point.forward && offset === l) {
                        break;
                    }
                    next = false;
                    while (true) {
                        nn = node.nextSibling;
                        if (!nn) {
                            break;
                        }
                        if (Node.TEXT_NODE <= (ρσ_cond_temp = nn.nodeType) && ρσ_cond_temp <= Node.ENTITY_NODE && nn.nodeValue && nn.nodeValue.length) {
                            next = nn;
                            break;
                        }
                        node = nn;
                    }
                    if (!next) {
                        if (offset > l) {
                            error = "Offset out of range: " + offset;
                            offset = l;
                        }
                        break;
                    }
                    node = next;
                    offset -= l;
                }
                point.offset = offset;
            }
            point.node = node;
            if (error) {
                point.error = error;
            } else if (cfi.length > 0) {
                point.error = "Undecoded CFI: " + cfi;
            }
            if (point.error) {
                print(point.error);
            }
            return point;
        };
        if (!decode.__argnames__) Object.defineProperties(decode, {
            __argnames__ : {value: ["cfi", "doc"]}
        });

        function cfi_sort_key(cfi) {
            var simple_node_regex, steps, r, target, ans, offset;
            simple_node_regex = /^\/(\d+)(\[[^\]]*\])?/;
            steps = [];
            while (cfi.length > 0) {
                r = cfi.match(simple_node_regex);
                if (r) {
                    target = parseInt(r[1]);
                    cfi = cfi.substr(r[0].length);
                    steps.push(target);
                } else if (cfi[0] === "!") {
                    cfi = cfi.substr(1);
                } else {
                    break;
                }
            }
            ans = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["steps"] = steps;
                ρσ_d["text_offset"] = 0;
                ρσ_d["temporal_offset"] = 0;
                ρσ_d["spatial_offset"] = [0, 0];
                return ρσ_d;
            }).call(this);
            r = cfi.match(/^:(\d+)/);
            if (r) {
                offset = parseInt(r[1]);
                ans["text_offset"] = offset;
                cfi = cfi.substr(r[0].length);
            }
            r = cfi.match(/^~(-?\d+(\.\d+)?)/);
            if (r) {
                ans["temporal_offset"] = r[1] - 0;
                cfi = cfi.substr(r[0].length);
            }
            r = cfi.match(/^@(-?\d+(\.\d+)?):(-?\d+(\.\d+)?)/);
            if (r) {
                ans["spatial_offset"] = [r[1] - 0, r[3] - 0];
                cfi = cfi.substr(r[0].length);
            }
            return ans;
        };
        if (!cfi_sort_key.__argnames__) Object.defineProperties(cfi_sort_key, {
            __argnames__ : {value: ["cfi"]}
        });

        function sort_cfis(array_of_cfis) {
            var key_map, cfi;
            key_map = (function() {
                var ρσ_Iter = ρσ_Iterable(array_of_cfis), ρσ_Result = Object.create(null), cfi;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    cfi = ρσ_Iter[ρσ_Index];
                    ρσ_Result[cfi] = (cfi_sort_key(cfi));
                }
                return ρσ_Result;
            })();
            Array.prototype.sort.call(array_of_cfis, (function() {
                var ρσ_anonfunc = function (a, b) {
                    var diff, i;
                    a = key_map[(typeof a === "number" && a < 0) ? key_map.length + a : a];
                    b = key_map[(typeof b === "number" && b < 0) ? key_map.length + b : b];
                    var ρσ_Iter0 = ρσ_Iterable(range(min(a.steps.length, b.steps.length)));
                    for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                        i = ρσ_Iter0[ρσ_Index0];
                        diff = (ρσ_expr_temp = a.steps)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i] - (ρσ_expr_temp = b.steps)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
                        if (diff !== 0) {
                            return diff;
                        }
                    }
                    diff = a.length - b.length;
                    if (diff !== 0) {
                        return diff;
                    }
                    if (a.temporal_offset !== b.temporal_offset) {
                        return a.temporal_offset - b.temporal_offset;
                    }
                    if (a.spatial_offset[0] !== b.spatial_offset[0]) {
                        return a.spatial_offset[0] - b.spatial_offset[0];
                    }
                    if (a.spatial_offset[1] !== b.spatial_offset[1]) {
                        return a.spatial_offset[1] - b.spatial_offset[1];
                    }
                    if (a.text_offset !== b.text_offset) {
                        return a.text_offset - b.text_offset;
                    }
                    return 0;
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["a", "b"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!sort_cfis.__argnames__) Object.defineProperties(sort_cfis, {
            __argnames__ : {value: ["array_of_cfis"]}
        });

        function at(x, y, doc) {
            var cdoc, target, tail, offset, name, cd, rect, px, py, ρσ_unpack;
            doc = doc || window.document;
            cdoc = doc;
            target = null;
            tail = "";
            offset = null;
            name = null;
            while (true) {
                target = cdoc.elementFromPoint(x, y);
                if (!target || target === cdoc.documentElement || target === cdoc.body) {
                    return null;
                }
                name = target.localName;
                if (!ρσ_in(name, (function(){
                    var s = ρσ_set();
                    s.jsset.add("iframe");
                    s.jsset.add("embed");
                    s.jsset.add("object");
                    return s;
                })())) {
                    break;
                }
                cd = target.contentDocument;
                if (!cd) {
                    break;
                }
                rect = target.getBoundingClientRect();
                x -= rect.left;
                y -= rect.top;
                cdoc = cd;
            }
            (target.parentNode || target).normalize();
            if (ρσ_in(name, (function(){
                var s = ρσ_set();
                s.jsset.add("audio");
                s.jsset.add("video");
                return s;
            })())) {
                tail = "~" + get_current_time(target);
            }
            if (ρσ_in(name, (function(){
                var s = ρσ_set();
                s.jsset.add("img");
                s.jsset.add("video");
                return s;
            })())) {
                rect = target.getBoundingClientRect();
                px = (x - rect.left) * 100 / target.offsetWidth;
                py = (y - rect.top) * 100 / target.offsetHeight;
                tail = str.format("{}@{}:{}", tail, fstr(px), fstr(py));
            } else if (name !== "audio") {
                ρσ_unpack = find_offset_for_point(x, y, target, cdoc);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                target = ρσ_unpack[0];
                offset = ρσ_unpack[1];
            }
            return encode(doc, target, offset, tail);
        };
        if (!at.__argnames__) Object.defineProperties(at, {
            __argnames__ : {value: ["x", "y", "doc"]}
        });

        function point(cfi, doc) {
            var r, node, ndoc, x, y, range_, try_list, a, rects, node_len, offset, k, t, start_offset, end_offset, ρσ_unpack;
            doc = doc || window.document;
            r = decode(cfi, doc);
            if (!r) {
                return null;
            }
            node = r.node;
            ndoc = node.ownerDocument;
            if (!ndoc) {
                print(str.format("CFI node has no owner document: {} {}", cfi, node));
                return null;
            }
            x = null;
            y = null;
            range_ = null;
            if (typeof r.offset === "number") {
                range_ = ndoc.createRange();
                if (r.forward) {
                    try_list = ρσ_list_decorate([ (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["start"] = 0;
                        ρσ_d["end"] = 0;
                        ρσ_d["a"] = .5;
                        return ρσ_d;
                    }).call(this), (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["start"] = 0;
                        ρσ_d["end"] = 1;
                        ρσ_d["a"] = 1;
                        return ρσ_d;
                    }).call(this), (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["start"] = -1;
                        ρσ_d["end"] = 0;
                        ρσ_d["a"] = 0;
                        return ρσ_d;
                    }).call(this) ]);
                } else {
                    try_list = ρσ_list_decorate([ (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["start"] = 0;
                        ρσ_d["end"] = 0;
                        ρσ_d["a"] = .5;
                        return ρσ_d;
                    }).call(this), (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["start"] = -1;
                        ρσ_d["end"] = 0;
                        ρσ_d["a"] = 0;
                        return ρσ_d;
                    }).call(this), (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["start"] = 0;
                        ρσ_d["end"] = 1;
                        ρσ_d["a"] = 1;
                        return ρσ_d;
                    }).call(this) ]);
                }
                a = null;
                rects = null;
                node_len = node.nodeValue.length;
                offset = r.offset;
                for (var i = 0; i < 2; i++) {
                    offset = r.offset - i;
                    if (offset < 0) {
                        offset = 0;
                    }
                    k = 0;
                    while ((!rects || !rects.length) && k < try_list.length) {
                        t = try_list[(typeof k === "number" && k < 0) ? try_list.length + k : k];
                        k += 1;
                        start_offset = offset + t.start;
                        end_offset = offset + t.end;
                        a = t.a;
                        if (start_offset < 0 || end_offset >= node_len) {
                            continue;
                        }
                        range_.setStart(node, start_offset);
                        range_.setEnd(node, end_offset);
                        rects = range_.getClientRects();
                    }
                }
                if (!rects || !rects.length) {
                    print(str.format("Could not find caret position: rects: {} offset: {}", rects, r.offset));
                    return null;
                }
            } else {
                ρσ_unpack = [r.x, r.y];
                x = ρσ_unpack[0];
                y = ρσ_unpack[1];
            }
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["x"] = x;
                ρσ_d["y"] = y;
                ρσ_d["node"] = r.node;
                ρσ_d["time"] = r.time;
                ρσ_d["range"] = range_;
                ρσ_d["a"] = a;
                return ρσ_d;
            }).call(this);
        };
        if (!point.__argnames__) Object.defineProperties(point, {
            __argnames__ : {value: ["cfi", "doc"]}
        });

        function scroll_to(cfi, callback, doc) {
            var point_, r, ρσ_unpack, so, eo, sc, ec, node, ndoc, span, fn;
            doc = doc || window.doc;
            point_ = point(cfi, doc);
            if (!point_) {
                print("No point found for cfi: " + cfi);
                return;
            }
            if (typeof point_.time === "number") {
                set_current_time(point_.node, point_.time);
            }
            if (point_.range !== null) {
                r = point_.range;
                ρσ_unpack = [r.startOffset, r.endOffset, r.startContainer, r.endContainer];
                so = ρσ_unpack[0];
                eo = ρσ_unpack[1];
                sc = ρσ_unpack[2];
                ec = ρσ_unpack[3];
                node = r.startContainer;
                ndoc = node.ownerDocument;
                span = ndoc.createElement("span");
                span.setAttribute("style", "border-width: 0; padding: 0; margin: 0");
                r.surroundContents(span);
                scroll_viewport.scroll_into_view(span);
                scroll_viewport.reset_transforms();
                fn = function () {
                    var rect, p, node, rects, x, y, ρσ_unpack;
                    rect = span.getBoundingClientRect();
                    p = span.parentNode;
                    var ρσ_Iter1 = ρσ_Iterable(span.childNodes);
                    for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                        node = ρσ_Iter1[ρσ_Index1];
                        span.removeChild(node);
                        p.insertBefore(node, span);
                    }
                    p.removeChild(span);
                    p.normalize();
                    r.setStart(sc, so);
                    try {
                        r.setEnd(ec, eo);
                    } catch (ρσ_Exception) {
                        ρσ_last_exception = ρσ_Exception;
                        {
                            r.setEnd(ec, eo - 1);
                        } 
                    }
                    rects = r.getClientRects();
                    if (rects.length > 0) {
                        rect = rects[0];
                    }
                    x = point_.a * rect.left + (1 - point_.a) * rect.right;
                    y = (rect.top + rect.bottom) / 2;
                    ρσ_unpack = viewport_to_document(x, y, ndoc);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    x = ρσ_unpack[0];
                    y = ρσ_unpack[1];
                    if (callback) {
                        callback(x, y);
                    }
                };
            } else {
                node = point_.node;
                scroll_viewport.scroll_into_view(node);
                scroll_viewport.reset_transforms();
                fn = function () {
                    var r, ρσ_unpack, x, y;
                    r = node.getBoundingClientRect();
                    ρσ_unpack = viewport_to_document(r.left, r.top, node.ownerDocument);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    x = ρσ_unpack[0];
                    y = ρσ_unpack[1];
                    if (typeof point_.x === "number" && node.offsetWidth) {
                        x += point_.x * node.offsetWidth / 100;
                    }
                    if (typeof point_.y === "number" && node.offsetHeight) {
                        y += point_.y * node.offsetHeight / 100;
                    }
                    scroll_viewport.scroll_to(x, y);
                    if (callback) {
                        callback(x, y);
                    }
                };
            }
            setTimeout(fn, 10);
        };
        if (!scroll_to.__argnames__) Object.defineProperties(scroll_to, {
            __argnames__ : {value: ["cfi", "callback", "doc"]}
        });

        function at_point(ox, oy) {
            var cfi, p, r, rect, x, y, ρσ_unpack, node;
            function dist(p1, p2) {
                Math.sqrt(Math.pow(p1[0] - p2[0], 2), Math.pow(p1[1] - p2[1], 2));
            };
            if (!dist.__argnames__) Object.defineProperties(dist, {
                __argnames__ : {value: ["p1", "p2"]}
            });

            try {
                cfi = at(ox, oy);
                p = point(cfi);
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                if (ρσ_Exception instanceof Error) {
                    cfi = null;
                } else {
                    throw ρσ_Exception;
                }
            }
            if (!p) {
                return null;
            }
            if (cfi) {
                if (p.range !== null) {
                    r = p.range;
                    rect = r.getClientRects()[0];
                    x = p.a * rect.left + (1 - p.a) * rect.right;
                    y = (rect.top + rect.bottom) / 2;
                    ρσ_unpack = viewport_to_document(x, y, r.startContainer.ownerDocument);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    x = ρσ_unpack[0];
                    y = ρσ_unpack[1];
                } else {
                    node = p.node;
                    r = node.getBoundingClientRect();
                    ρσ_unpack = viewport_to_document(r.left, r.top, node.ownerDocument);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    x = ρσ_unpack[0];
                    y = ρσ_unpack[1];
                    if (typeof p.x === "number" && node.offsetWidth) {
                        x += p.x * node.offsetWidth / 100;
                    }
                    if (typeof p.y === "number" && node.offsetHeight) {
                        y += p.y * node.offsetHeight / 100;
                    }
                }
                if (dist(viewport_to_document(ox, oy), [x, y]) > 50) {
                    cfi = null;
                }
            }
            return cfi;
        };
        if (!at_point.__argnames__) Object.defineProperties(at_point, {
            __argnames__ : {value: ["ox", "oy"]}
        });

        function at_current() {
            var ρσ_unpack, winx, winy, winw, winh, deltay, deltax, miny, maxy, minx, maxx, delta, cury, cfi, direction, x, y, de, rect, px, py;
            ρσ_unpack = window_scroll_pos();
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            winx = ρσ_unpack[0];
            winy = ρσ_unpack[1];
            ρσ_unpack = [scroll_viewport.width(), scroll_viewport.height()];
            winw = ρσ_unpack[0];
            winh = ρσ_unpack[1];
            winw = max(winw, 400);
            winh = max(winh, 600);
            deltay = Math.floor(winh / 50);
            deltax = Math.floor(winw / 25);
            miny = max(-winy, -winh);
            maxy = winh;
            minx = max(-winx, -winw);
            maxx = winw;
            function x_loop(cury) {
                var delta, curx, cfi, direction;
                var ρσ_Iter2 = ρσ_Iterable([-1, 1]);
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    direction = ρσ_Iter2[ρσ_Index2];
                    delta = deltax * direction;
                    curx = 0;
                    while (!(direction < 0 && curx < minx || direction > 0 && curx > maxx)) {
                        cfi = at_point(curx, cury);
                        if (cfi) {
                            return cfi;
                        }
                        curx += delta;
                    }
                }
            };
            if (!x_loop.__argnames__) Object.defineProperties(x_loop, {
                __argnames__ : {value: ["cury"]}
            });

            var ρσ_Iter3 = ρσ_Iterable([-1, 1]);
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                direction = ρσ_Iter3[ρσ_Index3];
                delta = deltay * direction;
                cury = 0;
                while (!(direction < 0 && cury < miny || direction > 0 && cury > maxy)) {
                    cfi = x_loop(cury, -1);
                    if (cfi) {
                        return cfi;
                    }
                    cury += delta;
                }
            }
            ρσ_unpack = window_scroll_pos();
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            x = ρσ_unpack[0];
            y = ρσ_unpack[1];
            de = document.documentElement;
            rect = de.getBoundingClientRect();
            px = x * 100 / rect.width;
            py = y * 100 / rect.height;
            cfi = str.format("/2@{}:{}", fstr(px), fstr(py));
            return cfi;
        };

        if (__name__ === "__main__") {
            t = "a^!,1";
            if (unescape_from_cfi(escape_for_cfi(t)) !== t) {
                throw new Exception("Failed to properly roundtrip cfi");
            }
        }
        ρσ_modules["read_book.cfi"].escape_pat = escape_pat;
        ρσ_modules["read_book.cfi"].unescape_pat = unescape_pat;
        ρσ_modules["read_book.cfi"].t = t;
        ρσ_modules["read_book.cfi"].escape_for_cfi = escape_for_cfi;
        ρσ_modules["read_book.cfi"].unescape_from_cfi = unescape_from_cfi;
        ρσ_modules["read_book.cfi"].fstr = fstr;
        ρσ_modules["read_book.cfi"].get_current_time = get_current_time;
        ρσ_modules["read_book.cfi"].window_scroll_pos = window_scroll_pos;
        ρσ_modules["read_book.cfi"].viewport_to_document = viewport_to_document;
        ρσ_modules["read_book.cfi"].range_has_point = range_has_point;
        ρσ_modules["read_book.cfi"].offset_in_text_node = offset_in_text_node;
        ρσ_modules["read_book.cfi"].find_offset_for_point = find_offset_for_point;
        ρσ_modules["read_book.cfi"].set_current_time = set_current_time;
        ρσ_modules["read_book.cfi"].encode = encode;
        ρσ_modules["read_book.cfi"].decode = decode;
        ρσ_modules["read_book.cfi"].cfi_sort_key = cfi_sort_key;
        ρσ_modules["read_book.cfi"].sort_cfis = sort_cfis;
        ρσ_modules["read_book.cfi"].at = at;
        ρσ_modules["read_book.cfi"].point = point;
        ρσ_modules["read_book.cfi"].scroll_to = scroll_to;
        ρσ_modules["read_book.cfi"].at_point = at_point;
        ρσ_modules["read_book.cfi"].at_current = at_current;
    })();

    (function(){
        var __name__ = "read_book.extract";
        function get_elements(x, y) {
            var ans, elem;
            ans = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["link"] = null;
                ρσ_d["img"] = null;
                return ρσ_d;
            }).call(this);
            var ρσ_Iter0 = ρσ_Iterable(document.elementsFromPoint(x, y));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                elem = ρσ_Iter0[ρσ_Index0];
                if (elem.tagName.toLowerCase() === "a" && elem.getAttribute("href") && !ans.link) {
                    ans.link = elem.getAttribute("href");
                } else if (elem.tagName.toLowerCase() === "img" && elem.getAttribute("data-calibre-src") && !ans.img) {
                    ans.img = elem.getAttribute("data-calibre-src");
                }
            }
            return ans;
        };
        if (!get_elements.__argnames__) Object.defineProperties(get_elements, {
            __argnames__ : {value: ["x", "y"]}
        });

        ρσ_modules["read_book.extract"].get_elements = get_elements;
    })();

    (function(){
        var __name__ = "select";
        function range_from_point(x, y) {
            var r, p;
            r = null;
            if (document.caretPositionFromPoint) {
                p = document.caretPositionFromPoint(x, y);
                if (p) {
                    r = document.createRange();
                    r.setStart(p.offsetNode, p.offset);
                    r.collapse(true);
                }
            } else if (document.caretRangeFromPoint) {
                r = document.caretRangeFromPoint(x, y);
            }
            return r;
        };
        if (!range_from_point.__argnames__) Object.defineProperties(range_from_point, {
            __argnames__ : {value: ["x", "y"]}
        });

        function word_boundary_regex() {
            var ans;
            ans = word_boundary_regex.ans;
            if (ans === undefined) {
                ans = word_boundary_regex.ans = /[\s!-#%-\x2A,-/:;\x3F@\x5B-\x5D_\x7B}\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E3B\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]/;
            }
            return ans;
        };

        function expand_offset_to_word(string, offset) {
            var start, pat, ρσ_unpack, end, sz;
            start = offset;
            pat = word_boundary_regex();
            while (start >= 1 && !pat.test(string.charAt(start - 1))) {
                start -= 1;
            }
            ρσ_unpack = [offset, string.length];
            end = ρσ_unpack[0];
            sz = ρσ_unpack[1];
            while (end < sz && !pat.test(string.charAt(end))) {
                end += 1;
            }
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["word"] = string.slice(start, end);
                ρσ_d["start"] = start;
                ρσ_d["end"] = end;
                return ρσ_d;
            }).call(this);
        };
        if (!expand_offset_to_word.__argnames__) Object.defineProperties(expand_offset_to_word, {
            __argnames__ : {value: ["string", "offset"]}
        });

        function word_at_point(x, y) {
            var r, word_info;
            r = range_from_point(x, y);
            if (r && r.startContainer.nodeType === 3) {
                word_info = expand_offset_to_word(r.startContainer.data, r.startOffset);
                if (word_info.word) {
                    r.setStart(r.startContainer, word_info.start);
                    r.setEnd(r.startContainer, word_info.end);
                    return r;
                }
            }
        };
        if (!word_at_point.__argnames__) Object.defineProperties(word_at_point, {
            __argnames__ : {value: ["x", "y"]}
        });

        ρσ_modules.select.range_from_point = range_from_point;
        ρσ_modules.select.word_boundary_regex = word_boundary_regex;
        ρσ_modules.select.expand_offset_to_word = expand_offset_to_word;
        ρσ_modules.select.word_at_point = word_at_point;
    })();

    (function(){
        var __name__ = "read_book.flow_mode";
        var small_scroll_events, smooth_y_data, flick_animator, anchor_funcs;
        var word_at_point = ρσ_modules.select.word_at_point;

        var set_css = ρσ_modules.dom.set_css;

        var get_boss = ρσ_modules["read_book.globals"].get_boss;

        var scroll_viewport = ρσ_modules["read_book.viewport"].scroll_viewport;

        var document_height = ρσ_modules.utils.document_height;
        var viewport_to_document = ρσ_modules.utils.viewport_to_document;

        function flow_to_scroll_fraction(frac) {
            scroll_viewport.scroll_to(0, document_height() * frac);
        };
        if (!flow_to_scroll_fraction.__argnames__) Object.defineProperties(flow_to_scroll_fraction, {
            __argnames__ : {value: ["frac"]}
        });

        small_scroll_events = [];
        function clear_small_scrolls() {
            small_scroll_events = [];
        };

        function dispatch_small_scrolls() {
            var now, amt, x;
            if (small_scroll_events.length) {
                now = window.performance.now();
                if (now - small_scroll_events[small_scroll_events.length-1].time <= 2e3) {
                    window.setTimeout(dispatch_small_scrolls, 100);
                    return;
                }
                amt = 0;
                var ρσ_Iter0 = ρσ_Iterable(small_scroll_events);
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    x = ρσ_Iter0[ρσ_Index0];
                    amt += x.amt;
                }
                clear_small_scrolls();
                get_boss().report_human_scroll(amt / document_height());
            }
        };

        function add_small_scroll(amt) {
            small_scroll_events.push((function(){
                var ρσ_d = Object.create(null);
                ρσ_d["amt"] = amt;
                ρσ_d["time"] = window.performance.now();
                return ρσ_d;
            }).call(this));
            window.setTimeout(dispatch_small_scrolls, 100);
        };
        if (!add_small_scroll.__argnames__) Object.defineProperties(add_small_scroll, {
            __argnames__ : {value: ["amt"]}
        });

        function report_human_scroll(amt) {
            var h, is_large_scroll;
            if (amt > 0) {
                h = scroll_viewport.height();
                is_large_scroll = amt / h >= .5;
                if (is_large_scroll) {
                    clear_small_scrolls();
                    get_boss().report_human_scroll(amt / document_height());
                } else {
                    add_small_scroll(amt);
                }
            } else {
                clear_small_scrolls();
            }
        };
        if (!report_human_scroll.__argnames__) Object.defineProperties(report_human_scroll, {
            __argnames__ : {value: ["amt"]}
        });

        function _check_for_scroll_end(func, obj, args, report) {
            var before;
            before = window.pageYOffset;
            func.apply(obj, args);
            if (window.pageYOffset === before) {
                (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["next_spine_item"].concat([ρσ_desugar_kwargs({previous: args[0] < 0})])));
                return false;
            }
            if (report) {
                report_human_scroll(window.pageYOffset - before);
            }
            return true;
        };
        if (!_check_for_scroll_end.__argnames__) Object.defineProperties(_check_for_scroll_end, {
            __argnames__ : {value: ["func", "obj", "args", "report"]}
        });

        function check_for_scroll_end(func) {
            return function () {
                return _check_for_scroll_end(func, this, arguments, false);
            };
        };
        if (!check_for_scroll_end.__argnames__) Object.defineProperties(check_for_scroll_end, {
            __argnames__ : {value: ["func"]}
        });

        function check_for_scroll_end_and_report(func) {
            return function () {
                return _check_for_scroll_end(func, this, arguments, true);
            };
        };
        if (!check_for_scroll_end_and_report.__argnames__) Object.defineProperties(check_for_scroll_end_and_report, {
            __argnames__ : {value: ["func"]}
        });

        
        var scroll_by = check_for_scroll_end_and_report((function() {
            var ρσ_anonfunc = function scroll_by(y) {
                window.scrollBy(0, y);
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["y"]}
            });
            return ρσ_anonfunc;
        })());

        function flow_onwheel(evt) {
            var dx, dy;
            dx = dy = 0;
            if (evt.deltaY) {
                if (evt.deltaMode === evt.DOM_DELTA_PIXEL) {
                    dy = evt.deltaY;
                } else if (evt.deltaMode === evt.DOM_DELTA_LINE) {
                    dy = 15 * evt.deltaY;
                }
                if (evt.deltaMode === evt.DOM_DELTA_PAGE) {
                    dy = (scroll_viewport.height() - 30) * evt.deltaY;
                }
            }
            if (evt.deltaX) {
                if (evt.deltaMode === evt.DOM_DELTA_PIXEL) {
                    dx = evt.deltaX;
                } else if (evt.deltaMode === evt.DOM_DELTA_LINE) {
                    dx = 15 * evt.deltaX;
                } else {
                    dx = (scroll_viewport.width() - 30) * evt.deltaX;
                }
            }
            if (dx) {
                window.scrollBy(dx, 0);
            } else if (dy) {
                scroll_by(dy);
            }
        };
        if (!flow_onwheel.__argnames__) Object.defineProperties(flow_onwheel, {
            __argnames__ : {value: ["evt"]}
        });

        smooth_y_data = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["last_event_at"] = 0;
            ρσ_d["up"] = false;
            ρσ_d["timer"] = null;
            ρσ_d["source"] = "wheel";
            ρσ_d["pixels_per_ms"] = .2;
            ρσ_d["scroll_interval"] = 10;
            ρσ_d["stop_scrolling_after"] = 100;
            return ρσ_d;
        }).call(this);
        function do_y_scroll() {
            if (scroll_by(((smooth_y_data.up) ? -1 : 1) * smooth_y_data.pixels_per_ms * smooth_y_data.scroll_interval)) {
                if (Date.now() - smooth_y_data.last_event_at < smooth_y_data.stop_scrolling_after) {
                    smooth_y_data.timer = setTimeout(do_y_scroll, smooth_y_data.scroll_interval);
                }
            }
        };

        function smooth_y_scroll(up) {
            clearTimeout(smooth_y_data.timer);
            smooth_y_data.last_event_at = Date.now();
            smooth_y_data.up = up;
            do_y_scroll();
        };
        if (!smooth_y_scroll.__argnames__) Object.defineProperties(smooth_y_scroll, {
            __argnames__ : {value: ["up"]}
        });

        
        var goto_boundary = check_for_scroll_end((function() {
            var ρσ_anonfunc = function goto_boundary(y) {
                scroll_viewport.scroll_to(window.pageXOffset, 0);
                get_boss().report_human_scroll();
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["y"]}
            });
            return ρσ_anonfunc;
        })());

        
        var scroll_by_page = check_for_scroll_end_and_report((function() {
            var ρσ_anonfunc = function scroll_by_page(direction) {
                var h;
                h = scroll_viewport.height() - 10;
                window.scrollBy(0, h * direction);
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["direction"]}
            });
            return ρσ_anonfunc;
        })());

        function handle_shortcut(sc_name, evt) {
            if (sc_name === "down") {
                smooth_y_scroll(false);
                return true;
            }
            if (sc_name === "up") {
                smooth_y_scroll(true);
                return true;
            }
            if (sc_name === "start_of_file") {
                goto_boundary(-1);
                return true;
            }
            if (sc_name === "end_of_file") {
                goto_boundary(1);
                return true;
            }
            if (sc_name === "left") {
                window.scrollBy(-15, 0);
                return true;
            }
            if (sc_name === "right") {
                window.scrollBy(15, 0);
                return true;
            }
            if (sc_name === "start_of_book") {
                (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["goto_doc_boundary"].concat([ρσ_desugar_kwargs({start: true})])));
                return true;
            }
            if (sc_name === "end_of_book") {
                (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["goto_doc_boundary"].concat([ρσ_desugar_kwargs({start: false})])));
                return true;
            }
            if (sc_name === "pageup") {
                scroll_by_page(-1);
                return true;
            }
            if (sc_name === "pagedown") {
                scroll_by_page(1);
                return true;
            }
            return false;
        };
        if (!handle_shortcut.__argnames__) Object.defineProperties(handle_shortcut, {
            __argnames__ : {value: ["sc_name", "evt"]}
        });

        function layout(is_single_page) {
            ρσ_interpolate_kwargs.call(this, set_css, [document.body].concat([ρσ_desugar_kwargs({margin: "0", border_width: "0", padding: "0"})]));
        };
        if (!layout.__argnames__) Object.defineProperties(layout, {
            __argnames__ : {value: ["is_single_page"]}
        });

        function FlickAnimator() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            FlickAnimator.prototype.__bind_methods__.call(this);
            FlickAnimator.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(FlickAnimator.prototype, "__bind_methods__", {value: function () {
            this.start = FlickAnimator.prototype.start.bind(this);
            this.auto_scroll = FlickAnimator.prototype.auto_scroll.bind(this);
            this.stop = FlickAnimator.prototype.stop.bind(this);
        }});
        FlickAnimator.prototype.__init__ = function __init__() {
            var self = this;
            self.animation_id = null;
        };
        FlickAnimator.__argnames__ = FlickAnimator.prototype.__init__.__argnames__;
        FlickAnimator.__handles_kwarg_interpolation__ = FlickAnimator.prototype.__init__.__handles_kwarg_interpolation__;
        FlickAnimator.prototype.start = function start(gesture) {
            var self = this;
            var now, points, times, ρσ_unpack, i, t, elapsed, delta, velocity;
            self.vertical = gesture.axis === "vertical";
            now = window.performance.now();
            points = times = null;
            var ρσ_Iter1 = ρσ_Iterable(enumerate(gesture.times));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                ρσ_unpack = ρσ_Iter1[ρσ_Index1];
                i = ρσ_unpack[0];
                t = ρσ_unpack[1];
                if (now - t < self.VELOCITY_HISTORY) {
                    ρσ_unpack = [gesture.points.slice(i), gesture.times.slice(i)];
                    points = ρσ_unpack[0];
                    times = ρσ_unpack[1];
                    break;
                }
            }
            if (times && times.length > 1) {
                elapsed = (times[times.length-1] - times[0]) / 1e3;
                if (elapsed > 0 && points.length > 1) {
                    delta = points[0] - points[points.length-1];
                    velocity = delta / elapsed;
                    if (abs(velocity) > self.MIMUMUM_VELOCITY) {
                        self.amplitude = self.SPEED_FACTOR * velocity;
                        self.start_time = now;
                        self.animation_id = window.requestAnimationFrame(self.auto_scroll);
                    }
                }
            }
        };
        if (!FlickAnimator.prototype.start.__argnames__) Object.defineProperties(FlickAnimator.prototype.start, {
            __argnames__ : {value: ["gesture"]}
        });
        FlickAnimator.prototype.auto_scroll = function auto_scroll(ts) {
            var self = this;
            var elapsed, delta;
            if (self.animation_id === null) {
                return;
            }
            elapsed = window.performance.now() - self.start_time;
            delta = self.amplitude * Math.exp(-elapsed / self.DECEL_TIME_CONSTANT);
            if (abs(delta) >= 1) {
                delta = Math.round(delta);
                if (self.vertical) {
                    window.scrollBy(0, delta);
                } else {
                    window.scrollBy(delta, 0);
                }
                self.animation_id = window.requestAnimationFrame(self.auto_scroll);
            }
        };
        if (!FlickAnimator.prototype.auto_scroll.__argnames__) Object.defineProperties(FlickAnimator.prototype.auto_scroll, {
            __argnames__ : {value: ["ts"]}
        });
        FlickAnimator.prototype.stop = function stop() {
            var self = this;
            if (self.animation_id !== null) {
                window.cancelAnimationFrame(self.animation_id);
                self.animation_id = null;
            }
        };
        FlickAnimator.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        FlickAnimator.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(FlickAnimator.prototype, "__bases__", {value: []});
        FlickAnimator.prototype.SPEED_FACTOR = .04;
        FlickAnimator.prototype.DECEL_TIME_CONSTANT = 325;
        FlickAnimator.prototype.VELOCITY_HISTORY = 300;
        FlickAnimator.prototype.MIMUMUM_VELOCITY = 100;

        flick_animator = new FlickAnimator;
        function handle_gesture(gesture) {
            var delta, r, s;
            flick_animator.stop();
            if (gesture.type === "swipe") {
                if (gesture.points.length > 1 && !gesture.is_held) {
                    delta = (ρσ_expr_temp = gesture.points)[ρσ_expr_temp.length-2] - (ρσ_expr_temp = gesture.points)[ρσ_expr_temp.length-1];
                    if (gesture.axis === "vertical") {
                        scroll_by(delta);
                    } else {
                        window.scrollBy(delta, 0);
                    }
                }
                if (!gesture.active && !gesture.is_held) {
                    flick_animator.start(gesture);
                }
            } else if (gesture.type === "prev-page") {
                scroll_by_page(-1);
            } else if (gesture.type === "next-page") {
                scroll_by_page(1);
            } else if (gesture.type === "long-tap") {
                r = word_at_point(gesture.viewport_x, gesture.viewport_y);
                if (r) {
                    s = document.getSelection();
                    s.removeAllRanges();
                    s.addRange(r);
                    (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["lookup_word"].concat([ρσ_desugar_kwargs({word: str(r)})])));
                }
            }
        };
        if (!handle_gesture.__argnames__) Object.defineProperties(handle_gesture, {
            __argnames__ : {value: ["gesture"]}
        });

        anchor_funcs = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["pos_for_elem"] = (function() {
                var ρσ_anonfunc = function pos_for_elem(elem) {
                    var br, ρσ_unpack, x, y;
                    if (!elem) {
                        return [0, 0];
                    }
                    br = elem.getBoundingClientRect();
                    ρσ_unpack = viewport_to_document(br.left, br.top, elem.ownerDocument);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    x = ρσ_unpack[0];
                    y = ρσ_unpack[1];
                    return [y, x];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["elem"]}
                });
                return ρσ_anonfunc;
            })();
            ρσ_d["visibility"] = (function() {
                var ρσ_anonfunc = function visibility(pos) {
                    var ρσ_unpack, y, x;
                    ρσ_unpack = pos;
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    y = ρσ_unpack[0];
                    x = ρσ_unpack[1];
                    if (y < window.pageYOffset) {
                        return -1;
                    }
                    if (y < window.pageYOffset + scroll_viewport.height()) {
                        if (x < window.pageXOffset) {
                            return -1;
                        }
                        if (x < window.pageXOffset + scroll_viewport.width()) {
                            return 0;
                        }
                    }
                    return 1;
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["pos"]}
                });
                return ρσ_anonfunc;
            })();
            ρσ_d["cmp"] = (function() {
                var ρσ_anonfunc = function cmp(a, b) {
                    return a[0] - b[0] || a[1] - b[1];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["a", "b"]}
                });
                return ρσ_anonfunc;
            })();
            return ρσ_d;
        }).call(this);
        ρσ_modules["read_book.flow_mode"].small_scroll_events = small_scroll_events;
        ρσ_modules["read_book.flow_mode"].smooth_y_data = smooth_y_data;
        ρσ_modules["read_book.flow_mode"].flick_animator = flick_animator;
        ρσ_modules["read_book.flow_mode"].anchor_funcs = anchor_funcs;
        ρσ_modules["read_book.flow_mode"].flow_to_scroll_fraction = flow_to_scroll_fraction;
        ρσ_modules["read_book.flow_mode"].clear_small_scrolls = clear_small_scrolls;
        ρσ_modules["read_book.flow_mode"].dispatch_small_scrolls = dispatch_small_scrolls;
        ρσ_modules["read_book.flow_mode"].add_small_scroll = add_small_scroll;
        ρσ_modules["read_book.flow_mode"].report_human_scroll = report_human_scroll;
        ρσ_modules["read_book.flow_mode"]._check_for_scroll_end = _check_for_scroll_end;
        ρσ_modules["read_book.flow_mode"].check_for_scroll_end = check_for_scroll_end;
        ρσ_modules["read_book.flow_mode"].check_for_scroll_end_and_report = check_for_scroll_end_and_report;
        ρσ_modules["read_book.flow_mode"].scroll_by = scroll_by;
        ρσ_modules["read_book.flow_mode"].flow_onwheel = flow_onwheel;
        ρσ_modules["read_book.flow_mode"].do_y_scroll = do_y_scroll;
        ρσ_modules["read_book.flow_mode"].smooth_y_scroll = smooth_y_scroll;
        ρσ_modules["read_book.flow_mode"].goto_boundary = goto_boundary;
        ρσ_modules["read_book.flow_mode"].scroll_by_page = scroll_by_page;
        ρσ_modules["read_book.flow_mode"].handle_shortcut = handle_shortcut;
        ρσ_modules["read_book.flow_mode"].layout = layout;
        ρσ_modules["read_book.flow_mode"].FlickAnimator = FlickAnimator;
        ρσ_modules["read_book.flow_mode"].handle_gesture = handle_gesture;
    })();

    (function(){
        var __name__ = "read_book.mathjax";
        var E = ρσ_modules.elementmaker.E;

        var runtime = ρσ_modules["read_book.globals"].runtime;

        function get_url(mathjax_files, name) {
            var ans;
            ans = mathjax_files[(typeof name === "number" && name < 0) ? mathjax_files.length + name : name];
            if (!ans) {
                return name;
            }
            if (typeof ans !== "string") {
                ans = mathjax_files[(typeof name === "number" && name < 0) ? mathjax_files.length + name : name] = window.URL.createObjectURL(ans);
            }
            return ans;
        };
        if (!get_url.__argnames__) Object.defineProperties(get_url, {
            __argnames__ : {value: ["mathjax_files", "name"]}
        });

        function monkeypatch(mathjax_files) {
            var StyleString, orig;
            StyleString = window.MathJax.Ajax.StyleString.bind(window.MathJax.Ajax);
            function style_string(styles) {
                return StyleString(styles).replace(/url\('?(.*?)'?\)/g, (function() {
                    var ρσ_anonfunc = function (match, url) {
                        var ans;
                        if (!url.endsWith(".woff")) {
                            return match;
                        }
                        url = get_url(mathjax_files, url);
                        ans = "url('" + ρσ_str.format("{}", url) + "')";
                        return ans;
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["match", "url"]}
                    });
                    return ρσ_anonfunc;
                })());
            };
            if (!style_string.__argnames__) Object.defineProperties(style_string, {
                __argnames__ : {value: ["styles"]}
            });

            orig = window.MathJax.Ajax.fileURL.bind(window.MathJax.Ajax);
            function file_url(file) {
                var ans, name;
                ans = orig(file);
                name = ans.lstrip("/");
                if (name.startswith("../fonts")) {
                    name = name.slice(3);
                }
                if (ρσ_in((ρσ_expr_temp = name.rpartition("/"))[ρσ_expr_temp.length-1], "otf eot woff")) {
                    return name;
                }
                ans = get_url(mathjax_files, name);
                if (ans === name && !name.startswith("blob:")) {
                    if (ans.endswith(".eot") || ans.endswith(".otf")) {
                        return "";
                    }
                    print("WARNING: Failed to resolve MathJax file:", name);
                }
                return ans;
            };
            if (!file_url.__argnames__) Object.defineProperties(file_url, {
                __argnames__ : {value: ["file"]}
            });

            window.MathJax.Ajax.fileURL = file_url;
            window.MathJax.Ajax.StyleString = style_string;
            window.MathJax.Ajax.fileRev = (function() {
                var ρσ_anonfunc = function (file) {
                    return "";
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["file"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!monkeypatch.__argnames__) Object.defineProperties(monkeypatch, {
            __argnames__ : {value: ["mathjax_files"]}
        });

        function postprocess(link_uid, proceed) {
            var href, a;
            var ρσ_Iter0 = ρσ_Iterable(document.getElementsByTagName("a"));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                a = ρσ_Iter0[ρσ_Index0];
                href = a.getAttribute("href");
                if (href.startswith("#")) {
                    a.setAttribute("href", "javascript: void(0)");
                    a.setAttribute("data-" + link_uid, JSON.stringify((function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["frag"] = href.slice(1);
                        return ρσ_d;
                    }).call(this)));
                }
            }
            proceed();
        };
        if (!postprocess.__argnames__) Object.defineProperties(postprocess, {
            __argnames__ : {value: ["link_uid", "proceed"]}
        });

        function init_mathjax(mathjax_files, link_uid, proceed) {
            monkeypatch(mathjax_files);
            window.MathJax.Hub.Register.StartupHook("End", postprocess.bind(this, link_uid, proceed));
        };
        if (!init_mathjax.__argnames__) Object.defineProperties(init_mathjax, {
            __argnames__ : {value: ["mathjax_files", "link_uid", "proceed"]}
        });

        function apply_mathjax(mathjax_files, link_uid, proceed) {
            var m, script;
            window.MathJax = m = {};
            m.positionToHash = false;
            m.showMathMenu = false;
            m.showMathMenuMSIE = false;
            m.extensions = "tex2jax.js asciimath2jax.js mml2jax.js".split(" ");
            m.jax = "input/TeX input/MathML input/AsciiMath output/CommonHTML".split(" ");
            m.TeX = {};
            m.TeX.extensions = "AMSmath.js AMSsymbols.js noErrors.js noUndefined.js".split(" ");
            m.CommonHTML = { linebreaks: { automatic: true} };
            script = ρσ_interpolate_kwargs.call(E, E.script, [ρσ_desugar_kwargs({type: "text/javascript"})]);
            document.head.appendChild(script);
            if (runtime.is_standalone_viewer) {
                script.onload = function () {
                    var ev;
                    ev = new CustomEvent("calibre-mathjax-init", (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["detail"] = (function(){
                            var ρσ_d = Object.create(null);
                            ρσ_d["MathJax"] = m;
                            ρσ_d["link_uid"] = link_uid;
                            ρσ_d["mathjax_files"] = mathjax_files;
                            return ρσ_d;
                        }).call(this);
                        return ρσ_d;
                    }).call(this));
                    document.documentElement.dispatchEvent(ev);
                };
                document.documentElement.addEventListener("calibre-mathjax-init-done", (function() {
                    var ρσ_anonfunc = function (ev) {
                        proceed();
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["ev"]}
                    });
                    return ρσ_anonfunc;
                })());
            } else {
                m.AuthorInit = init_mathjax.bind(this, mathjax_files, link_uid, proceed);
            }
            script.src = get_url(mathjax_files, "MathJax.js");
        };
        if (!apply_mathjax.__argnames__) Object.defineProperties(apply_mathjax, {
            __argnames__ : {value: ["mathjax_files", "link_uid", "proceed"]}
        });

        ρσ_modules["read_book.mathjax"].get_url = get_url;
        ρσ_modules["read_book.mathjax"].monkeypatch = monkeypatch;
        ρσ_modules["read_book.mathjax"].postprocess = postprocess;
        ρσ_modules["read_book.mathjax"].init_mathjax = init_mathjax;
        ρσ_modules["read_book.mathjax"].apply_mathjax = apply_mathjax;
    })();

    (function(){
        var __name__ = "read_book.paged_mode";
        var _in_paged_mode, col_width, screen_width, screen_height, cols_per_screen, gap, col_and_gap, number_of_cols, is_full_screen_layout, anchor_funcs;
        var traceback = ρσ_modules.traceback;

        var E = ρσ_modules.elementmaker.E;

        var word_at_point = ρσ_modules.select.word_at_point;

        var set_css = ρσ_modules.dom.set_css;

        var cfi_at_current = ρσ_modules["read_book.cfi"].at_current;
        var cfi_at_point = ρσ_modules["read_book.cfi"].at_point;
        var cfi_scroll_to = ρσ_modules["read_book.cfi"].scroll_to;

        var get_boss = ρσ_modules["read_book.globals"].get_boss;

        var opts = ρσ_modules["read_book.settings"].opts;

        var scroll_viewport = ρσ_modules["read_book.viewport"].scroll_viewport;

        var document_width = ρσ_modules.utils.document_width;
        var get_elem_data = ρσ_modules.utils.get_elem_data;
        var set_elem_data = ρσ_modules.utils.set_elem_data;
        var viewport_to_document = ρσ_modules.utils.viewport_to_document;

        function first_child(parent) {
            var c, count;
            c = parent.firstChild;
            count = 0;
            while ((typeof c !== "undefined" && c !== null ? c : Object.create(null)).nodeType !== Node.ELEMENT_NODE && count < 20) {
                c = (typeof c !== "undefined" && c !== null ? c : Object.create(null)).nextSibling;
                count += 1;
            }
            if ((typeof c !== "undefined" && c !== null ? c : Object.create(null)).nodeType === Node.ELEMENT_NODE) {
                return c;
            }
        };
        if (!first_child.__argnames__) Object.defineProperties(first_child, {
            __argnames__ : {value: ["parent"]}
        });

        function has_start_text(elem) {
            var c;
            var ρσ_Iter0 = ρσ_Iterable(elem.childNodes);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                c = ρσ_Iter0[ρσ_Index0];
                if (c.nodeType !== Node.TEXT_NODE) {
                    break;
                }
                if (c.nodeType === Node.TEXT_NODE && c.nodeValue && /\S/.test(c.nodeValue)) {
                    return true;
                }
            }
            return false;
        };
        if (!has_start_text.__argnames__) Object.defineProperties(has_start_text, {
            __argnames__ : {value: ["elem"]}
        });

        function handle_rtl_body(body_style) {
            var node;
            if (body_style.direction === "rtl") {
                var ρσ_Iter1 = ρσ_Iterable(document.body.childNodes);
                for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                    node = ρσ_Iter1[ρσ_Index1];
                    if (node.nodeType === Node.ELEMENT_NODE && window.getComputedStyle(node).direction === "rtl") {
                        node.style.setProperty("direction", "rtl");
                    }
                }
                document.body.style.direction = "ltr";
                document.documentElement.style.direction = "ltr";
            }
        };
        if (!handle_rtl_body.__argnames__) Object.defineProperties(handle_rtl_body, {
            __argnames__ : {value: ["body_style"]}
        });

        function create_page_div(elem) {
            var div;
            div = E("blank-page-div", " \n    ");
            document.body.appendChild(div);
            ρσ_interpolate_kwargs.call(this, set_css, [div].concat([ρσ_desugar_kwargs({break_before: "always", display: "block", white_space: "pre", background_color: "transparent", background_image: "none", border_width: "0", float: "none", position: "static"})]));
        };
        if (!create_page_div.__argnames__) Object.defineProperties(create_page_div, {
            __argnames__ : {value: ["elem"]}
        });

        _in_paged_mode = false;
        function in_paged_mode() {
            return _in_paged_mode;
        };

        col_width = screen_width = screen_height = cols_per_screen = gap = col_and_gap = number_of_cols = 0;
        is_full_screen_layout = false;
        function reset_paged_mode_globals() {
            scroll_viewport.reset_globals();
            col_width = screen_width = screen_height = cols_per_screen = gap = col_and_gap = number_of_cols = 0;
            is_full_screen_layout = _in_paged_mode = false;
        };

        function column_at(xpos) {
            var sw;
            sw = scroll_viewport.paged_content_width();
            if (xpos >= sw - col_and_gap) {
                xpos = sw - col_width + 10;
            }
            return Math.floor((xpos + gap) / col_and_gap);
        };
        if (!column_at.__argnames__) Object.defineProperties(column_at, {
            __argnames__ : {value: ["xpos"]}
        });

        function fit_images() {
            var images, vimages, img_tags, bounding_rects, img_tag, maxh, img, br, previously_limited, data, left, col, rleft, width, rright, i, ρσ_unpack, max_width;
            images = [];
            vimages = [];
            img_tags = document.getElementsByTagName("img");
            bounding_rects = [];
            var ρσ_Iter2 = ρσ_Iterable(img_tags);
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                img_tag = ρσ_Iter2[ρσ_Index2];
                bounding_rects.push(img_tag.getBoundingClientRect());
            }
            maxh = screen_height;
            for (var ρσ_Index3 = 0; ρσ_Index3 < img_tags.length; ρσ_Index3++) {
                i = ρσ_Index3;
                img = img_tags[(typeof i === "number" && i < 0) ? img_tags.length + i : i];
                br = bounding_rects[(typeof i === "number" && i < 0) ? bounding_rects.length + i : i];
                previously_limited = get_elem_data(img, "width-limited", false);
                data = get_elem_data(img, "img-data", null);
                if (data === null) {
                    data = (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["left"] = br.left;
                        ρσ_d["right"] = br.right;
                        ρσ_d["height"] = br.height;
                        ρσ_d["display"] = img.style.display;
                        return ρσ_d;
                    }).call(this);
                    set_elem_data(img, "img-data", data);
                }
                left = viewport_to_document(br.left, 0, img.ownerDocument)[0];
                col = column_at(left) * col_and_gap;
                rleft = left - col;
                width = br.right - br.left;
                rright = rleft + width;
                if (previously_limited || rright > col_width) {
                    images.push([img, col_width - rleft]);
                }
                previously_limited = get_elem_data(img, "height-limited", false);
                if (previously_limited || br.height > maxh || br.height === maxh && br.width > col_width) {
                    vimages.push(img);
                }
                if (previously_limited) {
                    ρσ_interpolate_kwargs.call(this, set_css, [img].concat([ρσ_desugar_kwargs({break_before: "auto", display: data.display})]));
                }
                ρσ_interpolate_kwargs.call(this, set_css, [img].concat([ρσ_desugar_kwargs({break_inside: "avoid"})]));
            }
            var ρσ_Iter4 = ρσ_Iterable(images);
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                ρσ_unpack = ρσ_Iter4[ρσ_Index4];
                img_tag = ρσ_unpack[0];
                max_width = ρσ_unpack[1];
                img_tag.style.setProperty("max-width", max_width + "px");
                set_elem_data(img_tag, "width-limited", true);
            }
            var ρσ_Iter5 = ρσ_Iterable(vimages);
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                img_tag = ρσ_Iter5[ρσ_Index5];
                data = get_elem_data(img_tag, "img-data", null);
                ρσ_interpolate_kwargs.call(this, set_css, [img_tag].concat([ρσ_desugar_kwargs({break_before: "always", max_height: "100vh"})]));
                set_elem_data(img, "height-limited", true);
            }
        };

        function calc_columns_per_screen() {
            var cps;
            cps = opts.columns_per_screen || Object.create(null);
            cps = (scroll_viewport.width() > scroll_viewport.height()) ? cps.landscape : cps.portrait;
            try {
                cps = int(cps);
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                {
                    cps = 0;
                } 
            }
            if (!cps) {
                cps = int(Math.floor(scroll_viewport.width() / 500));
            }
            cps = max(1, min(cps || 1, 20));
            return cps;
        };

        function layout(is_single_page) {
            var body_style, first_layout, cps, single_screen, has_svg, imgs, only_img, num, elems, n, ww, sm, c, c2, data, dw, elem;
            body_style = window.getComputedStyle(document.body);
            first_layout = !_in_paged_mode;
            cps = calc_columns_per_screen();
            if (first_layout) {
                handle_rtl_body(body_style);
                single_screen = document.body.scrollHeight < scroll_viewport.height() + 75;
                first_layout = true;
                has_svg = document.getElementsByTagName("svg").length > 0;
                imgs = document.getElementsByTagName("img");
                only_img = imgs.length === 1 && document.getElementsByTagName("div").length < 3 && document.getElementsByTagName("p").length < 2;
                if (only_img && window.getComputedStyle(imgs[0]).zIndex < 0) {
                    imgs[0].style.zIndex = "0";
                }
                if (!single_screen && cps > 1) {
                    num = cps - 1;
                    elems = document.querySelectorAll("body > *");
                    if ((elems.length === 1 || typeof elems.length === "object" && ρσ_equals(elems.length, 1))) {
                        elems[0].style.height = "auto";
                    }
                    while (num > 0) {
                        num -= 1;
                        create_page_div();
                    }
                }
            }
            n = cols_per_screen = cps;
            ww = col_width = screen_width = scroll_viewport.width();
            gap = 0;
            if (n > 1) {
                sm = opts.margin_left + opts.margin_right;
                gap = sm + (ww + sm) % n;
                col_width = Math.floor((ww + gap) / n) - gap;
            }
            screen_height = scroll_viewport.height();
            col_and_gap = col_width + gap;
            ρσ_interpolate_kwargs.call(this, set_css, [document.body].concat([ρσ_desugar_kwargs({column_gap: gap + "px", column_width: col_width + "px", column_rule: "0px inset blue", min_width: "0", max_width: "none", min_height: "0", max_height: "100vh", column_fill: "auto", margin: "0", border_width: "0", padding: "0", box_sizing: "content-box", width: screen_width + "px", height: screen_height + "px"})]));
            document.body.style.setProperty("-webkit-margin-collapse", "separate");
            c = first_child(document.body);
            if (c) {
                ρσ_interpolate_kwargs.call(this, set_css, [c].concat([ρσ_desugar_kwargs({break_before: "avoid"})]));
                if (c.tagName.toLowerCase() === "div") {
                    c2 = first_child(c);
                    if (c2 && !has_start_text(c)) {
                        ρσ_interpolate_kwargs.call(this, set_css, [c2].concat([ρσ_desugar_kwargs({break_before: "avoid"})]));
                    }
                }
            }
            if (first_layout) {
                is_full_screen_layout = (only_img || has_svg) && single_screen && scroll_viewport.paged_content_width() < 2 * ww + 10;
                if (is_single_page) {
                    is_full_screen_layout = true;
                }
            }
            function check_column_widths() {
                var ncols, n, dw, data;
                ncols = number_of_cols = (scroll_viewport.paged_content_width() + gap) / col_and_gap;
                if (ncols !== Math.floor(ncols)) {
                    n = number_of_cols = Math.floor(ncols);
                    dw = n * col_width + (n - 1) * gap;
                    data = (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["col_width"] = col_width;
                        ρσ_d["gap"] = gap;
                        ρσ_d["scrollWidth"] = scroll_viewport.paged_content_width();
                        ρσ_d["ncols"] = ncols;
                        ρσ_d["desired_width"] = dw;
                        return ρσ_d;
                    }).call(this);
                    return data;
                }
            };

            data = check_column_widths();
            if (data) {
                dw = data.desired_width;
                var ρσ_Iter6 = ρσ_Iterable(ρσ_list_decorate([ document.documentElement, document.body ]));
                for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                    elem = ρσ_Iter6[ρσ_Index6];
                    ρσ_interpolate_kwargs.call(this, set_css, [elem].concat([ρσ_desugar_kwargs({max_width: dw + "px", min_width: dw + "px"})]));
                }
            }
            data = check_column_widths();
            if (data) {
                print("WARNING: column layout broken, probably because there is some non-reflowable content in the book that is wider than the column width", data);
            }
            _in_paged_mode = true;
            fit_images();
            return gap;
        };
        if (!layout.__argnames__) Object.defineProperties(layout, {
            __argnames__ : {value: ["is_single_page"]}
        });

        function current_scroll_offset() {
            return scroll_viewport.x();
        };

        function scroll_to_offset(x) {
            scroll_viewport.scroll_to(x, 0);
        };
        if (!scroll_to_offset.__argnames__) Object.defineProperties(scroll_to_offset, {
            __argnames__ : {value: ["x"]}
        });

        function scroll_to_column() {
            var number = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var notify = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? scroll_to_column.__defaults__.notify : arguments[1];
            var duration = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? scroll_to_column.__defaults__.duration : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "notify")){
                notify = ρσ_kwargs_obj.notify;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "duration")){
                duration = ρσ_kwargs_obj.duration;
            }
            var pos, limit;
            pos = number * col_and_gap;
            limit = scroll_viewport.paged_content_width() - screen_width;
            pos = min(pos, limit);
            scroll_to_offset(pos);
        };
        if (!scroll_to_column.__defaults__) Object.defineProperties(scroll_to_column, {
            __defaults__ : {value: {notify:false, duration:1e3}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["number", "notify", "duration"]}
        });

        function scroll_to_xpos() {
            var xpos = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var notify = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? scroll_to_xpos.__defaults__.notify : arguments[1];
            var duration = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? scroll_to_xpos.__defaults__.duration : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "notify")){
                notify = ρσ_kwargs_obj.notify;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "duration")){
                duration = ρσ_kwargs_obj.duration;
            }
            if (typeof xpos !== "number") {
                print(xpos, "is not a number, cannot scroll to it!");
                return;
            }
            if (is_full_screen_layout) {
                scroll_to_offset(0);
                return;
            }
            ρσ_interpolate_kwargs.call(this, scroll_to_column, [column_at(xpos)].concat([ρσ_desugar_kwargs({notify: notify, duration: duration})]));
        };
        if (!scroll_to_xpos.__defaults__) Object.defineProperties(scroll_to_xpos, {
            __defaults__ : {value: {notify:false, duration:1e3}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["xpos", "notify", "duration"]}
        });

        function scroll_to_fraction(frac) {
            var xpos;
            xpos = Math.floor(scroll_viewport.paged_content_width() * frac);
            scroll_to_xpos(xpos);
        };
        if (!scroll_to_fraction.__argnames__) Object.defineProperties(scroll_to_fraction, {
            __argnames__ : {value: ["frac"]}
        });

        function column_boundaries() {
            var l;
            l = column_at(current_scroll_offset() + 10);
            return [l, l + cols_per_screen];
        };

        function current_column_location() {
            var c;
            if (is_full_screen_layout) {
                return 0;
            }
            c = column_at(current_scroll_offset() + 10);
            return c * col_and_gap;
        };

        function next_screen_location() {
            var cc, ans, current_col, ncols, cols_left, limit;
            if (is_full_screen_layout) {
                return -1;
            }
            cc = current_column_location();
            ans = cc + screen_width;
            if (cols_per_screen > 1) {
                current_col = column_at(current_scroll_offset() + 10);
                ncols = Math.floor((scroll_viewport.paged_content_width() + gap) / col_and_gap);
                cols_left = ncols - (current_col + cols_per_screen);
                if (cols_left < cols_per_screen) {
                    return -1;
                }
            }
            limit = scroll_viewport.paged_content_width() - scroll_viewport.width();
            if (limit < col_and_gap) {
                return -1;
            }
            if (ans > limit) {
                ans = (Math.ceil(current_scroll_offset()) < limit) ? limit : -1;
            }
            return ans;
        };

        function previous_screen_location() {
            var cc, ans;
            if (is_full_screen_layout) {
                return -1;
            }
            cc = current_column_location();
            ans = cc - screen_width;
            if (ans < 0) {
                ans = (current_scroll_offset() > 15) ? 0 : -1;
            }
            return ans;
        };

        function next_col_location() {
            var cc, ans, limit;
            if (is_full_screen_layout) {
                return -1;
            }
            cc = current_column_location();
            ans = cc + col_and_gap;
            limit = scroll_viewport.paged_content_width() - scroll_viewport.width();
            if (ans > limit) {
                ans = (Math.ceil(current_scroll_offset()) < limit) ? limit : -1;
            }
            return ans;
        };

        function previous_col_location() {
            var cc, ans;
            if (is_full_screen_layout) {
                return -1;
            }
            cc = current_column_location();
            ans = cc - col_and_gap;
            if (ans < 0) {
                ans = (Math.floor(current_scroll_offset()) > 0) ? 0 : -1;
            }
            return ans;
        };

        function jump_to_anchor(name) {
            var elem, elems;
            elem = document.getElementById(name);
            if (!elem) {
                elems = document.getElementsByName(name);
                if (elems) {
                    elem = elems[0];
                }
            }
            if (!elem) {
                return;
            }
            scroll_to_elem(elem);
        };
        if (!jump_to_anchor.__argnames__) Object.defineProperties(jump_to_anchor, {
            __argnames__ : {value: ["name"]}
        });

        function scroll_to_elem(elem) {
            var br, left;
            scroll_viewport.scroll_into_view(elem);
            scroll_viewport.reset_transforms();
            if (in_paged_mode()) {
                br = elem.getBoundingClientRect();
                if (br.top < -100) {
                    left = elem.scrollLeft;
                } else {
                    left = br.left;
                }
                scroll_to_xpos(viewport_to_document(left + 2, elem.scrollTop, elem.ownerDocument)[0]);
            }
        };
        if (!scroll_to_elem.__argnames__) Object.defineProperties(scroll_to_elem, {
            __argnames__ : {value: ["elem"]}
        });

        function snap_to_selection() {
            var sel, r, node, left;
            if (in_paged_mode()) {
                scroll_viewport.reset_transforms();
                sel = window.getSelection();
                r = sel.getRangeAt(0).getBoundingClientRect();
                node = sel.anchorNode;
                left = ρσ_interpolate_kwargs.call(this, viewport_to_document, [r.left, r.top].concat([ρσ_desugar_kwargs({doc: node.ownerDocument})]))[0];
                scroll_to_xpos(left + 5);
            }
        };

        function jump_to_cfi(cfi) {
            cfi_scroll_to(cfi, (function() {
                var ρσ_anonfunc = function (x, y) {
                    if (in_paged_mode()) {
                        scroll_to_xpos(x);
                    } else {
                        scroll_viewport.scroll_to(0, y);
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["x", "y"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!jump_to_cfi.__argnames__) Object.defineProperties(jump_to_cfi, {
            __argnames__ : {value: ["cfi"]}
        });

        function current_cfi() {
            var ans, c, ρσ_unpack, left, right, deltax, deltay, cury, curx, cfi, x;
            ans = null;
            if (in_paged_mode()) {
                c = current_column_location();
                var ρσ_Iter7 = ρσ_Iterable(ρσ_list_decorate([ c, c - col_and_gap, c + col_and_gap ]));
                for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                    x = ρσ_Iter7[ρσ_Index7];
                    ρσ_unpack = [x, x + col_and_gap];
                    left = ρσ_unpack[0];
                    right = ρσ_unpack[1];
                    if (left < 0 || right > scroll_viewport.paged_content_width()) {
                        continue;
                    }
                    deltax = Math.floor(col_and_gap / 25);
                    deltay = Math.floor(scroll_viewport.height() / 25);
                    cury = 0;
                    while (cury < scroll_viewport.height()) {
                        curx = left;
                        while (curx < right - gap) {
                            cfi = cfi_at_point(curx - Math.ceil(current_scroll_offset()), cury - Math.ceil(window.pageYOffset));
                            if (cfi) {
                                return cfi;
                            }
                            curx += deltax;
                        }
                        cury += deltay;
                    }
                }
            } else {
                try {
                    ans = cfi_at_current() || null;
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        traceback.print_exc();
                    } 
                }
            }
            return ans;
        };

        function progress_frac(frac) {
            var limit;
            if (in_paged_mode()) {
                limit = scroll_viewport.paged_content_width() - scroll_viewport.width();
                if (limit <= 0) {
                    return 0;
                }
                return current_scroll_offset() / limit;
            }
            limit = document.body.scrollHeight - scroll_viewport.height();
            if (limit <= 0) {
                return 0;
            }
            return window.pageYOffset / limit;
        };
        if (!progress_frac.__argnames__) Object.defineProperties(progress_frac, {
            __argnames__ : {value: ["frac"]}
        });

        function onwheel(evt) {
            var backward, x;
            if (evt.deltaY) {
                backward = evt.deltaY < 0;
                if (opts.paged_wheel_scrolls_by_screen) {
                    x = (backward) ? previous_screen_location() : next_screen_location();
                } else {
                    x = (backward) ? previous_col_location() : next_col_location();
                }
                if (x === -1) {
                    (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["next_spine_item"].concat([ρσ_desugar_kwargs({previous: backward})])));
                } else {
                    scroll_to_xpos(x);
                }
            }
        };
        if (!onwheel.__argnames__) Object.defineProperties(onwheel, {
            __argnames__ : {value: ["evt"]}
        });

        function scroll_by_page(backward, by_screen) {
            var pos, pages, scrolled_frac;
            if (by_screen) {
                pos = (backward) ? previous_screen_location() : next_screen_location();
                pages = cols_per_screen;
            } else {
                pos = (backward) ? previous_col_location() : next_col_location();
                pages = 1;
            }
            if (pos === -1) {
                (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["next_spine_item"].concat([ρσ_desugar_kwargs({previous: backward})])));
            } else {
                if (!backward) {
                    scrolled_frac = (number_of_cols > 0) ? pages / number_of_cols : 0;
                    get_boss().report_human_scroll(scrolled_frac);
                } else {
                    get_boss().report_human_scroll();
                }
                scroll_to_xpos(pos);
            }
        };
        if (!scroll_by_page.__argnames__) Object.defineProperties(scroll_by_page, {
            __argnames__ : {value: ["backward", "by_screen"]}
        });

        function handle_shortcut(sc_name, evt) {
            if (sc_name === "up") {
                scroll_by_page(true, true);
                return true;
            }
            if (sc_name === "down") {
                scroll_by_page(false, true);
                return true;
            }
            if (sc_name === "start_of_file") {
                get_boss().report_human_scroll();
                scroll_to_offset(0);
                return true;
            }
            if (sc_name === "end_of_file") {
                get_boss().report_human_scroll();
                scroll_to_offset(document_width());
                return true;
            }
            if (sc_name === "left") {
                scroll_by_page(true, false);
                return true;
            }
            if (sc_name === "right") {
                scroll_by_page(false, false);
                return true;
            }
            if (sc_name === "start_of_book") {
                get_boss().report_human_scroll();
                (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["goto_doc_boundary"].concat([ρσ_desugar_kwargs({start: true})])));
                return true;
            }
            if (sc_name === "end_of_book") {
                get_boss().report_human_scroll();
                (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["goto_doc_boundary"].concat([ρσ_desugar_kwargs({start: false})])));
                return true;
            }
            if (sc_name === "pageup") {
                scroll_by_page(true, true);
                return true;
            }
            if (sc_name === "pagedown") {
                scroll_by_page(false, true);
                return true;
            }
            return false;
        };
        if (!handle_shortcut.__argnames__) Object.defineProperties(handle_shortcut, {
            __argnames__ : {value: ["sc_name", "evt"]}
        });

        function handle_gesture(gesture) {
            var r, s;
            if (gesture.type === "swipe") {
                if (gesture.axis === "vertical") {
                    if (!gesture.active) {
                        (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["next_section"].concat([ρσ_desugar_kwargs({forward: gesture.direction === "up"})])));
                    }
                } else {
                    if (!gesture.active || gesture.is_held) {
                        scroll_by_page(gesture.direction === "right", true);
                    }
                }
            } else if (gesture.type === "prev-page") {
                scroll_by_page(true, false);
            } else if (gesture.type === "next-page") {
                scroll_by_page(false, false);
            } else if (gesture.type === "long-tap") {
                r = word_at_point(gesture.viewport_x, gesture.viewport_y);
                if (r) {
                    s = document.getSelection();
                    s.removeAllRanges();
                    s.addRange(r);
                    (ρσ_expr_temp = get_boss(), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.send_message, ["lookup_word"].concat([ρσ_desugar_kwargs({word: str(r)})])));
                }
            }
        };
        if (!handle_gesture.__argnames__) Object.defineProperties(handle_gesture, {
            __argnames__ : {value: ["gesture"]}
        });

        anchor_funcs = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["pos_for_elem"] = (function() {
                var ρσ_anonfunc = function pos_for_elem(elem) {
                    var br, x;
                    if (!elem) {
                        return 0;
                    }
                    br = elem.getBoundingClientRect();
                    x = viewport_to_document(br.left, br.top, elem.ownerDocument)[0];
                    return column_at(x);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["elem"]}
                });
                return ρσ_anonfunc;
            })();
            ρσ_d["visibility"] = (function() {
                var ρσ_anonfunc = function visibility(pos) {
                    var first;
                    first = column_at(current_scroll_offset() + 10);
                    if (pos < first) {
                        return -1;
                    }
                    if (pos < first + cols_per_screen) {
                        return 0;
                    }
                    return 1;
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["pos"]}
                });
                return ρσ_anonfunc;
            })();
            ρσ_d["cmp"] = (function() {
                var ρσ_anonfunc = function cmp(a, b) {
                    return a - b;
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["a", "b"]}
                });
                return ρσ_anonfunc;
            })();
            return ρσ_d;
        }).call(this);
        ρσ_modules["read_book.paged_mode"]._in_paged_mode = _in_paged_mode;
        ρσ_modules["read_book.paged_mode"].col_width = col_width;
        ρσ_modules["read_book.paged_mode"].screen_width = screen_width;
        ρσ_modules["read_book.paged_mode"].screen_height = screen_height;
        ρσ_modules["read_book.paged_mode"].cols_per_screen = cols_per_screen;
        ρσ_modules["read_book.paged_mode"].gap = gap;
        ρσ_modules["read_book.paged_mode"].col_and_gap = col_and_gap;
        ρσ_modules["read_book.paged_mode"].number_of_cols = number_of_cols;
        ρσ_modules["read_book.paged_mode"].is_full_screen_layout = is_full_screen_layout;
        ρσ_modules["read_book.paged_mode"].anchor_funcs = anchor_funcs;
        ρσ_modules["read_book.paged_mode"].first_child = first_child;
        ρσ_modules["read_book.paged_mode"].has_start_text = has_start_text;
        ρσ_modules["read_book.paged_mode"].handle_rtl_body = handle_rtl_body;
        ρσ_modules["read_book.paged_mode"].create_page_div = create_page_div;
        ρσ_modules["read_book.paged_mode"].in_paged_mode = in_paged_mode;
        ρσ_modules["read_book.paged_mode"].reset_paged_mode_globals = reset_paged_mode_globals;
        ρσ_modules["read_book.paged_mode"].column_at = column_at;
        ρσ_modules["read_book.paged_mode"].fit_images = fit_images;
        ρσ_modules["read_book.paged_mode"].calc_columns_per_screen = calc_columns_per_screen;
        ρσ_modules["read_book.paged_mode"].layout = layout;
        ρσ_modules["read_book.paged_mode"].current_scroll_offset = current_scroll_offset;
        ρσ_modules["read_book.paged_mode"].scroll_to_offset = scroll_to_offset;
        ρσ_modules["read_book.paged_mode"].scroll_to_column = scroll_to_column;
        ρσ_modules["read_book.paged_mode"].scroll_to_xpos = scroll_to_xpos;
        ρσ_modules["read_book.paged_mode"].scroll_to_fraction = scroll_to_fraction;
        ρσ_modules["read_book.paged_mode"].column_boundaries = column_boundaries;
        ρσ_modules["read_book.paged_mode"].current_column_location = current_column_location;
        ρσ_modules["read_book.paged_mode"].next_screen_location = next_screen_location;
        ρσ_modules["read_book.paged_mode"].previous_screen_location = previous_screen_location;
        ρσ_modules["read_book.paged_mode"].next_col_location = next_col_location;
        ρσ_modules["read_book.paged_mode"].previous_col_location = previous_col_location;
        ρσ_modules["read_book.paged_mode"].jump_to_anchor = jump_to_anchor;
        ρσ_modules["read_book.paged_mode"].scroll_to_elem = scroll_to_elem;
        ρσ_modules["read_book.paged_mode"].snap_to_selection = snap_to_selection;
        ρσ_modules["read_book.paged_mode"].jump_to_cfi = jump_to_cfi;
        ρσ_modules["read_book.paged_mode"].current_cfi = current_cfi;
        ρσ_modules["read_book.paged_mode"].progress_frac = progress_frac;
        ρσ_modules["read_book.paged_mode"].onwheel = onwheel;
        ρσ_modules["read_book.paged_mode"].scroll_by_page = scroll_by_page;
        ρσ_modules["read_book.paged_mode"].handle_shortcut = handle_shortcut;
        ρσ_modules["read_book.paged_mode"].handle_gesture = handle_gesture;
    })();

    (function(){
        var __name__ = "read_book.shortcuts";
        var GROUP_DESC, SHORTCUTS;
        var _ = ρσ_modules.gettext.gettext;

        function parse_key_repr(sc) {
            var parts, key, ans, q, modifier;
            parts = sc.split("+");
            if (sc.endsWith("++")) {
                parts = parts.slice(0, -2);
                parts.push("+");
            }
            key = parts[parts.length-1];
            ans = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["key"] = key;
                ρσ_d["altKey"] = false;
                ρσ_d["ctrlKey"] = false;
                ρσ_d["metaKey"] = false;
                ρσ_d["shiftKey"] = false;
                return ρσ_d;
            }).call(this);
            var ρσ_Iter0 = ρσ_Iterable(parts.slice(0, -1));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                modifier = ρσ_Iter0[ρσ_Index0];
                q = modifier.toLowerCase();
                if (q === "ctrl") {
                    ans.ctrlKey = true;
                } else if (q === "alt") {
                    ans.altKey = true;
                } else if (q === "meta") {
                    ans.metaKey = true;
                } else if (q === "shift") {
                    ans.shiftKey = true;
                }
            }
            return ans;
        };
        if (!parse_key_repr.__argnames__) Object.defineProperties(parse_key_repr, {
            __argnames__ : {value: ["sc"]}
        });

        function desc(sc, group, short, long) {
            var pkey, x;
            if (typeof sc === "string") {
                sc = [sc];
            }
            pkey = [];
            var ρσ_Iter1 = ρσ_Iterable(sc);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                x = ρσ_Iter1[ρσ_Index1];
                pkey.push(parse_key_repr(x));
            }
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["group"] = group;
                ρσ_d["short"] = short;
                ρσ_d["long"] = long;
                ρσ_d["shortcuts"] = pkey;
                return ρσ_d;
            }).call(this);
        };
        if (!desc.__argnames__) Object.defineProperties(desc, {
            __argnames__ : {value: ["sc", "group", "short", "long"]}
        });

        function keyevent_as_shortcut(evt) {
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["key"] = evt.key;
                ρσ_d["altKey"] = evt.altKey;
                ρσ_d["ctrlKey"] = evt.ctrlKey;
                ρσ_d["metaKey"] = evt.metaKey;
                ρσ_d["shiftKey"] = evt.shiftKey;
                return ρσ_d;
            }).call(this);
        };
        if (!keyevent_as_shortcut.__argnames__) Object.defineProperties(keyevent_as_shortcut, {
            __argnames__ : {value: ["evt"]}
        });

        function shortcut_differs(a, b) {
            return !(a.key === b.key && a.altKey === b.altKey && a.ctrlKey === b.ctrlKey && a.metaKey === b.metaKey && a.shiftKey === b.shiftKey);
        };
        if (!shortcut_differs.__argnames__) Object.defineProperties(shortcut_differs, {
            __argnames__ : {value: ["a", "b"]}
        });

        function get_key_text(evt) {
            var key, cc;
            key = evt.key;
            if (key) {
                cc = key.charCodeAt(0);
                if (0 < cc && cc < 32 && evt.ctrlKey && !evt.metaKey && !evt.shiftKey && !evt.altKey) {
                    key = chr(96 + cc);
                }
            }
            return key;
        };
        if (!get_key_text.__argnames__) Object.defineProperties(get_key_text, {
            __argnames__ : {value: ["evt"]}
        });

        function keyevent_to_index(evt) {
            var parts, mod;
            parts = [];
            var ρσ_Iter2 = ρσ_Iterable(['altKey', 'ctrlKey', 'metaKey', 'shiftKey']);
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                mod = ρσ_Iter2[ρσ_Index2];
                parts.push((evt[(typeof mod === "number" && mod < 0) ? evt.length + mod : mod]) ? "y" : "n");
            }
            return parts.join("") + get_key_text(evt);
        };
        if (!keyevent_to_index.__argnames__) Object.defineProperties(keyevent_to_index, {
            __argnames__ : {value: ["evt"]}
        });

        function key_as_text(evt) {
            var mods, x, key;
            mods = [];
            var ρσ_Iter3 = ρσ_Iterable(ρσ_list_decorate([ "alt", "ctrl", "meta", "shift" ]));
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                x = ρσ_Iter3[ρσ_Index3];
                if (evt[ρσ_bound_index(x + "Key", evt)]) {
                    if (ρσ_in("macos", window.navigator.userAgent)) {
                        if (x === "alt") {
                            x = "option";
                        } else if (x === "meta") {
                            x = "⌘";
                        }
                    }
                    mods.push(x.capitalize());
                }
            }
            mods = "+".join(mods);
            if (mods) {
                mods += "+";
            }
            key = get_key_text(evt);
            if (key === " ") {
                key = "Space";
            }
            return mods + key;
        };
        if (!key_as_text.__argnames__) Object.defineProperties(key_as_text, {
            __argnames__ : {value: ["evt"]}
        });

        GROUP_DESC = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["scroll"] = _("Navigation");
            ρσ_d["ui"] = _("Interface");
            return ρσ_d;
        }).call(this);
        SHORTCUTS = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["start_of_file"] = desc(['Ctrl+ArrowUp', 'Ctrl+ArrowLeft', 'Home'], "scroll", _("Scroll to the beginning of the current file"), _("When the e-book is made of of multiple individual files, scroll to the start of the current file."));
            ρσ_d["start_of_book"] = desc("Ctrl+Home", "scroll", _("Scroll to the beginning of the book"));
            ρσ_d["end_of_book"] = desc("Ctrl+End", "scroll", _("Scroll to the end of the book"));
            ρσ_d["end_of_file"] = desc(['Ctrl+ArrowDown', 'Ctrl+ArrowRight', 'End'], "scroll", _("Scroll to the end of the current file"), _("When the e-book is made of of multiple individual files, scroll to the end of the current file."));
            ρσ_d["up"] = desc("ArrowUp", "scroll", _("Scroll backwards smoothly (by screen-fulls in paged mode)"), _("Scroll backwards, smoothly in flow mode and by screen fulls in paged mode"));
            ρσ_d["down"] = desc("ArrowDown", "scroll", _("Scroll forwards smoothly (by screen-fulls in paged mode)"), _("Scroll forwards, smoothly in flow mode and by screen fulls in paged mode"));
            ρσ_d["left"] = desc("ArrowLeft", "scroll", _("Scroll left"), _("Scroll leftwards by a little in flow mode and by a page in paged mode"));
            ρσ_d["right"] = desc("ArrowRight", "scroll", _("Scroll right"), _("Scroll rightwards by a little in flow mode and by a page in paged mode"));
            ρσ_d["pageup"] = desc("PageUp", "scroll", _("Scroll backwards by screen-fulls"));
            ρσ_d["pagedown"] = desc([' ', 'PageDown'], "scroll", _("Scroll forwards by screen-fulls"));
            ρσ_d["previous_section"] = desc("Ctrl+PageUp", "scroll", _("Scroll to the previous section"));
            ρσ_d["next_section"] = desc("Ctrl+PageDown", "scroll", _("Scroll to the next section"));
            ρσ_d["back"] = desc(['Alt+ArrowLeft', 'Shift+ArrowLeft'], "scroll", _("Back"));
            ρσ_d["forward"] = desc(['Alt+ArrowRight', 'Shift+ArrowRight'], "scroll", _("Forward"));
            ρσ_d["toggle_toc"] = desc("Ctrl+t", "ui", _("Show/hide Table of Contents"));
            ρσ_d["start_search"] = desc(['/', 'Ctrl+f'], "ui", _("Start search"));
            ρσ_d["next_match"] = desc(['F3'], "ui", _("Find next"));
            ρσ_d["previous_match"] = desc(['Shift+F3'], "ui", _("Find previous"));
            ρσ_d["increase_font_size"] = desc(['Ctrl+=', 'Ctrl++', 'Ctrl+Shift++', 'Ctrl+Shift+='], "ui", _("Increase font size"));
            ρσ_d["decrease_font_size"] = desc(['Ctrl+-', 'Ctrl+_', 'Ctrl+Shift+-', 'Ctrl+Shift+_'], "ui", _("Decrease font size"));
            ρσ_d["toggle_full_screen"] = desc(['F11', 'Ctrl+Shift+F'], "ui", _("Toggle full screen"));
            ρσ_d["toggle_paged_mode"] = desc("Ctrl+m", "ui", _("Toggle between Paged mode and Flow mode for text layout"));
            ρσ_d["reload_book"] = desc(['F5', 'Ctrl+r'], "ui", _("Reload book"));
            ρσ_d["search_for_selection"] = desc(['Ctrl+s'], "ui", _("Search for next occurrence of selected text"));
            ρσ_d["show_chrome"] = desc(['Escape', 'ContextMenu'], "ui", _("Show the viewer controls"));
            return ρσ_d;
        }).call(this);
        function add_standalone_viewer_shortcuts() {
            var ismacos, quit_shortcut;
            ismacos = ρσ_in("macos", window.navigator.userAgent);
            SHORTCUTS["toggle_bookmarks"] = desc(['Ctrl+b'], "ui", _("Show/hide bookmarks"));
            SHORTCUTS["toggle_inspector"] = desc(['Ctrl+i'], "ui", _("Show/hide Inspector"));
            SHORTCUTS["toggle_lookup"] = desc(['Ctrl+l'], "ui", _("Show/hide the word lookup panel"));
            quit_shortcut = (ismacos) ? "Meta+q" : "Ctrl+q";
            SHORTCUTS["quit"] = desc(quit_shortcut, "ui", _("Quit the viewer"));
        };

        function create_shortcut_map(custom_shortcuts) {
            var ans, entry, shortcuts, sc, sc_name;
            ans = Object.create(null);
            var ρσ_Iter4 = ρσ_Iterable(Object.keys(SHORTCUTS));
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                sc_name = ρσ_Iter4[ρσ_Index4];
                entry = SHORTCUTS[(typeof sc_name === "number" && sc_name < 0) ? SHORTCUTS.length + sc_name : sc_name];
                shortcuts = entry.shortcuts;
                if (custom_shortcuts && custom_shortcuts[(typeof sc_name === "number" && sc_name < 0) ? custom_shortcuts.length + sc_name : sc_name]) {
                    shortcuts = custom_shortcuts[(typeof sc_name === "number" && sc_name < 0) ? custom_shortcuts.length + sc_name : sc_name];
                }
                var ρσ_Iter5 = ρσ_Iterable(shortcuts);
                for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                    sc = ρσ_Iter5[ρσ_Index5];
                    ans[ρσ_bound_index(keyevent_to_index(sc), ans)] = sc_name;
                }
            }
            return ans;
        };
        if (!create_shortcut_map.__argnames__) Object.defineProperties(create_shortcut_map, {
            __argnames__ : {value: ["custom_shortcuts"]}
        });

        function shortcut_for_key_event(evt, shortcut_map) {
            var idx;
            idx = keyevent_to_index(evt);
            return shortcut_map[(typeof idx === "number" && idx < 0) ? shortcut_map.length + idx : idx];
        };
        if (!shortcut_for_key_event.__argnames__) Object.defineProperties(shortcut_for_key_event, {
            __argnames__ : {value: ["evt", "shortcut_map"]}
        });

        ρσ_modules["read_book.shortcuts"].GROUP_DESC = GROUP_DESC;
        ρσ_modules["read_book.shortcuts"].SHORTCUTS = SHORTCUTS;
        ρσ_modules["read_book.shortcuts"].parse_key_repr = parse_key_repr;
        ρσ_modules["read_book.shortcuts"].desc = desc;
        ρσ_modules["read_book.shortcuts"].keyevent_as_shortcut = keyevent_as_shortcut;
        ρσ_modules["read_book.shortcuts"].shortcut_differs = shortcut_differs;
        ρσ_modules["read_book.shortcuts"].get_key_text = get_key_text;
        ρσ_modules["read_book.shortcuts"].keyevent_to_index = keyevent_to_index;
        ρσ_modules["read_book.shortcuts"].key_as_text = key_as_text;
        ρσ_modules["read_book.shortcuts"].add_standalone_viewer_shortcuts = add_standalone_viewer_shortcuts;
        ρσ_modules["read_book.shortcuts"].create_shortcut_map = create_shortcut_map;
        ρσ_modules["read_book.shortcuts"].shortcut_for_key_event = shortcut_for_key_event;
    })();

    (function(){
        var __name__ = "complete";
        var ensure_id = ρσ_modules.dom.ensure_id;

        var E = ρσ_modules.elementmaker.E;

        var local_storage = ρσ_modules.session.local_storage;

        var CompletionPopup = ρσ_modules.popups.CompletionPopup;

        var uniq = ρσ_modules.utils.uniq;

        function EditWithComplete() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            EditWithComplete.prototype.__bind_methods__.call(this);
            EditWithComplete.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(EditWithComplete.prototype, "__bind_methods__", {value: function () {
            this.apply_completion = EditWithComplete.prototype.apply_completion.bind(this);
            this.onkeydown = EditWithComplete.prototype.onkeydown.bind(this);
            this.oninput = EditWithComplete.prototype.oninput.bind(this);
            this.hide_completion_popup = EditWithComplete.prototype.hide_completion_popup.bind(this);
            this.add_associated_widget = EditWithComplete.prototype.add_associated_widget.bind(this);
            this.set_all_items = EditWithComplete.prototype.set_all_items.bind(this);
        }});
        Object.defineProperties(EditWithComplete.prototype,  {
            "text_input": {
                "enumerable": true, 
                "get": function text_input() {
                    var self = this;
                    return document.getElementById(self.input_id);
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        EditWithComplete.prototype.__init__ = function __init__() {
            var self = this;
            var name = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var placeholder = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.placeholder : arguments[1];
            var tooltip = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.tooltip : arguments[2];
            var parent = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.parent : arguments[3];
            var input_type = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.input_type : arguments[4];
            var onenterkey = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.onenterkey : arguments[5];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "placeholder")){
                placeholder = ρσ_kwargs_obj.placeholder;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "tooltip")){
                tooltip = ρσ_kwargs_obj.tooltip;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "parent")){
                parent = ρσ_kwargs_obj.parent;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "input_type")){
                input_type = ρσ_kwargs_obj.input_type;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "onenterkey")){
                onenterkey = ρσ_kwargs_obj.onenterkey;
            }
            var inpt;
            inpt = ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: input_type, name: name, title: tooltip || "", placeholder: placeholder || ""})]);
            self.input_id = ensure_id(inpt);
            self.onenterkey = onenterkey;
            self.completion_popup = ρσ_interpolate_kwargs_constructor.call(Object.create(CompletionPopup.prototype), false, CompletionPopup, [ρσ_desugar_kwargs({parent: parent, onselect: self.apply_completion})]);
            inpt.addEventListener("keydown", self.onkeydown);
            inpt.addEventListener("input", self.oninput);
            self.completion_popup.add_associated_widget(inpt);
            if (parent) {
                parent.appendChild(inpt);
            }
        };
        if (!EditWithComplete.prototype.__init__.__defaults__) Object.defineProperties(EditWithComplete.prototype.__init__, {
            __defaults__ : {value: {placeholder:null, tooltip:null, parent:null, input_type:"text", onenterkey:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["name", "placeholder", "tooltip", "parent", "input_type", "onenterkey"]}
        });
        EditWithComplete.__argnames__ = EditWithComplete.prototype.__init__.__argnames__;
        EditWithComplete.__handles_kwarg_interpolation__ = EditWithComplete.prototype.__init__.__handles_kwarg_interpolation__;
        EditWithComplete.prototype.apply_completion = function apply_completion(text) {
            var self = this;
            var ti;
            if (text) {
                ti = self.text_input;
                ti.value = text;
                ti.focus();
                return true;
            }
        };
        if (!EditWithComplete.prototype.apply_completion.__argnames__) Object.defineProperties(EditWithComplete.prototype.apply_completion, {
            __argnames__ : {value: ["text"]}
        });
        EditWithComplete.prototype.onkeydown = function onkeydown(event) {
            var self = this;
            if (self.completion_popup.is_visible && self.completion_popup.handle_keydown(event)) {
                [event.preventDefault(), event.stopPropagation()];
                return;
            }
            if (event.key === "Enter") {
                if (self.onenterkey) {
                    [event.preventDefault(), event.stopPropagation()];
                    self.onenterkey();
                }
            } else if (event.key === "Tab") {
                if (self.completion_popup.is_visible) {
                    if (self.apply_completion(self.completion_popup.current_text)) {
                        self.completion_popup.hide();
                    } else {
                        self.completion_popup.move_highlight();
                    }
                    [event.preventDefault(), event.stopPropagation()];
                }
            }
        };
        if (!EditWithComplete.prototype.onkeydown.__argnames__) Object.defineProperties(EditWithComplete.prototype.onkeydown, {
            __argnames__ : {value: ["event"]}
        });
        EditWithComplete.prototype.oninput = function oninput(event) {
            var self = this;
            var ti;
            ti = self.text_input;
            self.completion_popup.set_query(ti.value || "");
            self.completion_popup.popup(ti);
        };
        if (!EditWithComplete.prototype.oninput.__argnames__) Object.defineProperties(EditWithComplete.prototype.oninput, {
            __argnames__ : {value: ["event"]}
        });
        EditWithComplete.prototype.hide_completion_popup = function hide_completion_popup() {
            var self = this;
            self.completion_popup.hide();
        };
        EditWithComplete.prototype.add_associated_widget = function add_associated_widget(widget_or_id) {
            var self = this;
            self.completion_popup.add_associated_widget(widget_or_id);
        };
        if (!EditWithComplete.prototype.add_associated_widget.__argnames__) Object.defineProperties(EditWithComplete.prototype.add_associated_widget, {
            __argnames__ : {value: ["widget_or_id"]}
        });
        EditWithComplete.prototype.set_all_items = function set_all_items(items) {
            var self = this;
            self.completion_popup.set_all_items(items);
        };
        if (!EditWithComplete.prototype.set_all_items.__argnames__) Object.defineProperties(EditWithComplete.prototype.set_all_items, {
            __argnames__ : {value: ["items"]}
        });
        EditWithComplete.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        EditWithComplete.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(EditWithComplete.prototype, "__bases__", {value: []});
        

        function create_search_bar() {
            var action = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var name = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var tooltip = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_search_bar.__defaults__.tooltip : arguments[2];
            var placeholder = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_search_bar.__defaults__.placeholder : arguments[3];
            var button = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_search_bar.__defaults__.button : arguments[4];
            var history_size = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_search_bar.__defaults__.history_size : arguments[5];
            var associated_widgets = (arguments[6] === undefined || ( 6 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_search_bar.__defaults__.associated_widgets : arguments[6];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "tooltip")){
                tooltip = ρσ_kwargs_obj.tooltip;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "placeholder")){
                placeholder = ρσ_kwargs_obj.placeholder;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "button")){
                button = ρσ_kwargs_obj.button;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "history_size")){
                history_size = ρσ_kwargs_obj.history_size;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "associated_widgets")){
                associated_widgets = ρσ_kwargs_obj.associated_widgets;
            }
            var parent, ewc, history_name, w;
            parent = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "display:flex"})]);
            ewc = ρσ_interpolate_kwargs_constructor.call(Object.create(EditWithComplete.prototype), false, EditWithComplete, [name].concat([ρσ_desugar_kwargs({parent: parent, tooltip: tooltip, placeholder: placeholder, input_type: "search"})]));
            parent.lastChild.style.width = "100%";
            history_name = "search-bar-history-" + name;
            function update_completion_items() {
                var items;
                items = local_storage().get(history_name);
                if ((typeof items !== "undefined" && items !== null ? items : Object.create(null)).length) {
                    ewc.set_all_items(items);
                }
            };

            update_completion_items();
            function trigger() {
                var text, items, idx;
                text = ewc.text_input.value;
                ewc.hide_completion_popup();
                action(text);
                if (text && text.strip()) {
                    items = local_storage().get(history_name) || [];
                    idx = items.indexOf(text);
                    if (idx > -1) {
                        items = items.splice(idx, 1);
                    }
                    items.unshift(text);
                    local_storage().set(history_name, uniq(items.slice(0, history_size)));
                    update_completion_items();
                }
            };

            ewc.onenterkey = trigger;
            if (button) {
                ewc.add_associated_widget(button);
                button.addEventListener("click", trigger);
            }
            if (associated_widgets !== null) {
                var ρσ_Iter0 = ρσ_Iterable(associated_widgets);
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    w = ρσ_Iter0[ρσ_Index0];
                    ewc.add_associated_widget(w);
                }
            }
            return parent;
        };
        if (!create_search_bar.__defaults__) Object.defineProperties(create_search_bar, {
            __defaults__ : {value: {tooltip:null, placeholder:null, button:null, history_size:100, associated_widgets:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["action", "name", "tooltip", "placeholder", "button", "history_size", "associated_widgets"]}
        });

        function main(container) {
            container.appendChild(ρσ_interpolate_kwargs.call(this, create_search_bar, [print, "test-search-bar"].concat([ρσ_desugar_kwargs({placeholder: "Testing search bar"})])));
            container.firstChild.lastChild.focus();
        };
        if (!main.__argnames__) Object.defineProperties(main, {
            __argnames__ : {value: ["container"]}
        });

        ρσ_modules.complete.EditWithComplete = EditWithComplete;
        ρσ_modules.complete.create_search_bar = create_search_bar;
        ρσ_modules.complete.main = main;
    })();

    (function(){
        var __name__ = "widgets";
        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var svgicon = ρσ_modules.dom.svgicon;
        var create_keyframes = ρσ_modules.dom.create_keyframes;
        var set_css = ρσ_modules.dom.set_css;
        var change_icon_image = ρσ_modules.dom.change_icon_image;
        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var ensure_id = ρσ_modules.dom.ensure_id;

        var E = ρσ_modules.elementmaker.E;

        var get_color = ρσ_modules["book_list.theme"].get_color;

        function create_button() {
            var text = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var icon = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_button.__defaults__.icon : arguments[1];
            var action = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_button.__defaults__.action : arguments[2];
            var tooltip = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_button.__defaults__.tooltip : arguments[3];
            var highlight = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_button.__defaults__.highlight : arguments[4];
            var download_filename = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_button.__defaults__.download_filename : arguments[5];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "icon")){
                icon = ρσ_kwargs_obj.icon;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "action")){
                action = ρσ_kwargs_obj.action;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "tooltip")){
                tooltip = ρσ_kwargs_obj.tooltip;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "highlight")){
                highlight = ρσ_kwargs_obj.highlight;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "download_filename")){
                download_filename = ρσ_kwargs_obj.download_filename;
            }
            var ic, ans;
            ic = "";
            if (icon) {
                ic = svgicon(icon);
                text = " " + text;
            }
            ans = ρσ_interpolate_kwargs.call(E, E.a, [ic, E.span(text)].concat([ρσ_desugar_kwargs({class_: "calibre-push-button", href: "javascript: void(0)", title: tooltip || ""})]));
            if (download_filename && "download" in ans) {
                ans.setAttribute("download", download_filename);
            }
            if (action !== null) {
                if (typeof action === "string") {
                    ans.setAttribute("href", action);
                } else {
                    ans.addEventListener("click", (function() {
                        var ρσ_anonfunc = function (event) {
                            [event.preventDefault(), action(event)];
                        };
                        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                            __argnames__ : {value: ["event"]}
                        });
                        return ρσ_anonfunc;
                    })());
                }
            }
            if (highlight) {
                ρσ_interpolate_kwargs.call(this, set_css, [ans].concat([ρσ_desugar_kwargs({font_size: "larger", font_weight: "bold"})]));
            }
            return ans;
        };
        if (!create_button.__defaults__) Object.defineProperties(create_button, {
            __defaults__ : {value: {icon:null, action:null, tooltip:null, highlight:false, download_filename:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["text", "icon", "action", "tooltip", "highlight", "download_filename"]}
        });

        create_button.style = ρσ_interpolate_kwargs.call(this, build_rule, ["a.calibre-push-button"].concat([ρσ_desugar_kwargs({border_radius: "1em", background_clip: "padding-box", background_color: get_color("button-start"), background_image: "linear-gradient(to bottom, {}, {})".format(get_color("button-start"), get_color("button-end")), padding: "0.5ex 1em", color: get_color("button-text"), cursor: "pointer", font_size: "inherit", display: "inline-flex", align_items: "center", box_shadow: "0px 2px 1px rgba(50, 50, 50, 0.75)", white_space: "nowrap"})]));
        create_button.style += ρσ_interpolate_kwargs.call(this, build_rule, ["a.calibre-push-button:hover"].concat([ρσ_desugar_kwargs({transform: "scale(1.2)"})]));
        create_button.style += ρσ_interpolate_kwargs.call(this, build_rule, ["a.calibre-push-button:active"].concat([ρσ_desugar_kwargs({transform: "scale(2)"})]));
        function create_spinner(height, width) {
            var ans;
            ans = svgicon("cog", height, width);
            ans.classList.add("spin");
            return ans;
        };
        if (!create_spinner.__argnames__) Object.defineProperties(create_spinner, {
            __argnames__ : {value: ["height", "width"]}
        });

        create_spinner.style = ρσ_interpolate_kwargs.call(this, build_rule, [".spin"].concat([ρσ_desugar_kwargs({animation: "spin 2s infinite linear"})]));
        create_spinner.style += create_keyframes("spin", "from { transform: rotate(0deg); } to { transform: rotate(359deg);}");
        function Breadcrumbs() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            Breadcrumbs.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperties(Breadcrumbs.prototype,  {
            "container": {
                "enumerable": true, 
                "get": function container() {
                    var self = this;
                    return document.getElementById(self.container_id);
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        Breadcrumbs.prototype.__init__ = function __init__(container) {
            var self = this;
            self.container_id = ensure_id(container, "calibre-breadcrumbs-");
            container.classList.add("calibre-breadcrumbs");
            clear(container);
        };
        if (!Breadcrumbs.prototype.__init__.__argnames__) Object.defineProperties(Breadcrumbs.prototype.__init__, {
            __argnames__ : {value: ["container"]}
        });
        Breadcrumbs.__argnames__ = Breadcrumbs.prototype.__init__.__argnames__;
        Breadcrumbs.__handles_kwarg_interpolation__ = Breadcrumbs.prototype.__init__.__handles_kwarg_interpolation__;
        Breadcrumbs.prototype.reset = function reset() {
            var self = this;
            clear(self.container);
        };
        Breadcrumbs.prototype.add_crumb = function add_crumb(callback) {
            var self = this;
            var li;
            li = E.li();
            if (callback) {
                li.addEventListener("click", callback);
            }
            self.container.appendChild(li);
            return li;
        };
        if (!Breadcrumbs.prototype.add_crumb.__argnames__) Object.defineProperties(Breadcrumbs.prototype.add_crumb, {
            __argnames__ : {value: ["callback"]}
        });
        Breadcrumbs.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        Breadcrumbs.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(Breadcrumbs.prototype, "__bases__", {value: []});
        Breadcrumbs.prototype.STYLE_RULES = ρσ_interpolate_kwargs.call(this, build_rule, [".calibre-breadcrumbs"].concat([ρσ_desugar_kwargs({user_select: "none", white_space: "nowrap", background_color: get_color("window-background2"), z_index: "-1", border_radius: "10px", margin: "1ex 1em", margin_bottom: "0"})]));
        Breadcrumbs.prototype.STYLE_RULES += ρσ_interpolate_kwargs.call(this, build_rule, [".calibre-breadcrumbs > li"].concat([ρσ_desugar_kwargs({cursor: "pointer", display: "inline-block", line_height: "26px", margin: "0 9px 0 -10px", padding: "0.5ex 1rem", position: "relative"})]));
        Breadcrumbs.prototype.STYLE_RULES += ρσ_interpolate_kwargs.call(this, build_rule, [".calibre-breadcrumbs > li:hover"].concat([ρσ_desugar_kwargs({color: get_color("window-hover-foreground")})]));
        Breadcrumbs.prototype.STYLE_RULES += ρσ_interpolate_kwargs.call(this, build_rule, [".calibre-breadcrumbs > li:active"].concat([ρσ_desugar_kwargs({color: get_color("window-hover-foreground"), transform: "scale(1.5)"})]));
        Breadcrumbs.prototype.STYLE_RULES += ρσ_interpolate_kwargs.call(this, build_rule, [".calibre-breadcrumbs > li:before, .calibre-breadcrumbs > li:after"].concat([ρσ_desugar_kwargs({border_right: "2px solid currentColor", content: "\"\"", display: "block", height: "50%", position: "absolute", left: "0", top: "0", right: "0", transform: "skewX(45deg)"})]));
        Breadcrumbs.prototype.STYLE_RULES += ρσ_interpolate_kwargs.call(this, build_rule, [".calibre-breadcrumbs > li:after"].concat([ρσ_desugar_kwargs({bottom: "0", top: "auto", transform: "skewX(-45deg)"})]));
        Breadcrumbs.prototype.STYLE_RULES += ρσ_interpolate_kwargs.call(this, build_rule, [".calibre-breadcrumbs > li:last-of-type:before, .calibre-breadcrumbs > li:last-of-type:after"].concat([ρσ_desugar_kwargs({display: "none"})]));
        

        function create_tree(root, populate_data, onclick) {
            var container;
            container = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: "simple-tree"})]);
            ρσ_interpolate_kwargs.call(this, set_css, [container].concat([ρσ_desugar_kwargs({overflow: "auto"})]));
            function toggle_node(li) {
                if (li.dataset.treeState === "closed") {
                    li.dataset.treeState = "open";
                    li.lastChild.style.display = "block";
                    change_icon_image(li.firstChild.firstChild, "caret-down");
                } else {
                    li.dataset.treeState = "closed";
                    li.lastChild.style.display = "none";
                    change_icon_image(li.firstChild.firstChild, "caret-right");
                }
            };
            if (!toggle_node.__argnames__) Object.defineProperties(toggle_node, {
                __argnames__ : {value: ["li"]}
            });

            function process_node(node, parent_container, level) {
                var ul, icon, li, child;
                if (ρσ_exists.d(node.children).length) {
                    ul = E.div();
                    parent_container.appendChild(ul);
                    var ρσ_Iter0 = ρσ_Iterable(node.children);
                    for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                        child = ρσ_Iter0[ρσ_Index0];
                        icon = (ρσ_exists.d(child.children).length) ? "caret-right" : null;
                        li = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [svgicon(icon), E.span(" "), ρσ_interpolate_kwargs.call(E, E.a, [ρσ_desugar_kwargs({href: "javascript: void(0)", class_: "simple-link tree-item-title", onclick: (function() {
                            var ρσ_anonfunc = function (event) {
                                if (onclick) {
                                    if (event.button === 0) {
                                        [event.preventDefault(), event.stopPropagation()];
                                    }
                                    onclick(event, event.currentTarget.parentNode.parentNode);
                                }
                            };
                            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                                __argnames__ : {value: ["event"]}
                            });
                            return ρσ_anonfunc;
                        })()})])].concat([ρσ_desugar_kwargs({style: "display:flex; align-items: center"})])), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "display:none", data_tree_subtree_container: "1"})])].concat([ρσ_desugar_kwargs({style: "display:flex; flex-direction:column; margin: 1ex 1em; margin-left: {}em".format(level + 1), data_tree_state: "closed"})]));
                        ul.appendChild(li);
                        populate_data(child, li, li.firstChild.lastChild);
                        if (icon) {
                            ρσ_interpolate_kwargs.call(this, set_css, [li.firstChild.firstChild].concat([ρσ_desugar_kwargs({cursor: "pointer"})]));
                            li.firstChild.firstChild.addEventListener("click", (function() {
                                var ρσ_anonfunc = function (event) {
                                    toggle_node(event.currentTarget.parentNode.parentNode);
                                };
                                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                                    __argnames__ : {value: ["event"]}
                                });
                                return ρσ_anonfunc;
                            })());
                            process_node(child, li.lastChild, level + 1);
                        }
                    }
                }
            };
            if (!process_node.__argnames__) Object.defineProperties(process_node, {
                __argnames__ : {value: ["node", "parent_container", "level"]}
            });

            if (root) {
                process_node(root, container, 0);
            }
            return container;
        };
        if (!create_tree.__argnames__) Object.defineProperties(create_tree, {
            __argnames__ : {value: ["root", "populate_data", "onclick"]}
        });

        function find_text_in_tree(container, q) {
            var last_match, lm, before, seen, ans, a;
            q = q.lower();
            last_match = container.querySelector("a[data-tree-last-match]");
            if (last_match) {
                last_match.parentNode.style.backgroundColor = "transparent";
                last_match.parentNode.style.borderRadius = "0";
                lm = last_match.getAttribute("data-tree-last-match");
                last_match.removeAttribute("data-tree-last-match");
                if (lm !== q) {
                    last_match = null;
                }
            }
            if (!q) {
                return;
            }
            before = ρσ_list_decorate([]);
            seen = false;
            ans = null;
            var ρσ_Iter1 = ρσ_Iterable(container.querySelectorAll("a.tree-item-title"));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                a = ρσ_Iter1[ρσ_Index1];
                if (a === last_match) {
                    seen = true;
                } else {
                    if (ρσ_not_equals(a.textContent.lower().indexOf(q), -1)) {
                        if (seen) {
                            ans = a;
                            break;
                        }
                        if (last_match === null) {
                            ans = a;
                            break;
                        }
                        before.push(a);
                    }
                }
            }
            if (!ans && before.length) {
                ans = before[0];
            }
            ans = ans || last_match;
            if (ans) {
                ans.dataset.treeLastMatch = q;
            }
            if (ans) {
                ans.parentNode.style.backgroundColor = get_color("tree-highlight-item");
                ans.parentNode.style.borderRadius = "5px";
                ans = ans.parentNode.parentNode;
            }
            return ans;
        };
        if (!find_text_in_tree.__argnames__) Object.defineProperties(find_text_in_tree, {
            __argnames__ : {value: ["container", "q"]}
        });

        function scroll_tree_item_into_view(item) {
            var p;
            p = ρσ_exists.d(item.parentNode).parentNode;
            while (p && p.getAttribute("data-tree-subtree-container")) {
                p.style.display = "block";
                p = ρσ_exists.d(ρσ_exists.d(p.parentNode).parentNode).parentNode;
            }
            item.scrollIntoView();
        };
        if (!scroll_tree_item_into_view.__argnames__) Object.defineProperties(scroll_tree_item_into_view, {
            __argnames__ : {value: ["item"]}
        });

        add_extra_css(function () {
            var ans;
            ans = "a, button:focus { outline: none }; a, button::-moz-focus-inner { border: 0 }\n";
            ans += ".simple-link { cursor: pointer } .simple-link:hover { color: HC } .simple-link:active { transform: scale(1.5) }\n".replace("HC", get_color("window-hover-foreground"));
            ans += ".blue-link { cursor: pointer; color: COL } .blue-link:hover { color: HC } .blue-link:active { transform: scale(1.5) }\n".replace("HC", get_color("window-hover-foreground")).replace("COL", get_color("link-foreground"));
            ans += create_button.style + "\n";
            ans += create_button.style + "\n";
            ans += create_spinner.style + "\n";
            ans += Breadcrumbs.prototype.STYLE_RULES + "\n";
            return ans;
        });
        ρσ_modules.widgets.create_button = create_button;
        ρσ_modules.widgets.create_spinner = create_spinner;
        ρσ_modules.widgets.Breadcrumbs = Breadcrumbs;
        ρσ_modules.widgets.create_tree = create_tree;
        ρσ_modules.widgets.find_text_in_tree = find_text_in_tree;
        ρσ_modules.widgets.scroll_tree_item_into_view = scroll_tree_item_into_view;
    })();

    (function(){
        var __name__ = "read_book.toc";
        var create_search_bar = ρσ_modules.complete.create_search_bar;

        var set_css = ρσ_modules.dom.set_css;
        var svgicon = ρσ_modules.dom.svgicon;
        var ensure_id = ρσ_modules.dom.ensure_id;

        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var error_dialog = ρσ_modules.modals.error_dialog;

        var create_tree = ρσ_modules.widgets.create_tree;
        var find_text_in_tree = ρσ_modules.widgets.find_text_in_tree;
        var scroll_tree_item_into_view = ρσ_modules.widgets.scroll_tree_item_into_view;

        var toc_anchor_map = ρσ_modules["read_book.globals"].toc_anchor_map;
        var set_toc_anchor_map = ρσ_modules["read_book.globals"].set_toc_anchor_map;
        var current_spine_item = ρσ_modules["read_book.globals"].current_spine_item;
        var current_layout_mode = ρσ_modules["read_book.globals"].current_layout_mode;
        var current_book = ρσ_modules["read_book.globals"].current_book;

        var scroll_viewport = ρσ_modules["read_book.viewport"].scroll_viewport;

        function update_visible_toc_nodes(visible_anchors) {
            update_visible_toc_nodes.data = visible_anchors;
        };
        if (!update_visible_toc_nodes.__argnames__) Object.defineProperties(update_visible_toc_nodes, {
            __argnames__ : {value: ["visible_anchors"]}
        });

        update_visible_toc_nodes.data = Object.create(null);
        function iter_toc_descendants(node, callback) {
            var child;
            var ρσ_Iter0 = ρσ_Iterable(node.children);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                child = ρσ_Iter0[ρσ_Index0];
                if (callback(child)) {
                    return;
                }
                iter_toc_descendants(child, callback);
            }
        };
        if (!iter_toc_descendants.__argnames__) Object.defineProperties(iter_toc_descendants, {
            __argnames__ : {value: ["node", "callback"]}
        });

        function get_border_nodes(toc, id_map) {
            var data, ρσ_unpack, before, after, spine, spine_before, spine_after, which, csi, name, prev;
            data = update_visible_toc_nodes.data;
            ρσ_unpack = [data.before, data.after];
            before = ρσ_unpack[0];
            after = ρσ_unpack[1];
            if (before) {
                before = id_map[(typeof before === "number" && before < 0) ? id_map.length + before : before];
            }
            if (after) {
                after = id_map[(typeof after === "number" && after < 0) ? id_map.length + after : after];
            }
            if (before && after) {
                return [before, after];
            }
            spine = current_book().manifest.spine;
            ρσ_unpack = [Object.create(null), Object.create(null)];
            spine_before = ρσ_unpack[0];
            spine_after = ρσ_unpack[1];
            which = spine_before;
            csi = current_spine_item();
            var ρσ_Iter1 = ρσ_Iterable(spine);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                name = ρσ_Iter1[ρσ_Index1];
                if (name === csi) {
                    which = spine_after;
                } else {
                    which[(typeof name === "number" && name < 0) ? which.length + name : name] = true;
                }
            }
            prev = null;
            iter_toc_descendants(toc, (function() {
                var ρσ_anonfunc = function (node) {
                    if (node.dest) {
                        if (spine_before[ρσ_bound_index(node.dest, spine_before)]) {
                            prev = node;
                        } else if (spine_after[ρσ_bound_index(node.dest, spine_after)]) {
                            if (!before) {
                                before = prev;
                            }
                            if (!after) {
                                after = node;
                            }
                            return true;
                        }
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["node"]}
                });
                return ρσ_anonfunc;
            })());
            return [before, after];
        };
        if (!get_border_nodes.__argnames__) Object.defineProperties(get_border_nodes, {
            __argnames__ : {value: ["toc", "id_map"]}
        });

        function get_current_toc_nodes() {
            var toc, ρσ_unpack, parent_map, id_map, data, ans, before, pid, node_id, p;
            toc = current_book().manifest.toc;
            ρσ_unpack = get_toc_maps(toc);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            parent_map = ρσ_unpack[0];
            id_map = ρσ_unpack[1];
            data = update_visible_toc_nodes.data;
            ans = Object.create(null);
            if (data.has_visible) {
                ans = data.visible_anchors;
            } else {
                if (data.before) {
                    ans[ρσ_bound_index(data.before, ans)] = true;
                } else {
                    before = get_border_nodes(toc, id_map)[0];
                    if (before) {
                        ans[ρσ_bound_index(before.id, ans)] = true;
                    }
                }
            }
            ans = Object.keys(ans);
            if (ans.length) {
                pid = node_id = ans[0];
                p = parent_map[(typeof pid === "number" && pid < 0) ? parent_map.length + pid : pid];
                while (p && p.title) {
                    pid = p.id;
                    p = parent_map[(typeof pid === "number" && pid < 0) ? parent_map.length + pid : pid];
                }
                p = id_map[(typeof pid === "number" && pid < 0) ? id_map.length + pid : pid];
                return [id_map[(typeof node_id === "number" && node_id < 0) ? id_map.length + node_id : node_id], 
                (p && p.title) ? p : null];
            }
            return [null, null];
        };

        function get_highlighted_toc_nodes(toc, parent_map, id_map) {
            var data, ans, before, p, node_id;
            data = update_visible_toc_nodes.data;
            ans = Object.create(null);
            if (data.has_visible) {
                ans = data.visible_anchors;
            } else {
                if (data.before) {
                    ans[ρσ_bound_index(data.before, ans)] = true;
                } else {
                    before = get_border_nodes(toc, id_map)[0];
                    if (before) {
                        ans[ρσ_bound_index(before.id, ans)] = true;
                    }
                }
            }
            var ρσ_Iter2 = ρσ_Iterable(Object.keys(ans));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                node_id = ρσ_Iter2[ρσ_Index2];
                p = parent_map[(typeof node_id === "number" && node_id < 0) ? parent_map.length + node_id : node_id];
                while (p && p.title) {
                    ans[ρσ_bound_index(p.id, ans)] = true;
                    p = parent_map[ρσ_bound_index(p.id, parent_map)];
                }
            }
            return ans;
        };
        if (!get_highlighted_toc_nodes.__argnames__) Object.defineProperties(get_highlighted_toc_nodes, {
            __argnames__ : {value: ["toc", "parent_map", "id_map"]}
        });

        function get_toc_maps(toc) {
            var ρσ_unpack, parent_map, id_map;
            if (!toc) {
                toc = current_book().manifest.toc;
            }
            ρσ_unpack = [Object.create(null), Object.create(null)];
            parent_map = ρσ_unpack[0];
            id_map = ρσ_unpack[1];
            function process_node(node, parent) {
                var c;
                id_map[ρσ_bound_index(node.id, id_map)] = node;
                parent_map[ρσ_bound_index(node.id, parent_map)] = parent;
                var ρσ_Iter3 = ρσ_Iterable(node.children);
                for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                    c = ρσ_Iter3[ρσ_Index3];
                    process_node(c, node);
                }
            };
            if (!process_node.__argnames__) Object.defineProperties(process_node, {
                __argnames__ : {value: ["node", "parent"]}
            });

            process_node(toc);
            return [parent_map, id_map];
        };
        if (!get_toc_maps.__argnames__) Object.defineProperties(get_toc_maps, {
            __argnames__ : {value: ["toc"]}
        });

        function create_toc_tree(toc, onclick) {
            var ρσ_unpack, parent_map, id_map, highlighted_toc_nodes;
            ρσ_unpack = get_toc_maps(toc);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            parent_map = ρσ_unpack[0];
            id_map = ρσ_unpack[1];
            highlighted_toc_nodes = get_highlighted_toc_nodes(toc, parent_map, id_map);
            function populate_data(node, li, a) {
                var title;
                li.dataset.tocDest = node.dest || "";
                li.dataset.tocFrag = node.frag || "";
                title = node.title || "";
                if (highlighted_toc_nodes[ρσ_bound_index(node.id, highlighted_toc_nodes)]) {
                    a.appendChild(E.b(E.i(title)));
                } else {
                    a.textContent = title;
                }
            };
            if (!populate_data.__argnames__) Object.defineProperties(populate_data, {
                __argnames__ : {value: ["node", "li", "a"]}
            });

            return create_tree(toc, populate_data, onclick);
        };
        if (!create_toc_tree.__argnames__) Object.defineProperties(create_toc_tree, {
            __argnames__ : {value: ["toc", "onclick"]}
        });

        function do_search(text) {
            var container, a;
            container = document.getElementById(this);
            a = find_text_in_tree(container, text);
            if (!text) {
                return;
            }
            if (!a) {
                return error_dialog(_("No matches found"), _("The text \"{}\" was not found in the Table of Contents").format(text));
            }
            scroll_tree_item_into_view(a);
        };
        if (!do_search.__argnames__) Object.defineProperties(do_search, {
            __argnames__ : {value: ["text"]}
        });

        function create_toc_panel(book, container, onclick) {
            var toc_panel, toc_panel_id, search_button, t, search_bar;
            function handle_click(event, li) {
                if (event.button === 0) {
                    onclick(li.dataset.tocDest, li.dataset.tocFrag);
                }
            };
            if (!handle_click.__argnames__) Object.defineProperties(handle_click, {
                __argnames__ : {value: ["event", "li"]}
            });

            toc_panel = create_toc_tree(book.manifest.toc, handle_click);
            toc_panel_id = ensure_id(toc_panel);
            ρσ_interpolate_kwargs.call(this, set_css, [container].concat([ρσ_desugar_kwargs({display: "flex", flex_direction: "column"})]));
            ρσ_interpolate_kwargs.call(this, set_css, [toc_panel].concat([ρσ_desugar_kwargs({flex_grow: "10"})]));
            container.appendChild(toc_panel);
            search_button = ρσ_interpolate_kwargs.call(E, E.div, [svgicon("search")].concat([ρσ_desugar_kwargs({class_: "simple-link"})]));
            t = _("Search Table of Contents");
            search_bar = ρσ_interpolate_kwargs.call(this, create_search_bar, [do_search.bind(toc_panel_id), "search-book-toc"].concat([ρσ_desugar_kwargs({button: search_button, placeholder: t})]));
            ρσ_interpolate_kwargs.call(this, set_css, [search_bar].concat([ρσ_desugar_kwargs({flex_grow: "10", margin_right: "1em"})]));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [search_bar, search_button].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em; display: flex;"})])));
        };
        if (!create_toc_panel.__argnames__) Object.defineProperties(create_toc_panel, {
            __argnames__ : {value: ["book", "container", "onclick"]}
        });

        function current_toc_anchor_map(tam, anchor_funcs) {
            var current_map, name, am, anchors, pos_map, val, elem, ρσ_unpack, i, anchor;
            current_map = toc_anchor_map();
            if (!(current_map && current_map.layout_mode === current_layout_mode() && current_map.width === scroll_viewport.width() && current_map.height === scroll_viewport.height())) {
                name = current_spine_item().name;
                am = Object.create(null);
                anchors = [];
                pos_map = Object.create(null);
                var ρσ_Iter4 = ρσ_Iterable(enumerate(tam[(typeof name === "number" && name < 0) ? tam.length + name : name] || []));
                for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                    ρσ_unpack = ρσ_Iter4[ρσ_Index4];
                    i = ρσ_unpack[0];
                    anchor = ρσ_unpack[1];
                    val = anchor_funcs.pos_for_elem();
                    if (anchor.frag) {
                        elem = document.getElementById(anchor.frag);
                        if (elem) {
                            val = anchor_funcs.pos_for_elem(elem);
                        }
                    }
                    am[ρσ_bound_index(anchor.id, am)] = val;
                    anchors.push(anchor.id);
                    pos_map[ρσ_bound_index(anchor.id, pos_map)] = i;
                }
                anchors.sort((function() {
                    var ρσ_anonfunc = function (a, b) {
                        return anchor_funcs.cmp(am[(typeof a === "number" && a < 0) ? am.length + a : a], am[(typeof b === "number" && b < 0) ? am.length + b : b]) || pos_map[(typeof a === "number" && a < 0) ? pos_map.length + a : a] - pos_map[(typeof b === "number" && b < 0) ? pos_map.length + b : b];
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["a", "b"]}
                    });
                    return ρσ_anonfunc;
                })());
                current_map = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["layout_mode"] = current_layout_mode;
                    ρσ_d["width"] = scroll_viewport.width();
                    ρσ_d["height"] = scroll_viewport.height();
                    ρσ_d["pos_map"] = am;
                    ρσ_d["sorted_anchors"] = anchors;
                    return ρσ_d;
                }).call(this);
                set_toc_anchor_map(current_map);
            }
            return current_map;
        };
        if (!current_toc_anchor_map.__argnames__) Object.defineProperties(current_toc_anchor_map, {
            __argnames__ : {value: ["tam", "anchor_funcs"]}
        });

        function update_visible_toc_anchors(toc_anchor_map, anchor_funcs) {
            var tam, before, after, visible_anchors, has_visible, pos, visibility, anchor_id;
            tam = current_toc_anchor_map(toc_anchor_map, anchor_funcs);
            before = after = null;
            visible_anchors = Object.create(null);
            has_visible = false;
            var ρσ_Iter5 = ρσ_Iterable(tam.sorted_anchors);
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                anchor_id = ρσ_Iter5[ρσ_Index5];
                pos = (ρσ_expr_temp = tam.pos_map)[(typeof anchor_id === "number" && anchor_id < 0) ? ρσ_expr_temp.length + anchor_id : anchor_id];
                visibility = anchor_funcs.visibility(pos);
                if (visibility < 0) {
                    before = anchor_id;
                } else if (visibility === 0) {
                    has_visible = true;
                    visible_anchors[(typeof anchor_id === "number" && anchor_id < 0) ? visible_anchors.length + anchor_id : anchor_id] = true;
                } else if (visibility > 0) {
                    after = anchor_id;
                    break;
                }
            }
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["visible_anchors"] = visible_anchors;
                ρσ_d["has_visible"] = has_visible;
                ρσ_d["before"] = before;
                ρσ_d["after"] = after;
                ρσ_d["sorted_anchors"] = tam.sorted_anchors;
                return ρσ_d;
            }).call(this);
        };
        if (!update_visible_toc_anchors.__argnames__) Object.defineProperties(update_visible_toc_anchors, {
            __argnames__ : {value: ["toc_anchor_map", "anchor_funcs"]}
        });

        ρσ_modules["read_book.toc"].update_visible_toc_nodes = update_visible_toc_nodes;
        ρσ_modules["read_book.toc"].iter_toc_descendants = iter_toc_descendants;
        ρσ_modules["read_book.toc"].get_border_nodes = get_border_nodes;
        ρσ_modules["read_book.toc"].get_current_toc_nodes = get_current_toc_nodes;
        ρσ_modules["read_book.toc"].get_highlighted_toc_nodes = get_highlighted_toc_nodes;
        ρσ_modules["read_book.toc"].get_toc_maps = get_toc_maps;
        ρσ_modules["read_book.toc"].create_toc_tree = create_toc_tree;
        ρσ_modules["read_book.toc"].do_search = do_search;
        ρσ_modules["read_book.toc"].create_toc_panel = create_toc_panel;
        ρσ_modules["read_book.toc"].current_toc_anchor_map = current_toc_anchor_map;
        ρσ_modules["read_book.toc"].update_visible_toc_anchors = update_visible_toc_anchors;
    })();

    (function(){
        var __name__ = "read_book.touch";
        var HOLD_THRESHOLD, TAP_THRESHOLD, TAP_LINK_THRESHOLD, PINCH_THRESHOLD, LONG_TAP_THRESHOLD, gesture_id, main_touch_handler, left_margin_handler, right_margin_handler;
        var get_boss = ρσ_modules["read_book.globals"].get_boss;
        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var scroll_viewport = ρσ_modules["read_book.viewport"].scroll_viewport;

        HOLD_THRESHOLD = 750;
        TAP_THRESHOLD = 7;
        TAP_LINK_THRESHOLD = 5;
        PINCH_THRESHOLD = 10;
        LONG_TAP_THRESHOLD = 500;
        gesture_id = 0;
        function touch_id(touch) {
            return touch.identifier + "";
        };
        if (!touch_id.__argnames__) Object.defineProperties(touch_id, {
            __argnames__ : {value: ["touch"]}
        });

        function copy_touch(t) {
            var now;
            now = window.performance.now();
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["identifier"] = touch_id(t);
                ρσ_d["page_x"] = [t.pageX];
                ρσ_d["page_y"] = [t.pageY];
                ρσ_d["viewport_x"] = [t.clientX];
                ρσ_d["viewport_y"] = [t.clientY];
                ρσ_d["active"] = true;
                ρσ_d["mtimes"] = [now];
                ρσ_d["ctime"] = now;
                ρσ_d["is_held"] = false;
                ρσ_d["x_velocity"] = 0;
                ρσ_d["y_velocity"] = 0;
                return ρσ_d;
            }).call(this);
        };
        if (!copy_touch.__argnames__) Object.defineProperties(copy_touch, {
            __argnames__ : {value: ["t"]}
        });

        function max_displacement(points) {
            var ans, first, delta, p;
            ans = 0;
            first = points[0];
            if (!(typeof first !== "undefined" && first !== null)) {
                return ans;
            }
            var ρσ_Iter0 = ρσ_Iterable(points);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                p = ρσ_Iter0[ρσ_Index0];
                delta = abs(p - first);
                if (delta > ans) {
                    ans = delta;
                }
            }
            return ans;
        };
        if (!max_displacement.__argnames__) Object.defineProperties(max_displacement, {
            __argnames__ : {value: ["points"]}
        });

        function interpret_single_gesture(touch, gesture_id) {
            var max_x_displacement, max_y_displacement, ans, delta_x, delta_y, pts, positive;
            max_x_displacement = max_displacement(touch.viewport_x);
            max_y_displacement = max_displacement(touch.viewport_y);
            ans = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["active"] = touch.active;
                ρσ_d["is_held"] = touch.is_held;
                ρσ_d["id"] = gesture_id;
                ρσ_d["start_time"] = touch.ctime;
                return ρσ_d;
            }).call(this);
            if (max(max_x_displacement, max_y_displacement) < TAP_THRESHOLD) {
                ans.type = "tap";
                ans.viewport_x = touch.viewport_x[0];
                ans.viewport_y = touch.viewport_y[0];
                return ans;
            }
            if (touch.viewport_y.length < 2) {
                return ans;
            }
            delta_x = abs((ρσ_expr_temp = touch.viewport_x)[ρσ_expr_temp.length-1] - touch.viewport_x[0]);
            delta_y = abs((ρσ_expr_temp = touch.viewport_y)[ρσ_expr_temp.length-1] - touch.viewport_y[0]);
            if (max(delta_y, delta_x) > TAP_THRESHOLD && min(delta_x, delta_y) / max(delta_y, delta_x) < .35) {
                ans.type = "swipe";
                ans.axis = (delta_y > delta_x) ? "vertical" : "horizontal";
                ans.points = pts = (ans.axis === "vertical") ? touch.viewport_y : touch.viewport_x;
                ans.times = touch.mtimes;
                positive = pts[pts.length-1] > pts[0];
                if (ans.axis === "vertical") {
                    ans.direction = (positive) ? "down" : "up";
                    ans.velocity = touch.y_velocity;
                } else {
                    ans.direction = (positive) ? "right" : "left";
                    ans.velocity = touch.x_velocity;
                }
                return ans;
            }
            return ans;
        };
        if (!interpret_single_gesture.__argnames__) Object.defineProperties(interpret_single_gesture, {
            __argnames__ : {value: ["touch", "gesture_id"]}
        });

        function interpret_double_gesture(touch1, touch2, gesture_id) {
            var ans, max_x_displacement1, max_x_displacement2, max_y_displacement1, max_y_displacement2, initial_distance, final_distance, distance;
            ans = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["active"] = touch1.active || touch2.active;
                ρσ_d["is_held"] = touch1.is_held || touch2.is_held;
                ρσ_d["id"] = gesture_id;
                return ρσ_d;
            }).call(this);
            max_x_displacement1 = max_displacement(touch1.viewport_x);
            max_x_displacement2 = max_displacement(touch2.viewport_x);
            max_y_displacement1 = max_displacement(touch1.viewport_y);
            max_y_displacement2 = max_displacement(touch2.viewport_y);
            if (max(max_x_displacement1, max_y_displacement1) < TAP_THRESHOLD && max(max_x_displacement2, max_y_displacement2) < TAP_THRESHOLD) {
                ans.type = "double-tap";
                ans.viewport_x1 = touch1.viewport_x[0];
                ans.viewport_y1 = touch1.viewport_y[0];
                ans.viewport_x2 = touch2.viewport_x[0];
                ans.viewport_y2 = touch2.viewport_y[0];
                return ans;
            }
            initial_distance = Math.sqrt(Math.pow((touch1.viewport_x[0] - touch2.viewport_x[0]), 2) + Math.pow((touch1.viewport_y[0] - touch2.viewport_y[0]), 2));
            final_distance = Math.sqrt(Math.pow(((ρσ_expr_temp = touch1.viewport_x)[ρσ_expr_temp.length-1] - (ρσ_expr_temp = touch2.viewport_x)[ρσ_expr_temp.length-1]), 2) + Math.pow(((ρσ_expr_temp = touch1.viewport_y)[ρσ_expr_temp.length-1] - (ρσ_expr_temp = touch2.viewport_y)[ρσ_expr_temp.length-1]), 2));
            distance = abs(final_distance - initial_distance);
            if (distance > PINCH_THRESHOLD) {
                ans.type = "pinch";
                ans.direction = (final_distance < initial_distance) ? "in" : "out";
                ans.distance = distance;
                return ans;
            }
            return ans;
        };
        if (!interpret_double_gesture.__argnames__) Object.defineProperties(interpret_double_gesture, {
            __argnames__ : {value: ["touch1", "touch2", "gesture_id"]}
        });

        function element_from_point(x, y) {
            return document.elementFromPoint(x, y);
        };
        if (!element_from_point.__argnames__) Object.defineProperties(element_from_point, {
            __argnames__ : {value: ["x", "y"]}
        });

        function find_link(x, y) {
            var p;
            p = element_from_point(x, y);
            while (p) {
                if (p.tagName && p.tagName.toLowerCase() === "a" && p.hasAttribute("href")) {
                    return p;
                }
                p = p.parentNode;
            }
        };
        if (!find_link.__argnames__) Object.defineProperties(find_link, {
            __argnames__ : {value: ["x", "y"]}
        });

        function tap_on_link(gesture) {
            var x, y, link, delta_y, delta_x;
            var ρσ_Iter1 = ρσ_Iterable(ρσ_list_decorate([ 0, TAP_LINK_THRESHOLD, -TAP_LINK_THRESHOLD ]));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                delta_x = ρσ_Iter1[ρσ_Index1];
                var ρσ_Iter2 = ρσ_Iterable(ρσ_list_decorate([ 0, TAP_LINK_THRESHOLD, -TAP_LINK_THRESHOLD ]));
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    delta_y = ρσ_Iter2[ρσ_Index2];
                    x = gesture.viewport_x + delta_x;
                    y = gesture.viewport_y + delta_y;
                    link = find_link(x, y);
                    if (link) {
                        link.click();
                        return true;
                    }
                }
            }
            return false;
        };
        if (!tap_on_link.__argnames__) Object.defineProperties(tap_on_link, {
            __argnames__ : {value: ["gesture"]}
        });

        function TouchHandler() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            TouchHandler.prototype.__bind_methods__.call(this);
            TouchHandler.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(TouchHandler.prototype, "__bind_methods__", {value: function () {
            this.prune_expired_touches = TouchHandler.prototype.prune_expired_touches.bind(this);
            this.start_hold_timer = TouchHandler.prototype.start_hold_timer.bind(this);
            this.stop_hold_timer = TouchHandler.prototype.stop_hold_timer.bind(this);
            this.check_for_hold = TouchHandler.prototype.check_for_hold.bind(this);
            this.handle_touchstart = TouchHandler.prototype.handle_touchstart.bind(this);
            this.update_touch = TouchHandler.prototype.update_touch.bind(this);
            this.handle_touchmove = TouchHandler.prototype.handle_touchmove.bind(this);
            this.handle_touchend = TouchHandler.prototype.handle_touchend.bind(this);
            this.handle_touchcancel = TouchHandler.prototype.handle_touchcancel.bind(this);
            this.dispatch_gesture = TouchHandler.prototype.dispatch_gesture.bind(this);
        }});
        Object.defineProperties(TouchHandler.prototype,  {
            "has_active_touches": {
                "enumerable": true, 
                "get": function has_active_touches() {
                    var self = this;
                    var t, tid;
                    var ρσ_Iter3 = ρσ_Iterable(self.ongoing_touches);
                    for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                        tid = ρσ_Iter3[ρσ_Index3];
                        t = (ρσ_expr_temp = self.ongoing_touches)[(typeof tid === "number" && tid < 0) ? ρσ_expr_temp.length + tid : tid];
                        if (t.active) {
                            return true;
                        }
                    }
                    return false;
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        TouchHandler.prototype.__init__ = function __init__() {
            var self = this;
            self.ongoing_touches = Object.create(null);
            self.gesture_id = null;
            self.hold_timer = null;
            self.handled_tap_hold = false;
        };
        TouchHandler.__argnames__ = TouchHandler.prototype.__init__.__argnames__;
        TouchHandler.__handles_kwarg_interpolation__ = TouchHandler.prototype.__init__.__handles_kwarg_interpolation__;
        TouchHandler.prototype.prune_expired_touches = function prune_expired_touches() {
            var self = this;
            var now, expired, t, tid;
            now = window.performance.now();
            expired = [];
            var ρσ_Iter4 = ρσ_Iterable(self.ongoing_touches);
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                tid = ρσ_Iter4[ρσ_Index4];
                t = (ρσ_expr_temp = self.ongoing_touches)[(typeof tid === "number" && tid < 0) ? ρσ_expr_temp.length + tid : tid];
                if (t.active) {
                    if (now - (ρσ_expr_temp = t.mtimes)[ρσ_expr_temp.length-1] > 3e3) {
                        expired.push(touch_id(t));
                    }
                }
            }
            var ρσ_Iter5 = ρσ_Iterable(expired);
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                tid = ρσ_Iter5[ρσ_Index5];
                delete self.ongoing_touches[tid];
            }
        };
        TouchHandler.prototype.start_hold_timer = function start_hold_timer() {
            var self = this;
            self.stop_hold_timer();
            self.hold_timer = window.setTimeout(self.check_for_hold, 100);
        };
        TouchHandler.prototype.stop_hold_timer = function stop_hold_timer() {
            var self = this;
            if (self.hold_timer !== null) {
                window.clearTimeout(self.hold_timer);
                self.hold_timer = null;
            }
        };
        TouchHandler.prototype.check_for_hold = function check_for_hold() {
            var self = this;
            var now, found_hold, touch, touchid;
            if (len(self.ongoing_touches) > 0) {
                now = window.performance.now();
                found_hold = false;
                var ρσ_Iter6 = ρσ_Iterable(self.ongoing_touches);
                for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                    touchid = ρσ_Iter6[ρσ_Index6];
                    touch = (ρσ_expr_temp = self.ongoing_touches)[(typeof touchid === "number" && touchid < 0) ? ρσ_expr_temp.length + touchid : touchid];
                    if (touch.active && now - (ρσ_expr_temp = touch.mtimes)[ρσ_expr_temp.length-1] > HOLD_THRESHOLD) {
                        touch.is_held = true;
                        found_hold = true;
                    }
                }
                if (found_hold) {
                    self.dispatch_gesture();
                }
                self.start_hold_timer();
            }
        };
        TouchHandler.prototype.handle_touchstart = function handle_touchstart(ev) {
            var self = this;
            var touch;
            [ev.preventDefault(), ev.stopPropagation()];
            self.prune_expired_touches();
            var ρσ_Iter7 = ρσ_Iterable(ev.changedTouches);
            for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                touch = ρσ_Iter7[ρσ_Index7];
                (ρσ_expr_temp = self.ongoing_touches)[ρσ_bound_index(touch_id(touch), ρσ_expr_temp)] = copy_touch(touch);
                if (self.gesture_id === null) {
                    gesture_id += 1;
                    self.gesture_id = gesture_id;
                    self.handled_tap_hold = false;
                }
            }
            if (len(self.ongoing_touches) > 0) {
                self.start_hold_timer();
            }
        };
        if (!TouchHandler.prototype.handle_touchstart.__argnames__) Object.defineProperties(TouchHandler.prototype.handle_touchstart, {
            __argnames__ : {value: ["ev"]}
        });
        TouchHandler.prototype.update_touch = function update_touch(t, touch) {
            var self = this;
            var now;
            now = window.performance.now();
            t.mtimes.push(now);
            [t.page_x.push(touch.pageX), t.page_y.push(touch.pageY)];
            [t.viewport_x.push(touch.clientX), t.viewport_y.push(touch.clientY)];
        };
        if (!TouchHandler.prototype.update_touch.__argnames__) Object.defineProperties(TouchHandler.prototype.update_touch, {
            __argnames__ : {value: ["t", "touch"]}
        });
        TouchHandler.prototype.handle_touchmove = function handle_touchmove(ev) {
            var self = this;
            var t, touch;
            [ev.preventDefault(), ev.stopPropagation()];
            var ρσ_Iter8 = ρσ_Iterable(ev.changedTouches);
            for (var ρσ_Index8 = 0; ρσ_Index8 < ρσ_Iter8.length; ρσ_Index8++) {
                touch = ρσ_Iter8[ρσ_Index8];
                t = (ρσ_expr_temp = self.ongoing_touches)[ρσ_bound_index(touch_id(touch), ρσ_expr_temp)];
                if (t) {
                    self.update_touch(t, touch);
                    self.dispatch_gesture();
                }
            }
        };
        if (!TouchHandler.prototype.handle_touchmove.__argnames__) Object.defineProperties(TouchHandler.prototype.handle_touchmove, {
            __argnames__ : {value: ["ev"]}
        });
        TouchHandler.prototype.handle_touchend = function handle_touchend(ev) {
            var self = this;
            var t, touch;
            [ev.preventDefault(), ev.stopPropagation()];
            var ρσ_Iter9 = ρσ_Iterable(ev.changedTouches);
            for (var ρσ_Index9 = 0; ρσ_Index9 < ρσ_Iter9.length; ρσ_Index9++) {
                touch = ρσ_Iter9[ρσ_Index9];
                t = (ρσ_expr_temp = self.ongoing_touches)[ρσ_bound_index(touch_id(touch), ρσ_expr_temp)];
                if (t) {
                    t.active = false;
                    self.update_touch(t, touch);
                }
            }
            self.prune_expired_touches();
            if (!self.has_active_touches) {
                self.dispatch_gesture();
                self.ongoing_touches = Object.create(null);
                self.gesture_id = null;
                self.handled_tap_hold = false;
            }
        };
        if (!TouchHandler.prototype.handle_touchend.__argnames__) Object.defineProperties(TouchHandler.prototype.handle_touchend, {
            __argnames__ : {value: ["ev"]}
        });
        TouchHandler.prototype.handle_touchcancel = function handle_touchcancel(ev) {
            var self = this;
            var tid, touch;
            [ev.preventDefault(), ev.stopPropagation()];
            var ρσ_Iter10 = ρσ_Iterable(ev.changedTouches);
            for (var ρσ_Index10 = 0; ρσ_Index10 < ρσ_Iter10.length; ρσ_Index10++) {
                touch = ρσ_Iter10[ρσ_Index10];
                tid = touch_id(touch);
                delete self.ongoing_touches[tid];
            }
            self.gesture_id = null;
            self.handled_tap_hold = false;
        };
        if (!TouchHandler.prototype.handle_touchcancel.__argnames__) Object.defineProperties(TouchHandler.prototype.handle_touchcancel, {
            __argnames__ : {value: ["ev"]}
        });
        TouchHandler.prototype.dispatch_gesture = function dispatch_gesture() {
            var self = this;
            var touches, num, gesture, t;
            touches = self.ongoing_touches;
            num = len(touches);
            gesture = Object.create(null);
            if (num === 1) {
                gesture = interpret_single_gesture(touches[ρσ_bound_index(Object.keys(touches)[0], touches)], self.gesture_id);
            } else if (num === 2) {
                t = Object.keys(touches);
                gesture = interpret_double_gesture(touches[ρσ_bound_index(t[0], touches)], touches[ρσ_bound_index(t[1], touches)], self.gesture_id);
            }
            if (!(typeof gesture !== "undefined" && gesture !== null ? gesture : Object.create(null)).type) {
                return;
            }
            self.handle_gesture(gesture);
        };
        TouchHandler.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        TouchHandler.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(TouchHandler.prototype, "__bases__", {value: []});
        

        function BookTouchHandler() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            BookTouchHandler.prototype.__bind_methods__.call(this);
            BookTouchHandler.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(BookTouchHandler, TouchHandler);
        Object.defineProperty(BookTouchHandler.prototype, "__bind_methods__", {value: function () {
            TouchHandler.prototype.__bind_methods__ && TouchHandler.prototype.__bind_methods__.call(this);
            this.handle_gesture = BookTouchHandler.prototype.handle_gesture.bind(this);
            this.__repr__ = BookTouchHandler.prototype.__repr__.bind(this);
        }});
        BookTouchHandler.prototype.__init__ = function __init__() {
            var self = this;
            var for_side_margin = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? __init__.__defaults__.for_side_margin : arguments[0];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "for_side_margin")){
                for_side_margin = ρσ_kwargs_obj.for_side_margin;
            }
            self.for_side_margin = for_side_margin;
            TouchHandler.prototype.__init__.call(self);
        };
        if (!BookTouchHandler.prototype.__init__.__defaults__) Object.defineProperties(BookTouchHandler.prototype.__init__, {
            __defaults__ : {value: {for_side_margin:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["for_side_margin"]}
        });
        BookTouchHandler.__argnames__ = BookTouchHandler.prototype.__init__.__argnames__;
        BookTouchHandler.__handles_kwarg_interpolation__ = BookTouchHandler.prototype.__init__.__handles_kwarg_interpolation__;
        BookTouchHandler.prototype.handle_gesture = function handle_gesture(gesture) {
            var self = this;
            gesture.from_side_margin = self.for_side_margin;
            if (gesture.type === "tap") {
                if (gesture.is_held) {
                    if (!self.for_side_margin && !self.handled_tap_hold && window.performance.now() - gesture.start_time >= LONG_TAP_THRESHOLD) {
                        self.handled_tap_hold = true;
                        gesture.type = "long-tap";
                        get_boss().handle_gesture(gesture);
                    }
                    return;
                }
                if (!gesture.active) {
                    if (self.for_side_margin || !tap_on_link(gesture)) {
                        if (gesture.viewport_y < min(100, scroll_viewport.height() / 4)) {
                            gesture.type = "show-chrome";
                        } else {
                            if (gesture.viewport_x < min(100, scroll_viewport.width() / 4)) {
                                gesture.type = "prev-page";
                            } else {
                                gesture.type = "next-page";
                            }
                        }
                    }
                }
            }
            if (gesture.type === "pinch") {
                if (gesture.active) {
                    return;
                }
            }
            if (gesture.type === "double-tap") {
                if (gesture.active) {
                    return;
                }
                gesture.type = "show-chrome";
            }
            if (self.for_side_margin) {
                ui_operations.forward_gesture(gesture);
            } else {
                get_boss().handle_gesture(gesture);
            }
        };
        if (!BookTouchHandler.prototype.handle_gesture.__argnames__) Object.defineProperties(BookTouchHandler.prototype.handle_gesture, {
            __argnames__ : {value: ["gesture"]}
        });
        BookTouchHandler.prototype.__repr__ = function __repr__() {
            var self = this;
            return "BookTouchHandler:for_side_margin:" + self.for_side_margin;
        };
        BookTouchHandler.prototype.__str__ = function __str__ () {
            if(TouchHandler.prototype.__str__) return TouchHandler.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(BookTouchHandler.prototype, "__bases__", {value: [TouchHandler]});

        main_touch_handler = new BookTouchHandler;
        left_margin_handler = new BookTouchHandler("left");
        right_margin_handler = new BookTouchHandler("right");
        function install_handlers(elem, handler) {
            var options;
            options = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["capture"] = true;
                ρσ_d["passive"] = false;
                return ρσ_d;
            }).call(this);
            elem.addEventListener("touchstart", handler.handle_touchstart, options);
            elem.addEventListener("touchmove", handler.handle_touchmove, options);
            elem.addEventListener("touchend", handler.handle_touchend, options);
            elem.addEventListener("touchcancel", handler.handle_touchcancel, options);
        };
        if (!install_handlers.__argnames__) Object.defineProperties(install_handlers, {
            __argnames__ : {value: ["elem", "handler"]}
        });

        function create_handlers() {
            install_handlers(document, main_touch_handler);
        };

        function set_left_margin_handler(elem) {
            install_handlers(elem, left_margin_handler);
        };
        if (!set_left_margin_handler.__argnames__) Object.defineProperties(set_left_margin_handler, {
            __argnames__ : {value: ["elem"]}
        });

        function set_right_margin_handler(elem) {
            install_handlers(elem, right_margin_handler);
        };
        if (!set_right_margin_handler.__argnames__) Object.defineProperties(set_right_margin_handler, {
            __argnames__ : {value: ["elem"]}
        });

        ρσ_modules["read_book.touch"].HOLD_THRESHOLD = HOLD_THRESHOLD;
        ρσ_modules["read_book.touch"].TAP_THRESHOLD = TAP_THRESHOLD;
        ρσ_modules["read_book.touch"].TAP_LINK_THRESHOLD = TAP_LINK_THRESHOLD;
        ρσ_modules["read_book.touch"].PINCH_THRESHOLD = PINCH_THRESHOLD;
        ρσ_modules["read_book.touch"].LONG_TAP_THRESHOLD = LONG_TAP_THRESHOLD;
        ρσ_modules["read_book.touch"].gesture_id = gesture_id;
        ρσ_modules["read_book.touch"].main_touch_handler = main_touch_handler;
        ρσ_modules["read_book.touch"].left_margin_handler = left_margin_handler;
        ρσ_modules["read_book.touch"].right_margin_handler = right_margin_handler;
        ρσ_modules["read_book.touch"].touch_id = touch_id;
        ρσ_modules["read_book.touch"].copy_touch = copy_touch;
        ρσ_modules["read_book.touch"].max_displacement = max_displacement;
        ρσ_modules["read_book.touch"].interpret_single_gesture = interpret_single_gesture;
        ρσ_modules["read_book.touch"].interpret_double_gesture = interpret_double_gesture;
        ρσ_modules["read_book.touch"].element_from_point = element_from_point;
        ρσ_modules["read_book.touch"].find_link = find_link;
        ρσ_modules["read_book.touch"].tap_on_link = tap_on_link;
        ρσ_modules["read_book.touch"].TouchHandler = TouchHandler;
        ρσ_modules["read_book.touch"].BookTouchHandler = BookTouchHandler;
        ρσ_modules["read_book.touch"].install_handlers = install_handlers;
        ρσ_modules["read_book.touch"].create_handlers = create_handlers;
        ρσ_modules["read_book.touch"].set_left_margin_handler = set_left_margin_handler;
        ρσ_modules["read_book.touch"].set_right_margin_handler = set_right_margin_handler;
    })();

    (function(){
        var __name__ = "read_book.iframe";
        var FORCE_FLOW_MODE, CALIBRE_VERSION, ERS_SUPPORTED_FEATURES;
        var traceback = ρσ_modules.traceback;

        var _ = ρσ_modules.gettext.gettext;

        var IframeClient = ρσ_modules.iframe_comm.IframeClient;

        var at_current = ρσ_modules["read_book.cfi"].at_current;
        var scroll_to_cfi = ρσ_modules["read_book.cfi"].scroll_to;

        var get_elements = ρσ_modules["read_book.extract"].get_elements;

        var flow_anchor_funcs = ρσ_modules["read_book.flow_mode"].anchor_funcs;
        var flow_onwheel = ρσ_modules["read_book.flow_mode"].flow_onwheel;
        var flow_to_scroll_fraction = ρσ_modules["read_book.flow_mode"].flow_to_scroll_fraction;
        var flow_handle_gesture = ρσ_modules["read_book.flow_mode"].handle_gesture;
        var flow_handle_shortcut = ρσ_modules["read_book.flow_mode"].handle_shortcut;
        var flow_layout = ρσ_modules["read_book.flow_mode"].layout;
        var flow_scroll_by_page = ρσ_modules["read_book.flow_mode"].scroll_by_page;

        var is_footnote_link = ρσ_modules["read_book.footnotes"].is_footnote_link;

        var current_book = ρσ_modules["read_book.globals"].current_book;
        var current_layout_mode = ρσ_modules["read_book.globals"].current_layout_mode;
        var current_spine_item = ρσ_modules["read_book.globals"].current_spine_item;
        var runtime = ρσ_modules["read_book.globals"].runtime;
        var set_boss = ρσ_modules["read_book.globals"].set_boss;
        var set_current_spine_item = ρσ_modules["read_book.globals"].set_current_spine_item;
        var set_layout_mode = ρσ_modules["read_book.globals"].set_layout_mode;

        var apply_mathjax = ρσ_modules["read_book.mathjax"].apply_mathjax;

        var paged_anchor_funcs = ρσ_modules["read_book.paged_mode"].anchor_funcs;
        var calc_columns_per_screen = ρσ_modules["read_book.paged_mode"].calc_columns_per_screen;
        var paged_handle_gesture = ρσ_modules["read_book.paged_mode"].handle_gesture;
        var paged_handle_shortcut = ρσ_modules["read_book.paged_mode"].handle_shortcut;
        var paged_jump_to_cfi = ρσ_modules["read_book.paged_mode"].jump_to_cfi;
        var paged_layout = ρσ_modules["read_book.paged_mode"].layout;
        var paged_onwheel = ρσ_modules["read_book.paged_mode"].onwheel;
        var progress_frac = ρσ_modules["read_book.paged_mode"].progress_frac;
        var reset_paged_mode_globals = ρσ_modules["read_book.paged_mode"].reset_paged_mode_globals;
        var paged_scroll_by_page = ρσ_modules["read_book.paged_mode"].scroll_by_page;
        var scroll_to_elem = ρσ_modules["read_book.paged_mode"].scroll_to_elem;
        var paged_scroll_to_fraction = ρσ_modules["read_book.paged_mode"].scroll_to_fraction;
        var snap_to_selection = ρσ_modules["read_book.paged_mode"].snap_to_selection;

        var finalize_resources = ρσ_modules["read_book.resources"].finalize_resources;
        var unserialize_html = ρσ_modules["read_book.resources"].unserialize_html;

        var apply_colors = ρσ_modules["read_book.settings"].apply_colors;
        var apply_font_size = ρσ_modules["read_book.settings"].apply_font_size;
        var apply_settings = ρσ_modules["read_book.settings"].apply_settings;
        var apply_stylesheet = ρσ_modules["read_book.settings"].apply_stylesheet;
        var opts = ρσ_modules["read_book.settings"].opts;
        var update_settings = ρσ_modules["read_book.settings"].update_settings;

        var create_shortcut_map = ρσ_modules["read_book.shortcuts"].create_shortcut_map;
        var keyevent_as_shortcut = ρσ_modules["read_book.shortcuts"].keyevent_as_shortcut;
        var shortcut_for_key_event = ρσ_modules["read_book.shortcuts"].shortcut_for_key_event;

        var update_visible_toc_anchors = ρσ_modules["read_book.toc"].update_visible_toc_anchors;

        var create_touch_handlers = ρσ_modules["read_book.touch"].create_handlers;

        var scroll_viewport = ρσ_modules["read_book.viewport"].scroll_viewport;

        var debounce = ρσ_modules.utils.debounce;
        var html_escape = ρσ_modules.utils.html_escape;
        var is_ios = ρσ_modules.utils.is_ios;

        FORCE_FLOW_MODE = false;
        CALIBRE_VERSION = "__CALIBRE_VERSION__";
        ERS_SUPPORTED_FEATURES = (function(){
            var s = ρσ_set();
            s.jsset.add("dom-manipulation");
            s.jsset.add("layout-changes");
            s.jsset.add("touch-events");
            s.jsset.add("mouse-events");
            s.jsset.add("keyboard-events");
            s.jsset.add("spine-scripting");
            return s;
        })();
        function EPUBReadingSystem() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            EPUBReadingSystem.prototype.__bind_methods__.call(this);
            EPUBReadingSystem.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(EPUBReadingSystem.prototype, "__bind_methods__", {value: function () {
            this.hasFeature = EPUBReadingSystem.prototype.hasFeature.bind(this);
            this.__repr__ = EPUBReadingSystem.prototype.__repr__.bind(this);
            this.__str__ = EPUBReadingSystem.prototype.__str__.bind(this);
        }});
        Object.defineProperties(EPUBReadingSystem.prototype,  {
            "name": {
                "enumerable": true, 
                "get": function name() {
                    var self = this;
                    return "calibre";
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "version": {
                "enumerable": true, 
                "get": function version() {
                    var self = this;
                    return CALIBRE_VERSION;
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "layoutStyle": {
                "enumerable": true, 
                "get": function layoutStyle() {
                    var self = this;
                    return (current_layout_mode() === "flow") ? "scrolling" : "paginated";
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        EPUBReadingSystem.prototype.__init__ = function __init__ () {
                    };
        EPUBReadingSystem.prototype.hasFeature = function hasFeature(feature, version) {
            var self = this;
            return ρσ_in(feature, ERS_SUPPORTED_FEATURES);
        };
        if (!EPUBReadingSystem.prototype.hasFeature.__argnames__) Object.defineProperties(EPUBReadingSystem.prototype.hasFeature, {
            __argnames__ : {value: ["feature", "version"]}
        });
        EPUBReadingSystem.prototype.__repr__ = function __repr__() {
            var self = this;
            return "{name:" + ρσ_str.format("{}", self.name) + ", version:" + ρσ_str.format("{}", self.version) + ", layoutStyle:" + ρσ_str.format("{}", self.layoutStyle) + "}";
        };
        EPUBReadingSystem.prototype.__str__ = function __str__() {
            var self = this;
            return self.__repr__();
        };
        Object.defineProperty(EPUBReadingSystem.prototype, "__bases__", {value: []});
        
        
        

        function IframeBoss() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            IframeBoss.prototype.__bind_methods__.call(this);
            IframeBoss.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(IframeBoss.prototype, "__bind_methods__", {value: function () {
            this.set_forward_keypresses = IframeBoss.prototype.set_forward_keypresses.bind(this);
            this.initialize = IframeBoss.prototype.initialize.bind(this);
            this.onerror = IframeBoss.prototype.onerror.bind(this);
            this.display = IframeBoss.prototype.display.bind(this);
            this.on_scroll_to_frac = IframeBoss.prototype.on_scroll_to_frac.bind(this);
            this.handle_gesture = IframeBoss.prototype.handle_gesture.bind(this);
            this.gesture_from_margin = IframeBoss.prototype.gesture_from_margin.bind(this);
            this.report_human_scroll = IframeBoss.prototype.report_human_scroll.bind(this);
            this.on_scroll_to_anchor = IframeBoss.prototype.on_scroll_to_anchor.bind(this);
            this.on_next_screen = IframeBoss.prototype.on_next_screen.bind(this);
            this.change_font_size = IframeBoss.prototype.change_font_size.bind(this);
            this.change_stylesheet = IframeBoss.prototype.change_stylesheet.bind(this);
            this.change_color_scheme = IframeBoss.prototype.change_color_scheme.bind(this);
            this.fix_fullscreen_svg_images = IframeBoss.prototype.fix_fullscreen_svg_images.bind(this);
            this.content_loaded = IframeBoss.prototype.content_loaded.bind(this);
            this.content_loaded_stage2 = IframeBoss.prototype.content_loaded_stage2.bind(this);
            this.calculate_progress_frac = IframeBoss.prototype.calculate_progress_frac.bind(this);
            this.get_current_cfi = IframeBoss.prototype.get_current_cfi.bind(this);
            this.update_cfi = IframeBoss.prototype.update_cfi.bind(this);
            this.update_toc_position = IframeBoss.prototype.update_toc_position.bind(this);
            this.onscroll = IframeBoss.prototype.onscroll.bind(this);
            this.no_latency_onscroll = IframeBoss.prototype.no_latency_onscroll.bind(this);
            this.onresize = IframeBoss.prototype.onresize.bind(this);
            this.onselectionchange = IframeBoss.prototype.onselectionchange.bind(this);
            this.onresize_stage2 = IframeBoss.prototype.onresize_stage2.bind(this);
            this.received_window_size = IframeBoss.prototype.received_window_size.bind(this);
            this.onwheel = IframeBoss.prototype.onwheel.bind(this);
            this.onkeydown = IframeBoss.prototype.onkeydown.bind(this);
            this.oncontextmenu = IframeBoss.prototype.oncontextmenu.bind(this);
            this.send_message = IframeBoss.prototype.send_message.bind(this);
            this.connect_links = IframeBoss.prototype.connect_links.bind(this);
            this.link_activated = IframeBoss.prototype.link_activated.bind(this);
            this.scroll_to_anchor = IframeBoss.prototype.scroll_to_anchor.bind(this);
            this.find = IframeBoss.prototype.find.bind(this);
        }});
        IframeBoss.prototype.__init__ = function __init__() {
            var self = this;
            var handlers;
            window.navigator.epubReadingSystem = new EPUBReadingSystem;
            self.last_cfi = null;
            self.replace_history_on_next_cfi_update = true;
            self.blob_url_map = Object.create(null);
            self.resource_urls = Object.create(null);
            self.content_ready = false;
            self.last_window_width = self.last_window_height = -1;
            self.forward_keypresses = false;
            set_boss(self);
            handlers = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["initialize"] = self.initialize;
                ρσ_d["display"] = self.display;
                ρσ_d["scroll_to_anchor"] = self.on_scroll_to_anchor;
                ρσ_d["scroll_to_frac"] = self.on_scroll_to_frac;
                ρσ_d["next_screen"] = self.on_next_screen;
                ρσ_d["change_font_size"] = self.change_font_size;
                ρσ_d["change_color_scheme"] = self.change_color_scheme;
                ρσ_d["gesture_from_margin"] = self.gesture_from_margin;
                ρσ_d["find"] = self.find;
                ρσ_d["window_size"] = self.received_window_size;
                ρσ_d["get_current_cfi"] = self.get_current_cfi;
                ρσ_d["set_forward_keypresses"] = self.set_forward_keypresses;
                return ρσ_d;
            }).call(this);
            self.comm = new IframeClient(handlers);
            self.last_window_ypos = 0;
            self.length_before = null;
        };
        IframeBoss.__argnames__ = IframeBoss.prototype.__init__.__argnames__;
        IframeBoss.__handles_kwarg_interpolation__ = IframeBoss.prototype.__init__.__handles_kwarg_interpolation__;
        IframeBoss.prototype.set_forward_keypresses = function set_forward_keypresses(data) {
            var self = this;
            self.forward_keypresses = data.forward;
        };
        if (!IframeBoss.prototype.set_forward_keypresses.__argnames__) Object.defineProperties(IframeBoss.prototype.set_forward_keypresses, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.initialize = function initialize(data) {
            var self = this;
            scroll_viewport.update_window_size(data.width, data.height);
            window.onerror = self.onerror;
            window.addEventListener("scroll", debounce(self.onscroll, 1e3));
            window.addEventListener("scroll", self.no_latency_onscroll);
            window.addEventListener("resize", debounce(self.onresize, 500));
            window.addEventListener("wheel", self.onwheel, (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["passive"] = false;
                return ρσ_d;
            }).call(this));
            window.addEventListener("keydown", self.onkeydown, (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["passive"] = false;
                return ρσ_d;
            }).call(this));
            document.documentElement.addEventListener("contextmenu", self.oncontextmenu, (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["passive"] = false;
                return ρσ_d;
            }).call(this));
            document.addEventListener("selectionchange", self.onselectionchange);
            self.color_scheme = data.color_scheme;
            create_touch_handlers();
        };
        if (!IframeBoss.prototype.initialize.__argnames__) Object.defineProperties(IframeBoss.prototype.initialize, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.onerror = function onerror(msg, script_url, line_number, column_number, error_object) {
            var self = this;
            var is_internal_error, fname, details;
            if (error_object === null) {
                console.log("Unhandled error from external javascript, ignoring: " + ρσ_str.format("{}", msg) + " " + ρσ_str.format("{}", script_url) + " " + ρσ_str.format("{}", line_number) + "");
                return;
            }
            is_internal_error = !(ρσ_expr_temp = self.resource_urls)[(typeof script_url === "number" && script_url < 0) ? ρσ_expr_temp.length + script_url : script_url];
            if (is_internal_error) {
                console.log(error_object);
                try {
                    fname = (ρσ_expr_temp = script_url.rpartition("/"))[ρσ_expr_temp.length-1] || script_url;
                    msg = msg + "<br><span style=\"font-size:smaller\">" + "Error at {}:{}:{}".format(fname, line_number, column_number || "") + "</span>";
                    details = (error_object) ? traceback.format_exception(error_object).join("") : "";
                    ρσ_interpolate_kwargs.call(self, self.send_message, ["error"].concat([ρσ_desugar_kwargs({title: _("Unhandled error"), details: details, msg: msg})]));
                    return true;
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        console.log("There was an error in the iframe unhandled exception handler");
                    } 
                }
            } else {
                (console.error || console.log)("There was an error in the JavaScript from within the book");
            }
        };
        if (!IframeBoss.prototype.onerror.__argnames__) Object.defineProperties(IframeBoss.prototype.onerror, {
            __argnames__ : {value: ["msg", "script_url", "line_number", "column_number", "error_object"]}
        });
        IframeBoss.prototype.display = function display(data) {
            var self = this;
            var spine, index, name, ρσ_unpack, root_data;
            self.length_before = null;
            self.content_ready = false;
            self.replace_history_on_next_cfi_update = true;
            self.book = current_book.book = data.book;
            self.is_titlepage = data.is_titlepage;
            spine = self.book.manifest.spine;
            index = spine.indexOf(data.name);
            reset_paged_mode_globals();
            set_layout_mode((FORCE_FLOW_MODE) ? "flow" : data.settings.read_mode);
            if (current_layout_mode() === "flow") {
                self.do_layout = flow_layout;
                self.handle_wheel = flow_onwheel;
                self.handle_navigation_shortcut = flow_handle_shortcut;
                self._handle_gesture = flow_handle_gesture;
                self.to_scroll_fraction = flow_to_scroll_fraction;
                self.jump_to_cfi = scroll_to_cfi;
                self.anchor_funcs = flow_anchor_funcs;
            } else {
                self.do_layout = paged_layout;
                self.handle_wheel = paged_onwheel;
                self.handle_navigation_shortcut = paged_handle_shortcut;
                self.to_scroll_fraction = paged_scroll_to_fraction;
                self.jump_to_cfi = paged_jump_to_cfi;
                self._handle_gesture = paged_handle_gesture;
                self.anchor_funcs = paged_anchor_funcs;
            }
            update_settings(data.settings);
            self.keyboard_shortcut_map = create_shortcut_map(data.settings.keyboard_shortcuts);
            set_current_spine_item((function(){
                var ρσ_d = Object.create(null);
                ρσ_d["name"] = data.name;
                ρσ_d["is_first"] = index === 0;
                ρσ_d["is_last"] = index === spine.length - 1;
                ρσ_d["initial_position"] = data.initial_position;
                return ρσ_d;
            }).call(this));
            self.last_cfi = null;
            var ρσ_Iter0 = ρσ_Iterable(self.blob_url_map);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                name = ρσ_Iter0[ρσ_Index0];
                window.URL.revokeObjectURL((ρσ_expr_temp = self.blob_url_map)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name]);
            }
            document.body.style.removeProperty("font-family");
            ρσ_unpack = finalize_resources(self.book, data.name, data.resource_data);
ρσ_unpack = ρσ_unpack_asarray(3, ρσ_unpack);
            root_data = ρσ_unpack[0];
            self.mathjax = ρσ_unpack[1];
            self.blob_url_map = ρσ_unpack[2];
            self.resource_urls = unserialize_html(root_data, self.content_loaded);
        };
        if (!IframeBoss.prototype.display.__argnames__) Object.defineProperties(IframeBoss.prototype.display, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.on_scroll_to_frac = function on_scroll_to_frac(data) {
            var self = this;
            self.to_scroll_fraction(data.frac);
        };
        if (!IframeBoss.prototype.on_scroll_to_frac.__argnames__) Object.defineProperties(IframeBoss.prototype.on_scroll_to_frac, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.handle_gesture = function handle_gesture(gesture) {
            var self = this;
            if (gesture.type === "show-chrome") {
                self.send_message("show_chrome");
            } else if (gesture.type === "pinch") {
                ρσ_interpolate_kwargs.call(self, self.send_message, ["bump_font_size"].concat([ρσ_desugar_kwargs({increase: gesture.direction === "out"})]));
            } else {
                self._handle_gesture(gesture);
            }
        };
        if (!IframeBoss.prototype.handle_gesture.__argnames__) Object.defineProperties(IframeBoss.prototype.handle_gesture, {
            __argnames__ : {value: ["gesture"]}
        });
        IframeBoss.prototype.gesture_from_margin = function gesture_from_margin(data) {
            var self = this;
            self.handle_gesture(data.gesture);
        };
        if (!IframeBoss.prototype.gesture_from_margin.__argnames__) Object.defineProperties(IframeBoss.prototype.gesture_from_margin, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.report_human_scroll = function report_human_scroll(scrolled_by_frac) {
            var self = this;
            ρσ_interpolate_kwargs.call(self, self.send_message, ["human_scroll"].concat([ρσ_desugar_kwargs({scrolled_by_frac: scrolled_by_frac || null})]));
        };
        if (!IframeBoss.prototype.report_human_scroll.__argnames__) Object.defineProperties(IframeBoss.prototype.report_human_scroll, {
            __argnames__ : {value: ["scrolled_by_frac"]}
        });
        IframeBoss.prototype.on_scroll_to_anchor = function on_scroll_to_anchor(data) {
            var self = this;
            var frag;
            frag = data.frag;
            if (frag) {
                self.scroll_to_anchor(frag);
            } else {
                self.to_scroll_fraction(0);
            }
        };
        if (!IframeBoss.prototype.on_scroll_to_anchor.__argnames__) Object.defineProperties(IframeBoss.prototype.on_scroll_to_anchor, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.on_next_screen = function on_next_screen(data) {
            var self = this;
            var backwards;
            backwards = data.backwards;
            if (current_layout_mode() === "flow") {
                flow_scroll_by_page(backwards);
            } else {
                paged_scroll_by_page(backwards, data.all_pages_on_screen);
            }
        };
        if (!IframeBoss.prototype.on_next_screen.__argnames__) Object.defineProperties(IframeBoss.prototype.on_next_screen, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.change_font_size = function change_font_size(data) {
            var self = this;
            if (ρσ_exists.n(data.base_font_size) && (data.base_font_size !== opts.base_font_size && (typeof data.base_font_size !== "object" || ρσ_not_equals(data.base_font_size, opts.base_font_size)))) {
                opts.base_font_size = data.base_font_size;
                apply_font_size();
            }
        };
        if (!IframeBoss.prototype.change_font_size.__argnames__) Object.defineProperties(IframeBoss.prototype.change_font_size, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.change_stylesheet = function change_stylesheet(data) {
            var self = this;
            opts.user_stylesheet = data.sheet || "";
            apply_stylesheet();
        };
        if (!IframeBoss.prototype.change_stylesheet.__argnames__) Object.defineProperties(IframeBoss.prototype.change_stylesheet, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.change_color_scheme = function change_color_scheme(data) {
            var self = this;
            if (data.color_scheme && data.color_scheme.foreground && data.color_scheme.background) {
                opts.color_scheme = data.color_scheme;
                apply_colors();
            }
        };
        if (!IframeBoss.prototype.change_color_scheme.__argnames__) Object.defineProperties(IframeBoss.prototype.change_color_scheme, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.fix_fullscreen_svg_images = function fix_fullscreen_svg_images() {
            var self = this;
            var child_names, name, node, names, svg;
            child_names = [];
            var ρσ_Iter1 = ρσ_Iterable(document.body.childNodes);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                node = ρσ_Iter1[ρσ_Index1];
                if (node.tagName) {
                    name = node.tagName.toLowerCase();
                    if (name !== "style" && name !== "script") {
                        child_names.push(name);
                    }
                    if (child_names.length > 1) {
                        break;
                    }
                }
            }
            if (child_names.length === 1 && child_names[0] === "div") {
                names = ρσ_list_decorate([]);
                svg = null;
                var ρσ_Iter2 = ρσ_Iterable(document.body.querySelectorAll("*"));
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    node = ρσ_Iter2[ρσ_Index2];
                    if (node.tagName) {
                        name = node.tagName.toLowerCase();
                        if (name !== "style" && name !== "script") {
                            names.push(name);
                            if (name === "svg") {
                                svg = node;
                            }
                        }
                    }
                }
                if (ρσ_equals(names, ρσ_list_decorate([ "div", "svg", "image" ])) || ρσ_equals(names, ρσ_list_decorate([ "svg", "image" ]))) {
                    if (svg.getAttribute("width") === "100%" && svg.getAttribute("height") === "100%") {
                        svg.setAttribute("width", "100vw");
                        svg.setAttribute("height", "100vh");
                    }
                }
            }
        };
        IframeBoss.prototype.content_loaded = function content_loaded() {
            var self = this;
            var ρσ_unpack;
            document.documentElement.style.overflow = "hidden";
            if (self.is_titlepage && !opts.cover_preserve_aspect_ratio) {
                document.body.classList.add("cover-fill");
            }
            ρσ_unpack = [scroll_viewport.width(), scroll_viewport.height()];
            self.last_window_width = ρσ_unpack[0];
            self.last_window_height = ρσ_unpack[1];
            apply_settings();
            self.fix_fullscreen_svg_images();
            self.do_layout();
            if (self.mathjax) {
                return apply_mathjax(self.mathjax, self.book.manifest.link_uid, self.content_loaded_stage2);
            }
            self.content_loaded_stage2();
        };
        IframeBoss.prototype.content_loaded_stage2 = function content_loaded_stage2() {
            var self = this;
            var csi, ipos, spine, files, current_name, spine_index, si, i;
            document.head.firstChild.textContent = "";
            self.connect_links();
            self.content_ready = true;
            csi = current_spine_item();
            if (csi.initial_position) {
                ipos = csi.initial_position;
                self.replace_history_on_next_cfi_update = ipos.replace_history || false;
                if (ipos.type === "frac") {
                    self.to_scroll_fraction(ipos.frac);
                } else if (ipos.type === "anchor") {
                    self.scroll_to_anchor(ipos.anchor);
                } else if (ipos.type === "cfi") {
                    self.jump_to_cfi(ipos.cfi);
                } else if (ipos.type === "search") {
                    self.find(ipos.search_data, true);
                }
            }
            spine = self.book.manifest.spine;
            files = self.book.manifest.files;
            current_name = current_spine_item().name;
            spine_index = spine.indexOf(current_name);
            self.length_before = 0;
            if (spine_index > -1) {
                for (var ρσ_Index3 = 0; ρσ_Index3 < spine_index; ρσ_Index3++) {
                    i = ρσ_Index3;
                    si = spine[(typeof i === "number" && i < 0) ? spine.length + i : i];
                    if (si) {
                        self.length_before += ρσ_exists.d(files[(typeof si === "number" && si < 0) ? files.length + si : si]).length || 0;
                    }
                }
            }
            self.onscroll();
            ρσ_interpolate_kwargs.call(self, self.send_message, ["content_loaded"].concat([ρσ_desugar_kwargs({progress_frac: self.calculate_progress_frac(), file_progress_frac: progress_frac()})]));
            self.last_cfi = null;
            window.setTimeout(self.update_cfi, 0);
            window.setTimeout(self.update_toc_position, 0);
        };
        IframeBoss.prototype.calculate_progress_frac = function calculate_progress_frac() {
            var self = this;
            var current_name, files, file_length, frac, ans;
            current_name = current_spine_item().name;
            files = self.book.manifest.files;
            file_length = ρσ_exists.d(files[(typeof current_name === "number" && current_name < 0) ? files.length + current_name : current_name]).length || 0;
            if (self.length_before === null) {
                return 0;
            }
            frac = progress_frac();
            ans = (self.length_before + file_length * frac) / self.book.manifest.spine_length;
            return ans;
        };
        IframeBoss.prototype.get_current_cfi = function get_current_cfi(data) {
            var self = this;
            var cfi, selected_text, spine, current_name, index;
            cfi = at_current();
            selected_text = window.getSelection().toString();
            if (cfi) {
                spine = self.book.manifest.spine;
                current_name = current_spine_item().name;
                index = spine.indexOf(current_name);
                if (index > -1) {
                    cfi = "epubcfi(/{}{})".format(2 * (index + 1), cfi);
                    ρσ_interpolate_kwargs.call(self, self.send_message, ["report_cfi"].concat([ρσ_desugar_kwargs({cfi: cfi, progress_frac: self.calculate_progress_frac(), file_progress_frac: progress_frac(), request_id: data.request_id, selected_text: selected_text})]));
                    return;
                }
            }
            ρσ_interpolate_kwargs.call(self, self.send_message, ["report_cfi"].concat([ρσ_desugar_kwargs({cfi: null, progress_frac: 0, file_progress_frac: 0, selected_text: selected_text, request_id: data.request_id})]));
        };
        if (!IframeBoss.prototype.get_current_cfi.__argnames__) Object.defineProperties(IframeBoss.prototype.get_current_cfi, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.update_cfi = function update_cfi() {
            var self = this;
            var cfi, spine, current_name, index, pf, fpf, selected_text;
            cfi = at_current();
            if (cfi) {
                spine = self.book.manifest.spine;
                current_name = current_spine_item().name;
                index = spine.indexOf(current_name);
                if (index > -1) {
                    cfi = "epubcfi(/{}{})".format(2 * (index + 1), cfi);
                    pf = self.calculate_progress_frac();
                    fpf = progress_frac();
                    if (cfi !== self.last_cfi) {
                        self.last_cfi = cfi;
                        selected_text = window.getSelection().toString();
                        ρσ_interpolate_kwargs.call(self, self.send_message, ["update_cfi"].concat([ρσ_desugar_kwargs({cfi: cfi, replace_history: self.replace_history_on_next_cfi_update, progress_frac: pf, file_progress_frac: fpf, selected_text: selected_text})]));
                        self.replace_history_on_next_cfi_update = true;
                    } else {
                        ρσ_interpolate_kwargs.call(self, self.send_message, ["update_progress_frac"].concat([ρσ_desugar_kwargs({progress_frac: pf, file_progress_frac: fpf})]));
                    }
                }
            }
        };
        IframeBoss.prototype.update_toc_position = function update_toc_position() {
            var self = this;
            var visible_anchors;
            visible_anchors = update_visible_toc_anchors(self.book.manifest.toc_anchor_map, self.anchor_funcs);
            ρσ_interpolate_kwargs.call(self, self.send_message, ["update_toc_position"].concat([ρσ_desugar_kwargs({visible_anchors: visible_anchors})]));
        };
        IframeBoss.prototype.onscroll = function onscroll() {
            var self = this;
            if (self.content_ready) {
                self.update_cfi();
                self.update_toc_position();
            }
        };
        IframeBoss.prototype.no_latency_onscroll = function no_latency_onscroll() {
            var self = this;
            var pf, fpf;
            pf = self.calculate_progress_frac();
            fpf = progress_frac();
            ρσ_interpolate_kwargs.call(self, self.send_message, ["update_progress_frac"].concat([ρσ_desugar_kwargs({progress_frac: pf, file_progress_frac: fpf})]));
        };
        IframeBoss.prototype.onresize = function onresize() {
            var self = this;
            self.send_message("request_size");
            if (self.content_ready) {
                if (is_ios) {
                    return;
                }
                self.onresize_stage2();
            }
        };
        IframeBoss.prototype.onselectionchange = function onselectionchange() {
            var self = this;
            if (self.content_ready) {
                ρσ_interpolate_kwargs.call(self, self.send_message, ["selectionchange"].concat([ρσ_desugar_kwargs({text: document.getSelection().toString()})]));
            }
        };
        IframeBoss.prototype.onresize_stage2 = function onresize_stage2() {
            var self = this;
            var ρσ_unpack, cfi;
            if (scroll_viewport.width() === self.last_window_width && scroll_viewport.height() === self.last_window_height) {
                return;
            }
            ρσ_unpack = [scroll_viewport.width(), scroll_viewport.height()];
            self.last_window_width = ρσ_unpack[0];
            self.last_window_height = ρσ_unpack[1];
            if (current_layout_mode() !== "flow") {
                self.do_layout();
            }
            if (self.last_cfi) {
                cfi = self.last_cfi.slice(len("epubcfi(/"), -1).partition("/")[2];
                if (cfi) {
                    paged_jump_to_cfi("/" + cfi);
                }
            }
            self.update_cfi();
            self.update_toc_position();
        };
        IframeBoss.prototype.received_window_size = function received_window_size(data) {
            var self = this;
            scroll_viewport.update_window_size(data.width, data.height);
            if (self.content_ready) {
                self.onresize_stage2();
            }
        };
        if (!IframeBoss.prototype.received_window_size.__argnames__) Object.defineProperties(IframeBoss.prototype.received_window_size, {
            __argnames__ : {value: ["data"]}
        });
        IframeBoss.prototype.onwheel = function onwheel(evt) {
            var self = this;
            if (self.content_ready) {
                evt.preventDefault();
                if (evt.deltaY && evt.ctrlKey && !evt.shiftKey && !evt.altKey && !evt.metaKey) {
                    ρσ_interpolate_kwargs.call(self, self.send_message, ["handle_shortcut"].concat([ρσ_desugar_kwargs({name: (evt.deltaY < 0) ? "increase_font_size" : "decrease_font_size"})]));
                } else {
                    self.handle_wheel(evt);
                }
            }
        };
        if (!IframeBoss.prototype.onwheel.__argnames__) Object.defineProperties(IframeBoss.prototype.onwheel, {
            __argnames__ : {value: ["evt"]}
        });
        IframeBoss.prototype.onkeydown = function onkeydown(evt) {
            var self = this;
            var sc_name;
            if (current_layout_mode() !== "flow" && evt.key === "Tab") {
                evt.preventDefault();
            }
            if (self.forward_keypresses) {
                ρσ_interpolate_kwargs.call(self, self.send_message, ["handle_keypress"].concat([ρσ_desugar_kwargs({evt: keyevent_as_shortcut(evt)})]));
                [evt.preventDefault(), evt.stopPropagation()];
                return;
            }
            if (self.content_ready) {
                sc_name = shortcut_for_key_event(evt, self.keyboard_shortcut_map);
                if (sc_name) {
                    if (self.handle_navigation_shortcut(sc_name, evt)) {
                        evt.preventDefault();
                    } else {
                        ρσ_interpolate_kwargs.call(self, self.send_message, ["handle_shortcut"].concat([ρσ_desugar_kwargs({name: sc_name})]));
                    }
                }
            }
        };
        if (!IframeBoss.prototype.onkeydown.__argnames__) Object.defineProperties(IframeBoss.prototype.onkeydown, {
            __argnames__ : {value: ["evt"]}
        });
        IframeBoss.prototype.oncontextmenu = function oncontextmenu(evt) {
            var self = this;
            if (self.content_ready) {
                evt.preventDefault();
                ρσ_interpolate_kwargs.call(self, self.send_message, ["show_chrome"].concat([ρσ_desugar_kwargs({elements: get_elements(evt.clientX, evt.clientY)})]));
            }
        };
        if (!IframeBoss.prototype.oncontextmenu.__argnames__) Object.defineProperties(IframeBoss.prototype.oncontextmenu, {
            __argnames__ : {value: ["evt"]}
        });
        IframeBoss.prototype.send_message = function send_message() {
            var self = this;
            var action = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var data = arguments[arguments.length-1];
            if (data === null || typeof data !== "object" || data [ρσ_kwargs_symbol] !== true) data = {};
            self.comm.send_message(action, data);
        };
        if (!IframeBoss.prototype.send_message.__handles_kwarg_interpolation__) Object.defineProperties(IframeBoss.prototype.send_message, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["action"]}
        });
        IframeBoss.prototype.connect_links = function connect_links() {
            var self = this;
            var link_attr, a;
            link_attr = "data-" + self.book.manifest.link_uid;
            var ρσ_Iter4 = ρσ_Iterable(document.body.querySelectorAll("a[{}]".format(link_attr)));
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                a = ρσ_Iter4[ρσ_Index4];
                a.addEventListener("click", self.link_activated);
            }
            if (runtime.is_standalone_viewer) {
                var ρσ_Iter5 = ρσ_Iterable(document.body.querySelectorAll("a[target]"));
                for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                    a = ρσ_Iter5[ρσ_Index5];
                    a.removeAttribute("target");
                }
            }
        };
        IframeBoss.prototype.link_activated = function link_activated(evt) {
            var self = this;
            var link_attr, data, ρσ_unpack, name, frag, is_popup;
            link_attr = "data-" + self.book.manifest.link_uid;
            try {
                data = JSON.parse(evt.currentTarget.getAttribute(link_attr));
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                {
                    print("WARNING: Failed to parse link data {}, ignoring".format(ρσ_exists.c(ρσ_exists.d(evt.currentTarget).getAttribute)(link_attr)));
                    return;
                } 
            }
            ρσ_unpack = [data.name, data.frag];
            name = ρσ_unpack[0];
            frag = ρσ_unpack[1];
            if (!name) {
                name = current_spine_item().name;
            }
            try {
                is_popup = is_footnote_link(evt.currentTarget, name, frag, current_spine_item().name, self.book.manifest.link_to_map || Object.create(null));
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                {
                    var traceback = ρσ_modules.traceback;

                    traceback.print_exc();
                    is_popup = false;
                } 
            }
            if (is_popup) {
                ρσ_interpolate_kwargs.call(self, self.send_message, ["show_footnote"].concat([ρσ_desugar_kwargs({name: name, frag: frag, title: evt.currentTarget.textContent, cols_per_screen: calc_columns_per_screen()})]));
                return;
            }
            if (name === current_spine_item().name) {
                self.replace_history_on_next_cfi_update = false;
                self.scroll_to_anchor(frag);
            } else {
                ρσ_interpolate_kwargs.call(self, self.send_message, ["scroll_to_anchor"].concat([ρσ_desugar_kwargs({name: name, frag: frag})]));
            }
        };
        if (!IframeBoss.prototype.link_activated.__argnames__) Object.defineProperties(IframeBoss.prototype.link_activated, {
            __argnames__ : {value: ["evt"]}
        });
        IframeBoss.prototype.scroll_to_anchor = function scroll_to_anchor(frag) {
            var self = this;
            var elem, c;
            if (frag) {
                elem = document.getElementById(frag);
                if (!elem) {
                    c = document.getElementsByName(frag);
                    if (c && c.length) {
                        elem = c[0];
                    }
                }
                if (elem) {
                    scroll_to_elem(elem);
                }
            } else {
                scroll_viewport.scroll_to(0, 0);
            }
        };
        if (!IframeBoss.prototype.scroll_to_anchor.__argnames__) Object.defineProperties(IframeBoss.prototype.scroll_to_anchor, {
            __argnames__ : {value: ["frag"]}
        });
        IframeBoss.prototype.find = function find(data, from_load) {
            var self = this;
            if (data.searched_in_spine) {
                window.getSelection().removeAllRanges();
            }
            if (window.find(data.text, false, data.backwards, from_load && data.backwards)) {
                if (current_layout_mode() !== "flow") {
                    snap_to_selection();
                }
            } else {
                if (from_load) {
                    ρσ_interpolate_kwargs.call(self, self.send_message, ["error"].concat([ρσ_desugar_kwargs({title: _("Invisible text"), msg: _("The text <i>{}</i> is present on this page but not visible").format(html_escape(data.text))})]));
                } else {
                    ρσ_interpolate_kwargs.call(self, self.send_message, ["find_in_spine"].concat([ρσ_desugar_kwargs({text: data.text, backwards: data.backwards, searched_in_spine: data.searched_in_spine})]));
                }
            }
        };
        if (!IframeBoss.prototype.find.__argnames__) Object.defineProperties(IframeBoss.prototype.find, {
            __argnames__ : {value: ["data", "from_load"]}
        });
        IframeBoss.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        IframeBoss.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(IframeBoss.prototype, "__bases__", {value: []});

        function main() {
            main.boss = new IframeBoss;
        };

        ρσ_modules["read_book.iframe"].FORCE_FLOW_MODE = FORCE_FLOW_MODE;
        ρσ_modules["read_book.iframe"].CALIBRE_VERSION = CALIBRE_VERSION;
        ρσ_modules["read_book.iframe"].ERS_SUPPORTED_FEATURES = ERS_SUPPORTED_FEATURES;
        ρσ_modules["read_book.iframe"].EPUBReadingSystem = EPUBReadingSystem;
        ρσ_modules["read_book.iframe"].IframeBoss = IframeBoss;
        ρσ_modules["read_book.iframe"].main = main;
    })();

    (function(){
        var __name__ = "read_book.content_popup";
        var CLASS_NAME, TOP_LEVEL_DISPLAY;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var svgicon = ρσ_modules.dom.svgicon;

        var IframeWrapper = ρσ_modules.iframe_comm.IframeWrapper;

        var runtime = ρσ_modules["read_book.globals"].runtime;

        var load_resources = ρσ_modules["read_book.resources"].load_resources;

        CLASS_NAME = "book-content-popup-container";
        TOP_LEVEL_DISPLAY = "flex";
        add_extra_css(function () {
            var sel, style;
            sel = "." + CLASS_NAME;
            style = "";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({justify_content: "center", align_items: "center", height: "100%"})]));
            sel += " > div";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({border_radius: "8px", border: "solid currentColor 2px", margin: "1rem", padding: "0.5rem", box_shadow: "2px 2px 4px currentColor"})]));
            sel += " > div";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({padding_bottom: "1ex", margin_bottom: "1ex", border_bottom: "solid currentColor 2px", display: "flex", justify_content: "space-between", align_items: "center"})]));
            sel += " > div";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({display: "flex", justify_content: "space-between", align_items: "center"})]));
            sel += " > a";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({margin_left: "1ex", cursor: "pointer", display: "inline-block"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ":hover"].concat([ρσ_desugar_kwargs({transform: "scale(1.5)"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ":active"].concat([ρσ_desugar_kwargs({transform: "scale(2)"})]));
            return style;
        });
        function ContentPopupOverlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            ContentPopupOverlay.prototype.__bind_methods__.call(this);
            ContentPopupOverlay.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(ContentPopupOverlay.prototype, "__bind_methods__", {value: function () {
            this.hide = ContentPopupOverlay.prototype.hide.bind(this);
            this.show = ContentPopupOverlay.prototype.show.bind(this);
            this.on_iframe_ready = ContentPopupOverlay.prototype.on_iframe_ready.bind(this);
            this.apply_color_scheme = ContentPopupOverlay.prototype.apply_color_scheme.bind(this);
            this.create_footnote_header = ContentPopupOverlay.prototype.create_footnote_header.bind(this);
            this.load_doc = ContentPopupOverlay.prototype.load_doc.bind(this);
            this.show_footnote = ContentPopupOverlay.prototype.show_footnote.bind(this);
            this.show_footnote_item = ContentPopupOverlay.prototype.show_footnote_item.bind(this);
            this.do_pending_load = ContentPopupOverlay.prototype.do_pending_load.bind(this);
            this.show_footnote_item_stage2 = ContentPopupOverlay.prototype.show_footnote_item_stage2.bind(this);
            this.on_content_loaded = ContentPopupOverlay.prototype.on_content_loaded.bind(this);
        }});
        Object.defineProperties(ContentPopupOverlay.prototype,  {
            "container": {
                "enumerable": true, 
                "get": function container() {
                    var self = this;
                    return document.getElementById("book-content-popup-overlay");
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "iframe": {
                "enumerable": true, 
                "get": function iframe() {
                    var self = this;
                    return self.iframe_wrapper.iframe;
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "is_visible": {
                "enumerable": true, 
                "get": function is_visible() {
                    var self = this;
                    return self.container.style.display !== "none";
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        ContentPopupOverlay.prototype.__init__ = function __init__(view) {
            var self = this;
            var c, iframe, handlers, entry_point;
            self.view = view;
            self.loaded_resources = Object.create(null);
            c = self.container;
            c.classList.add(CLASS_NAME);
            iframe = ρσ_interpolate_kwargs.call(E, E.iframe, [ρσ_desugar_kwargs({seamless: true, sandbox: "allow-scripts", style: "width: 100%; max-height: 70vh"})]);
            c.appendChild(E.div(E.div(), iframe));
            c.addEventListener("click", self.hide);
            c.firstChild.addEventListener("click", (function() {
                var ρσ_anonfunc = function (ev) {
                    [ev.stopPropagation(), ev.preventDefault()];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })());
            handlers = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["ready"] = self.on_iframe_ready;
                ρσ_d["error"] = self.view.on_iframe_error;
                ρσ_d["content_loaded"] = self.on_content_loaded;
                return ρσ_d;
            }).call(this);
            entry_point = (runtime.is_standalone_viewer) ? null : "read_book.footnotes";
            self.iframe_wrapper = new IframeWrapper(handlers, iframe, entry_point, _("Loading data, please wait..."), "<div id=\"calibre-viewer-footnote-iframe\"> </div>");
            self.pending_load = null;
        };
        if (!ContentPopupOverlay.prototype.__init__.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.__init__, {
            __argnames__ : {value: ["view"]}
        });
        ContentPopupOverlay.__argnames__ = ContentPopupOverlay.prototype.__init__.__argnames__;
        ContentPopupOverlay.__handles_kwarg_interpolation__ = ContentPopupOverlay.prototype.__init__.__handles_kwarg_interpolation__;
        ContentPopupOverlay.prototype.hide = function hide() {
            var self = this;
            self.container.style.display = "none";
        };
        ContentPopupOverlay.prototype.show = function show() {
            var self = this;
            var c;
            c = self.container;
            c.style.display = TOP_LEVEL_DISPLAY;
        };
        ContentPopupOverlay.prototype.on_iframe_ready = function on_iframe_ready(msg) {
            var self = this;
            return self.do_pending_load;
        };
        if (!ContentPopupOverlay.prototype.on_iframe_ready.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.on_iframe_ready, {
            __argnames__ : {value: ["msg"]}
        });
        ContentPopupOverlay.prototype.apply_color_scheme = function apply_color_scheme(bg, fg) {
            var self = this;
            var c;
            c = self.container.firstChild;
            c.style.backgroundColor = bg;
            c.style.color = fg;
        };
        if (!ContentPopupOverlay.prototype.apply_color_scheme.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.apply_color_scheme, {
            __argnames__ : {value: ["bg", "fg"]}
        });
        ContentPopupOverlay.prototype.create_footnote_header = function create_footnote_header(header) {
            var self = this;
            var bc;
            clear(header);
            header.appendChild(E.h3(self.current_footnote_data.title || _("Footnote")));
            bc = E.div(ρσ_interpolate_kwargs.call(E, E.a, [svgicon("arrow-right")].concat([ρσ_desugar_kwargs({title: _("Go to this footnote in the main view"), href: "javascript:void(0)"})])), ρσ_interpolate_kwargs.call(E, E.a, [svgicon("close")].concat([ρσ_desugar_kwargs({title: _("Close the footnotes window"), href: "javascript:void(0)"})])));
            bc.firstChild.addEventListener("click", function () {
                self.hide();
                self.view.goto_named_destination(self.current_footnote_data.name, self.current_footnote_data.frag);
            });
            bc.lastChild.addEventListener("click", self.hide);
            header.appendChild(bc);
        };
        if (!ContentPopupOverlay.prototype.create_footnote_header.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.create_footnote_header, {
            __argnames__ : {value: ["header"]}
        });
        ContentPopupOverlay.prototype.load_doc = function load_doc(name, done_callback) {
            var self = this;
            function cb(resource_data) {
                self.loaded_resources = resource_data;
                done_callback(resource_data);
            };
            if (!cb.__argnames__) Object.defineProperties(cb, {
                __argnames__ : {value: ["resource_data"]}
            });

            load_resources(self.view.book, name, self.loaded_resources, cb);
        };
        if (!ContentPopupOverlay.prototype.load_doc.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.load_doc, {
            __argnames__ : {value: ["name", "done_callback"]}
        });
        ContentPopupOverlay.prototype.show_footnote = function show_footnote(data) {
            var self = this;
            var width, c, header;
            self.current_footnote_data = data;
            width = Math.floor(100 / data.cols_per_screen);
            c = self.container.firstChild;
            c.style.width = "" + ρσ_str.format("{}", width) + "vw";
            header = c.firstChild;
            self.create_footnote_header(header);
            self.load_doc(data.name, self.show_footnote_item);
            self.iframe.style.height = "12ex";
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["clear"].concat([ρσ_desugar_kwargs({text: _("Loading note, please wait...")})]));
        };
        if (!ContentPopupOverlay.prototype.show_footnote.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.show_footnote, {
            __argnames__ : {value: ["data"]}
        });
        ContentPopupOverlay.prototype.show_footnote_item = function show_footnote_item(resource_data) {
            var self = this;
            self.pending_load = [resource_data, self.show_footnote_item_stage2];
            if (self.iframe_wrapper.ready) {
                self.do_pending_load();
            } else {
                self.iframe_wrapper.init();
            }
        };
        if (!ContentPopupOverlay.prototype.show_footnote_item.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.show_footnote_item, {
            __argnames__ : {value: ["resource_data"]}
        });
        ContentPopupOverlay.prototype.do_pending_load = function do_pending_load() {
            var self = this;
            var ρσ_unpack, data, func;
            if (self.pending_load) {
                ρσ_unpack = self.pending_load;
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                data = ρσ_unpack[0];
                func = ρσ_unpack[1];
                self.pending_load = null;
                func(data);
            }
        };
        ContentPopupOverlay.prototype.show_footnote_item_stage2 = function show_footnote_item_stage2(resource_data) {
            var self = this;
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_unencrypted_message, ["display"].concat([ρσ_desugar_kwargs({resource_data: resource_data, book: self.view.book, name: self.current_footnote_data.name, frag: self.current_footnote_data.frag, settings: self.view.iframe_settings()})]));
        };
        if (!ContentPopupOverlay.prototype.show_footnote_item_stage2.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.show_footnote_item_stage2, {
            __argnames__ : {value: ["resource_data"]}
        });
        ContentPopupOverlay.prototype.on_content_loaded = function on_content_loaded(data) {
            var self = this;
            self.iframe.style.height = "" + ρσ_str.format("{}", data.height) + "px";
        };
        if (!ContentPopupOverlay.prototype.on_content_loaded.__argnames__) Object.defineProperties(ContentPopupOverlay.prototype.on_content_loaded, {
            __argnames__ : {value: ["data"]}
        });
        ContentPopupOverlay.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        ContentPopupOverlay.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(ContentPopupOverlay.prototype, "__bases__", {value: []});
        
        
        

        ρσ_modules["read_book.content_popup"].CLASS_NAME = CLASS_NAME;
        ρσ_modules["read_book.content_popup"].TOP_LEVEL_DISPLAY = TOP_LEVEL_DISPLAY;
        ρσ_modules["read_book.content_popup"].ContentPopupOverlay = ContentPopupOverlay;
    })();

    (function(){
        var __name__ = "read_book.scrollbar";
        var E = ρσ_modules.elementmaker.E;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var cached_color_to_rgba = ρσ_modules["book_list.theme"].cached_color_to_rgba;

        var unique_id = ρσ_modules.dom.unique_id;

        function BookScrollbar() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            BookScrollbar.prototype.__bind_methods__.call(this);
            BookScrollbar.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(BookScrollbar.prototype, "__bind_methods__", {value: function () {
            this.create = BookScrollbar.prototype.create.bind(this);
            this.bar_clicked = BookScrollbar.prototype.bar_clicked.bind(this);
            this.on_bob_mouse_event = BookScrollbar.prototype.on_bob_mouse_event.bind(this);
            this.apply_visibility = BookScrollbar.prototype.apply_visibility.bind(this);
            this.set_position = BookScrollbar.prototype.set_position.bind(this);
            this.sync_to_contents = BookScrollbar.prototype.sync_to_contents.bind(this);
            this.apply_color_scheme = BookScrollbar.prototype.apply_color_scheme.bind(this);
        }});
        Object.defineProperties(BookScrollbar.prototype,  {
            "container": {
                "enumerable": true, 
                "get": function container() {
                    var self = this;
                    return document.getElementById(self.container_id);
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        BookScrollbar.prototype.__init__ = function __init__(view) {
            var self = this;
            self.view = view;
            self.container_id = unique_id("book-scrollbar");
            self.sync_to_contents_timer = 0;
            self.sync_contents_timer = 0;
        };
        if (!BookScrollbar.prototype.__init__.__argnames__) Object.defineProperties(BookScrollbar.prototype.__init__, {
            __argnames__ : {value: ["view"]}
        });
        BookScrollbar.__argnames__ = BookScrollbar.prototype.__init__.__argnames__;
        BookScrollbar.__handles_kwarg_interpolation__ = BookScrollbar.prototype.__init__.__handles_kwarg_interpolation__;
        BookScrollbar.prototype.create = function create() {
            var self = this;
            self.on_bob_mousedown = self.on_bob_mouse_event.bind(null, "down");
            self.on_bob_mousemove = self.on_bob_mouse_event.bind(null, "move");
            self.on_bob_mouseup = self.on_bob_mouse_event.bind(null, "up");
            return ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "position: relative; width: 100%; height: 22px; background-color: #444; border-radius: 5px", onmousedown: self.on_bob_mousedown})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "position: absolute; z-index: 2147483647; width: 100vw; height: 100vh; left: 0; top: 0; display: none;"})])].concat([ρσ_desugar_kwargs({id: self.container_id, style: "height: 100vh; background-color: #aaa; width: 10px; border-radius: 5px", onclick: self.bar_clicked})]));
        };
        BookScrollbar.prototype.bar_clicked = function bar_clicked(evt) {
            var self = this;
            var c, b, bob_top, bob_bottom;
            if (evt.button === 0) {
                c = self.container;
                b = c.firstChild;
                bob_top = b.offsetTop;
                bob_bottom = bob_top + b.offsetHeight;
                if (evt.clientY < bob_top) {
                    self.view.left_margin_clicked(evt);
                } else if (evt.clientY > bob_bottom) {
                    self.view.right_margin_clicked(evt);
                }
            }
        };
        if (!BookScrollbar.prototype.bar_clicked.__argnames__) Object.defineProperties(BookScrollbar.prototype.bar_clicked, {
            __argnames__ : {value: ["evt"]}
        });
        BookScrollbar.prototype.on_bob_mouse_event = function on_bob_mouse_event(which, evt) {
            var self = this;
            var c, bob, mouse_grab, top, height, frac;
            c = self.container;
            bob = c.firstChild;
            mouse_grab = bob.nextSibling;
            if (which === "move") {
                top = evt.pageY - self.down_y;
                height = c.clientHeight - bob.clientHeight;
                top = max(0, min(top, height));
                bob.style.top = "" + ρσ_str.format("{}", top) + "px";
                [evt.preventDefault(), evt.stopPropagation()];
                frac = bob.offsetTop / height;
                if (self.sync_contents_timer) {
                    window.clearTimeout(self.sync_contents_timer);
                }
                self.sync_contents_timer = window.setTimeout(self.view.goto_frac.bind(null, frac), 2);
            } else if (which === "down") {
                if (evt.button !== 0) {
                    return;
                }
                [evt.preventDefault(), evt.stopPropagation()];
                self.down_y = evt.clientY - bob.getBoundingClientRect().top;
                mouse_grab.style.display = "block";
                window.addEventListener("mousemove", self.on_bob_mousemove, (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["capture"] = true;
                    ρσ_d["passive"] = false;
                    return ρσ_d;
                }).call(this));
                window.addEventListener("mouseup", self.on_bob_mouseup, (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["capture"] = true;
                    ρσ_d["passive"] = false;
                    return ρσ_d;
                }).call(this));
            } else if (which === "up") {
                self.down_y = 0;
                window.removeEventListener("mousemove", self.on_bob_mousemove, (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["capture"] = true;
                    ρσ_d["passive"] = false;
                    return ρσ_d;
                }).call(this));
                window.removeEventListener("mouseup", self.on_bob_mouseup, (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["capture"] = true;
                    ρσ_d["passive"] = false;
                    return ρσ_d;
                }).call(this));
                window.setTimeout(function () {
                    self.container.firstChild.nextSibling.style.display = "none";
                }, 10);
                [evt.preventDefault(), evt.stopPropagation()];
            }
        };
        if (!BookScrollbar.prototype.on_bob_mouse_event.__argnames__) Object.defineProperties(BookScrollbar.prototype.on_bob_mouse_event, {
            __argnames__ : {value: ["which", "evt"]}
        });
        BookScrollbar.prototype.apply_visibility = function apply_visibility() {
            var self = this;
            var sd;
            sd = get_session_data();
            self.container.style.display = (sd.get("book_scrollbar")) ? "block" : "none";
        };
        BookScrollbar.prototype.set_position = function set_position(frac) {
            var self = this;
            var c;
            c = self.container;
            frac = max(0, min(frac, 1));
            c.firstChild.style.top = "" + ρσ_str.format("{}", frac * (c.clientHeight - c.firstChild.clientHeight)) + "px";
        };
        if (!BookScrollbar.prototype.set_position.__argnames__) Object.defineProperties(BookScrollbar.prototype.set_position, {
            __argnames__ : {value: ["frac"]}
        });
        BookScrollbar.prototype.sync_to_contents = function sync_to_contents(frac) {
            var self = this;
            if (self.sync_to_contents_timer) {
                window.clearTimeout(self.sync_to_contents_timer);
            }
            self.sync_to_contents_timer = window.setTimeout(self.set_position.bind(null, frac), 100);
        };
        if (!BookScrollbar.prototype.sync_to_contents.__argnames__) Object.defineProperties(BookScrollbar.prototype.sync_to_contents, {
            __argnames__ : {value: ["frac"]}
        });
        BookScrollbar.prototype.apply_color_scheme = function apply_color_scheme(colors) {
            var self = this;
            var fg, bg, rbg, rfg, c;
            fg = cached_color_to_rgba(colors.foreground);
            bg = cached_color_to_rgba(colors.background);
            function mix(fg, bg, frac) {
                function m(x) {
                    return frac * fg[(typeof x === "number" && x < 0) ? fg.length + x : x] + (1 - frac) * bg[(typeof x === "number" && x < 0) ? bg.length + x : x];
                };
                if (!m.__argnames__) Object.defineProperties(m, {
                    __argnames__ : {value: ["x"]}
                });

                return [m[0], m[1], m[2]];
            };
            if (!mix.__argnames__) Object.defineProperties(mix, {
                __argnames__ : {value: ["fg", "bg", "frac"]}
            });

            rbg = mix(fg, bg, .3);
            rfg = mix(fg, bg, .7);
            c = self.container;
            c.style.backgroundColor = "rgb(" + ρσ_str.format("{}", rbg[0]) + ", " + ρσ_str.format("{}", rbg[1]) + ", " + ρσ_str.format("{}", rbg[2]) + ")";
            c.firstChild.style.backgroundColor = "rgb(" + ρσ_str.format("{}", rfg[0]) + ", " + ρσ_str.format("{}", rfg[1]) + ", " + ρσ_str.format("{}", rfg[2]) + ")";
        };
        if (!BookScrollbar.prototype.apply_color_scheme.__argnames__) Object.defineProperties(BookScrollbar.prototype.apply_color_scheme, {
            __argnames__ : {value: ["colors"]}
        });
        BookScrollbar.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        BookScrollbar.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(BookScrollbar.prototype, "__bases__", {value: []});
        

        ρσ_modules["read_book.scrollbar"].BookScrollbar = BookScrollbar;
    })();

    (function(){
        var __name__ = "book_list.item_list";
        var CLASS_NAME;
        var build_rule = ρσ_modules.dom.build_rule;
        var svgicon = ρσ_modules.dom.svgicon;
        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var clear = ρσ_modules.dom.clear;

        var E = ρσ_modules.elementmaker.E;

        var get_font_size = ρσ_modules["book_list.theme"].get_font_size;
        var get_color = ρσ_modules["book_list.theme"].get_color;

        CLASS_NAME = "generic-items-list";
        add_extra_css(function () {
            var sel, style;
            sel = "." + CLASS_NAME + " ";
            style = "";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "li"].concat([ρσ_desugar_kwargs({padding: "1em", border_bottom: "solid 1px " + get_color("window-foreground"), border_top: "solid 1px " + get_color("window-background"), cursor: "pointer", list_style: "none"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ".item-title"].concat([ρσ_desugar_kwargs({font_size: get_font_size("item-list-title")})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " .item-subtitle"].concat([ρσ_desugar_kwargs({font_size: get_font_size("item-list-subtitle"), font_style: "italic"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " li:hover"].concat([ρσ_desugar_kwargs({color: get_color("list-hover-foreground"), background_color: get_color("list-hover-background"), border_top_color: get_color("list-hover-foreground")})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " li:active"].concat([ρσ_desugar_kwargs({transform: "scale(1, 1.5)"})]));
            return style;
        });
        function build_list(container, items, subtitle) {
            var c, ul, has_icons, item, ic, div;
            c = container;
            clear(c);
            c.classList.add(CLASS_NAME);
            if (subtitle) {
                c.appendChild(ρσ_interpolate_kwargs.call(E, E.p, [subtitle].concat([ρσ_desugar_kwargs({style: "font-style:italic; padding: 1em 1ex; border-bottom: solid 1px currentColor"})])));
            }
            ul = E.ul();
            c.appendChild(ul);
            has_icons = false;
            var ρσ_Iter0 = ρσ_Iterable(items);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                item = ρσ_Iter0[ρσ_Index0];
                if (item.icon) {
                    has_icons = true;
                    break;
                }
            }
            var ρσ_Iter1 = ρσ_Iterable(items);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                item = ρσ_Iter1[ρσ_Index1];
                ic = "";
                if (has_icons) {
                    if (item.icon) {
                        ic = svgicon(item.icon);
                    }
                    ic = E.span(ic, " ");
                }
                ul.appendChild(E.li(ρσ_interpolate_kwargs.call(E, E.div, [ic, item.title].concat([ρσ_desugar_kwargs({class_: "item-title"})]))));
                div = ul.lastChild.firstChild;
                if (item.subtitle) {
                    div.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [item.subtitle].concat([ρσ_desugar_kwargs({class_: "item-subtitle", style: "padding-top:1ex"})])));
                }
                if (item.action) {
                    ul.lastChild.addEventListener("click", item.action);
                }
                if (item.data) {
                    ul.lastChild.dataset.userData = item.data;
                }
            }
        };
        if (!build_list.__argnames__) Object.defineProperties(build_list, {
            __argnames__ : {value: ["container", "items", "subtitle"]}
        });

        function create_item() {
            var title = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var action = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_item.__defaults__.action : arguments[1];
            var subtitle = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_item.__defaults__.subtitle : arguments[2];
            var icon = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_item.__defaults__.icon : arguments[3];
            var data = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_item.__defaults__.data : arguments[4];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "action")){
                action = ρσ_kwargs_obj.action;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "subtitle")){
                subtitle = ρσ_kwargs_obj.subtitle;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "icon")){
                icon = ρσ_kwargs_obj.icon;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "data")){
                data = ρσ_kwargs_obj.data;
            }
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["title"] = title;
                ρσ_d["action"] = action;
                ρσ_d["subtitle"] = subtitle;
                ρσ_d["icon"] = icon;
                ρσ_d["data"] = data;
                return ρσ_d;
            }).call(this);
        };
        if (!create_item.__defaults__) Object.defineProperties(create_item, {
            __defaults__ : {value: {action:null, subtitle:null, icon:null, data:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["title", "action", "subtitle", "icon", "data"]}
        });

        function create_item_list() {
            var container = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var items = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var subtitle = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_item_list.__defaults__.subtitle : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "subtitle")){
                subtitle = ρσ_kwargs_obj.subtitle;
            }
            build_list(container, items, subtitle);
        };
        if (!create_item_list.__defaults__) Object.defineProperties(create_item_list, {
            __defaults__ : {value: {subtitle:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["container", "items", "subtitle"]}
        });

        ρσ_modules["book_list.item_list"].CLASS_NAME = CLASS_NAME;
        ρσ_modules["book_list.item_list"].build_list = build_list;
        ρσ_modules["book_list.item_list"].create_item = create_item;
        ρσ_modules["book_list.item_list"].create_item_list = create_item_list;
    })();

    (function(){
        var __name__ = "read_book.goto";
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var build_list = ρσ_modules["book_list.item_list"].build_list;
        var create_item = ρσ_modules["book_list.item_list"].create_item;

        var ensure_id = ρσ_modules.dom.ensure_id;
        var set_css = ρσ_modules.dom.set_css;

        var error_dialog = ρσ_modules.modals.error_dialog;

        var current_book = ρσ_modules["read_book.globals"].current_book;
        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var get_border_nodes = ρσ_modules["read_book.toc"].get_border_nodes;
        var get_toc_maps = ρσ_modules["read_book.toc"].get_toc_maps;

        var create_button = ρσ_modules.widgets.create_button;

        function create_goto_list(onclick, current_cfi) {
            var ans, items, landmarks, toc, id_map, ρσ_unpack, before, after, l;
            ans = E.div();
            items = [];
            landmarks = current_book().manifest.landmarks;
            toc = current_book().manifest.toc;
            id_map = get_toc_maps(toc)[1];
            ρσ_unpack = get_border_nodes(toc, id_map);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            before = ρσ_unpack[0];
            after = ρσ_unpack[1];
            if (after) {
                items.push(ρσ_interpolate_kwargs.call(this, create_item, [_("Next section")].concat([ρσ_desugar_kwargs({icon: "caret-right", subtitle: after.title, action: onclick.bind(null, after.dest, after.frag)})])));
            }
            if (before) {
                items.push(ρσ_interpolate_kwargs.call(this, create_item, [_("Previous section")].concat([ρσ_desugar_kwargs({icon: "caret-left", subtitle: before.title, action: onclick.bind(null, before.dest, before.frag)})])));
            }
            items.push(ρσ_interpolate_kwargs.call(this, create_item, [_("Book start")].concat([ρσ_desugar_kwargs({action: onclick.bind(null, (function() {
                var ρσ_anonfunc = function (view) {
                    view.goto_doc_boundary(true);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["view"]}
                });
                return ρσ_anonfunc;
            })())})])));
            items.push(ρσ_interpolate_kwargs.call(this, create_item, [_("Book end")].concat([ρσ_desugar_kwargs({action: onclick.bind(null, (function() {
                var ρσ_anonfunc = function (view) {
                    view.goto_doc_boundary(false);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["view"]}
                });
                return ρσ_anonfunc;
            })())})])));
            items.push(ρσ_interpolate_kwargs.call(this, create_item, [_("Metadata")].concat([ρσ_desugar_kwargs({subtitle: _("Details about this book"), action: onclick.bind(null, (function() {
                var ρσ_anonfunc = function (view) {
                    view.overlay.show_metadata();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["view"]}
                });
                return ρσ_anonfunc;
            })())})])));
            items.push(ρσ_interpolate_kwargs.call(this, create_item, [_("Location")].concat([ρσ_desugar_kwargs({subtitle: current_cfi || null, action: onclick.bind(null, (function() {
                var ρσ_anonfunc = function (view) {
                    view.overlay.show_ask_for_location();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["view"]}
                });
                return ρσ_anonfunc;
            })())})])));
            var ρσ_Iter0 = ρσ_Iterable(landmarks);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                l = ρσ_Iter0[ρσ_Index0];
                items.push(ρσ_interpolate_kwargs.call(this, create_item, [l.title].concat([ρσ_desugar_kwargs({action: onclick.bind(null, l.dest, l.frag)})])));
            }
            build_list(ans, items);
            return ans;
        };
        if (!create_goto_list.__argnames__) Object.defineProperties(create_goto_list, {
            __argnames__ : {value: ["onclick", "current_cfi"]}
        });

        function get_next_section(forward) {
            var toc, id_map, ρσ_unpack, before, after;
            toc = current_book().manifest.toc;
            id_map = get_toc_maps(toc)[1];
            ρσ_unpack = get_border_nodes(toc, id_map);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            before = ρσ_unpack[0];
            after = ρσ_unpack[1];
            return (forward) ? after : before;
        };
        if (!get_next_section.__argnames__) Object.defineProperties(get_next_section, {
            __argnames__ : {value: ["forward"]}
        });

        function create_goto_panel(current_cfi, book, container, onclick) {
            var panel;
            panel = create_goto_list(onclick, current_cfi);
            ρσ_interpolate_kwargs.call(this, set_css, [container].concat([ρσ_desugar_kwargs({display: "flex", flex_direction: "column"})]));
            ρσ_interpolate_kwargs.call(this, set_css, [panel].concat([ρσ_desugar_kwargs({flex_grow: "10"})]));
            container.appendChild(panel);
        };
        if (!create_goto_panel.__argnames__) Object.defineProperties(create_goto_panel, {
            __argnames__ : {value: ["current_cfi", "book", "container", "onclick"]}
        });

        function create_location_overlay(current_cfi, overlay, container) {
            var container_id;
            container_id = ensure_id(container);
            if (current_cfi) {
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "text", readonly: "readonly", value: _("Currently at: {}").format(current_cfi), name: "current_location", style: "border-width: 0; background-color: transparent; outline: none; flex-grow: 10; font-family: inherit"})]), ρσ_interpolate_kwargs.call(this, create_button, [_("Copy")].concat([ρσ_desugar_kwargs({action: function () {
                    var src, orig;
                    src = document.querySelector("#" + ρσ_str.format("{}", container_id) + " [name=current_location]");
                    orig = src.value;
                    src.value = current_cfi;
                    src.focus();
                    src.select();
                    try {
                        document.execCommand("copy");
                    } finally {
                        src.value = orig;
                        src.blur();
                    }
                }})]))].concat([ρσ_desugar_kwargs({style: "margin: 1rem; display: flex; align-items: baseline"})])));
            }
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.label, [_("Go to:")].concat([ρσ_desugar_kwargs({style: "margin-right: 1rem"})])), ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({name: "newloc", type: "text", style: "flex-grow: 10; margin-right: 1rem"})]), E.span(" "), ρσ_interpolate_kwargs.call(this, create_button, [_("Go")].concat([ρσ_desugar_kwargs({action: function () {
                var src;
                src = document.querySelector("#" + ρσ_str.format("{}", container_id) + " [name=newloc]");
                if (src.value) {
                    if (ui_operations.goto_bookpos(src.value)) {
                        overlay.hide();
                    } else {
                        error_dialog(_("No such location"), _("No location {} found").format(src.value));
                    }
                }
            }})]))].concat([ρσ_desugar_kwargs({style: "display: flex; align-items: baseline"})]))].concat([ρσ_desugar_kwargs({style: "margin: 1rem;"})])));
        };
        if (!create_location_overlay.__argnames__) Object.defineProperties(create_location_overlay, {
            __argnames__ : {value: ["current_cfi", "overlay", "container"]}
        });

        ρσ_modules["read_book.goto"].create_goto_list = create_goto_list;
        ρσ_modules["read_book.goto"].get_next_section = get_next_section;
        ρσ_modules["read_book.goto"].create_goto_panel = create_goto_panel;
        ρσ_modules["read_book.goto"].create_location_overlay = create_location_overlay;
    })();

    (function(){
        var __name__ = "read_book.open_book";
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var create_item = ρσ_modules["book_list.item_list"].create_item;
        var create_item_list = ρσ_modules["book_list.item_list"].create_item_list;

        var unique_id = ρσ_modules.dom.unique_id;

        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var create_button = ρσ_modules.widgets.create_button;

        function create_open_book(container, book) {
            var sd, rl, c, items, fname, entry;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin: 1rem"})]));
            container = container.lastChild;
            container.appendChild(ρσ_interpolate_kwargs.call(this, create_button, [_("Open a book from your computer")].concat([ρσ_desugar_kwargs({action: ui_operations.ask_for_open.bind(null, null)})])));
            sd = get_session_data();
            rl = sd.get("standalone_recently_opened");
            if (rl.length) {
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: unique_id()})]));
                c = container.lastChild;
                items = ρσ_list_decorate([]);
                c.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Recently viewed books")].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem"})])));
                c.appendChild(E.div());
                var ρσ_Iter0 = ρσ_Iterable(rl);
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    entry = ρσ_Iter0[ρσ_Index0];
                    if (book && book.manifest.pathtoebook === entry.pathtoebook) {
                        continue;
                    }
                    fname = str.replace(entry.pathtoebook, "\\", "/");
                    if (ρσ_in("/", fname)) {
                        fname = (ρσ_expr_temp = fname.rpartition("/"))[ρσ_expr_temp.length-1];
                    }
                    items.push(create_item(entry.title, ui_operations.ask_for_open.bind(null, entry.pathtoebook), fname));
                }
                create_item_list(c.lastChild, items);
                c.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin: 1rem"})]));
                c.lastChild.appendChild(ρσ_interpolate_kwargs.call(this, create_button, [_("Clear recent list")].concat([ρσ_desugar_kwargs({action: clear_recent_list.bind(null, c.id)})])));
            }
        };
        if (!create_open_book.__argnames__) Object.defineProperties(create_open_book, {
            __argnames__ : {value: ["container", "book"]}
        });

        function clear_recent_list(container_id) {
            var sd;
            sd = get_session_data();
            sd.set("standalone_recently_opened", []);
            document.getElementById(container_id).style.display = "none";
        };
        if (!clear_recent_list.__argnames__) Object.defineProperties(clear_recent_list, {
            __argnames__ : {value: ["container_id"]}
        });

        function add_book_to_recently_viewed(book) {
            var sd, rl, key, new_entry, ans, entry;
            sd = get_session_data();
            rl = sd.get("standalone_recently_opened");
            key = book.manifest.pathtoebook;
            new_entry = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["key"] = key;
                ρσ_d["pathtoebook"] = book.manifest.pathtoebook;
                ρσ_d["title"] = book.metadata.title;
                ρσ_d["authors"] = book.metadata.authors;
                ρσ_d["timestamp"] = (new Date).toISOString();
                return ρσ_d;
            }).call(this);
            ans = [];
            ans.push(new_entry);
            var ρσ_Iter1 = ρσ_Iterable(rl);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                entry = ρσ_Iter1[ρσ_Index1];
                if (entry.key !== key) {
                    ans.push(entry);
                }
            }
            sd.set("standalone_recently_opened", ans.slice(0, 25));
            return ans;
        };
        if (!add_book_to_recently_viewed.__argnames__) Object.defineProperties(add_book_to_recently_viewed, {
            __argnames__ : {value: ["book"]}
        });

        ρσ_modules["read_book.open_book"].create_open_book = create_open_book;
        ρσ_modules["read_book.open_book"].clear_recent_list = clear_recent_list;
        ρσ_modules["read_book.open_book"].add_book_to_recently_viewed = add_book_to_recently_viewed;
    })();

    (function(){
        var __name__ = "book_list.top_bar";
        var bar_counter, CLASS_NAME, SPACING, VSPACING, THROBBER_NAME;
        var get_color = ρσ_modules["book_list.theme"].get_color;
        var get_font_size = ρσ_modules["book_list.theme"].get_font_size;

        var set_css = ρσ_modules.dom.set_css;
        var clear = ρσ_modules.dom.clear;
        var create_keyframes = ρσ_modules.dom.create_keyframes;
        var build_rule = ρσ_modules.dom.build_rule;
        var svgicon = ρσ_modules.dom.svgicon;
        var add_extra_css = ρσ_modules.dom.add_extra_css;

        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        bar_counter = 0;
        CLASS_NAME = "main-top-bar";
        SPACING = "0.75em";
        VSPACING = "0.5ex";
        THROBBER_NAME = "top-bar-throbber";
        add_extra_css(function () {
            var sel, style;
            sel = "." + CLASS_NAME + " ";
            style = "";
            style += create_keyframes(THROBBER_NAME, "from { transform: scale(1); } 50% { transform: scale(0.5); } to { transform: scale(1); }");
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "a"].concat([ρσ_desugar_kwargs({display: "inline-block", vertical_align: "middle", overflow: "hidden", cursor: "pointer", color: get_color("bar-foreground"), background: "none", padding_top: VSPACING, padding_bottom: VSPACING})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "a:hover"].concat([ρσ_desugar_kwargs({transform: "scale(1.5)"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "a:active"].concat([ρσ_desugar_kwargs({transform: "scale(2)"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "a:focus"].concat([ρσ_desugar_kwargs({outline: "none"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "a.top-bar-title:hover"].concat([ρσ_desugar_kwargs({transform: "scale(1)", color: get_color("bar-highlight"), font_style: "italic"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "a.top-bar-title:active"].concat([ρσ_desugar_kwargs({transform: "scale(1)", color: get_color("bar-highlight"), font_style: "italic"})]));
            return style;
        });
        function create_markup(container) {
            var bar, i;
            for (var ρσ_Index0 = 0; ρσ_Index0 < 2; ρσ_Index0++) {
                i = ρσ_Index0;
                bar = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "white-space:nowrap; overflow:hidden; text-overflow: ellipsis; padding-left: 0.5em;"})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "white-space:nowrap; text-align:right; padding-right: 0.5em;"})])].concat([ρσ_desugar_kwargs({class_: CLASS_NAME})]));
                if (i === 0) {
                    ρσ_interpolate_kwargs.call(this, set_css, [bar].concat([ρσ_desugar_kwargs({position: "fixed", left: "0", top: "0", z_index: "1"})]));
                }
                ρσ_interpolate_kwargs.call(this, set_css, [bar].concat([ρσ_desugar_kwargs({width: "100%", display: "flex", flex_direction: "row", flex_wrap: "wrap", justify_content: "space-between", font_size: get_font_size("title"), user_select: "none", color: get_color("bar-foreground"), background_color: get_color("bar-background")})]));
                container.appendChild(bar);
            }
        };
        if (!create_markup.__argnames__) Object.defineProperties(create_markup, {
            __argnames__ : {value: ["container"]}
        });

        function get_bars(container) {
            return container.getElementsByClassName(CLASS_NAME);
        };
        if (!get_bars.__argnames__) Object.defineProperties(get_bars, {
            __argnames__ : {value: ["container"]}
        });

        function set_left_data() {
            var container = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var title = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? set_left_data.__defaults__.title : arguments[1];
            var icon = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? set_left_data.__defaults__.icon : arguments[2];
            var action = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? set_left_data.__defaults__.action : arguments[3];
            var tooltip = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? set_left_data.__defaults__.tooltip : arguments[4];
            var run_animation = (arguments[5] === undefined || ( 5 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? set_left_data.__defaults__.run_animation : arguments[5];
            var title_action = (arguments[6] === undefined || ( 6 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? set_left_data.__defaults__.title_action : arguments[6];
            var title_tooltip = (arguments[7] === undefined || ( 7 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? set_left_data.__defaults__.title_tooltip : arguments[7];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "title")){
                title = ρσ_kwargs_obj.title;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "icon")){
                icon = ρσ_kwargs_obj.icon;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "action")){
                action = ρσ_kwargs_obj.action;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "tooltip")){
                tooltip = ρσ_kwargs_obj.tooltip;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "run_animation")){
                run_animation = ρσ_kwargs_obj.run_animation;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "title_action")){
                title_action = ρσ_kwargs_obj.title_action;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "title_tooltip")){
                title_tooltip = ρσ_kwargs_obj.title_tooltip;
            }
            var bars, interface_data, left, title_elem, a, ρσ_unpack, i, bar;
            bars = get_bars(container);
            if (icon === "heart") {
                if (!tooltip) {
                    tooltip = _("Donate to support calibre development");
                }
            }
            interface_data = get_interface_data();
            var ρσ_Iter1 = ρσ_Iterable(enumerate(bars));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                ρσ_unpack = ρσ_Iter1[ρσ_Index1];
                i = ρσ_unpack[0];
                bar = ρσ_unpack[1];
                left = bar.firstChild;
                clear(left);
                title_elem = (callable(title_action)) ? "a" : "span";
                left.appendChild(ρσ_interpolate_kwargs.call(E, E.a, [svgicon(icon)].concat([ρσ_desugar_kwargs({title: tooltip})])));
                left.appendChild(ρσ_interpolate_kwargs.call(this, E, [title_elem, title].concat([ρσ_desugar_kwargs({title: title_tooltip, class_: "top-bar-title", style: "margin-left: {0}; font-weight: bold; padding-top: {1}; padding-bottom: {1}; vertical-align: middle".format(SPACING, VSPACING)})])));
                if (i === 0) {
                    a = left.firstChild;
                    if (icon === "heart") {
                        ρσ_interpolate_kwargs.call(this, set_css, [a].concat([ρσ_desugar_kwargs({animation_name: THROBBER_NAME, animation_duration: "1s", animation_timing_function: "ease-in-out", animation_iteration_count: "5", animation_play_state: (run_animation) ? "running" : "paused"})]));
                        ρσ_interpolate_kwargs.call(this, set_css, [a.firstChild].concat([ρσ_desugar_kwargs({color: get_color("heart")})]));
                        a.setAttribute("href", interface_data.donate_link);
                        a.setAttribute("target", "donate-to-calibre");
                    }
                    if (action !== null) {
                        a.addEventListener("click", (function() {
                            var ρσ_anonfunc = function (event) {
                                [event.preventDefault(), action()];
                            };
                            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                                __argnames__ : {value: ["event"]}
                            });
                            return ρσ_anonfunc;
                        })());
                    }
                    if (callable(title_action)) {
                        a = a.nextSibling;
                        a.addEventListener("click", (function() {
                            var ρσ_anonfunc = function (event) {
                                [event.preventDefault(), title_action()];
                            };
                            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                                __argnames__ : {value: ["event"]}
                            });
                            return ρσ_anonfunc;
                        })());
                    }
                }
            }
        };
        if (!set_left_data.__defaults__) Object.defineProperties(set_left_data, {
            __defaults__ : {value: {title:"calibre", icon:"heart", action:null, tooltip:"", run_animation:false, title_action:null, title_tooltip:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["container", "title", "icon", "action", "tooltip", "run_animation", "title_action", "title_tooltip"]}
        });

        function set_title(container, text) {
            var bars, bar;
            bars = get_bars(container);
            var ρσ_Iter2 = ρσ_Iterable(bars);
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                bar = ρσ_Iter2[ρσ_Index2];
                bar.firstChild.firstChild.nextSibling.textContent = text;
            }
        };
        if (!set_title.__argnames__) Object.defineProperties(set_title, {
            __argnames__ : {value: ["container", "text"]}
        });

        function create_top_bar() {
            var container = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var kw = arguments[arguments.length-1];
            if (kw === null || typeof kw !== "object" || kw [ρσ_kwargs_symbol] !== true) kw = {};
            create_markup(container);
            ρσ_interpolate_kwargs.call(this, set_left_data, [container].concat([ρσ_desugar_kwargs(kw)]));
        };
        if (!create_top_bar.__handles_kwarg_interpolation__) Object.defineProperties(create_top_bar, {
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["container"]}
        });

        function add_button() {
            var container = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var icon = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var action = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? add_button.__defaults__.action : arguments[2];
            var tooltip = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? add_button.__defaults__.tooltip : arguments[3];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "action")){
                action = ρσ_kwargs_obj.action;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "tooltip")){
                tooltip = ρσ_kwargs_obj.tooltip;
            }
            var bars, right, ρσ_unpack, i, bar;
            if (!icon) {
                throw new ValueError("An icon must be specified");
            }
            bars = get_bars(container);
            var ρσ_Iter3 = ρσ_Iterable(enumerate(bars));
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                ρσ_unpack = ρσ_Iter3[ρσ_Index3];
                i = ρσ_unpack[0];
                bar = ρσ_unpack[1];
                right = bar.firstChild.nextSibling;
                right.appendChild(ρσ_interpolate_kwargs.call(E, E.a, [svgicon(icon)].concat([ρσ_desugar_kwargs({style: "margin-left: " + SPACING, title: tooltip})])));
                right.lastChild.dataset.buttonIcon = icon;
                if (i === 0) {
                    if (action !== null) {
                        right.lastChild.addEventListener("click", (function() {
                            var ρσ_anonfunc = function (event) {
                                [event.preventDefault(), action()];
                            };
                            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                                __argnames__ : {value: ["event"]}
                            });
                            return ρσ_anonfunc;
                        })());
                    }
                }
            }
        };
        if (!add_button.__defaults__) Object.defineProperties(add_button, {
            __defaults__ : {value: {action:null, tooltip:""}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["container", "icon", "action", "tooltip"]}
        });

        function clear_buttons(container) {
            var bars, right, ρσ_unpack, i, bar;
            bars = get_bars(container);
            var ρσ_Iter4 = ρσ_Iterable(enumerate(bars));
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                ρσ_unpack = ρσ_Iter4[ρσ_Index4];
                i = ρσ_unpack[0];
                bar = ρσ_unpack[1];
                right = bar.firstChild.nextSibling;
                clear(right);
            }
        };
        if (!clear_buttons.__argnames__) Object.defineProperties(clear_buttons, {
            __argnames__ : {value: ["container"]}
        });

        function set_button_visibility(container, icon, visible) {
            var right, elem, bar;
            var ρσ_Iter5 = ρσ_Iterable(get_bars(container));
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                bar = ρσ_Iter5[ρσ_Index5];
                right = bar.firstChild.nextSibling;
                elem = right.querySelector("[data-button-icon=\"" + ρσ_str.format("{}", icon) + "\"]");
                if (elem) {
                    elem.style.display = (visible) ? "inline-block" : "none";
                }
            }
        };
        if (!set_button_visibility.__argnames__) Object.defineProperties(set_button_visibility, {
            __argnames__ : {value: ["container", "icon", "visible"]}
        });

        ρσ_modules["book_list.top_bar"].bar_counter = bar_counter;
        ρσ_modules["book_list.top_bar"].CLASS_NAME = CLASS_NAME;
        ρσ_modules["book_list.top_bar"].SPACING = SPACING;
        ρσ_modules["book_list.top_bar"].VSPACING = VSPACING;
        ρσ_modules["book_list.top_bar"].THROBBER_NAME = THROBBER_NAME;
        ρσ_modules["book_list.top_bar"].create_markup = create_markup;
        ρσ_modules["book_list.top_bar"].get_bars = get_bars;
        ρσ_modules["book_list.top_bar"].set_left_data = set_left_data;
        ρσ_modules["book_list.top_bar"].set_title = set_title;
        ρσ_modules["book_list.top_bar"].create_top_bar = create_top_bar;
        ρσ_modules["book_list.top_bar"].add_button = add_button;
        ρσ_modules["book_list.top_bar"].clear_buttons = clear_buttons;
        ρσ_modules["book_list.top_bar"].set_button_visibility = set_button_visibility;
    })();

    (function(){
        var __name__ = "book_list.ui";
        var panel_handlers, default_panel_handler;
        var ensure_id = ρσ_modules.dom.ensure_id;
        var clear = ρσ_modules.dom.clear;

        var E = ρσ_modules.elementmaker.E;

        var book_list_container_id = ρσ_modules["book_list.constants"].book_list_container_id;

        var get_current_query = ρσ_modules["book_list.globals"].get_current_query;

        var push_state = ρσ_modules["book_list.router"].push_state;

        var current_library_id = ρσ_modules["book_list.library_data"].current_library_id;
        var current_virtual_library = ρσ_modules["book_list.library_data"].current_virtual_library;

        var encode_query_with_path = ρσ_modules.utils.encode_query_with_path;

        panel_handlers = Object.create(null);
        default_panel_handler = null;
        function set_panel_handler(panel, handler) {
            panel_handlers[(typeof panel === "number" && panel < 0) ? panel_handlers.length + panel : panel] = handler;
        };
        if (!set_panel_handler.__argnames__) Object.defineProperties(set_panel_handler, {
            __argnames__ : {value: ["panel", "handler"]}
        });

        function set_default_panel_handler(handler) {
            default_panel_handler = handler;
        };
        if (!set_default_panel_handler.__argnames__) Object.defineProperties(set_default_panel_handler, {
            __argnames__ : {value: ["handler"]}
        });

        function develop_panel(container_id) {
            var container, q, m;
            container = document.getElementById(container_id);
            q = get_current_query();
            m = q.widget_module;
            if (m) {
                m = get_module(m);
                if ((typeof m !== "undefined" && m !== null ? m : Object.create(null)).develop) {
                    m.develop(container);
                } else {
                    container.textContent = "The module {} either does not exist or has no develop method.".format(q.widget_module);
                }
            }
        };
        if (!develop_panel.__argnames__) Object.defineProperties(develop_panel, {
            __argnames__ : {value: ["container_id"]}
        });

        set_panel_handler("develop-widgets", develop_panel);
        function currently_showing_panel() {
            var c;
            c = document.getElementById(book_list_container_id);
            return c.dataset.panel;
        };

        function add_library_info(query) {
            var vlid;
            if (!query.library_id) {
                query.library_id = current_library_id();
            }
            if (!query.vl) {
                if (query.vl === null) {
                    delete query.vl;
                } else {
                    vlid = current_virtual_library();
                    if (vlid) {
                        query.vl = vlid;
                    }
                }
            }
        };
        if (!add_library_info.__argnames__) Object.defineProperties(add_library_info, {
            __argnames__ : {value: ["query"]}
        });

        function prepare_query(query, panel) {
            var q, k;
            q = (function() {
                var ρσ_Iter = ρσ_Iterable(query || Object.create(null)), ρσ_Result = Object.create(null), k;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    k = ρσ_Iter[ρσ_Index];
                    if (k !== "panel") {
                        ρσ_Result[k] = (query[(typeof k === "number" && k < 0) ? query.length + k : k]);
                    }
                }
                return ρσ_Result;
            })();
            if (panel !== "home") {
                q.panel = panel;
                add_library_info(q);
            }
            return q;
        };
        if (!prepare_query.__argnames__) Object.defineProperties(prepare_query, {
            __argnames__ : {value: ["query", "panel"]}
        });

        function query_as_href(query, panel) {
            var q;
            q = prepare_query(query, panel || "book_list");
            return encode_query_with_path(q);
        };
        if (!query_as_href.__argnames__) Object.defineProperties(query_as_href, {
            __argnames__ : {value: ["query", "panel"]}
        });

        function show_panel() {
            var panel = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var query = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_panel.__defaults__.query : arguments[1];
            var replace = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_panel.__defaults__.replace : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "query")){
                query = ρσ_kwargs_obj.query;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "replace")){
                replace = ρσ_kwargs_obj.replace;
            }
            ρσ_interpolate_kwargs.call(this, push_state, [prepare_query(query, panel)].concat([ρσ_desugar_kwargs({replace: replace})]));
        };
        if (!show_panel.__defaults__) Object.defineProperties(show_panel, {
            __defaults__ : {value: {query:null, replace:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["panel", "query", "replace"]}
        });

        function apply_url_state(state) {
            var panel, c, handler;
            panel = state.panel || "home";
            c = document.getElementById(book_list_container_id);
            clear(c);
            c.appendChild(E.div());
            c.dataset.panel = panel;
            handler = panel_handlers[(typeof panel === "number" && panel < 0) ? panel_handlers.length + panel : panel] || default_panel_handler;
            handler(ensure_id(c.firstChild, "panel"));
        };
        if (!apply_url_state.__argnames__) Object.defineProperties(apply_url_state, {
            __argnames__ : {value: ["state"]}
        });

        apply_url_state.back_from_current = (function() {
            var ρσ_anonfunc = function back_from_current(current_query) {
                var q, k;
                q = current_query;
                if (q.panel) {
                    if (ρσ_in("^", q.panel)) {
                        q = (function() {
                            var ρσ_Iter = ρσ_Iterable(q), ρσ_Result = Object.create(null), k;
                            for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                                k = ρσ_Iter[ρσ_Index];
                                ρσ_Result[k] = (q[(typeof k === "number" && k < 0) ? q.length + k : k]);
                            }
                            return ρσ_Result;
                        })();
                        q.panel = q.panel.rpartition("^")[0];
                    } else if (q.panel === "book_list") {
                        q = Object.create(null);
                    } else {
                        q = (function(){
                            var ρσ_d = Object.create(null);
                            ρσ_d["panel"] = "book_list";
                            return ρσ_d;
                        }).call(this);
                        add_library_info(q);
                    }
                }
                return q;
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["current_query"]}
            });
            return ρσ_anonfunc;
        })();
        ρσ_modules["book_list.ui"].panel_handlers = panel_handlers;
        ρσ_modules["book_list.ui"].default_panel_handler = default_panel_handler;
        ρσ_modules["book_list.ui"].set_panel_handler = set_panel_handler;
        ρσ_modules["book_list.ui"].set_default_panel_handler = set_default_panel_handler;
        ρσ_modules["book_list.ui"].develop_panel = develop_panel;
        ρσ_modules["book_list.ui"].currently_showing_panel = currently_showing_panel;
        ρσ_modules["book_list.ui"].add_library_info = add_library_info;
        ρσ_modules["book_list.ui"].prepare_query = prepare_query;
        ρσ_modules["book_list.ui"].query_as_href = query_as_href;
        ρσ_modules["book_list.ui"].show_panel = show_panel;
        ρσ_modules["book_list.ui"].apply_url_state = apply_url_state;
    })();

    (function(){
        var __name__ = "file_uploads";
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var ensure_id = ρσ_modules.dom.ensure_id;

        var human_readable = ρσ_modules.utils.human_readable;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;

        function upload_files_widget() {
            var container = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var proceed = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var msg = ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[2];
            var single_file = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? upload_files_widget.__defaults__.single_file : arguments[3];
            var accept_extensions = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? upload_files_widget.__defaults__.accept_extensions : arguments[4];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "single_file")){
                single_file = ρσ_kwargs_obj.single_file;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "accept_extensions")){
                accept_extensions = ρσ_kwargs_obj.accept_extensions;
            }
            var container_id, c, a;
            container_id = ensure_id(container, "upload-files");
            function files_selected() {
                var files, container;
                files = this.files;
                container = document.getElementById(container_id);
                container.removeChild(container.lastChild);
                if (callable(proceed) && files.length) {
                    proceed(container_id, files);
                }
            };

            msg = msg || _("Upload books by <a>selecting the book files</a> or drag and drop of the files here");
            c = E.div(E.span(), ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "file", style: "display:none", onchange: files_selected})]));
            if (!single_file) {
                c.lastChild.setAttribute("multiple", "multiple");
            }
            if (accept_extensions) {
                c.lastChild.setAttribute("accept", ", ".join((function() {
                    var ρσ_Iter = ρσ_Iterable(accept_extensions.split(" ")), ρσ_Result = [], x;
                    for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                        x = ρσ_Iter[ρσ_Index];
                        ρσ_Result.push("." + x);
                    }
                    ρσ_Result = ρσ_list_constructor(ρσ_Result);
                    return ρσ_Result;
                })()));
            }
            c.style.minHeight = "80vh";
            c.style.padding = "1rem";
            c.style.borderBottom = "solid 1px currentColor";
            safe_set_inner_html(c.firstChild, msg);
            a = c.getElementsByTagName("a")[0];
            a.setAttribute("href", "javascript: void(0)");
            a.classList.add("blue-link");
            a.addEventListener("click", function () {
                document.getElementById(container_id).querySelector("input[type=file]").click();
            }, false);
            container.appendChild(c);
            function stop(e) {
                [e.stopPropagation(), e.preventDefault()];
            };
            if (!stop.__argnames__) Object.defineProperties(stop, {
                __argnames__ : {value: ["e"]}
            });

            function drop(e) {
                var dt;
                stop(e);
                dt = e.dataTransfer;
                files_selected.call(dt);
            };
            if (!drop.__argnames__) Object.defineProperties(drop, {
                __argnames__ : {value: ["e"]}
            });

            c.addEventListener("dragenter", stop, false);
            c.addEventListener("dragover", stop, false);
            c.addEventListener("drop", drop, false);
            return c;
        };
        if (!upload_files_widget.__defaults__) Object.defineProperties(upload_files_widget, {
            __defaults__ : {value: {single_file:false, accept_extensions:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["container", "proceed", "msg", "single_file", "accept_extensions"]}
        });

        function update_status_widget(w, sent, total) {
            var p;
            if (total) {
                p = w.getElementsByTagName("progress")[0];
                p.setAttribute("value", "" + sent);
                p.setAttribute("max", "" + total);
                w.lastChild.textContent = (ρσ_expr_temp = _(" {percent:.0%} of {total}"), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.format, [ρσ_desugar_kwargs({percent: sent / total, total: human_readable(total)})]));
            }
        };
        if (!update_status_widget.__argnames__) Object.defineProperties(update_status_widget, {
            __argnames__ : {value: ["w", "sent", "total"]}
        });

        function upload_status_widget(name, job_id) {
            var ans;
            ans = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "padding: 1rem 1ex;", data_job: "" + job_id})]);
            if (name) {
                ans.appendChild(E.h3(E.b(name)));
            }
            ans.appendChild(E.progress());
            ans.appendChild(E.span());
            return ans;
        };
        if (!upload_status_widget.__argnames__) Object.defineProperties(upload_status_widget, {
            __argnames__ : {value: ["name", "job_id"]}
        });

        ρσ_modules.file_uploads.upload_files_widget = upload_files_widget;
        ρσ_modules.file_uploads.update_status_widget = update_status_widget;
        ρσ_modules.file_uploads.upload_status_widget = upload_status_widget;
    })();

    (function(){
        var __name__ = "book_list.add";
        var state;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var ajax_send_file = ρσ_modules.ajax.ajax_send_file;

        var force_refresh_on_next_load = ρσ_modules["book_list.library_data"].force_refresh_on_next_load;
        var loaded_books_query = ρσ_modules["book_list.library_data"].loaded_books_query;

        var back = ρσ_modules["book_list.router"].back;

        var create_top_bar = ρσ_modules["book_list.top_bar"].create_top_bar;

        var query_as_href = ρσ_modules["book_list.ui"].query_as_href;
        var show_panel = ρσ_modules["book_list.ui"].show_panel;

        var clear = ρσ_modules.dom.clear;
        var ensure_id = ρσ_modules.dom.ensure_id;

        var update_status_widget = ρσ_modules.file_uploads.update_status_widget;
        var upload_files_widget = ρσ_modules.file_uploads.upload_files_widget;
        var upload_status_widget = ρσ_modules.file_uploads.upload_status_widget;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;

        var create_button = ρσ_modules.widgets.create_button;

        state = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["in_progress"] = false;
            ρσ_d["container_id"] = null;
            ρσ_d["counter"] = 0;
            ρσ_d["number"] = 0;
            ρσ_d["fake_send"] = false;
            ρσ_d["transfers"] = [];
            return ρσ_d;
        }).call(this);
        function cancel_in_progress() {
            var xhr;
            var ρσ_Iter0 = ρσ_Iterable(state.transfers);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                xhr = ρσ_Iter0[ρσ_Index0];
                xhr.abort();
            }
            state.transfers = [];
            state.in_progress = false;
        };

        function on_close() {
            cancel_in_progress();
            back();
        };

        function get_job_container(container_id, job_id) {
            var container;
            container = document.getElementById(container_id);
            if (!container) {
                return;
            }
            return container.querySelector("[data-job=\"" + ρσ_str.format("{}", job_id) + "\"]");
        };
        if (!get_job_container.__argnames__) Object.defineProperties(get_job_container, {
            __argnames__ : {value: ["container_id", "job_id"]}
        });

        function on_progress(container_id, job_id, loaded, total, xhr) {
            var container;
            container = get_job_container(container_id, job_id);
            if (container === null) {
                return;
            }
            if (total) {
                update_status_widget(container, loaded, total);
            }
        };
        if (!on_progress.__argnames__) Object.defineProperties(on_progress, {
            __argnames__ : {value: ["container_id", "job_id", "loaded", "total", "xhr"]}
        });

        function list_added_book(container, data) {
            var q, a;
            container.appendChild(E.h3(E.b(data.title), E.span(" " + _("by") + " "), E.i(" & ".join(data.authors))));
            container.appendChild(E.span(_("Added successfully") + " "));
            q = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["book_id"] = data.book_id + "";
                return ρσ_d;
            }).call(this);
            a = ρσ_interpolate_kwargs.call(this, create_button, [_("Open")].concat([ρσ_desugar_kwargs({action: query_as_href(q, "book_details")})]));
            if (state.number > 1) {
                a.setAttribute("target", "_blank");
            } else {
                a.addEventListener("click", (function() {
                    var ρσ_anonfunc = function (e) {
                        e.preventDefault();
                        show_panel("book_details", (function(){
                            var ρσ_d = Object.create(null);
                            ρσ_d["book_id"] = data.book_id + "";
                            return ρσ_d;
                        }).call(this), true);
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["e"]}
                    });
                    return ρσ_anonfunc;
                })());
            }
            container.appendChild(a);
        };
        if (!list_added_book.__argnames__) Object.defineProperties(list_added_book, {
            __argnames__ : {value: ["container", "data"]}
        });

        function list_duplicate_book(container, container_id, job_id, data, file) {
            var b;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("A book with the title \"{0}\" already exists in the library.").format(data.title)].concat([ρσ_desugar_kwargs({style: "padding: 1rem 1ex"})])));
            b = ρσ_interpolate_kwargs.call(this, create_button, [_("Add anyway")].concat([ρσ_desugar_kwargs({action: function () {
                var c, w;
                c = get_job_container(container_id, job_id);
                clear(c);
                w = upload_status_widget(file.name, job_id);
                c.appendChild(w);
                send_file(file, container_id, job_id, true);
            }})]));
            container.appendChild(b);
        };
        if (!list_duplicate_book.__argnames__) Object.defineProperties(list_duplicate_book, {
            __argnames__ : {value: ["container", "container_id", "job_id", "data", "file"]}
        });

        function write_access_error(msg, xhr) {
            var html, un;
            html = msg + "<br>";
            if (xhr.status === 403) {
                un = get_interface_data().username;
                if (un) {
                    html += _("You are not allowed to make changes to the library") + "<hr>";
                } else {
                    html += _("You must be logged in to make changes to the library") + "<hr>";
                }
            }
            return html + "<br>" + xhr.error_html;
        };
        if (!write_access_error.__argnames__) Object.defineProperties(write_access_error, {
            __argnames__ : {value: ["msg", "xhr"]}
        });

        function on_complete(container_id, job_id, end_type, xhr, ev) {
            var idx, container, data, html;
            idx = state.transfers.indexOf(xhr);
            if (idx > -1) {
                state.transfers.splice(idx, 1);
            }
            container = get_job_container(container_id, job_id);
            if (container === null) {
                return;
            }
            clear(container);
            if (end_type === "load") {
                data = JSON.parse(xhr.responseText);
                if (data.book_id) {
                    list_added_book(container, data);
                    force_refresh_on_next_load();
                } else {
                    list_duplicate_book(container, container_id, job_id, data, this);
                }
            } else if (end_type === "abort") {
                return;
            } else {
                html = write_access_error(_("Failed to upload the file: {}").format(this.name), xhr);
                safe_set_inner_html(container, html);
            }
        };
        if (!on_complete.__argnames__) Object.defineProperties(on_complete, {
            __argnames__ : {value: ["container_id", "job_id", "end_type", "xhr", "ev"]}
        });

        function fake_send(container_id, job_id) {
            var container, prev;
            container = get_job_container(container_id, job_id);
            prev = parseInt(container.dataset.fake || "0");
            container.dataset.fake = prev + 10;
            update_status_widget(container, container.dataset.fake, 100);
            if (parseInt(container.dataset.fake || "0") < 100) {
                setTimeout(fake_send.bind(null, container_id, job_id), 1e3);
            }
        };
        if (!fake_send.__argnames__) Object.defineProperties(fake_send, {
            __argnames__ : {value: ["container_id", "job_id"]}
        });

        function send_file(file, container_id, job_id, add_duplicates) {
            var lid, ad, xhr;
            lid = loaded_books_query().library_id;
            ad = (add_duplicates) ? "y" : "n";
            xhr = ajax_send_file("cdb/add-book/" + ρσ_str.format("{}", job_id) + "/" + ρσ_str.format("{}", ad) + "/" + ρσ_str.format("{}", encodeURIComponent(file.name)) + "/" + ρσ_str.format("{}", lid) + "", file, on_complete.bind(file, container_id, job_id), on_progress.bind(null, container_id, job_id));
            state.transfers.push(xhr);
            return xhr;
        };
        if (!send_file.__argnames__) Object.defineProperties(send_file, {
            __argnames__ : {value: ["file", "container_id", "job_id", "add_duplicates"]}
        });

        function files_chosen(container_id, files) {
            var container, job_id, w, file;
            container = document.getElementById(container_id);
            if (!container) {
                return;
            }
            state.number = 0;
            var ρσ_Iter1 = ρσ_Iterable(files);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                file = ρσ_Iter1[ρσ_Index1];
                state.counter += 1;
                state.number += 1;
                job_id = state.counter;
                w = upload_status_widget(file.name, job_id);
                container.appendChild(w);
                w.style.borderBottom = "solid 1px currentColor";
                if (state.fake_send) {
                    setTimeout(fake_send.bind(null, container_id, job_id), 100);
                } else {
                    send_file(file, container_id, job_id);
                }
            }
        };
        if (!files_chosen.__argnames__) Object.defineProperties(files_chosen, {
            __argnames__ : {value: ["container_id", "files"]}
        });

        function add_books_panel(container_id) {
            var container;
            container = document.getElementById(container_id);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("Add books"), action: on_close, icon: "close"})]));
            cancel_in_progress();
            state.in_progress = true;
            state.container_id = container_id;
            state.fake_send = false;
            return upload_files_widget(container, files_chosen);
        };
        if (!add_books_panel.__argnames__) Object.defineProperties(add_books_panel, {
            __argnames__ : {value: ["container_id"]}
        });

        function develop(container) {
            add_books_panel(ensure_id(container));
        };
        if (!develop.__argnames__) Object.defineProperties(develop, {
            __argnames__ : {value: ["container"]}
        });

        ρσ_modules["book_list.add"].state = state;
        ρσ_modules["book_list.add"].cancel_in_progress = cancel_in_progress;
        ρσ_modules["book_list.add"].on_close = on_close;
        ρσ_modules["book_list.add"].get_job_container = get_job_container;
        ρσ_modules["book_list.add"].on_progress = on_progress;
        ρσ_modules["book_list.add"].list_added_book = list_added_book;
        ρσ_modules["book_list.add"].list_duplicate_book = list_duplicate_book;
        ρσ_modules["book_list.add"].write_access_error = write_access_error;
        ρσ_modules["book_list.add"].on_complete = on_complete;
        ρσ_modules["book_list.add"].fake_send = fake_send;
        ρσ_modules["book_list.add"].send_file = send_file;
        ρσ_modules["book_list.add"].files_chosen = files_chosen;
        ρσ_modules["book_list.add"].add_books_panel = add_books_panel;
        ρσ_modules["book_list.add"].develop = develop;
    })();

    (function(){
        var __name__ = "book_list.delete_book";
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var ajax = ρσ_modules.ajax.ajax;

        var write_access_error = ρσ_modules["book_list.add"].write_access_error;

        var book_after = ρσ_modules["book_list.library_data"].book_after;
        var force_refresh_on_next_load = ρσ_modules["book_list.library_data"].force_refresh_on_next_load;

        var back = ρσ_modules["book_list.router"].back;

        var show_panel = ρσ_modules["book_list.ui"].show_panel;

        var clear = ρσ_modules.dom.clear;

        var create_custom_dialog = ρσ_modules.modals.create_custom_dialog;

        var get_db = ρσ_modules["read_book.db"].get_db;

        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;

        var create_button = ρσ_modules.widgets.create_button;

        function delete_from_cache(library_id, book_id, title) {
            var db;
            db = get_db();
            db.delete_books_matching(library_id, book_id);
        };
        if (!delete_from_cache.__argnames__) Object.defineProperties(delete_from_cache, {
            __argnames__ : {value: ["library_id", "book_id", "title"]}
        });

        function refresh_after_delete(book_id, library_id) {
            var next_book_id;
            force_refresh_on_next_load();
            next_book_id = book_after(book_id);
            if (next_book_id) {
                show_panel("book_details", (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["book_id"] = str(next_book_id);
                    ρσ_d["library_id"] = library_id;
                    return ρσ_d;
                }).call(this), true);
            } else {
                back();
            }
        };
        if (!refresh_after_delete.__argnames__) Object.defineProperties(refresh_after_delete, {
            __argnames__ : {value: ["book_id", "library_id"]}
        });

        function do_delete_from_library(parent, close_modal, library_id, book_id, title) {
            parent.appendChild(E.div(_("Deleting {0} from library, please wait...").format(title)));
            function oncomplete(end_type, xhr, ev) {
                var msg;
                if (end_type === "load" || end_type === "abort") {
                    close_modal();
                    if (end_type === "load") {
                        refresh_after_delete(book_id, library_id);
                    }
                    return;
                }
                clear(parent);
                msg = E.div();
                safe_set_inner_html(msg, write_access_error(_("Failed to delete {0}, with error:").format(title), xhr));
                parent.appendChild(E.div(msg, ρσ_interpolate_kwargs.call(E, E.div, [create_button(_("Close"), null, close_modal, true)].concat([ρσ_desugar_kwargs({class_: "button-box"})]))));
            };
            if (!oncomplete.__argnames__) Object.defineProperties(oncomplete, {
                __argnames__ : {value: ["end_type", "xhr", "ev"]}
            });

            ρσ_interpolate_kwargs.call(this, ajax, ["cdb/delete-books/" + ρσ_str.format("{}", book_id) + "/" + ρσ_str.format("{}", library_id) + "", oncomplete].concat([ρσ_desugar_kwargs({method: "POST"})])).send();
        };
        if (!do_delete_from_library.__argnames__) Object.defineProperties(do_delete_from_library, {
            __argnames__ : {value: ["parent", "close_modal", "library_id", "book_id", "title"]}
        });

        function confirm_delete_from_library(library_id, book_id, title) {
            create_custom_dialog(_("Are you sure?"), (function() {
                var ρσ_anonfunc = function (parent, close_modal) {
                    var msg, m;
                    function action(doit) {
                        if (doit) {
                            clear(parent);
                            do_delete_from_library(parent, close_modal, library_id, book_id, title);
                        } else {
                            close_modal();
                        }
                    };
                    if (!action.__argnames__) Object.defineProperties(action, {
                        __argnames__ : {value: ["doit"]}
                    });

                    msg = _("This will <b>permanently delete</b> <i>{0}</i> from your calibre library. Are you sure?").format(title);
                    m = E.div();
                    safe_set_inner_html(m, msg);
                    parent.appendChild(E.div(m, ρσ_interpolate_kwargs.call(E, E.div, [create_button(_("OK"), null, action.bind(null, true)), " ", ρσ_interpolate_kwargs.call(this, create_button, [_("Cancel"), null, action.bind(null, false)].concat([ρσ_desugar_kwargs({highlight: true})]))].concat([ρσ_desugar_kwargs({class_: "button-box"})]))));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["parent", "close_modal"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!confirm_delete_from_library.__argnames__) Object.defineProperties(confirm_delete_from_library, {
            __argnames__ : {value: ["library_id", "book_id", "title"]}
        });

        function choose_which_delete(library_id, book_id, title) {
            create_custom_dialog(_("Delete from?"), (function() {
                var ρσ_anonfunc = function (parent, close_modal) {
                    function action(from_cache, from_library) {
                        close_modal();
                        if (from_cache) {
                            delete_from_cache(library_id, book_id, title);
                        }
                        if (from_library) {
                            confirm_delete_from_library(library_id, book_id, title);
                        }
                    };
                    if (!action.__argnames__) Object.defineProperties(action, {
                        __argnames__ : {value: ["from_cache", "from_library"]}
                    });

                    parent.appendChild(E.div(E.div(_("{0} is available both in the browser cache for offline reading and in your calibre library. Where do you want to delete it from?").format(title)), ρσ_interpolate_kwargs.call(E, E.div, [create_button(_("Cache"), null, action.bind(null, true, false)), " ", create_button(_("Library and cache"), null, action.bind(null, true, true))].concat([ρσ_desugar_kwargs({class_: "button-box"})]))));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["parent", "close_modal"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!choose_which_delete.__argnames__) Object.defineProperties(choose_which_delete, {
            __argnames__ : {value: ["library_id", "book_id", "title"]}
        });

        function delete_book_stage2(library_id, book_id, title, has_offline_copies) {
            if (has_offline_copies) {
                choose_which_delete(library_id, book_id, title);
            } else {
                confirm_delete_from_library(library_id, book_id, title);
            }
        };
        if (!delete_book_stage2.__argnames__) Object.defineProperties(delete_book_stage2, {
            __argnames__ : {value: ["library_id", "book_id", "title", "has_offline_copies"]}
        });

        function start_delete_book(library_id, book_id, title) {
            var db;
            book_id = int(book_id);
            db = get_db();
            db.has_book_matching(library_id, book_id, delete_book_stage2.bind(null, library_id, book_id, title));
        };
        if (!start_delete_book.__argnames__) Object.defineProperties(start_delete_book, {
            __argnames__ : {value: ["library_id", "book_id", "title"]}
        });

        ρσ_modules["book_list.delete_book"].delete_from_cache = delete_from_cache;
        ρσ_modules["book_list.delete_book"].refresh_after_delete = refresh_after_delete;
        ρσ_modules["book_list.delete_book"].do_delete_from_library = do_delete_from_library;
        ρσ_modules["book_list.delete_book"].confirm_delete_from_library = confirm_delete_from_library;
        ρσ_modules["book_list.delete_book"].choose_which_delete = choose_which_delete;
        ρσ_modules["book_list.delete_book"].delete_book_stage2 = delete_book_stage2;
        ρσ_modules["book_list.delete_book"].start_delete_book = start_delete_book;
    })();

    (function(){
        var __name__ = "book_list.cover_grid";
        var COVER_GRID_CLASS, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, THUMBNAIL_MIN_WIDTH, THUMBNAIL_MIN_HEIGHT, BORDER_RADIUS;
        var clear = ρσ_modules.dom.clear;
        var set_css = ρσ_modules.dom.set_css;
        var build_rule = ρσ_modules.dom.build_rule;

        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        COVER_GRID_CLASS = "book-list-cover-grid";
        THUMBNAIL_MAX_WIDTH = 3 * 100;
        THUMBNAIL_MAX_HEIGHT = 4 * 100;
        THUMBNAIL_MIN_WIDTH = 3 * 35;
        THUMBNAIL_MIN_HEIGHT = 4 * 35;
        BORDER_RADIUS = 10;
        function description() {
            return _("A grid of book covers");
        };

        function cover_grid_css() {
            var sel, ρσ_unpack, margin, margin_unit, ans, mq, dim;
            sel = "." + COVER_GRID_CLASS;
            ρσ_unpack = [10, "px"];
            margin = ρσ_unpack[0];
            margin_unit = ρσ_unpack[1];
            ans = ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({display: "flex", flex_wrap: "wrap", justify_content: "space-around", align_items: "flex-end", align_content: "flex-start", user_select: "none", overflow: "hidden", margin_top: "" + ρσ_str.format("{}", margin / 2) + "" + ρσ_str.format("{}", margin_unit) + ""})]));
            sel += " > a";
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({margin: "" + ρσ_str.format("{}", margin) + "" + ρσ_str.format("{}", margin_unit) + "", display: "flex", align_content: "flex-end", align_items: "flex-end", justify_content: "space-around", max_width: THUMBNAIL_MAX_WIDTH + "px", max_height: THUMBNAIL_MAX_HEIGHT + "px", cursor: "pointer", min_width: THUMBNAIL_MIN_WIDTH + "px", min_height: THUMBNAIL_MIN_HEIGHT + "px"})]));
            mq = "@media all and (orientation: {orient}) {{ {sel} {{ width: 21{dim}; height: 28{dim} }} }}\n";
            var ρσ_Iter0 = ρσ_Iterable(ρσ_list_decorate([ "vw", "vh" ]));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                dim = ρσ_Iter0[ρσ_Index0];
                ans += ρσ_interpolate_kwargs.call(mq, mq.format, [ρσ_desugar_kwargs({sel: sel, dim: dim, orient: (dim === "vw") ? "portrait" : "landscape"})]);
            }
            ans += ρσ_interpolate_kwargs.call(this, build_rule, ["" + ρσ_str.format("{}", sel) + ":hover"].concat([ρσ_desugar_kwargs({transform: "scale(1.2)"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, ["" + ρσ_str.format("{}", sel) + ":active"].concat([ρσ_desugar_kwargs({transform: "scale(2)"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ".cover-grid-filler"].concat([ρσ_desugar_kwargs({height: "0", max_height: "0", min_height: "0"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " > div"].concat([ρσ_desugar_kwargs({position: "relative", top: "-50%", transform: "translateY(50%)", margin: "0"})]));
            sel += " > img";
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({max_width: "100%", max_height: "100%", display: "block", width: "auto", height: "auto", border_radius: BORDER_RADIUS + "px"})]));
            return ans;
        };

        function init(container) {
            var i;
            clear(container);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: COVER_GRID_CLASS})]));
            for (var ρσ_Index1 = 0; ρσ_Index1 < 12; ρσ_Index1++) {
                i = ρσ_Index1;
                container.lastChild.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: "cover-grid-filler"})]));
            }
        };
        if (!init.__argnames__) Object.defineProperties(init, {
            __argnames__ : {value: ["container"]}
        });

        function on_img_load(img, load_type) {
            var div;
            div = img.parentNode;
            if (!div) {
                return;
            }
            if (load_type !== "load") {
                clear(div);
                div.appendChild(E.div(ρσ_interpolate_kwargs.call(E, E.h2, [img.dataset.title].concat([ρσ_desugar_kwargs({style: "text-align:center; font-size:larger; font-weight: bold"})])), ρσ_interpolate_kwargs.call(E, E.div, [_("by")].concat([ρσ_desugar_kwargs({style: "text-align: center"})])), ρσ_interpolate_kwargs.call(E, E.h2, [img.dataset.authors].concat([ρσ_desugar_kwargs({style: "text-align:center; font-size:larger; font-weight: bold"})]))));
                ρσ_interpolate_kwargs.call(this, set_css, [div].concat([ρσ_desugar_kwargs({border: "dashed 1px currentColor", border_radius: BORDER_RADIUS + "px"})]));
            }
        };
        if (!on_img_load.__argnames__) Object.defineProperties(on_img_load, {
            __argnames__ : {value: ["img", "load_type"]}
        });

        function create_item(book_id, metadata, create_image, show_book_details, href) {
            var authors, img, tooltip, ρσ_unpack, ans;
            authors = (metadata.authors) ? metadata.authors.join(" & ") : _("Unknown");
            img = create_image(book_id, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, on_img_load);
            tooltip = _("{} by {}").format(metadata.title, authors);
            img.setAttribute("alt", tooltip);
            ρσ_unpack = [metadata.title, authors];
            img.dataset.title = ρσ_unpack[0];
            img.dataset.authors = ρσ_unpack[1];
            ans = ρσ_interpolate_kwargs.call(E, E.a, [img].concat([ρσ_desugar_kwargs({onclick: show_book_details, title: tooltip, href: href})]));
            return ans;
        };
        if (!create_item.__argnames__) Object.defineProperties(create_item, {
            __argnames__ : {value: ["book_id", "metadata", "create_image", "show_book_details", "href"]}
        });

        function append_item(container, item) {
            var first_filler;
            first_filler = container.lastChild.querySelector(".cover-grid-filler");
            container.lastChild.insertBefore(item, first_filler);
        };
        if (!append_item.__argnames__) Object.defineProperties(append_item, {
            __argnames__ : {value: ["container", "item"]}
        });

        ρσ_modules["book_list.cover_grid"].COVER_GRID_CLASS = COVER_GRID_CLASS;
        ρσ_modules["book_list.cover_grid"].THUMBNAIL_MAX_WIDTH = THUMBNAIL_MAX_WIDTH;
        ρσ_modules["book_list.cover_grid"].THUMBNAIL_MAX_HEIGHT = THUMBNAIL_MAX_HEIGHT;
        ρσ_modules["book_list.cover_grid"].THUMBNAIL_MIN_WIDTH = THUMBNAIL_MIN_WIDTH;
        ρσ_modules["book_list.cover_grid"].THUMBNAIL_MIN_HEIGHT = THUMBNAIL_MIN_HEIGHT;
        ρσ_modules["book_list.cover_grid"].BORDER_RADIUS = BORDER_RADIUS;
        ρσ_modules["book_list.cover_grid"].description = description;
        ρσ_modules["book_list.cover_grid"].cover_grid_css = cover_grid_css;
        ρσ_modules["book_list.cover_grid"].init = init;
        ρσ_modules["book_list.cover_grid"].on_img_load = on_img_load;
        ρσ_modules["book_list.cover_grid"].create_item = create_item;
        ρσ_modules["book_list.cover_grid"].append_item = append_item;
    })();

    (function(){
        var __name__ = "book_list.details_list";
        var DETAILS_LIST_CLASS, ITEM_CLASS, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, BORDER_RADIUS;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_color = ρσ_modules["book_list.theme"].get_color;

        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var set_css = ρσ_modules.dom.set_css;
        var svgicon = ρσ_modules.dom.svgicon;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        var fmt_sidx = ρσ_modules.utils.fmt_sidx;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;
        var sandboxed_html = ρσ_modules.utils.sandboxed_html;

        DETAILS_LIST_CLASS = "book-list-details-list";
        ITEM_CLASS = DETAILS_LIST_CLASS + "-item";
        function description() {
            return _("A list with thumbnails and some book details");
        };

        THUMBNAIL_MAX_WIDTH = 35 * 3;
        THUMBNAIL_MAX_HEIGHT = 35 * 4;
        BORDER_RADIUS = 6;
        function details_list_css() {
            var ans, sel, s, top, extra_data, narrow_style;
            ans = "";
            sel = "." + DETAILS_LIST_CLASS;
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({cursor: "pointer", user_select: "none"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " > div"].concat([ρσ_desugar_kwargs({margin: "1ex 1em", padding_bottom: "1ex", border_bottom: "solid 1px currentColor"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, ["" + ρσ_str.format("{}", sel) + " ." + ρσ_str.format("{}", ITEM_CLASS) + ":hover .details-list-left"].concat([ρσ_desugar_kwargs({transform: "scale(1.2)"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, ["" + ρσ_str.format("{}", sel) + " ." + ρσ_str.format("{}", ITEM_CLASS) + ":active .details-list-left"].concat([ρσ_desugar_kwargs({transform: "scale(2)"})]));
            s = sel + " .details-list-left";
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [s].concat([ρσ_desugar_kwargs({margin_right: "1em", min_width: "" + ρσ_str.format("{}", THUMBNAIL_MAX_WIDTH) + "px"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [s + " > img"].concat([ρσ_desugar_kwargs({border_radius: BORDER_RADIUS + "px", max_height: "" + ρσ_str.format("{}", THUMBNAIL_MAX_HEIGHT) + "px", max_width: "" + ρσ_str.format("{}", THUMBNAIL_MAX_WIDTH) + "px"})]));
            s = sel + " .details-list-right";
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [s].concat([ρσ_desugar_kwargs({flex_grow: "10", overflow: "hidden", display: "flex", flex_direction: "column"})]));
            top = s + " > div:first-child";
            extra_data = top + " > div:last-child";
            ans += "" + ρσ_str.format("{}", extra_data) + " { text-align: right }";
            narrow_style = "" + ρσ_str.format("{}", s) + " iframe { display: none } " + ρσ_str.format("{}", top) + " { flex-direction: column } " + ρσ_str.format("{}", extra_data) + " { text-align: left; margin-top: 1ex }";
            ans += "@media (max-width: 450px) { " + ρσ_str.format("{}", narrow_style) + " }";
            s += " iframe";
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [s].concat([ρσ_desugar_kwargs({flex_grow: "10", height: "50px", cursor: "pointer", pointer_events: "none"})]));
            return ans;
        };

        function init(container) {
            clear(container);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: DETAILS_LIST_CLASS})]));
        };
        if (!init.__argnames__) Object.defineProperties(init, {
            __argnames__ : {value: ["container"]}
        });

        function on_img_load(img, load_type) {
            var div;
            div = img.parentNode;
            if (!div) {
                return;
            }
            if (load_type !== "load") {
                clear(div);
                div.appendChild(E.div(ρσ_interpolate_kwargs.call(E, E.h2, [img.dataset.title].concat([ρσ_desugar_kwargs({style: "text-align:center; font-size:larger; font-weight: bold"})])), ρσ_interpolate_kwargs.call(E, E.div, [_("by")].concat([ρσ_desugar_kwargs({style: "text-align: center"})])), ρσ_interpolate_kwargs.call(E, E.h2, [img.dataset.authors].concat([ρσ_desugar_kwargs({style: "text-align:center; font-size:larger; font-weight: bold"})]))));
                ρσ_interpolate_kwargs.call(this, set_css, [div].concat([ρσ_desugar_kwargs({border: "dashed 1px currentColor", border_radius: BORDER_RADIUS + "px"})]));
            }
        };
        if (!on_img_load.__argnames__) Object.defineProperties(on_img_load, {
            __argnames__ : {value: ["img", "load_type"]}
        });

        function sandbox_css() {
            if (!sandbox_css.ans) {
                sandbox_css.ans = "html {{ overflow: hidden; color: {} }}".format(get_color("window-foreground"));
            }
            return sandbox_css.ans;
        };

        function create_item(book_id, metadata, create_image, show_book_details, href) {
            var authors, img, ρσ_unpack, img_div, extra_data, comments, interface_data, stars, i, ival, right, ans;
            authors = (metadata.authors) ? metadata.authors.join(" & ") : _("Unknown");
            img = create_image(book_id, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, on_img_load);
            img.setAttribute("alt", _("{} by {}").format(metadata.title, authors));
            ρσ_unpack = [metadata.title, authors];
            img.dataset.title = ρσ_unpack[0];
            img.dataset.authors = ρσ_unpack[1];
            img_div = ρσ_interpolate_kwargs.call(E, E.div, [img].concat([ρσ_desugar_kwargs({class_: "details-list-left"})]));
            extra_data = E.div();
            comments = sandboxed_html(metadata.comments, sandbox_css());
            if (!metadata.comments) {
                comments.style.display = "none";
            }
            comments.style.marginTop = "1ex";
            interface_data = get_interface_data();
            if (metadata.rating) {
                stars = ρσ_interpolate_kwargs.call(E, E.span, [ρσ_desugar_kwargs({style: "white-space:nowrap"})]);
                var ρσ_Iter0 = ρσ_Iterable(range(Math.floor(int(metadata.rating) / 2)));
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    i = ρσ_Iter0[ρσ_Index0];
                    stars.appendChild(svgicon("star"));
                }
                [extra_data.appendChild(stars), extra_data.appendChild(E.br())];
            }
            if (metadata.series) {
                try {
                    ival = float(metadata.series_index);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        ival = 1;
                    } else {
                        throw ρσ_Exception;
                    }
                }
                ival = ρσ_interpolate_kwargs.call(this, fmt_sidx, [ival].concat([ρσ_desugar_kwargs({use_roman: interface_data.use_roman_numerals_for_series_number})]));
                extra_data.appendChild(safe_set_inner_html(E.span(), _("{0} of <i>{1}</i>").format(ival, metadata.series)));
            }
            right = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [E.div(E.b(metadata.title || _("Unknown")), E.br(), authors), extra_data].concat([ρσ_desugar_kwargs({style: "display:flex; justify-content: space-between; overflow: hidden"})])), comments].concat([ρσ_desugar_kwargs({class_: "details-list-right"})]));
            ans = E.div(ρσ_interpolate_kwargs.call(E, E.a, [img_div, right].concat([ρσ_desugar_kwargs({href: href, style: "height:" + ρσ_str.format("{}", THUMBNAIL_MAX_HEIGHT) + "px; display: flex", class_: ITEM_CLASS})])));
            ans.addEventListener("click", show_book_details, true);
            return ans;
        };
        if (!create_item.__argnames__) Object.defineProperties(create_item, {
            __argnames__ : {value: ["book_id", "metadata", "create_image", "show_book_details", "href"]}
        });

        function append_item(container, item) {
            container.lastChild.appendChild(item);
        };
        if (!append_item.__argnames__) Object.defineProperties(append_item, {
            __argnames__ : {value: ["container", "item"]}
        });

        ρσ_modules["book_list.details_list"].DETAILS_LIST_CLASS = DETAILS_LIST_CLASS;
        ρσ_modules["book_list.details_list"].ITEM_CLASS = ITEM_CLASS;
        ρσ_modules["book_list.details_list"].THUMBNAIL_MAX_WIDTH = THUMBNAIL_MAX_WIDTH;
        ρσ_modules["book_list.details_list"].THUMBNAIL_MAX_HEIGHT = THUMBNAIL_MAX_HEIGHT;
        ρσ_modules["book_list.details_list"].BORDER_RADIUS = BORDER_RADIUS;
        ρσ_modules["book_list.details_list"].description = description;
        ρσ_modules["book_list.details_list"].details_list_css = details_list_css;
        ρσ_modules["book_list.details_list"].init = init;
        ρσ_modules["book_list.details_list"].on_img_load = on_img_load;
        ρσ_modules["book_list.details_list"].sandbox_css = sandbox_css;
        ρσ_modules["book_list.details_list"].create_item = create_item;
        ρσ_modules["book_list.details_list"].append_item = append_item;
    })();

    (function(){
        var __name__ = "date";
        var UNDEFINED_DATE_ISO, UNDEFINED_DATE, lcdata, supports_locales, _fmt_date_pat, fd_function_index;
        UNDEFINED_DATE_ISO = "0101-01-01T00:00:00+00:00";
        UNDEFINED_DATE = new Date(UNDEFINED_DATE_ISO);
        function is_date_undefined(date) {
            var ρσ_unpack, dy, uy;
            ρσ_unpack = [date.getUTCFullYear(), UNDEFINED_DATE.getUTCFullYear()];
            dy = ρσ_unpack[0];
            uy = ρσ_unpack[1];
            return dy < uy || dy === uy && date.getUTCMonth() === UNDEFINED_DATE.getUTCMonth() && date.getUTCDate() <= UNDEFINED_DATE.getUTCDate() + 1;
        };
        if (!is_date_undefined.__argnames__) Object.defineProperties(is_date_undefined, {
            __argnames__ : {value: ["date"]}
        });

        lcdata = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["abday"] = ρσ_list_decorate([ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]);
            ρσ_d["abmon"] = ρσ_list_decorate([ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]);
            ρσ_d["day"] = ρσ_list_decorate([ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]);
            ρσ_d["mon"] = ρσ_list_decorate([ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]);
            return ρσ_d;
        }).call(this);
        supports_locales = false;
        try {
            (new Date).toLocaleString("dfkjghdfkgj");
        } catch (ρσ_Exception) {
            ρσ_last_exception = ρσ_Exception;
            if (ρσ_Exception instanceof RangeError) {
                supports_locales = true;
            } else {
            } 
        }
        _fmt_date_pat = null;
        function fmt_date_pat() {
            if (!_fmt_date_pat) {
                _fmt_date_pat = /(s{1,2})|(m{1,2})|(h{1,2})|(ap)|(AP)|(d{1,4}|M{1,4}|(?:yyyy|yy))/g;
            }
            return _fmt_date_pat;
        };

        function fd_format_hour(dt, ampm, hr, as_utc) {
            var h;
            h = (as_utc) ? dt.getUTCHours() : dt.getHours();
            if (ampm) {
                h = h % 12;
            }
            return (hr.length === 1) ? h.toString() : str.format("{:02d}", h);
        };
        if (!fd_format_hour.__argnames__) Object.defineProperties(fd_format_hour, {
            __argnames__ : {value: ["dt", "ampm", "hr", "as_utc"]}
        });

        function fd_format_minute(dt, ampm, min, as_utc) {
            var m;
            m = (as_utc) ? dt.getUTCMinutes() : dt.getMinutes();
            return (min.length === 1) ? m.toString() : str.format("{:02d}", m);
        };
        if (!fd_format_minute.__argnames__) Object.defineProperties(fd_format_minute, {
            __argnames__ : {value: ["dt", "ampm", "min", "as_utc"]}
        });

        function fd_format_second(dt, ampm, min, as_utc) {
            var s;
            s = (as_utc) ? dt.getUTCSeconds() : dt.getSeconds();
            return (min.length === 1) ? s.toString() : str.format("{:02d}", s);
        };
        if (!fd_format_second.__argnames__) Object.defineProperties(fd_format_second, {
            __argnames__ : {value: ["dt", "ampm", "min", "as_utc"]}
        });

        function fd_format_ampm(dt, ampm, ap, as_utc) {
            var h, ans;
            h = (as_utc) ? dt.getUTCHours() : dt.getHours();
            ans = (h < 12) ? "am" : "pm";
            return (ap === "ap") ? ans : ans.toUpperCase();
        };
        if (!fd_format_ampm.__argnames__) Object.defineProperties(fd_format_ampm, {
            __argnames__ : {value: ["dt", "ampm", "ap", "as_utc"]}
        });

        function fd_format_day(dt, ampm, dy, as_utc) {
            var d, options, w;
            d = (as_utc) ? dt.getUTCDate() : dt.getDate();
            if (dy.length === 1) {
                return d.toString();
            }
            if (dy.length === 2) {
                return str.format("{:02d}", d);
            }
            if (supports_locales) {
                options = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["weekday"] = (dy.length === 3) ? "short" : "long";
                    return ρσ_d;
                }).call(this);
                if (as_utc) {
                    options["timeZone"] = "UTC";
                }
                return dt.toLocaleString(window.navigator.language, options);
            }
            w = (as_utc) ? dt.getUTCDay() : dt.getDay();
            return (ρσ_expr_temp = lcdata[ρσ_bound_index((dy.length === 3) ? "abday" : "day", lcdata)])[ρσ_bound_index((w + 1) % 7, ρσ_expr_temp)];
        };
        if (!fd_format_day.__argnames__) Object.defineProperties(fd_format_day, {
            __argnames__ : {value: ["dt", "ampm", "dy", "as_utc"]}
        });

        function fd_format_month(dt, ampm, mo, as_utc) {
            var m, options;
            m = (as_utc) ? dt.getUTCMonth() : dt.getMonth();
            if (mo.length === 1) {
                return (m + 1).toString();
            }
            if (mo.length === 2) {
                return str.format("{:02d}", m + 1);
            }
            if (supports_locales) {
                options = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["month"] = (ρσ_expr_temp = (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d[1] = "numeric";
                        ρσ_d[2] = "2-digit";
                        ρσ_d[3] = "short";
                        ρσ_d[4] = "long";
                        return ρσ_d;
                    }).call(this))[ρσ_bound_index(mo.length, ρσ_expr_temp)] || "long";
                    return ρσ_d;
                }).call(this);
                if (as_utc) {
                    options["timeZone"] = "UTC";
                }
                return dt.toLocaleString(window.navigator.language, options);
            }
            return (ρσ_expr_temp = lcdata[ρσ_bound_index((mo.length === 3) ? "abmon" : "mon", lcdata)])[(typeof m === "number" && m < 0) ? ρσ_expr_temp.length + m : m];
        };
        if (!fd_format_month.__argnames__) Object.defineProperties(fd_format_month, {
            __argnames__ : {value: ["dt", "ampm", "mo", "as_utc"]}
        });

        function fd_format_year(dt, ampm, yr, as_utc) {
            var y;
            y = (as_utc) ? dt.getUTCFullYear() : dt.getFullYear();
            if (yr.length === 2) {
                return str.format("{:02d}", y % 100);
            }
            return str.format("{:04d}", y);
        };
        if (!fd_format_year.__argnames__) Object.defineProperties(fd_format_year, {
            __argnames__ : {value: ["dt", "ampm", "yr", "as_utc"]}
        });

        fd_function_index = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["d"] = fd_format_day;
            ρσ_d["M"] = fd_format_month;
            ρσ_d["y"] = fd_format_year;
            ρσ_d["h"] = fd_format_hour;
            ρσ_d["m"] = fd_format_minute;
            ρσ_d["s"] = fd_format_second;
            ρσ_d["a"] = fd_format_ampm;
            ρσ_d["A"] = fd_format_ampm;
            return ρσ_d;
        }).call(this);
        function test_fd(date, fmt, ans) {
            var q;
            q = ρσ_interpolate_kwargs.call(this, format_date, [date, fmt].concat([ρσ_desugar_kwargs({as_utc: true})]));
            if (q !== ans) {
                throw new Exception(str.format("Failed to format {} with {}: {} is not {}", date, fmt, q, ans));
            }
        };
        if (!test_fd.__argnames__) Object.defineProperties(test_fd, {
            __argnames__ : {value: ["date", "fmt", "ans"]}
        });

        function format_date() {
            var date = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? format_date.__defaults__.date : arguments[0];
            var fmt = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? format_date.__defaults__.fmt : arguments[1];
            var as_utc = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? format_date.__defaults__.as_utc : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "date")){
                date = ρσ_kwargs_obj.date;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "fmt")){
                fmt = ρσ_kwargs_obj.fmt;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "as_utc")){
                as_utc = ρσ_kwargs_obj.as_utc;
            }
            var ampm;
            fmt = fmt || "dd MMM yyyy";
            ampm = ρσ_in("ap", fmt.toLowerCase());
            if (typeof date === "string") {
                date = new Date(date);
            }
            date = date || new Date;
            if (is_date_undefined(date)) {
                return "";
            }
            return fmt.replace(fmt_date_pat(), (function() {
                var ρσ_anonfunc = function (match) {
                    if (!match) {
                        return "";
                    }
                    try {
                        return fd_function_index[ρσ_bound_index(match[0], fd_function_index)](date, ampm, match, as_utc);
                    } catch (ρσ_Exception) {
                        ρσ_last_exception = ρσ_Exception;
                        if (ρσ_Exception instanceof Error) {
                            print(str.format("Failed to format date with format: {} and match: {}", fmt, match));
                            return "";
                        } else {
                            throw ρσ_Exception;
                        }
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["match"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!format_date.__defaults__) Object.defineProperties(format_date, {
            __defaults__ : {value: {date:null, fmt:"dd MMM yyyy", as_utc:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["date", "fmt", "as_utc"]}
        });

        if (__name__ === "__main__") {
            test_fd("1101-01-01T09:00:00+00:00", "hh h", "09 9");
            test_fd("1101-01-01T09:05:01+00:00", "hh h mm m ss s ap AP yy yyyy", "09 9 05 5 01 1 am AM 01 1101");
            test_fd("2001-01-02T09:00:00+00:00", "M MM MMM MMMM", "1 01 Jan January");
            test_fd("2001-01-01T12:00:00+00:00", "d dd ddd dddd", "1 01 Mon Monday");
        }
        ρσ_modules.date.UNDEFINED_DATE_ISO = UNDEFINED_DATE_ISO;
        ρσ_modules.date.UNDEFINED_DATE = UNDEFINED_DATE;
        ρσ_modules.date.lcdata = lcdata;
        ρσ_modules.date.supports_locales = supports_locales;
        ρσ_modules.date._fmt_date_pat = _fmt_date_pat;
        ρσ_modules.date.fd_function_index = fd_function_index;
        ρσ_modules.date.is_date_undefined = is_date_undefined;
        ρσ_modules.date.fmt_date_pat = fmt_date_pat;
        ρσ_modules.date.fd_format_hour = fd_format_hour;
        ρσ_modules.date.fd_format_minute = fd_format_minute;
        ρσ_modules.date.fd_format_second = fd_format_second;
        ρσ_modules.date.fd_format_ampm = fd_format_ampm;
        ρσ_modules.date.fd_format_day = fd_format_day;
        ρσ_modules.date.fd_format_month = fd_format_month;
        ρσ_modules.date.fd_format_year = fd_format_year;
        ρσ_modules.date.test_fd = test_fd;
        ρσ_modules.date.format_date = format_date;
    })();

    (function(){
        var __name__ = "book_list.custom_list";
        var CUSTOM_LIST_CLASS, ITEM_CLASS;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var sandbox_css = ρσ_modules["book_list.details_list"].sandbox_css;
        var BORDER_RADIUS = ρσ_modules["book_list.details_list"].BORDER_RADIUS;

        var library_data = ρσ_modules["book_list.library_data"].library_data;

        var format_date = ρσ_modules.date.format_date;

        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var set_css = ρσ_modules.dom.set_css;
        var svgicon = ρσ_modules.dom.svgicon;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        var fmt_sidx = ρσ_modules.utils.fmt_sidx;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;
        var sandboxed_html = ρσ_modules.utils.sandboxed_html;

        CUSTOM_LIST_CLASS = "book-list-custom-list";
        ITEM_CLASS = CUSTOM_LIST_CLASS + "-item";
        function description() {
            return _("A customizable list (see Preferences->Sharing over the net->Book list template)");
        };

        function custom_list_css() {
            var ans, sel, s;
            ans = "";
            sel = "." + CUSTOM_LIST_CLASS;
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({cursor: "pointer", user_select: "none"})]));
            sel += " ." + ITEM_CLASS;
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({margin: "1ex 1em", padding_bottom: "1ex", border_bottom: "solid 1px currentColor"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, ["" + ρσ_str.format("{}", sel) + ":hover .custom-list-left"].concat([ρσ_desugar_kwargs({transform: "scale(1.2)"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, ["" + ρσ_str.format("{}", sel) + ":active .custom-list-left"].concat([ρσ_desugar_kwargs({transform: "scale(2)"})]));
            s = sel + " .custom-list-left";
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [s].concat([ρσ_desugar_kwargs({margin_right: "1em"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [s + " > img"].concat([ρσ_desugar_kwargs({border_radius: BORDER_RADIUS + "px"})]));
            sel += " iframe";
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({flex_grow: "10", cursor: "pointer", pointer_events: "none"})]));
            return ans;
        };

        function default_template() {
            if (!default_template.ans) {
                default_template.ans = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["thumbnail"] = true;
                    ρσ_d["thumbnail_height"] = 140;
                    ρσ_d["height"] = "auto";
                    ρσ_d["comments_fields"] = ['comments'];
                    ρσ_d["lines"] = ρσ_list_decorate([ _("<b>{title}</b> by {authors}"), _("{series_index} of <i>{series}</i>") + "|||{rating}", "{tags}", _("Date: {timestamp}") + "|||" + _("Published: {pubdate}") + "|||" + _("Publisher: {publisher}"), "" ]);
                    return ρσ_d;
                }).call(this);
            }
            return default_template.ans;
        };

        function render_field(field, mi, book_id) {
            var field_metadata, fm, val, interface_data, name, datatype, func, ans, join, fmt;
            if (field === "id") {
                return book_id + "";
            }
            field_metadata = library_data.field_metadata;
            fm = field_metadata[(typeof field === "number" && field < 0) ? field_metadata.length + field : field];
            if (!fm) {
                return;
            }
            val = mi[(typeof field === "number" && field < 0) ? mi.length + field : field];
            if (val === undefined || val === null) {
                return;
            }
            interface_data = get_interface_data();
            function add_val() {
                var val = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
                var is_html = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? add_val.__defaults__.is_html : arguments[1];
                var join = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? add_val.__defaults__.join : arguments[2];
                var ρσ_kwargs_obj = arguments[arguments.length-1];
                if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
                if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "is_html")){
                    is_html = ρσ_kwargs_obj.is_html;
                }
                if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "join")){
                    join = ρσ_kwargs_obj.join;
                }
                if (is_html && /[<>]/.test(val + "")) {
                    return safe_set_inner_html(E.span(), val);
                }
                if (join) {
                    val = val.join(join);
                } else {
                    val += "";
                }
                return val;
            };
            if (!add_val.__defaults__) Object.defineProperties(add_val, {
                __defaults__ : {value: {is_html:false, join:null}},
                __handles_kwarg_interpolation__ : {value: true},
                __argnames__ : {value: ["val", "is_html", "join"]}
            });

            function process_composite(field, fm, name, val) {
                var all_vals;
                if (fm.display && fm.display.contains_html) {
                    return ρσ_interpolate_kwargs.call(this, add_val, [val].concat([ρσ_desugar_kwargs({is_html: true})]));
                }
                if (fm.is_multiple && fm.is_multiple.list_to_ui) {
                    all_vals = filter(null, map(str.strip, val.split(fm.is_multiple.list_to_ui)));
                    return ρσ_interpolate_kwargs.call(this, add_val, [all_vals].concat([ρσ_desugar_kwargs({join: fm.is_multiple.list_to_ui})]));
                }
                return add_val(val);
            };
            if (!process_composite.__argnames__) Object.defineProperties(process_composite, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_authors(field, fm, name, val) {
                return ρσ_interpolate_kwargs.call(this, add_val, [val].concat([ρσ_desugar_kwargs({join: " & "})]));
            };
            if (!process_authors.__argnames__) Object.defineProperties(process_authors, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_publisher(field, fm, name, val) {
                return add_val(val);
            };
            if (!process_publisher.__argnames__) Object.defineProperties(process_publisher, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_formats(field, fm, name, val) {
                return ρσ_interpolate_kwargs.call(this, add_val, [val].concat([ρσ_desugar_kwargs({join: ", "})]));
            };
            if (!process_formats.__argnames__) Object.defineProperties(process_formats, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_rating(field, fm, name, val) {
                var stars, i;
                stars = E.span();
                val = int(val || 0);
                if (val > 0) {
                    for (var ρσ_Index0 = 0; ρσ_Index0 < Math.floor(val / 2); ρσ_Index0++) {
                        i = ρσ_Index0;
                        stars.appendChild(svgicon("star"));
                    }
                    if (fm.display.allow_half_stars && val % 2) {
                        stars.appendChild(svgicon("star-half"));
                    }
                    return stars;
                }
            };
            if (!process_rating.__argnames__) Object.defineProperties(process_rating, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_identifiers(field, fm, name, val) {
                var keys, ans, key;
                if (val) {
                    keys = Object.keys(val);
                    if (keys.length) {
                        ans = [];
                        var ρσ_Iter1 = ρσ_Iterable(keys);
                        for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                            key = ρσ_Iter1[ρσ_Index1];
                            ans.push(key + ":" + val[(typeof key === "number" && key < 0) ? val.length + key : key]);
                        }
                        return ρσ_interpolate_kwargs.call(this, add_val, [ans].concat([ρσ_desugar_kwargs({join: ", "})]));
                    }
                }
            };
            if (!process_identifiers.__argnames__) Object.defineProperties(process_identifiers, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_languages(field, fm, name, val) {
                var langs, k;
                if (val && val.length) {
                    langs = (function() {
                        var ρσ_Iter = ρσ_Iterable(val), ρσ_Result = [], k;
                        for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                            k = ρσ_Iter[ρσ_Index];
                            ρσ_Result.push((ρσ_expr_temp = mi.lang_names)[(typeof k === "number" && k < 0) ? ρσ_expr_temp.length + k : k]);
                        }
                        ρσ_Result = ρσ_list_constructor(ρσ_Result);
                        return ρσ_Result;
                    })();
                    return ρσ_interpolate_kwargs.call(this, add_val, [langs].concat([ρσ_desugar_kwargs({join: ", "})]));
                }
            };
            if (!process_languages.__argnames__) Object.defineProperties(process_languages, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_datetime(field, fm, name, val) {
                var fmt;
                if (val) {
                    fmt = interface_data[ρσ_bound_index("gui_" + field + "_display_format", interface_data)] || (fm["display"] || Object.create(null)).date_format;
                    return add_val(format_date(val, fmt));
                }
            };
            if (!process_datetime.__argnames__) Object.defineProperties(process_datetime, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_series(field, fm, name, val) {
                if (val) {
                    return add_val(val);
                }
            };
            if (!process_series.__argnames__) Object.defineProperties(process_series, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_series_index(field, fm, name, val) {
                var sval;
                sval = mi[ρσ_bound_index(field.slice(0, -6), mi)];
                if (sval) {
                    if (val === null || val === undefined) {
                        val = 1;
                    }
                    return ρσ_interpolate_kwargs.call(this, fmt_sidx, [val].concat([ρσ_desugar_kwargs({use_roman: interface_data.use_roman_numerals_for_series_number})]));
                }
            };
            if (!process_series_index.__argnames__) Object.defineProperties(process_series_index, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_size(field, fm, name, val) {
                var mb;
                val = val || 0;
                mb = 1024 * 1024;
                function fmt(val, suffix) {
                    var ans;
                    ans = "" + ρσ_str.format("{:.1f}", val) + "";
                    if (ans.endsWith(".0")) {
                        ans = ans.slice(0, -2);
                    }
                    return ans + suffix;
                };
                if (!fmt.__argnames__) Object.defineProperties(fmt, {
                    __argnames__ : {value: ["val", "suffix"]}
                });

                if (val < mb) {
                    return fmt(val / 1024, "KB");
                }
                return fmt(val / mb, "MB");
            };
            if (!process_size.__argnames__) Object.defineProperties(process_size, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            name = fm.name || field;
            datatype = fm.datatype;
            if (field === "comments" || datatype === "comments") {
                return;
            }
            func = null;
            if (datatype === "composite") {
                func = process_composite;
            } else if (field === "formats") {
                func = process_formats;
            } else if (datatype === "rating") {
                func = process_rating;
            } else if (field === "identifiers") {
                func = process_identifiers;
            } else if (field === "authors") {
                func = process_authors;
            } else if (field === "publisher") {
                func = process_publisher;
            } else if (field === "languages") {
                func = process_languages;
            } else if (datatype === "datetime") {
                func = process_datetime;
            } else if (datatype === "series") {
                func = process_series;
            } else if (field.endswith("_index")) {
                func = process_series_index;
            } else if (field === "size") {
                func = process_size;
            }
            ans = null;
            if (func) {
                ans = func(field, fm, name, val);
            } else {
                if (datatype === "text" || datatype === "enumeration") {
                    if (val !== undefined && val !== null) {
                        join = (fm.is_multiple) ? fm.is_multiple.list_to_ui : null;
                        ans = ρσ_interpolate_kwargs.call(this, add_val, [val].concat([ρσ_desugar_kwargs({join: join})]));
                    }
                } else if (datatype === "bool") {
                    ans = add_val((val) ? _("Yes") : _("No"));
                } else if (datatype === "int" || datatype === "float") {
                    if (val !== undefined && val !== null) {
                        fmt = (fm.display || Object.create(null)).number_format;
                        if (fmt) {
                            val = fmt.format(val);
                        } else {
                            val += "";
                        }
                        ans = add_val(val);
                    }
                }
            }
            return ans;
        };
        if (!render_field.__argnames__) Object.defineProperties(render_field, {
            __argnames__ : {value: ["field", "mi", "book_id"]}
        });

        function render_part(part, template, book_id, metadata) {
            var count, rendered_count, ans, walk, replacements, n, rendered, val, field, ρσ_unpack, new_child, old_child;
            count = rendered_count = 0;
            ans = E.div();
            ans.innerHTML = part;
            walk = document.createTreeWalker(ans, NodeFilter.SHOW_TEXT, null, false);
            replacements = [];
            while (true) {
                n = walk.nextNode();
                if (!n) {
                    break;
                }
                rendered = E.span();
                var ρσ_Iter2 = ρσ_Iterable(n.nodeValue.split(/({#?[_a-z0-9]+})/));
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    field = ρσ_Iter2[ρσ_Index2];
                    if (field[0] === "{" && field[field.length-1] === "}") {
                        count += 1;
                        val = render_field(field.slice(1, -1), metadata, book_id);
                        if (val) {
                            rendered_count += 1;
                            if (typeof val === "string") {
                                val = document.createTextNode(val);
                            }
                            rendered.appendChild(val);
                        }
                    } else {
                        rendered.appendChild(document.createTextNode(field));
                    }
                }
                replacements.push([rendered, n]);
            }
            var ρσ_Iter3 = ρσ_Iterable(replacements);
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                ρσ_unpack = ρσ_Iter3[ρσ_Index3];
                new_child = ρσ_unpack[0];
                old_child = ρσ_unpack[1];
                old_child.parentNode.replaceChild(new_child, old_child);
            }
            if (count && !rendered_count) {
                return;
            }
            return ans;
        };
        if (!render_part.__argnames__) Object.defineProperties(render_part, {
            __argnames__ : {value: ["part", "template", "book_id", "metadata"]}
        });

        function render_line(line, template, book_id, metadata) {
            var parts, part, p, ans;
            parts = [];
            line = line || " ";
            var ρσ_Iter4 = ρσ_Iterable(line.split(/\|\|\|/));
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                p = ρσ_Iter4[ρσ_Index4];
                part = render_part(p, template, book_id, metadata);
                if (part) {
                    parts.push(part);
                }
            }
            if (!parts.length) {
                return;
            }
            ans = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: "custom-line"})]);
            var ρσ_Iter5 = ρσ_Iterable(parts);
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                p = ρσ_Iter5[ρσ_Index5];
                ans.appendChild(p);
            }
            if (parts.length > 1) {
                ρσ_interpolate_kwargs.call(this, set_css, [ans].concat([ρσ_desugar_kwargs({display: "flex", justify_content: "space-between"})]));
            }
            return ans;
        };
        if (!render_line.__argnames__) Object.defineProperties(render_line, {
            __argnames__ : {value: ["line", "template", "book_id", "metadata"]}
        });

        function render_template_text(template, book_id, metadata) {
            var ans, ldiv, line, html, val, f, comments;
            ans = E.div();
            var ρσ_Iter6 = ρσ_Iterable(template.lines);
            for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                line = ρσ_Iter6[ρσ_Index6];
                ldiv = render_line(line, template, book_id, metadata);
                if (ldiv) {
                    ans.appendChild(ldiv);
                }
            }
            if (template.comments_fields.length) {
                html = "";
                var ρσ_Iter7 = ρσ_Iterable(template.comments_fields);
                for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                    f = ρσ_Iter7[ρσ_Index7];
                    val = metadata[(typeof f === "number" && f < 0) ? metadata.length + f : f];
                    if (val) {
                        html += "<div style=\"margin-bottom:1.5ex\">" + ρσ_str.format("{}", val) + "</div>";
                    }
                }
                if (html) {
                    comments = sandboxed_html(html, sandbox_css());
                    ans.appendChild(comments);
                }
            }
            return ans;
        };
        if (!render_template_text.__argnames__) Object.defineProperties(render_template_text, {
            __argnames__ : {value: ["template", "book_id", "metadata"]}
        });

        function init(container) {
            clear(container);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: CUSTOM_LIST_CLASS})]));
        };
        if (!init.__argnames__) Object.defineProperties(init, {
            __argnames__ : {value: ["container"]}
        });

        function on_img_load(img, load_type) {
            var div;
            div = img.parentNode;
            if (!div) {
                return;
            }
            if (load_type !== "load") {
                clear(div);
                div.appendChild(E.div(ρσ_interpolate_kwargs.call(E, E.h2, [img.dataset.title].concat([ρσ_desugar_kwargs({style: "text-align:center; font-size:larger; font-weight: bold"})])), ρσ_interpolate_kwargs.call(E, E.div, [_("by")].concat([ρσ_desugar_kwargs({style: "text-align: center"})])), ρσ_interpolate_kwargs.call(E, E.h2, [img.dataset.authors].concat([ρσ_desugar_kwargs({style: "text-align:center; font-size:larger; font-weight: bold"})]))));
                ρσ_interpolate_kwargs.call(this, set_css, [div].concat([ρσ_desugar_kwargs({border: "dashed 1px currentColor", border_radius: BORDER_RADIUS + "px"})]));
            }
        };
        if (!on_img_load.__argnames__) Object.defineProperties(on_img_load, {
            __argnames__ : {value: ["img", "load_type"]}
        });

        function create_item(book_id, metadata, create_image, show_book_details, href) {
            var template, text_data, height, extra, ans, h, w, img, authors, ρσ_unpack, img_div;
            template = get_interface_data().custom_list_template || default_template();
            text_data = render_template_text(template, book_id, metadata);
            text_data.style.flexGrow = "10";
            text_data.style.overflow = "hidden";
            if (template.thumbnail) {
                height = "" + ρσ_str.format("{}", template.thumbnail_height) + "px";
            } else {
                if (template.height === "auto") {
                    extra = (template.comments_fields.length) ? 5 : 1;
                    height = template.lines.length * 2.5 + extra + "ex";
                } else {
                    height = template.height;
                    if (typeof height === "number") {
                        height += "px";
                    }
                }
            }
            ans = ρσ_interpolate_kwargs.call(E, E.a, [ρσ_desugar_kwargs({style: "height:" + ρσ_str.format("{}", height) + "; display: flex", class_: ITEM_CLASS, href: href})]);
            if (template.thumbnail) {
                h = template.thumbnail_height;
                w = int(.75 * h);
                img = create_image(book_id, w, h, on_img_load);
                authors = (metadata.authors) ? metadata.authors.join(" & ") : _("Unknown");
                img.setAttribute("alt", _("{} by {}").format(metadata.title, authors));
                ρσ_unpack = [metadata.title, authors];
                img.dataset.title = ρσ_unpack[0];
                img.dataset.authors = ρσ_unpack[1];
                img.style.maxWidth = w + "px";
                img.style.maxHeight = h + "px";
                img_div = ρσ_interpolate_kwargs.call(E, E.div, [img].concat([ρσ_desugar_kwargs({class_: "custom-list-left", style: "min-width: " + ρσ_str.format("{}", w) + "px"})]));
                ans.appendChild(img_div);
            }
            ans.appendChild(text_data);
            ans.addEventListener("click", show_book_details, true);
            return ans;
        };
        if (!create_item.__argnames__) Object.defineProperties(create_item, {
            __argnames__ : {value: ["book_id", "metadata", "create_image", "show_book_details", "href"]}
        });

        function append_item(container, item) {
            container.lastChild.appendChild(item);
        };
        if (!append_item.__argnames__) Object.defineProperties(append_item, {
            __argnames__ : {value: ["container", "item"]}
        });

        ρσ_modules["book_list.custom_list"].CUSTOM_LIST_CLASS = CUSTOM_LIST_CLASS;
        ρσ_modules["book_list.custom_list"].ITEM_CLASS = ITEM_CLASS;
        ρσ_modules["book_list.custom_list"].description = description;
        ρσ_modules["book_list.custom_list"].custom_list_css = custom_list_css;
        ρσ_modules["book_list.custom_list"].default_template = default_template;
        ρσ_modules["book_list.custom_list"].render_field = render_field;
        ρσ_modules["book_list.custom_list"].render_part = render_part;
        ρσ_modules["book_list.custom_list"].render_line = render_line;
        ρσ_modules["book_list.custom_list"].render_template_text = render_template_text;
        ρσ_modules["book_list.custom_list"].init = init;
        ρσ_modules["book_list.custom_list"].on_img_load = on_img_load;
        ρσ_modules["book_list.custom_list"].create_item = create_item;
        ρσ_modules["book_list.custom_list"].append_item = append_item;
    })();

    (function(){
        var __name__ = "book_list.prefs";
        var pp_counter, widget_counter, state;
        var clear = ρσ_modules.dom.clear;
        var ensure_id = ρσ_modules.dom.ensure_id;

        var E = ρσ_modules.elementmaker.E;

        var create_button = ρσ_modules.widgets.create_button;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var create_top_bar = ρσ_modules["book_list.top_bar"].create_top_bar;

        var back = ρσ_modules["book_list.router"].back;

        pp_counter = 0;
        widget_counter = 0;
        function ConfigItem() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            ConfigItem.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperties(ConfigItem.prototype,  {
            "container": {
                "enumerable": true, 
                "get": function container() {
                    var self = this;
                    return document.getElementById(self.widget_id);
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "control": {
                "enumerable": true, 
                "get": function control() {
                    var self = this;
                    return self.container.lastChild;
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        ConfigItem.prototype.__init__ = function __init__(item_data) {
            var self = this;
            widget_counter += 1;
            self.widget_id = "pref-widget-" + widget_counter;
            self.item_data = item_data;
            self.ignore_ui_value_changed = false;
        };
        if (!ConfigItem.prototype.__init__.__argnames__) Object.defineProperties(ConfigItem.prototype.__init__, {
            __argnames__ : {value: ["item_data"]}
        });
        ConfigItem.__argnames__ = ConfigItem.prototype.__init__.__argnames__;
        ConfigItem.__handles_kwarg_interpolation__ = ConfigItem.prototype.__init__.__handles_kwarg_interpolation__;
        ConfigItem.prototype.initialize = function initialize() {
            var self = this;
            self.ignore_ui_value_changed = true;
            try {
                self.to_ui(self.from_storage());
            } finally {
                self.ignore_ui_value_changed = false;
            }
            return self;
        };
        ConfigItem.prototype.from_storage = function from_storage() {
            var self = this;
            var val;
            val = get_session_data().get(self.item_data.name);
            if (self.item_data.from_storage) {
                val = self.item_data.from_storage(val);
            }
            return val;
        };
        ConfigItem.prototype.to_storage = function to_storage(val) {
            var self = this;
            if (self.item_data.to_storage) {
                val = self.item_data.to_storage(val);
            }
            get_session_data().set(self.item_data.name, val);
        };
        if (!ConfigItem.prototype.to_storage.__argnames__) Object.defineProperties(ConfigItem.prototype.to_storage, {
            __argnames__ : {value: ["val"]}
        });
        ConfigItem.prototype.defval = function defval() {
            var self = this;
            var val;
            val = get_session_data().defval(self.item_data.name);
            if (self.item_data.from_storage) {
                val = self.item_data.from_storage(val);
            }
            return val;
        };
        ConfigItem.prototype.ui_value_changed = function ui_value_changed() {
            var self = this;
            if (self.ignore_ui_value_changed) {
                return;
            }
            self.to_storage(self.from_ui());
        };
        ConfigItem.prototype.reset_to_default = function reset_to_default() {
            var self = this;
            self.to_ui(self.defval());
            self.ui_value_changed();
        };
        ConfigItem.prototype.to_ui = function to_ui(val) {
            var self = this;
        };
        if (!ConfigItem.prototype.to_ui.__argnames__) Object.defineProperties(ConfigItem.prototype.to_ui, {
            __argnames__ : {value: ["val"]}
        });
        ConfigItem.prototype.from_ui = function from_ui() {
            var self = this;
        };
        ConfigItem.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        ConfigItem.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(ConfigItem.prototype, "__bases__", {value: []});
        
        

        function Choices() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            Choices.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(Choices, ConfigItem);
        Choices.prototype.__init__ = function __init__(item_data, container, onfocus) {
            var self = this;
            var div, select, ρσ_unpack, choice, text;
            ConfigItem.prototype.__init__.call(self, item_data);
            div = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.span, [item_data.text + ": "].concat([ρσ_desugar_kwargs({style: "white-space:pre"})])), ρσ_interpolate_kwargs.call(E, E.select, [ρσ_desugar_kwargs({required: "1"})])].concat([ρσ_desugar_kwargs({id: self.widget_id})]));
            container.appendChild(div);
            select = div.lastChild;
            var ρσ_Iter0 = ρσ_Iterable(item_data.choices);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                ρσ_unpack = ρσ_Iter0[ρσ_Index0];
                choice = ρσ_unpack[0];
                text = ρσ_unpack[1];
                select.appendChild(ρσ_interpolate_kwargs.call(E, E.option, [text].concat([ρσ_desugar_kwargs({value: choice})])));
            }
            select.addEventListener("change", self.ui_value_changed.bind(self));
            select.addEventListener("focus", onfocus);
            div.addEventListener("click", onfocus);
        };
        if (!Choices.prototype.__init__.__argnames__) Object.defineProperties(Choices.prototype.__init__, {
            __argnames__ : {value: ["item_data", "container", "onfocus"]}
        });
        Choices.__argnames__ = Choices.prototype.__init__.__argnames__;
        Choices.__handles_kwarg_interpolation__ = Choices.prototype.__init__.__handles_kwarg_interpolation__;
        Choices.prototype.to_ui = function to_ui(val) {
            var self = this;
            self.control.value = val;
        };
        if (!Choices.prototype.to_ui.__argnames__) Object.defineProperties(Choices.prototype.to_ui, {
            __argnames__ : {value: ["val"]}
        });
        Choices.prototype.from_ui = function from_ui() {
            var self = this;
            return self.control.value;
        };
        Choices.prototype.__repr__ = function __repr__ () {
            if(ConfigItem.prototype.__repr__) return ConfigItem.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        Choices.prototype.__str__ = function __str__ () {
            if(ConfigItem.prototype.__str__) return ConfigItem.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(Choices.prototype, "__bases__", {value: [ConfigItem]});

        function CheckBox() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            CheckBox.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(CheckBox, ConfigItem);
        Object.defineProperties(CheckBox.prototype,  {
            "control": {
                "enumerable": true, 
                "get": function control() {
                    var self = this;
                    return self.container.firstChild;
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        CheckBox.prototype.__init__ = function __init__(item_data, container, onfocus) {
            var self = this;
            var div, control;
            ConfigItem.prototype.__init__.call(self, item_data);
            div = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "checkbox"})]), ρσ_interpolate_kwargs.call(E, E.span, [" " + item_data.text].concat([ρσ_desugar_kwargs({style: "white-space:pre"})]))].concat([ρσ_desugar_kwargs({id: self.widget_id})]));
            container.appendChild(div);
            control = div.firstChild;
            control.addEventListener("change", self.ui_value_changed.bind(self));
            control.addEventListener("focus", onfocus);
            div.addEventListener("click", onfocus);
            div.lastChild.addEventListener("click", self.toggle.bind(self));
        };
        if (!CheckBox.prototype.__init__.__argnames__) Object.defineProperties(CheckBox.prototype.__init__, {
            __argnames__ : {value: ["item_data", "container", "onfocus"]}
        });
        CheckBox.__argnames__ = CheckBox.prototype.__init__.__argnames__;
        CheckBox.__handles_kwarg_interpolation__ = CheckBox.prototype.__init__.__handles_kwarg_interpolation__;
        CheckBox.prototype.to_ui = function to_ui(val) {
            var self = this;
            self.control.checked = bool(val);
        };
        if (!CheckBox.prototype.to_ui.__argnames__) Object.defineProperties(CheckBox.prototype.to_ui, {
            __argnames__ : {value: ["val"]}
        });
        CheckBox.prototype.from_ui = function from_ui() {
            var self = this;
            return bool(self.control.checked);
        };
        CheckBox.prototype.toggle = function toggle() {
            var self = this;
            self.to_ui(!self.from_ui());
            self.ui_value_changed();
        };
        CheckBox.prototype.__repr__ = function __repr__ () {
            if(ConfigItem.prototype.__repr__) return ConfigItem.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        CheckBox.prototype.__str__ = function __str__ () {
            if(ConfigItem.prototype.__str__) return ConfigItem.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(CheckBox.prototype, "__bases__", {value: [ConfigItem]});
        

        function SpinBox() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            SpinBox.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(SpinBox, ConfigItem);
        SpinBox.prototype.__init__ = function __init__(item_data, container, onfocus) {
            var self = this;
            var div, control, val, attr;
            ConfigItem.prototype.__init__.call(self, item_data);
            div = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.span, [item_data.text + ": "].concat([ρσ_desugar_kwargs({style: "white-space:pre"})])), ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "number", step: "any", min: "1", max: "100"})])].concat([ρσ_desugar_kwargs({id: self.widget_id})]));
            container.appendChild(div);
            control = div.lastChild;
            var ρσ_Iter1 = ρσ_Iterable("min max step".split(" "));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                attr = ρσ_Iter1[ρσ_Index1];
                val = item_data[(typeof attr === "number" && attr < 0) ? item_data.length + attr : attr];
                if (val !== undefined && val !== null) {
                    control.setAttribute(attr, "" + val);
                }
            }
            control.addEventListener("change", self.ui_value_changed.bind(self));
            control.addEventListener("focus", onfocus);
            div.addEventListener("click", onfocus);
        };
        if (!SpinBox.prototype.__init__.__argnames__) Object.defineProperties(SpinBox.prototype.__init__, {
            __argnames__ : {value: ["item_data", "container", "onfocus"]}
        });
        SpinBox.__argnames__ = SpinBox.prototype.__init__.__argnames__;
        SpinBox.__handles_kwarg_interpolation__ = SpinBox.prototype.__init__.__handles_kwarg_interpolation__;
        SpinBox.prototype.to_ui = function to_ui(val) {
            var self = this;
            self.control.value = val;
        };
        if (!SpinBox.prototype.to_ui.__argnames__) Object.defineProperties(SpinBox.prototype.to_ui, {
            __argnames__ : {value: ["val"]}
        });
        SpinBox.prototype.from_ui = function from_ui() {
            var self = this;
            return self.control.value;
        };
        SpinBox.prototype.__repr__ = function __repr__ () {
            if(ConfigItem.prototype.__repr__) return ConfigItem.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        SpinBox.prototype.__str__ = function __str__ () {
            if(ConfigItem.prototype.__str__) return ConfigItem.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(SpinBox.prototype, "__bases__", {value: [ConfigItem]});

        function LineEdit() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            LineEdit.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(LineEdit, ConfigItem);
        LineEdit.prototype.__init__ = function __init__(item_data, container, onfocus) {
            var self = this;
            var div, control;
            ConfigItem.prototype.__init__.call(self, item_data);
            div = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.span, [item_data.text + ": "].concat([ρσ_desugar_kwargs({style: "white-space:pre"})])), ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "text"})])].concat([ρσ_desugar_kwargs({id: self.widget_id})]));
            container.appendChild(div);
            control = div.lastChild;
            control.addEventListener("change", self.ui_value_changed.bind(self));
            control.addEventListener("focus", onfocus);
            div.addEventListener("click", onfocus);
        };
        if (!LineEdit.prototype.__init__.__argnames__) Object.defineProperties(LineEdit.prototype.__init__, {
            __argnames__ : {value: ["item_data", "container", "onfocus"]}
        });
        LineEdit.__argnames__ = LineEdit.prototype.__init__.__argnames__;
        LineEdit.__handles_kwarg_interpolation__ = LineEdit.prototype.__init__.__handles_kwarg_interpolation__;
        LineEdit.prototype.to_ui = function to_ui(val) {
            var self = this;
            self.control.value = val || "";
        };
        if (!LineEdit.prototype.to_ui.__argnames__) Object.defineProperties(LineEdit.prototype.to_ui, {
            __argnames__ : {value: ["val"]}
        });
        LineEdit.prototype.from_ui = function from_ui() {
            var self = this;
            return self.control.value || "";
        };
        LineEdit.prototype.__repr__ = function __repr__ () {
            if(ConfigItem.prototype.__repr__) return ConfigItem.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        LineEdit.prototype.__str__ = function __str__ () {
            if(ConfigItem.prototype.__str__) return ConfigItem.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(LineEdit.prototype, "__bases__", {value: [ConfigItem]});

        state = Object.create(null);
        function onfocus(name) {
            return (function() {
                var ρσ_anonfunc = function (ev) {
                    var c, div;
                    c = document.getElementById(state.container_id);
                    div = c.querySelector("div[data-name=\"{}\"]".format(name));
                    div.lastChild.style.display = "block";
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!onfocus.__argnames__) Object.defineProperties(onfocus, {
            __argnames__ : {value: ["name"]}
        });

        function create_prefs_widget(container, prefs_data) {
            var div, val, cls, item;
            state = Object.create(null);
            state.container_id = ensure_id(container);
            state.widgets = ρσ_list_decorate([]);
            clear(container);
            var ρσ_Iter2 = ρσ_Iterable(prefs_data);
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                item = ρσ_Iter2[ρσ_Index2];
                div = ρσ_interpolate_kwargs.call(E, E.div, [E.div(), ρσ_interpolate_kwargs.call(E, E.div, [item.tooltip || ""].concat([ρσ_desugar_kwargs({style: "font-size:0.8rem; font-style: italic; margin-top:1ex; display:none"})]))].concat([ρσ_desugar_kwargs({style: "margin-bottom:1ex; padding: 1ex 1em; border-bottom: solid 1px currentColor", title: item.tooltip, data_name: item.name})]));
                container.appendChild(div);
                val = get_session_data().get(item.name);
                if (item.from_storage) {
                    val = item.from_storage(val);
                }
                if (item.choices) {
                    cls = Choices;
                } else if (val === true || val === false) {
                    cls = CheckBox;
                } else if (typeof val === "number") {
                    cls = SpinBox;
                } else {
                    cls = LineEdit;
                }
                state.widgets.push(new cls(item, div.firstChild, onfocus(item.name)).initialize());
            }
            if (state.widgets.length) {
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [create_button(_("Restore default settings"), "refresh", reset_to_defaults)].concat([ρσ_desugar_kwargs({style: "margin:1ex 1em; padding: 1em; text-align:center"})])));
            }
        };
        if (!create_prefs_widget.__argnames__) Object.defineProperties(create_prefs_widget, {
            __argnames__ : {value: ["container", "prefs_data"]}
        });

        function reset_to_defaults() {
            var w;
            var ρσ_Iter3 = ρσ_Iterable(state.widgets);
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                w = ρσ_Iter3[ρσ_Index3];
                w.reset_to_default();
            }
        };

        function prefs_panel_handler() {
            var title = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var get_prefs_data = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
            var on_close = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? prefs_panel_handler.__defaults__.on_close : arguments[2];
            var icon = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? prefs_panel_handler.__defaults__.icon : arguments[3];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "on_close")){
                on_close = ρσ_kwargs_obj.on_close;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "icon")){
                icon = ρσ_kwargs_obj.icon;
            }
            function close_action() {
                if (on_close !== null) {
                    on_close();
                }
                back();
            };

            return (function() {
                var ρσ_anonfunc = function init_prefs_panel(container_id) {
                    var container;
                    container = document.getElementById(container_id);
                    ρσ_interpolate_kwargs.call(this, create_top_bar, [container, title].concat([ρσ_desugar_kwargs({action: close_action, icon: icon})]));
                    container.appendChild(E.div());
                    create_prefs_widget(container.lastChild, get_prefs_data());
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["container_id"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!prefs_panel_handler.__defaults__) Object.defineProperties(prefs_panel_handler, {
            __defaults__ : {value: {on_close:null, icon:"close"}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["title", "get_prefs_data", "on_close", "icon"]}
        });

        ρσ_modules["book_list.prefs"].pp_counter = pp_counter;
        ρσ_modules["book_list.prefs"].widget_counter = widget_counter;
        ρσ_modules["book_list.prefs"].state = state;
        ρσ_modules["book_list.prefs"].ConfigItem = ConfigItem;
        ρσ_modules["book_list.prefs"].Choices = Choices;
        ρσ_modules["book_list.prefs"].CheckBox = CheckBox;
        ρσ_modules["book_list.prefs"].SpinBox = SpinBox;
        ρσ_modules["book_list.prefs"].LineEdit = LineEdit;
        ρσ_modules["book_list.prefs"].onfocus = onfocus;
        ρσ_modules["book_list.prefs"].create_prefs_widget = create_prefs_widget;
        ρσ_modules["book_list.prefs"].reset_to_defaults = reset_to_defaults;
        ρσ_modules["book_list.prefs"].prefs_panel_handler = prefs_panel_handler;
    })();

    (function(){
        var __name__ = "book_list.search";
        var apply_search, sp_counter, CLASS_NAME, state, last_accepted_search;
        var ajax = ρσ_modules.ajax.ajax;
        var absolute_path = ρσ_modules.ajax.absolute_path;

        var create_search_bar = ρσ_modules.complete.create_search_bar;

        var clear = ρσ_modules.dom.clear;
        var set_css = ρσ_modules.dom.set_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var svgicon = ρσ_modules.dom.svgicon;
        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var ensure_id = ρσ_modules.dom.ensure_id;

        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var create_button = ρσ_modules.widgets.create_button;
        var create_spinner = ρσ_modules.widgets.create_spinner;
        var Breadcrumbs = ρσ_modules.widgets.Breadcrumbs;

        var show_modal = ρσ_modules.modals.show_modal;
        var create_custom_dialog = ρσ_modules.modals.create_custom_dialog;

        var rating_to_stars = ρσ_modules.utils.rating_to_stars;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;
        var is_ios = ρσ_modules.utils.is_ios;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        var library_data = ρσ_modules["book_list.library_data"].library_data;
        var current_library_id = ρσ_modules["book_list.library_data"].current_library_id;
        var current_virtual_library = ρσ_modules["book_list.library_data"].current_virtual_library;

        var show_panel = ρσ_modules["book_list.ui"].show_panel;

        var back = ρσ_modules["book_list.router"].back;

        var create_top_bar = ρσ_modules["book_list.top_bar"].create_top_bar;
        var add_button = ρσ_modules["book_list.top_bar"].add_button;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var get_color = ρσ_modules["book_list.theme"].get_color;
        var get_font_size = ρσ_modules["book_list.theme"].get_font_size;

        var prefs_panel_handler = ρσ_modules["book_list.prefs"].prefs_panel_handler;

        apply_search = null;
        function set_apply_search(func) {
            apply_search = func;
        };
        if (!set_apply_search.__argnames__) Object.defineProperties(set_apply_search, {
            __argnames__ : {value: ["func"]}
        });

        sp_counter = 0;
        CLASS_NAME = "book-search-panel";
        add_extra_css(function () {
            var sel, style;
            sel = "." + CLASS_NAME + " ";
            style = ρσ_interpolate_kwargs.call(this, build_rule, [sel + " div.tag-name > span"].concat([ρσ_desugar_kwargs({word_break: "break-all", hyphens: "auto", padding_left: "1ex"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " div.tag-name:hover"].concat([ρσ_desugar_kwargs({color: get_color("list-hover-foreground"), background_color: get_color("list-hover-background")})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " div.tag-menu:hover"].concat([ρσ_desugar_kwargs({color: get_color("list-hover-foreground"), background_color: get_color("list-hover-background")})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " div.tag-name:active"].concat([ρσ_desugar_kwargs({transform: "scale(1.5)"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " div.tag-menu:active"].concat([ρσ_desugar_kwargs({transform: "scale(2)"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " ul.search-items"].concat([ρσ_desugar_kwargs({margin_top: "1ex", list_style_type: "none", text_align: "left"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " ul.search-items > li"].concat([ρσ_desugar_kwargs({display: "inline-block", cursor: "pointer", background_color: get_color("window-background2"), border_radius: "10px", padding: "0.5ex", margin_right: "1em"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " ul.search-items > li:hover"].concat([ρσ_desugar_kwargs({color: get_color("window-hover-foreground")})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " ul.search-items > li:active"].concat([ρσ_desugar_kwargs({transform: "scale(1.5)"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, ["#modal-container ul.tb-action-list > li:hover"].concat([ρσ_desugar_kwargs({color: get_color("list-hover-foreground"), background_color: get_color("list-hover-background")})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, ["#modal-container ul.tb-action-list > li:active"].concat([ρσ_desugar_kwargs({color: get_color("window-hover-foreground"), color: get_color("list-hover-foreground"), background_color: get_color("list-hover-background")})]));
            return style;
        });
        state = Object.create(null);
        last_accepted_search = null;
        function component(container, name) {
            return container.querySelector("[data-component=\"" + ρσ_str.format("{}", name) + "\"]");
        };
        if (!component.__argnames__) Object.defineProperties(component, {
            __argnames__ : {value: ["container", "name"]}
        });

        function icon_for_node(node) {
            var interface_data, ans;
            interface_data = get_interface_data();
            ans = (ρσ_expr_temp = interface_data.icon_map)[ρσ_bound_index(node.data.category, ρσ_expr_temp)] || "column.png";
            return absolute_path(interface_data.icon_path + "/" + ans);
        };
        if (!icon_for_node.__argnames__) Object.defineProperties(icon_for_node, {
            __argnames__ : {value: ["node"]}
        });

        function node_for_path(path) {
            var ans, child_index;
            path = path || state.tag_path;
            ans = state.tag_browser_data;
            var ρσ_Iter0 = ρσ_Iterable(path);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                child_index = ρσ_Iter0[ρσ_Index0];
                ans = (ρσ_expr_temp = ans.children)[(typeof child_index === "number" && child_index < 0) ? ρσ_expr_temp.length + child_index : child_index];
            }
            return ans;
        };
        if (!node_for_path.__argnames__) Object.defineProperties(node_for_path, {
            __argnames__ : {value: ["path"]}
        });

        function execute_search(text) {
            if (state.tag_path && state.tag_path.length) {
                last_accepted_search = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["library_id"] = current_library_id();
                    ρσ_d["vl"] = current_virtual_library();
                    ρσ_d["tag_path"] = list(state.tag_path);
                    return ρσ_d;
                }).call(this);
            }
            apply_search(text);
        };
        if (!execute_search.__argnames__) Object.defineProperties(execute_search, {
            __argnames__ : {value: ["text"]}
        });

        function ask_about_smart_quotes(text) {
            create_custom_dialog(_("Search contains smart quotes"), (function() {
                var ρσ_anonfunc = function (parent, close_modal) {
                    function action(replace) {
                        close_modal();
                        if (replace) {
                            text = text.replace(/[“”«»„]/g, "\"");
                        }
                        execute_search(text);
                    };
                    if (!action.__argnames__) Object.defineProperties(action, {
                        __argnames__ : {value: ["replace"]}
                    });

                    parent.appendChild(E.div(E.div(_("The search expression {} contains smart quotes. By default, Apple inserts smart quotes instead of normal quotes when tapping the quote button. This will prevent the search from working, if you intended to use normal quotes. You can type normal quotes by long-tapping the quotes button. Do you want to keep the smart quotes or replace them with normal quotes?").format(text)), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(this, create_button, [_("Replace"), null, action.bind(null, true)].concat([ρσ_desugar_kwargs({highlight: true})])), " ", create_button(_("Keep"), null, action.bind(null, false))].concat([ρσ_desugar_kwargs({class_: "button-box"})]))));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["parent", "close_modal"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!ask_about_smart_quotes.__argnames__) Object.defineProperties(ask_about_smart_quotes, {
            __argnames__ : {value: ["text"]}
        });

        function execute_search_interactive(text) {
            var container, search_control;
            if (!text) {
                container = document.getElementById(state.container_id);
                search_control = container.querySelector("input[name=\"search-books\"]");
                text = search_control.value || "";
            }
            if (is_ios && /[“”«»„]/.test(text)) {
                ask_about_smart_quotes(text);
            } else {
                execute_search(text);
            }
        };
        if (!execute_search_interactive.__argnames__) Object.defineProperties(execute_search_interactive, {
            __argnames__ : {value: ["text"]}
        });

        function search_expression_for_item(node, node_state) {
            var item, search_state, stars, category, letters_seen, child, charclass, expr, rnum, fm, suffix, name;
            item = node.data;
            if (item.is_searchable === false || !node_state || node_state === "clear") {
                return "";
            }
            search_state = (ρσ_expr_temp = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["plus"] = "true";
                ρσ_d["plusplus"] = ".true";
                ρσ_d["minus"] = "false";
                ρσ_d["minusminus"] = ".false";
                return ρσ_d;
            }).call(this))[(typeof node_state === "number" && node_state < 0) ? ρσ_expr_temp.length + node_state : node_state];
            stars = rating_to_stars(3, true);
            if (item.is_category) {
                category = item.category;
                if (item.is_first_letter) {
                    letters_seen = Object.create(null);
                    var ρσ_Iter1 = ρσ_Iterable(node.children);
                    for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                        child = ρσ_Iter1[ρσ_Index1];
                        if (child.data.sort) {
                            letters_seen[ρσ_bound_index(child.data.sort[0], letters_seen)] = true;
                        }
                    }
                    letters_seen = Object.keys(letters_seen);
                    if (letters_seen.length) {
                        charclass = letters_seen.join("");
                        if (category === "authors") {
                            expr = "author_sort:\"~(^[{0}])|(&\\s*[{0}])\"".format(charclass);
                        } else if (category === "series") {
                            expr = "series_sort:\"~^[{0}]\"".format(charclass);
                        } else {
                            expr = "{0}:\"~^[{1}]\"".format(category, charclass);
                        }
                    } else {
                        expr = "{}:false".format(category);
                    }
                } else if (category === "news") {
                    expr = "tags:\"={}\"".format(item.name);
                } else {
                    return "{}:{}".format(category, search_state);
                }
                if (ρσ_in("false", search_state)) {
                    expr = "(not " + expr + ")";
                }
                return expr;
            }
            category = (item.category === "news") ? "tags" : item.category;
            if (item.name && ρσ_in(item.name[0], stars)) {
                rnum = item.name.length;
                if (item.name.endswith(stars[stars.length-1])) {
                    rnum = "{}.5".format(rnum - 1);
                }
                expr = "{}:{}".format(category, rnum);
            } else {
                fm = (ρσ_expr_temp = library_data.field_metadata)[ρσ_bound_index(item.category, ρσ_expr_temp)];
                suffix = (fm && fm.is_csp) ? ":" : "";
                name = item.original_name || item.name || item.sort;
                if (!name) {
                    return "";
                }
                name = str.replace(name, "\"", "\\\"");
                if (name[0] === ".") {
                    name = "." + name;
                }
                if (search_state === ".true" || search_state === ".false") {
                    name = "." + name;
                }
                expr = "{}:\"={}{}\"".format(category, name, suffix);
            }
            if (ρσ_in("false", search_state)) {
                expr = "(not " + expr + ")";
            }
            return expr;
        };
        if (!search_expression_for_item.__argnames__) Object.defineProperties(search_expression_for_item, {
            __argnames__ : {value: ["node", "node_state"]}
        });

        function node_clicked(i) {
            var node, expr;
            node = (ρσ_expr_temp = node_for_path().children)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
            if (node.children && node.children.length) {
                state.tag_path.append(i);
                render_tag_browser();
            } else {
                expr = search_expression_for_item(node, "plus");
                execute_search(expr);
            }
        };
        if (!node_clicked.__argnames__) Object.defineProperties(node_clicked, {
            __argnames__ : {value: ["i"]}
        });

        function add_to_search(node, search_type) {
            var anded;
            anded = get_session_data().get("and_search_terms");
            (ρσ_expr_temp = state.active_nodes)[ρσ_bound_index(node.id, ρσ_expr_temp)] = ρσ_list_decorate([ search_type, anded ]);
            render_search_expression();
        };
        if (!add_to_search.__argnames__) Object.defineProperties(add_to_search, {
            __argnames__ : {value: ["node", "search_type"]}
        });

        function remove_expression(node_id) {
            delete state.active_nodes[node_id];
            render_search_expression();
        };
        if (!remove_expression.__argnames__) Object.defineProperties(remove_expression, {
            __argnames__ : {value: ["node_id"]}
        });

        function render_search_expression() {
            var parts, container, sic, ρσ_unpack, search_type, anded, node, expr, name, c, node_id, search_control;
            parts = [];
            container = document.getElementById(state.container_id);
            sic = component(container, "search_expression");
            clear(sic);
            var ρσ_Iter2 = ρσ_Iterable(Object.keys(state.active_nodes));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                node_id = ρσ_Iter2[ρσ_Index2];
                ρσ_unpack = (ρσ_expr_temp = state.active_nodes)[(typeof node_id === "number" && node_id < 0) ? ρσ_expr_temp.length + node_id : node_id];
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                search_type = ρσ_unpack[0];
                anded = ρσ_unpack[1];
                node = (ρσ_expr_temp = state.node_id_map)[(typeof node_id === "number" && node_id < 0) ? ρσ_expr_temp.length + node_id : node_id];
                expr = search_expression_for_item(node, search_type);
                name = node.data.original_name || node.data.name || node.data.sort || "";
                if (expr) {
                    c = E.li(svgicon("remove"), " " + name);
                    sic.appendChild(c);
                    c.addEventListener("click", remove_expression.bind(null, node_id));
                    if (parts.length) {
                        expr = ((anded) ? "and" : "or") + " " + expr;
                    }
                    parts.push(expr);
                }
            }
            search_control = container.querySelector("input[name=\"search-books\"]");
            search_control.value = parts.join(" ");
        };

        function menu_clicked(i) {
            function create_details(container, hide_modal) {
                var node, data, name, items, suffix, title, ul, interface_data, li, ρσ_unpack, text, search_type, f, and_control;
                node = (ρσ_expr_temp = node_for_path().children)[(typeof i === "number" && i < 0) ? ρσ_expr_temp.length + i : i];
                data = node.data;
                name = data.original_name || data.name || data.sort;
                items = ρσ_list_decorate([]);
                if (data.count !== undefined) {
                    items.append(_("Count: ") + data.count);
                }
                if (data.avg_rating !== undefined) {
                    items.append(_("Rating: {:.1f}").format(data.avg_rating));
                }
                suffix = "";
                if (items.length) {
                    suffix = " [" + items.join(" ") + "]";
                }
                title = ρσ_interpolate_kwargs.call(E, E.h2, [ρσ_interpolate_kwargs.call(E, E.img, [ρσ_desugar_kwargs({src: icon_for_node(node), style: "height:2ex"})]), E.span(" " + name + suffix)].concat([ρσ_desugar_kwargs({style: "display:flex; align-items: center; border-bottom: solid 1px currentColor; font-weight:bold; font-size:" + get_font_size("title")})]));
                container.appendChild(title);
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Search for books based on this category (a search term will be added to the search box)")].concat([ρσ_desugar_kwargs({style: "margin-top:1ex; margin-bottom: 1ex"})])));
                ul = ρσ_interpolate_kwargs.call(E, E.ul, [ρσ_desugar_kwargs({style: "list-style:none; overflow:hidden", class_: "tb-action-list"})]);
                container.appendChild(ul);
                items = ρσ_list_decorate([ [_("Books matching this category"), "plus"], [_("Books that do not match this category"), 
                "minus"] ]);
                if (node.data.is_hierarchical === 5) {
                    items.extend(ρσ_list_decorate([ [_("Books that match this category and all sub-categories"), 
                    "plusplus"], [_("Books that do not match this category or any of its sub-categories"), 
                    "minusminus"] ]));
                }
                interface_data = get_interface_data();
                var ρσ_Iter3 = ρσ_Iterable(items);
                for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                    ρσ_unpack = ρσ_Iter3[ρσ_Index3];
                    text = ρσ_unpack[0];
                    search_type = ρσ_unpack[1];
                    li = ρσ_interpolate_kwargs.call(E, E.li, [ρσ_interpolate_kwargs.call(E, E.img, [ρσ_desugar_kwargs({src: absolute_path("{}/{}.png".format(interface_data.icon_path, search_type)), style: "max-height: 2.5ex"})]), E.span(" " + text)].concat([ρσ_desugar_kwargs({style: "display:flex; align-items: center; margin-bottom:0.5ex; padding: 0.5ex; cursor:pointer"})]));
                    li.addEventListener("click", add_to_search.bind(null, node, search_type));
                    li.addEventListener("click", hide_modal);
                    ul.appendChild(li);
                }
                f = ρσ_interpolate_kwargs.call(E, E.form, [E.span(_("Add to the search expression with:")), ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "radio", name: "expr_join", value: "OR", checked: ""})]), E.span(" OR "), ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "radio", name: "expr_join", value: "AND"})]), E.span(" AND")].concat([ρσ_desugar_kwargs({style: "text-align:left; border-top: solid 1px currentColor; padding-top:1ex; margin-top:0.5ex; display:flex; align-items:center"})]));
                and_control = f.lastChild.previousSibling;
                and_control.checked = get_session_data().get("and_search_terms");
                container.appendChild(f);
                and_control.addEventListener("change", (function() {
                    var ρσ_anonfunc = function (ev) {
                        get_session_data().set("and_search_terms", bool(ev.target.checked));
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["ev"]}
                    });
                    return ρσ_anonfunc;
                })());
                f.firstChild.nextSibling.addEventListener("change", (function() {
                    var ρσ_anonfunc = function (ev) {
                        get_session_data().set("and_search_terms", !ev.target.checked);
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["ev"]}
                    });
                    return ρσ_anonfunc;
                })());
            };
            if (!create_details.__argnames__) Object.defineProperties(create_details, {
                __argnames__ : {value: ["container", "hide_modal"]}
            });

            show_modal(create_details);
        };
        if (!menu_clicked.__argnames__) Object.defineProperties(menu_clicked, {
            __argnames__ : {value: ["i"]}
        });

        function render_children(container, children) {
            var data, tooltip, div, ρσ_unpack, i, node;
            var ρσ_Iter4 = ρσ_Iterable(enumerate(children));
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                ρσ_unpack = ρσ_Iter4[ρσ_Index4];
                i = ρσ_unpack[0];
                node = ρσ_unpack[1];
                data = node.data;
                tooltip = "";
                if (data.count !== undefined) {
                    tooltip += "\n" + _("Number of books in this category: {}").format(data.count);
                }
                if (data.avg_rating !== undefined) {
                    tooltip += "\n" + _("Average rating for books in this category: {:.1f}").format(data.avg_rating);
                }
                div = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.img, [ρσ_desugar_kwargs({src: icon_for_node(node), style: "display:inline-block; max-height:2.5ex"})]), E.span(data.name)].concat([ρσ_desugar_kwargs({class_: "tag-name", style: "border-right:solid 1px currentColor; padding: 1ex; display:flex; align-items: center"})])), ρσ_interpolate_kwargs.call(E, E.div, [E.div(svgicon("angle-down"))].concat([ρσ_desugar_kwargs({class_: "tag-menu", style: "padding: 1ex; display:flex; align-items:center"})]))].concat([ρσ_desugar_kwargs({title: tooltip.lstrip(), style: "display:flex; align-items: stretch"})]));
                ρσ_interpolate_kwargs.call(this, set_css, [div].concat([ρσ_desugar_kwargs({max_width: "95vw", border: "solid 1px currentColor", border_radius: "20px", margin: "0.5rem", cursor: "pointer", overflow: "hidden", user_select: "none"})]));
                div.firstChild.addEventListener("click", node_clicked.bind(null, i));
                div.lastChild.addEventListener("click", menu_clicked.bind(null, i));
                container.appendChild(div);
            }
        };
        if (!render_children.__argnames__) Object.defineProperties(render_children, {
            __argnames__ : {value: ["container", "children"]}
        });

        function render_breadcrumbs() {
            var container, parent, ρσ_unpack, i, index;
            container = state.breadcrumbs.container;
            if (!state.tag_path.length) {
                container.style.display = "none";
                return;
            }
            container.style.display = "inline-block";
            state.breadcrumbs.reset();
            function onclick(i) {
                return (function() {
                    var ρσ_anonfunc = function (ev) {
                        state.tag_path = state.tag_path.slice(0, i + 1);
                        render_tag_browser();
                        ev.preventDefault();
                        return true;
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["ev"]}
                    });
                    return ρσ_anonfunc;
                })();
            };
            if (!onclick.__argnames__) Object.defineProperties(onclick, {
                __argnames__ : {value: ["i"]}
            });

            function create_breadcrumb() {
                var index = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_breadcrumb.__defaults__.index : arguments[0];
                var item = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? create_breadcrumb.__defaults__.item : arguments[1];
                var ρσ_kwargs_obj = arguments[arguments.length-1];
                if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
                if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "index")){
                    index = ρσ_kwargs_obj.index;
                }
                if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "item")){
                    item = ρσ_kwargs_obj.item;
                }
                var li;
                li = state.breadcrumbs.add_crumb(onclick(index));
                if (item) {
                    li.appendChild(E.span(item.name));
                } else {
                    li.appendChild(svgicon("home", "2.2ex", "2.2ex"));
                }
            };
            if (!create_breadcrumb.__defaults__) Object.defineProperties(create_breadcrumb, {
                __defaults__ : {value: {index:-1, item:null}},
                __handles_kwarg_interpolation__ : {value: true},
                __argnames__ : {value: ["index", "item"]}
            });

            create_breadcrumb();
            parent = state.tag_browser_data;
            var ρσ_Iter5 = ρσ_Iterable(enumerate(state.tag_path));
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                ρσ_unpack = ρσ_Iter5[ρσ_Index5];
                i = ρσ_unpack[0];
                index = ρσ_unpack[1];
                parent = (ρσ_expr_temp = parent.children)[(typeof index === "number" && index < 0) ? ρσ_expr_temp.length + index : index];
                create_breadcrumb(i, parent.data);
            }
        };

        function render_tag_browser() {
            var container, node;
            container = document.getElementById(state.container_id).lastChild.lastChild;
            clear(container);
            ρσ_interpolate_kwargs.call(this, set_css, [container].concat([ρσ_desugar_kwargs({padding: "1ex 1em", display: "flex", flex_wrap: "wrap", margin_left: "-0.5rem"})]));
            try {
                node = node_for_path();
            } catch (ρσ_Exception) {
                ρσ_last_exception = ρσ_Exception;
                {
                    state.tag_path = ρσ_list_decorate([]);
                    node = node_for_path();
                } 
            }
            render_children(container, node.children);
            render_breadcrumbs();
        };

        function on_data_fetched(end_type, xhr, ev) {
            var container, loading_panel, tag_browser_data;
            state.currently_loading = null;
            if (end_type === "abort") {
                return;
            }
            container = document.getElementById(state.container_id);
            if (!container) {
                return;
            }
            loading_panel = component(container, "loading");
            loading_panel.style.display = "none";
            container = component(container, "tag_browser");
            container.style.display = "block";
            clear(container);
            function show_error(error_html) {
                var ediv;
                ediv = E.div();
                container.appendChild(ediv);
                safe_set_inner_html(ediv, "<h3>" + _("Failed to load Tag browser data") + "</h3>" + error_html);
            };
            if (!show_error.__argnames__) Object.defineProperties(show_error, {
                __argnames__ : {value: ["error_html"]}
            });

            function process_node(node, item_map) {
                var child;
                (ρσ_expr_temp = state.node_id_map)[ρσ_bound_index(node.id, ρσ_expr_temp)] = node;
                node.data = item_map[ρσ_bound_index(node.id, item_map)];
                var ρσ_Iter6 = ρσ_Iterable(node.children);
                for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                    child = ρσ_Iter6[ρσ_Index6];
                    child.parent = node;
                    process_node(child, item_map);
                }
            };
            if (!process_node.__argnames__) Object.defineProperties(process_node, {
                __argnames__ : {value: ["node", "item_map"]}
            });

            if (end_type === "load") {
                try {
                    tag_browser_data = JSON.parse(xhr.responseText);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        var err = ρσ_Exception;
                        show_error(err + "");
                        return;
                    } else {
                        throw ρσ_Exception;
                    }
                }
                state.tag_browser_data = tag_browser_data.root;
                state.node_id_map = Object.create(null);
                state.active_nodes = Object.create(null);
                process_node(state.tag_browser_data, tag_browser_data.item_map);
                if (last_accepted_search && last_accepted_search.library_id === current_library_id() && last_accepted_search.vl === current_virtual_library()) {
                    if (last_accepted_search.tag_path.length) {
                        state.tag_path = list(last_accepted_search.tag_path);
                    }
                }
                render_tag_browser();
            } else {
                show_error(xhr.error_html);
            }
        };
        if (!on_data_fetched.__argnames__) Object.defineProperties(on_data_fetched, {
            __argnames__ : {value: ["end_type", "xhr", "ev"]}
        });

        function refresh() {
            var sd, query, k, xhr;
            if (state.currently_loading !== null) {
                state.currently_loading.abort();
                state.currently_loading = null;
            }
            sd = get_session_data();
            query = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["library_id"] = current_library_id();
                ρσ_d["vl"] = current_virtual_library();
                return ρσ_d;
            }).call(this);
            var ρσ_Iter7 = ρσ_Iterable("sort_tags_by partition_method collapse_at dont_collapse hide_empty_categories".split(" "));
            for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                k = ρσ_Iter7[ρσ_Index7];
                query[(typeof k === "number" && k < 0) ? query.length + k : k] = sd.get(k) + "";
            }
            xhr = ρσ_interpolate_kwargs.call(this, ajax, ["interface-data/tag-browser", on_data_fetched].concat([ρσ_desugar_kwargs({query: query, bypass_cache: false})]));
            xhr.send();
            state.currently_loading = xhr;
        };

        function create_search_panel(container) {
            var search_container, search_button, search_bar, loading_panel;
            state = Object.create(null);
            container.classList.add(CLASS_NAME);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({data_component: "search", style: "text-align:center; padding:1ex 1em; border-bottom: solid 1px currentColor; margin-bottom: 0.5ex"})]));
            container.appendChild(E.div(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({data_component: "loading"})]), ρσ_interpolate_kwargs.call(E, E.ol, [ρσ_desugar_kwargs({style: "display:none", data_component: "breadcrumbs"})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "display:none", data_component: "tag_browser"})])));
            search_container = component(container, "search");
            search_button = ρσ_interpolate_kwargs.call(this, create_button, [_("Search")].concat([ρσ_desugar_kwargs({icon: "search", tooltip: _("Do the search")})]));
            search_bar = ρσ_interpolate_kwargs.call(this, create_search_bar, [execute_search_interactive, "search-books"].concat([ρσ_desugar_kwargs({tooltip: _("Search for books"), placeholder: _("Enter the search query"), button: search_button})]));
            ρσ_interpolate_kwargs.call(this, set_css, [search_bar].concat([ρσ_desugar_kwargs({flex_grow: "10", margin_right: "0.5em"})]));
            search_container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [search_bar, search_button].concat([ρσ_desugar_kwargs({style: "display: flex; width: 100%;"})])));
            search_container.appendChild(ρσ_interpolate_kwargs.call(E, E.ul, [ρσ_desugar_kwargs({class_: "search-items", data_component: "search_expression"})]));
            loading_panel = component(container, "loading");
            loading_panel.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [create_spinner(), " " + _("Fetching data for the Tag browser, please wait") + "…"].concat([ρσ_desugar_kwargs({style: "margin-left:auto; margin-right:auto; font-size: 1.5rem; font-weight; bold; text-align:center; margin-top:30vh"})])));
            state.breadcrumbs = new Breadcrumbs(component(container, "breadcrumbs"));
            state.currently_loading = null;
            state.tag_browser_data = null;
            state.node_id_map = Object.create(null);
            state.active_nodes = Object.create(null);
            state.tag_path = ρσ_list_decorate([]);
            state.container_id = ensure_id(container);
            refresh();
        };
        if (!create_search_panel.__argnames__) Object.defineProperties(create_search_panel, {
            __argnames__ : {value: ["container"]}
        });

        function get_prefs() {
            return ρσ_list_decorate([ (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["name"] = "sort_tags_by";
                ρσ_d["text"] = _("Sort tags by");
                ρσ_d["choices"] = ρσ_list_decorate([ ["name", _("Name")], ["popularity", _("Popularity (number of books)")], ["rating", 
                _("Average rating")] ]);
                ρσ_d["tooltip"] = _("Change how the tags/authors/etc. are sorted in the \"Tag browser\"");
                return ρσ_d;
            }).call(this), (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["name"] = "partition_method";
                ρσ_d["text"] = _("Tag browser category partitioning method");
                ρσ_d["choices"] = ρσ_list_decorate([ ["first letter", _("First Letter")], ["disable", 
                _("Disable")], ["partition", _("Partition")] ]);
                ρσ_d["tooltip"] = _("Choose how Tag browser subcategories are displayed when there are more items than the limit. Select by first letter to see an A, B, C list. Choose partitioned to have a list of fixed-sized groups. Set to disabled if you never want subcategories.");
                return ρσ_d;
            }).call(this), (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["name"] = "collapse_at";
                ρσ_d["text"] = _("Collapse when more items than");
                ρσ_d["min"] = 5;
                ρσ_d["max"] = 1e4;
                ρσ_d["step"] = 5;
                ρσ_d["from_storage"] = int;
                ρσ_d["to_storage"] = int;
                ρσ_d["tooltip"] = _("If a \"Tag browser\" category has more than this number of items, it is divided up into subcategories. If the partition method is set to disable, this value is ignored.");
                return ρσ_d;
            }).call(this), (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["name"] = "dont_collapse";
                ρσ_d["text"] = _("Categories not to partition");
                ρσ_d["tooltip"] = _("A comma-separated list of categories in which items containing periods are displayed in the Tag browser trees. For example, if this box contains 'tags' then tags of the form 'Mystery.English' and 'Mystery.Thriller' will be displayed with English and Thriller both under 'Mystery'. If 'tags' is not in this box, then the tags will be displayed each on their own line.");
                return ρσ_d;
            }).call(this), (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["name"] = "hide_empty_categories";
                ρσ_d["text"] = _("Hide empty categories (columns)");
                ρσ_d["from_storage"] = (function() {
                    var ρσ_anonfunc = function (x) {
                        return x.toLowerCase() === "yes";
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["x"]}
                    });
                    return ρσ_anonfunc;
                })();
                ρσ_d["to_storage"] = (function() {
                    var ρσ_anonfunc = function (x) {
                        return (x) ? "yes" : "no";
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["x"]}
                    });
                    return ρσ_anonfunc;
                })();
                ρσ_d["tooltip"] = _("When checked, calibre will automatically hide any category (a column, custom or standard) that has no items to show. For example, some categories might not have values when using virtual libraries. Checking this box will cause these empty categories to be hidden.");
                return ρσ_d;
            }).call(this) ]);
        };

        function tb_config_panel_handler() {
            return prefs_panel_handler(_("Configure Tag browser"), get_prefs);
        };

        function init(container_id) {
            var container;
            if (!library_data.sortable_fields) {
                ρσ_interpolate_kwargs.call(this, show_panel, ["book_list"].concat([ρσ_desugar_kwargs({replace: true})]));
                return;
            }
            container = document.getElementById(container_id);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("Search for books"), action: back, icon: "close"})]));
            ρσ_interpolate_kwargs.call(this, add_button, [container].concat([ρσ_desugar_kwargs({icon: "cogs", action: show_panel.bind(null, "book_list^search^prefs"), tooltip: _("Configure Tag browser")})]));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: CLASS_NAME})]));
            create_search_panel(container.lastChild);
        };
        if (!init.__argnames__) Object.defineProperties(init, {
            __argnames__ : {value: ["container_id"]}
        });

        ρσ_modules["book_list.search"].apply_search = apply_search;
        ρσ_modules["book_list.search"].sp_counter = sp_counter;
        ρσ_modules["book_list.search"].CLASS_NAME = CLASS_NAME;
        ρσ_modules["book_list.search"].state = state;
        ρσ_modules["book_list.search"].last_accepted_search = last_accepted_search;
        ρσ_modules["book_list.search"].set_apply_search = set_apply_search;
        ρσ_modules["book_list.search"].component = component;
        ρσ_modules["book_list.search"].icon_for_node = icon_for_node;
        ρσ_modules["book_list.search"].node_for_path = node_for_path;
        ρσ_modules["book_list.search"].execute_search = execute_search;
        ρσ_modules["book_list.search"].ask_about_smart_quotes = ask_about_smart_quotes;
        ρσ_modules["book_list.search"].execute_search_interactive = execute_search_interactive;
        ρσ_modules["book_list.search"].search_expression_for_item = search_expression_for_item;
        ρσ_modules["book_list.search"].node_clicked = node_clicked;
        ρσ_modules["book_list.search"].add_to_search = add_to_search;
        ρσ_modules["book_list.search"].remove_expression = remove_expression;
        ρσ_modules["book_list.search"].render_search_expression = render_search_expression;
        ρσ_modules["book_list.search"].menu_clicked = menu_clicked;
        ρσ_modules["book_list.search"].render_children = render_children;
        ρσ_modules["book_list.search"].render_breadcrumbs = render_breadcrumbs;
        ρσ_modules["book_list.search"].render_tag_browser = render_tag_browser;
        ρσ_modules["book_list.search"].on_data_fetched = on_data_fetched;
        ρσ_modules["book_list.search"].refresh = refresh;
        ρσ_modules["book_list.search"].create_search_panel = create_search_panel;
        ρσ_modules["book_list.search"].get_prefs = get_prefs;
        ρσ_modules["book_list.search"].tb_config_panel_handler = tb_config_panel_handler;
        ρσ_modules["book_list.search"].init = init;
    })();

    (function(){
        var __name__ = "book_list.views";
        var CLASS_NAME, ITEM_CLASS_NAME, ALLOWED_MODES, DEFAULT_MODE, book_list_data;
        var traceback = ρσ_modules.traceback;

        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var ajax_send = ρσ_modules.ajax.ajax_send;

        var add_books_panel = ρσ_modules["book_list.add"].add_books_panel;

        var cover_grid_append_item = ρσ_modules["book_list.cover_grid"].append_item;
        var cover_grid_css = ρσ_modules["book_list.cover_grid"].cover_grid_css;
        var create_cover_grid_item = ρσ_modules["book_list.cover_grid"].create_item;
        var COVER_GRID_DESCRIPTION = ρσ_modules["book_list.cover_grid"].description;
        var init_cover_grid = ρσ_modules["book_list.cover_grid"].init;

        var custom_list_append_item = ρσ_modules["book_list.custom_list"].append_item;
        var create_custom_list_item = ρσ_modules["book_list.custom_list"].create_item;
        var custom_list_css = ρσ_modules["book_list.custom_list"].custom_list_css;
        var CUSTOM_LIST_DESCRIPTION = ρσ_modules["book_list.custom_list"].description;
        var init_custom_list = ρσ_modules["book_list.custom_list"].init;

        var details_list_append_item = ρσ_modules["book_list.details_list"].append_item;
        var create_details_list_item = ρσ_modules["book_list.details_list"].create_item;
        var DETAILS_LIST_DESCRIPTION = ρσ_modules["book_list.details_list"].description;
        var details_list_css = ρσ_modules["book_list.details_list"].details_list_css;
        var init_details_list = ρσ_modules["book_list.details_list"].init;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var create_item = ρσ_modules["book_list.item_list"].create_item;
        var create_item_list = ρσ_modules["book_list.item_list"].create_item_list;

        var add_more_books = ρσ_modules["book_list.library_data"].add_more_books;
        var all_virtual_libraries = ρσ_modules["book_list.library_data"].all_virtual_libraries;
        var book_metadata = ρσ_modules["book_list.library_data"].book_metadata;
        var current_book_ids = ρσ_modules["book_list.library_data"].current_book_ids;
        var current_sorted_field = ρσ_modules["book_list.library_data"].current_sorted_field;
        var ensure_current_library_data = ρσ_modules["book_list.library_data"].ensure_current_library_data;
        var library_data = ρσ_modules["book_list.library_data"].library_data;
        var load_status = ρσ_modules["book_list.library_data"].load_status;
        var loaded_books_query = ρσ_modules["book_list.library_data"].loaded_books_query;
        var thumbnail_cache = ρσ_modules["book_list.library_data"].thumbnail_cache;
        var url_books_query = ρσ_modules["book_list.library_data"].url_books_query;

        var back = ρσ_modules["book_list.router"].back;
        var home = ρσ_modules["book_list.router"].home;
        var push_state = ρσ_modules["book_list.router"].push_state;
        var update_window_title = ρσ_modules["book_list.router"].update_window_title;

        var init_search_panel = ρσ_modules["book_list.search"].init;
        var set_apply_search = ρσ_modules["book_list.search"].set_apply_search;
        var tb_config_panel_handler = ρσ_modules["book_list.search"].tb_config_panel_handler;

        var add_button = ρσ_modules["book_list.top_bar"].add_button;
        var create_top_bar = ρσ_modules["book_list.top_bar"].create_top_bar;

        var query_as_href = ρσ_modules["book_list.ui"].query_as_href;
        var set_panel_handler = ρσ_modules["book_list.ui"].set_panel_handler;
        var show_panel = ρσ_modules["book_list.ui"].show_panel;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var ensure_id = ρσ_modules.dom.ensure_id;
        var set_css = ρσ_modules.dom.set_css;

        var error_dialog = ρσ_modules.modals.error_dialog;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        var conditional_timeout = ρσ_modules.utils.conditional_timeout;
        var parse_url_params = ρσ_modules.utils.parse_url_params;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;

        var create_button = ρσ_modules.widgets.create_button;
        var create_spinner = ρσ_modules.widgets.create_spinner;

        CLASS_NAME = "book-list-container";
        ITEM_CLASS_NAME = "book-list-item";
        ALLOWED_MODES = (function(){
            var s = ρσ_set();
            s.jsset.add("cover_grid");
            s.jsset.add("details_list");
            s.jsset.add("custom_list");
            return s;
        })();
        DEFAULT_MODE = "cover_grid";
        add_extra_css(function () {
            var sel, ans;
            sel = "." + CLASS_NAME + " ";
            ans = ρσ_interpolate_kwargs.call(this, build_rule, [sel + "[data-component=\"top_message\"]"].concat([ρσ_desugar_kwargs({margin: "1ex 1em"})]));
            ans += cover_grid_css();
            ans += details_list_css();
            ans += custom_list_css();
            return ans;
        });
        book_list_data = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["container_id"] = null;
            ρσ_d["shown_book_ids"] = set();
            ρσ_d["mode"] = null;
            ρσ_d["fetching_more_books"] = null;
            return ρσ_d;
        }).call(this);
        function component(name) {
            return document.getElementById(book_list_data.container_id).querySelector("[data-component=\"" + ρσ_str.format("{}", name) + "\"]");
        };
        if (!component.__argnames__) Object.defineProperties(component, {
            __argnames__ : {value: ["name"]}
        });

        function clear_grid() {
            var container, e, bl;
            container = document.getElementById(book_list_data.container_id);
            e = component("book_list");
            bl = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({data_component: "book_list"})]);
            container.insertBefore(bl, e);
            container.removeChild(e);
            book_list_data.init_grid(bl);
        };

        function has_parent_with_class(elem, cls) {
            while (elem) {
                if (elem.classList && elem.classList.contains(cls)) {
                    return elem;
                }
                elem = elem.parentNode;
            }
        };
        if (!has_parent_with_class.__argnames__) Object.defineProperties(has_parent_with_class, {
            __argnames__ : {value: ["elem", "cls"]}
        });

        function save_scroll_position() {
            var container, ρσ_unpack, left, top, elem, p, q, x, y;
            container = document.getElementById(book_list_data.container_id);
            if (container) {
                ρσ_unpack = [container.offsetLeft, container.offsetTop];
                left = ρσ_unpack[0];
                top = ρσ_unpack[1];
                for (var ρσ_Index0 = 5; ρσ_Index0 < 100; ρσ_Index0+=5) {
                    y = ρσ_Index0;
                    for (var ρσ_Index1 = 25; ρσ_Index1 < 125; ρσ_Index1+=5) {
                        x = ρσ_Index1;
                        elem = document.elementFromPoint(left + x, top + y);
                        p = has_parent_with_class(elem, ITEM_CLASS_NAME);
                        if (p) {
                            q = parse_url_params();
                            q.book_id = p.dataset.bookId;
                            ρσ_interpolate_kwargs.call(this, push_state, [q].concat([ρσ_desugar_kwargs({replace: true, call_handler: false})]));
                            return;
                        }
                    }
                }
            }
        };

        function show_subsequent_panel() {
            var name = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var query = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_subsequent_panel.__defaults__.query : arguments[1];
            var replace = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_subsequent_panel.__defaults__.replace : arguments[2];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "query")){
                query = ρσ_kwargs_obj.query;
            }
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "replace")){
                replace = ρσ_kwargs_obj.replace;
            }
            save_scroll_position();
            show_panel(name, query, replace);
        };
        if (!show_subsequent_panel.__defaults__) Object.defineProperties(show_subsequent_panel, {
            __defaults__ : {value: {query:null, replace:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["name", "query", "replace"]}
        });

        function on_book_click(book_id, evt) {
            evt.preventDefault();
            show_subsequent_panel("book_details", (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["book_id"] = book_id;
                return ρσ_d;
            }).call(this));
        };
        if (!on_book_click.__argnames__) Object.defineProperties(on_book_click, {
            __argnames__ : {value: ["book_id", "evt"]}
        });

        function create_image(book_id, max_width, max_height, on_load) {
            return thumbnail_cache.get(book_id, max_width, max_height, on_load);
        };
        if (!create_image.__argnames__) Object.defineProperties(create_image, {
            __argnames__ : {value: ["book_id", "max_width", "max_height", "on_load"]}
        });

        function render_id(book_id) {
            var l, metadata, ans;
            l = book_list_data.shown_book_ids.length;
            book_list_data.shown_book_ids.add(book_id);
            if (l < book_list_data.shown_book_ids.length) {
                metadata = book_metadata(book_id);
                ans = book_list_data.render_book(book_id, metadata, create_image, on_book_click.bind(null, book_id), query_as_href((function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["book_id"] = book_id + "";
                    return ρσ_d;
                }).call(this), "book_details"));
                ans.classList.add(ITEM_CLASS_NAME);
                ans.dataset.bookId = str(book_id);
                return ans;
            }
        };
        if (!render_id.__argnames__) Object.defineProperties(render_id, {
            __argnames__ : {value: ["book_id"]}
        });

        function render_ids(book_ids) {
            var div, child, book_id;
            book_ids = book_ids || current_book_ids();
            div = component("book_list");
            if (div) {
                var ρσ_Iter2 = ρσ_Iterable(book_ids);
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    book_id = ρσ_Iter2[ρσ_Index2];
                    child = render_id(book_id);
                    if (child) {
                        book_list_data.append_item(div, child);
                    }
                }
            }
        };
        if (!render_ids.__argnames__) Object.defineProperties(render_ids, {
            __argnames__ : {value: ["book_ids"]}
        });

        function get_view_mode() {
            var idata, mode;
            idata = get_interface_data();
            mode = get_session_data().get("view_mode", idata.default_book_list_mode);
            if (!ρσ_in(mode, ["cover_grid", "details_list", "custom_list"])) {
                mode = DEFAULT_MODE;
            }
            return mode;
        };

        function setup_view_mode(mode, book_list_data) {
            if (!ρσ_in(mode, ALLOWED_MODES)) {
                mode = DEFAULT_MODE;
            }
            book_list_data.mode = mode;
            if (mode === "cover_grid") {
                book_list_data.render_book = create_cover_grid_item;
                book_list_data.init_grid = init_cover_grid;
                book_list_data.append_item = cover_grid_append_item;
            } else if (mode === "details_list") {
                book_list_data.render_book = create_details_list_item;
                book_list_data.init_grid = init_details_list;
                book_list_data.append_item = details_list_append_item;
            } else if (mode === "custom_list") {
                book_list_data.render_book = create_custom_list_item;
                book_list_data.init_grid = init_custom_list;
                book_list_data.append_item = custom_list_append_item;
            }
            return mode;
        };
        if (!setup_view_mode.__argnames__) Object.defineProperties(setup_view_mode, {
            __argnames__ : {value: ["mode", "book_list_data"]}
        });

        function apply_view_mode() {
            var mode = (arguments[0] === undefined || ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? apply_view_mode.__defaults__.mode : arguments[0];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "mode")){
                mode = ρσ_kwargs_obj.mode;
            }
            if (book_list_data.mode === mode) {
                return;
            }
            setup_view_mode(mode, book_list_data);
            clear_grid();
            render_ids();
        };
        if (!apply_view_mode.__defaults__) Object.defineProperties(apply_view_mode, {
            __defaults__ : {value: {mode:DEFAULT_MODE}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["mode"]}
        });

        function update_fetching_status() {
            var more;
            more = component("more_button");
            if (!more) {
                return;
            }
            if (book_list_data.fetching_more_books) {
                more.firstChild.style.display = "none";
                more.lastChild.style.display = "block";
            } else if (library_data.search_result.total_num > book_list_data.shown_book_ids.length) {
                more.firstChild.style.display = "block";
                more.lastChild.style.display = "none";
            } else {
                more.firstChild.style.display = "none";
                more.lastChild.style.display = "none";
            }
        };

        function abort_get_more_books(no_update) {
            if (book_list_data.fetching_more_books) {
                book_list_data.fetching_more_books.abort();
                book_list_data.fetching_more_books = null;
                if (!no_update) {
                    update_fetching_status();
                }
            }
        };
        if (!abort_get_more_books.__argnames__) Object.defineProperties(abort_get_more_books, {
            __argnames__ : {value: ["no_update"]}
        });

        function got_more_books(end_type, xhr, event) {
            var data;
            if (book_list_data.fetching_more_books !== xhr) {
                return;
            }
            book_list_data.fetching_more_books = null;
            update_fetching_status();
            if (end_type === "load") {
                try {
                    data = JSON.parse(xhr.responseText);
                    if (!data.search_result.book_ids) {
                        throw new Exception("No books ids object in search result from server");
                    }
                    add_more_books(data);
                    render_ids(data.search_result.book_ids);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        error_dialog(_("Could not get more books"), _("Server returned an invalid response"), traceback.format_exc());
                    } else {
                        throw ρσ_Exception;
                    }
                }
            } else if (end_type !== "abort") {
                error_dialog(_("Could not get more books"), xhr.error_html);
            }
        };
        if (!got_more_books.__argnames__) Object.defineProperties(got_more_books, {
            __argnames__ : {value: ["end_type", "xhr", "event"]}
        });

        function get_more_books() {
            var data, key;
            data = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["offset"] = book_list_data.shown_book_ids.length;
                return ρσ_d;
            }).call(this);
            var ρσ_Iter3 = ρσ_Iterable(ρσ_list_decorate([ "query", "sort", "sort_order", "vl" ]));
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                key = ρσ_Iter3[ρσ_Index3];
                data[(typeof key === "number" && key < 0) ? data.length + key : key] = (ρσ_expr_temp = library_data.search_result)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
            }
            book_list_data.fetching_more_books = ρσ_interpolate_kwargs.call(this, ajax_send, ["interface-data/more-books", data, got_more_books].concat([ρσ_desugar_kwargs({query: (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["library_id"] = loaded_books_query().library_id;
                return ρσ_d;
            }).call(this)})]));
            update_fetching_status();
        };

        function create_more_button(more) {
            more.appendChild(create_button(_("Show more books"), "cloud-download", get_more_books));
            more.lastChild.setAttribute("rel", "next");
            ρσ_interpolate_kwargs.call(this, set_css, [more.firstChild].concat([ρσ_desugar_kwargs({display: "block", margin_left: "auto", margin_right: "auto"})]));
            ρσ_interpolate_kwargs.call(this, set_css, [more].concat([ρσ_desugar_kwargs({font_size: "1.5rem", padding_top: "1.5rem", margin_bottom: "1.5rem", text_align: "center", display: "flex"})]));
            more.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [create_spinner(), " " + _("Fetching metadata for more books, please wait") + "…"].concat([ρσ_desugar_kwargs({style: "margin-left:auto; margin-right:auto; display:none"})])));
            update_fetching_status();
        };
        if (!create_more_button.__argnames__) Object.defineProperties(create_more_button, {
            __argnames__ : {value: ["more"]}
        });

        function show_top_message() {
            var container, q, text;
            container = component("top_message");
            q = loaded_books_query();
            if (!q.search && !q.vl) {
                container.style.display = "none";
                return;
            }
            if (q.vl) {
                container.appendChild(E.span(E.span(_("Showing Virtual library: {} ").format(q.vl)), create_button(_("Close"), "close", function () {
                    show_vl();
                }, _("Show all books in library"))));
                if (q.search) {
                    container.appendChild(E.br());
                }
            }
            if (q.search) {
                text = _("Showing books matching: {} ");
                if (!library_data.search_result.total_num) {
                    text = _("No books matching: {} ");
                }
                container.appendChild(E.span(E.span(text.format(library_data.search_result.query)), create_button(_("Clear"), "close", function () {
                    search();
                }, _("Clear this search"))));
            }
        };

        function create_books_list(container) {
            var q, scrolled, e, div;
            book_list_data.container_id = ensure_id(container);
            book_list_data.shown_book_ids = set();
            book_list_data.mode = null;
            abort_get_more_books(true);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({data_component: "top_message"})]));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({data_component: "book_list"})]));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({data_component: "more_button"})]));
            show_top_message();
            apply_view_mode(get_view_mode());
            create_more_button(container.lastChild);
            ρσ_interpolate_kwargs.call(this, add_button, [container.parentNode].concat([ρσ_desugar_kwargs({icon: "plus", action: show_subsequent_panel.bind(null, "book_list^add"), tooltip: _("Add books")})]));
            ρσ_interpolate_kwargs.call(this, add_button, [container.parentNode].concat([ρσ_desugar_kwargs({icon: "sort-amount-desc", action: show_subsequent_panel.bind(null, "book_list^sort"), tooltip: _("Sort books")})]));
            ρσ_interpolate_kwargs.call(this, add_button, [container.parentNode].concat([ρσ_desugar_kwargs({icon: "search", action: show_subsequent_panel.bind(null, "book_list^search"), tooltip: _("Search for books")})]));
            ρσ_interpolate_kwargs.call(this, add_button, [container.parentNode].concat([ρσ_desugar_kwargs({icon: "ellipsis-v", action: show_subsequent_panel.bind(null, "book_list^more_actions"), tooltip: _("More actions")})]));
            q = parse_url_params();
            scrolled = false;
            if (q.book_id) {
                e = container.querySelector("." + ρσ_str.format("{}", ITEM_CLASS_NAME) + "[data-book-id=\"" + ρσ_str.format("{}", q.book_id) + "\"]");
                if (e && e.scrollIntoView) {
                    e.scrollIntoView(true);
                    window.scrollBy(0, -container.offsetTop);
                    scrolled = true;
                }
            }
            if (!scrolled) {
                window.scrollTo(0, 0);
            }
            q = loaded_books_query();
            if (!q.search && library_data.search_result.total_num < 1) {
                div = component("book_list");
                div.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("No books found")].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])));
            }
        };
        if (!create_books_list.__argnames__) Object.defineProperties(create_books_list, {
            __argnames__ : {value: ["container"]}
        });

        function check_for_books_loaded() {
            var container, container_id, err;
            container = this;
            container_id = container.id;
            if (load_status.loading) {
                conditional_timeout(container_id, 5, check_for_books_loaded);
                return;
            }
            container = container.lastChild;
            clear(container);
            if (!load_status.ok) {
                if (load_status.http_error_code === 401) {
                    container.appendChild(E.div(_("Username/password required, retrying...")));
                    ensure_current_library_data();
                    conditional_timeout(container_id, 100, check_for_books_loaded);
                    return;
                }
                err = E.div();
                safe_set_inner_html(err, load_status.error_html);
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.div(_("Failed to load books from calibre library, with error:")), err, ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.a, [_("Go back to the home page")].concat([ρσ_desugar_kwargs({onclick: function () {
                    ρσ_interpolate_kwargs.call(this, home, [ρσ_desugar_kwargs({replace: true})]);
                }, href: "javascript: void(0)", class_: "blue-link"})]))].concat([ρσ_desugar_kwargs({style: "margin-top: 1em; border-top: solid 1px currentColor; padding-top: 1ex;"})]))].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])));
                return;
            }
            create_books_list(container);
        };

        function init(container_id) {
            var interface_data, container, lid, title;
            interface_data = get_interface_data();
            ensure_current_library_data();
            container = document.getElementById(container_id);
            lid = container.dataset.library_id = url_books_query().library_id;
            title = (ρσ_expr_temp = interface_data.library_map)[(typeof lid === "number" && lid < 0) ? ρσ_expr_temp.length + lid : lid];
            update_window_title(title);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: title, action: function () {
                [save_scroll_position(), home()];
            }, icon: "home"})]));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: CLASS_NAME})]));
            container.lastChild.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Loading books from the {} calibre library, please wait...").format(title)].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])));
            conditional_timeout(container_id, 5, check_for_books_loaded);
        };
        if (!init.__argnames__) Object.defineProperties(init, {
            __argnames__ : {value: ["container_id"]}
        });

        function change_sort(field, order) {
            var sd, so, q;
            abort_get_more_books();
            sd = get_session_data();
            so = sd.get("last_sort_order");
            order = order || so[(typeof field === "number" && field < 0) ? so.length + field : field] || "asc";
            order = (order === "asc") ? "asc" : "desc";
            q = loaded_books_query();
            q.sort = field + "." + order;
            so[(typeof field === "number" && field < 0) ? so.length + field : field] = order;
            sd.set("last_sort_order", so);
            sd.set_library_option(q.library_id, "sort", q.sort);
            ρσ_interpolate_kwargs.call(this, show_panel, ["book_list"].concat([ρσ_desugar_kwargs({query: q, replace: true})]));
        };
        if (!change_sort.__argnames__) Object.defineProperties(change_sort, {
            __argnames__ : {value: ["field", "order"]}
        });

        function create_sort_panel(container_id) {
            var container, ρσ_unpack, close_action, close_icon, items, csf, csf_order, new_sort_order, subtitle, icon_name, action, field, name;
            if (!library_data.sortable_fields) {
                ρσ_interpolate_kwargs.call(this, show_panel, ["book_list"].concat([ρσ_desugar_kwargs({replace: true})]));
                return;
            }
            container = document.getElementById(container_id);
            ρσ_unpack = [back, "close"];
            close_action = ρσ_unpack[0];
            close_icon = ρσ_unpack[1];
            if (parse_url_params().close_action === "home") {
                ρσ_unpack = [function () {
                    home();
                }, "home"];
                close_action = ρσ_unpack[0];
                close_icon = ρσ_unpack[1];
            }
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("Sort books by…"), action: close_action, icon: close_icon})]));
            items = ρσ_list_decorate([]);
            ρσ_unpack = current_sorted_field();
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            csf = ρσ_unpack[0];
            csf_order = ρσ_unpack[1];
            new_sort_order = (csf_order === "asc") ? "desc" : "asc";
            if (csf === "date") {
                csf = "timestamp";
            }
            var ρσ_Iter4 = ρσ_Iterable(library_data.sortable_fields);
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                ρσ_unpack = ρσ_Iter4[ρσ_Index4];
                field = ρσ_unpack[0];
                name = ρσ_unpack[1];
                subtitle = icon_name = null;
                if (field === csf) {
                    subtitle = _("Reverse current sort order");
                    icon_name = (csf_order === "asc") ? "sort-amount-asc" : "sort-amount-desc";
                    action = change_sort.bind(null, field, new_sort_order);
                } else {
                    action = change_sort.bind(null, field, null);
                }
                items.push(ρσ_interpolate_kwargs.call(this, create_item, [name].concat([ρσ_desugar_kwargs({subtitle: subtitle, icon: icon_name, action: action})])));
            }
            container.appendChild(E.div());
            create_item_list(container.lastChild, items, _("Change how the list of books is sorted"));
        };
        if (!create_sort_panel.__argnames__) Object.defineProperties(create_sort_panel, {
            __argnames__ : {value: ["container_id"]}
        });

        function search_query_for(query) {
            var q;
            q = loaded_books_query();
            if (query) {
                q.search = query;
            } else {
                delete q.search;
            }
            return q;
        };
        if (!search_query_for.__argnames__) Object.defineProperties(search_query_for, {
            __argnames__ : {value: ["query"]}
        });

        function search() {
            var query = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var replace = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? search.__defaults__.replace : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "replace")){
                replace = ρσ_kwargs_obj.replace;
            }
            ρσ_interpolate_kwargs.call(this, show_panel, ["book_list"].concat([ρσ_desugar_kwargs({query: search_query_for(query), replace: replace})]));
        };
        if (!search.__defaults__) Object.defineProperties(search, {
            __defaults__ : {value: {replace:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["query", "replace"]}
        });

        set_apply_search((function() {
            var ρσ_anonfunc = function (query) {
                search(query, true);
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["query"]}
            });
            return ρσ_anonfunc;
        })());
        function create_vl_panel(container_id) {
            var container, items, vls, vl_names, name;
            if (!library_data.sortable_fields) {
                ρσ_interpolate_kwargs.call(this, show_panel, ["book_list"].concat([ρσ_desugar_kwargs({replace: true})]));
                return;
            }
            container = document.getElementById(container_id);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("Choose Virtual library…"), action: back, icon: "close"})]));
            items = ρσ_list_decorate([]);
            vls = all_virtual_libraries();
            vl_names = Object.keys(vls).sort((function() {
                var ρσ_anonfunc = function (a, b) {
                    return a.toLowerCase().localeCompare(b.toLowerCase());
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["a", "b"]}
                });
                return ρσ_anonfunc;
            })());
            var ρσ_Iter5 = ρσ_Iterable(vl_names);
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                name = ρσ_Iter5[ρσ_Index5];
                items.push(ρσ_interpolate_kwargs.call(this, create_item, [name].concat([ρσ_desugar_kwargs({subtitle: vls[(typeof name === "number" && name < 0) ? vls.length + name : name], action: show_vl.bind(null, name, true)})])));
            }
            container.appendChild(E.div());
            create_item_list(container.lastChild, items, _("Choose a Virtual library to browse from the list below"));
        };
        if (!create_vl_panel.__argnames__) Object.defineProperties(create_vl_panel, {
            __argnames__ : {value: ["container_id"]}
        });

        function show_vl(vl_name, replace) {
            var q;
            q = loaded_books_query();
            q.vl = vl_name || null;
            ρσ_interpolate_kwargs.call(this, show_panel, ["book_list"].concat([ρσ_desugar_kwargs({query: q, replace: replace || false})]));
        };
        if (!show_vl.__argnames__) Object.defineProperties(show_vl, {
            __argnames__ : {value: ["vl_name", "replace"]}
        });

        function create_mode_panel(container_id) {
            var container, items, current_mode;
            if (!library_data.sortable_fields) {
                ρσ_interpolate_kwargs.call(this, show_panel, ["book_list"].concat([ρσ_desugar_kwargs({replace: true})]));
                return;
            }
            container = document.getElementById(container_id);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("Choose book list mode…"), action: back, icon: "close"})]));
            items = ρσ_list_decorate([]);
            current_mode = get_view_mode();
            function ci(title, desc, name) {
                var ic;
                ic = (name === current_mode) ? "check" : null;
                items.push(ρσ_interpolate_kwargs.call(this, create_item, [title].concat([ρσ_desugar_kwargs({subtitle: desc, icon: ic, action: function () {
                    if (name !== current_mode) {
                        get_session_data().set("view_mode", name);
                    }
                    back();
                }})])));
            };
            if (!ci.__argnames__) Object.defineProperties(ci, {
                __argnames__ : {value: ["title", "desc", "name"]}
            });

            ci(_("Cover grid"), COVER_GRID_DESCRIPTION(), "cover_grid");
            ci(_("Detailed list"), DETAILS_LIST_DESCRIPTION(), "details_list");
            ci(_("Custom list"), CUSTOM_LIST_DESCRIPTION(), "custom_list");
            container.appendChild(E.div());
            create_item_list(container.lastChild, items, _("Choose a display mode for the list of books from below"));
        };
        if (!create_mode_panel.__argnames__) Object.defineProperties(create_mode_panel, {
            __argnames__ : {value: ["container_id"]}
        });

        function create_more_actions_panel(container_id) {
            var container, items, vls;
            container = document.getElementById(container_id);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("More actions…"), action: back, icon: "close"})]));
            items = ρσ_list_decorate([ ρσ_interpolate_kwargs.call(this, create_item, [_("Book list mode")].concat([ρσ_desugar_kwargs({subtitle: _("Change how the list of books is displayed"), action: function () {
                ρσ_interpolate_kwargs.call(this, show_panel, ["book_list^choose_mode"].concat([ρσ_desugar_kwargs({replace: true})]));
            }})])), ρσ_interpolate_kwargs.call(this, create_item, [_("A random book")].concat([ρσ_desugar_kwargs({subtitle: _("Choose a random book from the library"), action: function () {
                var query;
                query = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["book_id"] = "0";
                    return ρσ_d;
                }).call(this);
                ρσ_interpolate_kwargs.call(this, show_panel, ["book_details"].concat([ρσ_desugar_kwargs({query: query, replace: true})]));
            }})])) ]);
            vls = all_virtual_libraries();
            if (vls && Object.keys(vls).length > 0) {
                items.insert(1, ρσ_interpolate_kwargs.call(this, create_item, [_("Choose Virtual library")].concat([ρσ_desugar_kwargs({subtitle: _("Browse books in a Virtual library"), action: function () {
                    ρσ_interpolate_kwargs.call(this, show_panel, ["book_list^vl"].concat([ρσ_desugar_kwargs({replace: true})]));
                }})])));
            }
            container.appendChild(E.div());
            create_item_list(container.lastChild, items);
        };
        if (!create_more_actions_panel.__argnames__) Object.defineProperties(create_more_actions_panel, {
            __argnames__ : {value: ["container_id"]}
        });

        function create_add_panel(container_id) {
            if (!library_data.sortable_fields) {
                ρσ_interpolate_kwargs.call(this, show_panel, ["book_list"].concat([ρσ_desugar_kwargs({replace: true})]));
                return;
            }
            add_books_panel(container_id);
        };
        if (!create_add_panel.__argnames__) Object.defineProperties(create_add_panel, {
            __argnames__ : {value: ["container_id"]}
        });

        set_panel_handler("book_list", init);
        set_panel_handler("book_list^add", create_add_panel);
        set_panel_handler("book_list^sort", create_sort_panel);
        set_panel_handler("book_list^vl", create_vl_panel);
        set_panel_handler("book_list^search", init_search_panel);
        set_panel_handler("book_list^choose_mode", create_mode_panel);
        set_panel_handler("book_list^search^prefs", tb_config_panel_handler());
        set_panel_handler("book_list^more_actions", create_more_actions_panel);
        ρσ_modules["book_list.views"].CLASS_NAME = CLASS_NAME;
        ρσ_modules["book_list.views"].ITEM_CLASS_NAME = ITEM_CLASS_NAME;
        ρσ_modules["book_list.views"].ALLOWED_MODES = ALLOWED_MODES;
        ρσ_modules["book_list.views"].DEFAULT_MODE = DEFAULT_MODE;
        ρσ_modules["book_list.views"].book_list_data = book_list_data;
        ρσ_modules["book_list.views"].component = component;
        ρσ_modules["book_list.views"].clear_grid = clear_grid;
        ρσ_modules["book_list.views"].has_parent_with_class = has_parent_with_class;
        ρσ_modules["book_list.views"].save_scroll_position = save_scroll_position;
        ρσ_modules["book_list.views"].show_subsequent_panel = show_subsequent_panel;
        ρσ_modules["book_list.views"].on_book_click = on_book_click;
        ρσ_modules["book_list.views"].create_image = create_image;
        ρσ_modules["book_list.views"].render_id = render_id;
        ρσ_modules["book_list.views"].render_ids = render_ids;
        ρσ_modules["book_list.views"].get_view_mode = get_view_mode;
        ρσ_modules["book_list.views"].setup_view_mode = setup_view_mode;
        ρσ_modules["book_list.views"].apply_view_mode = apply_view_mode;
        ρσ_modules["book_list.views"].update_fetching_status = update_fetching_status;
        ρσ_modules["book_list.views"].abort_get_more_books = abort_get_more_books;
        ρσ_modules["book_list.views"].got_more_books = got_more_books;
        ρσ_modules["book_list.views"].get_more_books = get_more_books;
        ρσ_modules["book_list.views"].create_more_button = create_more_button;
        ρσ_modules["book_list.views"].show_top_message = show_top_message;
        ρσ_modules["book_list.views"].create_books_list = create_books_list;
        ρσ_modules["book_list.views"].check_for_books_loaded = check_for_books_loaded;
        ρσ_modules["book_list.views"].init = init;
        ρσ_modules["book_list.views"].change_sort = change_sort;
        ρσ_modules["book_list.views"].create_sort_panel = create_sort_panel;
        ρσ_modules["book_list.views"].search_query_for = search_query_for;
        ρσ_modules["book_list.views"].search = search;
        ρσ_modules["book_list.views"].create_vl_panel = create_vl_panel;
        ρσ_modules["book_list.views"].show_vl = show_vl;
        ρσ_modules["book_list.views"].create_mode_panel = create_mode_panel;
        ρσ_modules["book_list.views"].create_more_actions_panel = create_more_actions_panel;
        ρσ_modules["book_list.views"].create_add_panel = create_add_panel;
    })();

    (function(){
        var __name__ = "book_list.book_details";
        var bd_counter, CLASS_NAME, SEARCH_INTERNET_CLASS, COPY_TO_LIBRARY_CLASS, FORMAT_PRIORITIES, IGNORED_FIELDS, default_sort, ρσ_unpack, i, f, current_fetch;
        var traceback = ρσ_modules.traceback;

        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var ajax = ρσ_modules.ajax.ajax;
        var ajax_send = ρσ_modules.ajax.ajax_send;
        var encode_query_component = ρσ_modules.ajax.encode_query_component;

        var refresh_after_delete = ρσ_modules["book_list.delete_book"].refresh_after_delete;
        var start_delete_book = ρσ_modules["book_list.delete_book"].start_delete_book;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var create_item = ρσ_modules["book_list.item_list"].create_item;
        var create_item_list = ρσ_modules["book_list.item_list"].create_item_list;

        var all_libraries = ρσ_modules["book_list.library_data"].all_libraries;
        var book_after = ρσ_modules["book_list.library_data"].book_after;
        var book_metadata = ρσ_modules["book_list.library_data"].book_metadata;
        var cover_url = ρσ_modules["book_list.library_data"].cover_url;
        var current_library_id = ρσ_modules["book_list.library_data"].current_library_id;
        var current_virtual_library = ρσ_modules["book_list.library_data"].current_virtual_library;
        var download_url = ρσ_modules["book_list.library_data"].download_url;
        var library_data = ρσ_modules["book_list.library_data"].library_data;
        var load_status = ρσ_modules["book_list.library_data"].load_status;
        var set_book_metadata = ρσ_modules["book_list.library_data"].set_book_metadata;

        var back = ρσ_modules["book_list.router"].back;
        var home = ρσ_modules["book_list.router"].home;
        var open_book = ρσ_modules["book_list.router"].open_book;
        var report_a_load_failure = ρσ_modules["book_list.router"].report_a_load_failure;

        var get_color = ρσ_modules["book_list.theme"].get_color;
        var get_color_as_rgba = ρσ_modules["book_list.theme"].get_color_as_rgba;
        var get_font_size = ρσ_modules["book_list.theme"].get_font_size;

        var add_button = ρσ_modules["book_list.top_bar"].add_button;
        var clear_buttons = ρσ_modules["book_list.top_bar"].clear_buttons;
        var create_top_bar = ρσ_modules["book_list.top_bar"].create_top_bar;
        var set_title = ρσ_modules["book_list.top_bar"].set_title;

        var query_as_href = ρσ_modules["book_list.ui"].query_as_href;
        var set_panel_handler = ρσ_modules["book_list.ui"].set_panel_handler;
        var show_panel = ρσ_modules["book_list.ui"].show_panel;

        var search_query_for = ρσ_modules["book_list.views"].search_query_for;

        var format_date = ρσ_modules.date.format_date;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var ensure_id = ρσ_modules.dom.ensure_id;
        var svgicon = ρσ_modules.dom.svgicon;
        var unique_id = ρσ_modules.dom.unique_id;

        var create_custom_dialog = ρσ_modules.modals.create_custom_dialog;
        var error_dialog = ρσ_modules.modals.error_dialog;
        var warning_dialog = ρσ_modules.modals.warning_dialog;

        var get_interface_data = ρσ_modules.session.get_interface_data;

        var conditional_timeout = ρσ_modules.utils.conditional_timeout;
        var debounce = ρσ_modules.utils.debounce;
        var fmt_sidx = ρσ_modules.utils.fmt_sidx;
        var human_readable = ρσ_modules.utils.human_readable;
        var parse_url_params = ρσ_modules.utils.parse_url_params;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;
        var sandboxed_html = ρσ_modules.utils.sandboxed_html;

        var create_button = ρσ_modules.widgets.create_button;
        var create_spinner = ρσ_modules.widgets.create_spinner;

        bd_counter = 0;
        CLASS_NAME = "book-details-panel";
        SEARCH_INTERNET_CLASS = "book-details-search-internet";
        COPY_TO_LIBRARY_CLASS = "book-details-copy-to-library";
        FORMAT_PRIORITIES = ρσ_list_decorate([ "EPUB", "AZW3", "DOCX", "LIT", "MOBI", "ODT", "RTF", "MD", "MARKDOWN", "TXT", "PDF" ]);
        function sort_formats_key(fmt) {
            var ans;
            ans = FORMAT_PRIORITIES.indexOf(fmt);
            if (ans < 0) {
                ans = FORMAT_PRIORITIES.length;
            }
            return ans;
        };
        if (!sort_formats_key.__argnames__) Object.defineProperties(sort_formats_key, {
            __argnames__ : {value: ["fmt"]}
        });

        function get_preferred_format(metadata, output_format, input_formats) {
            var formats, f, fmt, q;
            formats = metadata && metadata.formats || [];
            formats = (function() {
                var ρσ_Iter = ρσ_Iterable(formats), ρσ_Result = [], f;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    f = ρσ_Iter[ρσ_Index];
                    ρσ_Result.push(f.toUpperCase());
                }
                ρσ_Result = ρσ_list_constructor(ρσ_Result);
                return ρσ_Result;
            })();
            fmt = (output_format === "PDF") ? "EPUB" : output_format;
            if (formats.length && formats.indexOf(fmt) === -1) {
                var ρσ_Iter0 = ρσ_Iterable(ρσ_interpolate_kwargs.call(this, sorted, [formats].concat([ρσ_desugar_kwargs({key: sort_formats_key})])));
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    q = ρσ_Iter0[ρσ_Index0];
                    if (input_formats[(typeof q === "number" && q < 0) ? input_formats.length + q : q]) {
                        fmt = q;
                        break;
                    }
                }
            }
            return fmt.toUpperCase();
        };
        if (!get_preferred_format.__argnames__) Object.defineProperties(get_preferred_format, {
            __argnames__ : {value: ["metadata", "output_format", "input_formats"]}
        });

        IGNORED_FIELDS = (function(){
            var s = ρσ_set();
            s.jsset.add("title");
            s.jsset.add("sort");
            s.jsset.add("uuid");
            s.jsset.add("id");
            s.jsset.add("urls_from_identifiers");
            s.jsset.add("lang_names");
            s.jsset.add("last_modified");
            s.jsset.add("path");
            return s;
        })();
        default_sort = (function() {
            var ρσ_Iter = ρσ_Iterable(enumerate(["title", "title_sort", "authors", "author_sort", 
            "series", "rating", "pubdate", "tags", "timestamp", "pubdate", "identifiers", "languages", 
            "publisher", "last_modified"])), ρσ_Result = Object.create(null), i, f;
            for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                ρσ_unpack = ρσ_Iter[ρσ_Index];
                i = ρσ_unpack[0];
                f = ρσ_unpack[1];
                ρσ_Result[f] = (i + 1);
            }
            return ρσ_Result;
        })();
        default_sort["formats"] = 999;
        function field_sorter(field_metadata) {
            return (function() {
                var ρσ_anonfunc = function (field) {
                    var lvl, fm;
                    lvl = "{:03d}".format(default_sort[(typeof field === "number" && field < 0) ? default_sort.length + field : field] || 998);
                    fm = (ρσ_expr_temp = (field_metadata[(typeof field === "number" && field < 0) ? field_metadata.length + field : field] || Object.create(null)))[(typeof field === "number" && field < 0) ? ρσ_expr_temp.length + field : field] || Object.create(null);
                    return lvl + (fm.name || "zzzzz");
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["field"]}
                });
                return ρσ_anonfunc;
            })();
        };
        if (!field_sorter.__argnames__) Object.defineProperties(field_sorter, {
            __argnames__ : {value: ["field_metadata"]}
        });

        function href_for_search(name, val) {
            var query, q;
            query = "{}:\"={}\"".format(name, str.replace(val, "\"", "\\\""));
            q = search_query_for(query);
            return query_as_href(q);
        };
        if (!href_for_search.__argnames__) Object.defineProperties(href_for_search, {
            __argnames__ : {value: ["name", "val"]}
        });

        function on_fmt_click(ev) {
            var fmt, book_id, ρσ_unpack, title, sz;
            fmt = ev.currentTarget.dataset.format;
            book_id = int(ev.currentTarget.dataset.bookId);
            ρσ_unpack = this;
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            title = ρσ_unpack[0];
            sz = ρσ_unpack[1];
            create_custom_dialog(title, (function() {
                var ρσ_anonfunc = function (parent, close_modal) {
                    function action(which) {
                        close_modal();
                        which(book_id, fmt);
                    };
                    if (!action.__argnames__) Object.defineProperties(action, {
                        __argnames__ : {value: ["which"]}
                    });

                    parent.appendChild(E.div(E.div(_("What would you like to do with the {} format?").format(fmt)), ρσ_interpolate_kwargs.call(E, E.div, [create_button(_("Read"), "book", action.bind(null, read_format)), " ", ρσ_interpolate_kwargs.call(this, create_button, [_("Download"), "cloud-download", download_url(book_id, fmt), _("File size: {}").format(human_readable(sz))].concat([ρσ_desugar_kwargs({download_filename: "" + ρσ_str.format("{}", title) + "." + ρσ_str.format("{}", fmt.toLowerCase()) + ""})]))].concat([ρσ_desugar_kwargs({class_: "button-box"})]))));
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["parent", "close_modal"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!on_fmt_click.__argnames__) Object.defineProperties(on_fmt_click, {
            __argnames__ : {value: ["ev"]}
        });

        function adjust_iframe_height(iframe) {
            var de;
            de = iframe.contentWindow.document.documentElement;
            iframe.style.height = de.offsetHeight + 5 + "px";
            iframe.dataset.last_window_width = window.innerWidth + "";
            return de;
        };
        if (!adjust_iframe_height.__argnames__) Object.defineProperties(adjust_iframe_height, {
            __argnames__ : {value: ["iframe"]}
        });

        function setup_iframe(iframe) {
            var de, a;
            de = adjust_iframe_height(iframe);
            var ρσ_Iter1 = ρσ_Iterable(de.querySelectorAll("a[href]"));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                a = ρσ_Iter1[ρσ_Index1];
                a.setAttribute("target", "_blank");
            }
        };
        if (!setup_iframe.__argnames__) Object.defineProperties(setup_iframe, {
            __argnames__ : {value: ["iframe"]}
        });

        function adjust_all_iframes(ev) {
            var ww, iframe;
            var ρσ_Iter2 = ρσ_Iterable(document.querySelectorAll("." + ρσ_str.format("{}", CLASS_NAME) + " iframe"));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                iframe = ρσ_Iter2[ρσ_Index2];
                ww = parseInt(iframe.dataset.last_window_width);
                if (ww !== window.innerWidth) {
                    adjust_iframe_height(iframe);
                }
            }
        };
        if (!adjust_all_iframes.__argnames__) Object.defineProperties(adjust_all_iframes, {
            __argnames__ : {value: ["ev"]}
        });

        function add_stars_to(stars, val, allow_half_stars) {
            var i;
            for (var ρσ_Index3 = 0; ρσ_Index3 < Math.floor(val / 2); ρσ_Index3++) {
                i = ρσ_Index3;
                stars.appendChild(svgicon("star"));
            }
            if (allow_half_stars && val % 2) {
                stars.appendChild(svgicon("star-half"));
            }
        };
        if (!add_stars_to.__argnames__) Object.defineProperties(add_stars_to, {
            __argnames__ : {value: ["stars", "val", "allow_half_stars"]}
        });

        window.addEventListener("resize", debounce(adjust_all_iframes, 250));
        function adjusting_sandboxed_html(html) {
            var css, ans;
            css = "html, body {{ overflow: hidden; color: {} }}".format(get_color("window-foreground"));
            ans = sandboxed_html(html, css, "allow-same-origin allow-popups allow-popups-to-escape-sandbox");
            ans.addEventListener("load", (function() {
                var ρσ_anonfunc = function (ev) {
                    setup_iframe(ev.target);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })());
            ans.style.height = "50vh";
            ans.dataset.last_window_width = "0";
            return ans;
        };
        if (!adjusting_sandboxed_html.__argnames__) Object.defineProperties(adjusting_sandboxed_html, {
            __argnames__ : {value: ["html"]}
        });

        function render_metadata(mi, table, book_id) {
            var field_metadata, interface_data, fields, comments, fm, field, all_html, name, ρσ_unpack, comment, iframe;
            field_metadata = library_data.field_metadata;
            interface_data = get_interface_data();
            function allowed_fields(field) {
                var fm;
                if (field.endswith("_index")) {
                    fm = field_metadata[ρσ_bound_index(field.slice(0, -len("_index")), field_metadata)];
                    if (fm && fm.datatype === "series") {
                        return false;
                    }
                }
                if (field.startswith("#")) {
                    return true;
                }
                if (ρσ_in(field, IGNORED_FIELDS) || field.endswith("_sort")) {
                    return false;
                }
                if (mi[(typeof field === "number" && field < 0) ? mi.length + field : field] === undefined) {
                    return false;
                }
                return true;
            };
            if (!allowed_fields.__argnames__) Object.defineProperties(allowed_fields, {
                __argnames__ : {value: ["field"]}
            });

            fields = library_data.book_display_fields;
            if (!fields || !fields.length || get_session_data().get("show_all_metadata")) {
                fields = ρσ_interpolate_kwargs.call(this, sorted, [filter(allowed_fields, mi)].concat([ρσ_desugar_kwargs({key: field_sorter(field_metadata)})]));
            } else {
                fields = filter(allowed_fields, fields);
            }
            comments = [];
            function add_row() {
                var name = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
                var val = ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[1];
                var is_searchable = (arguments[2] === undefined || ( 2 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? add_row.__defaults__.is_searchable : arguments[2];
                var is_html = (arguments[3] === undefined || ( 3 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? add_row.__defaults__.is_html : arguments[3];
                var join = (arguments[4] === undefined || ( 4 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? add_row.__defaults__.join : arguments[4];
                var ρσ_kwargs_obj = arguments[arguments.length-1];
                if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
                if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "is_searchable")){
                    is_searchable = ρσ_kwargs_obj.is_searchable;
                }
                if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "is_html")){
                    is_html = ρσ_kwargs_obj.is_html;
                }
                if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "join")){
                    join = ρσ_kwargs_obj.join;
                }
                var v;
                if (val === undefined || val === null) {
                    return;
                }
                function add_val(v) {
                    if (!v.appendChild) {
                        v += "";
                    }
                    if (is_searchable) {
                        table.lastChild.lastChild.appendChild(ρσ_interpolate_kwargs.call(E, E.a, [v].concat([ρσ_desugar_kwargs({title: _("Click to see books with {0}: {1}").format(name, v), class_: "blue-link", href: href_for_search(is_searchable, v)})])));
                    } else {
                        if (v.appendChild) {
                            table.lastChild.lastChild.appendChild(v);
                        } else {
                            table.lastChild.lastChild.appendChild(document.createTextNode(v));
                        }
                    }
                };
                if (!add_val.__argnames__) Object.defineProperties(add_val, {
                    __argnames__ : {value: ["v"]}
                });

                table.appendChild(E.tr(E.td(name + ":"), E.td()));
                if (is_html && /[<>]/.test(val + "")) {
                    table.lastChild.lastChild.appendChild(adjusting_sandboxed_html(val + ""));
                } else {
                    if (!join) {
                        add_val(val);
                    } else {
                        var ρσ_Iter4 = ρσ_Iterable(val);
                        for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                            v = ρσ_Iter4[ρσ_Index4];
                            add_val(v);
                            if (v !== val[val.length-1]) {
                                table.lastChild.lastChild.appendChild(document.createTextNode(join));
                            }
                        }
                    }
                }
                return table.lastChild.lastChild;
            };
            if (!add_row.__defaults__) Object.defineProperties(add_row, {
                __defaults__ : {value: {is_searchable:false, is_html:false, join:null}},
                __handles_kwarg_interpolation__ : {value: true},
                __argnames__ : {value: ["name", "val", "is_searchable", "is_html", "join"]}
            });

            function process_composite(field, fm, name, val) {
                var all_vals;
                if (fm.display && fm.display.contains_html) {
                    ρσ_interpolate_kwargs.call(this, add_row, [name, val].concat([ρσ_desugar_kwargs({is_html: true})]));
                    return;
                }
                if (fm.is_multiple && fm.is_multiple.list_to_ui) {
                    all_vals = filter(null, map(str.strip, val.split(fm.is_multiple.list_to_ui)));
                    ρσ_interpolate_kwargs.call(this, add_row, [name, all_vals].concat([ρσ_desugar_kwargs({is_searchable: field, join: fm.is_multiple.list_to_ui})]));
                } else {
                    ρσ_interpolate_kwargs.call(this, add_row, [name, val].concat([ρσ_desugar_kwargs({is_searchable: field})]));
                }
            };
            if (!process_composite.__argnames__) Object.defineProperties(process_composite, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_authors(field, fm, name, val) {
                ρσ_interpolate_kwargs.call(this, add_row, [name, val].concat([ρσ_desugar_kwargs({is_searchable: field, join: " & "})]));
            };
            if (!process_authors.__argnames__) Object.defineProperties(process_authors, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_publisher(field, fm, name, val) {
                ρσ_interpolate_kwargs.call(this, add_row, [name, val].concat([ρσ_desugar_kwargs({is_searchable: field})]));
            };
            if (!process_publisher.__argnames__) Object.defineProperties(process_publisher, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_formats(field, fm, name, val) {
                var td, fmt;
                if (val.length && (typeof book_id !== "undefined" && book_id !== null)) {
                    table.appendChild(E.tr(E.td(name + ":"), E.td()));
                    td = table.lastChild.lastChild;
                    var ρσ_Iter5 = ρσ_Iterable(val);
                    for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                        fmt = ρσ_Iter5[ρσ_Index5];
                        fmt = fmt.toUpperCase();
                        td.appendChild(ρσ_interpolate_kwargs.call(E, E.a, [fmt].concat([ρσ_desugar_kwargs({class_: "blue-link", href: "javascript:void(0)", title: _("Read or download this book in the {} format").format(fmt), onclick: on_fmt_click.bind([mi.title, mi.format_sizes[fmt] || 0]), data_format: fmt, data_book_id: "" + book_id})])));
                        if (fmt !== val[val.length-1]) {
                            td.appendChild(document.createTextNode(", "));
                        }
                    }
                }
            };
            if (!process_formats.__argnames__) Object.defineProperties(process_formats, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_rating(field, fm, name, val) {
                var stars;
                stars = E.span();
                val = int(val || 0);
                if (val > 0) {
                    add_stars_to(stars, val, ρσ_exists.d(fm.display).allow_half_stars);
                    add_row(name, stars);
                }
            };
            if (!process_rating.__argnames__) Object.defineProperties(process_rating, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_identifiers(field, fm, name, val) {
                var keys, td, url_map, ρσ_unpack, text, k, url, idval, x;
                if (val) {
                    keys = Object.keys(val);
                    if (keys.length) {
                        td = E.td();
                        url_map = (function() {
                            var ρσ_Iter = ρσ_Iterable(mi.urls_from_identifiers || []), ρσ_Result = Object.create(null), text, 
                            k, val, url;
                            for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                                ρσ_unpack = ρσ_flatten(ρσ_Iter[ρσ_Index]);
                                text = ρσ_unpack[0];
                                k = ρσ_unpack[1];
                                val = ρσ_unpack[2];
                                url = ρσ_unpack[3];
                                ρσ_Result[k] = ([text, url]);
                            }
                            return ρσ_Result;
                        })();
                        var ρσ_Iter6 = ρσ_Iterable(keys);
                        for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                            k = ρσ_Iter6[ρσ_Index6];
                            idval = val[(typeof k === "number" && k < 0) ? val.length + k : k];
                            x = url_map[(typeof k === "number" && k < 0) ? url_map.length + k : k];
                            if (x) {
                                if (td.childNodes.length) {
                                    td.appendChild(document.createTextNode(", "));
                                }
                                td.appendChild(ρσ_interpolate_kwargs.call(E, E.a, [x[0]].concat([ρσ_desugar_kwargs({class_: "blue-link", title: "{}:{}".format(k, idval), target: "_new", href: x[1]})])));
                            }
                        }
                        if (td.childNodes.length) {
                            table.appendChild(E.tr(E.td(name + ":"), td));
                        }
                    }
                }
            };
            if (!process_identifiers.__argnames__) Object.defineProperties(process_identifiers, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_languages(field, fm, name, val) {
                var td, lang, k;
                if (val && val.length) {
                    table.appendChild(E.tr(E.td(name + ":"), E.td()));
                    td = table.lastChild.lastChild;
                    var ρσ_Iter7 = ρσ_Iterable(val);
                    for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                        k = ρσ_Iter7[ρσ_Index7];
                        if (mi.lang_names) {
                            lang = (ρσ_expr_temp = mi.lang_names)[(typeof k === "number" && k < 0) ? ρσ_expr_temp.length + k : k] || k;
                        } else {
                            lang = k;
                        }
                        td.appendChild(ρσ_interpolate_kwargs.call(E, E.a, [lang].concat([ρσ_desugar_kwargs({class_: "blue-link", title: _("Click to see books with language: {}").format(lang), href: href_for_search(field, k)})])));
                        if (k !== val[val.length-1]) {
                            td.appendChild(document.createTextNode(", "));
                        }
                    }
                }
            };
            if (!process_languages.__argnames__) Object.defineProperties(process_languages, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_datetime(field, fm, name, val) {
                var fmt;
                if (val) {
                    fmt = interface_data[ρσ_bound_index("gui_" + field + "_display_format", interface_data)] || (fm["display"] || Object.create(null)).date_format;
                    val = format_date(val, fmt);
                    if (val) {
                        add_row(name, val);
                    }
                }
            };
            if (!process_datetime.__argnames__) Object.defineProperties(process_datetime, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_series(field, fm, name, val) {
                var ifield, ival, s, a;
                if (val) {
                    ifield = field + "_index";
                    try {
                        ival = float(mi[(typeof ifield === "number" && ifield < 0) ? mi.length + ifield : ifield]);
                    } catch (ρσ_Exception) {
                        ρσ_last_exception = ρσ_Exception;
                        if (ρσ_Exception instanceof Error) {
                            ival = 1;
                        } else {
                            throw ρσ_Exception;
                        }
                    }
                    ival = ρσ_interpolate_kwargs.call(this, fmt_sidx, [ival].concat([ρσ_desugar_kwargs({use_roman: interface_data.use_roman_numerals_for_series_number})]));
                    table.appendChild(E.tr(E.td(name + ":"), E.td()));
                    s = safe_set_inner_html(E.span(), _("{0} of <a>{1}</a>").format(ival, val));
                    a = s.getElementsByTagName("a");
                    if (a && a.length) {
                        a = a[0];
                        a.setAttribute("href", href_for_search(field, val));
                        a.setAttribute("title", _("Click to see books with {0}: {1}").format(name, val));
                    } else {
                        print("WARNING: Translation of series template is incorrect as it does not have an <a> tag");
                    }
                    table.lastChild.lastChild.appendChild(s);
                }
            };
            if (!process_series.__argnames__) Object.defineProperties(process_series, {
                __argnames__ : {value: ["field", "fm", "name", "val"]}
            });

            function process_field(field, fm) {
                var name, datatype, val, ias, hp, func, join, fmt;
                name = fm.name || field;
                datatype = fm.datatype;
                val = mi[(typeof field === "number" && field < 0) ? mi.length + field : field];
                if (field === "comments" || datatype === "comments") {
                    if (!val) {
                        return;
                    }
                    ias = ρσ_exists.d(fm.display).interpret_as || "html";
                    hp = ρσ_exists.d(fm.display).heading_position || "hide";
                    if (ias === "long-text") {
                        if (hp === "side") {
                            add_row(name, val).style.whiteSpace = "pre-wrap";
                            return;
                        }
                        val = ρσ_interpolate_kwargs.call(E, E.pre, [val].concat([ρσ_desugar_kwargs({style: "white-space:pre-wrap"})])).outerHTML;
                    } else if (ias === "short-text") {
                        if (hp === "side") {
                            add_row(name, val);
                            return;
                        }
                        val = E.span(val).outerHTML;
                    }
                    if (hp === "side") {
                        ρσ_interpolate_kwargs.call(this, add_row, [name, val].concat([ρσ_desugar_kwargs({is_html: true})]));
                        return;
                    }
                    comments.push([field, val]);
                    return;
                }
                func = null;
                if (datatype === "composite") {
                    func = process_composite;
                } else if (field === "formats") {
                    func = process_formats;
                } else if (datatype === "rating") {
                    func = process_rating;
                } else if (field === "identifiers") {
                    func = process_identifiers;
                } else if (field === "authors") {
                    func = process_authors;
                } else if (field === "publisher") {
                    func = process_publisher;
                } else if (field === "languages") {
                    func = process_languages;
                } else if (datatype === "datetime") {
                    func = process_datetime;
                } else if (datatype === "series") {
                    func = process_series;
                }
                if (func) {
                    func(field, fm, name, val);
                } else {
                    if (datatype === "text" || datatype === "enumeration") {
                        if (val !== undefined && val !== null) {
                            join = (fm.is_multiple) ? fm.is_multiple.list_to_ui : null;
                            ρσ_interpolate_kwargs.call(this, add_row, [name, val].concat([ρσ_desugar_kwargs({join: join, is_searchable: field})]));
                        }
                    } else if (datatype === "bool") {
                        add_row(name, (val) ? _("Yes") : _("No"));
                    } else if (datatype === "int" || datatype === "float") {
                        if (val !== undefined && val !== null) {
                            fmt = (fm.display || Object.create(null)).number_format;
                            if (fmt) {
                                val = fmt.format(val);
                            } else {
                                val += "";
                            }
                            add_row(name, val);
                        }
                    }
                }
            };
            if (!process_field.__argnames__) Object.defineProperties(process_field, {
                __argnames__ : {value: ["field", "fm"]}
            });

            var ρσ_Iter8 = ρσ_Iterable(fields);
            for (var ρσ_Index8 = 0; ρσ_Index8 < ρσ_Iter8.length; ρσ_Index8++) {
                field = ρσ_Iter8[ρσ_Index8];
                fm = field_metadata[(typeof field === "number" && field < 0) ? field_metadata.length + field : field];
                if (!fm) {
                    continue;
                }
                try {
                    process_field(field, fm);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        print("Failed to render metadata field: " + field);
                        traceback.print_exc();
                    } else {
                        throw ρσ_Exception;
                    }
                }
            }
            all_html = "";
            var ρσ_Iter9 = ρσ_Iterable(comments);
            for (var ρσ_Index9 = 0; ρσ_Index9 < ρσ_Iter9.length; ρσ_Index9++) {
                ρσ_unpack = ρσ_Iter9[ρσ_Index9];
                field = ρσ_unpack[0];
                comment = ρσ_unpack[1];
                if (comment) {
                    fm = field_metadata[(typeof field === "number" && field < 0) ? field_metadata.length + field : field];
                    if (ρσ_exists.d(fm.display).heading_position === "above") {
                        name = fm.name || field;
                        all_html += "<h3>" + ρσ_str.format("{}", name) + "</h3>";
                    }
                    all_html += comment;
                }
            }
            iframe = adjusting_sandboxed_html(all_html);
            iframe.style.marginTop = "2ex";
            table.parentNode.appendChild(iframe);
        };
        if (!render_metadata.__argnames__) Object.defineProperties(render_metadata, {
            __argnames__ : {value: ["mi", "table", "book_id"]}
        });

        function basic_table_rules(sel) {
            var style;
            style = "";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "table.metadata td"].concat([ρσ_desugar_kwargs({vertical_align: "top"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "table.metadata td:first-of-type"].concat([ρσ_desugar_kwargs({font_weight: "bold", padding_right: "1em", white_space: "nowrap"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + "table.metadata td:last-of-type"].concat([ρσ_desugar_kwargs({overflow_wrap: "break-word"})]));
            return style;
        };
        if (!basic_table_rules.__argnames__) Object.defineProperties(basic_table_rules, {
            __argnames__ : {value: ["sel"]}
        });

        add_extra_css(function () {
            var sel, style;
            sel = "." + CLASS_NAME + " ";
            style = basic_table_rules(sel);
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " .next-book-button:hover"].concat([ρσ_desugar_kwargs({transform: "scale(1.5)"})]));
            sel = "." + SEARCH_INTERNET_CLASS;
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({margin: "1ex 1em"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " ul > li"].concat([ρσ_desugar_kwargs({list_style_type: "none"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " ul > li > a"].concat([ρσ_desugar_kwargs({padding: "2ex 1em", display: "block", width: "100%"})]));
            sel = "." + COPY_TO_LIBRARY_CLASS;
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({margin: "1ex 1em"})]));
            return style;
        });
        current_fetch = null;
        function no_book(container) {
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("No book found")].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])));
        };
        if (!no_book.__argnames__) Object.defineProperties(no_book, {
            __argnames__ : {value: ["container"]}
        });

        function on_img_err(err) {
            var img;
            img = err.target;
            if (img.parentNode) {
                img.parentNode.style.display = "none";
            }
        };
        if (!on_img_err.__argnames__) Object.defineProperties(on_img_err, {
            __argnames__ : {value: ["err"]}
        });

        function preferred_format(book_id) {
            var interface_data;
            interface_data = get_interface_data();
            return get_preferred_format(book_metadata(book_id), interface_data.output_format, interface_data.input_formats);
        };
        if (!preferred_format.__argnames__) Object.defineProperties(preferred_format, {
            __argnames__ : {value: ["book_id"]}
        });

        function read_format(book_id, fmt) {
            open_book(book_id, fmt);
        };
        if (!read_format.__argnames__) Object.defineProperties(read_format, {
            __argnames__ : {value: ["book_id", "fmt"]}
        });

        function read_book(book_id) {
            var fmt;
            fmt = preferred_format(book_id);
            read_format(book_id, fmt);
        };
        if (!read_book.__argnames__) Object.defineProperties(read_book, {
            __argnames__ : {value: ["book_id"]}
        });

        function download_format(book_id, fmt) {
            window.location = download_url(book_id, fmt);
        };
        if (!download_format.__argnames__) Object.defineProperties(download_format, {
            __argnames__ : {value: ["book_id", "fmt"]}
        });

        function download_book(book_id) {
            var fmt;
            fmt = preferred_format(book_id);
            download_format(book_id, fmt);
        };
        if (!download_book.__argnames__) Object.defineProperties(download_book, {
            __argnames__ : {value: ["book_id"]}
        });

        function next_book(book_id, delta) {
            var next_book_id, q;
            next_book_id = book_after(book_id, delta);
            if (next_book_id) {
                q = parse_url_params();
                q.book_id = next_book_id + "";
                ρσ_interpolate_kwargs.call(this, show_panel, ["book_details"].concat([ρσ_desugar_kwargs({query: q, replace: true})]));
            }
        };
        if (!next_book.__argnames__) Object.defineProperties(next_book, {
            __argnames__ : {value: ["book_id", "delta"]}
        });

        function render_book(container_id, book_id) {
            var c, metadata, authors, alt, bsrgb, border_radius, imgdiv, img, container, read_button, fmt, download_button, row, md, table;
            render_book.book_id = book_id;
            c = document.getElementById(container_id);
            if (!c) {
                return;
            }
            metadata = book_metadata(book_id);
            render_book.title = metadata.title;
            set_title(c, metadata.title);
            authors = (metadata.authors) ? metadata.authors.join(" & ") : _("Unknown");
            alt = _("{} by {}\nClick to read").format(metadata.title, authors);
            bsrgb = get_color_as_rgba("button-start");
            function prev_next_button(is_prev) {
                return ρσ_interpolate_kwargs.call(E, E.div, [svgicon((is_prev) ? "chevron-left" : "chevron-right")].concat([ρσ_desugar_kwargs({style: "cursor: pointer; border-radius: " + ρσ_str.format("{}", Math.floor(border_radius / 5)) + "px; background-color:rgba(" + ρσ_str.format("{}", bsrgb[0]) + ", " + ρσ_str.format("{}", bsrgb[1]) + ", " + ρσ_str.format("{}", bsrgb[2]) + ", 0.75);", title: (is_prev) ? _("Previous book") : _("Next book"), class_: "next-book-button", onclick: next_book.bind(null, book_id, (is_prev) ? -1 : 1)})]));
            };
            if (!prev_next_button.__argnames__) Object.defineProperties(prev_next_button, {
                __argnames__ : {value: ["is_prev"]}
            });

            border_radius = 20;
            imgdiv = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.img, [ρσ_desugar_kwargs({alt: alt, title: alt, data_title: metadata.title, data_authors: authors, onclick: read_book.bind(null, book_id), style: "cursor: pointer; border-radius: 20px; max-width: calc(100vw - 2em); max-height: calc(100vh - 4ex - {}); display: block; width:auto; height:auto; border-radius: {}px".format(get_font_size("title"), border_radius)})]), ρσ_interpolate_kwargs.call(E, E.div, [prev_next_button(true), prev_next_button()].concat([ρσ_desugar_kwargs({style: "position: absolute; top:0; width: 100%; padding: " + ρσ_str.format("{}", Math.floor(border_radius / 2)) + "px; box-sizing: border-box; font-size: 2rem; display: flex; justify-content: space-between; color: " + ρσ_str.format("{}", get_color("button-text")) + ""})]))].concat([ρσ_desugar_kwargs({style: "position: relative"})]));
            img = imgdiv.getElementsByTagName("img")[0];
            img.onerror = on_img_err;
            img.src = cover_url(book_id);
            c = c.lastChild;
            c.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin-right: 1em; flex-grow: 3; max-width: 500px", data_book_id: "" + book_id})]), imgdiv].concat([ρσ_desugar_kwargs({style: "display:flex; padding: 1ex 1em; align-items: flex-start; justify-content: flex-start; flex-wrap: wrap"})])));
            container = c.lastChild.firstChild;
            read_button = create_button(_("Read"), "book", read_book.bind(null, book_id), _("Read this book"));
            fmt = preferred_format(book_id);
            download_button = ρσ_interpolate_kwargs.call(this, create_button, [_("Download"), "cloud-download", download_url(book_id, fmt), _("Download this book in the {0} format ({1})").format(fmt, human_readable((ρσ_expr_temp = metadata.format_sizes)[(typeof fmt === "number" && fmt < 0) ? ρσ_expr_temp.length + fmt : fmt] || 0))].concat([ρσ_desugar_kwargs({download_filename: "" + ρσ_str.format("{}", metadata.title) + "." + ρσ_str.format("{}", fmt.toLowerCase()) + ""})]));
            row = ρσ_interpolate_kwargs.call(E, E.div, [read_button, "   ", download_button].concat([ρσ_desugar_kwargs({style: "margin-bottom: 1ex"})]));
            if (!metadata.formats || !metadata.formats.length) {
                row.style.display = "none";
            }
            container.appendChild(row);
            md = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin-bottom: 2ex"})]);
            table = ρσ_interpolate_kwargs.call(E, E.table, [ρσ_desugar_kwargs({class_: "metadata"})]);
            container.appendChild(md);
            md.appendChild(table);
            render_metadata(metadata, table, book_id);
        };
        if (!render_book.__argnames__) Object.defineProperties(render_book, {
            __argnames__ : {value: ["container_id", "book_id"]}
        });

        function add_top_bar_buttons(container_id) {
            var container, book_id;
            container = document.getElementById(container_id);
            if (container) {
                clear_buttons(container);
                ρσ_interpolate_kwargs.call(this, add_button, [container, "convert"].concat([ρσ_desugar_kwargs({action: convert_book, tooltip: _("Convert this book to another format")})]));
                ρσ_interpolate_kwargs.call(this, add_button, [container, "edit"].concat([ρσ_desugar_kwargs({action: edit_metadata, tooltip: _("Edit the metadata for this book")})]));
                ρσ_interpolate_kwargs.call(this, add_button, [container, "trash"].concat([ρσ_desugar_kwargs({action: delete_book, tooltip: _("Delete this book")})]));
                book_id = parse_url_params().book_id;
                if (book_id === "0") {
                    add_button(container, "random", function () {
                        fetch_metadata(container_id, 0, proceed_after_succesful_fetch_metadata);
                    });
                }
                ρσ_interpolate_kwargs.call(this, add_button, [container, "ellipsis-v"].concat([ρσ_desugar_kwargs({action: show_subsequent_panel.bind(null, "more_actions"), tooltip: _("More actions")})]));
            }
        };
        if (!add_top_bar_buttons.__argnames__) Object.defineProperties(add_top_bar_buttons, {
            __argnames__ : {value: ["container_id"]}
        });

        function proceed_after_succesful_fetch_metadata(container_id, book_id) {
            render_book(container_id, book_id);
            add_top_bar_buttons(container_id);
        };
        if (!proceed_after_succesful_fetch_metadata.__argnames__) Object.defineProperties(proceed_after_succesful_fetch_metadata, {
            __argnames__ : {value: ["container_id", "book_id"]}
        });

        function metadata_fetched(container_id, book_id, proceed, end_type, xhr, event) {
            var c, data;
            if (current_fetch === null || current_fetch !== xhr) {
                return;
            }
            current_fetch = null;
            c = document.getElementById(container_id);
            if (!c) {
                return;
            }
            c = c.lastChild;
            if (end_type === "load") {
                try {
                    data = JSON.parse(xhr.responseText);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        var err = ρσ_Exception;
                        error_dialog(_("Could not fetch metadata for book"), _("Server returned an invalid response"), err.toString());
                        return;
                    } else {
                        throw ρσ_Exception;
                    }
                }
                clear(c);
                book_id = int(data["id"]);
                set_book_metadata(book_id, data);
                proceed(container_id, book_id);
            } else if (end_type !== "abort") {
                clear(c);
                c.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Could not fetch metadata for book"), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])));
                safe_set_inner_html(c.lastChild.lastChild, xhr.error_html);
            }
        };
        if (!metadata_fetched.__argnames__) Object.defineProperties(metadata_fetched, {
            __argnames__ : {value: ["container_id", "book_id", "proceed", "end_type", "xhr", "event"]}
        });

        function fetch_metadata(container_id, book_id, proceed) {
            var container;
            container = document.getElementById(container_id);
            if (!container) {
                return;
            }
            if (current_fetch) {
                current_fetch.abort();
            }
            current_fetch = ρσ_interpolate_kwargs.call(this, ajax, ["interface-data/book-metadata/" + book_id, metadata_fetched.bind(null, container_id, book_id, proceed)].concat([ρσ_desugar_kwargs({query: (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["library_id"] = current_library_id();
                ρσ_d["vl"] = current_virtual_library();
                return ρσ_d;
            }).call(this)})]));
            current_fetch.send();
            container = container.lastChild;
            clear(container);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [create_spinner(), " " + _("Fetching metadata for the book, please wait") + "…"].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])));
        };
        if (!fetch_metadata.__argnames__) Object.defineProperties(fetch_metadata, {
            __argnames__ : {value: ["container_id", "book_id", "proceed"]}
        });

        function create_book_details(container) {
            var q, current_book_id, container_id;
            q = parse_url_params();
            current_book_id = q.book_id;
            if (current_book_id === undefined || current_book_id === null) {
                no_book(container);
                return;
            }
            current_book_id = int(current_book_id);
            container_id = container.parentNode.id;
            if (current_book_id !== 0 && book_metadata(current_book_id)) {
                render_book(container_id, current_book_id);
                add_top_bar_buttons(container_id);
            } else {
                fetch_metadata(container_id, current_book_id, proceed_after_succesful_fetch_metadata);
            }
        };
        if (!create_book_details.__argnames__) Object.defineProperties(create_book_details, {
            __argnames__ : {value: ["container"]}
        });

        function report_load_failure(container) {
            report_a_load_failure(container, _("Failed to load books from calibre library, with error:"), load_status.error_html);
        };
        if (!report_load_failure.__argnames__) Object.defineProperties(report_load_failure, {
            __argnames__ : {value: ["container"]}
        });

        function check_for_books_loaded() {
            var container;
            container = this;
            if (load_status.loading) {
                conditional_timeout(container.id, 5, check_for_books_loaded);
                return;
            }
            container = container.lastChild;
            clear(container);
            if (!load_status.ok) {
                report_load_failure(container);
                return;
            }
            create_book_details(container);
        };

        function onkeydown(container_id, ev) {
            if (render_book.book_id) {
                if (!ev.altKey && !ev.ctrlKey && !ev.metaKey && !ev.shiftKey) {
                    if (ev.key === "ArrowLeft") {
                        next_book(render_book.book_id, -1);
                        [ev.preventDefault(), ev.stopPropagation()];
                    } else if (ev.key === "ArrowRight") {
                        next_book(render_book.book_id, 1);
                        [ev.preventDefault(), ev.stopPropagation()];
                    }
                }
            }
        };
        if (!onkeydown.__argnames__) Object.defineProperties(onkeydown, {
            __argnames__ : {value: ["container_id", "ev"]}
        });

        function init(container_id) {
            var container, ρσ_unpack, close_action, close_icon, q, ca;
            container = document.getElementById(container_id);
            ρσ_unpack = [back, "close"];
            close_action = ρσ_unpack[0];
            close_icon = ρσ_unpack[1];
            q = parse_url_params();
            ca = q.close_action;
            if (ca === "home") {
                ρσ_unpack = [function () {
                    home();
                }, "home"];
                close_action = ρσ_unpack[0];
                close_icon = ρσ_unpack[1];
            } else if (ca === "book_list") {
                close_action = function () {
                    show_panel("book_list", (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["book_id"] = q.book_id;
                        return ρσ_d;
                    }).call(this));
                };
            }
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("Book details"), action: close_action, icon: close_icon})]));
            window.scrollTo(0, 0);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: CLASS_NAME, tabindex: "0"})]));
            container.lastChild.addEventListener("keydown", onkeydown.bind(null, container_id), (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["passive"] = false;
                ρσ_d["capture"] = true;
                return ρσ_d;
            }).call(this));
            container.lastChild.focus();
            container.lastChild.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Loading books from the calibre library, please wait...")].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1em"})])));
            conditional_timeout(container_id, 5, check_for_books_loaded);
        };
        if (!init.__argnames__) Object.defineProperties(init, {
            __argnames__ : {value: ["container_id"]}
        });

        function show_subsequent_panel() {
            var name = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var replace = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_subsequent_panel.__defaults__.replace : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "replace")){
                replace = ρσ_kwargs_obj.replace;
            }
            var q;
            q = parse_url_params();
            q.book_id = (read_book.book_id || q.book_id) + "";
            ρσ_interpolate_kwargs.call(this, show_panel, ["book_details^" + name].concat([ρσ_desugar_kwargs({query: q, replace: replace})]));
        };
        if (!show_subsequent_panel.__defaults__) Object.defineProperties(show_subsequent_panel, {
            __defaults__ : {value: {replace:false}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["name", "replace"]}
        });

        function edit_metadata() {
            var q;
            q = parse_url_params();
            q.book_id = (read_book.book_id || q.book_id) + "";
            ρσ_interpolate_kwargs.call(this, show_panel, ["edit_metadata"].concat([ρσ_desugar_kwargs({query: q, replace: false})]));
        };

        function convert_book() {
            var q;
            q = parse_url_params();
            q.book_id = (read_book.book_id || q.book_id) + "";
            ρσ_interpolate_kwargs.call(this, show_panel, ["convert_book"].concat([ρσ_desugar_kwargs({query: q, replace: false})]));
        };

        function create_more_actions_panel(container_id) {
            var container, ρσ_unpack, title, subtitle, items;
            container = document.getElementById(container_id);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("More actions…"), action: back, icon: "close"})]));
            if (get_session_data().get("show_all_metadata")) {
                ρσ_unpack = [_("Show important metadata"), _("Show only the important metadata fields in the book details")];
                title = ρσ_unpack[0];
                subtitle = ρσ_unpack[1];
            } else {
                ρσ_unpack = [_("Show all metadata"), _("Show all metadata fields in the book details")];
                title = ρσ_unpack[0];
                subtitle = ρσ_unpack[1];
            }
            items = ρσ_list_decorate([ ρσ_interpolate_kwargs.call(this, create_item, [_("Search the internet")].concat([ρσ_desugar_kwargs({subtitle: _("Search for this author or book on various websites"), action: function () {
                ρσ_interpolate_kwargs.call(this, show_subsequent_panel, ["search_internet"].concat([ρσ_desugar_kwargs({replace: true})]));
            }})])), ρσ_interpolate_kwargs.call(this, create_item, [title].concat([ρσ_desugar_kwargs({subtitle: subtitle, action: toggle_fields})])), ρσ_interpolate_kwargs.call(this, create_item, [_("Copy to library")].concat([ρσ_desugar_kwargs({subtitle: _("Copy or move this book to another calibre library"), action: function () {
                ρσ_interpolate_kwargs.call(this, show_subsequent_panel, ["copy_to_library"].concat([ρσ_desugar_kwargs({replace: true})]));
            }})])) ]);
            container.appendChild(E.div());
            create_item_list(container.lastChild, items);
        };
        if (!create_more_actions_panel.__argnames__) Object.defineProperties(create_more_actions_panel, {
            __argnames__ : {value: ["container_id"]}
        });

        function return_to_book_details() {
            var q;
            q = parse_url_params();
            ρσ_interpolate_kwargs.call(this, show_panel, ["book_details"].concat([ρσ_desugar_kwargs({query: q, replace: true})]));
        };

        function toggle_fields() {
            var sd;
            sd = get_session_data();
            sd.set("show_all_metadata", (sd.get("show_all_metadata")) ? false : true);
            return_to_book_details();
        };

        function url_for(template, data) {
            function eqc(x) {
                return encode_query_component(x).replace(/%20/g, "+");
            };
            if (!eqc.__argnames__) Object.defineProperties(eqc, {
                __argnames__ : {value: ["x"]}
            });

            return ρσ_interpolate_kwargs.call(template, template.format, [ρσ_desugar_kwargs({title: eqc(data.title), author: eqc(data.author)})]);
        };
        if (!url_for.__argnames__) Object.defineProperties(url_for, {
            __argnames__ : {value: ["template", "data"]}
        });

        function search_internet(container_id) {
            var container, mi, data, interface_data, author_links, book_links, links, entry, ρσ_unpack, name, url;
            if (!render_book.book_id || !book_metadata(render_book.book_id)) {
                return return_to_book_details();
            }
            container = document.getElementById(container_id);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("Search the internet"), action: back, icon: "close"})]));
            mi = book_metadata(render_book.book_id);
            data = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["title"] = mi.title;
                ρσ_d["author"] = (mi.authors) ? mi.authors[0] : _("Unknown");
                return ρσ_d;
            }).call(this);
            interface_data = get_interface_data();
            function link_for(name, template) {
                return ρσ_interpolate_kwargs.call(E, E.a, [name].concat([ρσ_desugar_kwargs({class_: "simple-link", href: url_for(template, data), target: "_blank"})]));
            };
            if (!link_for.__argnames__) Object.defineProperties(link_for, {
                __argnames__ : {value: ["name", "template"]}
            });

            author_links = E.ul();
            book_links = E.ul();
            if (interface_data.search_the_net_urls) {
                var ρσ_Iter10 = ρσ_Iterable(interface_data.search_the_net_urls);
                for (var ρσ_Index10 = 0; ρσ_Index10 < ρσ_Iter10.length; ρσ_Index10++) {
                    entry = ρσ_Iter10[ρσ_Index10];
                    links = (entry.type === "book") ? book_links : author_links;
                    links.appendChild(E.li(link_for(entry.name, entry.url)));
                }
            }
            var ρσ_Iter11 = ρσ_Iterable(ρσ_list_decorate([ [_("Goodreads"), "https://www.goodreads.com/book/author/{author}"], [_("Wikipedia"), 
            "https://en.wikipedia.org/w/index.php?search={author}"], [_("Google books"), "https://www.google.com/search?tbm=bks&q=inauthor:%22{author}%22"] ]));
            for (var ρσ_Index11 = 0; ρσ_Index11 < ρσ_Iter11.length; ρσ_Index11++) {
                ρσ_unpack = ρσ_Iter11[ρσ_Index11];
                name = ρσ_unpack[0];
                url = ρσ_unpack[1];
                author_links.appendChild(E.li(link_for(name, url)));
            }
            var ρσ_Iter12 = ρσ_Iterable(ρσ_list_decorate([ [_("Goodreads"), "https://www.goodreads.com/search?q={author}+{title}&search%5Bsource%5D=goodreads&search_type=books&tab=books"], [_("Google books"), 
            "https://www.google.com/search?tbm=bks&q=inauthor:%22{author}%22+intitle:%22{title}%22"], [_("Amazon"), 
            "https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Dstripbooks&field-keywords={author}+{title}"] ]));
            for (var ρσ_Index12 = 0; ρσ_Index12 < ρσ_Iter12.length; ρσ_Index12++) {
                ρσ_unpack = ρσ_Iter12[ρσ_Index12];
                name = ρσ_unpack[0];
                url = ρσ_unpack[1];
                book_links.appendChild(E.li(link_for(name, url)));
            }
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [safe_set_inner_html(E.h2(), _("Search for the author <i>{}</i> at:").format(data.author)), author_links, E.hr(), safe_set_inner_html(E.h2(), _("Search for the book <i>{}</i> at:").format(data.title)), book_links].concat([ρσ_desugar_kwargs({class_: SEARCH_INTERNET_CLASS})])));
        };
        if (!search_internet.__argnames__) Object.defineProperties(search_internet, {
            __argnames__ : {value: ["container_id"]}
        });

        function do_copy_to_library(book_id, target_library_id, target_library_name) {
            var title, dupes_id, sd, saved_value;
            function handle_result(move, close_func, end_type, xhr, ev) {
                var title, response;
                close_func();
                title = book_metadata(book_id).title;
                return_to_book_details();
                if (end_type === "abort") {
                    return;
                }
                if (end_type !== "load") {
                    error_dialog(_("Failed to copy book"), _("Failed to copy the book \"{}\". Click \"Show details\" for more information.").format(title), xhr.error_html);
                    return;
                }
                try {
                    response = (ρσ_expr_temp = JSON.parse(xhr.responseText))[(typeof book_id === "number" && book_id < 0) ? ρσ_expr_temp.length + book_id : book_id];
                    if (!response) {
                        throw new Exception("bad");
                    }
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        error_dialog(_("Failed to copy book"), _("Failed to copy the book \"{}\" because of an invalid response from calibre").format(title));
                        return;
                    } 
                }
                if (!response.ok) {
                    error_dialog(_("Failed to copy book"), _("Failed to copy the book \"{}\". Click \"Show details\" for more information.").format(title), response.payload);
                    return;
                }
                if (response.action === "duplicate") {
                    warning_dialog(_("Book already exists"), _("Could not copy as a book with the same title and authors already exists in the {} library").format(target_library_name));
                } else if (response.action === "automerge") {
                    warning_dialog(_("Book merged"), _("The files from the book were merged into a book with the same title and authors in the {} library").format(target_library_name));
                }
                if (move) {
                    refresh_after_delete(book_id, current_library_id());
                }
            };
            if (!handle_result.__argnames__) Object.defineProperties(handle_result, {
                __argnames__ : {value: ["move", "close_func", "end_type", "xhr", "ev"]}
            });

            function trigger_copy(container_id, move, close_func) {
                var choice, ρσ_unpack, duplicate_action, automerge_action, data, container;
                try {
                    choice = document.querySelector("#" + ρσ_str.format("{}", dupes_id) + " input[name=\"dupes\"]:checked").value;
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        choice = document.querySelector("#" + ρσ_str.format("{}", dupes_id) + " input[name=\"dupes\"]").value;
                    } 
                }
                sd.set("copy_to_library_dupes", choice);
                ρσ_unpack = choice.split(";", 2);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                duplicate_action = ρσ_unpack[0];
                automerge_action = ρσ_unpack[1];
                data = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["book_ids"] = [book_id];
                    ρσ_d["move"] = move;
                    ρσ_d["duplicate_action"] = duplicate_action;
                    ρσ_d["automerge_action"] = automerge_action;
                    return ρσ_d;
                }).call(this);
                container = document.getElementById(container_id);
                clear(container);
                container.appendChild(E.div(_("Contacting calibre to copy book, please wait...")));
                ajax_send("cdb/copy-to-library/" + ρσ_str.format("{}", target_library_id) + "/" + ρσ_str.format("{}", current_library_id()) + "", data, handle_result.bind(null, move, close_func));
            };
            if (!trigger_copy.__argnames__) Object.defineProperties(trigger_copy, {
                __argnames__ : {value: ["container_id", "move", "close_func"]}
            });

            function radio(value, text) {
                return ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "radio", name: "dupes", value: value, checked: value === saved_value})]), " ", E.span(text)].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem"})]));
            };
            if (!radio.__argnames__) Object.defineProperties(radio, {
                __argnames__ : {value: ["value", "text"]}
            });

            title = book_metadata(book_id).title;
            dupes_id = unique_id();
            sd = get_session_data();
            saved_value = sd.get("copy_to_library_dupes");
            create_custom_dialog((ρσ_expr_temp = _("Copy book to \"{target_library_name}\""), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.format, [ρσ_desugar_kwargs({target_library_name: target_library_name})])), (function() {
                var ρσ_anonfunc = function (container, close_func) {
                    var container_id;
                    container_id = ensure_id(container);
                    container.appendChild(E.div(E.div(_("Copying: {}").format(title)), ρσ_interpolate_kwargs.call(E, E.div, [E.p(_("If there are already existing books in \"{}\" with the same title and authors, how would you like to handle them?").format(target_library_name)), radio("add;overwrite", _("Copy anyway")), radio("ignore;overwrite", _("Do not copy")), radio("add_formats_to_existing;overwrite", _("Merge into existing books, overwriting existing files")), radio("add_formats_to_existing;ignore", _("Merge into existing books, keeping existing files")), radio("add_formats_to_existing;new record", _("Merge into existing books, putting conflicting files into a new book record"))].concat([ρσ_desugar_kwargs({id: dupes_id})])), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(this, create_button, [_("Copy"), null, trigger_copy.bind(null, container_id, false, close_func)].concat([ρσ_desugar_kwargs({highlight: true})])), " ", create_button(_("Move"), null, trigger_copy.bind(null, container_id, true, close_func)), " ", create_button(_("Cancel"), null, close_func)].concat([ρσ_desugar_kwargs({class_: "button-box"})]))));
                    if (!container.querySelector("#" + ρσ_str.format("{}", dupes_id) + " input[name=\"dupes\"]:checked")) {
                        container.querySelector("#" + ρσ_str.format("{}", dupes_id) + " input[name=\"dupes\"]").checked = true;
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["container", "close_func"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!do_copy_to_library.__argnames__) Object.defineProperties(do_copy_to_library, {
            __argnames__ : {value: ["book_id", "target_library_id", "target_library_name"]}
        });

        function copy_to_library(container_id) {
            var container, libraries, items, ρσ_unpack, library_id, library_name;
            if (!render_book.book_id || !book_metadata(render_book.book_id)) {
                return return_to_book_details();
            }
            container = document.getElementById(container_id);
            ρσ_interpolate_kwargs.call(this, create_top_bar, [container].concat([ρσ_desugar_kwargs({title: _("Copy to library"), action: back, icon: "close"})]));
            libraries = all_libraries();
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: COPY_TO_LIBRARY_CLASS})]));
            container = container.lastChild;
            if (libraries.length < 2) {
                container.appendChild(E.div(_("There are no other calibre libraries available to copy the book to")));
                return;
            }
            container.appendChild(E.h2(_("Choose the library to copy to below")));
            items = ρσ_list_decorate([]);
            var ρσ_Iter13 = ρσ_Iterable(libraries);
            for (var ρσ_Index13 = 0; ρσ_Index13 < ρσ_Iter13.length; ρσ_Index13++) {
                ρσ_unpack = ρσ_Iter13[ρσ_Index13];
                library_id = ρσ_unpack[0];
                library_name = ρσ_unpack[1];
                if (library_id === current_library_id()) {
                    continue;
                }
                items.push(ρσ_interpolate_kwargs.call(this, create_item, [library_name].concat([ρσ_desugar_kwargs({action: do_copy_to_library.bind(null, render_book.book_id, library_id, library_name)})])));
            }
            container.appendChild(E.div());
            create_item_list(container.lastChild, items);
        };
        if (!copy_to_library.__argnames__) Object.defineProperties(copy_to_library, {
            __argnames__ : {value: ["container_id"]}
        });

        function delete_book() {
            start_delete_book(current_library_id(), render_book.book_id, render_book.title || _("Unknown"));
        };

        set_panel_handler("book_details", init);
        set_panel_handler("book_details^more_actions", create_more_actions_panel);
        set_panel_handler("book_details^search_internet", search_internet);
        set_panel_handler("book_details^copy_to_library", copy_to_library);
        ρσ_modules["book_list.book_details"].bd_counter = bd_counter;
        ρσ_modules["book_list.book_details"].CLASS_NAME = CLASS_NAME;
        ρσ_modules["book_list.book_details"].SEARCH_INTERNET_CLASS = SEARCH_INTERNET_CLASS;
        ρσ_modules["book_list.book_details"].COPY_TO_LIBRARY_CLASS = COPY_TO_LIBRARY_CLASS;
        ρσ_modules["book_list.book_details"].FORMAT_PRIORITIES = FORMAT_PRIORITIES;
        ρσ_modules["book_list.book_details"].IGNORED_FIELDS = IGNORED_FIELDS;
        ρσ_modules["book_list.book_details"].default_sort = default_sort;
        ρσ_modules["book_list.book_details"].ρσ_unpack = ρσ_unpack;
        ρσ_modules["book_list.book_details"].i = i;
        ρσ_modules["book_list.book_details"].f = f;
        ρσ_modules["book_list.book_details"].current_fetch = current_fetch;
        ρσ_modules["book_list.book_details"].sort_formats_key = sort_formats_key;
        ρσ_modules["book_list.book_details"].get_preferred_format = get_preferred_format;
        ρσ_modules["book_list.book_details"].field_sorter = field_sorter;
        ρσ_modules["book_list.book_details"].href_for_search = href_for_search;
        ρσ_modules["book_list.book_details"].on_fmt_click = on_fmt_click;
        ρσ_modules["book_list.book_details"].adjust_iframe_height = adjust_iframe_height;
        ρσ_modules["book_list.book_details"].setup_iframe = setup_iframe;
        ρσ_modules["book_list.book_details"].adjust_all_iframes = adjust_all_iframes;
        ρσ_modules["book_list.book_details"].add_stars_to = add_stars_to;
        ρσ_modules["book_list.book_details"].adjusting_sandboxed_html = adjusting_sandboxed_html;
        ρσ_modules["book_list.book_details"].render_metadata = render_metadata;
        ρσ_modules["book_list.book_details"].basic_table_rules = basic_table_rules;
        ρσ_modules["book_list.book_details"].no_book = no_book;
        ρσ_modules["book_list.book_details"].on_img_err = on_img_err;
        ρσ_modules["book_list.book_details"].preferred_format = preferred_format;
        ρσ_modules["book_list.book_details"].read_format = read_format;
        ρσ_modules["book_list.book_details"].read_book = read_book;
        ρσ_modules["book_list.book_details"].download_format = download_format;
        ρσ_modules["book_list.book_details"].download_book = download_book;
        ρσ_modules["book_list.book_details"].next_book = next_book;
        ρσ_modules["book_list.book_details"].render_book = render_book;
        ρσ_modules["book_list.book_details"].add_top_bar_buttons = add_top_bar_buttons;
        ρσ_modules["book_list.book_details"].proceed_after_succesful_fetch_metadata = proceed_after_succesful_fetch_metadata;
        ρσ_modules["book_list.book_details"].metadata_fetched = metadata_fetched;
        ρσ_modules["book_list.book_details"].fetch_metadata = fetch_metadata;
        ρσ_modules["book_list.book_details"].create_book_details = create_book_details;
        ρσ_modules["book_list.book_details"].report_load_failure = report_load_failure;
        ρσ_modules["book_list.book_details"].check_for_books_loaded = check_for_books_loaded;
        ρσ_modules["book_list.book_details"].onkeydown = onkeydown;
        ρσ_modules["book_list.book_details"].init = init;
        ρσ_modules["book_list.book_details"].show_subsequent_panel = show_subsequent_panel;
        ρσ_modules["book_list.book_details"].edit_metadata = edit_metadata;
        ρσ_modules["book_list.book_details"].convert_book = convert_book;
        ρσ_modules["book_list.book_details"].create_more_actions_panel = create_more_actions_panel;
        ρσ_modules["book_list.book_details"].return_to_book_details = return_to_book_details;
        ρσ_modules["book_list.book_details"].toggle_fields = toggle_fields;
        ρσ_modules["book_list.book_details"].url_for = url_for;
        ρσ_modules["book_list.book_details"].search_internet = search_internet;
        ρσ_modules["book_list.book_details"].do_copy_to_library = do_copy_to_library;
        ρσ_modules["book_list.book_details"].copy_to_library = copy_to_library;
        ρσ_modules["book_list.book_details"].delete_book = delete_book;
    })();

    (function(){
        var __name__ = "read_book.prefs";

    })();

    (function(){
        var __name__ = "read_book.prefs.font_size";
        var CONTAINER, QUICK;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var get_color = ρσ_modules["book_list.theme"].get_color;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var element = ρσ_modules.dom.element;
        var rule = ρσ_modules.dom.rule;
        var set_css = ρσ_modules.dom.set_css;
        var unique_id = ρσ_modules.dom.unique_id;

        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var create_button = ρσ_modules.widgets.create_button;

        CONTAINER = unique_id("font-size-prefs");
        QUICK = unique_id("quick");
        add_extra_css(function () {
            var style;
            style = ρσ_interpolate_kwargs.call(this, rule, [QUICK, "li.current"].concat([ρσ_desugar_kwargs({background_color: get_color("window-background2")})]));
            style += ρσ_interpolate_kwargs.call(this, rule, [QUICK, "li:hover"].concat([ρσ_desugar_kwargs({background_color: get_color("window-background2")})]));
            style += ρσ_interpolate_kwargs.call(this, rule, [CONTAINER, "a:hover"].concat([ρσ_desugar_kwargs({color: get_color("window-hover-foreground")})]));
            return style;
        });
        function change_font_size(sz) {
            var sd;
            sd = get_session_data();
            if (sd.get("base_font_size") !== sz) {
                sd.set("base_font_size", sz);
                ui_operations.update_font_size();
            }
        };
        if (!change_font_size.__argnames__) Object.defineProperties(change_font_size, {
            __argnames__ : {value: ["sz"]}
        });

        function set_quick_size(ev) {
            var li, sz;
            li = ev.currentTarget;
            sz = int(li.dataset.sz);
            change_font_size(sz);
        };
        if (!set_quick_size.__argnames__) Object.defineProperties(set_quick_size, {
            __argnames__ : {value: ["ev"]}
        });

        function set_custom_size(ev) {
            var sz;
            sz = int(element(CONTAINER, "input").value);
            change_font_size(sz);
        };
        if (!set_custom_size.__argnames__) Object.defineProperties(set_custom_size, {
            __argnames__ : {value: ["ev"]}
        });

        function change_font_size_by(amt) {
            var sd, sz, nsz;
            sd = get_session_data();
            sz = sd.get("base_font_size");
            nsz = sz + amt;
            nsz = max(8, min(nsz, 40));
            change_font_size(nsz);
        };
        if (!change_font_size_by.__argnames__) Object.defineProperties(change_font_size_by, {
            __argnames__ : {value: ["amt"]}
        });

        function show_custom_size(ev) {
            var c, child;
            c = element(CONTAINER);
            var ρσ_Iter0 = ρσ_Iterable(c.childNodes);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                child = ρσ_Iter0[ρσ_Index0];
                child.style.display = "none";
            }
            c.lastChild.style.display = "block";
        };
        if (!show_custom_size.__argnames__) Object.defineProperties(show_custom_size, {
            __argnames__ : {value: ["ev"]}
        });

        function create_font_size_panel(container, close) {
            var quick, sd, cfs, sz;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: CONTAINER, style: "margin:15vh auto; max-width: 500px; border-radius: 8px; border: solid 1px currentColor; padding:1ex 1rem", onclick: (function() {
                var ρσ_anonfunc = function (ev) {
                    [ev.preventDefault(), ev.stopPropagation()];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })()})]));
            container = container.lastChild;
            container.style.backgroundColor = get_color("window-background");
            quick = ρσ_interpolate_kwargs.call(E, E.ul, [ρσ_desugar_kwargs({id: QUICK, style: "display:flex; justify-content:space-around; flex-wrap: wrap; align-items: baseline; list-style: none"})]);
            container.appendChild(quick);
            sd = get_session_data();
            cfs = sd.get("base_font_size");
            var ρσ_Iter1 = ρσ_Iterable(ρσ_list_decorate([ 10, 12, 14, 16, 18, 20, 22 ]));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                sz = ρσ_Iter1[ρσ_Index1];
                quick.appendChild(ρσ_interpolate_kwargs.call(this, set_css, [ρσ_interpolate_kwargs.call(E, E.li, ["Aa"].concat([ρσ_desugar_kwargs({title: "{} px".format(sz), class_: (cfs === sz) ? "current" : "", data_sz: str(sz), onclick: (function() {
                    var ρσ_anonfunc = function (ev) {
                        [set_quick_size(ev), close()];
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["ev"]}
                    });
                    return ρσ_anonfunc;
                })()})]))].concat([ρσ_desugar_kwargs({display: "inline-block", font_size: sz + "px", padding: "5px", cursor: "pointer", border_radius: "2px"})])));
            }
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.a, [_("Custom size")].concat([ρσ_desugar_kwargs({class_: "blue-link", href: "javascript:void", onclick: show_custom_size, style: "cursor:pointer"})]))].concat([ρσ_desugar_kwargs({style: "text-align: right; font-size: smaller; margin-top: 2ex"})])));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.div(E.label(_("Font size (pixels):"), " ", ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "number", min: 8, max: 60, step: 1, value: str(sd.get("base_font_size"))})]))), ρσ_interpolate_kwargs.call(E, E.div, [create_button(_("OK"), "check", function () {
                [set_custom_size(), close()];
            }), E.span(" "), ρσ_interpolate_kwargs.call(this, create_button, [_("Cancel")].concat([ρσ_desugar_kwargs({action: close})]))].concat([ρσ_desugar_kwargs({style: "text-align:right; margin-top:1ex; display:flex; justify-content: flex-end"})]))].concat([ρσ_desugar_kwargs({style: "display:none"})])));
        };
        if (!create_font_size_panel.__argnames__) Object.defineProperties(create_font_size_panel, {
            __argnames__ : {value: ["container", "close"]}
        });

        function develop(container) {
            create_font_size_panel(container, function () {
            });
        };
        if (!develop.__argnames__) Object.defineProperties(develop, {
            __argnames__ : {value: ["container"]}
        });

        ρσ_modules["read_book.prefs.font_size"].CONTAINER = CONTAINER;
        ρσ_modules["read_book.prefs.font_size"].QUICK = QUICK;
        ρσ_modules["read_book.prefs.font_size"].change_font_size = change_font_size;
        ρσ_modules["read_book.prefs.font_size"].set_quick_size = set_quick_size;
        ρσ_modules["read_book.prefs.font_size"].set_custom_size = set_custom_size;
        ρσ_modules["read_book.prefs.font_size"].change_font_size_by = change_font_size_by;
        ρσ_modules["read_book.prefs.font_size"].show_custom_size = show_custom_size;
        ρσ_modules["read_book.prefs.font_size"].create_font_size_panel = create_font_size_panel;
        ρσ_modules["read_book.prefs.font_size"].develop = develop;
    })();

    (function(){
        var __name__ = "read_book.prefs.utils";
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var create_button = ρσ_modules.widgets.create_button;

        function create_button_box(restore_defaults_func, apply_func, cancel_func) {
            var cbutton, rbutton;
            cbutton = ρσ_interpolate_kwargs.call(this, create_button, [_("Cancel")].concat([ρσ_desugar_kwargs({action: cancel_func})]));
            if (restore_defaults_func) {
                rbutton = ρσ_interpolate_kwargs.call(this, create_button, [_("Restore defaults")].concat([ρσ_desugar_kwargs({action: restore_defaults_func})]));
            } else {
                rbutton = restore_defaults_func || E.div(" ");
            }
            cbutton.style.marginLeft = "1rem";
            return ρσ_interpolate_kwargs.call(E, E.div, [rbutton, E.div(ρσ_interpolate_kwargs.call(this, create_button, [_("OK")].concat([ρσ_desugar_kwargs({action: apply_func})])), cbutton)].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem; display: flex; justify-content: space-between"})]));
        };
        if (!create_button_box.__argnames__) Object.defineProperties(create_button_box, {
            __argnames__ : {value: ["restore_defaults_func", "apply_func", "cancel_func"]}
        });

        ρσ_modules["read_book.prefs.utils"].create_button_box = create_button_box;
    })();

    (function(){
        var __name__ = "read_book.prefs.colors";
        var CONTAINER, COLOR_LIST, ACTION_BUTTONS, EDIT_SCHEME, develop;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var set_css = ρσ_modules.dom.set_css;
        var svgicon = ρσ_modules.dom.svgicon;
        var unique_id = ρσ_modules.dom.unique_id;

        var error_dialog = ρσ_modules.modals.error_dialog;

        var default_color_schemes = ρσ_modules["read_book.globals"].default_color_schemes;
        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var create_button_box = ρσ_modules["read_book.prefs.utils"].create_button_box;

        var create_button = ρσ_modules.widgets.create_button;

        CONTAINER = unique_id("reader-color-scheme");
        COLOR_LIST = unique_id();
        ACTION_BUTTONS = unique_id();
        EDIT_SCHEME = unique_id();
        add_extra_css(function () {
            var sel, style;
            sel = "#" + COLOR_LIST;
            style = ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({list_style_type: "none", display: "flex", flex_wrap: "wrap"})]));
            sel += " > li";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({padding: "1ex 1rem", margin: "1ex 0.5rem", border_radius: "4px", cursor: "pointer", border: "solid 1px currentColor"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " svg"].concat([ρσ_desugar_kwargs({visibility: "hidden"})]));
            sel += ".current-color";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " svg"].concat([ρσ_desugar_kwargs({visibility: "visible"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, ["#{} #{} td".format(CONTAINER, EDIT_SCHEME)].concat([ρσ_desugar_kwargs({padding: "1ex 1em"})]));
            sel = "#" + ACTION_BUTTONS;
            style += sel + "{margin-top:2ex; padding-top:1ex; border-top: solid 1px currentColor; margin-bottom: 2ex; padding-bottom: 1ex; border-bottom: solid 1px currentColor}";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " > span "].concat([ρσ_desugar_kwargs({margin: "1ex 0.5rem", display: "inline-block"})]));
            return style;
        });
        function get_container() {
            return document.getElementById(CONTAINER);
        };

        function resolve_color_scheme(current_color_scheme) {
            var sd, cs, ucs, ans, sn;
            sd = get_session_data();
            cs = current_color_scheme || sd.get("current_color_scheme") || "white";
            ucs = sd.get("user_color_schemes");
            if (default_color_schemes[(typeof cs === "number" && cs < 0) ? default_color_schemes.length + cs : cs]) {
                ans = default_color_schemes[(typeof cs === "number" && cs < 0) ? default_color_schemes.length + cs : cs];
            } else if (ucs[(typeof cs === "number" && cs < 0) ? ucs.length + cs : cs] && ucs[(typeof cs === "number" && cs < 0) ? ucs.length + cs : cs].foreground && ucs[(typeof cs === "number" && cs < 0) ? ucs.length + cs : cs].background) {
                ans = ucs[(typeof cs === "number" && cs < 0) ? ucs.length + cs : cs];
            } else {
                var ρσ_Iter0 = ρσ_Iterable(default_color_schemes);
                for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                    sn = ρσ_Iter0[ρσ_Index0];
                    ans = default_color_schemes[(typeof sn === "number" && sn < 0) ? default_color_schemes.length + sn : sn];
                    break;
                }
            }
            return ans;
        };
        if (!resolve_color_scheme.__argnames__) Object.defineProperties(resolve_color_scheme, {
            __argnames__ : {value: ["current_color_scheme"]}
        });

        function change_current_color(ev) {
            var ul, li;
            ul = ev.currentTarget.parentNode;
            var ρσ_Iter1 = ρσ_Iterable(ul.childNodes);
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                li = ρσ_Iter1[ρσ_Index1];
                li.setAttribute("class", (li === ev.currentTarget) ? "current-color" : "");
            }
            set_action_button_visibility(ul.parentNode);
        };
        if (!change_current_color.__argnames__) Object.defineProperties(change_current_color, {
            __argnames__ : {value: ["ev"]}
        });

        function new_color_scheme(ev) {
            var container, inp;
            container = get_container();
            container.lastChild.style.display = "block";
            var ρσ_Iter2 = ρσ_Iterable(container.lastChild.querySelectorAll("input"));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                inp = ρσ_Iter2[ρσ_Index2];
                if (inp.name === "link_color_type") {
                    inp.checked = inp.value === "default";
                } else {
                    inp.value = (ρσ_expr_temp = (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["name"] = "";
                        ρσ_d["bg"] = "#ffffff";
                        ρσ_d["fg"] = "#000000";
                        ρσ_d["link"] = "#0000ee";
                        return ρσ_d;
                    }).call(this))[ρσ_bound_index(inp.name, ρσ_expr_temp)];
                }
            }
            container.lastChild.querySelector("input").focus();
            return container;
        };
        if (!new_color_scheme.__argnames__) Object.defineProperties(new_color_scheme, {
            __argnames__ : {value: ["ev"]}
        });

        function edit_color_scheme(ev) {
            var container, ccs, all_schemes, scheme;
            container = new_color_scheme(ev);
            ccs = current_color_scheme(container);
            all_schemes = all_color_schemes();
            if (all_schemes[(typeof ccs === "number" && ccs < 0) ? all_schemes.length + ccs : ccs]) {
                scheme = all_schemes[(typeof ccs === "number" && ccs < 0) ? all_schemes.length + ccs : ccs];
                container = document.getElementById(EDIT_SCHEME);
                container.querySelector("input").value = scheme.name;
                container.querySelector("input[name=bg]").value = scheme.background;
                container.querySelector("input[name=fg]").value = scheme.foreground;
                if (scheme.link) {
                    container.querySelector("input[value=custom]").checked = true;
                    container.querySelector("input[name=link]").value = scheme.link;
                } else {
                    container.querySelector("input[value=default]").checked = true;
                }
            }
        };
        if (!edit_color_scheme.__argnames__) Object.defineProperties(edit_color_scheme, {
            __argnames__ : {value: ["ev"]}
        });

        function remove_color_scheme(ev) {
            var ccs, sd, ucs;
            ccs = current_color_scheme();
            if (default_color_schemes[(typeof ccs === "number" && ccs < 0) ? default_color_schemes.length + ccs : ccs]) {
                return error_dialog(_("Cannot remove"), _("Cannot remove a builtin color scheme"));
            }
            sd = get_session_data();
            ucs = sd.get("user_color_schemes");
            delete ucs[ccs];
            sd.set("user_color_schemes", ucs);
            create_color_buttons();
            set_current_color_scheme();
        };
        if (!remove_color_scheme.__argnames__) Object.defineProperties(remove_color_scheme, {
            __argnames__ : {value: ["ev"]}
        });

        function current_color_scheme() {
            return get_container().querySelector("li.current-color").getAttribute("data-name");
        };

        function set_current_color_scheme(value) {
            var ul, done, li;
            ul = document.getElementById(COLOR_LIST);
            done = false;
            var ρσ_Iter3 = ρσ_Iterable(ul.childNodes);
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                li = ρσ_Iter3[ρσ_Index3];
                li.classList.remove("current-color");
                if (li.getAttribute("data-name") === value) {
                    li.classList.add("current-color");
                    done = true;
                }
            }
            if (!done) {
                var ρσ_Iter4 = ρσ_Iterable(ul.childNodes);
                for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                    li = ρσ_Iter4[ρσ_Index4];
                    li.classList.add("current-color");
                    break;
                }
            }
            set_action_button_visibility();
        };
        if (!set_current_color_scheme.__argnames__) Object.defineProperties(set_current_color_scheme, {
            __argnames__ : {value: ["value"]}
        });

        function add_color_scheme(ev) {
            var div, name, colors, col, key, sd, ucs;
            div = document.getElementById(EDIT_SCHEME);
            if (this !== "cancel") {
                name = div.querySelector("input[name=name]").value;
                if (!name) {
                    error_dialog(_("Name not specified"), _("You must specify a name for the color scheme"));
                    return;
                }
                colors = Object.create(null);
                var ρσ_Iter5 = ρσ_Iterable(ρσ_list_decorate([ "bg", "fg", "link" ]));
                for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                    col = ρσ_Iter5[ρσ_Index5];
                    colors[(typeof col === "number" && col < 0) ? colors.length + col : col] = div.querySelector("input[name=" + ρσ_str.format("{}", col) + "]").value;
                    if (!/^#[0-9A-F]{6}$/i.test(colors[(typeof col === "number" && col < 0) ? colors.length + col : col])) {
                        error_dialog(_("Invalid color"), _("The color {} is not a valid color").format(colors[(typeof col === "number" && col < 0) ? colors.length + col : col]));
                        return;
                    }
                }
                key = "*" + name;
                sd = get_session_data();
                ucs = sd.get("user_color_schemes");
                ucs[(typeof key === "number" && key < 0) ? ucs.length + key : key] = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["name"] = name;
                    ρσ_d["foreground"] = colors.fg;
                    ρσ_d["background"] = colors.bg;
                    return ρσ_d;
                }).call(this);
                if (div.querySelector("input[name=link_color_type]:checked").value === "custom") {
                    ucs[(typeof key === "number" && key < 0) ? ucs.length + key : key]["link"] = colors.link;
                }
                sd.set("user_color_schemes", ucs);
                create_color_buttons();
                set_current_color_scheme(key);
            }
            div.style.display = "none";
        };
        if (!add_color_scheme.__argnames__) Object.defineProperties(add_color_scheme, {
            __argnames__ : {value: ["ev"]}
        });

        function all_color_schemes() {
            var all_schemes, k, sd, ucs;
            all_schemes = Object.create(null);
            var ρσ_Iter6 = ρσ_Iterable(default_color_schemes);
            for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                k = ρσ_Iter6[ρσ_Index6];
                all_schemes[(typeof k === "number" && k < 0) ? all_schemes.length + k : k] = default_color_schemes[(typeof k === "number" && k < 0) ? default_color_schemes.length + k : k];
            }
            sd = get_session_data();
            ucs = sd.get("user_color_schemes");
            var ρσ_Iter7 = ρσ_Iterable(ucs);
            for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                k = ρσ_Iter7[ρσ_Index7];
                all_schemes[(typeof k === "number" && k < 0) ? all_schemes.length + k : k] = ucs[(typeof k === "number" && k < 0) ? ucs.length + k : k];
            }
            return all_schemes;
        };

        function create_color_buttons() {
            var ul, sd, all_schemes, ccs, scheme, item, name;
            ul = document.getElementById(COLOR_LIST);
            sd = get_session_data();
            clear(ul);
            all_schemes = all_color_schemes();
            ccs = sd.get("current_color_scheme");
            var ρσ_Iter8 = ρσ_Iterable(ρσ_interpolate_kwargs.call(this, sorted, [all_schemes].concat([ρσ_desugar_kwargs({key: (function() {
                var ρσ_anonfunc = function (k) {
                    return all_schemes[(typeof k === "number" && k < 0) ? all_schemes.length + k : k].name.toLowerCase();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["k"]}
                });
                return ρσ_anonfunc;
            })()})])));
            for (var ρσ_Index8 = 0; ρσ_Index8 < ρσ_Iter8.length; ρσ_Index8++) {
                name = ρσ_Iter8[ρσ_Index8];
                scheme = all_schemes[(typeof name === "number" && name < 0) ? all_schemes.length + name : name];
                item = ρσ_interpolate_kwargs.call(this, set_css, [ρσ_interpolate_kwargs.call(E, E.li, [svgicon("check"), " " + scheme.name].concat([ρσ_desugar_kwargs({data_name: name, onclick: change_current_color, class_: (name === ccs) ? "current-color" : ""})]))].concat([ρσ_desugar_kwargs({color: scheme.foreground, background_color: scheme.background})]));
                ul.appendChild(item);
            }
        };

        function set_action_button_visibility() {
            var container, ccs, is_custom, is_first, button;
            container = get_container();
            ccs = current_color_scheme(container);
            is_custom = ccs.startswith("*");
            is_first = true;
            var ρσ_Iter9 = ρσ_Iterable(container.querySelectorAll("#" + ACTION_BUTTONS + " > span"));
            for (var ρσ_Index9 = 0; ρσ_Index9 < ρσ_Iter9.length; ρσ_Index9++) {
                button = ρσ_Iter9[ρσ_Index9];
                if (is_first) {
                    is_first = false;
                } else {
                    button.style.display = (is_custom) ? "inline-block" : "none";
                }
            }
        };

        function create_colors_panel(container, apply_func, cancel_func) {
            var cs, ul;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: CONTAINER})]));
            container = container.lastChild;
            cs = resolve_color_scheme();
            container.dataset.bg = cs.background;
            container.dataset.fg = cs.foreground;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.p, [_("Choose a color scheme below")].concat([ρσ_desugar_kwargs({style: "margin:1ex 1em; padding: 1ex 0"})])));
            ul = ρσ_interpolate_kwargs.call(E, E.ul, [ρσ_desugar_kwargs({id: COLOR_LIST})]);
            container.appendChild(ul);
            create_color_buttons();
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.span(create_button(_("New scheme"), "plus", new_color_scheme)), E.span(create_button(_("Edit scheme"), "pencil", edit_color_scheme)), E.span(create_button(_("Remove scheme"), "trash", remove_color_scheme))].concat([ρσ_desugar_kwargs({id: ACTION_BUTTONS})])));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.table(E.tr(E.td(_("Name:")), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({name: "name"})]))), E.tr(E.td(_("Background:")), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({name: "bg", type: "color", value: "#ffffff"})]))), E.tr(E.td(_("Foreground:")), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({name: "fg", type: "color", value: "#000000"})]))), E.tr(E.td(_("Link:")), E.td(E.label(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "radio", name: "link_color_type", value: "default"})]), _("Default")), "  ", E.label(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "radio", name: "link_color_type", value: "custom"})]), _("Custom")), " ", ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({name: "link", type: "color", value: "#000000", onclick: (function() {
                var ρσ_anonfunc = function (ev) {
                    ev.currentTarget.parentNode.querySelector("[name=link_color_type][value=custom]").checked = true;
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })()})])))), ρσ_interpolate_kwargs.call(E, E.div, [create_button(_("Apply"), "check", add_color_scheme), E.span(" "), create_button(_("Discard"), "close", add_color_scheme.bind("cancel"))].concat([ρσ_desugar_kwargs({style: "display:flex; justify-content: flex-end; margin: 1ex 1em"})]))].concat([ρσ_desugar_kwargs({id: EDIT_SCHEME, style: "display:none"})])));
            set_action_button_visibility();
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [create_button_box(null, apply_func, cancel_func)].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
        };
        if (!create_colors_panel.__argnames__) Object.defineProperties(create_colors_panel, {
            __argnames__ : {value: ["container", "apply_func", "cancel_func"]}
        });

        develop = create_colors_panel;
        function commit_colors(onchange) {
            var ccs, rcs, c, sd;
            ccs = current_color_scheme();
            rcs = resolve_color_scheme(ccs);
            c = get_container();
            if (rcs.foreground !== c.dataset.fg || rcs.background !== c.dataset.bg) {
                sd = get_session_data();
                sd.set("current_color_scheme", ccs);
                ui_operations.update_color_scheme();
                onchange();
            }
        };
        if (!commit_colors.__argnames__) Object.defineProperties(commit_colors, {
            __argnames__ : {value: ["onchange"]}
        });

        ρσ_modules["read_book.prefs.colors"].CONTAINER = CONTAINER;
        ρσ_modules["read_book.prefs.colors"].COLOR_LIST = COLOR_LIST;
        ρσ_modules["read_book.prefs.colors"].ACTION_BUTTONS = ACTION_BUTTONS;
        ρσ_modules["read_book.prefs.colors"].EDIT_SCHEME = EDIT_SCHEME;
        ρσ_modules["read_book.prefs.colors"].develop = develop;
        ρσ_modules["read_book.prefs.colors"].get_container = get_container;
        ρσ_modules["read_book.prefs.colors"].resolve_color_scheme = resolve_color_scheme;
        ρσ_modules["read_book.prefs.colors"].change_current_color = change_current_color;
        ρσ_modules["read_book.prefs.colors"].new_color_scheme = new_color_scheme;
        ρσ_modules["read_book.prefs.colors"].edit_color_scheme = edit_color_scheme;
        ρσ_modules["read_book.prefs.colors"].remove_color_scheme = remove_color_scheme;
        ρσ_modules["read_book.prefs.colors"].current_color_scheme = current_color_scheme;
        ρσ_modules["read_book.prefs.colors"].set_current_color_scheme = set_current_color_scheme;
        ρσ_modules["read_book.prefs.colors"].add_color_scheme = add_color_scheme;
        ρσ_modules["read_book.prefs.colors"].all_color_schemes = all_color_schemes;
        ρσ_modules["read_book.prefs.colors"].create_color_buttons = create_color_buttons;
        ρσ_modules["read_book.prefs.colors"].set_action_button_visibility = set_action_button_visibility;
        ρσ_modules["read_book.prefs.colors"].create_colors_panel = create_colors_panel;
        ρσ_modules["read_book.prefs.colors"].commit_colors = commit_colors;
    })();

    (function(){
        var __name__ = "read_book.prefs.fonts";
        var CONTAINER, DEFAULT_STANDARD_FONT, DEFAULT_MINIMUM_FONT_SIZE, DEFAULT_ZOOM_STEP_SIZE, develop;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var unique_id = ρσ_modules.dom.unique_id;

        var runtime = ρσ_modules["read_book.globals"].runtime;

        var create_button_box = ρσ_modules["read_book.prefs.utils"].create_button_box;

        CONTAINER = unique_id("standalone-font-settings");
        DEFAULT_STANDARD_FONT = "serif";
        DEFAULT_MINIMUM_FONT_SIZE = 8;
        DEFAULT_ZOOM_STEP_SIZE = 20;
        function font_select(name, settings) {
            var ans, current_val, family;
            ans = ρσ_interpolate_kwargs.call(E, E.select, [ρσ_desugar_kwargs({name: name})]);
            ans.appendChild(ρσ_interpolate_kwargs.call(E, E.option, [_("— Choose a font —")].concat([ρσ_desugar_kwargs({value: ""})])));
            current_val = settings[(typeof name === "number" && name < 0) ? settings.length + name : name];
            if (!current_val) {
                ans.lastChild.setAttribute("selected", "selected");
            }
            var ρσ_Iter0 = ρσ_Iterable(runtime.all_font_families);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                family = ρσ_Iter0[ρσ_Index0];
                if (family) {
                    ans.appendChild(E.option(family));
                    if (family === current_val) {
                        ans.lastChild.setAttribute("selected", "selected");
                    }
                }
            }
            return ans;
        };
        if (!font_select.__argnames__) Object.defineProperties(font_select, {
            __argnames__ : {value: ["name", "settings"]}
        });

        function standard_font(settings) {
            var ans, sf;
            ans = ρσ_interpolate_kwargs.call(E, E.select, [ρσ_desugar_kwargs({name: "standard_font"})]);
            ans.appendChild(ρσ_interpolate_kwargs.call(E, E.option, [_("Serif")].concat([ρσ_desugar_kwargs({value: "serif"})])));
            ans.appendChild(ρσ_interpolate_kwargs.call(E, E.option, [_("Sans-serif")].concat([ρσ_desugar_kwargs({value: "sans"})])));
            ans.appendChild(ρσ_interpolate_kwargs.call(E, E.option, [_("Monospace")].concat([ρσ_desugar_kwargs({value: "mono"})])));
            sf = settings.standard_font || DEFAULT_STANDARD_FONT;
            ans.querySelector("[value=" + ρσ_str.format("{}", sf) + "]").setAttribute("selected", "selected");
            return ans;
        };
        if (!standard_font.__argnames__) Object.defineProperties(standard_font, {
            __argnames__ : {value: ["settings"]}
        });

        function minimum_font_size(settings) {
            var ans;
            ans = ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({max: "100", min: "0", step: "1", type: "number", name: "minimum_font_size"})]);
            if (typeof settings.minimum_font_size === "number") {
                ans.value = settings.minimum_font_size + "";
            } else {
                ans.value = "" + DEFAULT_MINIMUM_FONT_SIZE;
            }
            return ans;
        };
        if (!minimum_font_size.__argnames__) Object.defineProperties(minimum_font_size, {
            __argnames__ : {value: ["settings"]}
        });

        function zoom_step_size(settings) {
            var ans;
            ans = ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({max: "100", min: "1", step: "1", type: "number", name: "zoom_step_size"})]);
            if (typeof settings.zoom_step_size === "number") {
                ans.value = settings.zoom_step_size + "";
            } else {
                ans.value = "" + DEFAULT_ZOOM_STEP_SIZE;
            }
            return ans;
        };
        if (!zoom_step_size.__argnames__) Object.defineProperties(zoom_step_size, {
            __argnames__ : {value: ["settings"]}
        });

        function restore_defaults() {
            var container, q;
            container = get_container();
            var ρσ_Iter1 = ρσ_Iterable(ρσ_list_decorate([ "serif_family", "sans_family", "mono_family" ]));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                q = ρσ_Iter1[ρσ_Index1];
                container.querySelector("[name=" + ρσ_str.format("{}", q) + "]").value = "";
            }
            container.querySelector("[name=zoom_step_size]").value = DEFAULT_ZOOM_STEP_SIZE + "";
            container.querySelector("[name=minimum_font_size]").value = DEFAULT_MINIMUM_FONT_SIZE + "";
            container.querySelector("[name=standard_font]").value = DEFAULT_STANDARD_FONT;
        };

        function get_container() {
            return document.getElementById(CONTAINER);
        };

        function create_fonts_panel(container, apply_func, cancel_func) {
            var sd, settings;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: CONTAINER, style: "margin: 1rem"})]));
            container = container.lastChild;
            container.append(ρσ_interpolate_kwargs.call(E, E.div, [_("Choose fonts to use for un-styled text:")].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem"})])));
            sd = get_session_data();
            settings = sd.get("standalone_font_settings");
            function row(label, widget) {
                return E.tr(ρσ_interpolate_kwargs.call(E, E.td, [label + ": "].concat([ρσ_desugar_kwargs({style: "padding-top: 1ex"})])), ρσ_interpolate_kwargs.call(E, E.td, [widget].concat([ρσ_desugar_kwargs({style: "padding-top: 1ex"})])));
            };
            if (!row.__argnames__) Object.defineProperties(row, {
                __argnames__ : {value: ["label", "widget"]}
            });

            container.append(ρσ_interpolate_kwargs.call(E, E.table, [row(_("Serif family"), font_select("serif_family", settings)), row(_("Sans-serif family"), font_select("sans_family", settings)), row(_("Monospace family"), font_select("mono_family", settings)), row(_("Standard font"), standard_font(settings))].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem"})])));
            container.append(ρσ_interpolate_kwargs.call(E, E.div, [_("Zoom related settings")].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem"})])));
            container.append(ρσ_interpolate_kwargs.call(E, E.table, [row(_("Zoom step size (%)"), zoom_step_size(settings)), row(_("Minimum font size (px)"), minimum_font_size(settings))].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem"})])));
            container.appendChild(create_button_box(restore_defaults, apply_func, cancel_func));
        };
        if (!create_fonts_panel.__argnames__) Object.defineProperties(create_fonts_panel, {
            __argnames__ : {value: ["container", "apply_func", "cancel_func"]}
        });

        develop = create_fonts_panel;
        function commit_fonts(onchange) {
            var sd, container, vals, zss, mfs, sf, val, q;
            sd = get_session_data();
            container = get_container();
            vals = Object.create(null);
            zss = parseInt(container.querySelector("[name=zoom_step_size]").value);
            if (zss !== DEFAULT_ZOOM_STEP_SIZE) {
                vals.zoom_step_size = zss;
            }
            mfs = parseInt(container.querySelector("[name=minimum_font_size]").value);
            if (mfs !== DEFAULT_MINIMUM_FONT_SIZE) {
                vals.minimum_font_size = mfs;
            }
            sf = container.querySelector("[name=standard_font]").value;
            if (sf !== DEFAULT_STANDARD_FONT) {
                vals.standard_font = sf;
            }
            var ρσ_Iter2 = ρσ_Iterable(ρσ_list_decorate([ "serif_family", "sans_family", "mono_family" ]));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                q = ρσ_Iter2[ρσ_Index2];
                val = container.querySelector("[name=" + ρσ_str.format("{}", q) + "]").value;
                if (val) {
                    vals[(typeof q === "number" && q < 0) ? vals.length + q : q] = val;
                }
            }
            sd.set("standalone_font_settings", vals);
        };
        if (!commit_fonts.__argnames__) Object.defineProperties(commit_fonts, {
            __argnames__ : {value: ["onchange"]}
        });

        ρσ_modules["read_book.prefs.fonts"].CONTAINER = CONTAINER;
        ρσ_modules["read_book.prefs.fonts"].DEFAULT_STANDARD_FONT = DEFAULT_STANDARD_FONT;
        ρσ_modules["read_book.prefs.fonts"].DEFAULT_MINIMUM_FONT_SIZE = DEFAULT_MINIMUM_FONT_SIZE;
        ρσ_modules["read_book.prefs.fonts"].DEFAULT_ZOOM_STEP_SIZE = DEFAULT_ZOOM_STEP_SIZE;
        ρσ_modules["read_book.prefs.fonts"].develop = develop;
        ρσ_modules["read_book.prefs.fonts"].font_select = font_select;
        ρσ_modules["read_book.prefs.fonts"].standard_font = standard_font;
        ρσ_modules["read_book.prefs.fonts"].minimum_font_size = minimum_font_size;
        ρσ_modules["read_book.prefs.fonts"].zoom_step_size = zoom_step_size;
        ρσ_modules["read_book.prefs.fonts"].restore_defaults = restore_defaults;
        ρσ_modules["read_book.prefs.fonts"].get_container = get_container;
        ρσ_modules["read_book.prefs.fonts"].create_fonts_panel = create_fonts_panel;
        ρσ_modules["read_book.prefs.fonts"].commit_fonts = commit_fonts;
    })();

    (function(){
        var __name__ = "read_book.prefs.head_foot";
        var CONTAINER, time_formatter;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;
        var ngettext = ρσ_modules.gettext.ngettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var unique_id = ρσ_modules.dom.unique_id;

        var create_button_box = ρσ_modules["read_book.prefs.utils"].create_button_box;

        var defaults = ρσ_modules.session.defaults;
        var get_interface_data = ρσ_modules.session.get_interface_data;

        var fmt_sidx = ρσ_modules.utils.fmt_sidx;

        CONTAINER = unique_id("reader-hf-prefs");
        function create_item(region, label) {
            function sep() {
                return ρσ_interpolate_kwargs.call(E, E.option, [" "].concat([ρσ_desugar_kwargs({disabled: true})]));
            };

            function opt(label, name, selected) {
                return ρσ_interpolate_kwargs.call(E, E.option, [label].concat([ρσ_desugar_kwargs({id: name, value: name, selected: bool(selected)})]));
            };
            if (!opt.__argnames__) Object.defineProperties(opt, {
                __argnames__ : {value: ["label", "name", "selected"]}
            });

            return E.tr(ρσ_interpolate_kwargs.call(E, E.td, [label + ":"].concat([ρσ_desugar_kwargs({style: "padding: 1ex 1rem"})])), E.td(ρσ_interpolate_kwargs.call(E, E.select, [opt(_("Empty"), "empty", true), sep(), opt(_("Book title"), "title"), opt(_("Authors"), "authors"), opt(_("Series"), "series"), sep(), opt(_("Top level section"), "top-section"), opt(_("Current section"), "section"), sep(), opt(_("Progress"), "progress"), opt(_("Time to read book"), "time-book"), opt(_("Time to read chapter"), "time-chapter"), opt(_("Time to read chapter and book"), "time-chapter-book"), opt(_("Position in book"), "pos-book"), opt(_("Position in chapter"), "pos-chapter"), opt(_("Clock"), "clock")].concat([ρσ_desugar_kwargs({data_region: region})]))));
        };
        if (!create_item.__argnames__) Object.defineProperties(create_item, {
            __argnames__ : {value: ["region", "label"]}
        });

        function create_items(which) {
            var ans;
            ans = ρσ_interpolate_kwargs.call(E, E.table, [create_item("left", _("Left")), create_item("middle", _("Middle")), create_item("right", _("Right"))].concat([ρσ_desugar_kwargs({data_which: which})]));
            return ans;
        };
        if (!create_items.__argnames__) Object.defineProperties(create_items, {
            __argnames__ : {value: ["which"]}
        });

        function apply_setting(table, val) {
            var sel, opt, x, region;
            var ρσ_Iter0 = ρσ_Iterable("left middle right".split(" "));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                region = ρσ_Iter0[ρσ_Index0];
                sel = table.querySelector("select[data-region=" + ρσ_str.format("{}", region) + "]");
                var ρσ_Iter1 = ρσ_Iterable(sel.selectedOptions);
                for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                    opt = ρσ_Iter1[ρσ_Index1];
                    opt.selected = false;
                }
                x = val[(typeof region === "number" && region < 0) ? val.length + region : region] || "empty";
                opt = sel.namedItem(x);
                if (opt) {
                    opt.selected = true;
                } else {
                    sel.selectedIndex = 0;
                }
            }
        };
        if (!apply_setting.__argnames__) Object.defineProperties(apply_setting, {
            __argnames__ : {value: ["table", "val"]}
        });

        function get_setting(table) {
            var ans, sel, region;
            ans = Object.create(null);
            var ρσ_Iter2 = ρσ_Iterable("left middle right".split(" "));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                region = ρσ_Iter2[ρσ_Index2];
                sel = table.querySelector("select[data-region=" + ρσ_str.format("{}", region) + "]");
                if (sel.selectedIndex > -1) {
                    ans[(typeof region === "number" && region < 0) ? ans.length + region : region] = (ρσ_expr_temp = sel.options)[ρσ_bound_index(sel.selectedIndex, ρσ_expr_temp)].value;
                }
            }
            return ans;
        };
        if (!get_setting.__argnames__) Object.defineProperties(get_setting, {
            __argnames__ : {value: ["table"]}
        });

        function restore_defaults() {
            var container, table, which;
            container = document.getElementById(CONTAINER);
            var ρσ_Iter3 = ρσ_Iterable("header footer".split(" "));
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                which = ρσ_Iter3[ρσ_Index3];
                table = container.querySelector("table[data-which=" + ρσ_str.format("{}", which) + "]");
                apply_setting(table, defaults[(typeof which === "number" && which < 0) ? defaults.length + which : which] || Object.create(null));
            }
        };

        function create_head_foot_panel(container, apply_func, cancel_func) {
            var sd, table, which;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: CONTAINER})]));
            container = container.lastChild;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.h4, [_("Header")].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
            container.appendChild(create_items("header"));
            container.appendChild(E.hr());
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.h4, [_("Footer")].concat([ρσ_desugar_kwargs({style: "margin: 1rem; margin-top: 0"})])));
            container.appendChild(create_items("footer"));
            sd = get_session_data();
            var ρσ_Iter4 = ρσ_Iterable("header footer".split(" "));
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                which = ρσ_Iter4[ρσ_Index4];
                table = container.querySelector("table[data-which=" + ρσ_str.format("{}", which) + "]");
                apply_setting(table, sd.get(which) || Object.create(null));
            }
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [create_button_box(restore_defaults, apply_func, cancel_func)].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
        };
        if (!create_head_foot_panel.__argnames__) Object.defineProperties(create_head_foot_panel, {
            __argnames__ : {value: ["container", "apply_func", "cancel_func"]}
        });

        function commit_head_foot(onchange, container) {
            var sd, changed, prev, table, current, region, which;
            sd = get_session_data();
            changed = false;
            var ρσ_Iter5 = ρσ_Iterable("header footer".split(" "));
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                which = ρσ_Iter5[ρσ_Index5];
                prev = sd.get(which) || Object.create(null);
                table = container.querySelector("table[data-which=" + ρσ_str.format("{}", which) + "]");
                current = get_setting(table);
                var ρσ_Iter6 = ρσ_Iterable("left middle right".split(" "));
                for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                    region = ρσ_Iter6[ρσ_Index6];
                    if (prev[(typeof region === "number" && region < 0) ? prev.length + region : region] !== current[(typeof region === "number" && region < 0) ? current.length + region : region]) {
                        changed = true;
                    }
                }
                sd.set(which, get_setting(table));
            }
            if (changed) {
                onchange();
            }
        };
        if (!commit_head_foot.__argnames__) Object.defineProperties(commit_head_foot, {
            __argnames__ : {value: ["onchange", "container"]}
        });

        if (ρσ_exists.d(window.Intl).DateTimeFormat) {
            time_formatter = window.Intl.DateTimeFormat(undefined, (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["hour"] = "numeric";
                ρσ_d["minute"] = "numeric";
                return ρσ_d;
            }).call(this));
        } else {
            time_formatter = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["format"] = (function() {
                    var ρσ_anonfunc = function (date) {
                        return "{}:{}".format(date.getHours(), date.getMinutes());
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["date"]}
                    });
                    return ρσ_anonfunc;
                })();
                return ρσ_d;
            }).call(this);
        }
        function format_time_left(seconds) {
            var ρσ_unpack, hours, minutes;
            ρσ_unpack = divmod(int(seconds / 60), 60);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            hours = ρσ_unpack[0];
            minutes = ρσ_unpack[1];
            if (hours <= 0) {
                if (minutes < 1) {
                    return _("almost done");
                }
                minutes = minutes;
                return ngettext("{} min", "{} mins", minutes).format(minutes);
            }
            if (!minutes) {
                return ngettext("{} hour", "{} hours", hours).format(hours);
            }
            return _("{} h {} mins").format(hours, minutes);
        };
        if (!format_time_left.__argnames__) Object.defineProperties(format_time_left, {
            __argnames__ : {value: ["seconds"]}
        });

        function format_pos(progress_frac, length) {
            var pages, pos;
            if (length < 1) {
                return "";
            }
            pages = Math.ceil(length / 1e3);
            pos = progress_frac * pages;
            return "" + ρσ_str.format("{:.1f}", pos) + " / " + ρσ_str.format("{}", pages) + "";
        };
        if (!format_pos.__argnames__) Object.defineProperties(format_pos, {
            __argnames__ : {value: ["progress_frac", "length"]}
        });

        function render_head_foot(div, which, region, progress_frac, metadata, current_toc_node, current_toc_toplevel_node, book_time, chapter_time, pos) {
            var template, field, interface_data, text, has_clock, percent, ival;
            template = get_session_data().get(which) || Object.create(null);
            field = template[(typeof region === "number" && region < 0) ? template.length + region : region] || "empty";
            interface_data = get_interface_data();
            text = "";
            has_clock = false;
            if (field === "progress") {
                percent = min(100, max(Math.round(progress_frac * 100), 0));
                text = percent + "%";
            } else if (field === "title") {
                text = metadata.title || _("Untitled");
            } else if (field === "authors") {
                text = " & ".join(metadata.authors || []);
            } else if (field === "series") {
                if (metadata.series) {
                    ival = ρσ_interpolate_kwargs.call(this, fmt_sidx, [metadata.series_index].concat([ρσ_desugar_kwargs({use_roman: interface_data.use_roman_numerals_for_series_number})]));
                    text = _("{0} of {1}").format(ival, metadata.series);
                }
            } else if (field === "clock") {
                text = time_formatter.format(new Date);
                has_clock = true;
            } else if (field === "section") {
                text = (current_toc_node) ? current_toc_node.title : "";
            } else if (field === "top-section") {
                text = (current_toc_toplevel_node) ? current_toc_toplevel_node.title : "";
                if (!text) {
                    text = (current_toc_node) ? current_toc_node.title : "";
                }
            } else if (field.startswith("time-")) {
                if (book_time === null || chapter_time === null) {
                    text = _("Calculating...");
                } else {
                    if (field === "time-book") {
                        text = format_time_left(book_time);
                    } else if (field === "time-chapter") {
                        text = format_time_left(chapter_time);
                    } else {
                        text = "{} ({})".format(format_time_left(chapter_time), format_time_left(book_time));
                    }
                }
            } else if (field.startswith("pos-")) {
                if (field === "pos-book") {
                    text = format_pos(pos.current_progress_frac, pos.book_length);
                } else {
                    text = format_pos(pos.current_file_progress_frac, pos.chapter_length);
                }
            }
            if (!text) {
                text = " ";
            }
            if (text !== div.textContent) {
                div.textContent = text;
            }
            div.style.display = "block";
            return [text, has_clock];
        };
        if (!render_head_foot.__argnames__) Object.defineProperties(render_head_foot, {
            __argnames__ : {value: ["div", "which", "region", "progress_frac", "metadata", "current_toc_node", "current_toc_toplevel_node", "book_time", "chapter_time", "pos"]}
        });

        ρσ_modules["read_book.prefs.head_foot"].CONTAINER = CONTAINER;
        ρσ_modules["read_book.prefs.head_foot"].time_formatter = time_formatter;
        ρσ_modules["read_book.prefs.head_foot"].create_item = create_item;
        ρσ_modules["read_book.prefs.head_foot"].create_items = create_items;
        ρσ_modules["read_book.prefs.head_foot"].apply_setting = apply_setting;
        ρσ_modules["read_book.prefs.head_foot"].get_setting = get_setting;
        ρσ_modules["read_book.prefs.head_foot"].restore_defaults = restore_defaults;
        ρσ_modules["read_book.prefs.head_foot"].create_head_foot_panel = create_head_foot_panel;
        ρσ_modules["read_book.prefs.head_foot"].commit_head_foot = commit_head_foot;
        ρσ_modules["read_book.prefs.head_foot"].format_time_left = format_time_left;
        ρσ_modules["read_book.prefs.head_foot"].format_pos = format_pos;
        ρσ_modules["read_book.prefs.head_foot"].render_head_foot = render_head_foot;
    })();

    (function(){
        var __name__ = "read_book.prefs.keyboard";
        var develop;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var create_item = ρσ_modules["book_list.item_list"].create_item;
        var create_item_list = ρσ_modules["book_list.item_list"].create_item_list;

        var clear = ρσ_modules.dom.clear;
        var svgicon = ρσ_modules.dom.svgicon;
        var unique_id = ρσ_modules.dom.unique_id;

        var GROUP_DESC = ρσ_modules["read_book.shortcuts"].GROUP_DESC;
        var SHORTCUTS = ρσ_modules["read_book.shortcuts"].SHORTCUTS;
        var key_as_text = ρσ_modules["read_book.shortcuts"].key_as_text;
        var keyevent_as_shortcut = ρσ_modules["read_book.shortcuts"].keyevent_as_shortcut;
        var shortcut_differs = ρσ_modules["read_book.shortcuts"].shortcut_differs;

        var create_button = ρσ_modules.widgets.create_button;

        function get_container() {
            return document.getElementById(get_container.id);
        };

        function restore_defaults(close_func) {
            var q, item;
            get_container().dataset.changed = "true";
            var ρσ_Iter0 = ρσ_Iterable(get_container().querySelectorAll("[data-user-data]"));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                item = ρσ_Iter0[ρσ_Index0];
                q = JSON.parse(item.dataset.userData);
                q.shortcuts = SHORTCUTS[ρσ_bound_index(q.name, SHORTCUTS)].shortcuts;
                item.dataset.userData = JSON.stringify(q);
            }
            close_func();
        };
        if (!restore_defaults.__argnames__) Object.defineProperties(restore_defaults, {
            __argnames__ : {value: ["close_func"]}
        });

        function as_groups(shortcuts) {
            var ans, sc, sc_name;
            ans = Object.create(null);
            var ρσ_Iter1 = ρσ_Iterable(Object.keys(shortcuts));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                sc_name = ρσ_Iter1[ρσ_Index1];
                sc = shortcuts[(typeof sc_name === "number" && sc_name < 0) ? shortcuts.length + sc_name : sc_name];
                if (!ans[ρσ_bound_index(sc.group, ans)]) {
                    ans[ρσ_bound_index(sc.group, ans)] = Object.create(null);
                }
                (ρσ_expr_temp = ans[ρσ_bound_index(sc.group, ans)])[(typeof sc_name === "number" && sc_name < 0) ? ρσ_expr_temp.length + sc_name : sc_name] = sc;
            }
            return ans;
        };
        if (!as_groups.__argnames__) Object.defineProperties(as_groups, {
            __argnames__ : {value: ["shortcuts"]}
        });

        function sort_group_key(group, sc_name) {
            return group[(typeof sc_name === "number" && sc_name < 0) ? group.length + sc_name : sc_name].short.toLowerCase();
        };
        if (!sort_group_key.__argnames__) Object.defineProperties(sort_group_key, {
            __argnames__ : {value: ["group", "sc_name"]}
        });

        function sc_as_item(sc_name, sc, shortcuts) {
            var cuts;
            cuts = shortcuts || sc.shortcuts;
            return ρσ_interpolate_kwargs.call(this, create_item, [sc.short].concat([ρσ_desugar_kwargs({action: customize_shortcut.bind(null, sc_name), subtitle: sc.long, data: JSON.stringify((function(){
                var ρσ_d = Object.create(null);
                ρσ_d["name"] = sc_name;
                ρσ_d["shortcuts"] = cuts;
                return ρσ_d;
            }).call(this))})]));
        };
        if (!sc_as_item.__argnames__) Object.defineProperties(sc_as_item, {
            __argnames__ : {value: ["sc_name", "sc", "shortcuts"]}
        });

        function remove_key(evt) {
            var key_container;
            key_container = evt.currentTarget.parentNode.parentNode;
            key_container.parentNode.removeChild(key_container);
        };
        if (!remove_key.__argnames__) Object.defineProperties(remove_key, {
            __argnames__ : {value: ["evt"]}
        });

        function key_widget(key) {
            return ρσ_interpolate_kwargs.call(E, E.tr, [ρσ_interpolate_kwargs.call(E, E.td, [key_as_text(key)].concat([ρσ_desugar_kwargs({style: "padding: 0.5rem; border-right: solid 3px; margin-right: 0.5rem; margin-top: 0.5rem"})])), E.td(ρσ_interpolate_kwargs.call(E, E.a, [" ", svgicon("remove"), " ", _("Remove")].concat([ρσ_desugar_kwargs({class_: "simple-link", onclick: remove_key})])))].concat([ρσ_desugar_kwargs({data_shortcut: JSON.stringify(keyevent_as_shortcut(key))})]));
        };
        if (!key_widget.__argnames__) Object.defineProperties(key_widget, {
            __argnames__ : {value: ["key"]}
        });

        function close_customize_shortcut(apply_changes) {
            var container, q, item, shortcuts, sc, x, sc_name;
            container = get_container();
            container.firstChild.style.display = "block";
            container.lastChild.style.display = "none";
            if (close_customize_shortcut.shortcut_being_customized) {
                var ρσ_Iter2 = ρσ_Iterable(container.firstChild.querySelectorAll("[data-user-data]"));
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    item = ρσ_Iter2[ρσ_Index2];
                    q = JSON.parse(item.dataset.userData);
                    if (q.name === close_customize_shortcut.shortcut_being_customized) {
                        item.scrollIntoView();
                        break;
                    }
                }
            }
            if (apply_changes) {
                shortcuts = [];
                var ρσ_Iter3 = ρσ_Iterable(container.lastChild.querySelectorAll("[data-shortcut]"));
                for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                    x = ρσ_Iter3[ρσ_Index3];
                    sc = JSON.parse(x.dataset.shortcut);
                    shortcuts.push(sc);
                }
                sc_name = container.lastChild.dataset.scName;
                var ρσ_Iter4 = ρσ_Iterable(container.querySelectorAll("[data-user-data]"));
                for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                    item = ρσ_Iter4[ρσ_Index4];
                    q = JSON.parse(item.dataset.userData);
                    if (q.name === sc_name) {
                        q.shortcuts = shortcuts;
                        item.dataset.userData = JSON.stringify(q);
                        break;
                    }
                }
                get_container().dataset.changed = "true";
                commit_keyboard(create_keyboard_panel.onchange);
            }
        };
        if (!close_customize_shortcut.__argnames__) Object.defineProperties(close_customize_shortcut, {
            __argnames__ : {value: ["apply_changes"]}
        });

        function add_key_widget() {
            var uid;
            uid = unique_id("add-new-shortcut");
            return ρσ_interpolate_kwargs.call(E, E.div, [E.div(ρσ_interpolate_kwargs.call(this, create_button, [_("Add a new shortcut")].concat([ρσ_desugar_kwargs({icon: "plus", action: (function() {
                var ρσ_anonfunc = function (evt) {
                    var div;
                    div = document.getElementById(uid);
                    div.firstChild.style.display = "none";
                    div.lastChild.style.display = "block";
                    div.lastChild.querySelector("input").focus();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["evt"]}
                });
                return ρσ_anonfunc;
            })()})]))), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({readonly: "readonly", value: _("Press the key combination to use as a shortcut"), style: "width: 90vw", onkeydown: (function() {
                var ρσ_anonfunc = function (evt) {
                    var key_con, div;
                    evt.preventDefault();
                    evt.stopPropagation();
                    if (!ρσ_in(evt.key, ['Control', 'Meta', 'Alt', 'Shift'])) {
                        key_con = get_container().querySelector(".key-container");
                        key_con.appendChild(key_widget(evt));
                        div = document.getElementById(uid);
                        div.firstChild.style.display = "block";
                        div.lastChild.style.display = "none";
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["evt"]}
                });
                return ρσ_anonfunc;
            })()})])].concat([ρσ_desugar_kwargs({style: "display:none"})]))].concat([ρσ_desugar_kwargs({style: "margin-top: 1ex; margin-bottom: 1ex", id: uid})]));
        };

        function customize_shortcut(sc_name) {
            var container, shortcuts, q, item, sc, key_con, key;
            container = get_container();
            container.firstChild.style.display = "none";
            container.lastChild.style.display = "block";
            close_customize_shortcut.shortcut_being_customized = sc_name;
            shortcuts = [];
            var ρσ_Iter5 = ρσ_Iterable(container.querySelectorAll("[data-user-data]"));
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                item = ρσ_Iter5[ρσ_Index5];
                q = JSON.parse(item.dataset.userData);
                if (q.name === sc_name) {
                    shortcuts = q.shortcuts;
                    break;
                }
            }
            container = container.lastChild;
            clear(container);
            container.dataset.scName = sc_name;
            sc = SHORTCUTS[(typeof sc_name === "number" && sc_name < 0) ? SHORTCUTS.length + sc_name : sc_name];
            container.appendChild(E.h4(sc.short));
            if (sc.long) {
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [sc.long].concat([ρσ_desugar_kwargs({style: "font-style: italic; font-size: smaller; margin-top: 1ex"})])));
            }
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Existing shortcuts:")].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem"})])));
            key_con = container.appendChild(ρσ_interpolate_kwargs.call(E, E.table, [ρσ_desugar_kwargs({class_: "key-container"})]));
            var ρσ_Iter6 = ρσ_Iterable(shortcuts);
            for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                key = ρσ_Iter6[ρσ_Index6];
                key_con.appendChild(key_widget(key));
            }
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [add_key_widget()].concat([ρσ_desugar_kwargs({style: "margin-top:1ex;"})])));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(this, create_button, [_("OK")].concat([ρσ_desugar_kwargs({action: close_customize_shortcut.bind(null, true)})])), E.span(" "), ρσ_interpolate_kwargs.call(this, create_button, [_("Cancel")].concat([ρσ_desugar_kwargs({action: close_customize_shortcut.bind(null, false)})]))].concat([ρσ_desugar_kwargs({style: "margin-top:1ex; display:flex; justify-content: flex-end"})])));
        };
        if (!customize_shortcut.__argnames__) Object.defineProperties(customize_shortcut, {
            __argnames__ : {value: ["sc_name"]}
        });

        function create_keyboard_panel(container, close_func, onchange) {
            var sd, custom_shortcuts, groups, group, items, sc, sc_name, group_name;
            create_keyboard_panel.onchange = onchange;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: unique_id("keyboard-settings"), style: "margin: 1rem"})]));
            container = container.lastChild;
            container.dataset.changed = "false";
            get_container.id = container.id;
            container.appendChild(E.div());
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "display: none"})]));
            container = container.firstChild;
            sd = get_session_data();
            custom_shortcuts = sd.get("keyboard_shortcuts");
            groups = as_groups(SHORTCUTS);
            var ρσ_Iter7 = ρσ_Iterable(Object.keys(groups));
            for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                group_name = ρσ_Iter7[ρσ_Index7];
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.h3, [GROUP_DESC[(typeof group_name === "number" && group_name < 0) ? GROUP_DESC.length + group_name : group_name]].concat([ρσ_desugar_kwargs({style: "margin-top: 1ex"})])));
                group = groups[(typeof group_name === "number" && group_name < 0) ? groups.length + group_name : group_name];
                items = ρσ_list_decorate([]);
                var ρσ_Iter8 = ρσ_Iterable(ρσ_interpolate_kwargs.call(this, sorted, [Object.keys(group)].concat([ρσ_desugar_kwargs({key: sort_group_key.bind(null, group)})])));
                for (var ρσ_Index8 = 0; ρσ_Index8 < ρσ_Iter8.length; ρσ_Index8++) {
                    sc_name = ρσ_Iter8[ρσ_Index8];
                    sc = group[(typeof sc_name === "number" && sc_name < 0) ? group.length + sc_name : sc_name];
                    items.push(sc_as_item(sc_name, sc, custom_shortcuts[(typeof sc_name === "number" && sc_name < 0) ? custom_shortcuts.length + sc_name : sc_name]));
                }
                container.appendChild(E.div());
                create_item_list(container.lastChild, items);
            }
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(this, create_button, [_("Restore defaults")].concat([ρσ_desugar_kwargs({action: restore_defaults.bind(null, close_func)})]))].concat([ρσ_desugar_kwargs({style: "margin-top: 1rem"})])));
        };
        if (!create_keyboard_panel.__argnames__) Object.defineProperties(create_keyboard_panel, {
            __argnames__ : {value: ["container", "close_func", "onchange"]}
        });

        develop = create_keyboard_panel;
        function shortcuts_differ(a, b) {
            var ρσ_unpack, x, y;
            if (a.length !== b.length) {
                return true;
            }
            var ρσ_Iter9 = ρσ_Iterable(zip(a, b));
            for (var ρσ_Index9 = 0; ρσ_Index9 < ρσ_Iter9.length; ρσ_Index9++) {
                ρσ_unpack = ρσ_Iter9[ρσ_Index9];
                x = ρσ_unpack[0];
                y = ρσ_unpack[1];
                if (shortcut_differs(x, y)) {
                    return true;
                }
            }
            return false;
        };
        if (!shortcuts_differ.__argnames__) Object.defineProperties(shortcuts_differ, {
            __argnames__ : {value: ["a", "b"]}
        });

        function commit_keyboard(onchange) {
            var sd, vals, q, item;
            sd = get_session_data();
            vals = Object.create(null);
            var ρσ_Iter10 = ρσ_Iterable(get_container().querySelectorAll("[data-user-data]"));
            for (var ρσ_Index10 = 0; ρσ_Index10 < ρσ_Iter10.length; ρσ_Index10++) {
                item = ρσ_Iter10[ρσ_Index10];
                q = JSON.parse(item.dataset.userData);
                if (shortcuts_differ(q.shortcuts, SHORTCUTS[ρσ_bound_index(q.name, SHORTCUTS)].shortcuts)) {
                    vals[ρσ_bound_index(q.name, vals)] = q.shortcuts;
                }
            }
            sd.set("keyboard_shortcuts", vals);
            create_keyboard_panel.onchange = null;
            if (get_container().dataset.changed === "true") {
                onchange();
            }
        };
        if (!commit_keyboard.__argnames__) Object.defineProperties(commit_keyboard, {
            __argnames__ : {value: ["onchange"]}
        });

        ρσ_modules["read_book.prefs.keyboard"].develop = develop;
        ρσ_modules["read_book.prefs.keyboard"].get_container = get_container;
        ρσ_modules["read_book.prefs.keyboard"].restore_defaults = restore_defaults;
        ρσ_modules["read_book.prefs.keyboard"].as_groups = as_groups;
        ρσ_modules["read_book.prefs.keyboard"].sort_group_key = sort_group_key;
        ρσ_modules["read_book.prefs.keyboard"].sc_as_item = sc_as_item;
        ρσ_modules["read_book.prefs.keyboard"].remove_key = remove_key;
        ρσ_modules["read_book.prefs.keyboard"].key_widget = key_widget;
        ρσ_modules["read_book.prefs.keyboard"].close_customize_shortcut = close_customize_shortcut;
        ρσ_modules["read_book.prefs.keyboard"].add_key_widget = add_key_widget;
        ρσ_modules["read_book.prefs.keyboard"].customize_shortcut = customize_shortcut;
        ρσ_modules["read_book.prefs.keyboard"].create_keyboard_panel = create_keyboard_panel;
        ρσ_modules["read_book.prefs.keyboard"].shortcuts_differ = shortcuts_differ;
        ρσ_modules["read_book.prefs.keyboard"].commit_keyboard = commit_keyboard;
    })();

    (function(){
        var __name__ = "read_book.prefs.scrolling";
        var CONTAINER, develop;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var unique_id = ρσ_modules.dom.unique_id;

        var create_button_box = ρσ_modules["read_book.prefs.utils"].create_button_box;

        var defaults = ρσ_modules.session.defaults;

        CONTAINER = unique_id("standalone-scrolling-settings");
        function restore_defaults() {
            var container, control;
            container = get_container();
            var ρσ_Iter0 = ρσ_Iterable(container.querySelectorAll("input[name]"));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                control = ρσ_Iter0[ρσ_Index0];
                control.checked = defaults[ρσ_bound_index(control.getAttribute("name"), defaults)];
            }
        };

        function get_container() {
            return document.getElementById(CONTAINER);
        };

        function create_scrolling_panel(container, apply_func, cancel_func) {
            var sd;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: CONTAINER, style: "margin: 1rem"})]));
            container = container.lastChild;
            sd = get_session_data();
            function cb(name, text) {
                var ans;
                ans = ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "checkbox", name: name})]);
                if (sd.get(name)) {
                    ans.checked = true;
                }
                return ρσ_interpolate_kwargs.call(E, E.div, [E.label(ans, " " + text)].concat([ρσ_desugar_kwargs({style: "margin-top:1ex"})]));
            };
            if (!cb.__argnames__) Object.defineProperties(cb, {
                __argnames__ : {value: ["name", "text"]}
            });

            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Control how mouse based scrolling works in paged mode")].concat([ρσ_desugar_kwargs({style: "margin-top:1ex"})])));
            container.appendChild(cb("paged_wheel_scrolls_by_screen", _("Mouse wheel scrolls by screen fulls instead of pages")));
            container.appendChild(cb("paged_margin_clicks_scroll_by_screen", _("Clicking on the margins scrolls by screen fulls instead of pages")));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [" "].concat([ρσ_desugar_kwargs({style: "margin-top:1ex; border-top: solid 1px"})])));
            container.appendChild(cb("book_scrollbar", _("Show a scrollbar")));
            container.appendChild(create_button_box(restore_defaults, apply_func, cancel_func));
        };
        if (!create_scrolling_panel.__argnames__) Object.defineProperties(create_scrolling_panel, {
            __argnames__ : {value: ["container", "apply_func", "cancel_func"]}
        });

        develop = create_scrolling_panel;
        function commit_scrolling(onchange) {
            var sd, container, name, val, control;
            sd = get_session_data();
            container = get_container();
            var ρσ_Iter1 = ρσ_Iterable(container.querySelectorAll("input[name]"));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                control = ρσ_Iter1[ρσ_Index1];
                name = control.getAttribute("name");
                val = control.checked;
                sd.set(name, (val === defaults[(typeof name === "number" && name < 0) ? defaults.length + name : name]) ? null : val);
            }
            onchange();
        };
        if (!commit_scrolling.__argnames__) Object.defineProperties(commit_scrolling, {
            __argnames__ : {value: ["onchange"]}
        });

        ρσ_modules["read_book.prefs.scrolling"].CONTAINER = CONTAINER;
        ρσ_modules["read_book.prefs.scrolling"].develop = develop;
        ρσ_modules["read_book.prefs.scrolling"].restore_defaults = restore_defaults;
        ρσ_modules["read_book.prefs.scrolling"].get_container = get_container;
        ρσ_modules["read_book.prefs.scrolling"].create_scrolling_panel = create_scrolling_panel;
        ρσ_modules["read_book.prefs.scrolling"].commit_scrolling = commit_scrolling;
    })();

    (function(){
        var __name__ = "read_book.prefs.layout";
        var CONTAINER, MARGINS, READ_MODE, COLS, TEXT_AREA, develop;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var element = ρσ_modules.dom.element;
        var unique_id = ρσ_modules.dom.unique_id;

        var create_button_box = ρσ_modules["read_book.prefs.utils"].create_button_box;

        var defaults = ρσ_modules.session.defaults;

        CONTAINER = unique_id("reader-page-layout");
        MARGINS = unique_id("reader-page-margins");
        READ_MODE = unique_id("read-mode");
        COLS = unique_id("cols-per-screen");
        TEXT_AREA = unique_id("text-area");
        add_extra_css(function () {
            var sel, style;
            sel = "#" + MARGINS;
            style = ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({margin_left: "2em", margin_top: "-1em"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, ["#{} td".format(CONTAINER)].concat([ρσ_desugar_kwargs({padding: "1ex 1em"})]));
            return style;
        });
        function restore_defaults() {
            var container, which, name;
            container = document.getElementById(CONTAINER);
            var ρσ_Iter0 = ρσ_Iterable("top bottom left right".split(" "));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                which = ρσ_Iter0[ρσ_Index0];
                container.querySelector("input[name={}]".format(which)).value = str(defaults[ρσ_bound_index("margin_" + which, defaults)]);
            }
            var ρσ_Iter1 = ρσ_Iterable("paged flow".split(" "));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                name = ρσ_Iter1[ρσ_Index1];
                container.querySelector("input[data-name={}]".format(name)).checked = defaults.read_mode === name;
            }
            var ρσ_Iter2 = ρσ_Iterable("portrait landscape".split(" "));
            for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                name = ρσ_Iter2[ρσ_Index2];
                container.querySelector("input[name={}]".format(name)).value = str((ρσ_expr_temp = defaults.columns_per_screen)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name]);
            }
            var ρσ_Iter3 = ρσ_Iterable("width height".split(" "));
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                which = ρσ_Iter3[ρσ_Index3];
                container.querySelector("input[name={}]".format(which)).value = str(defaults[ρσ_bound_index("max_text_" + which, defaults)]);
            }
            container.querySelector("input[name=cover_preserve_aspect_ratio]").checked = defaults.cover_preserve_aspect_ratio;
        };

        function create_layout_panel(container, apply_func, cancel_func) {
            var sd, labels, which, rm, cps;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: CONTAINER})]));
            container = container.lastChild;
            sd = get_session_data();
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.p, [_("Change the page margins (in pixels) below")].concat([ρσ_desugar_kwargs({style: "margin:1ex 1rem; padding: 1ex 0"})])));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.table, [ρσ_desugar_kwargs({id: MARGINS})]));
            labels = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["top"] = _("Top:");
                ρσ_d["bottom"] = _("Bottom:");
                ρσ_d["left"] = _("Left:");
                ρσ_d["right"] = _("Right:");
                return ρσ_d;
            }).call(this);
            var ρσ_Iter4 = ρσ_Iterable("top bottom left right".split(" "));
            for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                which = ρσ_Iter4[ρσ_Index4];
                container.lastChild.appendChild(E.tr(E.td(labels[(typeof which === "number" && which < 0) ? labels.length + which : which]), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "number", min: "0", step: "1", name: which, value: str(sd.get("margin_" + which))})]))));
            }
            function sec(text) {
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [text].concat([ρσ_desugar_kwargs({style: "margin: 2ex 1rem; padding-top:2ex; border-top: solid 1px"})])));
            };
            if (!sec.__argnames__) Object.defineProperties(sec, {
                __argnames__ : {value: ["text"]}
            });

            sec(_("Choose the page layout mode. In paged mode, the text is split up into individual pages, as in a paper book. In flow mode text is presented as one long scrolling page, as in web browsers."));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: READ_MODE, style: "margin: 1ex 2rem; display: flex;"})]));
            rm = sd.get("read_mode");
            rm = (rm === "flow") ? "flow" : "paged";
            function rb(name, text) {
                var d;
                d = container.lastChild;
                d.appendChild(E.label(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "radio", name: "page-layout-mode", data_name: name, checked: rm === name})]), text));
            };
            if (!rb.__argnames__) Object.defineProperties(rb, {
                __argnames__ : {value: ["name", "text"]}
            });

            rb("paged", _("Paged mode"));
            container.lastChild.appendChild(ρσ_interpolate_kwargs.call(E, E.span, [" "].concat([ρσ_desugar_kwargs({style: "width:3em"})])));
            rb("flow", _("Flow mode"));
            sec(_("In paged mode, control the number of pages per screen. A setting of zero means the number of pages is set based on the screen size."));
            cps = sd.get("columns_per_screen");
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.table, [E.tr(E.td(_("In portrait orientation:")), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "number", name: "portrait", min: "0", step: "1", max: "20", value: str(cps.portrait)})]))), E.tr(E.td(_("In landscape orientation:")), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "number", name: "landscape", min: "0", step: "1", max: "20", value: str(cps.landscape)})])))].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1rem", id: COLS})])));
            sec(_("Change the maximum screen area (in pixels) used to display text. A value of zero means that all available screen area is used."));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.table, [E.tr(E.td(_("Max. width:")), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "number", name: "width", min: "0", step: "10", value: str(sd.get("max_text_width"))})]))), E.tr(E.td(_("Max. height:")), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "number", name: "height", min: "0", step: "10", value: str(sd.get("max_text_height"))})])))].concat([ρσ_desugar_kwargs({style: "margin: 1ex 1rem", id: TEXT_AREA})])));
            sec(_("Control how the cover is displayed"));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.label(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "checkbox", name: "cover_preserve_aspect_ratio", checked: sd.get("cover_preserve_aspect_ratio")})]), _("Preserve cover aspect ratio"))].concat([ρσ_desugar_kwargs({style: "margin: 1ex 2rem; display: flex;"})])));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [create_button_box(restore_defaults, apply_func, cancel_func)].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
        };
        if (!create_layout_panel.__argnames__) Object.defineProperties(create_layout_panel, {
            __argnames__ : {value: ["container", "apply_func", "cancel_func"]}
        });

        develop = create_layout_panel;
        function commit_layout(onchange, container) {
            var was_changed, sd, i, val, which, rm, crm, cps, inp, cover_preserve_aspect_ratio;
            was_changed = false;
            sd = get_session_data();
            var ρσ_Iter5 = ρσ_Iterable("top bottom left right".split(" "));
            for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                which = ρσ_Iter5[ρσ_Index5];
                i = element(MARGINS, "[name={}]".format(which));
                try {
                    val = int(i.value);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        continue;
                    } 
                }
                if (val !== sd.get("margin_" + which)) {
                    was_changed = true;
                    sd.set("margin_" + which, val);
                }
            }
            rm = sd.get("read_mode");
            rm = (rm === "flow") ? "flow" : "paged";
            crm = (element(READ_MODE, "input").checked) ? "paged" : "flow";
            if (rm !== crm) {
                was_changed = true;
                sd.set("read_mode", crm);
            }
            cps = sd.get("columns_per_screen");
            var ρσ_Iter6 = ρσ_Iterable(ρσ_list_decorate([ "portrait", "landscape" ]));
            for (var ρσ_Index6 = 0; ρσ_Index6 < ρσ_Iter6.length; ρσ_Index6++) {
                which = ρσ_Iter6[ρσ_Index6];
                inp = element(COLS, "input[name={}]".format(which));
                try {
                    val = int(inp.value);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        continue;
                    } 
                }
                if (cps[(typeof which === "number" && which < 0) ? cps.length + which : which] !== val) {
                    cps[(typeof which === "number" && which < 0) ? cps.length + which : which] = val;
                    sd.set("columns_per_screen", cps);
                    was_changed = true;
                }
            }
            var ρσ_Iter7 = ρσ_Iterable(ρσ_list_decorate([ "width", "height" ]));
            for (var ρσ_Index7 = 0; ρσ_Index7 < ρσ_Iter7.length; ρσ_Index7++) {
                which = ρσ_Iter7[ρσ_Index7];
                try {
                    val = int(element(TEXT_AREA, "input[name={}]".format(which)).value);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    {
                        continue;
                    } 
                }
                if (val !== sd.get("max_text_" + which)) {
                    was_changed = true;
                    sd.set("max_text_" + which, val);
                }
            }
            cover_preserve_aspect_ratio = element(CONTAINER, "input[name=cover_preserve_aspect_ratio]").checked;
            if (cover_preserve_aspect_ratio !== sd.get("cover_preserve_aspect_ratio")) {
                was_changed = true;
                sd.set("cover_preserve_aspect_ratio", cover_preserve_aspect_ratio);
            }
            if (was_changed) {
                onchange();
            }
        };
        if (!commit_layout.__argnames__) Object.defineProperties(commit_layout, {
            __argnames__ : {value: ["onchange", "container"]}
        });

        ρσ_modules["read_book.prefs.layout"].CONTAINER = CONTAINER;
        ρσ_modules["read_book.prefs.layout"].MARGINS = MARGINS;
        ρσ_modules["read_book.prefs.layout"].READ_MODE = READ_MODE;
        ρσ_modules["read_book.prefs.layout"].COLS = COLS;
        ρσ_modules["read_book.prefs.layout"].TEXT_AREA = TEXT_AREA;
        ρσ_modules["read_book.prefs.layout"].develop = develop;
        ρσ_modules["read_book.prefs.layout"].restore_defaults = restore_defaults;
        ρσ_modules["read_book.prefs.layout"].create_layout_panel = create_layout_panel;
        ρσ_modules["read_book.prefs.layout"].commit_layout = commit_layout;
    })();

    (function(){
        var __name__ = "read_book.prefs.misc";
        var CONTAINER, DEFAULTS, develop;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var unique_id = ρσ_modules.dom.unique_id;

        var defaults = ρσ_modules.session.defaults;

        var create_button_box = ρσ_modules["read_book.prefs.utils"].create_button_box;

        CONTAINER = unique_id("standalone-misc-settings");
        DEFAULTS = (function(){
            var ρσ_d = Object.create(null);
            ρσ_d["remember_window_geometry"] = false;
            ρσ_d["remember_last_read"] = true;
            ρσ_d["save_annotations_in_ebook"] = true;
            ρσ_d["singleinstance"] = false;
            return ρσ_d;
        }).call(this);
        function restore_defaults() {
            var container, q;
            container = get_container();
            var ρσ_Iter0 = ρσ_Iterable(Object.keys(DEFAULTS));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                q = ρσ_Iter0[ρσ_Index0];
                container.querySelector("[name=" + ρσ_str.format("{}", q) + "]").checked = DEFAULTS[(typeof q === "number" && q < 0) ? DEFAULTS.length + q : q];
            }
            container.querySelector("[name=hide_tooltips]").checked = defaults.hide_tooltips;
        };

        function get_container() {
            return document.getElementById(CONTAINER);
        };

        function create_misc_panel(container, apply_func, cancel_func) {
            var sd, settings;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: CONTAINER, style: "margin: 1rem"})]));
            container = container.lastChild;
            sd = get_session_data();
            settings = sd.get("standalone_misc_settings");
            settings.hide_tooltips = sd.get("hide_tooltips");
            function cb(name, text) {
                var ans;
                ans = ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "checkbox", name: name})]);
                ans.checked = (typeof settings[(typeof name === "number" && name < 0) ? settings.length + name : name] === "boolean") ? settings[(typeof name === "number" && name < 0) ? settings.length + name : name] : DEFAULTS[(typeof name === "number" && name < 0) ? DEFAULTS.length + name : name];
                return ρσ_interpolate_kwargs.call(E, E.div, [E.label(ans, " " + text)].concat([ρσ_desugar_kwargs({style: "margin-top:1ex"})]));
            };
            if (!cb.__argnames__) Object.defineProperties(cb, {
                __argnames__ : {value: ["name", "text"]}
            });

            container.append(cb("remember_window_geometry", _("Remember last used window size and position")));
            container.append(cb("remember_last_read", _("Remember current page when quitting")));
            container.append(cb("save_annotations_in_ebook", _("Keep a copy of annotations/bookmarks in the e-book file, for easy sharing")));
            container.append(cb("singleinstance", _("Allow only a single instance of the viewer (needs restart)")));
            container.append(cb("hide_tooltips", _("Hide mouse-over tooltips in the book text")));
            container.appendChild(create_button_box(restore_defaults, apply_func, cancel_func));
        };
        if (!create_misc_panel.__argnames__) Object.defineProperties(create_misc_panel, {
            __argnames__ : {value: ["container", "apply_func", "cancel_func"]}
        });

        develop = create_misc_panel;
        function commit_misc(onchange) {
            var sd, container, vals, val, q, hide_tooltips;
            sd = get_session_data();
            container = get_container();
            vals = Object.create(null);
            var ρσ_Iter1 = ρσ_Iterable(Object.keys(DEFAULTS));
            for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                q = ρσ_Iter1[ρσ_Index1];
                val = container.querySelector("[name=" + ρσ_str.format("{}", q) + "]").checked;
                if (val !== DEFAULTS[(typeof q === "number" && q < 0) ? DEFAULTS.length + q : q]) {
                    vals[(typeof q === "number" && q < 0) ? vals.length + q : q] = val;
                }
            }
            sd.set("standalone_misc_settings", vals);
            hide_tooltips = container.querySelector("[name=hide_tooltips]").checked;
            sd.set("hide_tooltips", (hide_tooltips === defaults.hide_tooltips) ? null : hide_tooltips);
            onchange();
        };
        if (!commit_misc.__argnames__) Object.defineProperties(commit_misc, {
            __argnames__ : {value: ["onchange"]}
        });

        ρσ_modules["read_book.prefs.misc"].CONTAINER = CONTAINER;
        ρσ_modules["read_book.prefs.misc"].DEFAULTS = DEFAULTS;
        ρσ_modules["read_book.prefs.misc"].develop = develop;
        ρσ_modules["read_book.prefs.misc"].restore_defaults = restore_defaults;
        ρσ_modules["read_book.prefs.misc"].get_container = get_container;
        ρσ_modules["read_book.prefs.misc"].create_misc_panel = create_misc_panel;
        ρσ_modules["read_book.prefs.misc"].commit_misc = commit_misc;
    })();

    (function(){
        var __name__ = "viewer";

    })();

    (function(){
        var __name__ = "viewer.constants";
        var FAKE_PROTOCOL, FAKE_HOST, READER_BACKGROUND_URL;
        FAKE_PROTOCOL = "clbr";
        FAKE_HOST = "internal.invalid";
        READER_BACKGROUND_URL = "" + ρσ_str.format("{}", FAKE_PROTOCOL) + "://" + ρσ_str.format("{}", FAKE_HOST) + "/reader-background";
        ρσ_modules["viewer.constants"].FAKE_PROTOCOL = FAKE_PROTOCOL;
        ρσ_modules["viewer.constants"].FAKE_HOST = FAKE_HOST;
        ρσ_modules["viewer.constants"].READER_BACKGROUND_URL = READER_BACKGROUND_URL;
    })();

    (function(){
        var __name__ = "read_book.prefs.user_stylesheet";
        var BLANK, develop;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var ensure_id = ρσ_modules.dom.ensure_id;
        var unique_id = ρσ_modules.dom.unique_id;

        var runtime = ρσ_modules["read_book.globals"].runtime;
        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var create_button_box = ρσ_modules["read_book.prefs.utils"].create_button_box;

        var defaults = ρσ_modules.session.defaults;

        var READER_BACKGROUND_URL = ρσ_modules["viewer.constants"].READER_BACKGROUND_URL;

        var create_button = ρσ_modules.widgets.create_button;

        BLANK = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
        function change_background_image(img_id) {
            ui_operations.change_background_image(img_id);
        };
        if (!change_background_image.__argnames__) Object.defineProperties(change_background_image, {
            __argnames__ : {value: ["img_id"]}
        });

        function clear_image(img_id) {
            document.getElementById(img_id).src = BLANK;
        };
        if (!clear_image.__argnames__) Object.defineProperties(clear_image, {
            __argnames__ : {value: ["img_id"]}
        });

        function standalone_background_widget(sd) {
            var src, img_id;
            if (sd.get("background_image")) {
                src = READER_BACKGROUND_URL;
            } else {
                src = BLANK;
            }
            img_id = unique_id("bg-image");
            return ρσ_interpolate_kwargs.call(E, E.div, [E.div(ρσ_interpolate_kwargs.call(E, E.img, [ρσ_desugar_kwargs({src: src, id: img_id, class_: "bg-image-preview", style: "width: 75px; height: 75px; border: solid 1px"})])), ρσ_interpolate_kwargs.call(E, E.div, [" "].concat([ρσ_desugar_kwargs({style: "margin: 0.5rem"})])), ρσ_interpolate_kwargs.call(this, create_button, [_("Change image")].concat([ρσ_desugar_kwargs({action: change_background_image.bind(null, img_id)})])), ρσ_interpolate_kwargs.call(E, E.div, [" "].concat([ρσ_desugar_kwargs({style: "margin: 0.5rem"})])), ρσ_interpolate_kwargs.call(this, create_button, [_("Clear image")].concat([ρσ_desugar_kwargs({action: clear_image.bind(null, img_id)})]))].concat([ρσ_desugar_kwargs({style: "display: flex; align-items: center"})]));
        };
        if (!standalone_background_widget.__argnames__) Object.defineProperties(standalone_background_widget, {
            __argnames__ : {value: ["sd"]}
        });

        function background_widget(sd) {
            if (runtime.is_standalone_viewer) {
                return standalone_background_widget(sd);
            }
            return ρσ_interpolate_kwargs.call(E, E.div, [E.label(_("Image URL") + ": ", ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "url", name: "background_image", value: sd.get("background_image") || ""})]))].concat([ρσ_desugar_kwargs({style: "margin-bottom: 1ex"})]));
        };
        if (!background_widget.__argnames__) Object.defineProperties(background_widget, {
            __argnames__ : {value: ["sd"]}
        });

        function background_style_widget(sd) {
            var ans;
            ans = ρσ_interpolate_kwargs.call(E, E.div, [E.label(_("Background image style") + ": ", ρσ_interpolate_kwargs.call(E, E.select, [ρσ_interpolate_kwargs.call(E, E.option, [_("Scaled")].concat([ρσ_desugar_kwargs({value: "scaled"})])), ρσ_interpolate_kwargs.call(E, E.option, [_("Tiled")].concat([ρσ_desugar_kwargs({value: "tiled"})]))].concat([ρσ_desugar_kwargs({name: "background_image_style"})])))].concat([ρσ_desugar_kwargs({style: "margin-bottom: 1ex"})]));
            ans.querySelector("select").value = sd.get("background_image_style");
            return ans;
        };
        if (!background_style_widget.__argnames__) Object.defineProperties(background_style_widget, {
            __argnames__ : {value: ["sd"]}
        });

        function background_fade_widget(sd) {
            return E.div(E.label(_("Background image fade (%)") + ": ", ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({name: "background_image_fade", type: "number", max: "100", min: "0", step: "1", value: "" + sd.get("background_image_fade"), title: _("Fading of the background image is done by blending it with the background color")})])));
        };
        if (!background_fade_widget.__argnames__) Object.defineProperties(background_fade_widget, {
            __argnames__ : {value: ["sd"]}
        });

        function restore_defaults() {
            var container;
            container = document.getElementById(create_user_stylesheet_panel.container_id);
            container.querySelector("[name=user-stylesheet]").value = "";
            if (runtime.is_standalone_viewer) {
                clear_image(container.querySelector("img").id);
            } else {
                container.querySelector("[name=background_image]").value = "";
            }
            container.querySelector("select[name=background_image_style]").value = defaults.background_image_style;
            container.querySelector("input[name=background_image_fade]").value = str(defaults.background_image_fade);
        };

        function create_user_stylesheet_panel(container, apply_func, cancel_func) {
            var sd, val;
            sd = get_session_data();
            create_user_stylesheet_panel.container_id = ensure_id(container);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [_("Choose a background image to display behind the book text")].concat([ρσ_desugar_kwargs({style: "margin-bottom: 1.5ex"})])), background_widget(sd), background_style_widget(sd), background_fade_widget(sd)].concat([ρσ_desugar_kwargs({style: "border-bottom: solid 1px; margin-bottom: 1.5ex; padding-bottom: 1.5ex"})])), ρσ_interpolate_kwargs.call(E, E.div, [E.div(_("A CSS style sheet that can be used to control the look and feel of the text. For examples, click"), " ", ρσ_interpolate_kwargs.call(E, E.a, [_("here")].concat([ρσ_desugar_kwargs({class_: "blue-link", title: _("Examples of user style sheets"), target: (runtime.is_standalone_viewer) ? "_self" : "_blank", href: "https://www.mobileread.com/forums/showthread.php?t=51500"})]))), ρσ_interpolate_kwargs.call(E, E.textarea, [ρσ_desugar_kwargs({name: "user-stylesheet", style: "width: 100%; margin-top: 1ex; box-sizing: border-box; flex-grow: 10"})])].concat([ρσ_desugar_kwargs({style: "flex-grow: 10; display: flex; flex-flow: column"})]))].concat([ρσ_desugar_kwargs({style: "min-height: 75vh; display: flex; flex-flow: column; margin: 1ex 1rem; padding: 1ex 0"})])));
            val = sd.get("user_stylesheet");
            if (val) {
                container.querySelector("[name=user-stylesheet]").value = val;
            }
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [create_button_box(restore_defaults, apply_func, cancel_func)].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
        };
        if (!create_user_stylesheet_panel.__argnames__) Object.defineProperties(create_user_stylesheet_panel, {
            __argnames__ : {value: ["container", "apply_func", "cancel_func"]}
        });

        develop = create_user_stylesheet_panel;
        function commit_user_stylesheet(onchange, container) {
            var sd, ta, val, old, changed, bg_image, bis, bif;
            sd = get_session_data();
            ta = container.querySelector("[name=user-stylesheet]");
            val = ta.value || "";
            old = sd.get("user_stylesheet");
            changed = false;
            if (old !== val) {
                sd.set("user_stylesheet", val);
                changed = true;
            }
            if (runtime.is_standalone_viewer) {
                bg_image = container.querySelector("img.bg-image-preview").src;
                if (bg_image === BLANK) {
                    bg_image = null;
                }
            } else {
                bg_image = container.querySelector("input[name=background_image]").value;
            }
            old = sd.get("background_image");
            if (old !== bg_image) {
                sd.set("background_image", bg_image);
                changed = true;
            }
            old = sd.get("background_image_style");
            bis = container.querySelector("select[name=background_image_style]").value;
            if (bis !== old) {
                changed = true;
                sd.set("background_image_style", bis);
            }
            old = int(sd.get("background_image_fade"));
            bif = int(container.querySelector("input[name=background_image_fade]").value);
            if (old !== bif) {
                changed = true;
                sd.set("background_image_fade", bif);
            }
            if (changed) {
                onchange();
            }
        };
        if (!commit_user_stylesheet.__argnames__) Object.defineProperties(commit_user_stylesheet, {
            __argnames__ : {value: ["onchange", "container"]}
        });

        ρσ_modules["read_book.prefs.user_stylesheet"].BLANK = BLANK;
        ρσ_modules["read_book.prefs.user_stylesheet"].develop = develop;
        ρσ_modules["read_book.prefs.user_stylesheet"].change_background_image = change_background_image;
        ρσ_modules["read_book.prefs.user_stylesheet"].clear_image = clear_image;
        ρσ_modules["read_book.prefs.user_stylesheet"].standalone_background_widget = standalone_background_widget;
        ρσ_modules["read_book.prefs.user_stylesheet"].background_widget = background_widget;
        ρσ_modules["read_book.prefs.user_stylesheet"].background_style_widget = background_style_widget;
        ρσ_modules["read_book.prefs.user_stylesheet"].background_fade_widget = background_fade_widget;
        ρσ_modules["read_book.prefs.user_stylesheet"].restore_defaults = restore_defaults;
        ρσ_modules["read_book.prefs.user_stylesheet"].create_user_stylesheet_panel = create_user_stylesheet_panel;
        ρσ_modules["read_book.prefs.user_stylesheet"].commit_user_stylesheet = commit_user_stylesheet;
    })();

    (function(){
        var __name__ = "read_book.prefs.main";
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var build_list = ρσ_modules["book_list.item_list"].build_list;
        var create_item = ρσ_modules["book_list.item_list"].create_item;

        var clear = ρσ_modules.dom.clear;
        var ensure_id = ρσ_modules.dom.ensure_id;
        var svgicon = ρσ_modules.dom.svgicon;

        var runtime = ρσ_modules["read_book.globals"].runtime;

        var commit_colors = ρσ_modules["read_book.prefs.colors"].commit_colors;
        var create_colors_panel = ρσ_modules["read_book.prefs.colors"].create_colors_panel;

        var commit_fonts = ρσ_modules["read_book.prefs.fonts"].commit_fonts;
        var create_fonts_panel = ρσ_modules["read_book.prefs.fonts"].create_fonts_panel;

        var commit_head_foot = ρσ_modules["read_book.prefs.head_foot"].commit_head_foot;
        var create_head_foot_panel = ρσ_modules["read_book.prefs.head_foot"].create_head_foot_panel;

        var commit_keyboard = ρσ_modules["read_book.prefs.keyboard"].commit_keyboard;
        var create_keyboard_panel = ρσ_modules["read_book.prefs.keyboard"].create_keyboard_panel;

        var commit_scrolling = ρσ_modules["read_book.prefs.scrolling"].commit_scrolling;
        var create_scrolling_panel = ρσ_modules["read_book.prefs.scrolling"].create_scrolling_panel;

        var commit_layout = ρσ_modules["read_book.prefs.layout"].commit_layout;
        var create_layout_panel = ρσ_modules["read_book.prefs.layout"].create_layout_panel;

        var commit_misc = ρσ_modules["read_book.prefs.misc"].commit_misc;
        var create_misc_panel = ρσ_modules["read_book.prefs.misc"].create_misc_panel;

        var commit_user_stylesheet = ρσ_modules["read_book.prefs.user_stylesheet"].commit_user_stylesheet;
        var create_user_stylesheet_panel = ρσ_modules["read_book.prefs.user_stylesheet"].create_user_stylesheet_panel;

        function Prefs() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            Prefs.prototype.__bind_methods__.call(this);
            Prefs.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(Prefs.prototype, "__bind_methods__", {value: function () {
            this.onchange = Prefs.prototype.onchange.bind(this);
            this.cancel = Prefs.prototype.cancel.bind(this);
            this.onclose = Prefs.prototype.onclose.bind(this);
            this.create_panel = Prefs.prototype.create_panel.bind(this);
            this.display_panel = Prefs.prototype.display_panel.bind(this);
            this.show_panel = Prefs.prototype.show_panel.bind(this);
            this.display_top = Prefs.prototype.display_top.bind(this);
            this.display_fonts = Prefs.prototype.display_fonts.bind(this);
            this.close_fonts = Prefs.prototype.close_fonts.bind(this);
            this.display_misc = Prefs.prototype.display_misc.bind(this);
            this.close_misc = Prefs.prototype.close_misc.bind(this);
            this.display_colors = Prefs.prototype.display_colors.bind(this);
            this.close_colors = Prefs.prototype.close_colors.bind(this);
            this.display_layout = Prefs.prototype.display_layout.bind(this);
            this.close_layout = Prefs.prototype.close_layout.bind(this);
            this.display_user_stylesheet = Prefs.prototype.display_user_stylesheet.bind(this);
            this.close_user_stylesheet = Prefs.prototype.close_user_stylesheet.bind(this);
            this.display_head_foot = Prefs.prototype.display_head_foot.bind(this);
            this.close_head_foot = Prefs.prototype.close_head_foot.bind(this);
            this.display_keyboard = Prefs.prototype.display_keyboard.bind(this);
            this.close_keyboard = Prefs.prototype.close_keyboard.bind(this);
            this.display_scrolling = Prefs.prototype.display_scrolling.bind(this);
            this.close_scrolling = Prefs.prototype.close_scrolling.bind(this);
        }});
        Object.defineProperties(Prefs.prototype,  {
            "container": {
                "enumerable": true, 
                "get": function container() {
                    var self = this;
                    return document.getElementById(self.container_id);
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        Prefs.prototype.__init__ = function __init__(container, close_func, on_change) {
            var self = this;
            var title;
            self.close_func = close_func;
            self.on_change = on_change;
            title = E.h2();
            self.title_id = ensure_id(title);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [title, ρσ_interpolate_kwargs.call(E, E.div, [svgicon("close")].concat([ρσ_desugar_kwargs({onclick: self.onclose, style: "cursor:pointer"})]))].concat([ρσ_desugar_kwargs({style: "display: flex; justify-content: space-between; padding: 1ex 1em; border-bottom: solid 1px currentColor"})])));
            container.appendChild(E.div());
            self.container_id = ensure_id(container.lastChild);
            self.stack = ["top"];
            self.display_top(container.lastChild);
        };
        if (!Prefs.prototype.__init__.__argnames__) Object.defineProperties(Prefs.prototype.__init__, {
            __argnames__ : {value: ["container", "close_func", "on_change"]}
        });
        Prefs.__argnames__ = Prefs.prototype.__init__.__argnames__;
        Prefs.__handles_kwarg_interpolation__ = Prefs.prototype.__init__.__handles_kwarg_interpolation__;
        Prefs.prototype.onchange = function onchange() {
            var self = this;
            self.on_change();
        };
        Prefs.prototype.cancel = function cancel() {
            var self = this;
            if (self.stack.length > 1) {
                self.stack.pop();
                self.display_panel((ρσ_expr_temp = self.stack)[ρσ_expr_temp.length-1]);
            }
        };
        Prefs.prototype.onclose = function onclose() {
            var self = this;
            var which, close_func;
            if (self.stack.length > 1) {
                which = self.stack.pop();
                close_func = getattr(self, "close_" + which, null);
                if (close_func) {
                    close_func.bind(self)();
                }
                self.display_panel((ρσ_expr_temp = self.stack)[ρσ_expr_temp.length-1]);
            } else {
                self.close_func();
            }
        };
        Prefs.prototype.create_panel = function create_panel(container, which, create_func) {
            var self = this;
            document.getElementById(self.title_id).textContent = (ρσ_expr_temp = self.title_map)[(typeof which === "number" && which < 0) ? ρσ_expr_temp.length + which : which] || which;
            create_func(container, self.onclose, self.cancel);
        };
        if (!Prefs.prototype.create_panel.__argnames__) Object.defineProperties(Prefs.prototype.create_panel, {
            __argnames__ : {value: ["container", "which", "create_func"]}
        });
        Prefs.prototype.display_panel = function display_panel(which) {
            var self = this;
            var container;
            container = self.container;
            clear(container);
            getattr(self, "display_" + which)(container);
        };
        if (!Prefs.prototype.display_panel.__argnames__) Object.defineProperties(Prefs.prototype.display_panel, {
            __argnames__ : {value: ["which"]}
        });
        Prefs.prototype.show_panel = function show_panel(which) {
            var self = this;
            self.stack.push(which);
            self.display_panel(which);
        };
        if (!Prefs.prototype.show_panel.__argnames__) Object.defineProperties(Prefs.prototype.show_panel, {
            __argnames__ : {value: ["which"]}
        });
        Prefs.prototype.display_top = function display_top(container) {
            var self = this;
            var c, items;
            document.getElementById(self.title_id).textContent = _("Configure book reader");
            c = E.div();
            container.appendChild(c);
            self.title_map = Object.create(null);
            items = ρσ_list_decorate([]);
            function ci(title, which, subtitle) {
                items.push(create_item(title, self.show_panel.bind(null, which), subtitle));
                (ρσ_expr_temp = self.title_map)[(typeof which === "number" && which < 0) ? ρσ_expr_temp.length + which : which] = title;
            };
            if (!ci.__argnames__) Object.defineProperties(ci, {
                __argnames__ : {value: ["title", "which", "subtitle"]}
            });

            ci(_("Colors"), "colors", _("Colors of the page and text"));
            ci(_("Page layout"), "layout", _("Page margins and number of pages per screen"));
            ci(_("Styles"), "user_stylesheet", _("Style rules for text and background image"));
            ci(_("Headers and footers"), "head_foot", _("Customize the headers and footers"));
            ci(_("Scrolling behavior"), "scrolling", _("Control how the viewer scrolls"));
            ci(_("Keyboard shortcuts"), "keyboard", _("Customize the keyboard shortcuts"));
            if (runtime.is_standalone_viewer) {
                ci(_("Fonts"), "fonts", _("Font choices"));
                ci(_("Miscellaneous"), "misc", _("Window size, last read position, etc."));
            }
            build_list(c, items);
        };
        if (!Prefs.prototype.display_top.__argnames__) Object.defineProperties(Prefs.prototype.display_top, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.display_fonts = function display_fonts(container) {
            var self = this;
            self.create_panel(container, "fonts", create_fonts_panel);
        };
        if (!Prefs.prototype.display_fonts.__argnames__) Object.defineProperties(Prefs.prototype.display_fonts, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.close_fonts = function close_fonts() {
            var self = this;
            commit_fonts(self.onchange, self.container);
        };
        Prefs.prototype.display_misc = function display_misc(container) {
            var self = this;
            self.create_panel(container, "misc", create_misc_panel);
        };
        if (!Prefs.prototype.display_misc.__argnames__) Object.defineProperties(Prefs.prototype.display_misc, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.close_misc = function close_misc() {
            var self = this;
            commit_misc(self.onchange, self.container);
        };
        Prefs.prototype.display_colors = function display_colors(container) {
            var self = this;
            self.create_panel(container, "colors", create_colors_panel);
        };
        if (!Prefs.prototype.display_colors.__argnames__) Object.defineProperties(Prefs.prototype.display_colors, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.close_colors = function close_colors() {
            var self = this;
            commit_colors(self.onchange, self.container);
        };
        Prefs.prototype.display_layout = function display_layout(container) {
            var self = this;
            self.create_panel(container, "layout", create_layout_panel);
        };
        if (!Prefs.prototype.display_layout.__argnames__) Object.defineProperties(Prefs.prototype.display_layout, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.close_layout = function close_layout() {
            var self = this;
            commit_layout(self.onchange, self.container);
        };
        Prefs.prototype.display_user_stylesheet = function display_user_stylesheet(container) {
            var self = this;
            self.create_panel(container, "user_stylesheet", create_user_stylesheet_panel);
        };
        if (!Prefs.prototype.display_user_stylesheet.__argnames__) Object.defineProperties(Prefs.prototype.display_user_stylesheet, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.close_user_stylesheet = function close_user_stylesheet() {
            var self = this;
            commit_user_stylesheet(self.onchange, self.container);
        };
        Prefs.prototype.display_head_foot = function display_head_foot(container) {
            var self = this;
            self.create_panel(container, "head_foot", create_head_foot_panel);
        };
        if (!Prefs.prototype.display_head_foot.__argnames__) Object.defineProperties(Prefs.prototype.display_head_foot, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.close_head_foot = function close_head_foot() {
            var self = this;
            commit_head_foot(self.onchange, self.container);
        };
        Prefs.prototype.display_keyboard = function display_keyboard(container) {
            var self = this;
            self.create_panel(container, "keyboard", create_keyboard_panel);
        };
        if (!Prefs.prototype.display_keyboard.__argnames__) Object.defineProperties(Prefs.prototype.display_keyboard, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.close_keyboard = function close_keyboard() {
            var self = this;
            commit_keyboard(self.onchange, self.container);
        };
        Prefs.prototype.display_scrolling = function display_scrolling(container) {
            var self = this;
            self.create_panel(container, "scrolling", create_scrolling_panel);
        };
        if (!Prefs.prototype.display_scrolling.__argnames__) Object.defineProperties(Prefs.prototype.display_scrolling, {
            __argnames__ : {value: ["container"]}
        });
        Prefs.prototype.close_scrolling = function close_scrolling() {
            var self = this;
            commit_scrolling(self.onchange, self.container);
        };
        Prefs.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        Prefs.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(Prefs.prototype, "__bases__", {value: []});
        

        function create_prefs_panel(container, close_func, on_change) {
            return new Prefs(container, close_func, on_change);
        };
        if (!create_prefs_panel.__argnames__) Object.defineProperties(create_prefs_panel, {
            __argnames__ : {value: ["container", "close_func", "on_change"]}
        });

        ρσ_modules["read_book.prefs.main"].Prefs = Prefs;
        ρσ_modules["read_book.prefs.main"].create_prefs_panel = create_prefs_panel;
    })();

    (function(){
        var __name__ = "read_book.word_actions";
        var current_data;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var create_item = ρσ_modules["book_list.item_list"].create_item;
        var create_item_list = ρσ_modules["book_list.item_list"].create_item_list;

        var clear = ρσ_modules.dom.clear;
        var ensure_id = ρσ_modules.dom.ensure_id;

        var error_dialog = ρσ_modules.modals.error_dialog;

        var create_button = ρσ_modules.widgets.create_button;

        function lookup(close_panel_func, url) {
            close_panel_func();
            window.open(url, "_blank");
        };
        if (!lookup.__argnames__) Object.defineProperties(lookup, {
            __argnames__ : {value: ["close_panel_func", "url"]}
        });

        function toggle_custom_container(container_id, visible) {
            var container, c, list_container;
            container = document.getElementById(container_id);
            if (container) {
                c = container.lastChild;
                list_container = c.previousSibling;
                list_container.style.display = (visible) ? "none" : "block";
                c.style.display = (visible) ? "block" : "none";
                return c;
            }
        };
        if (!toggle_custom_container.__argnames__) Object.defineProperties(toggle_custom_container, {
            __argnames__ : {value: ["container_id", "visible"]}
        });

        function add(container_id) {
            var container, c, name, url, sd, actions;
            container = document.getElementById(container_id);
            if (!container) {
                return;
            }
            c = container.lastChild;
            name = c.querySelector("input[name=\"name\"]").value;
            url = c.querySelector("input[name=\"url\"]").value;
            if (!name || !url) {
                error_dialog(_("Required fields missing"), _("You must specify both a name and a URL."));
                return;
            }
            sd = get_session_data();
            actions = sd.get("word_actions", []);
            actions.push((function(){
                var ρσ_d = Object.create(null);
                ρσ_d["title"] = name;
                ρσ_d["url"] = url;
                return ρσ_d;
            }).call(this));
            sd.set("word_actions", actions);
            toggle_custom_container(container_id, false);
            populate_list(container);
        };
        if (!add.__argnames__) Object.defineProperties(add, {
            __argnames__ : {value: ["container_id"]}
        });

        function add_custom(container_id) {
            var container, do_add;
            container = toggle_custom_container(container_id, true);
            if (!container) {
                return;
            }
            clear(container);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Enter the name and URL for a custom lookup source. The URL must contain  {0} in it, which will be replaced by the word being looked up. For example:  {1}").format("{word}", "https://google.com/search?q={word}")].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
            do_add = add.bind(null, container_id);
            container.appendChild(E.form(ρσ_interpolate_kwargs.call(E, E.button, [ρσ_desugar_kwargs({style: "display:none", onclick: do_add})]), ρσ_interpolate_kwargs.call(E, E.table, [E.tr(E.td(_("Name:") + " "), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "text", name: "name"})]))), E.tr(E.td(" "), E.td(" ")), E.tr(E.td(_("URL:") + " "), E.td(ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({type: "url", name: "url"})])))].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})]))));
            container.append(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(this, create_button, [_("Add"), "plus", add.bind(null, container_id)].concat([ρσ_desugar_kwargs({highlight: true})])), " ", create_button(_("Cancel"), toggle_custom_container.bind(null, container_id, false))].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
            container.querySelector("input").focus();
        };
        if (!add_custom.__argnames__) Object.defineProperties(add_custom, {
            __argnames__ : {value: ["container_id"]}
        });

        function remove(container_id, num) {
            var container, sd, actions;
            container = document.getElementById(container_id);
            if (!container) {
                return;
            }
            sd = get_session_data();
            actions = sd.get("word_actions", []);
            actions.splice(num, 1);
            sd.set("word_actions", actions);
            toggle_custom_container(container_id, false);
            populate_list(container);
        };
        if (!remove.__argnames__) Object.defineProperties(remove, {
            __argnames__ : {value: ["container_id", "num"]}
        });

        function remove_custom(container_id) {
            var container, items, sd, actions, ρσ_unpack, i, item;
            container = toggle_custom_container(container_id, true);
            if (!container) {
                return;
            }
            clear(container);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Choose a custom lookup to remove")].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
            items = ρσ_list_decorate([ create_item(_("Cancel (no removals)"), toggle_custom_container.bind(null, container_id, false)) ]);
            sd = get_session_data();
            actions = sd.get("word_actions", []);
            var ρσ_Iter0 = ρσ_Iterable(enumerate(actions));
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                ρσ_unpack = ρσ_Iter0[ρσ_Index0];
                i = ρσ_unpack[0];
                item = ρσ_unpack[1];
                items.push(create_item(item.title, remove.bind(null, container_id, i)));
            }
            container.appendChild(E.div());
            create_item_list(container.lastChild, items);
        };
        if (!remove_custom.__argnames__) Object.defineProperties(remove_custom, {
            __argnames__ : {value: ["container_id"]}
        });

        function lookup_items(word, close_panel_func, container_id) {
            var eword, items, custom_actions, has_custom, entry;
            eword = encodeURIComponent(word);
            items = ρσ_list_decorate([]);
            function a(title, url) {
                items.push(create_item(title, lookup.bind(word, close_panel_func, ρσ_interpolate_kwargs.call(url, url.format, [ρσ_desugar_kwargs({word: eword})]))));
            };
            if (!a.__argnames__) Object.defineProperties(a, {
                __argnames__ : {value: ["title", "url"]}
            });

            custom_actions = get_session_data().get("word_actions", []);
            has_custom = custom_actions && custom_actions.length;
            if (has_custom) {
                var ρσ_Iter1 = ρσ_Iterable(custom_actions);
                for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                    entry = ρσ_Iter1[ρσ_Index1];
                    if (entry.title && entry.url) {
                        a(entry.title, entry.url);
                    }
                }
            }
            a(_("Google dictionary"), "https://google.com/search?q=define:{word}");
            a(_("Wordnik"), "https://www.wordnik.com/words/{word}");
            a(_("Search the internet"), "https://google.com/search?q={word}");
            items.push(create_item(_("Add a custom lookup"), add_custom.bind(null, container_id)));
            if (has_custom) {
                items.push(create_item(_("Remove a custom lookup"), remove_custom.bind(null, container_id)));
            }
            return items;
        };
        if (!lookup_items.__argnames__) Object.defineProperties(lookup_items, {
            __argnames__ : {value: ["word", "close_panel_func", "container_id"]}
        });

        current_data = null;
        function populate_list(container) {
            var ρσ_unpack, word, close_panel_func, list_container;
            ρσ_unpack = current_data;
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            word = ρσ_unpack[0];
            close_panel_func = ρσ_unpack[1];
            list_container = container.lastChild.previousSibling;
            clear(list_container);
            create_item_list(list_container, lookup_items(word, close_panel_func, ensure_id(container)));
        };
        if (!populate_list.__argnames__) Object.defineProperties(populate_list, {
            __argnames__ : {value: ["container"]}
        });

        function create_word_actions_panel(container, word, close_panel_func) {
            word = str.replace(word, "\u00ad", "");
            current_data = [word, close_panel_func];
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "display:none"})]));
            populate_list(container);
        };
        if (!create_word_actions_panel.__argnames__) Object.defineProperties(create_word_actions_panel, {
            __argnames__ : {value: ["container", "word", "close_panel_func"]}
        });

        function develop(container) {
            container.appendChild(E.div());
            create_word_actions_panel(container, "develop", function () {
            });
        };
        if (!develop.__argnames__) Object.defineProperties(develop, {
            __argnames__ : {value: ["container"]}
        });

        ρσ_modules["read_book.word_actions"].current_data = current_data;
        ρσ_modules["read_book.word_actions"].lookup = lookup;
        ρσ_modules["read_book.word_actions"].toggle_custom_container = toggle_custom_container;
        ρσ_modules["read_book.word_actions"].add = add;
        ρσ_modules["read_book.word_actions"].add_custom = add_custom;
        ρσ_modules["read_book.word_actions"].remove = remove;
        ρσ_modules["read_book.word_actions"].remove_custom = remove_custom;
        ρσ_modules["read_book.word_actions"].lookup_items = lookup_items;
        ρσ_modules["read_book.word_actions"].populate_list = populate_list;
        ρσ_modules["read_book.word_actions"].create_word_actions_panel = create_word_actions_panel;
        ρσ_modules["read_book.word_actions"].develop = develop;
    })();

    (function(){
        var __name__ = "read_book.overlay";
        var MAIN_OVERLAY_TS_CLASS, MAIN_OVERLAY_ACTIONS_CLASS;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var BD_CLASS_NAME = ρσ_modules["book_list.book_details"].CLASS_NAME;
        var render_metadata = ρσ_modules["book_list.book_details"].render_metadata;

        var sync_library_books = ρσ_modules["book_list.library_data"].sync_library_books;

        var home = ρσ_modules["book_list.router"].home;

        var get_color = ρσ_modules["book_list.theme"].get_color;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var clear = ρσ_modules.dom.clear;
        var set_css = ρσ_modules.dom.set_css;
        var svgicon = ρσ_modules.dom.svgicon;
        var unique_id = ρσ_modules.dom.unique_id;

        var error_dialog = ρσ_modules.modals.error_dialog;

        var runtime = ρσ_modules["read_book.globals"].runtime;
        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var create_goto_panel = ρσ_modules["read_book.goto"].create_goto_panel;
        var create_location_overlay = ρσ_modules["read_book.goto"].create_location_overlay;

        var create_open_book = ρσ_modules["read_book.open_book"].create_open_book;

        var create_font_size_panel = ρσ_modules["read_book.prefs.font_size"].create_font_size_panel;

        var create_prefs_panel = ρσ_modules["read_book.prefs.main"].create_prefs_panel;

        var create_toc_panel = ρσ_modules["read_book.toc"].create_toc_panel;

        var create_word_actions_panel = ρσ_modules["read_book.word_actions"].create_word_actions_panel;

        var get_device_uuid = ρσ_modules.session.get_device_uuid;

        var full_screen_element = ρσ_modules.utils.full_screen_element;
        var is_ios = ρσ_modules.utils.is_ios;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;

        var create_button = ρσ_modules.widgets.create_button;
        var create_spinner = ρσ_modules.widgets.create_spinner;

        function LoadingMessage() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            LoadingMessage.prototype.__bind_methods__.call(this);
            LoadingMessage.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(LoadingMessage.prototype, "__bind_methods__", {value: function () {
            this.show = LoadingMessage.prototype.show.bind(this);
            this.set_msg = LoadingMessage.prototype.set_msg.bind(this);
            this.on_container_click = LoadingMessage.prototype.on_container_click.bind(this);
        }});
        LoadingMessage.prototype.__init__ = function __init__(msg, current_color_scheme) {
            var self = this;
            self.msg = msg || "";
            self.current_color_scheme = current_color_scheme;
            self.is_not_escapable = true;
        };
        if (!LoadingMessage.prototype.__init__.__argnames__) Object.defineProperties(LoadingMessage.prototype.__init__, {
            __argnames__ : {value: ["msg", "current_color_scheme"]}
        });
        LoadingMessage.__argnames__ = LoadingMessage.prototype.__init__.__argnames__;
        LoadingMessage.__handles_kwarg_interpolation__ = LoadingMessage.prototype.__init__.__handles_kwarg_interpolation__;
        LoadingMessage.prototype.show = function show(container) {
            var self = this;
            self.container_id = container.getAttribute("id");
            container.style.backgroundColor = self.current_color_scheme.background;
            container.style.color = self.current_color_scheme.foreground;
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.div(create_spinner("100px", "100px")), E.h2()].concat([ρσ_desugar_kwargs({style: "text-align:center"})])));
            safe_set_inner_html(container.firstChild.lastChild, self.msg);
            ρσ_interpolate_kwargs.call(this, set_css, [container.firstChild].concat([ρσ_desugar_kwargs({position: "relative", top: "50%", transform: "translateY(-50%)"})]));
        };
        if (!LoadingMessage.prototype.show.__argnames__) Object.defineProperties(LoadingMessage.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        LoadingMessage.prototype.set_msg = function set_msg(msg) {
            var self = this;
            var container;
            self.msg = msg;
            container = document.getElementById(self.container_id);
            safe_set_inner_html(container.firstChild.lastChild, self.msg);
        };
        if (!LoadingMessage.prototype.set_msg.__argnames__) Object.defineProperties(LoadingMessage.prototype.set_msg, {
            __argnames__ : {value: ["msg"]}
        });
        LoadingMessage.prototype.on_container_click = function on_container_click(evt) {
            var self = this;
        };
        if (!LoadingMessage.prototype.on_container_click.__argnames__) Object.defineProperties(LoadingMessage.prototype.on_container_click, {
            __argnames__ : {value: ["evt"]}
        });
        LoadingMessage.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        LoadingMessage.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(LoadingMessage.prototype, "__bases__", {value: []});

        function DeleteBook() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            DeleteBook.prototype.__bind_methods__.call(this);
            DeleteBook.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(DeleteBook.prototype, "__bind_methods__", {value: function () {
            this.show = DeleteBook.prototype.show.bind(this);
            this.show_working = DeleteBook.prototype.show_working.bind(this);
            this.on_container_click = DeleteBook.prototype.on_container_click.bind(this);
            this.delete_book = DeleteBook.prototype.delete_book.bind(this);
            this.cancel = DeleteBook.prototype.cancel.bind(this);
        }});
        DeleteBook.prototype.__init__ = function __init__(overlay, question, ok_icon, ok_text, reload_book) {
            var self = this;
            self.overlay = overlay;
            self.question = question || _("Are you sure you want to remove this book from local storage? You will have to re-download it from calibre if you want to read it again.");
            self.ok_icon = ok_icon || "trash";
            self.ok_text = ok_text || _("Delete book");
            self.reload_book = reload_book;
        };
        if (!DeleteBook.prototype.__init__.__argnames__) Object.defineProperties(DeleteBook.prototype.__init__, {
            __argnames__ : {value: ["overlay", "question", "ok_icon", "ok_text", "reload_book"]}
        });
        DeleteBook.__argnames__ = DeleteBook.prototype.__init__.__argnames__;
        DeleteBook.__handles_kwarg_interpolation__ = DeleteBook.prototype.__init__.__handles_kwarg_interpolation__;
        DeleteBook.prototype.show = function show(container) {
            var self = this;
            self.container_id = container.getAttribute("id");
            ρσ_interpolate_kwargs.call(this, set_css, [container].concat([ρσ_desugar_kwargs({display: "flex", justify_content: "center", flex_direction: "column", background_color: get_color("window-background")})]));
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.h2(self.question), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(this, create_button, [self.ok_text, self.ok_icon].concat([ρσ_desugar_kwargs({action: self.delete_book, highlight: true})])), E.span(" "), ρσ_interpolate_kwargs.call(this, create_button, [_("Cancel")].concat([ρσ_desugar_kwargs({action: self.cancel})]))].concat([ρσ_desugar_kwargs({style: "display:flex; justify-content:flex-end"})]))].concat([ρσ_desugar_kwargs({style: "margin:1ex 1em"})])));
        };
        if (!DeleteBook.prototype.show.__argnames__) Object.defineProperties(DeleteBook.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        DeleteBook.prototype.show_working = function show_working() {
            var self = this;
            var container;
            container = document.getElementById(self.container_id);
            clear(container);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.div(create_spinner("100px", "100px")), E.h2()].concat([ρσ_desugar_kwargs({style: "text-align:center"})])));
            safe_set_inner_html(container.lastChild.lastChild, _("Deleting local book copy, please wait..."));
        };
        DeleteBook.prototype.on_container_click = function on_container_click(evt) {
            var self = this;
        };
        if (!DeleteBook.prototype.on_container_click.__argnames__) Object.defineProperties(DeleteBook.prototype.on_container_click, {
            __argnames__ : {value: ["evt"]}
        });
        DeleteBook.prototype.delete_book = function delete_book() {
            var self = this;
            var view;
            if (runtime.is_standalone_viewer) {
                if (self.reload_book) {
                    ui_operations.reload_book();
                }
                return;
            }
            self.show_working();
            view = self.overlay.view;
            ui_operations.delete_book(view.book, (function() {
                var ρσ_anonfunc = function (book, errmsg) {
                    self.overlay.hide_current_panel();
                    if (errmsg) {
                        view.ui.show_error(_("Failed to delete book"), _("Failed to delete book from local storage, click \"Show details\" for more information."), errmsg);
                    } else {
                        if (self.reload_book) {
                            ui_operations.reload_book();
                        } else {
                            home();
                        }
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["book", "errmsg"]}
                });
                return ρσ_anonfunc;
            })());
        };
        DeleteBook.prototype.cancel = function cancel() {
            var self = this;
            self.overlay.hide_current_panel();
        };
        DeleteBook.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        DeleteBook.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(DeleteBook.prototype, "__bases__", {value: []});

        function SyncBook() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            SyncBook.prototype.__bind_methods__.call(this);
            SyncBook.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(SyncBook.prototype, "__bind_methods__", {value: function () {
            this.show = SyncBook.prototype.show.bind(this);
            this.on_container_click = SyncBook.prototype.on_container_click.bind(this);
            this.cancel = SyncBook.prototype.cancel.bind(this);
            this.sync_data_received = SyncBook.prototype.sync_data_received.bind(this);
        }});
        SyncBook.prototype.__init__ = function __init__(overlay) {
            var self = this;
            self.overlay = overlay;
            self.canceled = false;
        };
        if (!SyncBook.prototype.__init__.__argnames__) Object.defineProperties(SyncBook.prototype.__init__, {
            __argnames__ : {value: ["overlay"]}
        });
        SyncBook.__argnames__ = SyncBook.prototype.__init__.__argnames__;
        SyncBook.__handles_kwarg_interpolation__ = SyncBook.prototype.__init__.__handles_kwarg_interpolation__;
        SyncBook.prototype.show = function show(container) {
            var self = this;
            var book, to_sync;
            self.container_id = container.getAttribute("id");
            ρσ_interpolate_kwargs.call(this, set_css, [container].concat([ρσ_desugar_kwargs({display: "flex", justify_content: "center", flex_direction: "column", background_color: get_color("window-background")})]));
            book = self.overlay.view.book;
            to_sync = [[book.key, new Date(0)]];
            sync_library_books(book.key[0], to_sync, self.sync_data_received);
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.h2(_("Syncing to last read position")), E.p(_("Downloading last read data from server, please wait...")), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(this, create_button, [_("Cancel")].concat([ρσ_desugar_kwargs({action: self.cancel})]))].concat([ρσ_desugar_kwargs({style: "display:flex; justify-content:flex-end"})]))].concat([ρσ_desugar_kwargs({style: "margin:1ex 1em"})])));
        };
        if (!SyncBook.prototype.show.__argnames__) Object.defineProperties(SyncBook.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        SyncBook.prototype.on_container_click = function on_container_click(evt) {
            var self = this;
        };
        if (!SyncBook.prototype.on_container_click.__argnames__) Object.defineProperties(SyncBook.prototype.on_container_click, {
            __argnames__ : {value: ["evt"]}
        });
        SyncBook.prototype.cancel = function cancel() {
            var self = this;
            self.canceled = true;
            self.overlay.hide_current_panel();
        };
        SyncBook.prototype.sync_data_received = function sync_data_received(library_id, lrmap, load_type, xhr, ev) {
            var self = this;
            var data, book, dev, epoch, ans, ρσ_unpack, book_id, fmt, last_read_positions, d, key, cfi;
            if (self.canceled) {
                return;
            }
            self.overlay.hide();
            if (load_type !== "load") {
                if (xhr.responseText === "login required for sync") {
                    error_dialog(_("Failed to fetch sync data"), _("You must setup user accounts and login to use the sync functionality"));
                } else {
                    error_dialog(_("Failed to fetch sync data"), _("Failed to download last read data from server, click \"Show details\" for more information."), xhr.error_html);
                }
                return;
            }
            data = JSON.parse(xhr.responseText);
            book = self.overlay.view.book;
            dev = get_device_uuid();
            epoch = 0;
            ans = null;
            var ρσ_Iter0 = ρσ_Iterable(data);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                key = ρσ_Iter0[ρσ_Index0];
                ρσ_unpack = ρσ_eslice(key.partition(":"), 2);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                book_id = ρσ_unpack[0];
                fmt = ρσ_unpack[1];
                if (book_id === str(book.key[1]) && fmt.upper() === book.key[2].upper()) {
                    last_read_positions = data[(typeof key === "number" && key < 0) ? data.length + key : key];
                    var ρσ_Iter1 = ρσ_Iterable(last_read_positions);
                    for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                        d = ρσ_Iter1[ρσ_Index1];
                        if (d.device !== dev && d.epoch > epoch) {
                            epoch = d.epoch;
                            ans = d;
                        }
                    }
                }
            }
            if (ans !== null) {
                cfi = ans.cfi;
                if (cfi) {
                    self.overlay.view.goto_bookpos(cfi);
                }
            }
        };
        if (!SyncBook.prototype.sync_data_received.__argnames__) Object.defineProperties(SyncBook.prototype.sync_data_received, {
            __argnames__ : {value: ["library_id", "lrmap", "load_type", "xhr", "ev"]}
        });
        SyncBook.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        SyncBook.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(SyncBook.prototype, "__bases__", {value: []});

        MAIN_OVERLAY_TS_CLASS = "read-book-main-overlay-top-section";
        MAIN_OVERLAY_ACTIONS_CLASS = "read-book-main-overlay-actions";
        add_extra_css(function () {
            var style, sel;
            style = "";
            sel = "." + MAIN_OVERLAY_TS_CLASS + " > ." + MAIN_OVERLAY_ACTIONS_CLASS + " ";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({overflow: "hidden"})]));
            sel += "> ul ";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({display: "flex", flex_wrap: "wrap", list_style: "none", border_bottom: "1px solid currentColor"})]));
            sel += "> li";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({border_right: "1px solid currentColor", padding: "0.5em 1ex", display: "flex", align_items: "center", cursor: "pointer"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ":last-child"].concat([ρσ_desugar_kwargs({border_right_style: "none"})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ":hover > *:first-child"].concat([ρσ_desugar_kwargs({color: get_color("window-hover-foreground")})]));
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ":active > *:first-child"].concat([ρσ_desugar_kwargs({transform: "scale(1.8)"})]));
            return style;
        });
        function simple_overlay_title(title, overlay, container) {
            container.style.backgroundColor = get_color("window-background");
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.h2(title), ρσ_interpolate_kwargs.call(E, E.div, [svgicon("close")].concat([ρσ_desugar_kwargs({style: "cursor:pointer", onclick: (function() {
                var ρσ_anonfunc = function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    overlay.hide_current_panel(event);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })(), class_: "simple-link"})]))].concat([ρσ_desugar_kwargs({style: "padding: 1ex 1em; border-bottom: solid 1px currentColor; display:flex; justify-content: space-between"})])));
        };
        if (!simple_overlay_title.__argnames__) Object.defineProperties(simple_overlay_title, {
            __argnames__ : {value: ["title", "overlay", "container"]}
        });

        function MainOverlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            MainOverlay.prototype.__bind_methods__.call(this);
            MainOverlay.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(MainOverlay.prototype, "__bind_methods__", {value: function () {
            this.show = MainOverlay.prototype.show.bind(this);
            this.update_time = MainOverlay.prototype.update_time.bind(this);
            this.on_hide = MainOverlay.prototype.on_hide.bind(this);
            this.back = MainOverlay.prototype.back.bind(this);
            this.forward = MainOverlay.prototype.forward.bind(this);
        }});
        MainOverlay.prototype.__init__ = function __init__(overlay, elements) {
            var self = this;
            self.overlay = overlay;
            self.elements = elements || Object.create(null);
            self.timer = null;
            self.timer_id = unique_id();
            if (ρσ_exists.d(window.Intl).DateTimeFormat) {
                self.date_formatter = window.Intl.DateTimeFormat(undefined, (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["hour"] = "numeric";
                    ρσ_d["minute"] = "numeric";
                    return ρσ_d;
                }).call(this));
            } else {
                self.date_formatter = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["format"] = (function() {
                        var ρσ_anonfunc = function (date) {
                            return "{}:{}".format(date.getHours(), date.getMinutes());
                        };
                        if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                            __argnames__ : {value: ["date"]}
                        });
                        return ρσ_anonfunc;
                    })();
                    return ρσ_d;
                }).call(this);
            }
        };
        if (!MainOverlay.prototype.__init__.__argnames__) Object.defineProperties(MainOverlay.prototype.__init__, {
            __argnames__ : {value: ["overlay", "elements"]}
        });
        MainOverlay.__argnames__ = MainOverlay.prototype.__init__.__argnames__;
        MainOverlay.__handles_kwarg_interpolation__ = MainOverlay.prototype.__init__.__handles_kwarg_interpolation__;
        MainOverlay.prototype.show = function show(container) {
            var self = this;
            var icon_size, sync_action, delete_action, reload_action, home_action, back_action, forward_action, reload_actions, nav_actions, bookmarks_action, toc_actions, actions_div, full_screen_actions, text, copy_actions;
            self.container_id = container.getAttribute("id");
            icon_size = "3.5ex";
            function ac(text, tooltip, action, icon, is_text_button) {
                if (is_text_button) {
                    icon = ρσ_interpolate_kwargs.call(E, E.span, [icon].concat([ρσ_desugar_kwargs({style: "font-size: 175%; font-weight: bold"})]));
                } else {
                    icon = (icon) ? svgicon(icon, icon_size, icon_size) : "";
                }
                return ρσ_interpolate_kwargs.call(E, E.li, [icon, " ", text].concat([ρσ_desugar_kwargs({onclick: action, title: tooltip})]));
            };
            if (!ac.__argnames__) Object.defineProperties(ac, {
                __argnames__ : {value: ["text", "tooltip", "action", "icon", "is_text_button"]}
            });

            sync_action = ac(_("Sync"), _("Get last read position and annotations from the server"), self.overlay.sync_book, "cloud-download");
            delete_action = ac(_("Delete"), _("Delete this book from the device"), self.overlay.delete_book, "trash");
            reload_action = ac(_("Reload"), _("Reload this book from the {}").format((runtime.is_standalone_viewer) ? _("computer") : _("server")), self.overlay.reload_book, "refresh");
            home_action = ac(_("Home"), _("Return to list of books"), function () {
                home();
            }, "home");
            back_action = ac(_("Back"), null, self.back, "arrow-left");
            forward_action = ac(_("Forward"), null, self.forward, "arrow-right");
            if (runtime.is_standalone_viewer) {
                reload_actions = E.ul(ac(_("Open book"), _("Open a new book"), self.overlay.open_book, "book"), reload_action);
                nav_actions = E.ul(back_action, forward_action);
            } else {
                reload_actions = E.ul(sync_action, delete_action, reload_action);
                nav_actions = E.ul(home_action, back_action, forward_action);
            }
            bookmarks_action = ac(_("Bookmarks"), null, self.overlay.show_bookmarks, "bookmark");
            toc_actions = E.ul(ac(_("Table of Contents"), null, self.overlay.show_toc, "TC", true));
            if (runtime.is_standalone_viewer) {
                toc_actions.appendChild(bookmarks_action);
            }
            actions_div = ρσ_interpolate_kwargs.call(E, E.div, [nav_actions, E.ul(ac(_("Search"), _("Search for text in this book"), self.overlay.show_search, "search"), ac(_("Go to"), _("Go to a specific location in the book"), self.overlay.show_goto, "chevron-right")), reload_actions, toc_actions, E.ul(ac(_("Font size"), _("Change text size"), self.overlay.show_font_size_chooser, "Aa", true), ac(_("Preferences"), _("Configure the book reader"), self.overlay.show_prefs, "cogs"))].concat([ρσ_desugar_kwargs({class_: MAIN_OVERLAY_ACTIONS_CLASS})]));
            full_screen_actions = ρσ_list_decorate([]);
            if (runtime.is_standalone_viewer) {
                text = (runtime.viewer_in_full_screen) ? _("Exit full screen") : _("Enter full screen");
                full_screen_actions.push(ac(text, "", function () {
                    [self.overlay.hide(), ui_operations.toggle_full_screen()];
                }, "full-screen"));
            } else {
                if (!full_screen_element() && !is_ios) {
                    full_screen_actions.push(ac(_("Full screen"), _("Enter full screen mode"), function () {
                        [self.overlay.hide(), ui_operations.toggle_full_screen()];
                    }, "full-screen"));
                }
            }
            if (full_screen_actions.length) {
                actions_div.appendChild(E.ul.apply(E, full_screen_actions));
            }
            if (runtime.is_standalone_viewer) {
                actions_div.appendChild(E.ul(ac(_("Lookup/search word"), _("Lookup or search for the currently selected word"), function () {
                    [self.overlay.hide(), ui_operations.toggle_lookup()];
                }, "library")));
                copy_actions = E.ul();
                if (self.overlay.view.currently_showing.selected_text) {
                    copy_actions.appendChild(ac(_("Copy selection"), _("Copy the current selection"), function () {
                        [self.overlay.hide(), ui_operations.copy_selection()];
                    }, "copy"));
                }
                if (self.elements.link) {
                    copy_actions.appendChild(ac(_("Copy link"), _("Copy the current link"), function () {
                        [self.overlay.hide(), ui_operations.copy_selection(self.elements.link)];
                    }, "link"));
                }
                if (self.elements.img) {
                    copy_actions.appendChild(ac(_("View image"), _("View the current image"), function () {
                        [self.overlay.hide(), ui_operations.view_image(self.elements.img)];
                    }, "image"));
                    copy_actions.appendChild(ac(_("Copy image"), _("View the current image"), function () {
                        [self.overlay.hide(), ui_operations.copy_image(self.elements.img)];
                    }, "copy"));
                }
                if (copy_actions.childNodes.length) {
                    actions_div.appendChild(copy_actions);
                }
                actions_div.appendChild(E.ul(ac(_("Inspector"), _("Show the content inspector"), function () {
                    [self.overlay.hide(), ui_operations.toggle_inspector()];
                }, "bug")));
            }
            container.appendChild(ρσ_interpolate_kwargs.call(this, set_css, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(this, set_css, [E.div(ρσ_interpolate_kwargs.call(E, E.div, [self.overlay.view.book.metadata.title].concat([ρσ_desugar_kwargs({style: "max-width: 90%; text-overflow: ellipsis; font-weight: bold; white-space: nowrap"})])), ρσ_interpolate_kwargs.call(E, E.div, [self.date_formatter.format(new Date)].concat([ρσ_desugar_kwargs({id: self.timer_id, style: "max-width: 9%; text-overflow: ellipsis; white-space: nowrap"})])))].concat([ρσ_desugar_kwargs({display: "flex", justify_content: "space-between", align_items: "baseline", font_size: "smaller", padding: "0.5ex 1rem", border_bottom: "solid 1px currentColor"})])), actions_div].concat([ρσ_desugar_kwargs({class_: MAIN_OVERLAY_TS_CLASS, onclick: (function() {
                var ρσ_anonfunc = function (evt) {
                    evt.stopPropagation();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["evt"]}
                });
                return ρσ_anonfunc;
            })()})]))].concat([ρσ_desugar_kwargs({user_select: "none", background_color: get_color("window-background")})])));
            container.appendChild(ρσ_interpolate_kwargs.call(this, set_css, [E.div(svgicon("close", icon_size, icon_size), " ", _("Close"))].concat([ρσ_desugar_kwargs({cursor: "pointer", position: "fixed", width: "100vw", bottom: "0", display: "flex", justify_content: "center", align_items: "center", padding: "0.5ex 1em", user_select: "none", background_color: get_color("window-background")})])));
            self.on_hide();
            self.timer = setInterval(self.update_time, 1e3);
        };
        if (!MainOverlay.prototype.show.__argnames__) Object.defineProperties(MainOverlay.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        MainOverlay.prototype.update_time = function update_time() {
            var self = this;
            var tm;
            tm = document.getElementById(self.timer_id);
            if (tm) {
                tm.textContent = self.date_formatter.format(new Date);
            }
        };
        MainOverlay.prototype.on_hide = function on_hide() {
            var self = this;
            if (self.timer !== null) {
                clearInterval(self.timer);
            }
            self.timer = null;
        };
        MainOverlay.prototype.back = function back() {
            var self = this;
            window.history.back();
        };
        MainOverlay.prototype.forward = function forward() {
            var self = this;
            window.history.forward();
        };
        MainOverlay.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        MainOverlay.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(MainOverlay.prototype, "__bases__", {value: []});

        function SimpleOverlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            SimpleOverlay.prototype.__bind_methods__.call(this);
            SimpleOverlay.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(SimpleOverlay.prototype, "__bind_methods__", {value: function () {
            this.on_container_click = SimpleOverlay.prototype.on_container_click.bind(this);
            this.show = SimpleOverlay.prototype.show.bind(this);
        }});
        SimpleOverlay.prototype.__init__ = function __init__(overlay, create_func, title) {
            var self = this;
            self.overlay = overlay;
            self.create_func = create_func;
            self.title = title;
        };
        if (!SimpleOverlay.prototype.__init__.__argnames__) Object.defineProperties(SimpleOverlay.prototype.__init__, {
            __argnames__ : {value: ["overlay", "create_func", "title"]}
        });
        SimpleOverlay.__argnames__ = SimpleOverlay.prototype.__init__.__argnames__;
        SimpleOverlay.__handles_kwarg_interpolation__ = SimpleOverlay.prototype.__init__.__handles_kwarg_interpolation__;
        SimpleOverlay.prototype.on_container_click = function on_container_click(evt) {
            var self = this;
        };
        if (!SimpleOverlay.prototype.on_container_click.__argnames__) Object.defineProperties(SimpleOverlay.prototype.on_container_click, {
            __argnames__ : {value: ["evt"]}
        });
        SimpleOverlay.prototype.show = function show(container) {
            var self = this;
            simple_overlay_title(self.title, self.overlay, container);
            self.create_func(self.overlay, container);
        };
        if (!SimpleOverlay.prototype.show.__argnames__) Object.defineProperties(SimpleOverlay.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        SimpleOverlay.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        SimpleOverlay.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(SimpleOverlay.prototype, "__bases__", {value: []});

        function TOCOverlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            TOCOverlay.prototype.__bind_methods__.call(this);
            TOCOverlay.prototype.__init__.apply(this, arguments);
        }
        ρσ_extends(TOCOverlay, SimpleOverlay);
        Object.defineProperty(TOCOverlay.prototype, "__bind_methods__", {value: function () {
            SimpleOverlay.prototype.__bind_methods__ && SimpleOverlay.prototype.__bind_methods__.call(this);
            this.show = TOCOverlay.prototype.show.bind(this);
            this.handle_activate = TOCOverlay.prototype.handle_activate.bind(this);
        }});
        TOCOverlay.prototype.__init__ = function __init__(overlay, create_func, title) {
            var self = this;
            self.overlay = overlay;
            self.create_func = create_func || create_toc_panel;
            self.title = title || _("Table of Contents");
        };
        if (!TOCOverlay.prototype.__init__.__argnames__) Object.defineProperties(TOCOverlay.prototype.__init__, {
            __argnames__ : {value: ["overlay", "create_func", "title"]}
        });
        TOCOverlay.__argnames__ = TOCOverlay.prototype.__init__.__argnames__;
        TOCOverlay.__handles_kwarg_interpolation__ = TOCOverlay.prototype.__init__.__handles_kwarg_interpolation__;
        TOCOverlay.prototype.show = function show(container) {
            var self = this;
            simple_overlay_title(self.title, self.overlay, container);
            self.create_func(self.overlay.view.book, container, self.handle_activate);
        };
        if (!TOCOverlay.prototype.show.__argnames__) Object.defineProperties(TOCOverlay.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        TOCOverlay.prototype.handle_activate = function handle_activate(dest, frag) {
            var self = this;
            self.overlay.hide();
            if (typeof dest === "function") {
                dest(self.overlay.view, frag);
            } else {
                self.overlay.view.goto_named_destination(dest, frag);
            }
        };
        if (!TOCOverlay.prototype.handle_activate.__argnames__) Object.defineProperties(TOCOverlay.prototype.handle_activate, {
            __argnames__ : {value: ["dest", "frag"]}
        });
        TOCOverlay.prototype.__repr__ = function __repr__ () {
            if(SimpleOverlay.prototype.__repr__) return SimpleOverlay.prototype.__repr__.call(this);
            return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        TOCOverlay.prototype.__str__ = function __str__ () {
            if(SimpleOverlay.prototype.__str__) return SimpleOverlay.prototype.__str__.call(this);
return this.__repr__();
        };
        Object.defineProperty(TOCOverlay.prototype, "__bases__", {value: [SimpleOverlay]});

        function WordActionsOverlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            WordActionsOverlay.prototype.__bind_methods__.call(this);
            WordActionsOverlay.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(WordActionsOverlay.prototype, "__bind_methods__", {value: function () {
            this.on_container_click = WordActionsOverlay.prototype.on_container_click.bind(this);
            this.show = WordActionsOverlay.prototype.show.bind(this);
        }});
        WordActionsOverlay.prototype.__init__ = function __init__(word, overlay) {
            var self = this;
            self.word = word;
            self.overlay = overlay;
        };
        if (!WordActionsOverlay.prototype.__init__.__argnames__) Object.defineProperties(WordActionsOverlay.prototype.__init__, {
            __argnames__ : {value: ["word", "overlay"]}
        });
        WordActionsOverlay.__argnames__ = WordActionsOverlay.prototype.__init__.__argnames__;
        WordActionsOverlay.__handles_kwarg_interpolation__ = WordActionsOverlay.prototype.__init__.__handles_kwarg_interpolation__;
        WordActionsOverlay.prototype.on_container_click = function on_container_click(evt) {
            var self = this;
        };
        if (!WordActionsOverlay.prototype.on_container_click.__argnames__) Object.defineProperties(WordActionsOverlay.prototype.on_container_click, {
            __argnames__ : {value: ["evt"]}
        });
        WordActionsOverlay.prototype.show = function show(container) {
            var self = this;
            container.style.backgroundColor = get_color("window-background");
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.h2(_("Lookup: {}").format(self.word)), ρσ_interpolate_kwargs.call(E, E.div, [svgicon("close")].concat([ρσ_desugar_kwargs({style: "cursor:pointer", onclick: (function() {
                var ρσ_anonfunc = function (event) {
                    [event.preventDefault(), event.stopPropagation(), self.overlay.hide_current_panel(event)];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })(), class_: "simple-link"})]))].concat([ρσ_desugar_kwargs({style: "padding: 1ex 1em; border-bottom: solid 1px currentColor; display:flex; justify-content: space-between"})])));
            container.appendChild(E.div());
            create_word_actions_panel(container, self.word, self.overlay.hide);
        };
        if (!WordActionsOverlay.prototype.show.__argnames__) Object.defineProperties(WordActionsOverlay.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        WordActionsOverlay.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        WordActionsOverlay.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(WordActionsOverlay.prototype, "__bases__", {value: []});

        function PrefsOverlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            PrefsOverlay.prototype.__bind_methods__.call(this);
            PrefsOverlay.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(PrefsOverlay.prototype, "__bind_methods__", {value: function () {
            this.on_container_click = PrefsOverlay.prototype.on_container_click.bind(this);
            this.show = PrefsOverlay.prototype.show.bind(this);
            this.handle_escape = PrefsOverlay.prototype.handle_escape.bind(this);
            this.on_hide = PrefsOverlay.prototype.on_hide.bind(this);
        }});
        PrefsOverlay.prototype.__init__ = function __init__(overlay) {
            var self = this;
            self.overlay = overlay;
            self.changes_occurred = false;
        };
        if (!PrefsOverlay.prototype.__init__.__argnames__) Object.defineProperties(PrefsOverlay.prototype.__init__, {
            __argnames__ : {value: ["overlay"]}
        });
        PrefsOverlay.__argnames__ = PrefsOverlay.prototype.__init__.__argnames__;
        PrefsOverlay.__handles_kwarg_interpolation__ = PrefsOverlay.prototype.__init__.__handles_kwarg_interpolation__;
        PrefsOverlay.prototype.on_container_click = function on_container_click(evt) {
            var self = this;
        };
        if (!PrefsOverlay.prototype.on_container_click.__argnames__) Object.defineProperties(PrefsOverlay.prototype.on_container_click, {
            __argnames__ : {value: ["evt"]}
        });
        PrefsOverlay.prototype.show = function show(container) {
            var self = this;
            self.changes_occurred = false;
            container.style.backgroundColor = get_color("window-background");
            self.prefs = create_prefs_panel(container, self.overlay.hide_current_panel, function () {
                self.changes_occurred = true;
            });
        };
        if (!PrefsOverlay.prototype.show.__argnames__) Object.defineProperties(PrefsOverlay.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        PrefsOverlay.prototype.handle_escape = function handle_escape() {
            var self = this;
            self.prefs.onclose();
        };
        PrefsOverlay.prototype.on_hide = function on_hide() {
            var self = this;
            if (self.changes_occurred) {
                self.changes_occurred = false;
                ui_operations.redisplay_book();
            }
        };
        PrefsOverlay.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        PrefsOverlay.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(PrefsOverlay.prototype, "__bases__", {value: []});

        function FontSizeOverlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            FontSizeOverlay.prototype.__bind_methods__.call(this);
            FontSizeOverlay.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(FontSizeOverlay.prototype, "__bind_methods__", {value: function () {
            this.show = FontSizeOverlay.prototype.show.bind(this);
        }});
        FontSizeOverlay.prototype.__init__ = function __init__(overlay) {
            var self = this;
            self.overlay = overlay;
        };
        if (!FontSizeOverlay.prototype.__init__.__argnames__) Object.defineProperties(FontSizeOverlay.prototype.__init__, {
            __argnames__ : {value: ["overlay"]}
        });
        FontSizeOverlay.__argnames__ = FontSizeOverlay.prototype.__init__.__argnames__;
        FontSizeOverlay.__handles_kwarg_interpolation__ = FontSizeOverlay.prototype.__init__.__handles_kwarg_interpolation__;
        FontSizeOverlay.prototype.show = function show(container) {
            var self = this;
            create_font_size_panel(container, self.overlay.hide_current_panel);
        };
        if (!FontSizeOverlay.prototype.show.__argnames__) Object.defineProperties(FontSizeOverlay.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        FontSizeOverlay.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        FontSizeOverlay.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(FontSizeOverlay.prototype, "__bases__", {value: []});

        function OpenBook() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            OpenBook.prototype.__bind_methods__.call(this);
            OpenBook.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(OpenBook.prototype, "__bind_methods__", {value: function () {
            this.on_container_click = OpenBook.prototype.on_container_click.bind(this);
            this.show = OpenBook.prototype.show.bind(this);
        }});
        OpenBook.prototype.__init__ = function __init__(overlay, closeable) {
            var self = this;
            self.overlay = overlay;
            self.closeable = closeable;
            self.is_not_escapable = !closeable;
        };
        if (!OpenBook.prototype.__init__.__argnames__) Object.defineProperties(OpenBook.prototype.__init__, {
            __argnames__ : {value: ["overlay", "closeable"]}
        });
        OpenBook.__argnames__ = OpenBook.prototype.__init__.__argnames__;
        OpenBook.__handles_kwarg_interpolation__ = OpenBook.prototype.__init__.__handles_kwarg_interpolation__;
        OpenBook.prototype.on_container_click = function on_container_click(evt) {
            var self = this;
        };
        if (!OpenBook.prototype.on_container_click.__argnames__) Object.defineProperties(OpenBook.prototype.on_container_click, {
            __argnames__ : {value: ["evt"]}
        });
        OpenBook.prototype.show = function show(container) {
            var self = this;
            var close_button_style;
            container.style.backgroundColor = get_color("window-background");
            close_button_style = (self.closeable) ? "" : "display: none";
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [E.h2(_("Open a new book")), ρσ_interpolate_kwargs.call(E, E.div, [svgicon("close")].concat([ρσ_desugar_kwargs({style: "cursor:pointer; " + ρσ_str.format("{}", close_button_style) + "", onclick: (function() {
                var ρσ_anonfunc = function (event) {
                    [event.preventDefault(), event.stopPropagation(), self.overlay.hide_current_panel(event)];
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["event"]}
                });
                return ρσ_anonfunc;
            })(), class_: "simple-link"})]))].concat([ρσ_desugar_kwargs({style: "padding: 1ex 1em; border-bottom: solid 1px currentColor; display:flex; justify-content: space-between"})])));
            create_open_book(container, ρσ_exists.d(self.overlay.view).book);
        };
        if (!OpenBook.prototype.show.__argnames__) Object.defineProperties(OpenBook.prototype.show, {
            __argnames__ : {value: ["container"]}
        });
        OpenBook.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        OpenBook.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(OpenBook.prototype, "__bases__", {value: []});

        function Overlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            Overlay.prototype.__bind_methods__.call(this);
            Overlay.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(Overlay.prototype, "__bind_methods__", {value: function () {
            this.oncontextmenu = Overlay.prototype.oncontextmenu.bind(this);
            this.clear_container = Overlay.prototype.clear_container.bind(this);
            this.update_visibility = Overlay.prototype.update_visibility.bind(this);
            this.container_clicked = Overlay.prototype.container_clicked.bind(this);
            this.show_loading_message = Overlay.prototype.show_loading_message.bind(this);
            this.hide_loading_message = Overlay.prototype.hide_loading_message.bind(this);
            this.hide_current_panel = Overlay.prototype.hide_current_panel.bind(this);
            this.handle_escape = Overlay.prototype.handle_escape.bind(this);
            this.show_current_panel = Overlay.prototype.show_current_panel.bind(this);
            this.show = Overlay.prototype.show.bind(this);
            this.hide = Overlay.prototype.hide.bind(this);
            this.delete_book = Overlay.prototype.delete_book.bind(this);
            this.reload_book = Overlay.prototype.reload_book.bind(this);
            this.open_book = Overlay.prototype.open_book.bind(this);
            this.sync_book = Overlay.prototype.sync_book.bind(this);
            this.show_toc = Overlay.prototype.show_toc.bind(this);
            this.show_bookmarks = Overlay.prototype.show_bookmarks.bind(this);
            this.show_goto = Overlay.prototype.show_goto.bind(this);
            this.show_metadata = Overlay.prototype.show_metadata.bind(this);
            this.show_ask_for_location = Overlay.prototype.show_ask_for_location.bind(this);
            this.show_search = Overlay.prototype.show_search.bind(this);
            this.show_prefs = Overlay.prototype.show_prefs.bind(this);
            this.show_font_size_chooser = Overlay.prototype.show_font_size_chooser.bind(this);
            this.show_word_actions = Overlay.prototype.show_word_actions.bind(this);
        }});
        Object.defineProperties(Overlay.prototype,  {
            "container": {
                "enumerable": true, 
                "get": function container() {
                    var self = this;
                    return document.getElementById("book-overlay");
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "is_visible": {
                "enumerable": true, 
                "get": function is_visible() {
                    var self = this;
                    return self.container.style.display !== "none";
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        Overlay.prototype.__init__ = function __init__(view) {
            var self = this;
            var c;
            self.view = view;
            c = self.clear_container();
            c.addEventListener("click", self.container_clicked);
            c.addEventListener("contextmenu", self.oncontextmenu, (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["passive"] = false;
                return ρσ_d;
            }).call(this));
            self.panels = ρσ_list_decorate([]);
        };
        if (!Overlay.prototype.__init__.__argnames__) Object.defineProperties(Overlay.prototype.__init__, {
            __argnames__ : {value: ["view"]}
        });
        Overlay.__argnames__ = Overlay.prototype.__init__.__argnames__;
        Overlay.__handles_kwarg_interpolation__ = Overlay.prototype.__init__.__handles_kwarg_interpolation__;
        Overlay.prototype.oncontextmenu = function oncontextmenu(evt) {
            var self = this;
            evt.preventDefault();
            self.handle_escape();
        };
        if (!Overlay.prototype.oncontextmenu.__argnames__) Object.defineProperties(Overlay.prototype.oncontextmenu, {
            __argnames__ : {value: ["evt"]}
        });
        Overlay.prototype.clear_container = function clear_container() {
            var self = this;
            var c;
            c = self.container;
            clear(c);
            c.style.backgroundColor = "transparent";
            c.style.color = get_color("window-foreground");
            if (c.style.display !== "block") {
                c.style.display = "block";
                self.view.overlay_visibility_changed(true);
            }
            return c;
        };
        Overlay.prototype.update_visibility = function update_visibility() {
            var self = this;
            if (self.panels.length) {
                self.container.style.display = "block";
                self.view.overlay_visibility_changed(true);
            } else if (self.container.style.display === "block") {
                self.container.style.display = "none";
                self.view.focus_iframe();
                self.view.overlay_visibility_changed(false);
            }
        };
        Overlay.prototype.container_clicked = function container_clicked(evt) {
            var self = this;
            if (self.panels.length && typeof (ρσ_expr_temp = self.panels)[ρσ_expr_temp.length-1].on_container_click === "function") {
                (ρσ_expr_temp = self.panels)[ρσ_expr_temp.length-1].on_container_click(evt);
            } else {
                self.hide_current_panel();
            }
        };
        if (!Overlay.prototype.container_clicked.__argnames__) Object.defineProperties(Overlay.prototype.container_clicked, {
            __argnames__ : {value: ["evt"]}
        });
        Overlay.prototype.show_loading_message = function show_loading_message(msg) {
            var self = this;
            var lm;
            lm = new LoadingMessage(msg, self.view.current_color_scheme);
            self.panels.push(lm);
            self.show_current_panel();
        };
        if (!Overlay.prototype.show_loading_message.__argnames__) Object.defineProperties(Overlay.prototype.show_loading_message, {
            __argnames__ : {value: ["msg"]}
        });
        Overlay.prototype.hide_loading_message = function hide_loading_message() {
            var self = this;
            var p;
            self.panels = (function() {
                var ρσ_Iter = ρσ_Iterable(self.panels), ρσ_Result = [], p;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    p = ρσ_Iter[ρσ_Index];
                    if (!(ρσ_instanceof(p, LoadingMessage))) {
                        ρσ_Result.push(p);
                    }
                }
                ρσ_Result = ρσ_list_constructor(ρσ_Result);
                return ρσ_Result;
            })();
            self.show_current_panel();
        };
        Overlay.prototype.hide_current_panel = function hide_current_panel() {
            var self = this;
            var p;
            p = self.panels.pop();
            if (p && callable(p.on_hide)) {
                p.on_hide();
            }
            self.show_current_panel();
        };
        Overlay.prototype.handle_escape = function handle_escape() {
            var self = this;
            var p;
            if (self.panels.length) {
                p = (ρσ_expr_temp = self.panels)[ρσ_expr_temp.length-1];
                if (!p.is_not_escapable) {
                    if (p.handle_escape) {
                        p.handle_escape();
                    } else {
                        self.hide_current_panel();
                    }
                    return true;
                }
            }
            return false;
        };
        Overlay.prototype.show_current_panel = function show_current_panel() {
            var self = this;
            var c;
            if (self.panels.length) {
                c = self.clear_container();
                (ρσ_expr_temp = self.panels)[ρσ_expr_temp.length-1].show(c);
            }
            self.update_visibility();
        };
        Overlay.prototype.show = function show(elements) {
            var self = this;
            self.panels = ρσ_list_decorate([ new MainOverlay(self, elements) ]);
            self.show_current_panel();
        };
        if (!Overlay.prototype.show.__argnames__) Object.defineProperties(Overlay.prototype.show, {
            __argnames__ : {value: ["elements"]}
        });
        Overlay.prototype.hide = function hide() {
            var self = this;
            while (self.panels.length) {
                self.hide_current_panel();
            }
            self.update_visibility();
        };
        Overlay.prototype.delete_book = function delete_book() {
            var self = this;
            self.hide_current_panel();
            self.panels = ρσ_list_decorate([ new DeleteBook(self) ]);
            self.show_current_panel();
        };
        Overlay.prototype.reload_book = function reload_book() {
            var self = this;
            self.hide_current_panel();
            self.panels = ρσ_list_decorate([ new DeleteBook(self, _("Are you sure you want to reload this book?"), "refresh", _("Reload book"), true) ]);
            self.show_current_panel();
        };
        Overlay.prototype.open_book = function open_book(closeable) {
            var self = this;
            self.hide_current_panel();
            if (typeof closeable !== "boolean") {
                closeable = true;
            }
            self.panels = ρσ_list_decorate([ new OpenBook(self, closeable) ]);
            self.show_current_panel();
        };
        if (!Overlay.prototype.open_book.__argnames__) Object.defineProperties(Overlay.prototype.open_book, {
            __argnames__ : {value: ["closeable"]}
        });
        Overlay.prototype.sync_book = function sync_book() {
            var self = this;
            self.hide_current_panel();
            self.panels = ρσ_list_decorate([ new SyncBook(self) ]);
            self.show_current_panel();
        };
        Overlay.prototype.show_toc = function show_toc() {
            var self = this;
            self.hide_current_panel();
            if (runtime.is_standalone_viewer) {
                ui_operations.toggle_toc();
                return;
            }
            self.panels.push(new TOCOverlay(self));
            self.show_current_panel();
        };
        Overlay.prototype.show_bookmarks = function show_bookmarks() {
            var self = this;
            self.hide_current_panel();
            if (runtime.is_standalone_viewer) {
                ui_operations.toggle_bookmarks();
                return;
            }
        };
        Overlay.prototype.show_goto = function show_goto() {
            var self = this;
            self.hide_current_panel();
            self.panels.push(new TOCOverlay(self, create_goto_panel.bind(null, self.view.currently_showing.bookpos), _("Go to…")));
            self.show_current_panel();
        };
        Overlay.prototype.show_metadata = function show_metadata() {
            var self = this;
            self.hide_current_panel();
            function show_metadata_overlay(mi, pathtoebook, overlay, container) {
                var table;
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({class_: BD_CLASS_NAME, style: "padding: 1ex 1em"})]));
                table = ρσ_interpolate_kwargs.call(E, E.table, [ρσ_desugar_kwargs({class_: "metadata"})]);
                container.lastChild.appendChild(table);
                render_metadata(mi, table);
                if (pathtoebook) {
                    container.lastChild.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [_("Path: {}").format(pathtoebook)].concat([ρσ_desugar_kwargs({style: "font-size: smaller; margin-top: 1ex; padding-top: 1ex; border-top: solid 1px"})])));
                }
            };
            if (!show_metadata_overlay.__argnames__) Object.defineProperties(show_metadata_overlay, {
                __argnames__ : {value: ["mi", "pathtoebook", "overlay", "container"]}
            });

            self.panels.push(new SimpleOverlay(self, show_metadata_overlay.bind(null, self.view.book.metadata, self.view.book.manifest.pathtoebook), self.view.book.metadata.title));
            self.show_current_panel();
        };
        Overlay.prototype.show_ask_for_location = function show_ask_for_location() {
            var self = this;
            self.hide_current_panel();
            self.panels.push(new SimpleOverlay(self, create_location_overlay.bind(null, self.view.currently_showing.bookpos), _("Go to location…")));
            self.show_current_panel();
        };
        Overlay.prototype.show_search = function show_search() {
            var self = this;
            self.hide();
            self.view.show_search();
        };
        Overlay.prototype.show_prefs = function show_prefs() {
            var self = this;
            self.hide_current_panel();
            self.panels.push(new PrefsOverlay(self));
            self.show_current_panel();
        };
        Overlay.prototype.show_font_size_chooser = function show_font_size_chooser() {
            var self = this;
            self.hide_current_panel();
            self.panels.push(new FontSizeOverlay(self));
            self.show_current_panel();
        };
        Overlay.prototype.show_word_actions = function show_word_actions(word) {
            var self = this;
            self.hide_current_panel();
            self.panels.push(new WordActionsOverlay(word, self));
            self.show_current_panel();
        };
        if (!Overlay.prototype.show_word_actions.__argnames__) Object.defineProperties(Overlay.prototype.show_word_actions, {
            __argnames__ : {value: ["word"]}
        });
        Overlay.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        Overlay.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(Overlay.prototype, "__bases__", {value: []});
        
        

        ρσ_modules["read_book.overlay"].MAIN_OVERLAY_TS_CLASS = MAIN_OVERLAY_TS_CLASS;
        ρσ_modules["read_book.overlay"].MAIN_OVERLAY_ACTIONS_CLASS = MAIN_OVERLAY_ACTIONS_CLASS;
        ρσ_modules["read_book.overlay"].LoadingMessage = LoadingMessage;
        ρσ_modules["read_book.overlay"].DeleteBook = DeleteBook;
        ρσ_modules["read_book.overlay"].SyncBook = SyncBook;
        ρσ_modules["read_book.overlay"].simple_overlay_title = simple_overlay_title;
        ρσ_modules["read_book.overlay"].MainOverlay = MainOverlay;
        ρσ_modules["read_book.overlay"].SimpleOverlay = SimpleOverlay;
        ρσ_modules["read_book.overlay"].TOCOverlay = TOCOverlay;
        ρσ_modules["read_book.overlay"].WordActionsOverlay = WordActionsOverlay;
        ρσ_modules["read_book.overlay"].PrefsOverlay = PrefsOverlay;
        ρσ_modules["read_book.overlay"].FontSizeOverlay = FontSizeOverlay;
        ρσ_modules["read_book.overlay"].OpenBook = OpenBook;
        ρσ_modules["read_book.overlay"].Overlay = Overlay;
    })();

    (function(){
        var __name__ = "read_book.search";
        var CLASS_NAME;
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var get_color = ρσ_modules["book_list.theme"].get_color;

        var create_search_bar = ρσ_modules.complete.create_search_bar;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var svgicon = ρσ_modules.dom.svgicon;

        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var text_from_serialized_html = ρσ_modules["read_book.resources"].text_from_serialized_html;

        var shortcut_for_key_event = ρσ_modules["read_book.shortcuts"].shortcut_for_key_event;

        CLASS_NAME = "book-search-container";
        add_extra_css(function () {
            var sel, style;
            sel = "." + CLASS_NAME;
            style = ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({text_align: "right", user_select: "none"})]));
            sel += " > div ";
            style += ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({display: "inline-flex", pointer_events: "auto", background_color: get_color("window-background"), padding: "1ex"})]));
            return style;
        });
        function SearchOverlay() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            SearchOverlay.prototype.__bind_methods__.call(this);
            SearchOverlay.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(SearchOverlay.prototype, "__bind_methods__", {value: function () {
            this.onkeydown = SearchOverlay.prototype.onkeydown.bind(this);
            this.set_text = SearchOverlay.prototype.set_text.bind(this);
            this.hide = SearchOverlay.prototype.hide.bind(this);
            this.show = SearchOverlay.prototype.show.bind(this);
            this.find = SearchOverlay.prototype.find.bind(this);
            this.find_next = SearchOverlay.prototype.find_next.bind(this);
            this.find_previous = SearchOverlay.prototype.find_previous.bind(this);
        }});
        Object.defineProperties(SearchOverlay.prototype,  {
            "container": {
                "enumerable": true, 
                "get": function container() {
                    var self = this;
                    return document.getElementById("book-search-overlay");
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "search_text": {
                "enumerable": true, 
                "get": function search_text() {
                    var self = this;
                    return self.container.querySelector("input").value;
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
            "is_visible": {
                "enumerable": true, 
                "get": function is_visible() {
                    var self = this;
                    return self.container.style.display !== "none";
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        SearchOverlay.prototype.__init__ = function __init__(view) {
            var self = this;
            var c, next_button, prev_button, close_button;
            self.view = view;
            c = self.container;
            c.classList.add(CLASS_NAME);
            next_button = ρσ_interpolate_kwargs.call(E, E.div, [svgicon("chevron-down")].concat([ρσ_desugar_kwargs({class_: "simple-link", title: _("Next match")})]));
            prev_button = ρσ_interpolate_kwargs.call(E, E.div, [svgicon("chevron-up")].concat([ρσ_desugar_kwargs({class_: "simple-link", title: _("Previous match")})]));
            prev_button.addEventListener("click", (function() {
                var ρσ_anonfunc = function (ev) {
                    self.find_previous();
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })());
            close_button = ρσ_interpolate_kwargs.call(E, E.div, [svgicon("close")].concat([ρσ_desugar_kwargs({style: "cursor:pointer", title: _("Close Search bar")})]));
            close_button.addEventListener("click", (function() {
                var ρσ_anonfunc = function (ev) {
                    window.setTimeout(self.hide, 0);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["ev"]}
                });
                return ρσ_anonfunc;
            })());
            c.appendChild(E.div(svgicon("search"), " ", ρσ_interpolate_kwargs.call(this, create_search_bar, [self.find_next, "search-in-book"].concat([ρσ_desugar_kwargs({placeholder: _("Search") + "…", button: next_button, associated_widgets: ρσ_list_decorate([ prev_button, close_button ])})])), " ", next_button, " ", prev_button, " ", close_button));
            c.firstChild.addEventListener("keydown", self.onkeydown, (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["passive"] = false;
                return ρσ_d;
            }).call(this));
        };
        if (!SearchOverlay.prototype.__init__.__argnames__) Object.defineProperties(SearchOverlay.prototype.__init__, {
            __argnames__ : {value: ["view"]}
        });
        SearchOverlay.__argnames__ = SearchOverlay.prototype.__init__.__argnames__;
        SearchOverlay.__handles_kwarg_interpolation__ = SearchOverlay.prototype.__init__.__handles_kwarg_interpolation__;
        SearchOverlay.prototype.onkeydown = function onkeydown(event) {
            var self = this;
            var sc_name;
            if (event.key === "Escape" || event.key === "Esc") {
                self.hide();
                [event.preventDefault(), event.stopPropagation()];
                return;
            }
            sc_name = shortcut_for_key_event(event, self.view.keyboard_shortcut_map);
            if (sc_name === "next_match") {
                self.find_next();
                [event.preventDefault(), event.stopPropagation()];
                return;
            }
            if (sc_name === "previous_match") {
                self.find_previous();
                [event.preventDefault(), event.stopPropagation()];
                return;
            }
        };
        if (!SearchOverlay.prototype.onkeydown.__argnames__) Object.defineProperties(SearchOverlay.prototype.onkeydown, {
            __argnames__ : {value: ["event"]}
        });
        SearchOverlay.prototype.set_text = function set_text(text) {
            var self = this;
            self.container.querySelector("input").value = text || "";
        };
        if (!SearchOverlay.prototype.set_text.__argnames__) Object.defineProperties(SearchOverlay.prototype.set_text, {
            __argnames__ : {value: ["text"]}
        });
        SearchOverlay.prototype.hide = function hide() {
            var self = this;
            self.container.style.display = "none";
            ui_operations.focus_iframe();
        };
        SearchOverlay.prototype.show = function show() {
            var self = this;
            var c;
            c = self.container;
            c.style.display = "block";
            c.querySelector("input").focus();
        };
        SearchOverlay.prototype.find = function find(text, backwards) {
            var self = this;
            if (!text) {
                return;
            }
            self.view.find(text, backwards);
        };
        if (!SearchOverlay.prototype.find.__argnames__) Object.defineProperties(SearchOverlay.prototype.find, {
            __argnames__ : {value: ["text", "backwards"]}
        });
        SearchOverlay.prototype.find_next = function find_next() {
            var self = this;
            self.find(self.search_text, false);
        };
        SearchOverlay.prototype.find_previous = function find_previous() {
            var self = this;
            self.find(self.search_text, true);
        };
        SearchOverlay.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        SearchOverlay.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(SearchOverlay.prototype, "__bases__", {value: []});
        
        
        

        function find_in_serialized_html(data, text) {
            var haystack;
            haystack = text_from_serialized_html(data);
            return haystack.toLowerCase().indexOf(text) > -1;
        };
        if (!find_in_serialized_html.__argnames__) Object.defineProperties(find_in_serialized_html, {
            __argnames__ : {value: ["data", "text"]}
        });

        function find_in_spine(names, book, text, proceed) {
            text = text.toLowerCase();
            function got_one(data, name, mimetype) {
                if (find_in_serialized_html(data, text)) {
                    proceed(name);
                } else {
                    do_one();
                }
            };
            if (!got_one.__argnames__) Object.defineProperties(got_one, {
                __argnames__ : {value: ["data", "name", "mimetype"]}
            });

            function do_one() {
                var name;
                name = names.shift();
                if (name) {
                    ui_operations.get_file(book, name, got_one);
                } else {
                    proceed(null);
                }
            };

            do_one();
        };
        if (!find_in_spine.__argnames__) Object.defineProperties(find_in_spine, {
            __argnames__ : {value: ["names", "book", "text", "proceed"]}
        });

        ρσ_modules["read_book.search"].CLASS_NAME = CLASS_NAME;
        ρσ_modules["read_book.search"].SearchOverlay = SearchOverlay;
        ρσ_modules["read_book.search"].find_in_serialized_html = find_in_serialized_html;
        ρσ_modules["read_book.search"].find_in_spine = find_in_spine;
    })();

    (function(){
        var __name__ = "read_book.timers";
        var THRESHOLD, FILTER_THRESHOLD, MAX_SAMPLES;
        THRESHOLD = 5;
        FILTER_THRESHOLD = 25;
        MAX_SAMPLES = 256;
        function Timers() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            Timers.prototype.__bind_methods__.call(this);
            Timers.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(Timers.prototype, "__bind_methods__", {value: function () {
            this.start_book = Timers.prototype.start_book.bind(this);
            this.reset_read_timer = Timers.prototype.reset_read_timer.bind(this);
            this.calculate = Timers.prototype.calculate.bind(this);
            this.on_human_scroll = Timers.prototype.on_human_scroll.bind(this);
            this.time_for = Timers.prototype.time_for.bind(this);
        }});
        Timers.prototype.__init__ = function __init__() {
            var self = this;
            self.reset_read_timer();
            self.rates = [];
            self.average = self.stddev = 0;
        };
        Timers.__argnames__ = Timers.prototype.__init__.__argnames__;
        Timers.__handles_kwarg_interpolation__ = Timers.prototype.__init__.__handles_kwarg_interpolation__;
        Timers.prototype.start_book = function start_book(book) {
            var self = this;
            self.reset_read_timer();
            self.rates = [];
        };
        if (!Timers.prototype.start_book.__argnames__) Object.defineProperties(Timers.prototype.start_book, {
            __argnames__ : {value: ["book"]}
        });
        Timers.prototype.reset_read_timer = function reset_read_timer() {
            var self = this;
            self.last_scroll_at = null;
        };
        Timers.prototype.calculate = function calculate() {
            var self = this;
            var rates, rlen, avg, sq, x;
            rates = self.rates;
            rlen = rates.length;
            if (rlen >= THRESHOLD) {
                avg = 0;
                for (var i = 0; i < rlen; i++) {
                    avg += rates[(typeof i === "number" && i < 0) ? rates.length + i : i];
                }
                avg /= rlen;
                self.average = avg;
                sq = 0;
                for (var i = 0; i < rlen; i++) {
                    x = rates[(typeof i === "number" && i < 0) ? rates.length + i : i] - avg;
                    sq += x * x;
                }
                self.stddev = Math.sqrt(sq / (rlen - 1));
            } else {
                self.average = self.stddev = 0;
            }
        };
        Timers.prototype.on_human_scroll = function on_human_scroll(amt_scrolled) {
            var self = this;
            var last_scroll_at, now, time_since_last_scroll, rate;
            last_scroll_at = self.last_scroll_at;
            self.last_scroll_at = now = window.performance.now();
            if (last_scroll_at === null) {
                return;
            }
            time_since_last_scroll = (now - last_scroll_at) / 1e3;
            if (time_since_last_scroll <= 0 || time_since_last_scroll >= 300) {
                return;
            }
            if (time_since_last_scroll < 2) {
                return;
            }
            rate = amt_scrolled / time_since_last_scroll;
            if (self.rates.length >= FILTER_THRESHOLD && Math.abs(rate - self.average) > 2 * self.stddev) {
                return;
            }
            if (self.rates.length >= MAX_SAMPLES) {
                self.rates.shift();
            }
            self.rates.push(rate);
            self.calculate();
        };
        if (!Timers.prototype.on_human_scroll.__argnames__) Object.defineProperties(Timers.prototype.on_human_scroll, {
            __argnames__ : {value: ["amt_scrolled"]}
        });
        Timers.prototype.time_for = function time_for(length) {
            var self = this;
            if (length >= 0 && self.rates.length >= THRESHOLD && self.average > 0) {
                return length / self.average;
            }
            return null;
        };
        if (!Timers.prototype.time_for.__argnames__) Object.defineProperties(Timers.prototype.time_for, {
            __argnames__ : {value: ["length"]}
        });
        Timers.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        Timers.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(Timers.prototype, "__bases__", {value: []});

        ρσ_modules["read_book.timers"].THRESHOLD = THRESHOLD;
        ρσ_modules["read_book.timers"].FILTER_THRESHOLD = FILTER_THRESHOLD;
        ρσ_modules["read_book.timers"].MAX_SAMPLES = MAX_SAMPLES;
        ρσ_modules["read_book.timers"].Timers = Timers;
    })();

    (function(){
        var __name__ = "read_book.view";
        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;

        var read_book = ρσ_modules.read_book;
        read_book.iframe = ρσ_modules["read_book.iframe"];

        var ajax_send = ρσ_modules.ajax.ajax_send;

        var get_session_data = ρσ_modules["book_list.globals"].get_session_data;

        var cached_color_to_rgba = ρσ_modules["book_list.theme"].cached_color_to_rgba;
        var get_color = ρσ_modules["book_list.theme"].get_color;

        var add_extra_css = ρσ_modules.dom.add_extra_css;
        var build_rule = ρσ_modules.dom.build_rule;
        var set_css = ρσ_modules.dom.set_css;
        var svgicon = ρσ_modules.dom.svgicon;
        var unique_id = ρσ_modules.dom.unique_id;

        var IframeWrapper = ρσ_modules.iframe_comm.IframeWrapper;

        var error_dialog = ρσ_modules.modals.error_dialog;
        var warning_dialog = ρσ_modules.modals.warning_dialog;

        var ContentPopupOverlay = ρσ_modules["read_book.content_popup"].ContentPopupOverlay;

        var BookScrollbar = ρσ_modules["read_book.scrollbar"].BookScrollbar;

        var current_book = ρσ_modules["read_book.globals"].current_book;
        var runtime = ρσ_modules["read_book.globals"].runtime;
        var set_current_spine_item = ρσ_modules["read_book.globals"].set_current_spine_item;
        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var get_next_section = ρσ_modules["read_book.goto"].get_next_section;

        var add_book_to_recently_viewed = ρσ_modules["read_book.open_book"].add_book_to_recently_viewed;

        var Overlay = ρσ_modules["read_book.overlay"].Overlay;

        var resolve_color_scheme = ρσ_modules["read_book.prefs.colors"].resolve_color_scheme;

        var change_font_size_by = ρσ_modules["read_book.prefs.font_size"].change_font_size_by;

        var render_head_foot = ρσ_modules["read_book.prefs.head_foot"].render_head_foot;

        var load_resources = ρσ_modules["read_book.resources"].load_resources;

        var SearchOverlay = ρσ_modules["read_book.search"].SearchOverlay;
        var find_in_spine = ρσ_modules["read_book.search"].find_in_spine;

        var create_shortcut_map = ρσ_modules["read_book.shortcuts"].create_shortcut_map;

        var Timers = ρσ_modules["read_book.timers"].Timers;

        var get_current_toc_nodes = ρσ_modules["read_book.toc"].get_current_toc_nodes;
        var update_visible_toc_nodes = ρσ_modules["read_book.toc"].update_visible_toc_nodes;

        var set_left_margin_handler = ρσ_modules["read_book.touch"].set_left_margin_handler;
        var set_right_margin_handler = ρσ_modules["read_book.touch"].set_right_margin_handler;

        var get_device_uuid = ρσ_modules.session.get_device_uuid;
        var get_interface_data = ρσ_modules.session.get_interface_data;

        var html_escape = ρσ_modules.utils.html_escape;
        var is_ios = ρσ_modules.utils.is_ios;
        var parse_url_params = ρσ_modules.utils.parse_url_params;
        var safe_set_inner_html = ρσ_modules.utils.safe_set_inner_html;
        var username_key = ρσ_modules.utils.username_key;

        var READER_BACKGROUND_URL = ρσ_modules["viewer.constants"].READER_BACKGROUND_URL;

        add_extra_css(function () {
            var sel, ans;
            sel = ".book-side-margin";
            ans = ρσ_interpolate_kwargs.call(this, build_rule, [sel].concat([ρσ_desugar_kwargs({cursor: "pointer", text_align: "center", height: "100vh", user_select: "none", display: "flex", align_items: "center", justify_content: "center"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel + " > svg"].concat([ρσ_desugar_kwargs({visibility: "hidden"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ":hover > svg"].concat([ρσ_desugar_kwargs({visibility: "visible"})]));
            ans += ρσ_interpolate_kwargs.call(this, build_rule, [sel + ":active > svg"].concat([ρσ_desugar_kwargs({color: get_color("window-hover-foreground"), visibility: "visible", transform: "scale(2)"})]));
            return ans;
        });
        function show_controls_help() {
            var container, div;
            container = document.getElementById("controls-help-overlay");
            container.style.display = "block";
            container.style.backgroundColor = get_color("window-background");
            if (!show_controls_help.listener_added) {
                show_controls_help.listener_added = true;
                container.addEventListener("click", function () {
                    document.getElementById("controls-help-overlay").style.display = "none";
                    ui_operations.focus_iframe();
                });
                container.addEventListener("contextmenu", (function() {
                    var ρσ_anonfunc = function (evt) {
                        [evt.preventDefault(), evt.stopPropagation()];
                        document.getElementById("controls-help-overlay").style.display = "none";
                        ui_operations.focus_iframe();
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["evt"]}
                    });
                    return ρσ_anonfunc;
                })(), (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["passive"] = false;
                    return ρσ_d;
                }).call(this));
                container.addEventListener("keydown", (function() {
                    var ρσ_anonfunc = function (event) {
                        [event.preventDefault(), event.stopPropagation()];
                        document.getElementById("controls-help-overlay").style.display = "none";
                        ui_operations.focus_iframe();
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["event"]}
                    });
                    return ρσ_anonfunc;
                })(), (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["passive"] = false;
                    return ρσ_d;
                }).call(this));
            }
            function focus() {
                if (container.style.display === "block") {
                    container.querySelector("input").focus();
                    window.setTimeout(focus, 10);
                }
            };

            if (runtime.is_standalone_viewer) {
                container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin-top: 1rem"})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin-top: 1rem"})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin-top: 1rem"})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin-top: 1rem"})]), ρσ_interpolate_kwargs.call(E, E.input, [ρσ_desugar_kwargs({style: "background: transparent; border-width: 0; outline: none", readonly: "readonly"})])].concat([ρσ_desugar_kwargs({style: "margin: 1rem"})])));
                div = container.lastChild.firstChild;
                safe_set_inner_html(div, _("Welcome to the <b>calibre viewer</b>!"));
                div = div.nextSibling;
                safe_set_inner_html(div, _("Use the <b>PageUp/PageDn</b> or <b>Arrow keys</b> to turn pages"));
                div = div.nextSibling;
                safe_set_inner_html(div, _("Press the <b>Esc</b> key or <b>{} click</b> to show the viewer controls").format((ρσ_in("macos", window.navigator.userAgent)) ? "control" : _("right")));
                div = div.nextSibling;
                safe_set_inner_html(div, _("Press any key to continue…"));
                focus();
                return;
            }
            function msg(txt) {
                return ρσ_interpolate_kwargs.call(this, set_css, [E.div(txt)].concat([ρσ_desugar_kwargs({padding: "1ex 1em", text_align: "center", margin: "auto"})]));
            };
            if (!msg.__argnames__) Object.defineProperties(msg, {
                __argnames__ : {value: ["txt"]}
            });

            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [msg(_("Tap (or right click) for controls"))].concat([ρσ_desugar_kwargs({style: "height: 25vh; display:flex; align-items: center; border-bottom: solid 2px currentColor"})])), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [msg(_("Tap to turn back"))].concat([ρσ_desugar_kwargs({style: "width: 25vw; display:flex; align-items: center; border-right: solid 2px currentColor"})])), ρσ_interpolate_kwargs.call(E, E.div, [msg(_("Tap to turn page"))].concat([ρσ_desugar_kwargs({style: "width: 75vw; display:flex; align-items: center"})]))].concat([ρσ_desugar_kwargs({style: "display: flex; align-items: stretch; flex-grow: 10"})]))].concat([ρσ_desugar_kwargs({style: "overflow: hidden; width: 100vw; height: 100vh; text-align: center; font-size: 1.3rem; font-weight: bold; background: " + ρσ_str.format("{}", get_color("window-background")) + ";" + "display:flex; flex-direction: column; align-items: stretch"})])));
        };

        function margin_elem(sd, which, id, onclick) {
            var sz, fsz, s, ans;
            sz = sd.get(which, 20);
            fsz = min(max(0, sz - 6), 12);
            s = "; text-overflow: ellipsis; white-space: nowrap; overflow: hidden";
            ans = ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin-right: 1.5em" + s})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: s})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "margin-left: 1.5em" + s})])].concat([ρσ_desugar_kwargs({style: "height:" + ρσ_str.format("{}", sz) + "px; overflow: hidden; font-size:" + ρσ_str.format("{}", fsz) + "px; width:100%; padding: 0; display: flex; justify-content: space-between; align-items: center", id: id})]));
            if (onclick) {
                ans.addEventListener("click", onclick);
            }
            if (is_ios && which === "margin_bottom" && !window.navigator.standalone && !/CriOS\//.test(window.navigator.userAgent)) {
                ans.style.marginBottom = "25px";
            }
            return ans;
        };
        if (!margin_elem.__argnames__) Object.defineProperties(margin_elem, {
            __argnames__ : {value: ["sd", "which", "id", "onclick"]}
        });

        function View() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            View.prototype.__bind_methods__.call(this);
            View.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(View.prototype, "__bind_methods__", {value: function () {
            this.on_lookup_word = View.prototype.on_lookup_word.bind(this);
            this.left_margin_clicked = View.prototype.left_margin_clicked.bind(this);
            this.right_margin_clicked = View.prototype.right_margin_clicked.bind(this);
            this.top_margin_clicked = View.prototype.top_margin_clicked.bind(this);
            this.bottom_margin_clicked = View.prototype.bottom_margin_clicked.bind(this);
            this.forward_gesture = View.prototype.forward_gesture.bind(this);
            this.iframe_size = View.prototype.iframe_size.bind(this);
            this.on_request_size = View.prototype.on_request_size.bind(this);
            this.on_print = View.prototype.on_print.bind(this);
            this.on_human_scroll = View.prototype.on_human_scroll.bind(this);
            this.on_handle_keypress = View.prototype.on_handle_keypress.bind(this);
            this.handle_keypress = View.prototype.handle_keypress.bind(this);
            this.overlay_visibility_changed = View.prototype.overlay_visibility_changed.bind(this);
            this.on_handle_shortcut = View.prototype.on_handle_shortcut.bind(this);
            this.on_selection_change = View.prototype.on_selection_change.bind(this);
            this.toggle_paged_mode = View.prototype.toggle_paged_mode.bind(this);
            this.find = View.prototype.find.bind(this);
            this.on_find_in_spine = View.prototype.on_find_in_spine.bind(this);
            this.bump_font_size = View.prototype.bump_font_size.bind(this);
            this.on_show_footnote = View.prototype.on_show_footnote.bind(this);
            this.hide_overlays = View.prototype.hide_overlays.bind(this);
            this.focus_iframe = View.prototype.focus_iframe.bind(this);
            this.show_chrome = View.prototype.show_chrome.bind(this);
            this.do_show_chrome = View.prototype.do_show_chrome.bind(this);
            this.show_search = View.prototype.show_search.bind(this);
            this.show_content_popup = View.prototype.show_content_popup.bind(this);
            this.set_margins = View.prototype.set_margins.bind(this);
            this.on_iframe_ready = View.prototype.on_iframe_ready.bind(this);
            this.do_pending_load = View.prototype.do_pending_load.bind(this);
            this.on_iframe_error = View.prototype.on_iframe_error.bind(this);
            this.get_color_scheme = View.prototype.get_color_scheme.bind(this);
            this.on_resize = View.prototype.on_resize.bind(this);
            this.show_loading_message = View.prototype.show_loading_message.bind(this);
            this.show_loading = View.prototype.show_loading.bind(this);
            this.hide_loading = View.prototype.hide_loading.bind(this);
            this.parse_cfi = View.prototype.parse_cfi.bind(this);
            this.display_book = View.prototype.display_book.bind(this);
            this.redisplay_book = View.prototype.redisplay_book.bind(this);
            this.iframe_settings = View.prototype.iframe_settings.bind(this);
            this.show_name = View.prototype.show_name.bind(this);
            this.load_doc = View.prototype.load_doc.bind(this);
            this.goto_doc_boundary = View.prototype.goto_doc_boundary.bind(this);
            this.goto_frac = View.prototype.goto_frac.bind(this);
            this.on_scroll_to_anchor = View.prototype.on_scroll_to_anchor.bind(this);
            this.goto_bookpos = View.prototype.goto_bookpos.bind(this);
            this.goto_named_destination = View.prototype.goto_named_destination.bind(this);
            this.goto_toc_node = View.prototype.goto_toc_node.bind(this);
            this.on_next_spine_item = View.prototype.on_next_spine_item.bind(this);
            this.on_next_section = View.prototype.on_next_section.bind(this);
            this.get_current_cfi = View.prototype.get_current_cfi.bind(this);
            this.update_cfi_data = View.prototype.update_cfi_data.bind(this);
            this.on_report_cfi = View.prototype.on_report_cfi.bind(this);
            this.on_update_progress_frac = View.prototype.on_update_progress_frac.bind(this);
            this.on_update_cfi = View.prototype.on_update_cfi.bind(this);
            this.update_header_footer = View.prototype.update_header_footer.bind(this);
            this.on_update_toc_position = View.prototype.on_update_toc_position.bind(this);
            this.show_spine_item = View.prototype.show_spine_item.bind(this);
            this.show_spine_item_stage2 = View.prototype.show_spine_item_stage2.bind(this);
            this.on_content_loaded = View.prototype.on_content_loaded.bind(this);
            this.set_progress_frac = View.prototype.set_progress_frac.bind(this);
            this.update_font_size = View.prototype.update_font_size.bind(this);
            this.update_color_scheme = View.prototype.update_color_scheme.bind(this);
        }});
        Object.defineProperties(View.prototype,  {
            "iframe": {
                "enumerable": true, 
                "get": function iframe() {
                    var self = this;
                    return self.iframe_wrapper.iframe;
                }, 
                "set": function () { throw new AttributeError("can't set attribute") }
            }, 
        });
        View.prototype.__init__ = function __init__(container) {
            var self = this;
            var sd, left_margin, right_margin, iframe_id, handlers, entry_point;
            self.timers = new Timers;
            self.loaded_resources = Object.create(null);
            self.current_progress_frac = self.current_file_progress_frac = 0;
            self.current_toc_node = self.current_toc_toplevel_node = null;
            self.report_cfi_callbacks = Object.create(null);
            self.show_chrome_counter = 0;
            self.show_loading_callback_timer = null;
            self.timer_ids = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["clock"] = 0;
                return ρσ_d;
            }).call(this);
            self.book_scrollbar = new BookScrollbar(self);
            sd = get_session_data();
            self.keyboard_shortcut_map = create_shortcut_map(sd.get("keyboard_shortcuts"));
            left_margin = ρσ_interpolate_kwargs.call(E, E.div, [svgicon("caret-left")].concat([ρσ_desugar_kwargs({style: "width:{}px;".format(sd.get("margin_left", 20)), class_: "book-side-margin", id: "book-left-margin", onclick: self.left_margin_clicked})]));
            set_left_margin_handler(left_margin);
            right_margin = ρσ_interpolate_kwargs.call(E, E.div, [svgicon("caret-right")].concat([ρσ_desugar_kwargs({style: "width:{}px;".format(sd.get("margin_right", 20)), class_: "book-side-margin", id: "book-right-margin", onclick: self.right_margin_clicked})]));
            set_right_margin_handler(right_margin);
            iframe_id = unique_id("read-book-iframe");
            container.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [ρσ_interpolate_kwargs.call(E, E.div, [left_margin, ρσ_interpolate_kwargs.call(E, E.div, [margin_elem(sd, "margin_top", "book-top-margin", self.top_margin_clicked), ρσ_interpolate_kwargs.call(E, E.iframe, [ρσ_desugar_kwargs({id: iframe_id, seamless: true, sandbox: "allow-popups allow-scripts allow-popups-to-escape-sandbox", style: "flex-grow: 2", allowfullscreen: "true"})]), margin_elem(sd, "margin_bottom", "book-bottom-margin", self.bottom_margin_clicked)].concat([ρσ_desugar_kwargs({style: "flex-grow:2; display:flex; align-items:stretch; flex-direction: column"})])), right_margin, self.book_scrollbar.create(), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "position: absolute; top:0; left:0; width: 100%; pointer-events:none; display:none", id: "book-search-overlay"})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "position: absolute; top:0; left:0; width: 100%; height: 100%; display:none", id: "book-content-popup-overlay"})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "position: absolute; top:0; left:0; width: 100%; height: 100%; display:none", id: "book-overlay"})]), ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({style: "position: absolute; top:0; left:0; width: 100%; height: 100%; display:none", id: "controls-help-overlay"})])].concat([ρσ_desugar_kwargs({style: "max-height: 100vh; flex-grow: 2; display:flex; align-items: stretch"})]))].concat([ρσ_desugar_kwargs({style: "max-height: 100vh; display: flex; flex-direction: column; align-items: stretch; flex-grow:2"})]))].concat([ρσ_desugar_kwargs({style: "max-height: 100vh; width: 100vw; height: 100vh; overflow: hidden; display: flex; align-items: stretch"})])));
            handlers = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["ready"] = self.on_iframe_ready;
                ρσ_d["error"] = self.on_iframe_error;
                ρσ_d["next_spine_item"] = self.on_next_spine_item;
                ρσ_d["next_section"] = self.on_next_section;
                ρσ_d["lookup_word"] = self.on_lookup_word;
                ρσ_d["goto_doc_boundary"] = (function() {
                    var ρσ_anonfunc = function (data) {
                        self.goto_doc_boundary(data.start);
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["data"]}
                    });
                    return ρσ_anonfunc;
                })();
                ρσ_d["scroll_to_anchor"] = self.on_scroll_to_anchor;
                ρσ_d["update_cfi"] = self.on_update_cfi;
                ρσ_d["update_progress_frac"] = self.on_update_progress_frac;
                ρσ_d["report_cfi"] = self.on_report_cfi;
                ρσ_d["update_toc_position"] = self.on_update_toc_position;
                ρσ_d["content_loaded"] = self.on_content_loaded;
                ρσ_d["show_chrome"] = self.show_chrome;
                ρσ_d["bump_font_size"] = self.bump_font_size;
                ρσ_d["find_in_spine"] = self.on_find_in_spine;
                ρσ_d["request_size"] = self.on_request_size;
                ρσ_d["show_footnote"] = self.on_show_footnote;
                ρσ_d["print"] = self.on_print;
                ρσ_d["human_scroll"] = self.on_human_scroll;
                ρσ_d["selectionchange"] = self.on_selection_change;
                ρσ_d["handle_shortcut"] = self.on_handle_shortcut;
                ρσ_d["handle_keypress"] = self.on_handle_keypress;
                return ρσ_d;
            }).call(this);
            entry_point = (runtime.is_standalone_viewer) ? null : "read_book.iframe";
            if (runtime.is_standalone_viewer) {
                document.documentElement.addEventListener("keydown", self.handle_keypress, (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["passive"] = false;
                    return ρσ_d;
                }).call(this));
            }
            self.current_color_scheme = resolve_color_scheme();
            self.iframe_wrapper = new IframeWrapper(handlers, document.getElementById(iframe_id), entry_point, _("Bootstrapping book reader..."), runtime.FAKE_PROTOCOL, runtime.FAKE_HOST);
            self.search_overlay = new SearchOverlay(self);
            self.content_popup_overlay = new ContentPopupOverlay(self);
            self.overlay = new Overlay(self);
            self.processing_spine_item_display = false;
            self.pending_load = null;
            self.currently_showing = Object.create(null);
        };
        if (!View.prototype.__init__.__argnames__) Object.defineProperties(View.prototype.__init__, {
            __argnames__ : {value: ["container"]}
        });
        View.__argnames__ = View.prototype.__init__.__argnames__;
        View.__handles_kwarg_interpolation__ = View.prototype.__init__.__handles_kwarg_interpolation__;
        View.prototype.on_lookup_word = function on_lookup_word(data) {
            var self = this;
            if (runtime.is_standalone_viewer) {
                ui_operations.selection_changed(data.word);
                return;
            }
            self.overlay.show_word_actions(data.word);
        };
        if (!View.prototype.on_lookup_word.__argnames__) Object.defineProperties(View.prototype.on_lookup_word, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.left_margin_clicked = function left_margin_clicked(event) {
            var self = this;
            var sd;
            if (event.button === 0) {
                [event.preventDefault(), event.stopPropagation()];
                sd = get_session_data();
                ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["next_screen"].concat([ρσ_desugar_kwargs({backwards: true, all_pages_on_screen: sd.get("paged_margin_clicks_scroll_by_screen")})]));
            }
            self.focus_iframe();
        };
        if (!View.prototype.left_margin_clicked.__argnames__) Object.defineProperties(View.prototype.left_margin_clicked, {
            __argnames__ : {value: ["event"]}
        });
        View.prototype.right_margin_clicked = function right_margin_clicked(event) {
            var self = this;
            var sd;
            if (event.button === 0) {
                [event.preventDefault(), event.stopPropagation()];
                sd = get_session_data();
                ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["next_screen"].concat([ρσ_desugar_kwargs({backwards: false, all_pages_on_screen: sd.get("paged_margin_clicks_scroll_by_screen")})]));
            }
            self.focus_iframe();
        };
        if (!View.prototype.right_margin_clicked.__argnames__) Object.defineProperties(View.prototype.right_margin_clicked, {
            __argnames__ : {value: ["event"]}
        });
        View.prototype.top_margin_clicked = function top_margin_clicked(event) {
            var self = this;
            if (event.button === 0) {
                [event.preventDefault(), event.stopPropagation()];
                self.show_chrome();
            } else {
                self.focus_iframe();
            }
        };
        if (!View.prototype.top_margin_clicked.__argnames__) Object.defineProperties(View.prototype.top_margin_clicked, {
            __argnames__ : {value: ["event"]}
        });
        View.prototype.bottom_margin_clicked = function bottom_margin_clicked(event) {
            var self = this;
            self.focus_iframe();
        };
        if (!View.prototype.bottom_margin_clicked.__argnames__) Object.defineProperties(View.prototype.bottom_margin_clicked, {
            __argnames__ : {value: ["event"]}
        });
        View.prototype.forward_gesture = function forward_gesture(gesture) {
            var self = this;
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["gesture_from_margin"].concat([ρσ_desugar_kwargs({gesture: gesture})]));
        };
        if (!View.prototype.forward_gesture.__argnames__) Object.defineProperties(View.prototype.forward_gesture, {
            __argnames__ : {value: ["gesture"]}
        });
        View.prototype.iframe_size = function iframe_size() {
            var self = this;
            var iframe, ρσ_unpack, l, r, w, t, b, h;
            iframe = self.iframe;
            ρσ_unpack = [document.getElementById("book-left-margin"), document.getElementById("book-right-margin")];
            l = ρσ_unpack[0];
            r = ρσ_unpack[1];
            w = r.offsetLeft - l.offsetLeft - iframe.offsetLeft;
            ρσ_unpack = [document.getElementById("book-top-margin"), document.getElementById("book-bottom-margin")];
            t = ρσ_unpack[0];
            b = ρσ_unpack[1];
            h = b.offsetTop - t.offsetTop - iframe.offsetTop;
            return [w, h];
        };
        View.prototype.on_request_size = function on_request_size(data) {
            var self = this;
            var ρσ_unpack, w, h;
            window.scrollTo(0, 0);
            ρσ_unpack = self.iframe_size();
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            w = ρσ_unpack[0];
            h = ρσ_unpack[1];
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["window_size"].concat([ρσ_desugar_kwargs({width: w, height: h})]));
        };
        if (!View.prototype.on_request_size.__argnames__) Object.defineProperties(View.prototype.on_request_size, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_print = function on_print(data) {
            var self = this;
            print(data.string);
        };
        if (!View.prototype.on_print.__argnames__) Object.defineProperties(View.prototype.on_print, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_human_scroll = function on_human_scroll(data) {
            var self = this;
            var name, length, amt_scrolled;
            if (data.scrolled_by_frac === null) {
                self.timers.reset_read_timer();
            } else {
                name = self.currently_showing.name;
                length = ρσ_exists.d((ρσ_expr_temp = self.book.manifest.files)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name]).length;
                if (length) {
                    amt_scrolled = data.scrolled_by_frac * length;
                    self.timers.on_human_scroll(amt_scrolled);
                }
            }
        };
        if (!View.prototype.on_human_scroll.__argnames__) Object.defineProperties(View.prototype.on_human_scroll, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_handle_keypress = function on_handle_keypress(data) {
            var self = this;
            self.handle_keypress(data.evt);
        };
        if (!View.prototype.on_handle_keypress.__argnames__) Object.defineProperties(View.prototype.on_handle_keypress, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.handle_keypress = function handle_keypress(evt) {
            var self = this;
            if (self.overlay.is_visible && evt.key === "Escape") {
                if (self.overlay.handle_escape()) {
                    if (evt.preventDefault) {
                        [evt.preventDefault(), evt.stopPropagation()];
                    }
                }
            }
        };
        if (!View.prototype.handle_keypress.__argnames__) Object.defineProperties(View.prototype.handle_keypress, {
            __argnames__ : {value: ["evt"]}
        });
        View.prototype.overlay_visibility_changed = function overlay_visibility_changed(visible) {
            var self = this;
            if (self.iframe_wrapper.send_message) {
                ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["set_forward_keypresses"].concat([ρσ_desugar_kwargs({forward: !!visible})]));
            }
            if (ui_operations.overlay_visibility_changed) {
                ui_operations.overlay_visibility_changed(visible);
            }
        };
        if (!View.prototype.overlay_visibility_changed.__argnames__) Object.defineProperties(View.prototype.overlay_visibility_changed, {
            __argnames__ : {value: ["visible"]}
        });
        View.prototype.on_handle_shortcut = function on_handle_shortcut(data) {
            var self = this;
            if (data.name === "back") {
                window.history.back();
            } else if (data.name === "forward") {
                window.history.forward();
            } else if (data.name === "show_chrome") {
                self.show_chrome();
            } else if (data.name === "toggle_toc") {
                ui_operations.toggle_toc();
            } else if (data.name === "toggle_bookmarks") {
                ui_operations.toggle_bookmarks();
            } else if (data.name === "toggle_inspector") {
                ui_operations.toggle_inspector();
            } else if (data.name === "toggle_lookup") {
                ui_operations.toggle_lookup();
            } else if (data.name === "toggle_paged_mode") {
                self.toggle_paged_mode();
            } else if (data.name === "quit") {
                ui_operations.quit();
            } else if (data.name === "start_search") {
                self.show_search();
            } else if (data.name === "next_match") {
                self.search_overlay.find_next();
            } else if (data.name === "previous_match") {
                self.search_overlay.find_previous();
            } else if (data.name === "increase_font_size") {
                self.bump_font_size((function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["increase"] = true;
                    return ρσ_d;
                }).call(this));
            } else if (data.name === "decrease_font_size") {
                self.bump_font_size((function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["increase"] = false;
                    return ρσ_d;
                }).call(this));
            } else if (data.name === "toggle_full_screen") {
                ui_operations.toggle_full_screen();
            } else if (data.name === "reload_book") {
                ui_operations.reload_book();
            } else if (data.name === "search_for_selection") {
                if (self.currently_showing.selected_text) {
                    self.search_overlay.set_text(self.currently_showing.selected_text);
                    self.search_overlay.find_next();
                }
            } else if (data.name === "next_section") {
                self.on_next_section((function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["forward"] = true;
                    return ρσ_d;
                }).call(this));
            } else if (data.name === "previous_section") {
                self.on_next_section((function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["forward"] = false;
                    return ρσ_d;
                }).call(this));
            }
        };
        if (!View.prototype.on_handle_shortcut.__argnames__) Object.defineProperties(View.prototype.on_handle_shortcut, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_selection_change = function on_selection_change(data) {
            var self = this;
            self.currently_showing.selected_text = data.text;
            if (ui_operations.selection_changed) {
                ui_operations.selection_changed(data.text);
            }
        };
        if (!View.prototype.on_selection_change.__argnames__) Object.defineProperties(View.prototype.on_selection_change, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.toggle_paged_mode = function toggle_paged_mode() {
            var self = this;
            var sd, mode, new_mode;
            sd = get_session_data();
            mode = sd.get("read_mode");
            new_mode = (mode === "paged") ? "flow" : "paged";
            sd.set("read_mode", new_mode);
            ui_operations.redisplay_book();
        };
        View.prototype.find = function find(text, backwards) {
            var self = this;
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["find"].concat([ρσ_desugar_kwargs({text: text, backwards: backwards, searched_in_spine: false})]));
        };
        if (!View.prototype.find.__argnames__) Object.defineProperties(View.prototype.find, {
            __argnames__ : {value: ["text", "backwards"]}
        });
        View.prototype.on_find_in_spine = function on_find_in_spine(data) {
            var self = this;
            var spine, idx, names, item_groups, i, items;
            if (data.searched_in_spine) {
                ρσ_interpolate_kwargs.call(this, warning_dialog, [_("Not found"), _("The text: <i>{}</i> was not found in this book").format(html_escape(data.text))].concat([ρσ_desugar_kwargs({on_close: function () {
                    self.search_overlay.show();
                }})]));
                return;
            }
            spine = self.book.manifest.spine;
            idx = spine.indexOf(self.currently_showing.name);
            if (idx < 0) {
                ρσ_interpolate_kwargs.call(this, error_dialog, [_("Missing file"), _("Could not search as the spine item {} is missing from the book").format(self.currently_showing.name)].concat([ρσ_desugar_kwargs({on_close: function () {
                    self.search_overlay.show();
                }})]));
                return;
            }
            names = [];
            item_groups = (data.backwards) ? ρσ_list_decorate([ range(idx - 1, -1, -1), range(spine.length - 1, idx, -1) ]) : ρσ_list_decorate([ range(idx + 1, spine.length), range(idx) ]);
            var ρσ_Iter0 = ρσ_Iterable(item_groups);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                items = ρσ_Iter0[ρσ_Index0];
                var ρσ_Iter1 = ρσ_Iterable(items);
                for (var ρσ_Index1 = 0; ρσ_Index1 < ρσ_Iter1.length; ρσ_Index1++) {
                    i = ρσ_Iter1[ρσ_Index1];
                    names.push(spine[(typeof i === "number" && i < 0) ? spine.length + i : i]);
                }
            }
            find_in_spine(names, self.book, data.text, (function() {
                var ρσ_anonfunc = function (found_in) {
                    if (found_in) {
                        ρσ_interpolate_kwargs.call(self, self.show_name, [found_in].concat([ρσ_desugar_kwargs({initial_position: (function(){
                            var ρσ_d = Object.create(null);
                            ρσ_d["type"] = "search";
                            ρσ_d["search_data"] = data;
                            ρσ_d["replace_history"] = true;
                            return ρσ_d;
                        }).call(this)})]));
                    } else {
                        ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["find"].concat([ρσ_desugar_kwargs({text: data.text, backwards: data.backwards, searched_in_spine: true})]));
                    }
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["found_in"]}
                });
                return ρσ_anonfunc;
            })());
        };
        if (!View.prototype.on_find_in_spine.__argnames__) Object.defineProperties(View.prototype.on_find_in_spine, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.bump_font_size = function bump_font_size(data) {
            var self = this;
            var delta;
            delta = (data.increase) ? 2 : -2;
            change_font_size_by(delta);
        };
        if (!View.prototype.bump_font_size.__argnames__) Object.defineProperties(View.prototype.bump_font_size, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_show_footnote = function on_show_footnote(data) {
            var self = this;
            self.show_content_popup();
            self.content_popup_overlay.show_footnote(data);
        };
        if (!View.prototype.on_show_footnote.__argnames__) Object.defineProperties(View.prototype.on_show_footnote, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.hide_overlays = function hide_overlays() {
            var self = this;
            self.overlay.hide();
            self.search_overlay.hide();
            self.content_popup_overlay.hide();
            self.focus_iframe();
        };
        View.prototype.focus_iframe = function focus_iframe() {
            var self = this;
            self.iframe.contentWindow.focus();
        };
        View.prototype.show_chrome = function show_chrome(data) {
            var self = this;
            var elements;
            self.show_chrome_counter += 1;
            elements = Object.create(null);
            if (data && data.elements) {
                elements = data.elements;
            }
            self.get_current_cfi("show-chrome-" + self.show_chrome_counter, self.do_show_chrome.bind(null, elements));
        };
        if (!View.prototype.show_chrome.__argnames__) Object.defineProperties(View.prototype.show_chrome, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.do_show_chrome = function do_show_chrome(elements, request_id, cfi_data) {
            var self = this;
            self.hide_overlays();
            self.update_cfi_data(cfi_data);
            self.overlay.show(elements);
        };
        if (!View.prototype.do_show_chrome.__argnames__) Object.defineProperties(View.prototype.do_show_chrome, {
            __argnames__ : {value: ["elements", "request_id", "cfi_data"]}
        });
        View.prototype.show_search = function show_search() {
            var self = this;
            self.hide_overlays();
            self.search_overlay.show();
        };
        View.prototype.show_content_popup = function show_content_popup() {
            var self = this;
            self.hide_overlays();
            self.content_popup_overlay.show();
        };
        View.prototype.set_margins = function set_margins() {
            var self = this;
            var no_margins, sd, margin_left, margin_right, margin_top, margin_bottom, max_text_height, th, extra, max_text_width, tw;
            no_margins = self.currently_showing.name === self.book.manifest.title_page_name;
            sd = get_session_data();
            margin_left = (no_margins) ? 0 : sd.get("margin_left");
            margin_right = (no_margins) ? 0 : sd.get("margin_right");
            margin_top = (no_margins) ? 0 : sd.get("margin_top");
            margin_bottom = (no_margins) ? 0 : sd.get("margin_bottom");
            max_text_height = sd.get("max_text_height");
            th = window.innerHeight - margin_top - margin_bottom;
            if (!no_margins && max_text_height > 100 && th > max_text_height) {
                extra = Math.floor((th - max_text_height) / 2);
                margin_top += extra;
                margin_bottom += extra;
            }
            max_text_width = sd.get("max_text_width");
            tw = window.innerWidth - margin_left - margin_right;
            if (!no_margins && max_text_width > 100 && tw > max_text_width) {
                extra = Math.floor((tw - max_text_width) / 2);
                margin_left += extra;
                margin_right += extra;
            }
            ρσ_interpolate_kwargs.call(this, set_css, [document.getElementById("book-top-margin")].concat([ρσ_desugar_kwargs({height: margin_top + "px"})]));
            ρσ_interpolate_kwargs.call(this, set_css, [document.getElementById("book-bottom-margin")].concat([ρσ_desugar_kwargs({height: margin_bottom + "px"})]));
            function side_margin(which, val) {
                var m;
                m = document.getElementById("book-{}-margin".format(which));
                if (which === "left") {
                    m.nextSibling.style.maxWidth = "calc(100vw - {}px)".format(margin_left + margin_right);
                }
                ρσ_interpolate_kwargs.call(this, set_css, [m].concat([ρσ_desugar_kwargs({width: val + "px"})]));
                val = min(val, 75);
                m.firstChild.style.width = val + "px";
                m.firstChild.style.height = val + "px";
            };
            if (!side_margin.__argnames__) Object.defineProperties(side_margin, {
                __argnames__ : {value: ["which", "val"]}
            });

            [side_margin("left", margin_left), side_margin("right", margin_right)];
        };
        View.prototype.on_iframe_ready = function on_iframe_ready(data) {
            var self = this;
            var ρσ_unpack;
            ρσ_unpack = self.iframe_size();
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            data.width = ρσ_unpack[0];
            data.height = ρσ_unpack[1];
            return self.do_pending_load;
        };
        if (!View.prototype.on_iframe_ready.__argnames__) Object.defineProperties(View.prototype.on_iframe_ready, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.do_pending_load = function do_pending_load() {
            var self = this;
            var data;
            if (self.pending_load) {
                data = self.pending_load;
                self.pending_load = null;
                self.show_spine_item_stage2(data);
            }
        };
        View.prototype.on_iframe_error = function on_iframe_error(data) {
            var self = this;
            ui_operations.show_error(data.title || _("There was an error processing the book"), data.msg, data.details);
        };
        if (!View.prototype.on_iframe_error.__argnames__) Object.defineProperties(View.prototype.on_iframe_error, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.get_color_scheme = function get_color_scheme(apply_to_margins) {
            var self = this;
            var ans, m, s, which, sd, bg_image;
            ans = resolve_color_scheme();
            self.current_color_scheme = ans;
            if (apply_to_margins) {
                var ρσ_Iter2 = ρσ_Iterable("left top right bottom".split(" "));
                for (var ρσ_Index2 = 0; ρσ_Index2 < ρσ_Iter2.length; ρσ_Index2++) {
                    which = ρσ_Iter2[ρσ_Index2];
                    m = document.getElementById("book-{}-margin".format(which));
                    s = m.style;
                    s.color = ans.foreground;
                    s.backgroundColor = ans.background;
                }
                sd = get_session_data();
                self.iframe.style.backgroundColor = ans.background || "white";
                bg_image = sd.get("background_image");
                if (bg_image) {
                    self.iframe.style.backgroundImage = (runtime.is_standalone_viewer) ? "url(" + ρσ_str.format("{}", READER_BACKGROUND_URL) + "?" + ρσ_str.format("{}", (new Date).getTime()) + ")" : "url(" + ρσ_str.format("{}", bg_image) + ")";
                } else {
                    self.iframe.style.backgroundImage = "none";
                }
                if (sd.get("background_image_style") === "scaled") {
                    self.iframe.style.backgroundSize = "100% 100%";
                    self.iframe.style.backgroundRepeat = "no-repeat";
                    self.iframe.style.backgroundAttachment = "scroll";
                    self.iframe.style.backgroundPosition = "center";
                } else {
                    self.iframe.style.backgroundSize = "auto";
                    self.iframe.style.backgroundRepeat = "repeat";
                    self.iframe.style.backgroundAttachment = "scroll";
                    self.iframe.style.backgroundPosition = "0 0";
                }
                m.parentNode.style.backgroundColor = ans.background;
                self.content_popup_overlay.apply_color_scheme(ans.background, ans.foreground);
                self.book_scrollbar.apply_color_scheme(ans);
                self.iframe.parentNode.parentNode.style.backgroundColor = ans.background;
            }
            return ans;
        };
        if (!View.prototype.get_color_scheme.__argnames__) Object.defineProperties(View.prototype.get_color_scheme, {
            __argnames__ : {value: ["apply_to_margins"]}
        });
        View.prototype.on_resize = function on_resize() {
            var self = this;
            var sd;
            if (self.book && self.currently_showing.name) {
                sd = get_session_data();
                if (sd.get("max_text_width") || sd.get("max_text_height")) {
                    self.set_margins();
                }
            }
        };
        View.prototype.show_loading_message = function show_loading_message(msg) {
            var self = this;
            self.overlay.show_loading_message(msg);
        };
        if (!View.prototype.show_loading_message.__argnames__) Object.defineProperties(View.prototype.show_loading_message, {
            __argnames__ : {value: ["msg"]}
        });
        View.prototype.show_loading = function show_loading() {
            var self = this;
            var msg;
            msg = (ρσ_expr_temp = _("Loading next section from <i>{title}</i>, please wait…"), ρσ_interpolate_kwargs.call(ρσ_expr_temp, ρσ_expr_temp.format, [ρσ_desugar_kwargs({title: self.book.metadata.title})]));
            if (self.show_loading_callback_timer !== null) {
                clearTimeout(self.show_loading_callback_timer);
            }
            self.show_loading_callback_timer = setTimeout(self.show_loading_message.bind(null, msg), 200);
        };
        View.prototype.hide_loading = function hide_loading() {
            var self = this;
            if (self.show_loading_callback_timer !== null) {
                clearTimeout(self.show_loading_callback_timer);
                self.show_loading_callback_timer = null;
            }
            self.overlay.hide_loading_message();
        };
        View.prototype.parse_cfi = function parse_cfi(encoded_cfi, book) {
            var self = this;
            var name, cfi, ρσ_unpack, snum, rest;
            name = cfi = null;
            if (encoded_cfi && encoded_cfi.startswith("epubcfi(/")) {
                cfi = encoded_cfi.slice(len("epubcfi(/"), -1);
                ρσ_unpack = ρσ_eslice(cfi.partition("/"), 2);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                snum = ρσ_unpack[0];
                rest = ρσ_unpack[1];
                try {
                    snum = int(snum);
                } catch (ρσ_Exception) {
                    ρσ_last_exception = ρσ_Exception;
                    if (ρσ_Exception instanceof Error) {
                        print("Invalid spine number in CFI:", snum);
                    } else {
                        throw ρσ_Exception;
                    }
                }
                if (typeof snum === "number") {
                    name = (ρσ_expr_temp = book.manifest.spine)[ρσ_bound_index(Math.floor(int(snum) / 2) - 1, ρσ_expr_temp)] || name;
                    cfi = "/" + rest;
                }
            }
            return [name, cfi];
        };
        if (!View.prototype.parse_cfi.__argnames__) Object.defineProperties(View.prototype.parse_cfi, {
            __argnames__ : {value: ["encoded_cfi", "book"]}
        });
        View.prototype.display_book = function display_book(book, initial_cfi, initial_toc_node) {
            var self = this;
            var is_current_book, pos, unkey, name, cfi, q, ρσ_unpack, cfiname, internal_cfi, navigated, sd, c;
            self.hide_overlays();
            self.iframe.focus();
            is_current_book = self.book && (self.book.key === book.key || typeof self.book.key === "object" && ρσ_equals(self.book.key, book.key));
            if (!is_current_book) {
                self.iframe_wrapper.reset();
                self.content_popup_overlay.iframe_wrapper.reset();
                self.loaded_resources = Object.create(null);
                self.content_popup_overlay.loaded_resources = Object.create(null);
                self.timers.start_book(book);
            }
            self.book = current_book.book = book;
            if (runtime.is_standalone_viewer) {
                add_book_to_recently_viewed(book);
            }
            if (ui_operations.update_last_read_time) {
                ui_operations.update_last_read_time(book);
            }
            pos = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["replace_history"] = true;
                return ρσ_d;
            }).call(this);
            unkey = username_key(get_interface_data().username);
            name = book.manifest.spine[0];
            cfi = null;
            if (initial_cfi && initial_cfi.startswith("epubcfi(/")) {
                cfi = initial_cfi;
            } else {
                q = parse_url_params();
                if (q.bookpos && q.bookpos.startswith("epubcfi(/")) {
                    cfi = q.bookpos;
                } else if (book.last_read_position && (ρσ_expr_temp = book.last_read_position)[(typeof unkey === "number" && unkey < 0) ? ρσ_expr_temp.length + unkey : unkey]) {
                    cfi = (ρσ_expr_temp = book.last_read_position)[(typeof unkey === "number" && unkey < 0) ? ρσ_expr_temp.length + unkey : unkey];
                }
            }
            ρσ_unpack = self.parse_cfi(cfi, book);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            cfiname = ρσ_unpack[0];
            internal_cfi = ρσ_unpack[1];
            if (cfiname && internal_cfi) {
                name = cfiname;
                ρσ_unpack = ["cfi", internal_cfi];
                pos.type = ρσ_unpack[0];
                pos.cfi = ρσ_unpack[1];
            }
            navigated = false;
            if (typeof initial_toc_node === "number") {
                navigated = self.goto_toc_node(initial_toc_node);
            }
            if (!navigated) {
                ρσ_interpolate_kwargs.call(self, self.show_name, [name].concat([ρσ_desugar_kwargs({initial_position: pos})]));
            }
            sd = get_session_data();
            c = sd.get("controls_help_shown_count", 0);
            if (c < 2) {
                show_controls_help();
                sd.set("controls_help_shown_count", c + 1);
            }
        };
        if (!View.prototype.display_book.__argnames__) Object.defineProperties(View.prototype.display_book, {
            __argnames__ : {value: ["book", "initial_cfi", "initial_toc_node"]}
        });
        View.prototype.redisplay_book = function redisplay_book() {
            var self = this;
            var sd;
            sd = get_session_data();
            self.keyboard_shortcut_map = create_shortcut_map(sd.get("keyboard_shortcuts"));
            self.book_scrollbar.apply_visibility();
            self.display_book(self.book);
        };
        View.prototype.iframe_settings = function iframe_settings(name) {
            var self = this;
            var sd, bg_image_fade, cs, fade, rgba;
            sd = get_session_data();
            bg_image_fade = "transparent";
            cs = self.get_color_scheme(true);
            fade = int(sd.get("background_image_fade"));
            if (self.iframe.style.backgroundImage !== "none" && fade > 0) {
                rgba = cached_color_to_rgba(cs.background);
                bg_image_fade = "rgba(" + ρσ_str.format("{}", rgba[0]) + ", " + ρσ_str.format("{}", rgba[1]) + ", " + ρσ_str.format("{}", rgba[2]) + ", " + ρσ_str.format("{}", fade / 100) + ")";
            }
            return (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["margin_left"] = (name === self.book.manifest.title_page_name) ? 0 : sd.get("margin_left");
                ρσ_d["margin_right"] = (name === self.book.manifest.title_page_name) ? 0 : sd.get("margin_right");
                ρσ_d["read_mode"] = sd.get("read_mode");
                ρσ_d["columns_per_screen"] = sd.get("columns_per_screen");
                ρσ_d["color_scheme"] = cs;
                ρσ_d["bg_image_fade"] = bg_image_fade;
                ρσ_d["base_font_size"] = sd.get("base_font_size");
                ρσ_d["user_stylesheet"] = sd.get("user_stylesheet");
                ρσ_d["keyboard_shortcuts"] = sd.get("keyboard_shortcuts");
                ρσ_d["hide_tooltips"] = sd.get("hide_tooltips");
                ρσ_d["cover_preserve_aspect_ratio"] = sd.get("cover_preserve_aspect_ratio");
                ρσ_d["paged_wheel_scrolls_by_screen"] = sd.get("paged_wheel_scrolls_by_screen");
                return ρσ_d;
            }).call(this);
        };
        if (!View.prototype.iframe_settings.__argnames__) Object.defineProperties(View.prototype.iframe_settings, {
            __argnames__ : {value: ["name"]}
        });
        View.prototype.show_name = function show_name() {
            var self = this;
            var name = ( 0 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true) ? undefined : arguments[0];
            var initial_position = (arguments[1] === undefined || ( 1 === arguments.length-1 && arguments[arguments.length-1] !== null && typeof arguments[arguments.length-1] === "object" && arguments[arguments.length-1] [ρσ_kwargs_symbol] === true)) ? show_name.__defaults__.initial_position : arguments[1];
            var ρσ_kwargs_obj = arguments[arguments.length-1];
            if (ρσ_kwargs_obj === null || typeof ρσ_kwargs_obj !== "object" || ρσ_kwargs_obj [ρσ_kwargs_symbol] !== true) ρσ_kwargs_obj = {};
            if (Object.prototype.hasOwnProperty.call(ρσ_kwargs_obj, "initial_position")){
                initial_position = ρσ_kwargs_obj.initial_position;
            }
            var spine, idx;
            if (self.currently_showing.loading) {
                return;
            }
            self.processing_spine_item_display = false;
            initial_position = initial_position || (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["replace_history"] = false;
                return ρσ_d;
            }).call(this);
            self.currently_showing = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["name"] = name;
                ρσ_d["settings"] = self.iframe_settings(name);
                ρσ_d["initial_position"] = initial_position;
                ρσ_d["loading"] = true;
                return ρσ_d;
            }).call(this);
            self.show_loading();
            spine = self.book.manifest.spine;
            idx = spine.indexOf(name);
            set_current_spine_item(name);
            if (idx > -1) {
                self.currently_showing.bookpos = "epubcfi(/{})".format(2 * (idx + 1));
            }
            self.set_margins();
            self.load_doc(name, self.show_spine_item);
        };
        if (!View.prototype.show_name.__defaults__) Object.defineProperties(View.prototype.show_name, {
            __defaults__ : {value: {initial_position:null}},
            __handles_kwarg_interpolation__ : {value: true},
            __argnames__ : {value: ["name", "initial_position"]}
        });
        View.prototype.load_doc = function load_doc(name, done_callback) {
            var self = this;
            function cb(resource_data) {
                self.loaded_resources = resource_data;
                done_callback(resource_data);
            };
            if (!cb.__argnames__) Object.defineProperties(cb, {
                __argnames__ : {value: ["resource_data"]}
            });

            load_resources(self.book, name, self.loaded_resources, cb);
        };
        if (!View.prototype.load_doc.__argnames__) Object.defineProperties(View.prototype.load_doc, {
            __argnames__ : {value: ["name", "done_callback"]}
        });
        View.prototype.goto_doc_boundary = function goto_doc_boundary(start) {
            var self = this;
            var name;
            name = (ρσ_expr_temp = self.book.manifest.spine)[ρσ_bound_index((start) ? 0 : self.book.manifest.spine.length - 1, ρσ_expr_temp)];
            ρσ_interpolate_kwargs.call(self, self.show_name, [name].concat([ρσ_desugar_kwargs({initial_position: (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["type"] = "frac";
                ρσ_d["frac"] = (start) ? 0 : 1;
                ρσ_d["replace_history"] = false;
                return ρσ_d;
            }).call(this)})]));
        };
        if (!View.prototype.goto_doc_boundary.__argnames__) Object.defineProperties(View.prototype.goto_doc_boundary, {
            __argnames__ : {value: ["start"]}
        });
        View.prototype.goto_frac = function goto_frac(frac) {
            var self = this;
            var chapter_start_page, total_length, page, chapter_frac, chapter_name, chapter_length, chapter_end_page, num_pages, name;
            if (!self.book || !self.book.manifest) {
                return;
            }
            chapter_start_page = 0;
            total_length = self.book.manifest.spine_length;
            page = total_length * frac;
            chapter_frac = 0;
            chapter_name = null;
            var ρσ_Iter3 = ρσ_Iterable(self.book.manifest.spine);
            for (var ρσ_Index3 = 0; ρσ_Index3 < ρσ_Iter3.length; ρσ_Index3++) {
                name = ρσ_Iter3[ρσ_Index3];
                chapter_length = ρσ_exists.d((ρσ_expr_temp = self.book.manifest.files)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name]).length || 0;
                chapter_end_page = chapter_start_page + chapter_length;
                if (chapter_start_page <= page && page <= chapter_end_page) {
                    num_pages = chapter_end_page - chapter_start_page - 1;
                    if (num_pages > 0) {
                        chapter_frac = (page - chapter_start_page) / num_pages;
                    } else {
                        chapter_frac = 0;
                    }
                    chapter_name = name;
                    break;
                }
                chapter_start_page = chapter_end_page;
            }
            if (!chapter_name) {
                chapter_name = (ρσ_expr_temp = self.book.manifest.spine)[ρσ_expr_temp.length-1];
            }
            chapter_frac = max(0, min(chapter_frac, 1));
            if (self.currently_showing.name === chapter_name) {
                ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["scroll_to_frac"].concat([ρσ_desugar_kwargs({frac: chapter_frac})]));
            } else {
                ρσ_interpolate_kwargs.call(self, self.show_name, [chapter_name].concat([ρσ_desugar_kwargs({initial_position: (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["type"] = "frac";
                    ρσ_d["frac"] = chapter_frac;
                    ρσ_d["replace_history"] = true;
                    return ρσ_d;
                }).call(this)})]));
            }
        };
        if (!View.prototype.goto_frac.__argnames__) Object.defineProperties(View.prototype.goto_frac, {
            __argnames__ : {value: ["frac"]}
        });
        View.prototype.on_scroll_to_anchor = function on_scroll_to_anchor(data) {
            var self = this;
            ρσ_interpolate_kwargs.call(self, self.show_name, [data.name].concat([ρσ_desugar_kwargs({initial_position: (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["type"] = "anchor";
                ρσ_d["anchor"] = data.frag;
                ρσ_d["replace_history"] = false;
                return ρσ_d;
            }).call(this)})]));
        };
        if (!View.prototype.on_scroll_to_anchor.__argnames__) Object.defineProperties(View.prototype.on_scroll_to_anchor, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.goto_bookpos = function goto_bookpos(bookpos) {
            var self = this;
            var ρσ_unpack, cfiname, internal_cfi, pos, name;
            ρσ_unpack = self.parse_cfi(bookpos, self.book);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            cfiname = ρσ_unpack[0];
            internal_cfi = ρσ_unpack[1];
            if (cfiname && internal_cfi) {
                pos = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["replace_history"] = true;
                    return ρσ_d;
                }).call(this);
                name = cfiname;
                ρσ_unpack = ["cfi", internal_cfi];
                pos.type = ρσ_unpack[0];
                pos.cfi = ρσ_unpack[1];
                ρσ_interpolate_kwargs.call(self, self.show_name, [name].concat([ρσ_desugar_kwargs({initial_position: pos})]));
                return true;
            }
            return false;
        };
        if (!View.prototype.goto_bookpos.__argnames__) Object.defineProperties(View.prototype.goto_bookpos, {
            __argnames__ : {value: ["bookpos"]}
        });
        View.prototype.goto_named_destination = function goto_named_destination(name, frag) {
            var self = this;
            var spine, idx;
            if (self.currently_showing.name === name) {
                ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["scroll_to_anchor"].concat([ρσ_desugar_kwargs({frag: frag})]));
            } else {
                spine = self.book.manifest.spine;
                idx = spine.indexOf(name);
                if (idx === -1) {
                    ρσ_interpolate_kwargs.call(this, error_dialog, [_("Destination does not exist"), _("The file {} does not exist in this book").format(name)].concat([ρσ_desugar_kwargs({on_close: function () {
                        ui_operations.focus_iframe();
                    }})]));
                    return false;
                }
                ρσ_interpolate_kwargs.call(self, self.show_name, [name].concat([ρσ_desugar_kwargs({initial_position: (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["type"] = "anchor";
                    ρσ_d["anchor"] = frag;
                    ρσ_d["replace_history"] = false;
                    return ρσ_d;
                }).call(this)})]));
            }
            return true;
        };
        if (!View.prototype.goto_named_destination.__argnames__) Object.defineProperties(View.prototype.goto_named_destination, {
            __argnames__ : {value: ["name", "frag"]}
        });
        View.prototype.goto_toc_node = function goto_toc_node(node_id) {
            var self = this;
            var toc, found;
            toc = self.book.manifest.toc;
            found = false;
            function process_node(x) {
                var c;
                if (x.id === node_id) {
                    self.goto_named_destination(x.dest || "", x.frag || "");
                    found = true;
                    return;
                }
                var ρσ_Iter4 = ρσ_Iterable(x.children);
                for (var ρσ_Index4 = 0; ρσ_Index4 < ρσ_Iter4.length; ρσ_Index4++) {
                    c = ρσ_Iter4[ρσ_Index4];
                    process_node(c);
                }
            };
            if (!process_node.__argnames__) Object.defineProperties(process_node, {
                __argnames__ : {value: ["x"]}
            });

            if (toc) {
                process_node(toc);
            }
            return found;
        };
        if (!View.prototype.goto_toc_node.__argnames__) Object.defineProperties(View.prototype.goto_toc_node, {
            __argnames__ : {value: ["node_id"]}
        });
        View.prototype.on_next_spine_item = function on_next_spine_item(data) {
            var self = this;
            var spine, idx;
            spine = self.book.manifest.spine;
            idx = spine.indexOf(self.currently_showing.name);
            if (data.previous) {
                if (idx === 0) {
                    return;
                }
                idx = min(spine.length - 1, max(idx - 1, 0));
                ρσ_interpolate_kwargs.call(self, self.show_name, [spine[(typeof idx === "number" && idx < 0) ? spine.length + idx : idx]].concat([ρσ_desugar_kwargs({initial_position: (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["type"] = "frac";
                    ρσ_d["frac"] = 1;
                    ρσ_d["replace_history"] = true;
                    return ρσ_d;
                }).call(this)})]));
            } else {
                if (idx === spine.length - 1) {
                    return;
                }
                idx = max(0, min(spine.length - 1, idx + 1));
                ρσ_interpolate_kwargs.call(self, self.show_name, [spine[(typeof idx === "number" && idx < 0) ? spine.length + idx : idx]].concat([ρσ_desugar_kwargs({initial_position: (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["type"] = "frac";
                    ρσ_d["frac"] = 0;
                    ρσ_d["replace_history"] = true;
                    return ρσ_d;
                }).call(this)})]));
            }
        };
        if (!View.prototype.on_next_spine_item.__argnames__) Object.defineProperties(View.prototype.on_next_spine_item, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_next_section = function on_next_section(data) {
            var self = this;
            var toc_node;
            toc_node = get_next_section(data.forward);
            if (toc_node) {
                self.goto_named_destination(toc_node.dest, toc_node.frag);
            }
        };
        if (!View.prototype.on_next_section.__argnames__) Object.defineProperties(View.prototype.on_next_section, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.get_current_cfi = function get_current_cfi(request_id, callback) {
            var self = this;
            (ρσ_expr_temp = self.report_cfi_callbacks)[(typeof request_id === "number" && request_id < 0) ? ρσ_expr_temp.length + request_id : request_id] = callback;
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["get_current_cfi"].concat([ρσ_desugar_kwargs({request_id: request_id})]));
        };
        if (!View.prototype.get_current_cfi.__argnames__) Object.defineProperties(View.prototype.get_current_cfi, {
            __argnames__ : {value: ["request_id", "callback"]}
        });
        View.prototype.update_cfi_data = function update_cfi_data(data) {
            var self = this;
            var username, unkey;
            self.currently_showing.bookpos = data.cfi;
            self.currently_showing.selected_text = data.selected_text;
            username = get_interface_data().username;
            unkey = username_key(username);
            if (!self.book.last_read_position) {
                self.book.last_read_position = Object.create(null);
            }
            (ρσ_expr_temp = self.book.last_read_position)[(typeof unkey === "number" && unkey < 0) ? ρσ_expr_temp.length + unkey : unkey] = data.cfi;
            self.set_progress_frac(data.progress_frac, data.file_progress_frac);
            self.update_header_footer();
            if (ui_operations.update_last_read_time) {
                ui_operations.update_last_read_time(self.book);
            }
            return username;
        };
        if (!View.prototype.update_cfi_data.__argnames__) Object.defineProperties(View.prototype.update_cfi_data, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_report_cfi = function on_report_cfi(data) {
            var self = this;
            var cb;
            cb = (ρσ_expr_temp = self.report_cfi_callbacks)[ρσ_bound_index(data.request_id, ρσ_expr_temp)];
            if (cb) {
                cb(data.request_id, (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["cfi"] = data.cfi;
                    ρσ_d["progress_frac"] = data.progress_frac;
                    ρσ_d["file_progress_frac"] = data.file_progress_frac;
                    ρσ_d["selected_text"] = data.selected_text;
                    return ρσ_d;
                }).call(this));
                delete self.report_cfi_callbacks[data.request_id];
            }
        };
        if (!View.prototype.on_report_cfi.__argnames__) Object.defineProperties(View.prototype.on_report_cfi, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_update_progress_frac = function on_update_progress_frac(data) {
            var self = this;
            self.set_progress_frac(data.progress_frac, data.file_progress_frac);
            self.update_header_footer();
        };
        if (!View.prototype.on_update_progress_frac.__argnames__) Object.defineProperties(View.prototype.on_update_progress_frac, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.on_update_cfi = function on_update_cfi(data) {
            var self = this;
            var overlay_shown, username, key, lrd;
            overlay_shown = !self.processing_spine_item_display && self.overlay.is_visible;
            if (overlay_shown || self.search_overlay.is_visible || self.content_popup_overlay.is_visible) {
                return;
            }
            username = self.update_cfi_data(data);
            ui_operations.update_url_state(data.replace_history);
            if (username) {
                key = self.book.key;
                lrd = (function(){
                    var ρσ_d = Object.create(null);
                    ρσ_d["device"] = get_device_uuid();
                    ρσ_d["cfi"] = data.cfi;
                    ρσ_d["pos_frac"] = data.progress_frac;
                    return ρσ_d;
                }).call(this);
                ajax_send(ρσ_interpolate_kwargs.call("book-set-last-read-position/{library_id}/{book_id}/{fmt}", "book-set-last-read-position/{library_id}/{book_id}/{fmt}".format, [ρσ_desugar_kwargs({library_id: key[0], book_id: key[1], fmt: key[2]})]), lrd, (function() {
                    var ρσ_anonfunc = function (end_type, xhr, ev) {
                        if (end_type !== "load") {
                            print("Failed to update last read position, AJAX call did not succeed");
                        }
                    };
                    if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                        __argnames__ : {value: ["end_type", "xhr", "ev"]}
                    });
                    return ρσ_anonfunc;
                })());
            }
        };
        if (!View.prototype.on_update_cfi.__argnames__) Object.defineProperties(View.prototype.on_update_cfi, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.update_header_footer = function update_header_footer() {
            var self = this;
            var sd, has_clock, book_length, name, chapter_length, pos, book_time, chapter_time, div;
            sd = get_session_data();
            has_clock = false;
            if (ρσ_exists.d(self.book).manifest) {
                book_length = self.book.manifest.spine_length || 0;
                name = self.currently_showing.name;
                chapter_length = ρσ_exists.d((ρσ_expr_temp = self.book.manifest.files)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name]).length || 0;
            } else {
                book_length = chapter_length = 0;
            }
            pos = (function(){
                var ρσ_d = Object.create(null);
                ρσ_d["current_progress_frac"] = self.current_progress_frac;
                ρσ_d["book_length"] = book_length;
                ρσ_d["chapter_length"] = chapter_length;
                ρσ_d["current_file_progress_frac"] = self.current_file_progress_frac;
                return ρσ_d;
            }).call(this);
            book_length *= max(0, 1 - self.current_progress_frac);
            chapter_length *= max(0, 1 - self.current_file_progress_frac);
            book_time = self.timers.time_for(book_length);
            chapter_time = self.timers.time_for(chapter_length);
            function render_template(div, sz_attr, name) {
                var mi, ρσ_unpack, texta, hca, textb, hcb, textc, hcc, c;
                if (sd.get(sz_attr, 20) > 5) {
                    mi = self.book.metadata;
                    ρσ_unpack = render_head_foot(div.firstChild, name, "left", self.current_progress_frac, mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    texta = ρσ_unpack[0];
                    hca = ρσ_unpack[1];
                    ρσ_unpack = render_head_foot(div.firstChild.nextSibling, name, "middle", self.current_progress_frac, mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    textb = ρσ_unpack[0];
                    hcb = ρσ_unpack[1];
                    ρσ_unpack = render_head_foot(div.lastChild, name, "right", self.current_progress_frac, mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos);
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
                    textc = ρσ_unpack[0];
                    hcc = ρσ_unpack[1];
                    has_clock = hca || hcb || hcc;
                    if (textc && !textb && !texta) {
                        div.firstChild.style.display = "block";
                        div.firstChild.nextSibling.style.display = "block";
                    } else if (!texta && !textc && textb) {
                        div.firstChild.style.display = "block";
                        div.lastChild.style.display = "block";
                    }
                } else {
                    var ρσ_Iter5 = ρσ_Iterable(div.childNodes);
                    for (var ρσ_Index5 = 0; ρσ_Index5 < ρσ_Iter5.length; ρσ_Index5++) {
                        c = ρσ_Iter5[ρσ_Index5];
                        c.style.display = "none";
                    }
                }
            };
            if (!render_template.__argnames__) Object.defineProperties(render_template, {
                __argnames__ : {value: ["div", "sz_attr", "name"]}
            });

            div = document.getElementById("book-bottom-margin");
            if (div) {
                render_template(div, "margin_bottom", "footer");
            }
            div = document.getElementById("book-top-margin");
            if (div) {
                render_template(div, "margin_top", "header");
            }
            if (has_clock) {
                if (!self.timer_ids.clock) {
                    self.timer_ids.clock = window.setInterval(self.update_header_footer, 6e4);
                }
            } else {
                if (self.timer_ids.clock) {
                    window.clearInterval(self.timer_ids.clock);
                    self.timer_ids.clock = 0;
                }
            }
        };
        View.prototype.on_update_toc_position = function on_update_toc_position(data) {
            var self = this;
            var ρσ_unpack;
            update_visible_toc_nodes(data.visible_anchors);
            ρσ_unpack = get_current_toc_nodes();
ρσ_unpack = ρσ_unpack_asarray(2, ρσ_unpack);
            self.current_toc_node = ρσ_unpack[0];
            self.current_toc_toplevel_node = ρσ_unpack[1];
            if (runtime.is_standalone_viewer) {
                ui_operations.update_current_toc_nodes(ρσ_exists.d(self.current_toc_node).id, ρσ_exists.d(self.current_toc_toplevel_node).id);
            }
            self.update_header_footer();
        };
        if (!View.prototype.on_update_toc_position.__argnames__) Object.defineProperties(View.prototype.on_update_toc_position, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.show_spine_item = function show_spine_item(resource_data) {
            var self = this;
            self.pending_load = resource_data;
            if (self.iframe_wrapper.ready) {
                self.do_pending_load();
            } else {
                self.iframe_wrapper.init();
            }
        };
        if (!View.prototype.show_spine_item.__argnames__) Object.defineProperties(View.prototype.show_spine_item, {
            __argnames__ : {value: ["resource_data"]}
        });
        View.prototype.show_spine_item_stage2 = function show_spine_item_stage2(resource_data) {
            var self = this;
            self.currently_showing.loading = false;
            self.processing_spine_item_display = true;
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_unencrypted_message, ["display"].concat([ρσ_desugar_kwargs({resource_data: resource_data, book: self.book, name: self.currently_showing.name, initial_position: self.currently_showing.initial_position, settings: self.currently_showing.settings, is_titlepage: self.currently_showing.name === self.book.manifest.title_page_name})]));
        };
        if (!View.prototype.show_spine_item_stage2.__argnames__) Object.defineProperties(View.prototype.show_spine_item_stage2, {
            __argnames__ : {value: ["resource_data"]}
        });
        View.prototype.on_content_loaded = function on_content_loaded(data) {
            var self = this;
            self.processing_spine_item_display = false;
            self.hide_loading();
            self.set_progress_frac(data.progress_frac, data.file_progress_frac);
            self.update_header_footer();
            window.scrollTo(0, 0);
        };
        if (!View.prototype.on_content_loaded.__argnames__) Object.defineProperties(View.prototype.on_content_loaded, {
            __argnames__ : {value: ["data"]}
        });
        View.prototype.set_progress_frac = function set_progress_frac(progress_frac, file_progress_frac) {
            var self = this;
            self.current_progress_frac = progress_frac || 0;
            self.current_file_progress_frac = file_progress_frac || 0;
            self.book_scrollbar.sync_to_contents(self.current_progress_frac);
        };
        if (!View.prototype.set_progress_frac.__argnames__) Object.defineProperties(View.prototype.set_progress_frac, {
            __argnames__ : {value: ["progress_frac", "file_progress_frac"]}
        });
        View.prototype.update_font_size = function update_font_size() {
            var self = this;
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["change_font_size"].concat([ρσ_desugar_kwargs({base_font_size: get_session_data().get("base_font_size")})]));
        };
        View.prototype.update_color_scheme = function update_color_scheme() {
            var self = this;
            var cs;
            cs = self.get_color_scheme(true);
            ρσ_interpolate_kwargs.call(self.iframe_wrapper, self.iframe_wrapper.send_message, ["change_color_scheme"].concat([ρσ_desugar_kwargs({color_scheme: cs})]));
        };
        View.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        View.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(View.prototype, "__bases__", {value: []});
        

        ρσ_modules["read_book.view"].show_controls_help = show_controls_help;
        ρσ_modules["read_book.view"].margin_elem = margin_elem;
        ρσ_modules["read_book.view"].View = View;
    })();

    (function(){

        var __name__ = "__main__";


        var book, view, TRANSLATIONS_DATA, div;
        var traceback = ρσ_modules.traceback;

        var E = ρσ_modules.elementmaker.E;

        var _ = ρσ_modules.gettext.gettext;
        var install = ρσ_modules.gettext.install;

        var initialize = ρσ_modules.initialize;

        var ajax = ρσ_modules.ajax.ajax;

        var set_session_data = ρσ_modules["book_list.globals"].set_session_data;

        var library_data = ρσ_modules["book_list.library_data"].library_data;

        var get_color = ρσ_modules["book_list.theme"].get_color;

        var get_widget_css = ρσ_modules.dom.get_widget_css;
        var set_css = ρσ_modules.dom.set_css;

        var create_modal_container = ρσ_modules.modals.create_modal_container;
        var error_dialog = ρσ_modules.modals.error_dialog;

        var from_python = ρσ_modules.qt.from_python;
        var to_python = ρσ_modules.qt.to_python;

        var new_book = ρσ_modules["read_book.db"].new_book;

        var footnotes_main = ρσ_modules["read_book.footnotes"].main;

        var runtime = ρσ_modules["read_book.globals"].runtime;
        var ui_operations = ρσ_modules["read_book.globals"].ui_operations;

        var iframe_main = ρσ_modules["read_book.iframe"].main;

        var add_standalone_viewer_shortcuts = ρσ_modules["read_book.shortcuts"].add_standalone_viewer_shortcuts;

        var View = ρσ_modules["read_book.view"].View;

        var session_defaults = ρσ_modules.session.session_defaults;

        var encode_query_with_path = ρσ_modules.utils.encode_query_with_path;
        var parse_url_params = ρσ_modules.utils.parse_url_params;

        var FAKE_HOST = ρσ_modules["viewer.constants"].FAKE_HOST;
        var FAKE_PROTOCOL = ρσ_modules["viewer.constants"].FAKE_PROTOCOL;
        var READER_BACKGROUND_URL = ρσ_modules["viewer.constants"].READER_BACKGROUND_URL;

        runtime.is_standalone_viewer = true;
        runtime.FAKE_HOST = FAKE_HOST;
        runtime.FAKE_PROTOCOL = FAKE_PROTOCOL;
        add_standalone_viewer_shortcuts();
        book = null;
        view = null;
        function file_received(name, file_data, proceed, end_type, xhr, ev) {
            var result;
            if (end_type === "abort") {
                return;
            }
            if (end_type !== "load") {
                show_error(_("Failed to load file from book"), _("Could not load the file: {} with error: {}").format(name, xhr.error_html));
                return;
            }
            if (!xhr.responseType || xhr.responseType === "text") {
                result = xhr.responseText;
            } else if (xhr.responseType === "blob") {
                result = xhr.response;
            } else {
                show_error(_("Failed to load file from book"), _("Could not load the file: {} unknown response type: {}").format(name, xhr.responseType));
                return;
            }
            proceed(result, name, file_data.mimetype, book);
        };
        if (!file_received.__argnames__) Object.defineProperties(file_received, {
            __argnames__ : {value: ["name", "file_data", "proceed", "end_type", "xhr", "ev"]}
        });

        function get_file(book, name, proceed) {
            var entry, xhr;
            entry = (ρσ_expr_temp = book.manifest.files)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name];
            xhr = ρσ_interpolate_kwargs.call(this, ajax, ["book/" + name, file_received.bind(null, name, entry, proceed)].concat([ρσ_desugar_kwargs({ok_code: 0})]));
            if (entry.is_html || entry.mimetype.startswith("text/") || entry.mimetype === "application/javascript") {
                xhr.responseType = "text";
            } else {
                xhr.responseType = "blob";
            }
            xhr.send();
        };
        if (!get_file.__argnames__) Object.defineProperties(get_file, {
            __argnames__ : {value: ["book", "name", "proceed"]}
        });

        function mathjax_file_received(name, proceed, end_type, xhr, ev) {
            var result;
            if (end_type === "abort") {
                return;
            }
            if (end_type !== "load") {
                show_error(_("Failed to load MathJax file"), _("Could not load the file: {} with error: {}").format(name, xhr.error_html));
                return;
            }
            if (!xhr.responseType || xhr.responseType === "text") {
                result = xhr.responseText;
            } else if (xhr.responseType === "blob" || xhr.responseType === "json") {
                result = xhr.response;
            } else {
                show_error(_("Failed to load MathJax file"), _("Could not load the file: {} unknown response type: {}").format(name, xhr.responseType));
                return;
            }
            if (name === "manifest.json") {
                get_mathjax_files.manifest = result;
                get_mathjax_files_stage2.files_to_get = list(Object.keys(result));
                get_mathjax_files_stage2.file_data = Object.create(null);
                get_mathjax_files_stage2(proceed);
                return;
            }
            (ρσ_expr_temp = get_mathjax_files_stage2.file_data)[(typeof name === "number" && name < 0) ? ρσ_expr_temp.length + name : name] = result;
            get_mathjax_files_stage2.files_to_get.remove(name);
            if (!get_mathjax_files_stage2.files_to_get.length) {
                proceed(get_mathjax_files_stage2.file_data);
            }
        };
        if (!mathjax_file_received.__argnames__) Object.defineProperties(mathjax_file_received, {
            __argnames__ : {value: ["name", "proceed", "end_type", "xhr", "ev"]}
        });

        function get_mathjax_manifest(proceed) {
            var xhr;
            xhr = ρσ_interpolate_kwargs.call(this, ajax, ["mathjax/manifest.json", mathjax_file_received.bind(null, "manifest.json", proceed)].concat([ρσ_desugar_kwargs({ok_code: 0})]));
            xhr.responseType = "json";
            xhr.send();
        };
        if (!get_mathjax_manifest.__argnames__) Object.defineProperties(get_mathjax_manifest, {
            __argnames__ : {value: ["proceed"]}
        });

        function get_mathjax_files_stage2(proceed) {
            var xhr, filename;
            if (!get_mathjax_files_stage2.files_to_get.length) {
                proceed(get_mathjax_files_stage2.file_data);
                return;
            }
            var ρσ_Iter0 = ρσ_Iterable(get_mathjax_files_stage2.files_to_get);
            for (var ρσ_Index0 = 0; ρσ_Index0 < ρσ_Iter0.length; ρσ_Index0++) {
                filename = ρσ_Iter0[ρσ_Index0];
                xhr = ρσ_interpolate_kwargs.call(this, ajax, ["mathjax/" + ρσ_str.format("{}", filename) + "", mathjax_file_received.bind(null, filename, proceed)].concat([ρσ_desugar_kwargs({ok_code: 0})]));
                xhr.responseType = "blob";
                xhr.send();
            }
        };
        if (!get_mathjax_files_stage2.__argnames__) Object.defineProperties(get_mathjax_files_stage2, {
            __argnames__ : {value: ["proceed"]}
        });

        function get_mathjax_files(proceed) {
            if (!get_mathjax_files.manifest) {
                get_mathjax_manifest(proceed);
            } else {
                get_mathjax_files_stage2(proceed);
            }
        };
        if (!get_mathjax_files.__argnames__) Object.defineProperties(get_mathjax_files, {
            __argnames__ : {value: ["proceed"]}
        });

        function update_url_state(replace) {
            var bookpos, query;
            if (view && view.currently_showing) {
                bookpos = view.currently_showing.bookpos;
                if (bookpos) {
                    query = (function(){
                        var ρσ_d = Object.create(null);
                        ρσ_d["bookpos"] = bookpos;
                        return ρσ_d;
                    }).call(this);
                    query = encode_query_with_path(query);
                    if (replace) {
                        window.history.replaceState(null, "", query);
                    } else {
                        window.history.pushState(null, "", query);
                    }
                }
            }
        };
        if (!update_url_state.__argnames__) Object.defineProperties(update_url_state, {
            __argnames__ : {value: ["replace"]}
        });

        function on_pop_state() {
            var data;
            if (view && view.currently_showing) {
                data = parse_url_params();
                if (data.bookpos && data.bookpos.startswith("epubcfi(/")) {
                    view.goto_bookpos(data.bookpos);
                }
            }
        };

        function show_error(title, msg, details) {
            error_dialog(title, msg, details);
        };
        if (!show_error.__argnames__) Object.defineProperties(show_error, {
            __argnames__ : {value: ["title", "msg", "details"]}
        });

        function manifest_received(key, initial_cfi, initial_toc_node, pathtoebook, end_type, xhr, ev) {
            var data;
            if (end_type === "load") {
                book = new_book(key, Object.create(null));
                data = xhr.response;
                book.manifest = data[0];
                book.metadata = book.manifest.metadata = data[1];
                book.manifest.pathtoebook = pathtoebook;
                book.stored_files = Object.create(null);
                book.is_complete = true;
                delete book.manifest["metadata"];
                delete book.manifest["last_read_positions"];
                view.display_book(book, initial_cfi, initial_toc_node);
            } else {
                error_dialog(_("Could not open book"), _("Failed to load book manifest, click \"Show details\" for more info"), xhr.error_html || null);
            }
        };
        if (!manifest_received.__argnames__) Object.defineProperties(manifest_received, {
            __argnames__ : {value: ["key", "initial_cfi", "initial_toc_node", "pathtoebook", "end_type", "xhr", "ev"]}
        });

        function SessionData() {
            if (this.ρσ_object_id === undefined) Object.defineProperty(this, "ρσ_object_id", {"value":++ρσ_object_counter});
            SessionData.prototype.__bind_methods__.call(this);
            SessionData.prototype.__init__.apply(this, arguments);
        }
        Object.defineProperty(SessionData.prototype, "__bind_methods__", {value: function () {
            this.get = SessionData.prototype.get.bind(this);
            this.set = SessionData.prototype.set.bind(this);
            this.clear = SessionData.prototype.clear.bind(this);
        }});
        SessionData.prototype.__init__ = function __init__(prefs) {
            var self = this;
            var defaults, k;
            defaults = session_defaults();
            self.data = (function() {
                var ρσ_Iter = ρσ_Iterable(defaults), ρσ_Result = Object.create(null), k;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    k = ρσ_Iter[ρσ_Index];
                    ρσ_Result[k] = ((prefs[(typeof k === "number" && k < 0) ? prefs.length + k : k] === undefined) ? defaults[(typeof k === "number" && k < 0) ? defaults.length + k : k] : prefs[(typeof k === "number" && k < 0) ? prefs.length + k : k]);
                }
                return ρσ_Result;
            })();
        };
        if (!SessionData.prototype.__init__.__argnames__) Object.defineProperties(SessionData.prototype.__init__, {
            __argnames__ : {value: ["prefs"]}
        });
        SessionData.__argnames__ = SessionData.prototype.__init__.__argnames__;
        SessionData.__handles_kwarg_interpolation__ = SessionData.prototype.__init__.__handles_kwarg_interpolation__;
        SessionData.prototype.get = function get(key, defval) {
            var self = this;
            var ans;
            ans = (ρσ_expr_temp = self.data)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
            if (ans === undefined || ans === null) {
                if (defval === undefined) {
                    defval = null;
                }
                return defval;
            }
            return ans;
        };
        if (!SessionData.prototype.get.__argnames__) Object.defineProperties(SessionData.prototype.get, {
            __argnames__ : {value: ["key", "defval"]}
        });
        SessionData.prototype.set = function set(key, val) {
            var self = this;
            if (val === null) {
                (ρσ_expr_temp = self.data)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key] = (ρσ_expr_temp = session_defaults())[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key];
            } else {
                (ρσ_expr_temp = self.data)[(typeof key === "number" && key < 0) ? ρσ_expr_temp.length + key : key] = val;
            }
            to_python.set_session_data(key, val);
        };
        if (!SessionData.prototype.set.__argnames__) Object.defineProperties(SessionData.prototype.set, {
            __argnames__ : {value: ["key", "val"]}
        });
        SessionData.prototype.clear = function clear() {
            var self = this;
            var defaults, k;
            defaults = session_defaults();
            self.data = (function() {
                var ρσ_Iter = ρσ_Iterable(defaults), ρσ_Result = Object.create(null), k;
                for (var ρσ_Index = 0; ρσ_Index < ρσ_Iter.length; ρσ_Index++) {
                    k = ρσ_Iter[ρσ_Index];
                    ρσ_Result[k] = (defaults[(typeof k === "number" && k < 0) ? defaults.length + k : k]);
                }
                return ρσ_Result;
            })();
            to_python.set_session_data("*", null);
        };
        SessionData.prototype.__repr__ = function __repr__ () {
                        return "<" + __name__ + "." + this.constructor.name + " #" + this.ρσ_object_id + ">";
        };
        SessionData.prototype.__str__ = function __str__ () {
            return this.__repr__();
        };
        Object.defineProperty(SessionData.prototype, "__bases__", {value: []});

        function create_session_data(prefs) {
            var sd;
            sd = new SessionData(prefs);
            set_session_data(sd);
        };
        if (!create_session_data.__argnames__) Object.defineProperties(create_session_data, {
            __argnames__ : {value: ["prefs"]}
        });

        
        var create_view = from_python((function() {
            var ρσ_anonfunc = function create_view(prefs, all_font_families, field_metadata, ui_font_family, ui_font_sz) {
                runtime.all_font_families = all_font_families;
                library_data.field_metadata = field_metadata;
                document.documentElement.style.fontFamily = "\"" + ρσ_str.format("{}", ui_font_family) + "\", sans-serif";
                document.documentElement.style.fontSize = ui_font_sz;
                if (view === null) {
                    create_session_data(prefs);
                    view = new View(document.getElementById("view"));
                    view.overlay.open_book(false);
                }
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["prefs", "all_font_families", "field_metadata", "ui_font_family", "ui_font_sz"]}
            });
            return ρσ_anonfunc;
        })());

        
        var show_home_page = from_python(function show_home_page() {
            view.overlay.open_book(false);
        });

        
        var show_preparing_message = from_python((function() {
            var ρσ_anonfunc = function show_preparing_message(msg) {
                view.show_loading_message(msg);
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["msg"]}
            });
            return ρσ_anonfunc;
        })());

        
        var start_book_load = from_python((function() {
            var ρσ_anonfunc = function start_book_load(key, initial_cfi, initial_toc_node, pathtoebook) {
                var xhr;
                xhr = ρσ_interpolate_kwargs.call(this, ajax, ["manifest", manifest_received.bind(null, key, initial_cfi, initial_toc_node, pathtoebook)].concat([ρσ_desugar_kwargs({ok_code: 0})]));
                xhr.responseType = "json";
                xhr.send();
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["key", "initial_cfi", "initial_toc_node", "pathtoebook"]}
            });
            return ρσ_anonfunc;
        })());

        
        var goto_toc_node = from_python((function() {
            var ρσ_anonfunc = function goto_toc_node(node_id) {
                view.goto_toc_node(node_id);
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["node_id"]}
            });
            return ρσ_anonfunc;
        })());

        
        var goto_cfi = from_python((function() {
            var ρσ_anonfunc = function goto_cfi(cfi) {
                view.goto_bookpos(cfi);
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["cfi"]}
            });
            return ρσ_anonfunc;
        })());

        
        var full_screen_state_changed = from_python((function() {
            var ρσ_anonfunc = function full_screen_state_changed(viewer_in_full_screen) {
                runtime.viewer_in_full_screen = viewer_in_full_screen;
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["viewer_in_full_screen"]}
            });
            return ρσ_anonfunc;
        })());

        
        var get_current_cfi = from_python((function() {
            var ρσ_anonfunc = function get_current_cfi(request_id) {
                view.get_current_cfi(request_id, ui_operations.report_cfi);
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["request_id"]}
            });
            return ρσ_anonfunc;
        })());

        
        var goto_frac = from_python((function() {
            var ρσ_anonfunc = function goto_frac(frac) {
                if (view) {
                    view.goto_frac(frac);
                }
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["frac"]}
            });
            return ρσ_anonfunc;
        })());

        
        var background_image_changed = from_python((function() {
            var ρσ_anonfunc = function background_image_changed(img_id) {
                var img;
                img = document.getElementById(img_id);
                if (img) {
                    img.src = READER_BACKGROUND_URL + "?" + (new Date).getTime();
                }
            };
            if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                __argnames__ : {value: ["img_id"]}
            });
            return ρσ_anonfunc;
        })());

        function onerror(msg, script_url, line_number, column_number, error_object) {
            var fname, details;
            if (!error_object) {
                return false;
            }
            fname = (ρσ_expr_temp = script_url.rpartition("/"))[ρσ_expr_temp.length-1] || script_url;
            msg += "<br><span style=\"font-size:smaller\">" + "Error at {}:{}:{}".format(fname, line_number, column_number || "") + "</span>";
            details = "";
            console.log(error_object);
            details = traceback.format_exception(error_object).join("");
            error_dialog(_("Unhandled error"), msg, details);
            return true;
        };
        if (!onerror.__argnames__) Object.defineProperties(onerror, {
            __argnames__ : {value: ["msg", "script_url", "line_number", "column_number", "error_object"]}
        });

        if (window === window.top) {
            TRANSLATIONS_DATA = __TRANSLATIONS_DATA__;
            if (TRANSLATIONS_DATA) {
                install(TRANSLATIONS_DATA);
            }
            ui_operations.get_file = get_file;
            ui_operations.get_mathjax_files = get_mathjax_files;
            ui_operations.update_url_state = update_url_state;
            ui_operations.show_error = show_error;
            ui_operations.redisplay_book = function () {
                view.redisplay_book();
            };
            ui_operations.reload_book = function () {
                to_python.reload_book();
            };
            ui_operations.forward_gesture = (function() {
                var ρσ_anonfunc = function (gesture) {
                    view.forward_gesture(gesture);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["gesture"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.update_color_scheme = function () {
                view.update_color_scheme();
            };
            ui_operations.update_font_size = function () {
                view.update_font_size();
            };
            ui_operations.focus_iframe = function () {
                view.focus_iframe();
            };
            ui_operations.goto_bookpos = (function() {
                var ρσ_anonfunc = function (cfi) {
                    return view.goto_bookpos(cfi);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["cfi"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.toggle_toc = function () {
                to_python.toggle_toc();
            };
            ui_operations.toggle_bookmarks = function () {
                to_python.toggle_bookmarks();
            };
            ui_operations.toggle_inspector = function () {
                to_python.toggle_inspector();
            };
            ui_operations.toggle_lookup = function () {
                to_python.toggle_lookup();
            };
            ui_operations.selection_changed = (function() {
                var ρσ_anonfunc = function (selected_text) {
                    to_python.selection_changed(selected_text);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["selected_text"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.update_current_toc_nodes = (function() {
                var ρσ_anonfunc = function (current_node_id, top_level_node_id) {
                    to_python.update_current_toc_nodes(current_node_id, top_level_node_id);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["current_node_id", "top_level_node_id"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.toggle_full_screen = function () {
                to_python.toggle_full_screen();
            };
            ui_operations.report_cfi = (function() {
                var ρσ_anonfunc = function (request_id, data) {
                    to_python.report_cfi(request_id, data);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["request_id", "data"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.ask_for_open = (function() {
                var ρσ_anonfunc = function (path) {
                    to_python.ask_for_open(path);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["path"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.copy_selection = (function() {
                var ρσ_anonfunc = function (text) {
                    to_python.copy_selection(text || null);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["text"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.view_image = (function() {
                var ρσ_anonfunc = function (name) {
                    to_python.view_image(name);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["name"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.copy_image = (function() {
                var ρσ_anonfunc = function (name) {
                    to_python.copy_image(name);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["name"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.change_background_image = (function() {
                var ρσ_anonfunc = function (img_id) {
                    to_python.change_background_image(img_id);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["img_id"]}
                });
                return ρσ_anonfunc;
            })();
            ui_operations.quit = function () {
                to_python.quit();
            };
            ui_operations.overlay_visibility_changed = (function() {
                var ρσ_anonfunc = function (visible) {
                    to_python.overlay_visibility_changed(visible);
                };
                if (!ρσ_anonfunc.__argnames__) Object.defineProperties(ρσ_anonfunc, {
                    __argnames__ : {value: ["visible"]}
                });
                return ρσ_anonfunc;
            })();
            document.body.appendChild(ρσ_interpolate_kwargs.call(E, E.div, [ρσ_desugar_kwargs({id: "view"})]));
            window.onerror = onerror;
            create_modal_container();
            document.head.appendChild(E.style(get_widget_css()));
            ρσ_interpolate_kwargs.call(this, set_css, [document.body].concat([ρσ_desugar_kwargs({background_color: get_color("window-background"), color: get_color("window-foreground")})]));
            setTimeout(function () {
                window.onpopstate = on_pop_state;
            }, 0);
        } else {
            div = document.getElementById("calibre-viewer-footnote-iframe");
            if (div) {
                footnotes_main();
            } else {
                iframe_main();
            }
        }
    })();
})();
