taler-merchant-demos

Python-based Frontends for the Demonstration Web site
Log | Files | Refs | Submodules | README | LICENSE

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:
M.gitignore | 3++-
MMakefile | 41++++++++++++++++++++++++++++++++++++++++-
MREADME.md | 33++++++++++++++++++++++++++++-----
Msetup.py | 1+
Atalermerchantdemos/.gitignore | 7+++++++
Atalermerchantdemos/.vscode/launch.json | 16++++++++++++++++
Mtalermerchantdemos/blog/articles/scrap1_11.html | 1-
Mtalermerchantdemos/blog/blog.py | 139++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mtalermerchantdemos/blog/content.py | 13+++++++------
Dtalermerchantdemos/blog/templates/article_frame.html | 13-------------
Atalermerchantdemos/blog/templates/article_frame.html.j2 | 15+++++++++++++++
Dtalermerchantdemos/blog/templates/article_refunded.html | 10----------
Atalermerchantdemos/blog/templates/article_refunded.html.j2 | 16++++++++++++++++
Dtalermerchantdemos/blog/templates/base.html | 79-------------------------------------------------------------------------------
Atalermerchantdemos/blog/templates/base.html.j2 | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dtalermerchantdemos/blog/templates/confirm_refund.html | 19-------------------
Atalermerchantdemos/blog/templates/confirm_refund.html.j2 | 22++++++++++++++++++++++
Dtalermerchantdemos/blog/templates/error.html | 22----------------------
Atalermerchantdemos/blog/templates/error.html.j2 | 24++++++++++++++++++++++++
Dtalermerchantdemos/blog/templates/index.html | 40----------------------------------------
Dtalermerchantdemos/blog/templates/show_refund.html | 28----------------------------
Atalermerchantdemos/static/__init__.py | 1+
Dtalermerchantdemos/static/demo.css | 69---------------------------------------------------------------------
Atalermerchantdemos/static/demo.scss | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atalermerchantdemos/static/navbar.css | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atalermerchantdemos/static/navbar.css.map | 2++
Atalermerchantdemos/static/navbar.scss | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dtalermerchantdemos/static/pure.css | 1508-------------------------------------------------------------------------------
Atalermerchantdemos/static/pure.scss | 1508+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rtalermerchantdemos/static/taler-fallback.css -> talermerchantdemos/static/taler-fallback.scss | 0
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 &quot;Free Software, Free Society&quot;, - 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 &copy; 2014&mdash;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 &quot;Free Software, Free Society&quot;.") + "<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 &copy; 2014&mdash;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 &copy; 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