changeset 166:178f55b825b7

small refactoring/redesign, better BEM integration: - blog has been redesigned, and almost all blog CSS has been made generic and moved to main styles.css file. - better noscript handling, dynamic elements are created using "magic" classes (dom_update.js) - using better icons for older/newer messages - better state handling, classes now use "state_XXX" - more classes now use BEM convention - menu labels have been moved to a separate template (components/menu_labels.html), so it can be overriden easily by other sites - better styles.css organisation
author Goffi <goffi@goffi.org>
date Wed, 03 Oct 2018 21:00:24 +0200
parents 9e8d9d754337
children 6f05d4bdc58e
files sat_templates/templates/default/app/app.html sat_templates/templates/default/base/base.html sat_templates/templates/default/blog/articles.html sat_templates/templates/default/blog/item.html sat_templates/templates/default/blog/macros.html sat_templates/templates/default/components/common.html sat_templates/templates/default/components/menu_labels.html sat_templates/templates/default/event/admin.html sat_templates/templates/default/forum/view.html sat_templates/templates/default/input/field.html sat_templates/templates/default/input/navigation.html sat_templates/templates/default/input/textbox.html sat_templates/templates/default/merge-request/item.html sat_templates/templates/default/static/app.css sat_templates/templates/default/static/blog.css sat_templates/templates/default/static/common.js sat_templates/templates/default/static/dom_update.js sat_templates/templates/default/static/event.css sat_templates/templates/default/static/forum.css sat_templates/templates/default/static/login.css sat_templates/templates/default/static/photo.css sat_templates/templates/default/static/styles.css sat_templates/templates/default/static/styles_noscript.css sat_templates/templates/default/static/ticket.css sat_templates/templates/default/ticket/create.html
diffstat 25 files changed, 845 insertions(+), 669 deletions(-) [+]
line wrap: on
line diff
--- a/sat_templates/templates/default/app/app.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/app/app.html	Wed Oct 03 21:00:24 2018 +0200
@@ -1,23 +1,23 @@
 {% extends 'base/base.html' %}
 {% block body %}
-<article id="web_app_box" class="box">
-    <p>
-        {% trans app_name=C.APP_NAME %}
-            The following link allows you to access {{app_name}} web application, which is a more feature rich way to use this software (but it is also a bit more heavy and complex to use).
-        {% endtrans %}
-    </p>
-    <p class="warning_text">
-        {% trans %}
-            Please note that current version of web application use legacy technologies and will be rewritten for next version of Salut à Toi (0.8). It does contain some bugs and it is under minimal maintenance.
-        {% endtrans %}
-    </p>
-    <p id="link_section">
-        <a href="/libervia.html">{% trans %}Click here to access the web application{% endtrans %}</a>.
-    </p>
-    <p>
-        {% trans %}
-            Next time you can go directly to the above URL.
-        {% endtrans %}
-    </p>
-</article>
+    <article class="box">
+        <p>
+            {% trans app_name=C.APP_NAME %}
+                The following link allows you to access {{app_name}} web application, which is a more feature rich way to use this software (but it is also a bit more heavy and complex to use).
+            {% endtrans %}
+        </p>
+        <p class="warning_text">
+            {% trans %}
+                Please note that current version of web application use legacy technologies and will be rewritten for next version of Salut à Toi (0.8). It does contain some bugs and it is under minimal maintenance.
+            {% endtrans %}
+        </p>
+        <p id="link_section">
+            <a href="/libervia.html">{% trans %}Click here to access the web application{% endtrans %}</a>.
+        </p>
+        <p>
+            {% trans %}
+                Next time you can go directly to the above URL.
+            {% endtrans %}
+        </p>
+    </article>
 {% endblock body %}
