commit 2e665813a44988bfd906c0fab773f82652047841
parent ad45c1d0d6152d6eddde39881461a3472f799ab7
Author: Christian Grothoff <christian@grothoff.org>
Date: Sat, 10 Oct 2020 22:55:31 +0200
merge torsten-redesign branch, implement i18n support
Diffstat:
30 files changed, 2179 insertions(+), 1831 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1 +1,2 @@
-__pycache__
+talermerchantdemos/static/*.css
+talermerchantdemos/static/navbar.css.map
diff --git a/Makefile b/Makefile
@@ -3,7 +3,7 @@ install_global=false
.PHONY: all
all:
- @echo "This is a python project, no compilation required"
+ @echo "This is a python project, no compilation required\nSCSS/SASS Initial Setup: make sass-setup\nSCSS/SASS Build (for static files): make sass-build"
.PHONY: install
@@ -38,3 +38,42 @@ dist:
.PHONY: pretty
pretty:
yapf -r -i talerblog/
+
+# i18n
+extract:
+# Note: Flask-BabelEx expects 'translations/' for the dirname,
+# even though GNU gettext typically uses 'locale/'
+ mkdir -p translations/
+ pybabel extract -F babel.cfg -o translations/messages.pot .
+# Add new language as follows:
+# pybabel init -i locale/messages.pot -d locale/ -l de
+
+compile:
+ pybabel compile -d translations/
+
+update: extract
+ pybabel update -i translations/messages.pot -d translations/
+
+# SASS/SCSS
+
+sass-setup:
+ @echo "This is the initial sass-installation/setup script."
+ @echo "This setup must run as root, on a machine that has NPM installed!"
+ @echo "If your password is requested (for escalation), please enter it."
+ sudo npm install -g sass
+
+scss-setup: sass-setup
+
+sass-build:
+ @echo "Warning: If Sass/Scss is not installed, please run \`make sass-setup\` first!"
+ @echo "This script will only convert files inside /static"
+ sass talermerchantdemos/static:talermerchantdemos/static
+
+scss-build: sass-build
+
+sass-autobuild:
+ @echo "Warning: If Sass/Scss is not installed, please run \`make sass-setup\` first!"
+ @echo "This script will automatically build sass/scss files in the static directory!"
+ sass --watch talermerchantdemos/static:talermerchantdemos/static
+
+scss-autobuild: sass-autobuild
diff --git a/README.md b/README.md
@@ -1,14 +1,18 @@
# Taler Merchant Demos Setup
*Warning: This page is not completed yet. Follow the instructions at your own risk*
## Installing the dependencies
+*Step 0 (Optional - Reccomended): Update Apt Repositories*
+> ```$ sudo apt update```
+
+<br/>
Step 1: `cd` into the directory:<br/>
> ```$ cd taler-merchant-demos```
<br/>
-Step 2: Ensure Python3.5 or above is installed using a command like:<br/>
+Step 2: Ensure Python 3.5 or above and Flask with the Babel extension are installed using a command like:<br/>
-> ```$ sudo apt install python3.8 -y```
+> ```$ sudo apt install python3.8 python3-flask-babel -y```
<br/>
Step 3: Ensure Python3 Pip is installed:<br/>
@@ -16,7 +20,7 @@ Step 3: Ensure Python3 Pip is installed:<br/>
> ```$ sudo apt install python3-pip -y```
<br/>
-Step 4: configure it using:<br/>
+Step 4: configure this package using:<br/>
> ```$ ./configure --destination=local```
@@ -27,14 +31,28 @@ Step 5: Install UWSGI<br>
<br/>
Step 6: Install LXML
-*NOTE: DO NOT INSTALL USING PIP2 (on my system, that is what the pip command uses) - INSTALL IT USING PIP3*
+*NOTE: DO NOT INSTALL USING PIP2 (on my system, that is what the pip command uses) - INSTALL IT USING PIP3*<br>
> ```$ pip3 install lxml```
+
+<br/>
+
+Step 7: Install NPM<br>
+
+> ```$ sudo apt install npm; sudo npm install -g npm node```
+
<br>
+Step 8: Install scss<br>
+> ```$ make sass-install```
+
+This will the NPM implementation of sass. If you have a Ruby
+tool called 'sass' installed, this build will NOT work.
+
+
## Quick Install for the dependencies
Here's one command to automatically install all dependencies at once:
-> ```$ sudo apt install python3.8 python3-pip -y; pip3 install lxml uwsgi; ./configure --destination=local```
+> ```$ sudo apt install python3.8 python3-pip npm -y; pip3 install lxml uwsgi; ./configure --destination=local; sudo npm install -g npm node;make sass-install```
## Configuring the demo
*This is just how I did it, and not the main method of doing it*
@@ -72,6 +90,11 @@ Step 3: Configure the config:
To apply changes, use
> ```$ make install```
+<br>
+
+To apply ***SCSS*** changes, use
+> ```$ make scss-build```
+
## Running the program
To start the server, use the following command:<br>
> ```$ taler-merchant-demos blog```
diff --git a/setup.py b/setup.py
@@ -20,6 +20,7 @@ setup(name='talermerchantdemos',
"static/*.svg",
# Blog files
"blog/templates/*.html",
+ "blog/templates/*.j2",
"blog/articles/*",
"blog/data/*",
# Donation files
diff --git a/talermerchantdemos/.gitignore b/talermerchantdemos/.gitignore
@@ -0,0 +1,6 @@
+*.pyc
+*/__pycache__
+
+./static/*.css
+
+*/*.css.map
+\ No newline at end of file
diff --git a/talermerchantdemos/.vscode/launch.json b/talermerchantdemos/.vscode/launch.json
@@ -0,0 +1,15 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "pwa-chrome",
+ "request": "launch",
+ "name": "Launch Chrome against localhost",
+ "url": "http://localhost:8080",
+ "webRoot": "${workspaceFolder}"
+ }
+ ]
+}
+\ No newline at end of file
diff --git a/talermerchantdemos/blog/articles/scrap1_11.html b/talermerchantdemos/blog/articles/scrap1_11.html
@@ -52,4 +52,3 @@ traditional style, please visit
<br/>
</p>
<img alt="song-book-jutta-scrunch-crop" src="/essay/11._The_Free_Software_Song/data/song-book-jutta-scrunch-crop.jpg"/>
-
diff --git a/talermerchantdemos/blog/blog.py b/talermerchantdemos/blog/blog.py
@@ -1,6 +1,6 @@
##
-# This file is part of GNU taler.
-# Copyright (C) 2014-2017 INRIA
+# This file is part of GNU Taler.
+# Copyright (C) 2014-2020 Taler Systems SA
#
# TALER is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
@@ -24,6 +24,11 @@ import traceback
import uuid
import base64
import flask
+from flask import request
+from flask_babel import Babel
+from flask_babel import refresh
+from flask_babel import force_locale
+from flask_babel import gettext
import time
import sys
from urllib.parse import urljoin, urlencode, urlparse
@@ -85,6 +90,34 @@ ARTICLE_AMOUNT = CURRENCY + ":0.5"
BACKEND_URL = urljoin(BACKEND_BASE_URL, "instances/blog/")
app.config.from_object(__name__)
+babel = Babel(app)
+
+print("Using translations from:")
+print(list(babel.translation_directories))
+translations = [str(translation) for translation in babel.list_translations()]
+translations.append('en')
+print("Operating with the following translations available:")
+print(translations)
+
+
+##
+# Helper function used inside Jinja2 logic to create a links
+# to the current page but in a different language. Used to
+# implement the "Language" menu.
+#
+def self_localized(lang):
+ """
+ Return URL for the current page in another locale.
+ """
+ path = request.path
+ # path must have the form "/$LANG/$STUFF"
+ parts = path.split('/', 2)
+ if (2 >= len(parts)):
+ # Totally unexpected path format, do not localize
+ return path
+ return "/" + lang + "/" + parts[2]
+
+app.jinja_env.globals.update(self_localized=self_localized)
##
@@ -107,7 +140,7 @@ def utility_processor():
# @param abort_status_code status code to return along the response.
# @param params _kw_ arguments to passed verbatim to the templating engine.
def err_abort(abort_status_code, **params):
- t = flask.render_template("templates/error.html", **params)
+ t = flask.render_template("templates/error.html.j2", **params)
flask.abort(flask.make_response(t, abort_status_code))
@@ -120,23 +153,44 @@ def err_abort(abort_status_code, **params):
@app.errorhandler(Exception)
def internal_error(e):
return flask.render_template(
- "templates/error.html", message="Internal error", stack=traceback.format_exc()
+ "templates/error.html.j2", message=gettext("Internal error"), stack=traceback.format_exc()
)
##
-# Serve the main index page.
+# Serve the main index page, redirecting to /<lang>/
#
# @return response object of the index page.
@app.route("/")
def index():
+ default = 'en'
+ target = flask.request.accept_languages.best_match(translations, default)
+ return flask.redirect("/" + target + "/", code=302)
+
+@babel.localeselector
+def get_locale():
+ parts = request.path.split('/', 2)
+ if (2 >= len(parts)):
+ # Totally unexpected path format, do not localize
+ return "en"
+ lang = parts[1]
+ if lang in translations:
+ return lang
+ return "en"
+
+##
+# Serve the main index page for a particular language.
+#
+# @return response object of the index page.
+@app.route("/<lang>/")
+def start(lang):
return flask.render_template(
- "templates/index.html", merchant_currency=CURRENCY, articles=ARTICLES.values()
+ "templates/index.html.j2", lang=lang, merchant_currency=CURRENCY, articles=ARTICLES.values()
)
-@app.route("/confirm-refund/<order_id>", methods=["GET"])
-def confirm_refund(order_id):
+@app.route("/<lang>/confirm-refund/<order_id>", methods=["GET"])
+def confirm_refund(lang, order_id):
session_id = flask.session.get("session_id", "")
pay_status = backend_get(
BACKEND_URL, f"private/orders/{order_id}", params=dict(session_id=session_id)
@@ -144,16 +198,16 @@ def confirm_refund(order_id):
order_status = pay_status.get("order_status")
if order_status != "paid":
err_abort(
- 400, message="can't refund unpaid article",
+ 400, message="Cannot refund unpaid article",
)
article_name = pay_status["contract_terms"]["extra"]["article_name"]
if not refundable(pay_status):
return flask.render_template(
- "templates/error.html", message="Item not refundable (anymore)"
+ "templates/error.html.j2", message=gettext("Article is not anymore refundable")
)
return flask.render_template(
- "templates/confirm_refund.html", article_name=article_name, order_id=order_id
+ "templates/confirm_refund.html.j2", article_name=article_name, order_id=order_id
)
@@ -163,16 +217,15 @@ def confirm_refund(order_id):
#
# @param order_id the order ID of the transaction to refund.
# @return the following errors (named by HTTP response code):
-# - 400: no article was asked to be refunded!
-# - 401: the refund was asked on a non-payed article.
-# - 500: the backend was unable to give response.
-# Or, in the successful case, a redirection to the
-# "refund URL" is returned; then the wallet will run
-# the refund protocol in a transparent way.
+# - 400: order unknown
+# - 402: the refund was asked on an unpaid article.
+# - 302: in the successful case, a redirection to the
+# "refund URL" is returned; then the wallet will run
+# the refund protocol in a transparent way.
@app.route("/refund/<order_id>", methods=["POST"])
-def refund(order_id):
+def refund(lang, order_id):
if not order_id:
- return flask.jsonify(dict(error="Aborting refund: article not payed")), 401
+ return flask.jsonify(dict(error="Aborting refund: order unknown")), 400
session_id = flask.session.get("session_id", "")
pay_status = backend_get(
BACKEND_URL, f"private/orders/{order_id}", params=dict(session_id=session_id)
@@ -219,7 +272,7 @@ def render_article(article_name, data, order_id, refundable):
err_abort(404, message=m)
# the order_id is needed for refunds
return flask.render_template(
- "templates/article_frame.html",
+ "templates/article_frame.html.j2",
article_file=get_article_file(article_info),
article_name=article_name,
order_id=order_id,
@@ -247,6 +300,25 @@ def post_order(article_name,lang):
dict(order=order, refund_delay=dict(d_ms=1000 * 120)))
return order_resp
+##
+# Setup a fresh order with the backend.
+#
+# @param article_name which article the order is for
+# @param lang which language to use
+#
+def post_order(article_name,lang):
+ order = dict(
+ amount=ARTICLE_AMOUNT,
+ extra=dict(article_name=article_name,lang=lang),
+ fulfillment_url=flask.request.base_url,
+ summary="Essay: " + article_name.replace("_", " "),
+ # 10 minutes time for a refund
+ refund_deadline=dict(t_ms=1000 * int(time.time() + 10 * 30)),
+ wire_transfer_deadline=dict(t_ms=1000 * int(time.time() + 15 * 30)),
+ )
+ order_resp = backend_post(BACKEND_URL, "private/orders", dict(order=order))
+ return order_resp
+
##
# Trigger a article purchase. The logic follows the main steps:
@@ -267,9 +339,10 @@ def post_order(article_name,lang):
# In the successful case, either the article is returned, or
# the browser gets redirected to a page where the wallet can
# send the payment.
-@app.route("/essay/<article_name>")
+@app.route("/<lang>/essay/<article_name>")
+@app.route("/<lang>/essay/<article_name>/data/<data>")
@app.route("/essay/<article_name>/data/<data>")
-def article(article_name, data=None):
+def article(article_name, lang=None, data=None):
# We use an explicit session ID so that each payment (or payment replay) is
# bound to a browser. This forces re-play and prevents sharing the article
# by just sharing the URL.
@@ -279,8 +352,6 @@ def article(article_name, data=None):
if not session_id:
session_id = flask.session["session_id"] = str(uuid.uuid4())
order_id = None
- # Temporary workaround...
- lang="en"
##
# First-timer; generate order first.
if not order_id:
@@ -309,12 +380,19 @@ def article(article_name, data=None):
if order_status == "paid":
refunded = pay_status["refunded"]
if refunded:
- return flask.render_template(
- "templates/article_refunded.html",
+ return flask.render_template(
+ "templates/article_refunded.html.j2",
article_name=article_name,
order_id=order_id,
)
- return render_article(article_name, data, order_id, refundable(pay_status))
+ response = render_article(article_name, data, order_id, refundable(pay_status))
+ response.set_cookie(
+ "order_id", order_id, path=urllib.parse.quote(f"/essay/{article_name}")
+ )
+ response.set_cookie(
+ "order_id", order_id, path=urllib.parse.quote(f"/{lang}/essay/{article_name}")
+ )
+ return response
# Check if the customer came on this page via the
# re-purchase detection mechanism
@@ -333,14 +411,17 @@ def article(article_name, data=None):
response.set_cookie(
"order_id", order_id, path=urllib.parse.quote(f"/essay/{article_name}")
)
+ response.set_cookie(
+ "order_id", order_id, path=urllib.parse.quote(f"/{lang}/essay/{article_name}")
+ )
return response
@app.errorhandler(500)
def handler(e):
return flask.render_template(
- "templates/error.html", message="Internal server error")
+ "templates/error.html.j2", message=gettext("Internal server error"))
@app.errorhandler(404)
def handler(e):
return flask.render_template(
- "templates/error.html", message="Page not found")
+ "templates/error.html.j2", message=gettext("Page not found"))
diff --git a/talermerchantdemos/blog/content.py b/talermerchantdemos/blog/content.py
@@ -26,7 +26,7 @@ from pkg_resources import resource_stream, resource_filename
LOGGER = logging.getLogger(__name__)
NOISY_LOGGER = logging.getLogger("chardet.charsetprober")
NOISY_LOGGER.setLevel(logging.INFO)
-Article = namedtuple("Article", "slug title teaser main_file extra_files")
+Article = namedtuple("Article", "slug title teaser main_file extra_files lang")
##
# @var if a article is added to this list, then it will
@@ -43,8 +43,9 @@ ARTICLES = OrderedDict()
# @param main_file path to the article's HTML file.
# @param extra_file collection of extra files associated with the
# article, like images and sounds.
-def add_article(slug, title, teaser, main_file, extra_files):
- ARTICLES[slug] = Article(slug, title, teaser, main_file, extra_files)
+# @param lang language of the arcile
+def add_article(slug, title, teaser, main_file, extra_files, lang='en'):
+ ARTICLES[slug] = Article(slug, title, teaser, main_file, extra_files, lang)
##
@@ -85,7 +86,7 @@ def add_from_html(resource_name, teaser_paragraph=0, title=None):
if title is None:
title_el = soup.find("h1", attrs={"class": ["chapter", "unnumbered"]})
if title_el is None:
- LOGGER.warning("Can't extract title from '%s'", resource_name)
+ LOGGER.warning("Cannot extract title from '%s'", resource_name)
title = resource_name
else:
title = title_el.get_text().strip()
@@ -97,7 +98,7 @@ def add_from_html(resource_name, teaser_paragraph=0, title=None):
teaser = paragraphs[teaser_paragraph].get_text()
else:
teaser = teaser.get_text()
- re_proc = re.compile("^/essay/[^/]+/data/[^/]+$")
+ re_proc = re.compile("^/[^/][^/]/essay/[^/]+/data/[^/]+$")
imgs = soup.find_all("img")
extra_files = []
for img in imgs:
@@ -114,7 +115,7 @@ def add_from_html(resource_name, teaser_paragraph=0, title=None):
else:
LOGGER.warning("Image src and slug don't match: '%s' != '%s'" \
% (img['src'].split(os.sep)[2], slug))
- add_article(slug, title, teaser, resource_name, extra_files)
+ add_article(slug, title, teaser, resource_name, extra_files, 'en')
add_from_html("blog/articles/scrap1_U.0.html", 0)
diff --git a/talermerchantdemos/blog/templates/article_frame.html b/talermerchantdemos/blog/templates/article_frame.html
@@ -1,13 +0,0 @@
-{% extends "templates/base.html" %}
-{% block main %}
-{% include "articles/" + article_file %}
-
-{% if refundable %}
-<hr>
-<p>
- You don't like this article? <a href="{{ url_for('confirm_refund', order_id=order_id) }}">Get a refund</a> within
- the first hour after buying it.
-</p>
-{% endif %}
-
-{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/article_frame.html.j2 b/talermerchantdemos/blog/templates/article_frame.html.j2
@@ -0,0 +1,15 @@
+{% extends "templates/base.html.j2" %}
+{% block main %}
+{% include "articles/" + article_file %}
+
+{% if refundable %}
+<hr>
+<p>
+ {{
+ gettext("You did not like this article?") +
+ gettext("You can <a href="{url}">request a refund</a> within the first hour after buying it.").format(url=url_for('confirm_refund', lang='en', order_id=order_id)
+ }}
+</p>
+{% endif %}
+
+{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/article_refunded.html b/talermerchantdemos/blog/templates/article_refunded.html
@@ -1,10 +0,0 @@
-{% extends "templates/base.html" %}
-{% block main %}
-
-<h2>Refunded</h2>
-
-<p>Your payment (order ID <tt>{{ order_id }}<tt>) for the article "{{ article_name }}" has been refunded.</p>
-
-<p>You won't be able to view it until you pay for it again.</p>
-
-{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/article_refunded.html.j2 b/talermerchantdemos/blog/templates/article_refunded.html.j2
@@ -0,0 +1,16 @@
+{% extends "templates/base.html.j2" %}
+{% block main %}
+
+<h2>{{ gettext("Refunded") }}</h2>
+
+<p>
+{{
+ gettext("Your payment (order ID <tt>{order}<tt>) for the article "{article}" has been refunded.").format(order=order_id,article=article_name)
+}}
+</p>
+
+<p>
+{{ gettext("You won't be able to view it until you pay for it again.") }}
+</p>
+
+{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/base.html b/talermerchantdemos/blog/templates/base.html
@@ -1,79 +0,0 @@
-<!DOCTYPE html>
-<!--
- This file is part of GNU TALER.
- Copyright (C) 2014, 2015, 2016 INRIA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Lesser General Public License as published by the Free Software
- Foundation; either version 2.1, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
--->
-
-<html>
-<head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- {% block meta %}{% endblock %}
- <title>Taler Essay Shop Demo</title>
- <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='pure.css') }}" />
- <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='demo.css') }}" />
- <style>
- .warn {
- background-color: #aa393977;
- padding: 1em;
- }
- .notice {
- border-radius: 1em;
- background: #0333;
- border-left: 0.3em solid #033;
- padding-left: 1em;
- padding-top: 0.5em;
- padding-bottom: 0.5em;
- margin-top: 2em;
- margin-bottom: 2em;
- }
- #main a:link, #main a:visited, #main a:hover, #main a:active {
- color: black;
- }
- </style>
- {% block styles %}{% endblock %}
- {% block scripts %}{% endblock %}
-</head>
-
-<body>
- <div class="demobar" style="display: flex; flex-direction: column;">
- <h1><span class="tt adorn-brackets">Taler Demo</span></h1>
- <h1><span class="it"><a href="{{ env('TALER_ENV_URL_MERCHANT_BLOG') }}">Shop</a></span></h1>
- <p>On this page you can buy articles using an imaginary currency (for now).
- The articles are chapters from Richard Stallman's book "Free Software, Free Society",
- which is also
- <a href="http://shop.fsf.org/product/free-software-free-society-2/">published by the FSF</a>
- and available gratis at <a href="http://www.gnu.org/">gnu.org</a>.
- </p>
- <ul>
- <li><a href="{{ env('TALER_ENV_URL_INTRO', '#') }}">Introduction</a></li>
- <li><a href="{{ env('TALER_ENV_URL_BANK', '#') }}">Bank</a></li>
- <li><a href="{{ env('TALER_ENV_URL_MERCHANT_BLOG', '#') }}">Essay Shop</a></li>
- <li><a href="{{ env('TALER_ENV_URL_MERCHANT_DONATIONS', '#') }}">Donations</a></li>
- <li><a href="{{ env('TALER_ENV_URL_MERCHANT_SURVEY', '#') }}">Tipping/Survey</a></li>
- <li><a href="{{ env('TALER_ENV_URL_BACKOFFICE', '#') }}">Back-office</a></li>
- </ul>
- <p>You can learn more about Taler on our main <a href="https://taler.net">website</a>.</p>
- <div style="flex-grow:1"></div>
- <p>Copyright © 2014—2018 Inria</p>
- </div>
-
- <section id="main" class="content">
- {% block main %}
- This is the main content of the page.
- {% endblock %}
- <hr />
- </section>
-</body>
-</html>
diff --git a/talermerchantdemos/blog/templates/base.html.j2 b/talermerchantdemos/blog/templates/base.html.j2
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<!--
+ This file is part of GNU TALER.
+ Copyright (C) 2014, 2015, 2016, 2020 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+-->
+
+<html>
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ {% block meta %}{% endblock %}
+ <title>{{ gettext("Taler Essay Shop Demo") }}</title>
+ <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='pure.css') }}" />
+ <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='demo.css') }}" />
+ <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='navbar.css') }}" />
+ <style>
+ .warn {
+ background-color: #aa393977;
+ padding: 1em;
+ }
+ @keyframes hoveranim {
+ from {left:0;}
+ to {left:1vw;}
+ }
+ @keyframes hoveranimrevert {
+ from {left:1vw;}
+ to {left:0;}
+ }
+ .notice {
+ border-radius: 1em;
+ background: #0333;
+ border-left: 0.3em solid #033;
+ padding-left: 1em;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ margin-top: 2em;
+ margin-bottom: 2em;
+ }
+ .notice {
+ position: relative;
+ left: 0;
+ animation-name: hoveranimrevert;
+ animation-duration: 1s;
+ }
+ .notice:hover {
+ left: 1vw;
+ animation-name: hoveranim;
+ animation-duration: 1s;
+ }
+ #main a:link, #main a:visited, #main a:hover, #main a:active {
+ color: black;
+ }
+ </style>
+
+ {% block styles %}{% endblock %}
+ {% block scripts %}{% endblock %}
+</head>
+
+<body>
+ <header class="demobar" style="display: flex; flex-direction: column;">
+ <h1><span class="tt adorn-brackets">Taler Demo</span></h1>
+ <h1><span class="it"><a href="{{ env('TALER_ENV_URL_MERCHANT_BLOG') }}">Shop</a></span></h1>
+ <p>{{
+ gettext("On this page you can buy articles using an imaginary currency.") + "<br>" +
+ gettext("The articles are chapters from Richard Stallman's book "Free Software, Free Society".") + "<br>" +
+ gettext('The book is <a href="{shop}">published by the FSF</a> and available gratis at <a href="{gnu}">gnu.org</a>.').format(shop="https://shop.fsf.org/product/free-software-free-society-2", gnu="https://www.gnu.org")
+ }}
+ </p>
+ </header>
+ <div style="display:flex; flex-direction: column;" class="navcontainer">
+ <nav class="demolist">
+ <a href="{{ env('TALER_ENV_URL_INTRO', '#') }}">{{gettext("Introduction")}}</a>
+ <a href="{{ env('TALER_ENV_URL_BANK', '#') }}">{{gettext("Bank")}}</a>
+ <a href="{{ env('TALER_ENV_URL_MERCHANT_BLOG', '#') }}" class="active">{{gettext("Essay Shop")}}</a>
+ <a href="{{ env('TALER_ENV_URL_MERCHANT_DONATIONS', '#') }}">{{gettext("Donations")}}</a>
+ <a href="{{ env('TALER_ENV_URL_MERCHANT_SURVEY', '#') }}">{{gettext("Tipping/Survey")}}</a>
+ <!-- a href="{{ env('TALER_ENV_URL_BACKOFFICE', '#') }}">{{gettext("Back-office")}}</a -->
+ <span class="right">
+ {{ gettext("English [en]") }}
+ <!-- <input type="checkbox"> -->
+ <div class="nav">
+ <br>
+ <!--<hr style="width: 100%;">-->
+ {% if lang != 'en' %}
+ <a href="{{ self_localized('en') }}" class="navbtn">English [en]</a><br>
+ {% endif %}
+ {% if lang != 'de' %}
+ <a href="{{ self_localized('de') }}" class="navbtn">Deutsch [de]</a><br>
+ {% endif %}
+ </div>
+ </span>
+ </nav>
+ </div>
+ <!-- <input type="checkbox" class="r"><label>test</label> -->
+
+ <section id="main" class="content">
+ {% block main %}
+ This is the main content of the page.
+ {% endblock %}
+ <hr />
+ <div>
+ <p>{{ gettext('You can learn more about Taler on our main <a href="{site}">website</a>.').format(site="https://taler.net/") }}</p>
+ <div style="flex-grow:1"></div>
+ <p>Copyright © 2014—2020 Taler Systems SA</p>
+ </div>
+ </section>
+</body>
+</html>
diff --git a/talermerchantdemos/blog/templates/confirm_refund.html b/talermerchantdemos/blog/templates/confirm_refund.html
@@ -1,19 +0,0 @@
-{% extends "templates/base.html" %}
-{% block main %}
- <h1>Refund Article?</h1>
-
- <p>
- Do you want to get a refund for the article <em>{{ article_name }}</em>? After you've requested a refund,
- you won't be able to read the article anymore.
- </p>
-
- <p>
- You will only be able to receive the refund on the same wallet that you've used to pay
- for this article originally.
- </p>
-
- <form action="{{ url_for('refund', order_id=order_id) }}" method="POST">
- <input type="text" name="article_name" value={{ article_name}} hidden>
- <input type="submit" value="Request refund">
- </form>
-{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/confirm_refund.html.j2 b/talermerchantdemos/blog/templates/confirm_refund.html.j2
@@ -0,0 +1,22 @@
+{% extends "templates/base.html.j2" %}
+{% block main %}
+ <h1>{{ gettext("Confirm refund request for article"))</h1>
+
+ <p>
+ {{
+ gettext("Do you want to get a refund for the article <em>{name}</em>?").format(name=article_name) +
+ gettext("After you have requested a refund, you won't be able to read the article anymore.")
+ }}
+ </p>
+
+ <p>
+ {{
+ gettext ("You will only be able to receive the refund on the same wallet that you have used to pay for this article originally.")
+ }}
+ </p>
+
+ <form action="{{ url_for('refund', order_id=order_id) }}" method="POST">
+ <input type="text" name="article_name" value={{ article_name}} hidden>
+ <input type="submit" value="Request refund">
+ </form>
+{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/error.html b/talermerchantdemos/blog/templates/error.html
@@ -1,22 +0,0 @@
-{% extends "templates/base.html" %}
-{% block main %}
- <h1>An Error Occurred</h1>
-
- <p>{{ message }}</p>
-
- {% if status_code %}
- <p>The backend returned status code {{ status_code }}.</p>
- {% endif %}
-
- {% if json %}
- <p>Backend Response:</p>
- <pre>{{ json }}</pre>
- {% endif %}
-
- {% if stack %}
- <p>Stack trace:</p>
- <pre>
- {{ stack }}
- </pre>
- {% endif %}
-{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/error.html.j2 b/talermerchantdemos/blog/templates/error.html.j2
@@ -0,0 +1,24 @@
+{% extends "templates/base.html.j2" %}
+{% block main %}
+ <h1>{{ gettext("Error encountered") }}</h1>
+
+ <p>{{ message }}</p>
+
+ {% if status_code %}
+ <p>
+ {{ gettext ("The backend returned status code {code}.").format(code=status_code) }}.
+ </p>
+ {% endif %}
+
+ {% if json %}
+ <p>{{gettext("Backend response:")}}</p>
+ <pre>{{ json }}</pre>
+ {% endif %}
+
+ {% if stack %}
+ <p>{{gettext("Stack trace:")}}</p>
+ <pre>
+ {{ stack }}
+ </pre>
+ {% endif %}
+{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/index.html b/talermerchantdemos/blog/templates/index.html
@@ -1,40 +0,0 @@
-{% extends "templates/base.html" %}
-{% block main %}
- <h1>Essay Shop: Free Software, Free Society</h1>
- <div style="font-size: smaller;">
- <p>This is the second edition of <cite>Free Software, Free Society: Selected Essays of Richard M. Stallman.</cite><br>
- Free Software Foundation<br>
- 51 Franklin Street, Fifth Floor<br>
- Boston, MA 02110-1335
- <br>
- Copyright © 2002, 2010 Free Software Foundation, Inc.
- </p>
-
- <p>Verbatim copying and distribution of this entire book are permitted
- worldwide, without royalty, in any medium, provided this notice is
- preserved. Permission is granted to copy and distribute translations
- of this book from the original English into another language provided
- the translation has been approved by the Free Software Foundation and
- the copyright notice and this permission notice are preserved on all
- copies.
- </p>
- <p>ISBN 978-0-9831592-0-9</p>
- </div>
-
- <h2>Chapters</h2>
- <div>
- Click on an individual chapter to to purchase it. You can
- get free, virtual money to buy articles on this page at the <a href="{{ env('TALER_ENV_URL_BANK', '#') }}">bank</a>.
- </div>
-
- <div>
- {% for article in articles %}
- <div class="notice">
- <h3><a href="{{ url_for('article', article_name=article.slug) }}">{{article.title}}</a></h3>
- <p>{{ article.teaser|safe }} <a href="{{ url_for('article', article_name=article.slug) }}">(Pay to read more...)</a></p>
- </div>
- {% else %}
- <em>(No articles available)</em>
- {% endfor %}
- </div>
-{% endblock main %}
diff --git a/talermerchantdemos/blog/templates/show_refund.html b/talermerchantdemos/blog/templates/show_refund.html
@@ -1,28 +0,0 @@
-{% extends "templates/base.html" %}
-
-{% block main %}
-
-<h1>Refund</h1>
-
-<div class="taler-installed-hide">
- <p>
- Looks like your browser doesn't support GNU Taler payments. You can try
- installing a <a href="https://taler.net/en/wallet.html">wallet browser extension</a>.
- </p>
-</div>
-
-<div>
-
- <p>
- You can use this QR code to get a refund with your mobile wallet:
- </p>
-
- {{ qrcode_svg | safe }}
-
- <p>
- Click <a href="{{ taler_refund_uri }}">this link</a> to open your system's Taler wallet if it exists.
- </p>
-
-</div>
-
-{% endblock main %}
diff --git a/talermerchantdemos/static/__init__.py b/talermerchantdemos/static/__init__.py
@@ -0,0 +1 @@
+app.static_folder = 'static'
diff --git a/talermerchantdemos/static/demo.css b/talermerchantdemos/static/demo.css
@@ -1,69 +0,0 @@
-/* style common to all demo pages */
-
-.demobar h1 {
- text-align: center;
-}
-.demobar > p {
- padding: 0.5em;
-}
-.demobar a,
-.demobar a:visited {
- color: inherit;
-}
-.adorn-brackets::before {
- content: "❬";
- color: #aa3939;
-}
-.adorn-brackets::after {
- content: "❭";
- color: #aa3939;
-}
-.tt {
- font-family: 'Lucida Console', Monaco, monospace;
-}
-
-.informational-ok {
- background: lightgreen;
- border-radius: 1em;
- padding: 0.5em;
-}
-
-.informational-fail {
- background: lightpink;
- border-radius: 1em;
- padding: 0.5em;
-}
-
-.content {
- overflow-x: auto;
-}
-.demobar {
- overflow-x: auto;
- background-color: #033;
- color: white;
-}
-
-body {
- overflow-y: scroll;
-}
-
-@media (min-width: 500px) {
- .content {
- margin-left: 25%;
- padding-left: 2em;
- margin-right: 1em;
- overflow-x: auto;
- }
- .demobar {
- height: 100%;
- margin: 0;
- top: 0;
- left: 0;
- background-color: #033;
- color: white;
- position: fixed;
- width: 25%;
- padding-right: 1em;
- overflow: auto;
- }
-}
diff --git a/talermerchantdemos/static/demo.scss b/talermerchantdemos/static/demo.scss
@@ -0,0 +1,82 @@
+/* style common to all demo pages */
+
+.demobar h1 {
+ text-align: center;
+}
+.demobar > p {
+ padding: 0.5em;
+}
+.demobar a,
+.demobar a:visited {
+ color: inherit;
+}
+.adorn-brackets::before {
+ content: "❬";
+ color: #aa3939;
+}
+.adorn-brackets::after {
+ content: "❭";
+ color: #aa3939;
+}
+.tt {
+ font-family: 'Lucida Console', Monaco, monospace;
+}
+
+.informational-ok {
+ background: lightgreen;
+ border-radius: 1em;
+ padding: 0.5em;
+}
+
+.informational-fail {
+ background: lightpink;
+ border-radius: 1em;
+ padding: 0.5em;
+}
+
+.content {
+ overflow-x: auto;
+}
+.demobar {
+ overflow-x: auto;
+ background-color: #033;
+ color: white;
+}
+
+body {
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+body * {
+ /* margin-left: 0.5vw; */
+ left: 0.1vw;
+}
+
+@media (min-width: 500px) {
+ .content {
+ /* margin-left: 0vw; */
+ padding-left: 2em;
+ margin-right: 1em;
+ overflow-x: hidden;
+ overflow-y: auto;
+ }
+ .demobar {
+ /* height: 100%; */
+ /* width: 25%; */
+ /* NOTE: Please use "vh"/"vw" instead of "%" when possible, in the future. */
+ height: min-content;
+ width: 100vw;
+ margin: 0;
+ top: 0;
+ left: 0;
+ background-color: #033;
+ color: white;
+ position: relative;
+ padding-right: 1em;
+ overflow-x: hidden;
+ overflow-y: auto;
+ text-align: center;
+ }
+}
+
diff --git a/talermerchantdemos/static/navbar.css b/talermerchantdemos/static/navbar.css
@@ -0,0 +1,75 @@
+/**
+ * @author Torsten Grothoff
+ * @name navbar.css
+ * @description Makes the navigation bar have styles
+ * @license LGPL-3.0-or-later
+ */
+.navcontainer {
+ overflow: hidden;
+ background: #144;
+ margin-bottom: 50px;
+ width: 100%;
+ color: white;
+ position: -webkit-sticky;
+ position: sticky;
+ top: 0px;
+ width: 100vw;
+ backdrop-filter: blur(10px);
+ opacity: 1;
+ z-index: 10000;
+}
+
+nav {
+ left: 1vw;
+ position: relative;
+ background: #144;
+ z-index: 10000;
+}
+
+nav a, nav span, .navbtn {
+ border: none;
+ color: white;
+ text-align: center;
+ text-decoration: none;
+ display: inline-block;
+ font-size: 16px;
+ background: #00000000;
+ height: inherit;
+}
+
+nav a, nav span, .navbtn {
+ padding: 15px 32px;
+}
+
+nav a:hover, nav span:hover, .navbtn:hover {
+ background: #00000022;
+}
+
+nav a.active, nav span.active, .navbtn.active {
+ background-color: #4CAF50;
+}
+
+nav a.active:hover, nav span.active:hover, .navbtn.active:hover {
+ background: #377c39;
+}
+
+nav a, nav span, .navbtn {
+ cursor: pointer;
+}
+
+nav .right {
+ float: right;
+ margin-right: 5vw;
+}
+nav .right div.nav {
+ display: none;
+}
+nav .right div.nav:hover {
+ display: block;
+}
+
+nav .right:hover div.nav {
+ display: block;
+}
+
+/*# sourceMappingURL=navbar.css.map */
diff --git a/talermerchantdemos/static/navbar.css.map b/talermerchantdemos/static/navbar.css.map
@@ -0,0 +1 @@
+{"version":3,"sourceRoot":"","sources":["navbar.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEJ;EACI;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAGJ;EACI;;;AAEJ;EAiCI;EACA;;AAPA;EACI;;AAEJ;EACI;;;AAMJ;EACI","file":"navbar.css"}
+\ No newline at end of file
diff --git a/talermerchantdemos/static/navbar.scss b/talermerchantdemos/static/navbar.scss
@@ -0,0 +1,103 @@
+/**
+ * @author Torsten Grothoff
+ * @name navbar.css
+ * @description Makes the navigation bar have styles
+ * @license LGPL-3.0-or-later
+ */
+
+
+.navcontainer{
+ overflow:hidden;
+ background:#144;
+ margin-bottom:50px;
+ width:100%;
+ color:white;
+ position:-webkit-sticky;
+ position:sticky;
+ top:0px;
+ width: 100vw;
+ backdrop-filter: blur(10px);
+ opacity: 1;
+ z-index: 10000;
+}
+nav {
+ left: 1vw;
+ position: relative;
+ background:#144;
+ z-index: 10000;
+}
+
+nav a, nav span,.navbtn {
+ border: none;
+ color: white;
+ text-align: center;
+ text-decoration: none;
+ display: inline-block;
+ font-size: 16px;
+ background: #00000000;
+ height: inherit;
+}
+nav a, nav span,.navbtn{
+ padding: 15px 32px;
+}
+
+nav a:hover, nav span:hover,.navbtn:hover {
+ background: #00000022;
+}
+
+nav a.active, nav span.active,.navbtn.active {
+ background-color: #4CAF50;
+}
+
+nav a.active:hover, nav span.active:hover,.navbtn.active:hover {
+ background: #377c39;
+}
+
+nav a, nav span,.navbtn {
+ cursor: pointer;
+}
+nav .right {
+ // input[type=checkbox] {
+ // // // opacity: 0;
+ // // // position: absolute;
+ // // position: relative;
+ // // left:0.5vw;
+ // // // top:0;
+ // // width: inherit;
+ // // height: inherit;
+
+ // // $sx: 1.5;
+ // // $sy: 1.5;
+
+ // // -ms-transform: scale($sx,$sy); /* IE */
+ // // -moz-transform: scale($sx,$sy); /* FF */
+ // // -webkit-transform: scale($sx,$sy); /* Safari and Chrome */
+ // // -o-transform: scale($sx,$sy); /* Opera */
+ // // transform: scale($sx,$sy);
+ // // float:right;
+ // opacity: 0;
+ // }
+ // input[type=checkbox]:checked + div.nav {
+ // display: block;
+ // }
+ // input[type=checkbox] + div.nav {
+ // display: none;
+ // }
+ div.nav {
+ display: none;
+ }
+ div.nav:hover {
+ display: block;
+ }
+ float:right;
+ margin-right: 5vw;
+}
+nav .right:hover {
+ div.nav {
+ display:block;
+ }
+}
+
+// input[type=checkbox]:checked + label {
+// color: red;
+// }
+\ No newline at end of file
diff --git a/talermerchantdemos/static/pure.css b/talermerchantdemos/static/pure.css
@@ -1,1508 +0,0 @@
-/*!
-Pure v0.6.2
-Copyright 2013 Yahoo!
-Licensed under the BSD License.
-https://github.com/yahoo/pure/blob/master/LICENSE.md
-*/
-/*!
-normalize.css v^3.0 | MIT License | git.io/normalize
-Copyright (c) Nicolas Gallagher and Jonathan Neal
-*/
-/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
-
-/**
- * 1. Set default font family to sans-serif.
- * 2. Prevent iOS and IE text size adjust after device orientation change,
- * without disabling user zoom.
- */
-
-html {
- font-family: sans-serif; /* 1 */
- -ms-text-size-adjust: 100%; /* 2 */
- -webkit-text-size-adjust: 100%; /* 2 */
-}
-
-/**
- * Remove default margin.
- */
-
-body {
- margin: 0;
-}
-
-/* HTML5 display definitions
- ========================================================================== */
-
-/**
- * Correct `block` display not defined for any HTML5 element in IE 8/9.
- * Correct `block` display not defined for `details` or `summary` in IE 10/11
- * and Firefox.
- * Correct `block` display not defined for `main` in IE 11.
- */
-
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-main,
-menu,
-nav,
-section,
-summary {
- display: block;
-}
-
-/**
- * 1. Correct `inline-block` display not defined in IE 8/9.
- * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
- */
-
-audio,
-canvas,
-progress,
-video {
- display: inline-block; /* 1 */
- vertical-align: baseline; /* 2 */
-}
-
-/**
- * Prevent modern browsers from displaying `audio` without controls.
- * Remove excess height in iOS 5 devices.
- */
-
-audio:not([controls]) {
- display: none;
- height: 0;
-}
-
-/**
- * Address `[hidden]` styling not present in IE 8/9/10.
- * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
- */
-
-[hidden],
-template {
- display: none;
-}
-
-/* Links
- ========================================================================== */
-
-/**
- * Remove the gray background color from active links in IE 10.
- */
-
-a {
- background-color: transparent;
-}
-
-/**
- * Improve readability of focused elements when they are also in an
- * active/hover state.
- */
-
-a:active,
-a:hover {
- outline: 0;
-}
-
-/* Text-level semantics
- ========================================================================== */
-
-/**
- * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
- */
-
-abbr[title] {
- border-bottom: 1px dotted;
-}
-
-/**
- * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
- */
-
-b,
-strong {
- font-weight: bold;
-}
-
-/**
- * Address styling not present in Safari and Chrome.
- */
-
-dfn {
- font-style: italic;
-}
-
-/**
- * Address variable `h1` font-size and margin within `section` and `article`
- * contexts in Firefox 4+, Safari, and Chrome.
- */
-
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-
-/**
- * Address styling not present in IE 8/9.
- */
-
-mark {
- background: #ff0;
- color: #000;
-}
-
-/**
- * Address inconsistent and variable font size in all browsers.
- */
-
-small {
- font-size: 80%;
-}
-
-/**
- * Prevent `sub` and `sup` affecting `line-height` in all browsers.
- */
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sup {
- top: -0.5em;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-/* Embedded content
- ========================================================================== */
-
-/**
- * Remove border when inside `a` element in IE 8/9/10.
- */
-
-img {
- border: 0;
-}
-
-/**
- * Correct overflow not hidden in IE 9/10/11.
- */
-
-svg:not(:root) {
- overflow: hidden;
-}
-
-/* Grouping content
- ========================================================================== */
-
-/**
- * Address margin not present in IE 8/9 and Safari.
- */
-
-figure {
- margin: 1em 40px;
-}
-
-/**
- * Address differences between Firefox and other browsers.
- */
-
-hr {
- box-sizing: content-box;
- height: 0;
-}
-
-/**
- * Contain overflow in all browsers.
- */
-
-pre {
- overflow: auto;
-}
-
-/**
- * Address odd `em`-unit font size rendering in all browsers.
- */
-
-code,
-kbd,
-pre,
-samp {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-
-/* Forms
- ========================================================================== */
-
-/**
- * Known limitation: by default, Chrome and Safari on OS X allow very limited
- * styling of `select`, unless a `border` property is set.
- */
-
-/**
- * 1. Correct color not being inherited.
- * Known issue: affects color of disabled elements.
- * 2. Correct font properties not being inherited.
- * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
- */
-
-button,
-input,
-optgroup,
-select,
-textarea {
- color: inherit; /* 1 */
- font: inherit; /* 2 */
- margin: 0; /* 3 */
-}
-
-/**
- * Address `overflow` set to `hidden` in IE 8/9/10/11.
- */
-
-button {
- overflow: visible;
-}
-
-/**
- * Address inconsistent `text-transform` inheritance for `button` and `select`.
- * All other form control elements do not inherit `text-transform` values.
- * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
- * Correct `select` style inheritance in Firefox.
- */
-
-button,
-select {
- text-transform: none;
-}
-
-/**
- * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
- * and `video` controls.
- * 2. Correct inability to style clickable `input` types in iOS.
- * 3. Improve usability and consistency of cursor style between image-type
- * `input` and others.
- */
-
-button,
-html input[type="button"], /* 1 */
-input[type="reset"],
-input[type="submit"] {
- -webkit-appearance: button; /* 2 */
- cursor: pointer; /* 3 */
-}
-
-/**
- * Re-set default cursor for disabled elements.
- */
-
-button[disabled],
-html input[disabled] {
- cursor: default;
-}
-
-/**
- * Remove inner padding and border in Firefox 4+.
- */
-
-button::-moz-focus-inner,
-input::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-
-/**
- * Address Firefox 4+ setting `line-height` on `input` using `!important` in
- * the UA stylesheet.
- */
-
-input {
- line-height: normal;
-}
-
-/**
- * It's recommended that you don't attempt to style these elements.
- * Firefox's implementation doesn't respect box-sizing, padding, or width.
- *
- * 1. Address box sizing set to `content-box` in IE 8/9/10.
- * 2. Remove excess padding in IE 8/9/10.
- */
-
-input[type="checkbox"],
-input[type="radio"] {
- box-sizing: border-box; /* 1 */
- padding: 0; /* 2 */
-}
-
-/**
- * Fix the cursor style for Chrome's increment/decrement buttons. For certain
- * `font-size` values of the `input`, it causes the cursor style of the
- * decrement button to change from `default` to `text`.
- */
-
-input[type="number"]::-webkit-inner-spin-button,
-input[type="number"]::-webkit-outer-spin-button {
- height: auto;
-}
-
-/**
- * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
- * 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
- */
-
-input[type="search"] {
- -webkit-appearance: textfield; /* 1 */
- box-sizing: content-box; /* 2 */
-}
-
-/**
- * Remove inner padding and search cancel button in Safari and Chrome on OS X.
- * Safari (but not Chrome) clips the cancel button when the search input has
- * padding (and `textfield` appearance).
- */
-
-input[type="search"]::-webkit-search-cancel-button,
-input[type="search"]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-/**
- * Define consistent border, margin, and padding.
- */
-
-fieldset {
- border: 1px solid #c0c0c0;
- margin: 0 2px;
- padding: 0.35em 0.625em 0.75em;
-}
-
-/**
- * 1. Correct `color` not being inherited in IE 8/9/10/11.
- * 2. Remove padding so people aren't caught out if they zero out fieldsets.
- */
-
-legend {
- border: 0; /* 1 */
- padding: 0; /* 2 */
-}
-
-/**
- * Remove default vertical scrollbar in IE 8/9/10/11.
- */
-
-textarea {
- overflow: auto;
-}
-
-/**
- * Don't inherit the `font-weight` (applied by a rule above).
- * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
- */
-
-optgroup {
- font-weight: bold;
-}
-
-/* Tables
- ========================================================================== */
-
-/**
- * Remove most spacing between table cells.
- */
-
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-
-td,
-th {
- padding: 0;
-}
-
-/*csslint important:false*/
-
-/* ==========================================================================
- Pure Base Extras
- ========================================================================== */
-
-/**
- * Extra rules that Pure adds on top of Normalize.css
- */
-
-/**
- * Always hide an element when it has the `hidden` HTML attribute.
- */
-
-.hidden,
-[hidden] {
- display: none !important;
-}
-
-/**
- * Add this class to an image to make it fit within it's fluid parent wrapper while maintaining
- * aspect ratio.
- */
-.pure-img {
- max-width: 100%;
- height: auto;
- display: block;
-}
-
-/*csslint regex-selectors:false, known-properties:false, duplicate-properties:false*/
-
-.pure-g {
- letter-spacing: -0.31em; /* Webkit: collapse white-space between units */
- *letter-spacing: normal; /* reset IE < 8 */
- *word-spacing: -0.43em; /* IE < 8: collapse white-space between units */
- text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */
-
- /*
- Sets the font stack to fonts known to work properly with the above letter
- and word spacings. See: https://github.com/yahoo/pure/issues/41/
-
- The following font stack makes Pure Grids work on all known environments.
-
- * FreeSans: Ships with many Linux distros, including Ubuntu
-
- * Arimo: Ships with Chrome OS. Arimo has to be defined before Helvetica and
- Arial to get picked up by the browser, even though neither is available
- in Chrome OS.
-
- * Droid Sans: Ships with all versions of Android.
-
- * Helvetica, Arial, sans-serif: Common font stack on OS X and Windows.
- */
- font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif;
-
- /* Use flexbox when possible to avoid `letter-spacing` side-effects. */
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-flow: row wrap;
- -ms-flex-flow: row wrap;
- flex-flow: row wrap;
-
- /* Prevents distributing space between rows */
- -webkit-align-content: flex-start;
- -ms-flex-line-pack: start;
- align-content: flex-start;
-}
-
-/* IE10 display: -ms-flexbox (and display: flex in IE 11) does not work inside a table; fall back to block and rely on font hack */
-@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
- table .pure-g {
- display: block;
- }
-}
-
-/* Opera as of 12 on Windows needs word-spacing.
- The ".opera-only" selector is used to prevent actual prefocus styling
- and is not required in markup.
-*/
-.opera-only :-o-prefocus,
-.pure-g {
- word-spacing: -0.43em;
-}
-
-.pure-u {
- display: inline-block;
- *display: inline; /* IE < 8: fake inline-block */
- zoom: 1;
- letter-spacing: normal;
- word-spacing: normal;
- vertical-align: top;
- text-rendering: auto;
-}
-
-/*
-Resets the font family back to the OS/browser's default sans-serif font,
-this the same font stack that Normalize.css sets for the `body`.
-*/
-.pure-g [class *= "pure-u"] {
- font-family: sans-serif;
-}
-
-.pure-u-1,
-.pure-u-1-1,
-.pure-u-1-2,
-.pure-u-1-3,
-.pure-u-2-3,
-.pure-u-1-4,
-.pure-u-3-4,
-.pure-u-1-5,
-.pure-u-2-5,
-.pure-u-3-5,
-.pure-u-4-5,
-.pure-u-5-5,
-.pure-u-1-6,
-.pure-u-5-6,
-.pure-u-1-8,
-.pure-u-3-8,
-.pure-u-5-8,
-.pure-u-7-8,
-.pure-u-1-12,
-.pure-u-5-12,
-.pure-u-7-12,
-.pure-u-11-12,
-.pure-u-1-24,
-.pure-u-2-24,
-.pure-u-3-24,
-.pure-u-4-24,
-.pure-u-5-24,
-.pure-u-6-24,
-.pure-u-7-24,
-.pure-u-8-24,
-.pure-u-9-24,
-.pure-u-10-24,
-.pure-u-11-24,
-.pure-u-12-24,
-.pure-u-13-24,
-.pure-u-14-24,
-.pure-u-15-24,
-.pure-u-16-24,
-.pure-u-17-24,
-.pure-u-18-24,
-.pure-u-19-24,
-.pure-u-20-24,
-.pure-u-21-24,
-.pure-u-22-24,
-.pure-u-23-24,
-.pure-u-24-24 {
- display: inline-block;
- *display: inline;
- zoom: 1;
- letter-spacing: normal;
- word-spacing: normal;
- vertical-align: top;
- text-rendering: auto;
-}
-
-.pure-u-1-24 {
- width: 4.1667%;
- *width: 4.1357%;
-}
-
-.pure-u-1-12,
-.pure-u-2-24 {
- width: 8.3333%;
- *width: 8.3023%;
-}
-
-.pure-u-1-8,
-.pure-u-3-24 {
- width: 12.5000%;
- *width: 12.4690%;
-}
-
-.pure-u-1-6,
-.pure-u-4-24 {
- width: 16.6667%;
- *width: 16.6357%;
-}
-
-.pure-u-1-5 {
- width: 20%;
- *width: 19.9690%;
-}
-
-.pure-u-5-24 {
- width: 20.8333%;
- *width: 20.8023%;
-}
-
-.pure-u-1-4,
-.pure-u-6-24 {
- width: 25%;
- *width: 24.9690%;
-}
-
-.pure-u-7-24 {
- width: 29.1667%;
- *width: 29.1357%;
-}
-
-.pure-u-1-3,
-.pure-u-8-24 {
- width: 33.3333%;
- *width: 33.3023%;
-}
-
-.pure-u-3-8,
-.pure-u-9-24 {
- width: 37.5000%;
- *width: 37.4690%;
-}
-
-.pure-u-2-5 {
- width: 40%;
- *width: 39.9690%;
-}
-
-.pure-u-5-12,
-.pure-u-10-24 {
- width: 41.6667%;
- *width: 41.6357%;
-}
-
-.pure-u-11-24 {
- width: 45.8333%;
- *width: 45.8023%;
-}
-
-.pure-u-1-2,
-.pure-u-12-24 {
- width: 50%;
- *width: 49.9690%;
-}
-
-.pure-u-13-24 {
- width: 54.1667%;
- *width: 54.1357%;
-}
-
-.pure-u-7-12,
-.pure-u-14-24 {
- width: 58.3333%;
- *width: 58.3023%;
-}
-
-.pure-u-3-5 {
- width: 60%;
- *width: 59.9690%;
-}
-
-.pure-u-5-8,
-.pure-u-15-24 {
- width: 62.5000%;
- *width: 62.4690%;
-}
-
-.pure-u-2-3,
-.pure-u-16-24 {
- width: 66.6667%;
- *width: 66.6357%;
-}
-
-.pure-u-17-24 {
- width: 70.8333%;
- *width: 70.8023%;
-}
-
-.pure-u-3-4,
-.pure-u-18-24 {
- width: 75%;
- *width: 74.9690%;
-}
-
-.pure-u-19-24 {
- width: 79.1667%;
- *width: 79.1357%;
-}
-
-.pure-u-4-5 {
- width: 80%;
- *width: 79.9690%;
-}
-
-.pure-u-5-6,
-.pure-u-20-24 {
- width: 83.3333%;
- *width: 83.3023%;
-}
-
-.pure-u-7-8,
-.pure-u-21-24 {
- width: 87.5000%;
- *width: 87.4690%;
-}
-
-.pure-u-11-12,
-.pure-u-22-24 {
- width: 91.6667%;
- *width: 91.6357%;
-}
-
-.pure-u-23-24 {
- width: 95.8333%;
- *width: 95.8023%;
-}
-
-.pure-u-1,
-.pure-u-1-1,
-.pure-u-5-5,
-.pure-u-24-24 {
- width: 100%;
-}
-.pure-button {
- /* Structure */
- display: inline-block;
- zoom: 1;
- line-height: normal;
- white-space: nowrap;
- vertical-align: middle;
- text-align: center;
- cursor: pointer;
- -webkit-user-drag: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- box-sizing: border-box;
-}
-
-/* Firefox: Get rid of the inner focus border */
-.pure-button::-moz-focus-inner {
- padding: 0;
- border: 0;
-}
-
-/* Inherit .pure-g styles */
-.pure-button-group {
- letter-spacing: -0.31em; /* Webkit: collapse white-space between units */
- *letter-spacing: normal; /* reset IE < 8 */
- *word-spacing: -0.43em; /* IE < 8: collapse white-space between units */
- text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */
-}
-
-.opera-only :-o-prefocus,
-.pure-button-group {
- word-spacing: -0.43em;
-}
-
-.pure-button-group .pure-button {
- letter-spacing: normal;
- word-spacing: normal;
- vertical-align: top;
- text-rendering: auto;
-}
-
-/*csslint outline-none:false*/
-
-.pure-button {
- font-family: inherit;
- font-size: 100%;
- padding: 0.5em 1em;
- color: #444; /* rgba not supported (IE 8) */
- color: rgba(0, 0, 0, 0.80); /* rgba supported */
- border: 1px solid #999; /*IE 6/7/8*/
- border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
- background-color: #E6E6E6;
- text-decoration: none;
- border-radius: 2px;
-}
-
-.pure-button-hover,
-.pure-button:hover,
-.pure-button:focus {
- /* csslint ignore:start */
- filter: alpha(opacity=90);
- /* csslint ignore:end */
- background-image: -webkit-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
- background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
-}
-.pure-button:focus {
- outline: 0;
-}
-.pure-button-active,
-.pure-button:active {
- box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;
- border-color: #000\9;
-}
-
-.pure-button[disabled],
-.pure-button-disabled,
-.pure-button-disabled:hover,
-.pure-button-disabled:focus,
-.pure-button-disabled:active {
- border: none;
- background-image: none;
- /* csslint ignore:start */
- filter: alpha(opacity=40);
- /* csslint ignore:end */
- opacity: 0.40;
- cursor: not-allowed;
- box-shadow: none;
- pointer-events: none;
-}
-
-.pure-button-hidden {
- display: none;
-}
-
-.pure-button-primary,
-.pure-button-selected,
-a.pure-button-primary,
-a.pure-button-selected {
- background-color: rgb(0, 120, 231);
- color: #fff;
-}
-
-/* Button Groups */
-.pure-button-group .pure-button {
- margin: 0;
- border-radius: 0;
- border-right: 1px solid #111; /* fallback color for rgba() for IE7/8 */
- border-right: 1px solid rgba(0, 0, 0, 0.2);
-
-}
-
-.pure-button-group .pure-button:first-child {
- border-top-left-radius: 2px;
- border-bottom-left-radius: 2px;
-}
-.pure-button-group .pure-button:last-child {
- border-top-right-radius: 2px;
- border-bottom-right-radius: 2px;
- border-right: none;
-}
-
-/*csslint box-model:false*/
-/*
-Box-model set to false because we're setting a height on select elements, which
-also have border and padding. This is done because some browsers don't render
-the padding. We explicitly set the box-model for select elements to border-box,
-so we can ignore the csslint warning.
-*/
-
-.pure-form input[type="text"],
-.pure-form input[type="password"],
-.pure-form input[type="email"],
-.pure-form input[type="url"],
-.pure-form input[type="date"],
-.pure-form input[type="month"],
-.pure-form input[type="time"],
-.pure-form input[type="datetime"],
-.pure-form input[type="datetime-local"],
-.pure-form input[type="week"],
-.pure-form input[type="number"],
-.pure-form input[type="search"],
-.pure-form input[type="tel"],
-.pure-form input[type="color"],
-.pure-form select,
-.pure-form textarea {
- padding: 0.5em 0.6em;
- display: inline-block;
- border: 1px solid #ccc;
- box-shadow: inset 0 1px 3px #ddd;
- border-radius: 4px;
- vertical-align: middle;
- box-sizing: border-box;
-}
-
-/*
-Need to separate out the :not() selector from the rest of the CSS 2.1 selectors
-since IE8 won't execute CSS that contains a CSS3 selector.
-*/
-.pure-form input:not([type]) {
- padding: 0.5em 0.6em;
- display: inline-block;
- border: 1px solid #ccc;
- box-shadow: inset 0 1px 3px #ddd;
- border-radius: 4px;
- box-sizing: border-box;
-}
-
-
-/* Chrome (as of v.32/34 on OS X) needs additional room for color to display. */
-/* May be able to remove this tweak as color inputs become more standardized across browsers. */
-.pure-form input[type="color"] {
- padding: 0.2em 0.5em;
-}
-
-
-.pure-form input[type="text"]:focus,
-.pure-form input[type="password"]:focus,
-.pure-form input[type="email"]:focus,
-.pure-form input[type="url"]:focus,
-.pure-form input[type="date"]:focus,
-.pure-form input[type="month"]:focus,
-.pure-form input[type="time"]:focus,
-.pure-form input[type="datetime"]:focus,
-.pure-form input[type="datetime-local"]:focus,
-.pure-form input[type="week"]:focus,
-.pure-form input[type="number"]:focus,
-.pure-form input[type="search"]:focus,
-.pure-form input[type="tel"]:focus,
-.pure-form input[type="color"]:focus,
-.pure-form select:focus,
-.pure-form textarea:focus {
- outline: 0;
- border-color: #129FEA;
-}
-
-/*
-Need to separate out the :not() selector from the rest of the CSS 2.1 selectors
-since IE8 won't execute CSS that contains a CSS3 selector.
-*/
-.pure-form input:not([type]):focus {
- outline: 0;
- border-color: #129FEA;
-}
-
-.pure-form input[type="file"]:focus,
-.pure-form input[type="radio"]:focus,
-.pure-form input[type="checkbox"]:focus {
- outline: thin solid #129FEA;
- outline: 1px auto #129FEA;
-}
-.pure-form .pure-checkbox,
-.pure-form .pure-radio {
- margin: 0.5em 0;
- display: block;
-}
-
-.pure-form input[type="text"][disabled],
-.pure-form input[type="password"][disabled],
-.pure-form input[type="email"][disabled],
-.pure-form input[type="url"][disabled],
-.pure-form input[type="date"][disabled],
-.pure-form input[type="month"][disabled],
-.pure-form input[type="time"][disabled],
-.pure-form input[type="datetime"][disabled],
-.pure-form input[type="datetime-local"][disabled],
-.pure-form input[type="week"][disabled],
-.pure-form input[type="number"][disabled],
-.pure-form input[type="search"][disabled],
-.pure-form input[type="tel"][disabled],
-.pure-form input[type="color"][disabled],
-.pure-form select[disabled],
-.pure-form textarea[disabled] {
- cursor: not-allowed;
- background-color: #eaeded;
- color: #cad2d3;
-}
-
-/*
-Need to separate out the :not() selector from the rest of the CSS 2.1 selectors
-since IE8 won't execute CSS that contains a CSS3 selector.
-*/
-.pure-form input:not([type])[disabled] {
- cursor: not-allowed;
- background-color: #eaeded;
- color: #cad2d3;
-}
-.pure-form input[readonly],
-.pure-form select[readonly],
-.pure-form textarea[readonly] {
- background-color: #eee; /* menu hover bg color */
- color: #777; /* menu text color */
- border-color: #ccc;
-}
-
-.pure-form input:focus:invalid,
-.pure-form textarea:focus:invalid,
-.pure-form select:focus:invalid {
- color: #b94a48;
- border-color: #e9322d;
-}
-.pure-form input[type="file"]:focus:invalid:focus,
-.pure-form input[type="radio"]:focus:invalid:focus,
-.pure-form input[type="checkbox"]:focus:invalid:focus {
- outline-color: #e9322d;
-}
-.pure-form select {
- /* Normalizes the height; padding is not sufficient. */
- height: 2.25em;
- border: 1px solid #ccc;
- background-color: white;
-}
-.pure-form select[multiple] {
- height: auto;
-}
-.pure-form label {
- margin: 0.5em 0 0.2em;
-}
-.pure-form fieldset {
- margin: 0;
- padding: 0.35em 0 0.75em;
- border: 0;
-}
-.pure-form legend {
- display: block;
- width: 100%;
- padding: 0.3em 0;
- margin-bottom: 0.3em;
- color: #333;
- border-bottom: 1px solid #e5e5e5;
-}
-
-.pure-form-stacked input[type="text"],
-.pure-form-stacked input[type="password"],
-.pure-form-stacked input[type="email"],
-.pure-form-stacked input[type="url"],
-.pure-form-stacked input[type="date"],
-.pure-form-stacked input[type="month"],
-.pure-form-stacked input[type="time"],
-.pure-form-stacked input[type="datetime"],
-.pure-form-stacked input[type="datetime-local"],
-.pure-form-stacked input[type="week"],
-.pure-form-stacked input[type="number"],
-.pure-form-stacked input[type="search"],
-.pure-form-stacked input[type="tel"],
-.pure-form-stacked input[type="color"],
-.pure-form-stacked input[type="file"],
-.pure-form-stacked select,
-.pure-form-stacked label,
-.pure-form-stacked textarea {
- display: block;
- margin: 0.25em 0;
-}
-
-/*
-Need to separate out the :not() selector from the rest of the CSS 2.1 selectors
-since IE8 won't execute CSS that contains a CSS3 selector.
-*/
-.pure-form-stacked input:not([type]) {
- display: block;
- margin: 0.25em 0;
-}
-.pure-form-aligned input,
-.pure-form-aligned textarea,
-.pure-form-aligned select,
-/* NOTE: pure-help-inline is deprecated. Use .pure-form-message-inline instead. */
-.pure-form-aligned .pure-help-inline,
-.pure-form-message-inline {
- display: inline-block;
- *display: inline;
- *zoom: 1;
- vertical-align: middle;
-}
-.pure-form-aligned textarea {
- vertical-align: top;
-}
-
-/* Aligned Forms */
-.pure-form-aligned .pure-control-group {
- margin-bottom: 0.5em;
-}
-.pure-form-aligned .pure-control-group label {
- text-align: right;
- display: inline-block;
- vertical-align: middle;
- width: 10em;
- margin: 0 1em 0 0;
-}
-.pure-form-aligned .pure-controls {
- margin: 1.5em 0 0 11em;
-}
-
-/* Rounded Inputs */
-.pure-form input.pure-input-rounded,
-.pure-form .pure-input-rounded {
- border-radius: 2em;
- padding: 0.5em 1em;
-}
-
-/* Grouped Inputs */
-.pure-form .pure-group fieldset {
- margin-bottom: 10px;
-}
-.pure-form .pure-group input,
-.pure-form .pure-group textarea {
- display: block;
- padding: 10px;
- margin: 0 0 -1px;
- border-radius: 0;
- position: relative;
- top: -1px;
-}
-.pure-form .pure-group input:focus,
-.pure-form .pure-group textarea:focus {
- z-index: 3;
-}
-.pure-form .pure-group input:first-child,
-.pure-form .pure-group textarea:first-child {
- top: 1px;
- border-radius: 4px 4px 0 0;
- margin: 0;
-}
-.pure-form .pure-group input:first-child:last-child,
-.pure-form .pure-group textarea:first-child:last-child {
- top: 1px;
- border-radius: 4px;
- margin: 0;
-}
-.pure-form .pure-group input:last-child,
-.pure-form .pure-group textarea:last-child {
- top: -2px;
- border-radius: 0 0 4px 4px;
- margin: 0;
-}
-.pure-form .pure-group button {
- margin: 0.35em 0;
-}
-
-.pure-form .pure-input-1 {
- width: 100%;
-}
-.pure-form .pure-input-3-4 {
- width: 75%;
-}
-.pure-form .pure-input-2-3 {
- width: 66%;
-}
-.pure-form .pure-input-1-2 {
- width: 50%;
-}
-.pure-form .pure-input-1-3 {
- width: 33%;
-}
-.pure-form .pure-input-1-4 {
- width: 25%;
-}
-
-/* Inline help for forms */
-/* NOTE: pure-help-inline is deprecated. Use .pure-form-message-inline instead. */
-.pure-form .pure-help-inline,
-.pure-form-message-inline {
- display: inline-block;
- padding-left: 0.3em;
- color: #666;
- vertical-align: middle;
- font-size: 0.875em;
-}
-
-/* Block help for forms */
-.pure-form-message {
- display: block;
- color: #666;
- font-size: 0.875em;
-}
-
-@media only screen and (max-width : 480px) {
- .pure-form button[type="submit"] {
- margin: 0.7em 0 0;
- }
-
- .pure-form input:not([type]),
- .pure-form input[type="text"],
- .pure-form input[type="password"],
- .pure-form input[type="email"],
- .pure-form input[type="url"],
- .pure-form input[type="date"],
- .pure-form input[type="month"],
- .pure-form input[type="time"],
- .pure-form input[type="datetime"],
- .pure-form input[type="datetime-local"],
- .pure-form input[type="week"],
- .pure-form input[type="number"],
- .pure-form input[type="search"],
- .pure-form input[type="tel"],
- .pure-form input[type="color"],
- .pure-form label {
- margin-bottom: 0.3em;
- display: block;
- }
-
- .pure-group input:not([type]),
- .pure-group input[type="text"],
- .pure-group input[type="password"],
- .pure-group input[type="email"],
- .pure-group input[type="url"],
- .pure-group input[type="date"],
- .pure-group input[type="month"],
- .pure-group input[type="time"],
- .pure-group input[type="datetime"],
- .pure-group input[type="datetime-local"],
- .pure-group input[type="week"],
- .pure-group input[type="number"],
- .pure-group input[type="search"],
- .pure-group input[type="tel"],
- .pure-group input[type="color"] {
- margin-bottom: 0;
- }
-
- .pure-form-aligned .pure-control-group label {
- margin-bottom: 0.3em;
- text-align: left;
- display: block;
- width: 100%;
- }
-
- .pure-form-aligned .pure-controls {
- margin: 1.5em 0 0 0;
- }
-
- /* NOTE: pure-help-inline is deprecated. Use .pure-form-message-inline instead. */
- .pure-form .pure-help-inline,
- .pure-form-message-inline,
- .pure-form-message {
- display: block;
- font-size: 0.75em;
- /* Increased bottom padding to make it group with its related input element. */
- padding: 0.2em 0 0.8em;
- }
-}
-
-/*csslint adjoining-classes: false, box-model:false*/
-.pure-menu {
- box-sizing: border-box;
-}
-
-.pure-menu-fixed {
- position: fixed;
- left: 0;
- top: 0;
- z-index: 3;
-}
-
-.pure-menu-list,
-.pure-menu-item {
- position: relative;
-}
-
-.pure-menu-list {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-.pure-menu-item {
- padding: 0;
- margin: 0;
- height: 100%;
-}
-
-.pure-menu-link,
-.pure-menu-heading {
- display: block;
- text-decoration: none;
- white-space: nowrap;
-}
-
-/* HORIZONTAL MENU */
-.pure-menu-horizontal {
- width: 100%;
- white-space: nowrap;
-}
-
-.pure-menu-horizontal .pure-menu-list {
- display: inline-block;
-}
-
-/* Initial menus should be inline-block so that they are horizontal */
-.pure-menu-horizontal .pure-menu-item,
-.pure-menu-horizontal .pure-menu-heading,
-.pure-menu-horizontal .pure-menu-separator {
- display: inline-block;
- *display: inline;
- zoom: 1;
- vertical-align: middle;
-}
-
-/* Submenus should still be display: block; */
-.pure-menu-item .pure-menu-item {
- display: block;
-}
-
-.pure-menu-children {
- display: none;
- position: absolute;
- left: 100%;
- top: 0;
- margin: 0;
- padding: 0;
- z-index: 3;
-}
-
-.pure-menu-horizontal .pure-menu-children {
- left: 0;
- top: auto;
- width: inherit;
-}
-
-.pure-menu-allow-hover:hover > .pure-menu-children,
-.pure-menu-active > .pure-menu-children {
- display: block;
- position: absolute;
-}
-
-/* Vertical Menus - show the dropdown arrow */
-.pure-menu-has-children > .pure-menu-link:after {
- padding-left: 0.5em;
- content: "\25B8";
- font-size: small;
-}
-
-/* Horizontal Menus - show the dropdown arrow */
-.pure-menu-horizontal .pure-menu-has-children > .pure-menu-link:after {
- content: "\25BE";
-}
-
-/* scrollable menus */
-.pure-menu-scrollable {
- overflow-y: scroll;
- overflow-x: hidden;
-}
-
-.pure-menu-scrollable .pure-menu-list {
- display: block;
-}
-
-.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list {
- display: inline-block;
-}
-
-.pure-menu-horizontal.pure-menu-scrollable {
- white-space: nowrap;
- overflow-y: hidden;
- overflow-x: auto;
- -ms-overflow-style: none;
- -webkit-overflow-scrolling: touch;
- /* a little extra padding for this style to allow for scrollbars */
- padding: .5em 0;
-}
-
-.pure-menu-horizontal.pure-menu-scrollable::-webkit-scrollbar {
- display: none;
-}
-
-/* misc default styling */
-
-.pure-menu-separator,
-.pure-menu-horizontal .pure-menu-children .pure-menu-separator {
- background-color: #ccc;
- height: 1px;
- margin: .3em 0;
-}
-
-.pure-menu-horizontal .pure-menu-separator {
- width: 1px;
- height: 1.3em;
- margin: 0 .3em ;
-}
-
-/* Need to reset the separator since submenu is vertical */
-.pure-menu-horizontal .pure-menu-children .pure-menu-separator {
- display: block;
- width: auto;
-}
-
-.pure-menu-heading {
- text-transform: uppercase;
- color: #565d64;
-}
-
-.pure-menu-link {
- color: #777;
-}
-
-.pure-menu-children {
- background-color: #fff;
-}
-
-.pure-menu-link,
-.pure-menu-disabled,
-.pure-menu-heading {
- padding: .5em 1em;
-}
-
-.pure-menu-disabled {
- opacity: .5;
-}
-
-.pure-menu-disabled .pure-menu-link:hover {
- background-color: transparent;
-}
-
-.pure-menu-active > .pure-menu-link,
-.pure-menu-link:hover,
-.pure-menu-link:focus {
- background-color: #eee;
-}
-
-.pure-menu-selected .pure-menu-link,
-.pure-menu-selected .pure-menu-link:visited {
- color: #000;
-}
-
-.pure-table {
- /* Remove spacing between table cells (from Normalize.css) */
- border-collapse: collapse;
- border-spacing: 0;
- empty-cells: show;
- border: 1px solid #cbcbcb;
-}
-
-.pure-table caption {
- color: #000;
- font: italic 85%/1 arial, sans-serif;
- padding: 1em 0;
- text-align: center;
-}
-
-.pure-table td,
-.pure-table th {
- border-left: 1px solid #cbcbcb;/* inner column border */
- border-width: 0 0 0 1px;
- font-size: inherit;
- margin: 0;
- overflow: visible; /*to make ths where the title is really long work*/
- padding: 0.5em 1em; /* cell padding */
-}
-
-/* Consider removing this next declaration block, as it causes problems when
-there's a rowspan on the first cell. Case added to the tests. issue#432 */
-.pure-table td:first-child,
-.pure-table th:first-child {
- border-left-width: 0;
-}
-
-.pure-table thead {
- background-color: #e0e0e0;
- color: #000;
- text-align: left;
- vertical-align: bottom;
-}
-
-/*
-striping:
- even - #fff (white)
- odd - #f2f2f2 (light gray)
-*/
-.pure-table td {
- background-color: transparent;
-}
-.pure-table-odd td {
- background-color: #f2f2f2;
-}
-
-/* nth-child selector for modern browsers */
-.pure-table-striped tr:nth-child(2n-1) td {
- background-color: #f2f2f2;
-}
-
-/* BORDERED TABLES */
-.pure-table-bordered td {
- border-bottom: 1px solid #cbcbcb;
-}
-.pure-table-bordered tbody > tr:last-child > td {
- border-bottom-width: 0;
-}
-
-
-/* HORIZONTAL BORDERED TABLES */
-
-.pure-table-horizontal td,
-.pure-table-horizontal th {
- border-width: 0 0 1px 0;
- border-bottom: 1px solid #cbcbcb;
-}
-.pure-table-horizontal tbody > tr:last-child > td {
- border-bottom-width: 0;
-}
diff --git a/talermerchantdemos/static/pure.scss b/talermerchantdemos/static/pure.scss
@@ -0,0 +1,1508 @@
+/*!
+Pure v0.6.2
+Copyright 2013 Yahoo!
+Licensed under the BSD License.
+https://github.com/yahoo/pure/blob/master/LICENSE.md
+*/
+/*!
+normalize.css v^3.0 | MIT License | git.io/normalize
+Copyright (c) Nicolas Gallagher and Jonathan Neal
+*/
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS and IE text size adjust after device orientation change,
+ * without disabling user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * Improve readability of focused elements when they are also in an
+ * active/hover state.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ box-sizing: content-box; /* 2 */
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
+
+/*csslint important:false*/
+
+/* ==========================================================================
+ Pure Base Extras
+ ========================================================================== */
+
+/**
+ * Extra rules that Pure adds on top of Normalize.css
+ */
+
+/**
+ * Always hide an element when it has the `hidden` HTML attribute.
+ */
+
+.hidden,
+[hidden] {
+ display: none !important;
+}
+
+/**
+ * Add this class to an image to make it fit within it's fluid parent wrapper while maintaining
+ * aspect ratio.
+ */
+.pure-img {
+ max-width: 100%;
+ height: auto;
+ display: block;
+}
+
+/*csslint regex-selectors:false, known-properties:false, duplicate-properties:false*/
+
+.pure-g {
+ letter-spacing: -0.31em; /* Webkit: collapse white-space between units */
+ *letter-spacing: normal; /* reset IE < 8 */
+ *word-spacing: -0.43em; /* IE < 8: collapse white-space between units */
+ text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */
+
+ /*
+ Sets the font stack to fonts known to work properly with the above letter
+ and word spacings. See: https://github.com/yahoo/pure/issues/41/
+
+ The following font stack makes Pure Grids work on all known environments.
+
+ * FreeSans: Ships with many Linux distros, including Ubuntu
+
+ * Arimo: Ships with Chrome OS. Arimo has to be defined before Helvetica and
+ Arial to get picked up by the browser, even though neither is available
+ in Chrome OS.
+
+ * Droid Sans: Ships with all versions of Android.
+
+ * Helvetica, Arial, sans-serif: Common font stack on OS X and Windows.
+ */
+ font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif;
+
+ /* Use flexbox when possible to avoid `letter-spacing` side-effects. */
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-flow: row wrap;
+ -ms-flex-flow: row wrap;
+ flex-flow: row wrap;
+
+ /* Prevents distributing space between rows */
+ -webkit-align-content: flex-start;
+ -ms-flex-line-pack: start;
+ align-content: flex-start;
+}
+
+/* IE10 display: -ms-flexbox (and display: flex in IE 11) does not work inside a table; fall back to block and rely on font hack */
+@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
+ table .pure-g {
+ display: block;
+ }
+}
+
+/* Opera as of 12 on Windows needs word-spacing.
+ The ".opera-only" selector is used to prevent actual prefocus styling
+ and is not required in markup.
+*/
+.opera-only :-o-prefocus,
+.pure-g {
+ word-spacing: -0.43em;
+}
+
+.pure-u {
+ display: inline-block;
+ *display: inline; /* IE < 8: fake inline-block */
+ zoom: 1;
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+ text-rendering: auto;
+}
+
+/*
+Resets the font family back to the OS/browser's default sans-serif font,
+this the same font stack that Normalize.css sets for the `body`.
+*/
+.pure-g [class *= "pure-u"] {
+ font-family: sans-serif;
+}
+
+.pure-u-1,
+.pure-u-1-1,
+.pure-u-1-2,
+.pure-u-1-3,
+.pure-u-2-3,
+.pure-u-1-4,
+.pure-u-3-4,
+.pure-u-1-5,
+.pure-u-2-5,
+.pure-u-3-5,
+.pure-u-4-5,
+.pure-u-5-5,
+.pure-u-1-6,
+.pure-u-5-6,
+.pure-u-1-8,
+.pure-u-3-8,
+.pure-u-5-8,
+.pure-u-7-8,
+.pure-u-1-12,
+.pure-u-5-12,
+.pure-u-7-12,
+.pure-u-11-12,
+.pure-u-1-24,
+.pure-u-2-24,
+.pure-u-3-24,
+.pure-u-4-24,
+.pure-u-5-24,
+.pure-u-6-24,
+.pure-u-7-24,
+.pure-u-8-24,
+.pure-u-9-24,
+.pure-u-10-24,
+.pure-u-11-24,
+.pure-u-12-24,
+.pure-u-13-24,
+.pure-u-14-24,
+.pure-u-15-24,
+.pure-u-16-24,
+.pure-u-17-24,
+.pure-u-18-24,
+.pure-u-19-24,
+.pure-u-20-24,
+.pure-u-21-24,
+.pure-u-22-24,
+.pure-u-23-24,
+.pure-u-24-24 {
+ display: inline-block;
+ *display: inline;
+ zoom: 1;
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+ text-rendering: auto;
+}
+
+.pure-u-1-24 {
+ width: 4.1667%;
+ *width: 4.1357%;
+}
+
+.pure-u-1-12,
+.pure-u-2-24 {
+ width: 8.3333%;
+ *width: 8.3023%;
+}
+
+.pure-u-1-8,
+.pure-u-3-24 {
+ width: 12.5000%;
+ *width: 12.4690%;
+}
+
+.pure-u-1-6,
+.pure-u-4-24 {
+ width: 16.6667%;
+ *width: 16.6357%;
+}
+
+.pure-u-1-5 {
+ width: 20%;
+ *width: 19.9690%;
+}
+
+.pure-u-5-24 {
+ width: 20.8333%;
+ *width: 20.8023%;
+}
+
+.pure-u-1-4,
+.pure-u-6-24 {
+ width: 25%;
+ *width: 24.9690%;
+}
+
+.pure-u-7-24 {
+ width: 29.1667%;
+ *width: 29.1357%;
+}
+
+.pure-u-1-3,
+.pure-u-8-24 {
+ width: 33.3333%;
+ *width: 33.3023%;
+}
+
+.pure-u-3-8,
+.pure-u-9-24 {
+ width: 37.5000%;
+ *width: 37.4690%;
+}
+
+.pure-u-2-5 {
+ width: 40%;
+ *width: 39.9690%;
+}
+
+.pure-u-5-12,
+.pure-u-10-24 {
+ width: 41.6667%;
+ *width: 41.6357%;
+}
+
+.pure-u-11-24 {
+ width: 45.8333%;
+ *width: 45.8023%;
+}
+
+.pure-u-1-2,
+.pure-u-12-24 {
+ width: 50%;
+ *width: 49.9690%;
+}
+
+.pure-u-13-24 {
+ width: 54.1667%;
+ *width: 54.1357%;
+}
+
+.pure-u-7-12,
+.pure-u-14-24 {
+ width: 58.3333%;
+ *width: 58.3023%;
+}
+
+.pure-u-3-5 {
+ width: 60%;
+ *width: 59.9690%;
+}
+
+.pure-u-5-8,
+.pure-u-15-24 {
+ width: 62.5000%;
+ *width: 62.4690%;
+}
+
+.pure-u-2-3,
+.pure-u-16-24 {
+ width: 66.6667%;
+ *width: 66.6357%;
+}
+
+.pure-u-17-24 {
+ width: 70.8333%;
+ *width: 70.8023%;
+}
+
+.pure-u-3-4,
+.pure-u-18-24 {
+ width: 75%;
+ *width: 74.9690%;
+}
+
+.pure-u-19-24 {
+ width: 79.1667%;
+ *width: 79.1357%;
+}
+
+.pure-u-4-5 {
+ width: 80%;
+ *width: 79.9690%;
+}
+
+.pure-u-5-6,
+.pure-u-20-24 {
+ width: 83.3333%;
+ *width: 83.3023%;
+}
+
+.pure-u-7-8,
+.pure-u-21-24 {
+ width: 87.5000%;
+ *width: 87.4690%;
+}
+
+.pure-u-11-12,
+.pure-u-22-24 {
+ width: 91.6667%;
+ *width: 91.6357%;
+}
+
+.pure-u-23-24 {
+ width: 95.8333%;
+ *width: 95.8023%;
+}
+
+.pure-u-1,
+.pure-u-1-1,
+.pure-u-5-5,
+.pure-u-24-24 {
+ width: 100%;
+}
+.pure-button {
+ /* Structure */
+ display: inline-block;
+ zoom: 1;
+ line-height: normal;
+ white-space: nowrap;
+ vertical-align: middle;
+ text-align: center;
+ cursor: pointer;
+ -webkit-user-drag: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ box-sizing: border-box;
+}
+
+/* Firefox: Get rid of the inner focus border */
+.pure-button::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+
+/* Inherit .pure-g styles */
+.pure-button-group {
+ letter-spacing: -0.31em; /* Webkit: collapse white-space between units */
+ *letter-spacing: normal; /* reset IE < 8 */
+ *word-spacing: -0.43em; /* IE < 8: collapse white-space between units */
+ text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */
+}
+
+.opera-only :-o-prefocus,
+.pure-button-group {
+ word-spacing: -0.43em;
+}
+
+.pure-button-group .pure-button {
+ letter-spacing: normal;
+ word-spacing: normal;
+ vertical-align: top;
+ text-rendering: auto;
+}
+
+/*csslint outline-none:false*/
+
+.pure-button {
+ font-family: inherit;
+ font-size: 100%;
+ padding: 0.5em 1em;
+ color: #444; /* rgba not supported (IE 8) */
+ color: rgba(0, 0, 0, 0.80); /* rgba supported */
+ border: 1px solid #999; /*IE 6/7/8*/
+ border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
+ background-color: #E6E6E6;
+ text-decoration: none;
+ border-radius: 2px;
+}
+
+.pure-button-hover,
+.pure-button:hover,
+.pure-button:focus {
+ /* csslint ignore:start */
+ filter: alpha(opacity=90);
+ /* csslint ignore:end */
+ background-image: -webkit-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
+ background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
+}
+.pure-button:focus {
+ outline: 0;
+}
+.pure-button-active,
+.pure-button:active {
+ box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset;
+ border-color: #000;
+}
+
+.pure-button[disabled],
+.pure-button-disabled,
+.pure-button-disabled:hover,
+.pure-button-disabled:focus,
+.pure-button-disabled:active {
+ border: none;
+ background-image: none;
+ /* csslint ignore:start */
+ filter: alpha(opacity=40);
+ /* csslint ignore:end */
+ opacity: 0.40;
+ cursor: not-allowed;
+ box-shadow: none;
+ pointer-events: none;
+}
+
+.pure-button-hidden {
+ display: none;
+}
+
+.pure-button-primary,
+.pure-button-selected,
+a.pure-button-primary,
+a.pure-button-selected {
+ background-color: rgb(0, 120, 231);
+ color: #fff;
+}
+
+/* Button Groups */
+.pure-button-group .pure-button {
+ margin: 0;
+ border-radius: 0;
+ border-right: 1px solid #111; /* fallback color for rgba() for IE7/8 */
+ border-right: 1px solid rgba(0, 0, 0, 0.2);
+
+}
+
+.pure-button-group .pure-button:first-child {
+ border-top-left-radius: 2px;
+ border-bottom-left-radius: 2px;
+}
+.pure-button-group .pure-button:last-child {
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+ border-right: none;
+}
+
+/*csslint box-model:false*/
+/*
+Box-model set to false because we're setting a height on select elements, which
+also have border and padding. This is done because some browsers don't render
+the padding. We explicitly set the box-model for select elements to border-box,
+so we can ignore the csslint warning.
+*/
+
+.pure-form input[type="text"],
+.pure-form input[type="password"],
+.pure-form input[type="email"],
+.pure-form input[type="url"],
+.pure-form input[type="date"],
+.pure-form input[type="month"],
+.pure-form input[type="time"],
+.pure-form input[type="datetime"],
+.pure-form input[type="datetime-local"],
+.pure-form input[type="week"],
+.pure-form input[type="number"],
+.pure-form input[type="search"],
+.pure-form input[type="tel"],
+.pure-form input[type="color"],
+.pure-form select,
+.pure-form textarea {
+ padding: 0.5em 0.6em;
+ display: inline-block;
+ border: 1px solid #ccc;
+ box-shadow: inset 0 1px 3px #ddd;
+ border-radius: 4px;
+ vertical-align: middle;
+ box-sizing: border-box;
+}
+
+/*
+Need to separate out the :not() selector from the rest of the CSS 2.1 selectors
+since IE8 won't execute CSS that contains a CSS3 selector.
+*/
+.pure-form input:not([type]) {
+ padding: 0.5em 0.6em;
+ display: inline-block;
+ border: 1px solid #ccc;
+ box-shadow: inset 0 1px 3px #ddd;
+ border-radius: 4px;
+ box-sizing: border-box;
+}
+
+
+/* Chrome (as of v.32/34 on OS X) needs additional room for color to display. */
+/* May be able to remove this tweak as color inputs become more standardized across browsers. */
+.pure-form input[type="color"] {
+ padding: 0.2em 0.5em;
+}
+
+
+.pure-form input[type="text"]:focus,
+.pure-form input[type="password"]:focus,
+.pure-form input[type="email"]:focus,
+.pure-form input[type="url"]:focus,
+.pure-form input[type="date"]:focus,
+.pure-form input[type="month"]:focus,
+.pure-form input[type="time"]:focus,
+.pure-form input[type="datetime"]:focus,
+.pure-form input[type="datetime-local"]:focus,
+.pure-form input[type="week"]:focus,
+.pure-form input[type="number"]:focus,
+.pure-form input[type="search"]:focus,
+.pure-form input[type="tel"]:focus,
+.pure-form input[type="color"]:focus,
+.pure-form select:focus,
+.pure-form textarea:focus {
+ outline: 0;
+ border-color: #129FEA;
+}
+
+/*
+Need to separate out the :not() selector from the rest of the CSS 2.1 selectors
+since IE8 won't execute CSS that contains a CSS3 selector.
+*/
+.pure-form input:not([type]):focus {
+ outline: 0;
+ border-color: #129FEA;
+}
+
+.pure-form input[type="file"]:focus,
+.pure-form input[type="radio"]:focus,
+.pure-form input[type="checkbox"]:focus {
+ outline: thin solid #129FEA;
+ outline: 1px auto #129FEA;
+}
+.pure-form .pure-checkbox,
+.pure-form .pure-radio {
+ margin: 0.5em 0;
+ display: block;
+}
+
+.pure-form input[type="text"][disabled],
+.pure-form input[type="password"][disabled],
+.pure-form input[type="email"][disabled],
+.pure-form input[type="url"][disabled],
+.pure-form input[type="date"][disabled],
+.pure-form input[type="month"][disabled],
+.pure-form input[type="time"][disabled],
+.pure-form input[type="datetime"][disabled],
+.pure-form input[type="datetime-local"][disabled],
+.pure-form input[type="week"][disabled],
+.pure-form input[type="number"][disabled],
+.pure-form input[type="search"][disabled],
+.pure-form input[type="tel"][disabled],
+.pure-form input[type="color"][disabled],
+.pure-form select[disabled],
+.pure-form textarea[disabled] {
+ cursor: not-allowed;
+ background-color: #eaeded;
+ color: #cad2d3;
+}
+
+/*
+Need to separate out the :not() selector from the rest of the CSS 2.1 selectors
+since IE8 won't execute CSS that contains a CSS3 selector.
+*/
+.pure-form input:not([type])[disabled] {
+ cursor: not-allowed;
+ background-color: #eaeded;
+ color: #cad2d3;
+}
+.pure-form input[readonly],
+.pure-form select[readonly],
+.pure-form textarea[readonly] {
+ background-color: #eee; /* menu hover bg color */
+ color: #777; /* menu text color */
+ border-color: #ccc;
+}
+
+.pure-form input:focus:invalid,
+.pure-form textarea:focus:invalid,
+.pure-form select:focus:invalid {
+ color: #b94a48;
+ border-color: #e9322d;
+}
+.pure-form input[type="file"]:focus:invalid:focus,
+.pure-form input[type="radio"]:focus:invalid:focus,
+.pure-form input[type="checkbox"]:focus:invalid:focus {
+ outline-color: #e9322d;
+}
+.pure-form select {
+ /* Normalizes the height; padding is not sufficient. */
+ height: 2.25em;
+ border: 1px solid #ccc;
+ background-color: white;
+}
+.pure-form select[multiple] {
+ height: auto;
+}
+.pure-form label {
+ margin: 0.5em 0 0.2em;
+}
+.pure-form fieldset {
+ margin: 0;
+ padding: 0.35em 0 0.75em;
+ border: 0;
+}
+.pure-form legend {
+ display: block;
+ width: 100%;
+ padding: 0.3em 0;
+ margin-bottom: 0.3em;
+ color: #333;
+ border-bottom: 1px solid #e5e5e5;
+}
+
+.pure-form-stacked input[type="text"],
+.pure-form-stacked input[type="password"],
+.pure-form-stacked input[type="email"],
+.pure-form-stacked input[type="url"],
+.pure-form-stacked input[type="date"],
+.pure-form-stacked input[type="month"],
+.pure-form-stacked input[type="time"],
+.pure-form-stacked input[type="datetime"],
+.pure-form-stacked input[type="datetime-local"],
+.pure-form-stacked input[type="week"],
+.pure-form-stacked input[type="number"],
+.pure-form-stacked input[type="search"],
+.pure-form-stacked input[type="tel"],
+.pure-form-stacked input[type="color"],
+.pure-form-stacked input[type="file"],
+.pure-form-stacked select,
+.pure-form-stacked label,
+.pure-form-stacked textarea {
+ display: block;
+ margin: 0.25em 0;
+}
+
+/*
+Need to separate out the :not() selector from the rest of the CSS 2.1 selectors
+since IE8 won't execute CSS that contains a CSS3 selector.
+*/
+.pure-form-stacked input:not([type]) {
+ display: block;
+ margin: 0.25em 0;
+}
+.pure-form-aligned input,
+.pure-form-aligned textarea,
+.pure-form-aligned select,
+/* NOTE: pure-help-inline is deprecated. Use .pure-form-message-inline instead. */
+.pure-form-aligned .pure-help-inline,
+.pure-form-message-inline {
+ display: inline-block;
+ *display: inline;
+ *zoom: 1;
+ vertical-align: middle;
+}
+.pure-form-aligned textarea {
+ vertical-align: top;
+}
+
+/* Aligned Forms */
+.pure-form-aligned .pure-control-group {
+ margin-bottom: 0.5em;
+}
+.pure-form-aligned .pure-control-group label {
+ text-align: right;
+ display: inline-block;
+ vertical-align: middle;
+ width: 10em;
+ margin: 0 1em 0 0;
+}
+.pure-form-aligned .pure-controls {
+ margin: 1.5em 0 0 11em;
+}
+
+/* Rounded Inputs */
+.pure-form input.pure-input-rounded,
+.pure-form .pure-input-rounded {
+ border-radius: 2em;
+ padding: 0.5em 1em;
+}
+
+/* Grouped Inputs */
+.pure-form .pure-group fieldset {
+ margin-bottom: 10px;
+}
+.pure-form .pure-group input,
+.pure-form .pure-group textarea {
+ display: block;
+ padding: 10px;
+ margin: 0 0 -1px;
+ border-radius: 0;
+ position: relative;
+ top: -1px;
+}
+.pure-form .pure-group input:focus,
+.pure-form .pure-group textarea:focus {
+ z-index: 3;
+}
+.pure-form .pure-group input:first-child,
+.pure-form .pure-group textarea:first-child {
+ top: 1px;
+ border-radius: 4px 4px 0 0;
+ margin: 0;
+}
+.pure-form .pure-group input:first-child:last-child,
+.pure-form .pure-group textarea:first-child:last-child {
+ top: 1px;
+ border-radius: 4px;
+ margin: 0;
+}
+.pure-form .pure-group input:last-child,
+.pure-form .pure-group textarea:last-child {
+ top: -2px;
+ border-radius: 0 0 4px 4px;
+ margin: 0;
+}
+.pure-form .pure-group button {
+ margin: 0.35em 0;
+}
+
+.pure-form .pure-input-1 {
+ width: 100%;
+}
+.pure-form .pure-input-3-4 {
+ width: 75%;
+}
+.pure-form .pure-input-2-3 {
+ width: 66%;
+}
+.pure-form .pure-input-1-2 {
+ width: 50%;
+}
+.pure-form .pure-input-1-3 {
+ width: 33%;
+}
+.pure-form .pure-input-1-4 {
+ width: 25%;
+}
+
+/* Inline help for forms */
+/* NOTE: pure-help-inline is deprecated. Use .pure-form-message-inline instead. */
+.pure-form .pure-help-inline,
+.pure-form-message-inline {
+ display: inline-block;
+ padding-left: 0.3em;
+ color: #666;
+ vertical-align: middle;
+ font-size: 0.875em;
+}
+
+/* Block help for forms */
+.pure-form-message {
+ display: block;
+ color: #666;
+ font-size: 0.875em;
+}
+
+@media only screen and (max-width : 480px) {
+ .pure-form button[type="submit"] {
+ margin: 0.7em 0 0;
+ }
+
+ .pure-form input:not([type]),
+ .pure-form input[type="text"],
+ .pure-form input[type="password"],
+ .pure-form input[type="email"],
+ .pure-form input[type="url"],
+ .pure-form input[type="date"],
+ .pure-form input[type="month"],
+ .pure-form input[type="time"],
+ .pure-form input[type="datetime"],
+ .pure-form input[type="datetime-local"],
+ .pure-form input[type="week"],
+ .pure-form input[type="number"],
+ .pure-form input[type="search"],
+ .pure-form input[type="tel"],
+ .pure-form input[type="color"],
+ .pure-form label {
+ margin-bottom: 0.3em;
+ display: block;
+ }
+
+ .pure-group input:not([type]),
+ .pure-group input[type="text"],
+ .pure-group input[type="password"],
+ .pure-group input[type="email"],
+ .pure-group input[type="url"],
+ .pure-group input[type="date"],
+ .pure-group input[type="month"],
+ .pure-group input[type="time"],
+ .pure-group input[type="datetime"],
+ .pure-group input[type="datetime-local"],
+ .pure-group input[type="week"],
+ .pure-group input[type="number"],
+ .pure-group input[type="search"],
+ .pure-group input[type="tel"],
+ .pure-group input[type="color"] {
+ margin-bottom: 0;
+ }
+
+ .pure-form-aligned .pure-control-group label {
+ margin-bottom: 0.3em;
+ text-align: left;
+ display: block;
+ width: 100%;
+ }
+
+ .pure-form-aligned .pure-controls {
+ margin: 1.5em 0 0 0;
+ }
+
+ /* NOTE: pure-help-inline is deprecated. Use .pure-form-message-inline instead. */
+ .pure-form .pure-help-inline,
+ .pure-form-message-inline,
+ .pure-form-message {
+ display: block;
+ font-size: 0.75em;
+ /* Increased bottom padding to make it group with its related input element. */
+ padding: 0.2em 0 0.8em;
+ }
+}
+
+/*csslint adjoining-classes: false, box-model:false*/
+.pure-menu {
+ box-sizing: border-box;
+}
+
+.pure-menu-fixed {
+ position: fixed;
+ left: 0;
+ top: 0;
+ z-index: 3;
+}
+
+.pure-menu-list,
+.pure-menu-item {
+ position: relative;
+}
+
+.pure-menu-list {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.pure-menu-item {
+ padding: 0;
+ margin: 0;
+ height: 100%;
+}
+
+.pure-menu-link,
+.pure-menu-heading {
+ display: block;
+ text-decoration: none;
+ white-space: nowrap;
+}
+
+/* HORIZONTAL MENU */
+.pure-menu-horizontal {
+ width: 100%;
+ white-space: nowrap;
+}
+
+.pure-menu-horizontal .pure-menu-list {
+ display: inline-block;
+}
+
+/* Initial menus should be inline-block so that they are horizontal */
+.pure-menu-horizontal .pure-menu-item,
+.pure-menu-horizontal .pure-menu-heading,
+.pure-menu-horizontal .pure-menu-separator {
+ display: inline-block;
+ *display: inline;
+ zoom: 1;
+ vertical-align: middle;
+}
+
+/* Submenus should still be display: block; */
+.pure-menu-item .pure-menu-item {
+ display: block;
+}
+
+.pure-menu-children {
+ display: none;
+ position: absolute;
+ left: 100%;
+ top: 0;
+ margin: 0;
+ padding: 0;
+ z-index: 3;
+}
+
+.pure-menu-horizontal .pure-menu-children {
+ left: 0;
+ top: auto;
+ width: inherit;
+}
+
+.pure-menu-allow-hover:hover > .pure-menu-children,
+.pure-menu-active > .pure-menu-children {
+ display: block;
+ position: absolute;
+}
+
+/* Vertical Menus - show the dropdown arrow */
+.pure-menu-has-children > .pure-menu-link:after {
+ padding-left: 0.5em;
+ content: "\25B8";
+ font-size: small;
+}
+
+/* Horizontal Menus - show the dropdown arrow */
+.pure-menu-horizontal .pure-menu-has-children > .pure-menu-link:after {
+ content: "\25BE";
+}
+
+/* scrollable menus */
+.pure-menu-scrollable {
+ overflow-y: scroll;
+ overflow-x: hidden;
+}
+
+.pure-menu-scrollable .pure-menu-list {
+ display: block;
+}
+
+.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list {
+ display: inline-block;
+}
+
+.pure-menu-horizontal.pure-menu-scrollable {
+ white-space: nowrap;
+ overflow-y: hidden;
+ overflow-x: auto;
+ -ms-overflow-style: none;
+ -webkit-overflow-scrolling: touch;
+ /* a little extra padding for this style to allow for scrollbars */
+ padding: .5em 0;
+}
+
+.pure-menu-horizontal.pure-menu-scrollable::-webkit-scrollbar {
+ display: none;
+}
+
+/* misc default styling */
+
+.pure-menu-separator,
+.pure-menu-horizontal .pure-menu-children .pure-menu-separator {
+ background-color: #ccc;
+ height: 1px;
+ margin: .3em 0;
+}
+
+.pure-menu-horizontal .pure-menu-separator {
+ width: 1px;
+ height: 1.3em;
+ margin: 0 .3em ;
+}
+
+/* Need to reset the separator since submenu is vertical */
+.pure-menu-horizontal .pure-menu-children .pure-menu-separator {
+ display: block;
+ width: auto;
+}
+
+.pure-menu-heading {
+ text-transform: uppercase;
+ color: #565d64;
+}
+
+.pure-menu-link {
+ color: #777;
+}
+
+.pure-menu-children {
+ background-color: #fff;
+}
+
+.pure-menu-link,
+.pure-menu-disabled,
+.pure-menu-heading {
+ padding: .5em 1em;
+}
+
+.pure-menu-disabled {
+ opacity: .5;
+}
+
+.pure-menu-disabled .pure-menu-link:hover {
+ background-color: transparent;
+}
+
+.pure-menu-active > .pure-menu-link,
+.pure-menu-link:hover,
+.pure-menu-link:focus {
+ background-color: #eee;
+}
+
+.pure-menu-selected .pure-menu-link,
+.pure-menu-selected .pure-menu-link:visited {
+ color: #000;
+}
+
+.pure-table {
+ /* Remove spacing between table cells (from Normalize.css) */
+ border-collapse: collapse;
+ border-spacing: 0;
+ empty-cells: show;
+ border: 1px solid #cbcbcb;
+}
+
+.pure-table caption {
+ color: #000;
+ font: italic 85%/1 arial, sans-serif;
+ padding: 1em 0;
+ text-align: center;
+}
+
+.pure-table td,
+.pure-table th {
+ border-left: 1px solid #cbcbcb;/* inner column border */
+ border-width: 0 0 0 1px;
+ font-size: inherit;
+ margin: 0;
+ overflow: visible; /*to make ths where the title is really long work*/
+ padding: 0.5em 1em; /* cell padding */
+}
+
+/* Consider removing this next declaration block, as it causes problems when
+there's a rowspan on the first cell. Case added to the tests. issue#432 */
+.pure-table td:first-child,
+.pure-table th:first-child {
+ border-left-width: 0;
+}
+
+.pure-table thead {
+ background-color: #e0e0e0;
+ color: #000;
+ text-align: left;
+ vertical-align: bottom;
+}
+
+/*
+striping:
+ even - #fff (white)
+ odd - #f2f2f2 (light gray)
+*/
+.pure-table td {
+ background-color: transparent;
+}
+.pure-table-odd td {
+ background-color: #f2f2f2;
+}
+
+/* nth-child selector for modern browsers */
+.pure-table-striped tr:nth-child(2n-1) td {
+ background-color: #f2f2f2;
+}
+
+/* BORDERED TABLES */
+.pure-table-bordered td {
+ border-bottom: 1px solid #cbcbcb;
+}
+.pure-table-bordered tbody > tr:last-child > td {
+ border-bottom-width: 0;
+}
+
+
+/* HORIZONTAL BORDERED TABLES */
+
+.pure-table-horizontal td,
+.pure-table-horizontal th {
+ border-width: 0 0 1px 0;
+ border-bottom: 1px solid #cbcbcb;
+}
+.pure-table-horizontal tbody > tr:last-child > td {
+ border-bottom-width: 0;
+}
diff --git a/talermerchantdemos/static/taler-fallback.css b/talermerchantdemos/static/taler-fallback.scss