--- a/sat_templates/templates/default/base/base.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/base/base.html	Wed Oct 03 21:00:24 2018 +0200
@@ -1,6 +1,7 @@
 {% set embedded = True %} {# embedded is set to avoid including base.html several times if a generic page is included (e.g. blog/articles.html) #}
 {% import 'components/common.html' as component with context %}
 {{ script.include('common', '') }} {# common.js is, as its name state, a common script, so it's useful to import it here #}
+{{ script.include('dom_update') }} {# will check page for dom element to modify when javascript is enabled #}
 <!DOCTYPE html>
 <html>
 <head>
@@ -52,6 +53,8 @@
     {% if websocket is defined %}
         {{ script.include('websocket', '') }}
     {% endif %}
+    {# FIXME: following ugly hack is temporarily needed for dom_update, until a proper way to handle gettext dynamicly is implemented #}
+    <script>expand_txt="{% trans %}Click to expand…{% endtrans %}"; reduce_txt="{% trans %}Click to reduce…{% endtrans %}";</script>
     {{ script.generate_scripts() }}
     {% if websocket is defined %}
         <script>var socket=new WSHandler("{{websocket.url}}", "{{websocket.token}}", {{websocket.debug}});</script>
@@ -92,7 +95,7 @@
         {% block body %}
         {% endblock body %}
         </div>
-        <footer>{% block footer %}<span>{% trans app_name=C.APP_NAME %}Powered by {{app_name}}{% endtrans %}</span>{% endblock %}</footer>
+        <footer class="page__footer">{% block footer %}<span>{% trans app_name=C.APP_NAME %}Powered by {{app_name}}{% endtrans %}</span>{% endblock %}</footer>
     </main>
 </body>
 </html>
--- a/sat_templates/templates/default/blog/articles.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/blog/articles.html	Wed Oct 03 21:00:24 2018 +0200
@@ -1,6 +1,7 @@
 {% if not embedded %}{% extends 'base/base.html' %}{% endif %}
 {% set single = items|length == 1 %}
 {% set dates_format='relative' if single else 'short' %}
+{% import 'components/avatar.html' as avatar with context %}
 {% import 'blog/macros.html' as blog with context %}
 {% import 'input/navigation.html' as navigation with context %}
 
@@ -18,6 +19,7 @@
 {%- endblock title -%}
 
 {% block body %}
+{{ icon_defs('angle-double-left', 'angle-double-right') }}
 {% if items %}
     <div id="blog_items">
         {{ blog.show_items(items, expanded=single) }}
--- a/sat_templates/templates/default/blog/item.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/blog/item.html	Wed Oct 03 21:00:24 2018 +0200
@@ -11,34 +11,22 @@
 
 {% if item.language and locale and locale.language != item.language %}
     {# we may display items in different language in a specific way #}
-    {% set other_lang = " other_lang" %}
+    {% set other_lang = " other_lang" if expanded else " other_lang state_init" %}
 {% endif %}
 
-{% if expanded %}
-    {# FIXME: the style attribute is not nice, but due to the use of clicked_mh_fix. A cleaner way would be welcomed #}
-    <article id="{{item.id}}" class="init box{{other_lang}} clicked" style="max-height: none">
-{% else %}
-    <article id="{{item.id}}" class="init box{{other_lang}}" >
-{% endif %}
+    <article id="{{item.id}}" class="box {{"box--comment" if comment else "box--large"}} {{"" if (expanded or comment) else "box--expand"}}{{other_lang}}" >
 
     {# following message is displayed if item lang is different from page locale #}
     {% if other_lang is defined %}
-        <div class="info"><p>{% trans language=locale.language_name %}This message is not in {{language}}, click to display anyway{% endtrans %}</p></div>
+        <div class="info show_if_parent_init"><p>{% trans language=locale.language_name %}This message is not in {{language}}, click to display anyway{% endtrans %}</p></div>
     {% endif %}
 
-    {# we put a reduce button at the top #}
-    <div class="expand_box box_top" onclick="clicked_mh_fix('{{item.id}}')">
-        <p>
-            <span class='hide'>{% trans %}Click to reduce…{% endtrans %}</span>
-        </p>
-    </div>
-
     <header>
         {% block header %}
         {# title and publication date link to a HTTP page if items_http_uri is set #}
         {% set item_http_uri = items_http_uri.get(item.id) if items_http_uri is defined else none %}
 
-        <div class="title">
+        <div class="blog__title">
             {% block blog_title scoped %}
                 {% set title = item.title_xhtml or item.title or '' %}
                 {% if item_http_uri %}
@@ -49,15 +37,18 @@
             {% endblock %}
         </div>
             {% block metadata scoped %}
-            <div class="metadata">
+            <div class="blog__metadata">
             {% if identities is defined %}
-                <span class="author">{{identities[item.author_jid].nick | default(item.author)}}</span>
+                {% if avatar is defined %}
+                    {{ avatar.avatar(item.author_jid, "avatar--float-left") }}
+                {% endif %}
+                <span class="blog__author">{{identities[item.author_jid].nick | default(item.author)}}</span>
             {% else %}
-                <span class="author">{{item.author}}</span>
+                <span class="blog__author">{{item.author}}</span>
             {% endif %}
             {% set published = item.published|date_fmt(fmt=dates_format) %}
             {% if item_http_uri %}
-                <span class="blog_data"><a href="{{item_http_uri}}">{{published}}</a></span>
+                <span class="blog__date"><a href="{{item_http_uri}}">{{published}}</a></span>
             {% else %}
                 {{- published -}}
             {% endif %}
@@ -79,20 +70,12 @@
         {% endblock header %}
     </header>
 
-    <div class="content{{' text' if not item.content_xhtml}}">
+    <div class="box__content{{' box__content--plaintext' if not item.content_xhtml}}">
         {% block content %}
         {{- item.content_xhtml or item.content|urlize or '' -}}
         {% endblock content %}
     </div>
 
-    {# and the bottom button to expand/reduce the article #}
-    <div class="expand_box box_bottom" onclick="clicked_mh_fix('{{item.id}}')">
-        <p>
-            <span class='show'>{% trans %}Click to expand…{% endtrans %}</span>
-            <span class='hide'>{% trans %}Click to reduce…{% endtrans %}</span>
-        </p>
-    </div>
-
 </article>
 
 {% endblock item %}
--- a/sat_templates/templates/default/blog/macros.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/blog/macros.html	Wed Oct 03 21:00:24 2018 +0200
@@ -1,10 +1,10 @@
 {% import 'input/textbox.html' as textbox with context %}
 
-{% macro show_items(items, comments=False, expanded=false, dates_fmt=none) %}
+{% macro show_items(items, comment=False, expanded=false, dates_fmt=none) %}
     {# show items and comments items if present after each item,
         then post form if allow_commenting is set
         @param items(BlogItems): items to show
-        @param comments(bool): True items are comments
+        @param comment(bool): True items are comments
             if False, a div with "main_article" class will be added
         @param expanded(bool): initial state of items
     #}
@@ -12,18 +12,20 @@
         {% set dates_format = dates_fmt or 'short' %}
     {% endif %}
     {% for item in items %}
-        {% if not comments %}<div class="main_article">{% endif %}
+        {% if not comment %}<div class="main_article">{% endif %}
             {% include 'blog/item.html' %}
-        {% if not comments %}</div>{% endif %}
+        {% if not comment %}</div>{% endif %}
 
         {# we recursively display comments for all comments nodes (usually there's only one) #}
         {% for comments_items in item.comments_items_list %}
-            <button class="comments_btn" onclick="clicked_mh_fix('{{'comments_panel'|next_gidx}}');clicked_cls(this)">
-                <span class='show'>{% trans %}show comments{% endtrans %}</span>
-                <span class='hide'>{% trans %}hide comments{% endtrans %}</span>
+            <div class="box box__under box--large">
+            <button class="btn-fold" onclick="clicked_mh_fix('{{'comments_panel'|next_gidx}}');clicked_cls(this)">
+                <span class='show_if_parent_not_clicked'>{% trans %}show comments{% endtrans %}</span>
+                <span class='show_if_parent_clicked'>{% trans %}hide comments{% endtrans %}</span>
                 ({{comments_items|count}})
             </button>
-            <div id="{{'comments_panel'|cur_gidx}}" class="comments_panel">
+            </div>
+            <div id="{{'comments_panel'|cur_gidx}}" class="panel-drawer">
                 {% if allow_commenting %}
                     <div class="comment_post">
                         {{- textbox.comment(service=comments_items.service, node=comments_items.node) -}}
@@ -31,7 +33,7 @@
                 {% endif %}
 
                 <div class="comments">
-                    {{show_items(comments_items, comments=True)}}
+                    {{show_items(comments_items, comment=True)}}
                 </div>
             </div>
 
--- a/sat_templates/templates/default/components/common.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/components/common.html	Wed Oct 03 21:00:24 2018 +0200
@@ -1,26 +1,10 @@
-{# menu labels, map from menu names to labels #}
-{% set ml = {
-    'login': _('Session') if profile else _('Log in'),
-    'blog': _('Blog'),
-    'forums': _('Forums'),
-    'merge-requests': _('Merge requests'),
-    'merge-request_new': _('Create new merge request'),
-    'tickets': _('Tickets'),
-    'tickets_list': _('List tickets'),
-    'ticket_new': _('Create new ticket'),
-    'chat': _('Chat'),
-    'files': _('Files sharing'),
-    'events': _('Events'),
-    'event_new': _('Create an event'),
-    'photos': _('Photos albums'),
-    'app': _('Application'),
-} %}
+{% import 'components/menu_labels.html' as ml %}
 
 {% macro menu(menus, class='') %}
     <nav class="menu {{class}}">
         <ul>
         {% for name,url in menus %}
-            <li><a class="menu_item menu_item--{{name}}" {{ {'href': url}|xmlattr }}>{{ml[name]}}</a></li>
+            <li><a class="menu_item menu_item--{{name}}" {{ {'href': url}|xmlattr }}>{{ml.label[name]}}</a></li>
         {% endfor %}
         </ul>
     </nav>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sat_templates/templates/default/components/menu_labels.html	Wed Oct 03 21:00:24 2018 +0200
@@ -0,0 +1,17 @@
+{# menu labels, map from menu names to labels #}
+{% set label = {
+    'login': _('Session') if profile else _('Log in'),
+    'blog': _('Blog'),
+    'forums': _('Forums'),
+    'merge-requests': _('Merge requests'),
+    'merge-request_new': _('Create new merge request'),
+    'tickets': _('Tickets'),
+    'tickets_list': _('List tickets'),
+    'ticket_new': _('Create new ticket'),
+    'chat': _('Chat'),
+    'files': _('Files sharing'),
+    'events': _('Events'),
+    'event_new': _('Create an event'),
+    'photos': _('Photos albums'),
+    'app': _('Application'),
+} %}
--- a/sat_templates/templates/default/event/admin.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/event/admin.html	Wed Oct 03 21:00:24 2018 +0200
@@ -16,70 +16,84 @@
 
 {% include 'event/counter.html' %}
 
-{% if invitees %}
-    <div class="box">
-    <h3 class="title">{% trans %}invitees{% endtrans %}</h3>
-    <table class="table--main">
-    <tr>
-        <th>{% trans %}name{% endtrans %}</th>
-        <th>{% trans %}coming?{% endtrans %}</th>
-        <th>{% trans %}guests{% endtrans %}</th>
-    {% for name, data in invitees.iteritems() %}
-        <tr>
-            <td>{{name}}</td>
-            <td>{{data.attend|default('')}}</td>
-            {% if data.attend == 'no' %}
-                <td>&nbsp;</td>
-            {% else %}
-                <td>{{data.guests|default(0)}}</td>
-            {% endif %}
-        </tr>
-    {% endfor %}
-    <tr>
-        <td colspan=2 class="table__total">{% trans %}total expected{% endtrans %}</td>
-        <td class="table__total_value">{{invitees_guests|default('0')}}</td>
-    </tr>
-    </table>
+<div class="tab__container">
+    <div class="tab__header">
+        <ul>
+            <li class="tab__btn state_clicked" onclick='tab_select(this, "tab_guests")'>{% trans %}Invitees{% endtrans %}</li>
+            <li class="tab__btn" onclick='tab_select(this,"tab_invitations")'>{% trans %}Invite people{% endtrans %}</li>
+            <li class="tab__btn" onclick='tab_select(this,"tab_new_post")'>{% trans %}Write a blog post{% endtrans %}</li>
+            <li class="tab__btn" onclick='tab_select(this,"tab_blog")'>{% trans %}Read event blog{% endtrans %}</li>
+        </ul>
+    </div>
+
+    <div class="tab__page state_clicked" id="tab_guests">
+        {% if invitees %}
+            <table class="table--main">
+            <tr>
+                <th>{% trans %}name{% endtrans %}</th>
+                <th>{% trans %}coming?{% endtrans %}</th>
+                <th>{% trans %}guests{% endtrans %}</th>
+            {% for name, data in invitees.iteritems() %}
+                <tr>
+                    <td>{{name}}</td>
+                    <td>{{data.attend|default('')}}</td>
+                    {% if data.attend == 'no' %}
+                        <td>&nbsp;</td>
+                    {% else %}
+                        <td>{{data.guests|default(0)}}</td>
+                    {% endif %}
+                </tr>
+            {% endfor %}
+            <tr>
+                <td colspan=2 class="table__total">{% trans %}total expected{% endtrans %}</td>
+                <td class="table__total_value">{{invitees_guests|default('0')}}</td>
+            </tr>
+            </table>
+        {% else %}
+            <p class="message--info">{% trans %}No invitee has answered yet{% endtrans %}</p>
+        {% endif %}
     </div>
-{% endif %}
+
+
+    <div class="tab__page" id="tab_invitations">
+        {% call form.form(class="form--paper form__panel--vertical form__panel--center") %}
+            {{ textbox.head(event_service, event_node, 'event') }}
+            {{ field.meta('event_id', event_id) }}
+            {{ field.textarea("jids",
+                              _("enter here a list of jid (one per line) to invite"),
+                              class="form__field--medium") }}
+            {{ field.textarea("emails",
+                              _("enter here a list of emails addresses (one per line) to invite"),
+                              class="form__field--medium") }}
+            {{ field.submit(_("Invite people")) }}
+        {% endcall %}
+    </div>
 
-<div class="box">
-<h3 class="title">{% trans %}invite people{% endtrans %}</h3>
-{% call form.form(class="form--paper form__panel--vertical form__panel--center") %}
-    {{ textbox.head(event_service, event_node, 'event') }}
-    {{ field.meta('event_id', event_id) }}
-    {{ field.textarea("jids",
-                      _("enter here a list of jid (one per line) to invite"),
-                      class="form__field--medium") }}
-    {{ field.textarea("emails",
-                      _("enter here a list of emails addresses (one per line) to invite"),
-                      class="form__field--medium") }}
-    {{ field.submit(_("Invite people")) }}
-{% endcall %}
+    <div class="tab__page" id="tab_new_post">
+        {% call form.form(class="form--paper form__panel--vertical form__panel--center") %}
+            {{ textbox.head(service, node, 'blog') }}
+            {{ field.text("title",
+                          _("title"),
+                          class="form__field--big") }}
+            {{ field.textarea("body",
+                              _("body"),
+                              class="form__field--big") }}
+            {{ field.text("language",
+                          _("language"),
+                          class="form__field--tiny") }}
+            {{ field.checkbox("comments",
+                              _("allow comments"),
+                              checked=true) }}
+            {{ field.submit(_("send")) }}
+        {% endcall %}
+    </div>
+
+    <div class="tab__page" id="tab_blog">
+        {% if items is defined %}
+            {% include 'blog/articles.html' %}
+        {% endif %}
+    </div>
+
 </div>
 
-<div class="box">
-<h3 class="title">{% trans %}write a blog post{% endtrans %}</h3>
-{% call form.form(class="form--paper form__panel--vertical form__panel--center") %}
-    {{ textbox.head(service, node, 'blog') }}
-    {{ field.text("title",
-                  _("title"),
-                  class="form__field--big") }}
-    {{ field.textarea("body",
-                      _("body"),
-                      class="form__field--big") }}
-    {{ field.text("language",
-                  _("language"),
-                  class="form__field--tiny") }}
-    {{ field.checkbox("comments",
-                      _("allow comments"),
-                      checked=true) }}
-    {{ field.submit(_("send")) }}
-{% endcall %}
-</div>
-
-{% if items is defined %}
-    {% include 'blog/articles.html' %}
-{% endif %}
-
 {% endblock body %}
--- a/sat_templates/templates/default/forum/view.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/forum/view.html	Wed Oct 03 21:00:24 2018 +0200
@@ -2,8 +2,10 @@
 {% set dates_format='relative' if single else 'short' %}
 {% import 'blog/macros.html' as blog with context %}
 {% import 'input/textbox.html' as textbox with context %}
+{% import 'input/navigation.html' as navigation with context %}
 
 {% block body %}
+{{ icon_defs('angle-double-left', 'angle-double-right') }}
 
 <div id="blog_items">
     {{ blog.show_items(items, expanded=true) }}
@@ -11,24 +13,6 @@
 <div class="forum_topic_answer">
     {{- textbox.comment_or_login(service=service, node=node, placeholder=_("Enter your message here")) -}}
 </div>
-<nav class="prev_next_links">
-    <ul>
-        {% if newer_url is defined %}
-            <li class="newer_items">
-                <a href="{{newer_url}}">
-                    <img src="{{media_path}}icons/tango/actions/32/go-previous.png">
-                    {% trans %}newer messages{% endtrans %}
-                </a>
-            </li>
-        {% endif %}
-        {% if older_url is defined %}
-            <li class="older_items">
-                <a href="{{older_url}}">
-                    <img src="{{media_path}}icons/tango/actions/32/go-next.png">
-                    {% trans %}older messages{% endtrans %}
-                </a>
-            </li>
-        {% endif %}
-    </ul>
-</nav>
+
+{{ navigation.prev_next(_("newer articles"), _("older articles")) }}
 {% endblock body %}
--- a/sat_templates/templates/default/input/field.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/input/field.html	Wed Oct 03 21:00:24 2018 +0200
@@ -72,5 +72,5 @@
 {% endmacro %}
 
 {% macro submit(text=_("Send")) %}
-    <input class="form_submit button" type="submit" value="{{text}}" class="{{kwargs.pop('class', '')}}">
+    <input class="form_submit btn" type="submit" value="{{text}}" class="{{kwargs.pop('class', '')}}">
 {% endmacro %}
--- a/sat_templates/templates/default/input/navigation.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/input/navigation.html	Wed Oct 03 21:00:24 2018 +0200
@@ -1,19 +1,19 @@
 {% macro prev_next(prev_label=_("newer"), next_label=_("older")) %}
-    <nav class="prev_next_links">
+    <nav class="prev_next box box--large box--zero">
         <ul>
             {% if newer_url is defined %}
-                <li class="newer_items">
+                <li class="prev_next__newer">
                     <a href="{{newer_url}}">
-                        <img src="{{media_path}}icons/tango/actions/32/go-previous.png">
+                        {{ icon('angle-double-left', cls='icon--small') }}
                         {{prev_label}}
                     </a>
                 </li>
             {% endif %}
             {% if older_url is defined %}
-                <li class="older_items">
+                <li class="prev_next__older">
                     <a href="{{older_url}}">
-                        <img src="{{media_path}}icons/tango/actions/32/go-next.png">
                         {{next_label}}
+                        {{ icon('angle-double-right', cls='icon--small') }}
                     </a>
                 </li>
             {% endif %}
--- a/sat_templates/templates/default/input/textbox.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/input/textbox.html	Wed Oct 03 21:00:24 2018 +0200
@@ -9,7 +9,7 @@
 {% endmacro %}
 
 {% macro submit(label=_("Send")) %}
-    <input type="submit" value="{{label}}">
+    <input type="submit" class="btn" value="{{label}}">
 {% endmacro %}
 
 {% macro textbox(service, node, action='', placeholder='',
--- a/sat_templates/templates/default/merge-request/item.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/merge-request/item.html	Wed Oct 03 21:00:24 2018 +0200
@@ -21,14 +21,14 @@
 
 {% block body %}
 {{ icon_defs('pencil') }}
-<div class="tab_container">
-    <div class="tab_header">
+<div class="tab__container">
+    <div class="tab__header">
         <ul>
-            <li class="tab_button clicked" onclick='toggle_clicked_class_sel(".tab_button,.tab_page")'>{% trans %}Description{% endtrans %}</li>
-            <li class="tab_button" onclick='toggle_clicked_class_sel(".tab_button,.tab_page")'>{% trans %}Patches{% endtrans %}</li>
+            <li class="tab__btn state_clicked" onclick='tab_select(this, "tab_description")'>{% trans %}Description{% endtrans %}</li>
+            <li class="tab__btn" onclick='tab_select(this, "tab_patches")'>{% trans %}Patches{% endtrans %}</li>
         </ul>
     </div>
-    <div class="tab_page clicked" id="tab_description">
+    <div class="tab__page state_clicked" id="tab_description">
         <div id="{{ item.widget_value['id'] }}" class="view single ticket box">
             {% if url_ticket_edit is defined %}
                 <p class="box__tools">
@@ -56,7 +56,7 @@
             </div>
         {% endif %}
     </div>
-    <div class="tab_page" id="tab_patches">
+    <div class="tab__page" id="tab_patches">
         {% for patch in patches %}
             <div class="patch">
                 <header class="box">
--- a/sat_templates/templates/default/static/app.css	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/app.css	Wed Oct 03 21:00:24 2018 +0200
@@ -4,12 +4,6 @@
     justify-content: center;
 }
 
-#web_app_box {
-    width: 80%;
-    padding: 2em;
-    text-align: justify;
-}
-
 #link_section {
     font-weight: bold;
     text-align: center;
--- a/sat_templates/templates/default/static/blog.css	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/blog.css	Wed Oct 03 21:00:24 2018 +0200
@@ -1,313 +1,7 @@
-/*** articles ***/
-
-article.box {
-    position: relative;
-    margin: 2% auto;
-    border-style: solid none none;
-    border-width: 1px;
-    padding: 2%;
-    min-height: 9em;
-    max-height: 20em;
-    overflow: hidden;
-    transition: max-height 0.5s;
-}
-
-article video {
-    max-width: 100%;
-    height: auto;
-}
-
-.main_article article.box:not(.clicked) {
-    border-bottom-right-radius: 0;
-    border-bottom-left-radius: 0;
-}
-
-/** header **/
-
-header a {
-    color: inherit;
-    text-decoration: inherit;
-}
-
-header .metadata {
-    text-align: right;
-}
-
-article .author {
-    font-weight: bold;
-}
-
-article .author::after {
-    content: ", ";
-}
-
-/*** labels ***/
-
-.labels {
-    text-align: right;
-    white-space: nowrap;
-}
-
-.labels a {
-    text-decoration: none;
-    color: inherit;
-}
-
-.labels span {
-    font-variant: small-caps;
-    font-size: 0.8rem;
-    background-color: #ddd;
-    border-radius: 0.4em;
-    padding: 0 0.5em;
-    transition: all 0.5s;
-}
-
-.labels a>span {
-    cursor: pointer;
-}
-
-.labels a>span:hover {
-    box-shadow: 0px 0px 6px 1px #000;
-}
-
-
-/** content **/
-
-article div.content {
-    text-align: justify;
-    font-size: 0.9em;
-}
-
-article div.content.text {
-    white-space: pre-wrap;
-}
-
-
-article img {
-    max-width: 100%;
-    margin: 0;
-}
-
-/** reduce/expand buttons **/
-
-.expand_box {
-    cursor: pointer;
-}
-
-.box_top {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 100%;
-}
-
-.box_bottom {
-    position: absolute;
-    bottom: 0;
-    left: 0;
-    width: 100%;
-}
-
-.expand_box.box_bottom::before {
-    /* we do a gradient to show that text can be expanded */
-    background-image: linear-gradient(to bottom,rgba(0,0,0,0),#ffffff);
-    display: block;
-    content: "";
-    width: 100%;
-    height: 4em;
-    border: none;
-}
-
-.expand_box p {
-    background-color: white;
-    margin: 0;
-    text-align: center;
-    font-weight: bold;
-    font-size: 0.8em;
-    border-style: solid none dotted none;
-    border-width: 1px 0 1px;
-    border-bottom-color: gray;
-}
-
-article .expand_box .hide {
-    /* when not clicked, we only display .show */
-    display: none;
-}
-
-article .expand_box.box_top {
-    /* top expand box only show a reduce button
-     * so it should be displayed only when article is .clicked */
-    display: none;
-}
-
-/** other language **/
-
-/* we hide everything just to display a message informing that
- * the item is in an other language, and asking to click
- * to display it */
-
-article.other_lang>div.info {
-    display: none;
-}
-
-article.other_lang.init>* {
-    display: none;
-}
-
-article.other_lang.init>div.info {
-    display: initial;
-}
-
-article.other_lang.init>div.expand_box.box_top {
-    /* as we need to have the message clickable, we cheat and use
-     * expand box on the whole surface but fully transparent */
-    display: initial;
-    height: 100%;
-    opacity: 0;
-}
-
-article.other_lang.init>div.info>p {
-    margin: 0;
-    padding: 0.2em;
-    text-align: center;
-    font-style: italic;
-}
-
-article.other_lang.init {
-    border: none;
-    border-radius: 0;
-    padding: 0;
-    min-height: 0;
-}
-
-/*** comments ***/
-
-button.comments_btn {
-    border: none;
-    font-weight: bold;
-    display: block;
-    margin: 0 10% 0 auto;
-    border-radius: 1em;
-    background:  #b8bcc4;
-    color: #4d4d4d;
-}
-
-button.comments_btn:active {
-    background: #4d4d4d;
-    color: #b8bcc4;
-}
-
-button.comments_btn.clicked span.show {
-    display: none;
-}
-
-button.comments_btn:not(.clicked) span.hide {
-    display: none;
-}
-
-.comments_panel {
-    max-height: 0;
-    opacity: 0;
-    transition: max-height 1s, opacity 2s;
-    overflow: hidden;
-}
-
-.comments_panel.clicked {
-    opacity: 1;
-}
-
-.comments article {
-    background-color: #9ca0a8;
-    border: none;
-    max-height: none;
-}
-
-.comment_post {
-    text-align: center;
-}
-
-.comment_post textarea {
-    border-style: solid;
-    border-width: 1px  0;
-    border-color: black;
-    max-width: 100%;
-}
-
-.comments_panel article .expand_box {
-    /* no expand box in comments */
-    display: none;
-}
-
-/*** media queries ***/
-
 @media (min-width: 500px) {
-    /*** general ***/
-
     #main_area {
         background-image: var(--bg-img);
         background-repeat: no-repeat;
         background-size: cover;
     }
-
-    article.box {
-        width: 80%;
-        border-style: solid solid none solid;
-    }
-    .comments article.box {
-        width: 30rem;
-        margin: 2% auto;
-        border: none;
-    }
-    .comment_post textarea {
-        border-width: 1px;
-        border-radius: 1em;
-        border: solid 1px;
-        padding: 0.5em;
-    }
-
-    footer span {
-        background: rgba(200,200,200,0.6);
-        border-radius: 0.5em 0.5em 0 0;
-        padding: 0 0.5em;
-        margin-top: 1em;
-    }
-
 }
-
-/*** clicked ***/
-
-.main_article article.clicked {
-    border-bottom-style: solid;
-}
-
-.main_article article.clicked .expand_box.box_top {
-    display: initial;
-}
-
-.main_article article.clicked .expand_box {
-    opacity: 0;
-    transition: opacity 0.5s;
-}
-
-.main_article article.clicked .expand_box p {
-    background-color: transparent;
-    border: none;
-}
-
-.main_article article.clicked .expand_box:hover {
-    opacity: 1;
-    color: grey;
-}
-
-.main_article article.clicked .expand_box::before {
-    background-image: none;
-    display: none;
-}
-
-.main_article article.clicked .expand_box .hide {
-    display: inline;
-}
-
-.main_article article.clicked .expand_box .show {
-    display: none;
-}
--- a/sat_templates/templates/default/static/common.js	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/common.js	Wed Oct 03 21:00:24 2018 +0200
@@ -43,19 +43,19 @@
     return available;
 }
 
-function toggle_clicked_class_tag(tag_name, class_name='clicked') {
+function toggle_clicked_class_tag(tag_name, class_name='state_clicked') {
     for (let elt of document.getElementsByTagName(tag_name)) {
         elt.classList.toggle(class_name);
     }
 }
 
-function toggle_clicked_class_sel(selectors, class_name='clicked') {
+function toggle_clicked_class_sel(selectors, class_name='state_clicked') {
     for (let elt of document.querySelectorAll(selectors)) {
         elt.classList.toggle(class_name);
     }
 }
 
-function set_clicked_class_id(trigger_elem_id, target_elem_id=null, class_name='clicked') {
+function set_clicked_class_id(trigger_elem_id, target_elem_id=null, class_name='state_clicked') {
     if (target_elem_id === null) { target_elem_id = trigger_elem_id; }
     document.getElementById(trigger_elem_id).addEventListener(
         "click",
@@ -65,6 +65,26 @@
     );
 }
 
+function tab_select(tab_btn_elt, tab_page_id) {
+    for (let elt of document.getElementsByClassName("tab__btn")) {
+        if (elt === tab_btn_elt) {
+            elt.classList.add('state_clicked');
+        }
+        else {
+            elt.classList.remove('state_clicked');
+        }
+    }
+    let tab_page_elt = document.getElementById(tab_page_id);
+    for (let elt of document.getElementsByClassName("tab__page")) {
+        if (elt === tab_page_elt) {
+            elt.classList.add('state_clicked');
+        }
+        else {
+            elt.classList.remove('state_clicked');
+        }
+    }
+}
+
 function get_elt(arg) {
     if (typeof arg === 'string') {
         // we should have an id
@@ -77,58 +97,73 @@
 }
 
 function clicked_cls(elt) {
-    /* toggle "clicked" class on each click, and remove "init" class if present */
-    // init
-    if (elt.classList.contains("init")) {
-        elt.classList.remove("init");
+    /* toggle "state_clicked" class on each click, and remove "state_init" class if present */
+    // state_init
+    if (elt.classList.contains("state_init")) {
+        elt.classList.remove("state_init");
     }
 
     // clicked
-    elt.classList.toggle("clicked");
+    elt.classList.toggle("state_clicked");
 }
 
-function clicked_mh_fix(arg) {
-    /* toggle clicked, and fix max-height on transitionend
+function clicked_mh_fix(arg, max_height) {
+    /* toggle state_clicked, and fix max-height on transitionend
      *
      * needed to workaround transition issue with max-height:none
      * inspired from https://css-tricks.com/using-css-transitions-auto-dimensions,
      * thanks to Brandon Smith
      *
-     * @param arg: element to toggle (id as string, or element itself)
+     * @param arg(string, DOM element): element to toggle (id as string, or element itself)
+     * @param max_height(int): maximum height when collapsed (default to clientHeight)
      * */
     elt = get_elt(arg);
 
-    if (!elt.classList.contains("clicked")) {
+    if (!elt.classList.contains("state_clicked")) {
         /* expand */
-        var fix_expand = function(event) {
+        let fix_expand = function(event) {
             elt.removeEventListener("transitionend", fix_expand, false);
-            if (elt.classList.contains("clicked")) {
+            if (elt.classList.contains("state_clicked")) {
                 /* if event is clicked quicker than transition time,
                  * this callback can be called on reduce */
                 elt.style.maxHeight = "none";
             }
         };
 
-        elt.setAttribute('max_height_init', elt.clientHeight);
+        if (!elt.hasAttribute('_max_height_init')) {
+            elt.setAttribute('_max_height_init', max_height!==undefined?max_height:elt.clientHeight);
+        }
         elt.addEventListener("transitionend", fix_expand, false);
         clicked_cls(elt);
         elt.style.maxHeight = elt.scrollHeight + 'px';
+
     }
     else {
         /* reduce */
-        var transition_save = elt.style.transition;
+        let transition_save = elt.style.transition;
         elt.style.transition = '';
         requestAnimationFrame(function() {
             elt.style.maxHeight = elt.scrollHeight + 'px';
             elt.style.transition = transition_save;
 
             requestAnimationFrame(function() {
-                elt.style.maxHeight = elt.getAttribute('max_height_init') + 'px';
-                elt.removeAttribute('max_height_init');
-                elt.style.maxHeight = null;
+                elt.style.maxHeight = elt.getAttribute('_max_height_init') + 'px';
             });
         });
 
         clicked_cls(elt);
     }
 }
+
+function createElement(html) {
+    /* create a DOM element from raw HTML
+     *
+     * @param html(string): raw HTML to parse
+     * @return: DOM element
+     */
+
+    let template = document.createElement('template');
+    template.innerHTML = html.trim();
+    new_element = template.content.firstChild;
+    return new_element;
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sat_templates/templates/default/static/dom_update.js	Wed Oct 03 21:00:24 2018 +0200
@@ -0,0 +1,87 @@
+/* This script check for well-known DOM element to modify when javascript is enabled */
+
+const EXPAND_LIMIT = 250; // max height before expanding is needed, in pixels
+const MAGIC_CLASSES = {
+    "box--expand": "handleBoxExpand"};
+
+
+function addExpandListeners(elt, expand_elt, reduce_elt) {
+    let on_click = function(){
+        clicked_mh_fix(elt);
+    };
+    expand_elt.addEventListener('click', on_click, false);
+    reduce_elt.addEventListener('click', on_click, false);
+}
+
+function handleBoxExpand(box_elt) {
+    /* Add expand zone elements if box height is > EXPAND_LIMIT
+     *
+     * Those zone will expand/reduce the box when clicked
+     * @param box_elt(DOM element): element with box--expand class
+     */
+    let content_elt = box_elt.getElementsByClassName("box__content")[0];
+
+    if (content_elt === undefined) {
+        return;
+    }
+
+    if (content_elt.offsetHeight > EXPAND_LIMIT) {
+        /* top expand box */
+        let reduce_elt = document.createElement("div");
+        reduce_elt.className = "box__expand_zone box__expand_zone--top show_if_parent_clicked";
+        let p_elt = document.createElement("p");
+        p_elt.textContent = reduce_txt;
+        reduce_elt.appendChild(p_elt);
+        box_elt.insertBefore(reduce_elt, box_elt.firstChild);
+
+        /* bottom expand box */
+        let expand_elt = document.createElement("div");
+        expand_elt.className = "box__expand_zone box__expand_zone--bottom";
+        let p_elt_clicked = document.createElement("p");
+        p_elt_clicked.textContent = expand_txt;
+        p_elt_clicked.className = "show_if_grandparent_not_clicked";
+        let p_elt_not_clicked = document.createElement("p");
+        p_elt_not_clicked.textContent = reduce_txt;
+        p_elt_not_clicked.className = "show_if_grandparent_clicked";
+        expand_elt.appendChild(p_elt_clicked);
+        expand_elt.appendChild(p_elt_not_clicked);
+        box_elt.appendChild(expand_elt);
+
+        addExpandListeners(box_elt, expand_elt, reduce_elt);
+    }
+}
+
+
+function handleStateInit(elt) {
+    /* Add a click listener which remove state_init
+     *
+     * The listener will call magic classes handlers when suitable
+     * @param elt(DOM element): element with state_init class
+     */
+    function onClick() {
+        elt.removeEventListener('click', onClick, false);
+        elt.classList.remove("state_init");
+
+        for (let [className, funcName] of Object.entries(MAGIC_CLASSES)){
+            if (elt.classList.contains(className)) {
+                window[funcName](elt);
+            }
+        }
+    }
+    elt.addEventListener('click', onClick, false);
+}
+
+// we first have to handle "state_init"
+for (let elt of document.getElementsByClassName("state_init")) {
+    handleStateInit(elt);
+}
+
+// we then launch every handler where "state_init" is not set
+// "state_init" handler will launch the handlers itself on first click
+for (let [className, funcName] of Object.entries(MAGIC_CLASSES)){
+    for (let box_elt of document.getElementsByClassName(className)) {
+        if (!box_elt.classList.contains("state_init")) {
+            window[funcName](box_elt);
+        }
+    }
+}
--- a/sat_templates/templates/default/static/event.css	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/event.css	Wed Oct 03 21:00:24 2018 +0200
@@ -1,5 +1,3 @@
-@import 'blog.css'; /* needed as blog/articles.html is included */
-
 .invitation_header {
     text-align: center;
     font-variant: small-caps;
--- a/sat_templates/templates/default/static/forum.css	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/forum.css	Wed Oct 03 21:00:24 2018 +0200
@@ -1,5 +1,3 @@
-@import 'blog.css'; /* needed as blog/articles.html is included */
-
 .forums {
     margin: 2em auto 0 auto;
     width: 90%;
--- a/sat_templates/templates/default/static/login.css	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/login.css	Wed Oct 03 21:00:24 2018 +0200
@@ -71,8 +71,8 @@
     margin-bottom: 1em;
 }
 
-#login_form .form_submit,
-#logged .form_submit {
+#login_form .form_submit
+{
     /* FIXME: as above /media is not good.
      * url should be replaced by real gradient */
     color: #fff;
@@ -87,6 +87,11 @@
     margin-top: 30px;
 }
 
+#login_form .form_submit:hover
+{
+    background-color: #860000;
+}
+
 #login_error {
     position: absolute;
     margin: -90px 0 0;
@@ -166,7 +171,7 @@
         max-height: 50px;
         margin: 10px 46px 0;
     }
-     
+
     #login_error p {
         position: static;
         margin: 0;
--- a/sat_templates/templates/default/static/photo.css	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/photo.css	Wed Oct 03 21:00:24 2018 +0200
@@ -1,5 +1,3 @@
-@import 'blog.css'; /* needed for comments */
-
 .album {
     display: flex;
     flex-wrap: wrap;
@@ -38,14 +36,3 @@
 .comments__count {
     font-weight: bold;
 }
-
-.panel-drawer {
-    max-height: 0;
-    opacity: 0;
-    transition: max-height 1s, opacity 2s;
-    overflow: hidden;
-}
-
-.panel-drawer.clicked {
-    opacity: 1;
-}
--- a/sat_templates/templates/default/static/styles.css	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/styles.css	Wed Oct 03 21:00:24 2018 +0200
@@ -1,8 +1,24 @@
+/*************
+ * Constants *
+ *************/
+
 :root {
+  --box-bg-color: #efefef;
+  --box--expand_limit: 20rem;
+  --box--expand_height-min: 9rem;
   --select-bg-color: #ddd;
-  --size-medium: 3em;
+  --size-medium: 3rem;
+  --color-prim: #fafafa;
+  --color-prim--light: #ffffff;
+  --color-prim--dark: #c7c7c7;
+  --color-sec: #448aff;
+  --color-sec--light: #83b9ff;
+  --color-sec--dark: #005ecb;
 }
 
+/*****************
+ * Main Elements *
+ *****************/
 
 html {
     font-family: "sat-base-font";
@@ -37,16 +53,18 @@
     position: relative;
 }
 
-footer {
+.page__footer {
     text-align: center;
     font-size: 0.7em;
     font-weight: bold;
+    padding-top: 1em;
 }
-.title {
-    font-weight: bold;
-    text-align: center;
+
+.page__footer span {
+    background: white;
 }
 
+
 .post_confirm {
     text-align: center;
     background-color: lightgreen;
@@ -57,22 +75,132 @@
     margin: 1.5em auto;
 }
 
-/*** Generic ***/
+/**********
+ * States *
+ **********/
+
+.state_init {
+    cursor: pointer;
+}
+
+.other_lang.state_init>* {
+    display: none;
+}
+
+.show_if_init {
+    display: none;
+}
+
+.state_init.show_if_init {
+    /* unset is not working well here (it uses "inline", not element default) */
+    display: block;
+}
+
+.show_if_parent_init {
+    display: none;
+}
+
+.state_init>.show_if_parent_init {
+    display: block;
+}
+
+.show_if_parent_clicked {
+    display: none;
+}
 
-.button {
-    padding: 0.5em 1em;
-    background: #333;
-    color: #ccc;
+.state_clicked>.show_if_parent_clicked {
+    /* cf. .show_if_init */
+    display: block;
+}
+
+.state_clicked>span.show_if_parent_clicked {
+    /* cf. .show_if_init */
+    display: inline;
+}
+
+.state_clicked>.show_if_parent_not_clicked {
+    display: none;
+}
+
+.show_if_grandparent_clicked {
+    display: none;
+}
+
+.state_clicked>*>.show_if_grandparent_clicked {
+    /* cf. .show_if_init */
+    display: block;
+}
+
+.state_clicked>*>.show_if_grandparent_not_clicked {
+    display: none;
+}
+
+/***********
+ * Generic *
+ ***********/
+
+/** Buttons **/
+
+.btn {
+    padding: 0.3em 0.5em;
+    background-color: #222;
+    color: white;
     border: 1px solid #555;
     border-radius: 0.8em;
     font-weight: bold;
 }
 
 
-.button:hover {
-    background-color: #bc0000;
+.btn:hover {
+    background-color: var(--color-sec);
+}
+
+.btn-fold {
+    border: none;
+    border-radius: 1em;
+    background-color: var(--color-prim--light);
+    color: #727272;
+    font-weight: bold;
+    font-variant: small-caps;
+    padding: 0;
+    cursor: pointer;
+}
+
+.btn-fold:hover {
+    font-weight: bold;
+}
+
+/** Labels **/
+
+.labels {
+    text-align: right;
+    white-space: nowrap;
 }
 
+.labels a {
+    text-decoration: none;
+    color: inherit;
+}
+
+.labels span {
+    font-variant: small-caps;
+    font-size: 0.8rem;
+    background-color: #ddd;
+    border-radius: 0.4em;
+    padding: 0 0.5em;
+    transition: all 0.5s;
+}
+
+.labels a>span {
+    cursor: pointer;
+}
+
+.labels a>span:hover {
+    box-shadow: 0px 0px 6px 1px #000;
+}
+
+/** instructions **/
+
 .instructions--head {
     font-size: 1.5em;
     text-align: center;
@@ -83,27 +211,95 @@
     font-style: italic;
 }
 
+/** images **/
+
+.img--center{
+    display: block;
+    margin: 0 auto;
+    max-width: 100%;
+}
+
+.img--small {
+    height: 100px;
+}
+
+/** other language **/
+
+.other_lang.state_init>div.info>p {
+    margin: 0;
+    padding: 0.2em;
+    text-align: center;
+    font-style: italic;
+}
+
+/** misc **/
+
 .items_vert--centered {
     display: flex;
     flex-direction: column;
     align-items: center;
 }
 
-/*** boxes ***/
+.link--center {
+    display: block;
+    text-align: center;
+}
+
+/*********
+ * pages *
+ *********/
+
+.page__title {
+    text-align: center;
+
+}
+
+/*********
+ * boxes *
+ *********/
 
 .box {
-    background-color: #edf2ff;
-    border-radius: 0;
-    border-color: silver;
+    background: var(--color-prim--light);
+    position: relative;
+    border-top: solid 1px var(--color-prim-dark);
     margin: 0 auto;
+    padding: 2rem;
+    max-width: 100em;
+}
+
+.box__content {
+    text-align: justify;
+}
+
+.box__content img {
+    max-width: 100%;
+    margin: 0;
+}
+
+.box__content video {
+    max-width: 100%;
+    height: auto;
+}
+
+.box__content--plaintext {
+    white-space: pre-wrap;
+}
+
+
+.box--large {
+    max-width: 80rem;
+}
+
+.box--plain {
+    background-color: var(--box-bg-color);
 }
 
 .box--medium {
-    max-width: 50em;
+    max-width: 50rem;
 }
 
 .box--small {
-    max-width: 20em;
+    max-width: 20rem;
 }
 
 .box--hollow {
@@ -120,7 +316,75 @@
     border: none;
 }
 
+.box--comment {
+    max-width: 40rem;
+    background: var(--color-prim);
+}
+
 .box--center {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.box--zero {
+/* box with no padding or decoration, used when we want only the margin */
+    border: none;
+    padding: 0;
+}
+
+.box--expand {
+    /* a box which is folded when too big */
+    max-height: var(--box--expand_limit);
+    overflow: hidden;
+    transition: max-height 0.5s;
+}
+
+.box__expand_zone {
+    /* zone to click to expand/fold the box */
+    cursor: pointer;
+    position: absolute;
+    left: 0;
+    width: 100%;
+    transition: opacity 0.5s;
+}
+
+.box__expand_zone--top {
+    top: 0;
+}
+
+.box__expand_zone--bottom {
+    bottom: 0;
+}
+
+.box__expand_zone p {
+    background-color: white;
+    margin: 0;
+    text-align: center;
+    font-size: 0.8em;
+    font-variant: small-caps;
+}
+
+.state_clicked>.box__expand_zone {
+    opacity: 0;
+}
+
+.state_clicked>.box__expand_zone:hover {
+    opacity: 1;
+}
+
+.box__expand_zone--bottom::before {
+    /* we do a gradient to show that text can be expanded */
+    background-image: linear-gradient(to bottom,rgba(255,255,255,0),#ffffff);
+    display: block;
+    content: "";
+    width: 100%;
+    height: 4em;
+    border: none;
+}
+
+.state_clicked>.box__expand_zone--bottom::before {
+    display: none;
 }
 
 .box__tools {
@@ -140,8 +404,73 @@
     background-color: var(--select-bg-color);
 }
 
+.box__under {
+    /* block under a box showing action buttons */
+    border: none;
+    padding-top: 0;
+    padding-bottom: 0;
+    text-align: right;
+}
 
-/*** blocks ***/
+/********
+ * Blog *
+ ********/
+
+.blog__title {
+    font-weight: bold;
+    text-align: center;
+}
+
+.blog__title a {
+    color: inherit;
+    text-decoration: inherit;
+}
+
+.blog__metadata {
+    text-align: right;
+}
+
+.blog__author {
+    font-weight: bold;
+}
+
+.blog__author a {
+    color: inherit;
+    text-decoration: inherit;
+}
+
+.blog__author::after {
+    content: ", ";
+}
+
+.blog__date {
+}
+
+.blog__date a {
+    color: inherit;
+    text-decoration: inherit;
+}
+
+/**********
+ * Panels *
+ **********/
+
+.panel-drawer {
+    /* A panel which is hidden by default but can be
+       opened when it's clicked */
+    max-height: 0;
+    opacity: 0;
+    overflow: hidden;
+    transition: max-height 0.5s, opacity 0.5s;
+}
+
+.panel-drawer.state_clicked {
+    opacity: 1;
+}
+
+/**********
+ * blocks *
+ **********/
 
 .block_separator {
     font-size: 1.4em;
@@ -160,7 +489,9 @@
     margin-top: 0.7em;
 }
 
-/*** lists ***/
+/*********
+ * lists *
+ *********/
 
 .list {
     list-style: none;
@@ -173,7 +504,9 @@
     color: inherit;
 }
 
-/*** grids ***/
+/*********
+ * Grids *
+ *********/
 
 .grid {
     display: flex;
@@ -207,11 +540,13 @@
     background-color: var(--select-bg-color);
 }
 
-/*** tables ***/
+/**********
+ * Tables *
+ **********/
 
 .table--main {
     margin: 1em auto;
-	border-collapse: collapse;
+    border-collapse: collapse;
     text-align: center;
 }
 
@@ -234,14 +569,15 @@
     font-weight: bold;
 }
 
-/*** avatars ***/
+/***********
+ * Avatars *
+ ***********/
 
 .avatar {
     height: 2rem;
     width: 2rem;
     align-content: center;
     justify-content: center;
-    background: #ccc;
     border-radius: 0.2rem;
 }
 
@@ -252,8 +588,6 @@
 
 .avatar--float-left {
     float: left;
-    margin-top: 0.3em;
-    margin-right: 0.5em;
 }
 
 .avatar__content {
@@ -271,13 +605,9 @@
     background:  #43d2f6;
 }
 
-/*** images ***/
-.img--small {
-    height: 100px;
-}
-
-
-/*** icons ***/
+/*********
+ * icons *
+ *********/
 
 .icon--medium {
     height: var(--size-medium);
@@ -287,6 +617,7 @@
 
 .icon--small {
     height: 1em;
+    vertical-align: middle;
 }
 
 .icon--soft {
@@ -297,7 +628,9 @@
 
 }
 
-/*** Messages ***/
+/************
+ * Messages *
+ ************/
 
 .message--info {
     max-width: 500px;
@@ -318,7 +651,9 @@
     text-align: center;
 }
 
-/*** Menus ***/
+/*********
+ * Menus *
+ *********/
 
 .menu ul {
     display: flex;
@@ -379,21 +714,23 @@
     background: #eee;
 }
 
-/*** containers ***/
+/**************
+ * containers *
+ **************/
 
 /* tabs */
 
-.tab_container {
+.tab__container {
     max-width: 1000px;
     margin: 0 auto;
 }
 
-.tab_header {
+.tab__header {
     background-color: white;
     border-bottom: 1px solid lightgrey;
 }
 
-.tab_header ul {
+.tab__header ul {
     display: flex;
     margin: 0;
     padding: 0;
@@ -401,7 +738,7 @@
     background-color: white;
 }
 
-.tab_page {
+.tab__page {
     box-sizing: border-box;
     padding-top: 2em;
     border: 1px solid lightgrey;
@@ -409,11 +746,11 @@
     display: None;
 }
 
-.tab_page.clicked {
+.tab__page.state_clicked {
     display: block;
 }
 
-.tab_button {
+.tab__btn {
     display: inline;
     color: grey;
     background-color: white;
@@ -426,29 +763,31 @@
     margin-bottom: -1px;
 }
 
-.tab_button.clicked {
+.tab__btn.state_clicked {
     /* background: lightgrey; */
     color: inherit;
     border-bottom: none;
 }
 
-li.tab_button:last-child {
+li.tab__btn:last-child {
     border-right: 1px solid lightgrey;
 }
 
-.tab_button input {
+.tab__btn input {
     display: None;
 }
 
-.tab_button label {
+.tab__btn label {
     margin: 1em;
 }
 
-.tab_button input:checked + label {
+.tab__button input:checked + label {
     font-weight: bold;
 }
 
-/*** Forms ***/
+/*********
+ * Forms *
+ *********/
 
 /* a form with only one field */
 
@@ -549,7 +888,9 @@
     width: 100%;
 }
 
-/* Textboxes */
+/*************
+ * Textboxes *
+ *************/
 
 .textbox {
     margin-left: auto;
@@ -572,49 +913,44 @@
     text-align: center;
 }
 
-/*** Navigation ***/
+/**************
+ * Navigation *
+ **************/
 
-.prev_next_links ul {
+.prev_next ul {
     list-style: none;
     display: flex;
-    padding: 0 2em;
+    padding: 0;
     margin: 0;
 }
 
-.prev_next_links li {
+.prev_next li {
     flex: 1;
 }
 
-.prev_next_links li.older_items {
+.prev_next li.prev_next__older {
     text-align: right;
 }
 
-.prev_next_links img {
-    display: block;
-}
 
-.prev_next_links .older_items img {
-    display: block;
-    margin-left: auto;
-    margin-right: 0;
-}
-
-.prev_next_links a {
+.prev_next a {
     display: inline-block;
     margin-top: 1em;
     padding: 0.2em;
     text-decoration: None;
     color: inherit;
     font-variant: small-caps;
-    background: rgba(200,200,200,0.6);
+    background-color: var(--color-prim--light);
     border-radius: 0.5em;
 }
 
-.prev_next_links a:hover {
+.prev_next a:hover {
     background-color: #ddd;
 }
 
-/*** XMLUI ***/
+/*********
+ * XMLUI *
+ *********/
 
 .xmlui_cont_vertical>* {
     display: block;
@@ -631,6 +967,47 @@
     font-weight: bold;
 }
 
+ul.xmlui_list {
+    list-style: none;
+    display: flex;
+    flex-direction: column;
+    padding: 0;
+}
+
+.xmlui_list li {
+    display: inline-flex;
+    background: #eee;
+    padding: 0.5em;
+    margin: 0.5em 0;
+    border: 1px solid silver;
+}
+
+.xmlui_list li:hover {
+    background: yellow;
+}
+
+.xmlui_list a {
+    display: flex;
+    width: 100%;
+    text-decoration: none;
+    color: inherit;
+}
+
+.xmlui_list a:visited {
+    color: inherit;
+}
+
+.xmlui_field__id {
+    font-style: italic;
+    padding-right: 1em;
+}
+
+.xmlui_field__title {
+    padding-right: 1em;
+}
+
+
+
 td a {
   /* we use <a> for non JS links in table
    * so we don't want specific color/text-decoration by default
@@ -640,7 +1017,9 @@
 }
 
 
-/*** Notifications ***/
+/*****************
+ * Notifications *
+ *****************/
 
 .notification.retry {
     position: fixed;
@@ -664,6 +1043,11 @@
 }
 
 @media (min-width: 800px) {
+
+    /*****************
+     * Main Elements *
+     *****************/
+
     html {
         background-size: auto;
     }
@@ -676,12 +1060,29 @@
         overflow: auto;
     }
 
-    /*** boxes ***/
+    /***********
+     * Generic *
+     ***********/
+
+    .btn-fold {
+        padding: 0.3em;
+    }
+
+    /** instructions **/
+
+    .instructions--alt {
+        padding-top: 3rem;
+        margin-bottom: 3rem;
+    }
+
+
+    /*********
+     * boxes *
+     *********/
 
     .box {
-        border-radius: 1em;
-        box-shadow: 10px 10px 16px -5px rgba(0,0,0,0.5);
-        width: 94%;
+        border-radius: 0.2em;
+        box-shadow: 2px 4px 4px 0px rgba(0,0,0,0.2);
         margin: 1em auto;
         border: solid 1px;
         border-color: #9ca0a8;
@@ -698,7 +1099,23 @@
         margin: 0.5em;
     }
 
-    /*** Forms ***/
+    .box--zero {
+        box-shadow: none;
+        border: none;
+        background: none;
+    }
+
+    .box__under {
+        /* block under a box showing action buttons */
+        box-shadow: none;
+        border: none;
+        background: none;
+        text-align: right;
+    }
+
+    /*********
+     * Forms *
+     *********/
 
     .form__panel--vertical {
         display: flex;
@@ -711,26 +1128,6 @@
         width: 95%;
     }
 
-    .main_menu a {
-        display: block;
-        padding: 2em 0;
-    }
-
-    .main_menu ul {
-        flex-direction: column;
-        padding-left: 2em;
-    }
-
-    .prev_next_links ul {
-        padding: 0 6em;
-    }
-
-    .instructions--alt {
-        padding-top: 3rem;
-    }
-
-    /*** forms ***/
-
     .form--single input:not([type="submit"]) {
         margin: 0 1em;
     }
@@ -744,4 +1141,18 @@
     .form--single .form_input {
         flex-direction: row;
     }
+
+    /*********
+     * Menus *
+     *********/
+
+    .main_menu a {
+        display: block;
+        padding: 1em 0;
+    }
+
+    .main_menu ul {
+        flex-direction: column;
+        padding-left: 2em;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sat_templates/templates/default/static/styles_noscript.css	Wed Oct 03 21:00:24 2018 +0200
@@ -0,0 +1,29 @@
+/*******************************************************
+ * This styles are used when javascript is not enabled *
+ *******************************************************/
+
+
+/*************
+ * Constants *
+ *************/
+
+:root {
+  --box--expand_limit: none;
+}
+
+/*********
+ * boxes *
+ *********/
+
+.box__under {
+    display: none;
+}
+
+/************
+ * Comments *
+ ************/
+
+.comments_panel {
+    max-height: none;
+    opacity: 1;
+}
--- a/sat_templates/templates/default/static/ticket.css	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/static/ticket.css	Wed Oct 03 21:00:24 2018 +0200
@@ -1,58 +1,7 @@
-@import 'blog.css'; /* needed as blog/articles.html is included */
-
-.instructions {
-    font-style: italic;
-    text-align: center;
-}
-
-.instructions span {
-    padding: 0.3em;
-}
-
-ul.xmlui_list {
-    list-style: none;
-    display: flex;
-    flex-direction: column;
-    padding: 0;
-}
-
-.xmlui_list li {
-    display: inline-flex;
-    background: #eee;
-    padding: 0.5em;
-    margin: 0.5em 0;
-    border: 1px solid silver;
-}
-
-.xmlui_list li:hover {
-    background: yellow;
-}
-
-.xmlui_list a {
-    display: flex;
-    width: 100%;
-    text-decoration: none;
-    color: inherit;
-}
-
-.xmlui_list a:visited {
-    color: inherit;
-}
-
 .tickets a.status_closed {
     text-decoration: line-through;
     color: grey;
 }
-
-.xmlui_field__id {
-    font-style: italic;
-    padding-right: 1em;
-}
-
-.xmlui_field__title {
-    padding-right: 1em;
-}
-
 .tickets a.severity_major .xmlui_field__title {
     font-weight: bold;
     color: red;
--- a/sat_templates/templates/default/ticket/create.html	Fri Sep 14 19:49:15 2018 +0200
+++ b/sat_templates/templates/default/ticket/create.html	Wed Oct 03 21:00:24 2018 +0200
@@ -7,7 +7,7 @@
 {% import 'input/xmlui.html' as xmlui with context %}
 
 {% block body %}
-<div class='instructions'>
+<div class='instructions--alt'>
     <p><span class="box">{% trans app_name=C.APP_NAME%}This page allows you to report an issue or ask/suggest a new feature for {{app_name}}{% endtrans %}</span></p>
 </div>
 <div class="create single ticket box">