Merge default dev-dc
authorDamien Correia
Tue, 04 Dec 2018 15:53:25 +0100
branchdev-dc
changeset 274 39bf2d8df31d
parent 238 df8da54d790a (current diff)
parent 273 7e42b94d188e (diff)
child 275 ed29fe62235b
Merge default
--- a/.hgtags	Tue Nov 20 15:19:28 2018 +0100
+++ b/.hgtags	Tue Dec 04 15:53:25 2018 +0100
@@ -15,3 +15,5 @@
 fe7f30ba737d6790b949bac378f8539dcb3ab62f 0.1.14
 57a4e27aa1c4c87748db4caff29068e5905e0497 0.1.15
 d93f3085e2616c3e0f6499925b3ce056e8f4f08f 0.1.16
+cb03816a641948ec23bac912cdc7c6f56e44f004 0.1.17
+41f43b3456db36f329fba0bed098449c98f4b55d 0.1.18
--- a/buildout.cfg	Tue Nov 20 15:19:28 2018 +0100
+++ b/buildout.cfg	Tue Dec 04 15:53:25 2018 +0100
@@ -79,4 +79,4 @@
 eggs = pyams_default_theme [test]
 
 [versions]
-pyams_default_theme = 0.1.16
+pyams_default_theme = 0.1.18
--- a/docs/HISTORY.txt	Tue Nov 20 15:19:28 2018 +0100
+++ b/docs/HISTORY.txt	Tue Dec 04 15:53:25 2018 +0100
@@ -1,6 +1,18 @@
 History
 =======
 
+0.1.18
+------
+ - added renderers to simple navigation and site summary portlets
+ - added search results portlet
+ - updated breadcrumbs and tags content providers
+ - updated renderers templates
+ - updated CSS
+
+0.1.17
+------
+ - added customizable label to contact button
+
 0.1.16
 ------
  - added results internal OID into view's preview
--- a/setup.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/setup.py	Tue Dec 04 15:53:25 2018 +0100
@@ -22,7 +22,7 @@
 README = os.path.join(DOCS, 'README.txt')
 HISTORY = os.path.join(DOCS, 'HISTORY.txt')
 
-version = '0.1.16'
+version = '0.1.18'
 long_description = open(README).read() + '\n\n' + open(HISTORY).read()
 
 tests_require = []
--- a/src/pyams_default_theme.egg-info/PKG-INFO	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme.egg-info/PKG-INFO	Tue Dec 04 15:53:25 2018 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pyams-default-theme
-Version: 0.1.16
+Version: 0.1.18
 Summary: PyAMS default theme
 Home-page: http://hg.ztfy.org/pyams/pyams_default_theme
 Author: Thierry Florac
@@ -11,6 +11,18 @@
         History
         =======
         
+        0.1.18
+        ------
+         - added renderers to simple navigation and site summary portlets
+         - added search results portlet
+         - updated breadcrumbs and tags content providers
+         - updated renderers templates
+         - updated CSS
+        
+        0.1.17
+        ------
+         - added customizable label to contact button
+        
         0.1.16
         ------
          - added results internal OID into view's preview
--- a/src/pyams_default_theme.egg-info/SOURCES.txt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme.egg-info/SOURCES.txt	Tue Dec 04 15:53:25 2018 +0100
@@ -68,6 +68,7 @@
 src/pyams_default_theme/component/paragraph/templates/milestone-default.pt
 src/pyams_default_theme/component/paragraph/templates/pictogram-default.pt
 src/pyams_default_theme/component/paragraph/templates/raw-default.pt
+src/pyams_default_theme/component/paragraph/templates/raw-source-code.pt
 src/pyams_default_theme/component/paragraph/templates/verbatim-default.pt
 src/pyams_default_theme/component/paragraph/templates/verbatim-left.pt
 src/pyams_default_theme/component/paragraph/templates/verbatim-right.pt
@@ -99,10 +100,18 @@
 src/pyams_default_theme/features/menu/portlet/navigation/interfaces.py
 src/pyams_default_theme/features/menu/portlet/navigation/templates/double-select.pt
 src/pyams_default_theme/features/menu/portlet/navigation/templates/double-vertical.pt
+src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-carousel.pt
 src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-horizontal-tabs.pt
 src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-horizontal.pt
+src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-panels.pt
 src/pyams_default_theme/features/renderer/__init__.py
 src/pyams_default_theme/features/search/__init__.py
+src/pyams_default_theme/features/search/portlet/__init__.py
+src/pyams_default_theme/features/search/portlet/interfaces.py
+src/pyams_default_theme/features/search/portlet/templates/search-results.pt
+src/pyams_default_theme/features/share/__init__.py
+src/pyams_default_theme/features/share/portlet/__init__.py
+src/pyams_default_theme/features/share/portlet/templates/toolbox.pt
 src/pyams_default_theme/features/sitemap/__init__.py
 src/pyams_default_theme/features/sitemap/templates/humans.pt
 src/pyams_default_theme/features/sitemap/templates/robots.pt
@@ -118,6 +127,7 @@
 src/pyams_default_theme/resources/css/ext/ekko-lightbox.css
 src/pyams_default_theme/resources/css/ext/ekko-lightbox.min.css
 src/pyams_default_theme/resources/img/dot.png
+src/pyams_default_theme/resources/img/print-button.svg
 src/pyams_default_theme/resources/js/pyams-default.js
 src/pyams_default_theme/resources/js/pyams-default.min.js
 src/pyams_default_theme/resources/js/ext/ekko-lightbox.js
@@ -148,9 +158,11 @@
 src/pyams_default_theme/shared/site/folder.py
 src/pyams_default_theme/shared/site/link.py
 src/pyams_default_theme/shared/site/portlet/__init__.py
+src/pyams_default_theme/shared/site/portlet/templates/site-panels.pt
 src/pyams_default_theme/shared/site/portlet/templates/site-summary.pt
 src/pyams_default_theme/shared/view/__init__.py
 src/pyams_default_theme/shared/view/portlet/__init__.py
+src/pyams_default_theme/shared/view/portlet/interfaces.py
 src/pyams_default_theme/shared/view/portlet/templates/view-items-list.pt
 src/pyams_default_theme/shared/view/templates/render.pt
 src/pyams_default_theme/templates/index.pt
--- a/src/pyams_default_theme/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -15,7 +15,7 @@
 from fanstatic import Resource, Library
 from pyramid.i18n import TranslationStringFactory
 
-from pyams_skin import bootstrap_css, bootstrap, bootstrap_modal_css, myams_js
+from pyams_skin import bootstrap_css, bootstrap, bootstrap_modal_css, myams_js_core
 from pyams_utils.fanstatic import ExternalResource
 
 _ = TranslationStringFactory('pyams_default_theme')
@@ -23,7 +23,8 @@
 
 library = Library('pyams_default_theme', 'resources')
 
-pyams_default_theme_fonts = ExternalResource(library, 'https://fonts.googleapis.com/css?family=Lato:300|Oswald',
+pyams_default_theme_fonts = ExternalResource(library,
+                                             'https://fonts.googleapis.com/css?family=Lato:300|Oswald|Source+Code+Pro',
                                              resource_type='css')
 
 pyams_default_theme_css = Resource(library, 'css/pyams-default.css',
@@ -32,7 +33,7 @@
 
 pyams_default_theme = Resource(library, 'js/pyams-default.js',
                                minified='js/pyams-default.min.js',
-                               depends=(bootstrap, myams_js, pyams_default_theme_css),
+                               depends=(bootstrap, myams_js_core, pyams_default_theme_css),
                                bottom=True)
 
 #
--- a/src/pyams_default_theme/component/association/templates/association-remote-content.pt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/association/templates/association-remote-content.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -1,5 +1,7 @@
 <tal:var i18n:domain="pyams_default_theme"
-		define="settings view.settings">
+		 define="settings view.settings">
+	<h2 tal:define="title i18n:context.title"
+		tal:condition="title">${title}</h2>
 	<tal:loop repeat="link view.links">
 		<tal:var define="target link.target"
 				 condition="target is not None">
--- a/src/pyams_default_theme/component/illustration/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/illustration/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -24,7 +24,7 @@
 from pyams_content.interfaces import IBaseContent
 from pyams_content.root import ISiteRoot
 from pyams_content.shared.common import ISharedContent
-from pyams_content.shared.site.interfaces import IContentLink
+from pyams_default_theme import lightbox
 from pyams_default_theme.component.illustration.interfaces import IIllustrationRenderer, IIllustrationWithZoomSettings, \
     ILLUSTRATION_AFTER_BODY, ILLUSTRATION_BEFORE_BODY
 from pyams_default_theme.features.renderer import BaseContentRenderer
@@ -35,7 +35,7 @@
 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config, get_annotation_adapter
 from pyams_utils.interfaces.tales import ITALESExtension
 
-from pyams_default_theme import _, lightbox
+from pyams_default_theme import _
 
 
 #
@@ -84,14 +84,6 @@
         return request.registry.queryMultiAdapter((version, request), IContentNavigationIllustration)
 
 
-@adapter_config(context=(IContentLink, IPyAMSLayer), provides=IContentNavigationIllustration)
-def content_link_illustration_factory(context, request):
-    """Content link illustration factory"""
-    target = context.target
-    if target is not None:
-        return request.registry.queryMultiAdapter((target, request), IContentNavigationIllustration)
-
-
 @adapter_config(name='pyams_illustration',
                 context=(Interface, Interface, Interface),
                 provides=ITALESExtension)
--- a/src/pyams_default_theme/component/paragraph/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/paragraph/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,19 +12,14 @@
 
 __docformat__ = 'restructuredtext'
 
+from zope.interface import implementer
 
-# import standard library
-
-# import interfaces
 from pyams_content.component.paragraph.interfaces import IBaseParagraph
 from pyams_content.features.preview.interfaces import IPreviewView
 from pyams_default_theme.layer import IPyAMSDefaultLayer
-from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
-
-# import packages
 from pyams_default_theme.page import BasePreviewPage
 from pyams_pagelet.pagelet import pagelet_config
-from zope.interface import implementer
+from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
 
 
 @pagelet_config(name='preview.html', context=IBaseParagraph, layer=IPyAMSDefaultLayer,
@@ -46,6 +41,6 @@
 
     def render(self):
         if self.renderer is not None:
-            return self.renderer.render()
+            return '<div class="edito">{}</div>'.format(self.renderer.render())
         else:
             return ''
--- a/src/pyams_default_theme/component/paragraph/contact.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/paragraph/contact.py	Tue Dec 04 15:53:25 2018 +0100
@@ -21,6 +21,7 @@
 from pyams_content.features.renderer.interfaces import IContentRenderer
 from pyams_default_theme.component.paragraph.interfaces.contact import IContactParagraphDefaultRendererSettings
 from pyams_default_theme.features.renderer import BaseContentRenderer
+from pyams_i18n.interfaces import II18n
 from pyams_skin.layer import IPyAMSLayer
 from pyams_template.template import template_config
 from pyams_utils.adapter import adapter_config, get_annotation_adapter
@@ -87,3 +88,10 @@
     else:
         context_attrs = ('name', 'photo', 'company', 'address', 'phone_number', 'contact_email')
     i18n_context_attrs = ('title', 'charge',)
+
+    @property
+    def button_label(self):
+        label = II18n(self.settings).query_attribute('button_label', request=self.request)
+        if not label:
+            label = self.request.localizer.translate(_("contact-button-label", default="Contact"))
+        return label
--- a/src/pyams_default_theme/component/paragraph/html.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/paragraph/html.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,13 +12,18 @@
 
 __docformat__ = 'restructuredtext'
 
+from fanstatic import ConfigurationError
+
 from pyams_content.component.illustration import IIllustration
 from pyams_content.component.paragraph.interfaces.html import IHTMLParagraph, IRawParagraph
 from pyams_content.features.renderer.interfaces import IContentRenderer
+from pyams_default_theme import library
 from pyams_default_theme.features.renderer import BaseContentRenderer
 from pyams_skin.layer import IPyAMSLayer
 from pyams_template.template import template_config
-from pyams_utils.adapter import adapter_config
+from pyams_utils.adapter import adapter_config, get_annotation_adapter
+from pyams_utils.fanstatic import ExternalResource
+from pyams_utils.pygments import IPygmentsCodeConfiguration, PygmentsCodeRendererSettings, render_source
 
 from pyams_default_theme import _
 
@@ -33,8 +38,51 @@
     """Raw paragraph default renderer"""
 
     label = _("Default raw HTML renderer")
+    weight = 1
 
-    i18n_context_attrs = ('title', 'body',)
+    i18n_context_attrs = ('title', 'body')
+
+
+#
+# Raw paragraph source code renderer
+#
+
+RAW_PARAGRAPH_SOURCE_CODE_RENDERER_SETTINGS_KEY = 'pyams_content.raw.renderer:source-code'
+
+
+@adapter_config(context=IRawParagraph, provides=IPygmentsCodeConfiguration)
+def raw_paragraph_source_code_renderer_settings_factory(context):
+    """Raw paragraph source code renderer settings factory"""
+    return get_annotation_adapter(context, RAW_PARAGRAPH_SOURCE_CODE_RENDERER_SETTINGS_KEY,
+                                  PygmentsCodeRendererSettings)
+
+
+@adapter_config(name='source-code', context=(IRawParagraph, IPyAMSLayer), provides=IContentRenderer)
+@template_config(template='templates/raw-source-code.pt', layer=IPyAMSLayer)
+class RawParagraphSourceCodeRenderer(BaseContentRenderer):
+    """Raw paragraph source code renderer"""
+
+    label = _("Formatted source code renderer")
+    weight = 10
+
+    settings_interface = IPygmentsCodeConfiguration
+
+    i18n_context_attrs = ('title', 'body')
+
+    @property
+    def resources(self):
+        path = 'get-pygments-style.css?style={}'.format(self.settings.style)
+        try:
+            yield ExternalResource(library, path, resource_type='css')
+        except ConfigurationError:
+            yield library.known_resources[path]
+
+    @property
+    def source(self):
+        code = self.body
+        if code:
+            return render_source(code, self.settings)
+        return ''
 
 
 #
--- a/src/pyams_default_theme/component/paragraph/interfaces/contact.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/paragraph/interfaces/contact.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,17 +12,12 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
-# import interfaces
-
-# import packages
-from zope.interface import Interface, Attribute
+from zope.interface import Attribute, Interface
 from zope.schema import Bool, Choice
-from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
 
 from pyams_i18n.schema import I18nTextLineField
+
 from pyams_default_theme import _
 
 
@@ -62,7 +57,7 @@
 
     can_display_map = Attribute("Check if location map can be displayed")
 
-    button_label = I18nTextLineField(title=_("Button label"),
-                                     description=_("Label of the navigation button displayed by "
+    button_label = I18nTextLineField(title=_("Contact button label"),
+                                     description=_("Custom label of the contact button displayed by "
                                                    "front-office template"),
                                      required=False)
--- a/src/pyams_default_theme/component/paragraph/portlet/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/paragraph/portlet/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,24 +12,23 @@
 
 __docformat__ = 'restructuredtext'
 
-
-# import standard library
-
 from zope.interface import Interface
 
-# import interfaces
 from pyams_content.component.paragraph.interfaces import IParagraphContainer
 from pyams_content.component.paragraph.portlet.interfaces import IParagraphContainerPortletSettings, \
     IParagraphNavigationPortletSettings
 from pyams_content.features.renderer.interfaces import ISharedContentRenderer
-from pyams_default_theme import _
+from pyams_content.shared.site.interfaces import ISiteContainer
+from pyams_default_theme.interfaces import IContentSummaryInfo
 from pyams_portal.interfaces import IPortalContext, IPortletRenderer
-# import packages
 from pyams_portal.portlet import PortletRenderer
+from pyams_sequence.interfaces import IInternalReference, ISequentialIdInfo
 from pyams_skin.layer import IPyAMSLayer
 from pyams_template.template import template_config
 from pyams_utils.adapter import adapter_config
 
+from pyams_default_theme import _
+
 
 @adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, IParagraphContainerPortletSettings),
                 provides=IPortletRenderer)
@@ -57,6 +56,36 @@
         self.renderers = list(filter(lambda x: x is not None, renderers))
         [renderer.update() for renderer in self.renderers]
 
+    def get_navigation_links(self):
+
+        def test_item(nav_item):
+            item_sequence = ISequentialIdInfo(nav_item, None)
+            if (item_sequence is not None) and (item_sequence.oid == context_sequence.oid):
+                return True
+            if IInternalReference.providedBy(nav_item) and (nav_item.reference == context_sequence.hex_oid):
+                return True
+
+        prev_nav, next_nav = None, None
+        context_sequence = ISequentialIdInfo(self.context, None)
+        if context_sequence is not None:
+            display_context = self.request.display_context
+            if ISiteContainer.providedBy(display_context):
+                registry = self.request.registry
+                previous_item = None
+                items = display_context.get_visible_items(self.request)
+                for item in items:
+                    if test_item(item):
+                        prev_nav = registry.queryMultiAdapter((previous_item, self.request), IContentSummaryInfo)
+                        break
+                    previous_item = item
+                try:
+                    next_item = next(items)
+                except StopIteration:
+                    pass
+                else:
+                    next_nav = registry.queryMultiAdapter((next_item, self.request), IContentSummaryInfo)
+        return prev_nav, next_nav
+
 
 @adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, IParagraphNavigationPortletSettings),
                 provides=IPortletRenderer)
--- a/src/pyams_default_theme/component/paragraph/portlet/templates/content.pt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/paragraph/portlet/templates/content.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -6,4 +6,28 @@
 			${structure:renderer.render()}
 		</tal:if>
 	</tal:loop>
+	<tal:if define="settings view.settings"
+			condition="settings.display_navigation_links">
+		<tal:var define="(previous, next) view.get_navigation_links()"
+				 condition="(previous is not None) or (next is not None)">
+			<nav aria-label="Previous and next topics" i18n:attributes="aria-label">
+				<ul class="pager">
+					<li class="previous"
+						tal:condition="previous is not None">
+						<a href="${tales:relative_url(previous.context)}">
+							<span aria-hidden="true">&larr;</span>
+							${i18n:previous.title}
+						</a>
+					</li>
+					<li class="next"
+						tal:condition="next is not None">
+						<a href="${tales:relative_url(next.context)}">
+							${i18n:next.title}
+							<span aria-hidden="true">&rarr;</span>
+						</a>
+					</li>
+				</ul>
+			</nav>
+		</tal:var>
+	</tal:if>
 </div>
--- a/src/pyams_default_theme/component/paragraph/templates/contact-default.pt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/component/paragraph/templates/contact-default.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -23,8 +23,9 @@
 		</div>
 		<tal:if condition="view.contact_email">
 			<span i18n:translate="">Contact email:</span>
-			<a href="mailto:${view.contact_email}">
-				${view.contact_email}
+			<a tal:define="button_label view.button_label"
+			   href="mailto:${view.contact_email}?subject=${view.title}">
+				${button_label}
 			</a><br />
 		</tal:if>
 		<tal:if condition="view.phone_number">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/component/paragraph/templates/raw-source-code.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,9 @@
+<h3>${view.title}</h3>
+<tal:var define="settings view.settings">
+	<div class="source"
+		 tal:omit-tag="not settings.disable_wrap">
+		<pre tal:omit-tag="not settings.disable_wrap">
+			${structure:view.source}
+		</pre>
+	</div>
+</tal:var>
--- a/src/pyams_default_theme/features/header/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/features/header/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -16,6 +16,7 @@
 from zope.interface import implementer
 from zope.location import Location
 from zope.location.interfaces import ISublocations
+from zope.schema.fieldproperty import FieldProperty
 
 from pyams_content.component.association.interfaces import ASSOCIATION_CONTAINER_KEY
 from pyams_content.features.header.interfaces import IHeaderSettings, IHeaderTarget
@@ -62,8 +63,14 @@
 class SimpleHeaderRendererSettings(Persistent, Location):
     """Simple header renderer settings"""
 
+    apply_on_root = FieldProperty(ISimpleHeaderRendererSettings['apply_on_root'])
     banner = FileProperty(ISimpleHeaderRendererSettings['banner'])
     logo = FileProperty(ISimpleHeaderRendererSettings['logo'])
+    search_target = FieldProperty(ISimpleHeaderRendererSettings['search_target'])
+
+    @property
+    def can_apply_on_root(self):
+        return self.apply_on_root
 
     @property
     def menus(self):
--- a/src/pyams_default_theme/features/header/interfaces.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/features/header/interfaces.py	Tue Dec 04 15:53:25 2018 +0100
@@ -13,9 +13,11 @@
 __docformat__ = 'restructuredtext'
 
 from zope.interface import Interface, Attribute
+from zope.schema import Bool
 
 from pyams_content.features.header.interfaces import IHeaderRendererSettings
 from pyams_file.schema import ImageField
+from pyams_sequence.schema import InternalReferenceField
 
 from pyams_default_theme import _
 
@@ -23,6 +25,12 @@
 class ISimpleHeaderRendererSettings(IHeaderRendererSettings):
     """Simple header renderer settings"""
 
+    apply_on_root = Bool(title=_("Apply on root?"),
+                         description=_("If 'no', header settings will not be applied on site root but only "
+                                       "on inner sites"),
+                         required=True,
+                         default=True)
+
     banner = ImageField(title=_("Banner image"),
                         description=_("Image displayed as header background"),
                         required=False)
@@ -31,6 +39,10 @@
                       description=_("Logo displayed in header"),
                       required=False)
 
+    search_target = InternalReferenceField(title=_("Search form target"),
+                                           description=_("Site or folder handling site search"),
+                                           required=False)
+
     tabs = Attribute("Top tabs list")
 
     menus = Attribute("Top tabs menus list")
--- a/src/pyams_default_theme/features/header/skin/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/features/header/skin/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -13,7 +13,6 @@
 __docformat__ = 'restructuredtext'
 
 import logging
-logger = logging.getLogger('PyAMS (content)')
 
 from pyramid.decorator import reify
 from pyramid.location import lineage
@@ -21,16 +20,18 @@
 
 from pyams_cache.beaker import get_cache
 from pyams_content.component.association.interfaces import IAssociationInfo
-from pyams_content.component.links.interfaces import IInternalLink
 from pyams_content.features.header.interfaces import IHeaderRenderer, IHeaderRendererSettings, IHeaderSettings, \
     IHeaderTarget
 from pyams_content.features.renderer.interfaces import HIDDEN_RENDERER_NAME
+from pyams_content.root import ISiteRoot
 from pyams_default_theme.features.header import SimpleHeaderRendererSettings
 from pyams_default_theme.features.header.interfaces import ISimpleHeaderRendererSettings
 from pyams_default_theme.features.header.skin.interfaces import IHeaderClass
 from pyams_default_theme.features.renderer import BaseContentRenderer
 from pyams_portal.interfaces import PREVIEW_MODE
 from pyams_portal.portlet import PORTLETS_CACHE_KEY, PORTLETS_CACHE_NAME, PORTLETS_CACHE_REGION
+from pyams_sequence.interfaces import IInternalReference
+from pyams_sequence.reference import get_reference_target
 from pyams_skin.layer import IPyAMSLayer
 from pyams_template.template import template_config
 from pyams_utils.adapter import adapter_config
@@ -39,6 +40,8 @@
 
 from pyams_default_theme import _
 
+logger = logging.getLogger('PyAMS (content)')
+
 
 #
 # Base header renderer
@@ -80,7 +83,13 @@
         request = self.request
         return request.registry.queryMultiAdapter((request.context, request), IHeaderClass, default='')
 
+    @property
+    def search_target(self):
+        return get_reference_target(self.settings.search_target, request=self.request)
+
     def render(self):
+        if ISiteRoot.providedBy(self.request.context) and not self.settings.can_apply_on_root:
+            return ''
         preview_mode = self.request.annotations.get(PREVIEW_MODE, False)
         if preview_mode:
             return super(BaseHeaderRenderer, self).render()
@@ -146,7 +155,7 @@
         return IAssociationInfo(link)
 
     def is_active(self, link):
-        if IInternalLink.providedBy(link):
+        if IInternalReference.providedBy(link):
             target = link.get_target()
             if target is not None:
                 return target in self.request.annotations['REQUEST_PATH']
--- a/src/pyams_default_theme/features/header/skin/templates/simple-header.pt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/features/header/skin/templates/simple-header.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -19,16 +19,45 @@
 			</div>
 			<div class="collapse navbar-collapse" id="navbar-collapser">
 				<ul class="nav navbar-nav" role="tablist">
-					<tal:loop repeat="link settings.tabs.get_visible_items(request)">
-						<li role="presentation"
-							tal:attributes="class 'active' if view.is_active(link) else ''">
-							<a tal:define="info view.get_link_info(link);
-										   href link.get_url(request);"
+					<tal:loop repeat="menu settings.menus.get_visible_items(request)">
+						<li tal:condition="menu.reference and not menu.dynamic_menu"
+							tal:attributes="class 'active' if view.is_active(menu) else ''">
+							<a tal:define="info view.get_link_info(menu);
+										   href menu.get_url(request);"
 							   tal:condition="href"
 							   href="${href}">${info.user_title}</a>
 						</li>
+						<li class="dropdown"
+							tal:condition="(not menu.reference) or menu.dynamic_menu">
+							<a href="#" class="dropdown-toggle"
+							   data-toggle="dropdown" role="button"
+							   aria-haspopup="true" aria-expanded="false">
+								${i18n:menu.title}
+								<span class="caret"></span>
+							</a>
+							<ul class="dropdown-menu">
+								<tal:loop repeat="link menu.get_visible_items(request)">
+									<li>
+										<a tal:define="info view.get_link_info(link);
+													   href link.get_url(request);"
+										   tal:condition="href"
+										   href="${href}">${info.user_title}</a>
+									</li>
+								</tal:loop>
+							</ul>
+						</li>
 					</tal:loop>
 				</ul>
+				<form class="navbar-form navbar-right"
+					  tal:define="target view.search_target"
+					  tal:condition="target is not None"
+					  action="${tales:absolute_url(target)}">
+					<div class="form-group">
+						<input type="text" class="form-control" name="user_search"
+							   placeholder="Search..." i18n:attributes="placeholder">
+					</div>
+					<button type="submit" class="btn btn-default" i18n:translate="">Search</button>
+				</form>
 			</div>
 		</div>
 	</nav>
--- a/src/pyams_default_theme/features/menu/portlet/navigation/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/features/menu/portlet/navigation/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,30 +12,34 @@
 
 __docformat__ = 'restructuredtext'
 
+from persistent import Persistent
+from zope.interface import implementer, Interface
+from zope.location.location import Location
+from zope.schema.fieldproperty import FieldProperty
 
-# import standard library
-
-# import interfaces
+from pyams_content.component.association.interfaces import IAssociationInfo
 from pyams_content.features.menu.portlet.navigation.interfaces.double import IDoubleNavigationPortletSettings
 from pyams_content.features.menu.portlet.navigation.interfaces.simple import ISimpleNavigationPortletSettings
 from pyams_default_theme.features.menu.portlet.navigation.interfaces import \
     IDoubleNavigationPortletSelectMenusRendererSettings
-from pyams_portal.interfaces import IPortalContext, IPortletRenderer, PORTLET_RENDERER_SETTINGS_KEY
+from pyams_portal.interfaces import IPortalContext, IPortletRenderer
+from pyams_portal.portlet import PortletRenderer
 from pyams_skin.layer import IPyAMSLayer
-
-# import packages
-from persistent import Persistent
-from pyams_portal.portlet import PortletRenderer
 from pyams_template.template import template_config
 from pyams_utils.adapter import adapter_config
 from pyams_utils.factory import factory_config
-from zope.interface import implementer, Interface
-from zope.location.location import Location
-from zope.schema.fieldproperty import FieldProperty
 
 from pyams_default_theme import _
 
 
+class BaseNavigationRenderer(PortletRenderer):
+    """Base navigation portlet renderer"""
+
+    @staticmethod
+    def get_link_info(link):
+        return IAssociationInfo(link)
+
+
 #
 # Simple navigation portlet renderers
 #
@@ -43,20 +47,44 @@
 @adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, ISimpleNavigationPortletSettings),
                 provides=IPortletRenderer)
 @template_config(template='templates/simple-horizontal.pt', layer=IPyAMSLayer)
-class SimpleNavigationPortletHorizontalRenderer(PortletRenderer):
+class SimpleNavigationPortletHorizontalRenderer(BaseNavigationRenderer):
     """Simple navigation horizontal portlet renderer"""
 
     label = _("Horizontal list with vertical illustrations")
+    weight = 1
 
 
 @adapter_config(name='horizontal-tabs',
                 context=(IPortalContext, IPyAMSLayer, Interface, ISimpleNavigationPortletSettings),
                 provides=IPortletRenderer)
 @template_config(template='templates/simple-horizontal-tabs.pt', layer=IPyAMSLayer)
-class SimpleNavigationPortletHorizontalTabsRenderer(PortletRenderer):
+class SimpleNavigationPortletHorizontalTabsRenderer(BaseNavigationRenderer):
     """Simple navigation horizontal portlet renderer with tabs"""
 
     label = _("Horizontal list with tabs and horizontal illustrations")
+    weight = 2
+
+
+@adapter_config(name='carousel',
+                context=(IPortalContext, IPyAMSLayer, Interface, ISimpleNavigationPortletSettings),
+                provides=IPortletRenderer)
+@template_config(template='templates/simple-carousel.pt', layer=IPyAMSLayer)
+class SimpleNavigationPortletCarouselRenderer(BaseNavigationRenderer):
+    """Simple navigation portlet carousel renderer"""
+
+    label = _("Horizontal carousel with full width illustrations")
+    weight = 3
+
+
+@adapter_config(name='vertical-panels',
+                context=(IPortalContext, IPyAMSLayer, Interface, ISimpleNavigationPortletSettings),
+                provides=IPortletRenderer)
+@template_config(template='templates/simple-panels.pt', layer=IPyAMSLayer)
+class SimpleNavigationPortletVerticalPanelsRenderer(BaseNavigationRenderer):
+    """Simple navigation portlet vertical panels renderer"""
+
+    label = _("Vertical panels with panoramic illustrations")
+    weight = 4
 
 
 #
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-carousel.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,40 @@
+<section class="wrapper" i18n:domain="pyams_default_theme"
+	 tal:define="settings view.settings;
+				 cache_key tales:cache_key(settings);">
+	<div id="carousel-${cache_key}"
+		 class="carousel slide"
+	 	 data-ride="carousel">
+		<ol class="carousel-indicators">
+			<li tal:repeat="link settings.links.get_visible_items()"
+				class="${'active' if repeat.link.start() else None}"
+				data-target="#carousel-${cache_key}"
+				data-slide-to="${repeat.link.index}"></li>
+		</ol>
+		<div class="carousel-inner">
+			<div tal:repeat="link settings.links.get_visible_items()"
+				 class="item ${'active' if repeat.link.start() else None}">
+				<tal:var define="illustration tales:pyams_illustration(link);
+								 img_data i18n:illustration.data;
+								 alt i18n:illustration.alt_title;
+								 link_info view.get_link_info(link);">
+					${structure:tales:picture(img_data, lg_thumb='pano', md_thumb='pano',
+											  sm_thumb='pano', xs_thumb='pano', alt=alt)}
+					<a class="carousel-caption"
+					   href="${link.get_url(request)}">
+						<h3>${link_info.user_title}</h3>
+					</a>
+				</tal:var>
+			</div>
+		</div>
+		<a class="left carousel-control" role="button"
+		   data-target="#carousel-${cache_key}" data-slide="prev">
+			<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
+			<span class="sr-only" i18n:translate="">Previous</span>
+		</a>
+		<a class="right carousel-control" role="button"
+		   data-target="#carousel-${cache_key}" data-slide="next">
+			<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
+			<span class="sr-only" i18n:translate="">Next</span>
+		</a>
+	</div>
+</section>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-panels.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,24 @@
+<div class="panels" i18n:domain="pyams_default_theme"
+	 tal:define="settings view.settings">
+	<h2>${i18n:settings.title}</h2>
+	<div tal:repeat="link settings.links.get_visible_items()"
+		 class="col-sm-4">
+		<tal:var define="illustration tales:pyams_illustration(link);
+						 img_data i18n:illustration.data;
+						 alt i18n:illustration.alt_title;
+						 link_info view.get_link_info(link);">
+			<a href="${link.get_url(request)}">
+				${structure:tales:picture(img_data, lg_thumb='pano', lg_width=4, md_thumb='pano', md_width=4,
+										  sm_thumb='pano', sm_width=4, xs_thumb='pano', xs_width=4, alt=alt)}
+			</a>
+			<a class="caption"
+			   href="${link.get_url(request)}">
+				<h3>${link_info.user_title}</h3>
+			</a>
+			<tal:var define="description i18n:link.description">
+				${structure:tales:html(description)}
+			</tal:var>
+		</tal:var>
+	</div>
+	<div class="clearfix"></div>
+</div>
\ No newline at end of file
--- a/src/pyams_default_theme/features/search/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/features/search/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -13,10 +13,12 @@
 __docformat__ = 'restructuredtext'
 
 from pyams_content.features.search.interfaces import ISearchFolder
+from pyams_content.shared.site import ISiteElementNavigation
 from pyams_default_theme.interfaces import IContentSummaryInfo
-from pyams_content.shared.site import ISiteElementNavigation
 from pyams_i18n.interfaces import II18n
+from pyams_skin.interfaces.viewlet import IBreadcrumbItem
 from pyams_skin.layer import IPyAMSUserLayer
+from pyams_skin.viewlet.breadcrumb import BreadcrumbItem
 from pyams_utils.adapter import ContextRequestAdapter, adapter_config
 from pyams_utils.interfaces.url import IRelativeURL
 from pyams_utils.url import absolute_url
@@ -44,6 +46,17 @@
         return IWorkflowPublicationInfo(self.context).is_visible(self.request)
 
 
+@adapter_config(context=(ISearchFolder, IPyAMSUserLayer), provides=IBreadcrumbItem)
+class SearchFolderBreadcumbAdapter(BreadcrumbItem):
+    """Search folder breadcrumb adapter"""
+
+    @property
+    def label(self):
+        return II18n(self.context).query_attribute('short_name', request=self.request)
+
+    url = None
+
+
 @adapter_config(context=(ISearchFolder, IPyAMSUserLayer), provides=IContentSummaryInfo)
 class SearchFolderSummaryAdapter(ContextRequestAdapter):
     """Search folder summary adapter"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/features/search/portlet/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2008-2018 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+from persistent import Persistent
+from zope.container.contained import Contained
+from zope.interface import Interface, implementer
+from zope.location import ILocation
+from zope.schema.fieldproperty import FieldProperty
+
+from pyams_content.features.search.portlet import ISearchResultsPortletSettings
+from pyams_default_theme.features.search.portlet.interfaces import ISearchResultsPortletDefaultRendererSettings
+from pyams_default_theme.interfaces import ISearchResultsView
+from pyams_portal.interfaces import IPortalContext, IPortletRenderer
+from pyams_portal.portlet import PortletRenderer
+from pyams_skin.interfaces.viewlet import IBreadcrumbs
+from pyams_skin.layer import IPyAMSLayer, IPyAMSUserLayer
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config, NullAdapter
+from pyams_utils.factory import factory_config
+
+from pyams_default_theme import _
+
+
+@implementer(ISearchResultsPortletDefaultRendererSettings)
+@factory_config(provided=ISearchResultsPortletDefaultRendererSettings)
+class SearchResultsPortletDefaultRendererSettings(Persistent, Contained):
+    """Search results portlet default renderer settings"""
+
+    display_results_count = FieldProperty(ISearchResultsPortletDefaultRendererSettings['display_results_count'])
+    allow_sorting = FieldProperty(ISearchResultsPortletDefaultRendererSettings['allow_sorting'])
+    allow_pagination = FieldProperty(ISearchResultsPortletDefaultRendererSettings['allow_pagination'])
+
+
+@adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, ISearchResultsPortletSettings),
+                provides=IPortletRenderer)
+@template_config(template='templates/search-results.pt', layer=IPyAMSLayer)
+@implementer(ISearchResultsView)
+class SearchResultsPortletDefaultRenderer(PortletRenderer):
+    """Search results portlet default renderer"""
+
+    label = _("Default search results")
+
+    settings_interface = ISearchResultsPortletDefaultRendererSettings
+
+    def update(self):
+        settings = self.renderer_settings
+        if not settings.allow_pagination:
+            self.request.GET['length'] = '999'
+        super(SearchResultsPortletDefaultRenderer, self).update()
+
+
+@adapter_config(context=(ILocation, IPyAMSUserLayer, ISearchResultsView), provides=IBreadcrumbs)
+class BreadcrumbsAdapter(NullAdapter):
+    """Disable breadcrumbs in search results view"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/features/search/portlet/interfaces.py	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2008-2018 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+from zope.interface import Interface
+from zope.schema import Bool
+
+from pyams_default_theme import _
+
+
+class ISearchResultsPortletDefaultRendererSettings(Interface):
+    """Search results portlet default renderer settings interface"""
+
+    display_results_count = Bool(title=_("Display results count?"),
+                                 description=_("If 'no', results count will not be displayed"),
+                                 required=True,
+                                 default=True)
+
+    allow_sorting = Bool(title=_("Allow results sorting?"),
+                         description=_("If 'no', results will not be sortable"),
+                         required=True,
+                         default=True)
+
+    allow_pagination = Bool(title=_("Allow pagination?"),
+                            description=_("If 'no', results will not be paginated"),
+                            required=True,
+                            default=True)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/features/search/portlet/templates/search-results.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,49 @@
+<div tal:define="settings view.settings;
+				 renderer_settings view.renderer_settings;"
+	 i18n:domain="pyams_default_theme">
+	<h2>${i18n:settings.title}</h2>
+	<div class="search-results"
+		 tal:define="(items, count) settings.get_items(request)">
+		<header>
+			<tal:if condition="renderer_settings.display_results_count">
+				<div>
+					<tal:if condition="count" i18n:translate="">
+						<i18n:var name="count">${count}</i18n:var> result(s) found
+					</tal:if>
+					<tal:if condition="not:count" i18n:translate="">
+						No result found!
+					</tal:if>
+				</div>
+			</tal:if>
+			<hr />
+		</header>
+		<tal:loop repeat="item items">
+			<tal:var define="target tales:relative_url(item)">
+				<div class="thumbnail pull-left col-lg-3 col-md-3 col-sm-4 hidden-xs"
+					 tal:define="illustration tales:pyams_illustration(item)"
+					 tal:condition="illustration">
+					<a href="${target}">
+						<tal:if define="image i18n:illustration.data;
+										alt i18n:illustration.alt_title;"
+								condition="image">
+							${structure:tales:picture(image, lg_thumb='pano', lg_width=3, md_thumb='pano', md_width=3, sm_thumb='pano',
+													  sm_width=4, xs_thumb='pano', xs_width=12, alt=alt, css_class='result_media')}
+						</tal:if>
+					</a>
+				</div>
+				<div>
+					<a href="${target}">
+						<h3>${i18n:item.title}</h3>
+					</a>
+					<div class="breadcrumbs">${structure:tales:breadcrumbs(item)}</div>
+					<div class="tags">${structure:tales:tags(item)}</div>
+					<div class="header"
+						 tal:define="header i18n:item.header">
+						${structure:tales:html(header)}
+					</div>
+				</div>
+			</tal:var>
+			<div class="clearfix"></div>
+		</tal:loop>
+	</div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/features/share/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2008-2018 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/features/share/portlet/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2008-2018 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+from zope.interface import Interface
+
+from pyams_content.features.share.interfaces import ISocialShareManager
+from pyams_content.features.share.portlet import IToolboxPortletSettings
+from pyams_portal.interfaces import IPortalContext, IPortletRenderer
+from pyams_portal.portlet import PortletRenderer
+from pyams_skin import awesomefonts_css
+from pyams_skin.layer import IPyAMSLayer
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config
+
+from pyams_default_theme import _
+
+
+@adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, IToolboxPortletSettings),
+                provides=IPortletRenderer)
+@template_config(template='templates/toolbox.pt', layer=IPyAMSLayer)
+class ToolboxPortletDefaultRenderer(PortletRenderer):
+    """Toolbox portlet renderer"""
+
+    label = _("Default toolbox")
+
+    resources = (awesomefonts_css,)
+
+    @property
+    def social_items(self):
+        manager = ISocialShareManager(self.request.root, None)
+        if manager is not None:
+            yield from manager.get_active_items()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/features/share/portlet/templates/toolbox.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,28 @@
+<div class="toolbox btn-group btn-group-vertical" i18n:domain="pyams_default_theme"
+	 tal:define="settings view.settings">
+
+	<button tal:condition="settings.allow_printing"
+			type="button" class="btn btn-default hidden-xs hidden-sm"
+			onclick="javascript:window.print();"
+			title="Print page" i18n:attributes="title">
+		<i class="fa fa-fw fa-print"></i>
+		<span i18n:translate="">Print page</span>
+	</button>
+
+	<tal:if condition="settings.allow_sharing">
+		<tal:loop repeat="item view.social_items">
+			<tal:var define="url item.get_url(context, request)">
+				<button type="button" class="btn btn-default hidden-xs hidden-sm"
+						title="${i18n:item.label}"
+						onclick="javascript:window.location.href='${url}';">
+					<i class="fa fa-fw"
+					   tal:define="pictogram i18n:item.pictogram.image">
+						${structure:tales:thumbnail(pictogram, '2rem', '2rem')}
+					</i>
+					<span>${i18n:item.label}</span>
+				</button>
+			</tal:var>
+		</tal:loop>
+	</tal:if>
+
+</div>
\ No newline at end of file
--- a/src/pyams_default_theme/interfaces/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/interfaces/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -49,3 +49,7 @@
     header = Attribute("Header")
 
     button_title = Attribute("Button's target")
+
+
+class ISearchResultsView(Interface):
+    """Search results view marker interface"""
Binary file src/pyams_default_theme/locales/fr/LC_MESSAGES/pyams_default_theme.mo has changed
--- a/src/pyams_default_theme/locales/fr/LC_MESSAGES/pyams_default_theme.po	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/locales/fr/LC_MESSAGES/pyams_default_theme.po	Tue Dec 04 15:53:25 2018 +0100
@@ -5,7 +5,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2018-11-16 10:59+0100\n"
+"POT-Creation-Date: 2018-11-30 11:12+0100\n"
 "PO-Revision-Date: 2017-06-07 12:41+0200\n"
 "Last-Translator: Thierry Florac <tflorac@ulthar.net>\n"
 "Language-Team: French\n"
@@ -24,15 +24,19 @@
 msgid "Default grid gallery renderer"
 msgstr "Par défaut"
 
-#: src/pyams_default_theme/component/gallery/__init__.py:43
+#: src/pyams_default_theme/component/gallery/__init__.py:46
 msgid "Carousel gallery renderer"
 msgstr "Carousel horizontal"
 
-#: src/pyams_default_theme/component/gallery/templates/renderer-carousel.pt:31
+#: src/pyams_default_theme/component/gallery/templates/renderer-carousel.pt:32
+#: src/pyams_default_theme/shared/view/portlet/templates/view-items-list.pt:47
+#: src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-carousel.pt:32
 msgid "Previous"
 msgstr "Précédent"
 
-#: src/pyams_default_theme/component/gallery/templates/renderer-carousel.pt:35
+#: src/pyams_default_theme/component/gallery/templates/renderer-carousel.pt:36
+#: src/pyams_default_theme/shared/view/portlet/templates/view-items-list.pt:53
+#: src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-carousel.pt:37
 msgid "Next"
 msgstr "Suivant"
 
@@ -48,19 +52,19 @@
 msgid "Vertical list"
 msgstr "Liste verticale"
 
-#: src/pyams_default_theme/component/illustration/__init__.py:170
+#: src/pyams_default_theme/component/illustration/__init__.py:162
 msgid "Centered illustration before text"
 msgstr "Illustration centrée avant le texte"
 
-#: src/pyams_default_theme/component/illustration/__init__.py:181
+#: src/pyams_default_theme/component/illustration/__init__.py:173
 msgid "Small illustration on the left"
 msgstr "Illustration sur la gauche"
 
-#: src/pyams_default_theme/component/illustration/__init__.py:193
+#: src/pyams_default_theme/component/illustration/__init__.py:187
 msgid "Small illustration on the right"
 msgstr "Illustration sur la droite"
 
-#: src/pyams_default_theme/component/illustration/__init__.py:205
+#: src/pyams_default_theme/component/illustration/__init__.py:201
 msgid "Centered illustration after text"
 msgstr "Illustration centrée après le texte"
 
@@ -117,30 +121,43 @@
 msgid "Default verbatim renderer"
 msgstr "Encadré en pleine largeur (par défaut)"
 
-#: src/pyams_default_theme/component/paragraph/html.py:35
+#: src/pyams_default_theme/component/paragraph/html.py:40
 msgid "Default raw HTML renderer"
-msgstr "Par défaut"
+msgstr "Code HTML brut (par défaut)"
 
-#: src/pyams_default_theme/component/paragraph/html.py:49
+#: src/pyams_default_theme/component/paragraph/html.py:65
+msgid "Formatted source code renderer"
+msgstr "Code source formatté"
+
+#: src/pyams_default_theme/component/paragraph/html.py:97
 msgid "Default rich text renderer"
 msgstr "Par défaut"
 
-#: src/pyams_default_theme/component/paragraph/contact.py:80
+#: src/pyams_default_theme/component/paragraph/contact.py:82
 msgid "Default contact renderer"
 msgstr "Encadré en pleine largeur (par défaut)"
 
+#. Default: Contact
+#: src/pyams_default_theme/component/paragraph/contact.py:96
+msgid "contact-button-label"
+msgstr "Contacter"
+
 #: src/pyams_default_theme/component/paragraph/zmi/map.py:62
 msgid "Don't use default map configuration"
 msgstr "Ne pas utiliser la configuration de carte par défaut"
 
-#: src/pyams_default_theme/component/paragraph/portlet/__init__.py:40
+#: src/pyams_default_theme/component/paragraph/portlet/__init__.py:39
 msgid "Default paragraphs renderer"
 msgstr "Par défaut"
 
-#: src/pyams_default_theme/component/paragraph/portlet/__init__.py:67
+#: src/pyams_default_theme/component/paragraph/portlet/__init__.py:96
 msgid "Default paragraphs navigation"
 msgstr "Par défaut"
 
+#: src/pyams_default_theme/component/paragraph/portlet/templates/content.pt:13
+msgid "Previous and next topics"
+msgstr "Contenus précédent et suivant"
+
 #: src/pyams_default_theme/component/paragraph/interfaces/map.py:34
 msgid "Don't use default configuration?"
 msgstr "Ne pas utiliser la configuration par défaut ?"
@@ -151,13 +168,13 @@
 
 #: src/pyams_default_theme/component/paragraph/interfaces/frame.py:25
 #: src/pyams_default_theme/component/paragraph/interfaces/verbatim.py:22
-#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:29
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:25
 msgid "Left"
 msgstr "Gauche"
 
 #: src/pyams_default_theme/component/paragraph/interfaces/frame.py:26
 #: src/pyams_default_theme/component/paragraph/interfaces/verbatim.py:23
-#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:30
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:26
 msgid "Right"
 msgstr "Droite"
 
@@ -207,34 +224,44 @@
 "Cette largeur est indiquée en nombre de colonnes, la largeur totale étant de "
 "12 colonnes."
 
-#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:40
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:36
 msgid "Show photo?"
 msgstr "Afficher la photo ?"
 
-#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:41
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:37
 msgid "Display contact photo"
 msgstr ""
 "Si 'non', la photo du contact ne sera pas affichée même si elle est "
 "disponible"
 
-#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:45
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:41
 msgid "Photo position"
 msgstr "Position de la photo"
 
-#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:52
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:48
 msgid "Show location map?"
 msgstr "Afficher la carte ?"
 
-#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:53
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:49
 msgid "If 'no', location map will not be displayed"
 msgstr ""
 "Si 'non', la carte de situation ne sera pas affichée même si des coordonnées "
 "GPS ont été indiquées"
 
-#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:57
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:53
 msgid "Map position"
 msgstr "Position de la carte"
 
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:60
+msgid "Contact button label"
+msgstr "Libellé du bouton de contact"
+
+#: src/pyams_default_theme/component/paragraph/interfaces/contact.py:61
+msgid "Custom label of the contact button displayed by front-office template"
+msgstr ""
+"Vous pouvez remplacer le libellé par défaut du bouton de contact qui sera "
+"affiché en front-office en l'indiquant ici"
+
 #: src/pyams_default_theme/component/association/__init__.py:44
 msgid "Default associations renderer"
 msgstr "Par défaut"
@@ -282,7 +309,8 @@
 "sélectionnés"
 
 #: src/pyams_default_theme/shared/common/summary.py:38
-#: src/pyams_default_theme/shared/site/link.py:64
+#: src/pyams_default_theme/shared/site/link.py:70
+#: src/pyams_default_theme/shared/site/link.py:108
 msgid "Consult content"
 msgstr "Accéder au contenu"
 
@@ -290,7 +318,7 @@
 msgid "Default title renderer"
 msgstr "Par défaut"
 
-#: src/pyams_default_theme/shared/common/portlet/head.py:38
+#: src/pyams_default_theme/shared/common/portlet/head.py:33
 msgid "Default header renderer"
 msgstr "Par défaut"
 
@@ -304,10 +332,35 @@
 "ATTENTION : la sélection des éléments affichés dans cet aperçu ne tient pas "
 "compte du contexte éventuellement paramétré dans la vue"
 
-#: src/pyams_default_theme/shared/view/portlet/__init__.py:38
+#: src/pyams_default_theme/shared/view/portlet/__init__.py:48
 msgid "Simple vertical view"
 msgstr "Liste verticale simple"
 
+#: src/pyams_default_theme/shared/view/portlet/interfaces.py:24
+msgid "Display illustrations?"
+msgstr "Afficher les illustrations ?"
+
+#: src/pyams_default_theme/shared/view/portlet/interfaces.py:25
+msgid "If 'no', view contents will not display illustrations"
+msgstr "Si 'non', l'illustration associée aux contenus ne sera pas affichée"
+
+#: src/pyams_default_theme/shared/view/portlet/interfaces.py:29
+msgid "Paginate?"
+msgstr "Pagination ?"
+
+#: src/pyams_default_theme/shared/view/portlet/interfaces.py:30
+msgid "If 'no', results pagination will be disabled"
+msgstr ""
+"Si 'non', les résultats de la recherche ne seront pas oraganisés par pages"
+
+#: src/pyams_default_theme/shared/view/portlet/interfaces.py:34
+msgid "Page size"
+msgstr "Taille des pages"
+
+#: src/pyams_default_theme/shared/view/portlet/interfaces.py:35
+msgid "Number of items per page, if pagination is enabled"
+msgstr "Nombre de résultats par page, si la pagination est activée"
+
 #: src/pyams_default_theme/shared/imagemap/__init__.py:52
 msgid "Default imagemap renderer"
 msgstr "Par défaut"
@@ -317,14 +370,19 @@
 msgstr "Aperçu des zones cliquables"
 
 #: src/pyams_default_theme/shared/site/folder.py:60
-#: src/pyams_default_theme/features/search/__init__.py:64
+#: src/pyams_default_theme/features/search/__init__.py:77
 msgid "Consult folder"
 msgstr "Consulter la rubrique"
 
-#: src/pyams_default_theme/shared/site/portlet/__init__.py:35
+#: src/pyams_default_theme/shared/site/portlet/__init__.py:48
 msgid "Site container summary"
 msgstr "Par défaut"
 
+#: src/pyams_default_theme/shared/site/portlet/__init__.py:58
+#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:86
+msgid "Vertical panels with panoramic illustrations"
+msgstr "Panneaux verticaux avec illustrations panoramiques"
+
 #: src/pyams_default_theme/shared/logo/__init__.py:34
 msgid "Default logos renderer"
 msgstr "Par défaut"
@@ -337,19 +395,32 @@
 msgid "Hidden content"
 msgstr "NON affiché"
 
-#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:49
+#: src/pyams_default_theme/features/share/portlet/__init__.py:35
+msgid "Default toolbox"
+msgstr "Par défaut"
+
+#: src/pyams_default_theme/features/share/portlet/templates/toolbox.pt:7
+#: src/pyams_default_theme/features/share/portlet/templates/toolbox.pt:9
+msgid "Print page"
+msgstr "Imprimer la page"
+
+#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:53
 msgid "Horizontal list with vertical illustrations"
 msgstr "Liste horizontale avec illustrations verticales (par défaut)"
 
-#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:59
+#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:64
 msgid "Horizontal list with tabs and horizontal illustrations"
 msgstr "Liste horizontale avec onglets et illustrations panoramiques"
 
-#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:72
+#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:75
+msgid "Horizontal carousel with full width illustrations"
+msgstr "Carousel horizontal avec illustrations en pleine largeur"
+
+#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:100
 msgid "Vertical list with small horizontal menus illustrations"
 msgstr "Liste verticale avec illustrations horizontales"
 
-#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:95
+#: src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:123
 msgid "Double-level selection navigation"
 msgstr "Navigation par sélection à deux niveaux"
 
@@ -389,31 +460,87 @@
 msgid "PyAMS simple footer with links"
 msgstr "PyAMS: pied de page simple avec liens"
 
-#: src/pyams_default_theme/features/header/interfaces.py:31
+#: src/pyams_default_theme/features/search/portlet/__init__.py:52
+msgid "Default search results"
+msgstr "Affichage des résultats, sans facette (par défaut)"
+
+#: src/pyams_default_theme/features/search/portlet/interfaces.py:24
+msgid "Display results count?"
+msgstr "Afficher le nombre de résultats ?"
+
+#: src/pyams_default_theme/features/search/portlet/interfaces.py:25
+msgid "If 'no', results count will not be displayed"
+msgstr "Si 'non', le nombre de résultats ne sera pas affiché"
+
+#: src/pyams_default_theme/features/search/portlet/interfaces.py:29
+msgid "Allow results sorting?"
+msgstr "Autoriser le tri ?"
+
+#: src/pyams_default_theme/features/search/portlet/interfaces.py:30
+msgid "If 'no', results will not be sortable"
+msgstr "Si 'non', les résultats ne pourront pas être triés par l'utilisateur"
+
+#: src/pyams_default_theme/features/search/portlet/interfaces.py:34
+msgid "Allow pagination?"
+msgstr "Autoriser la pagination ?"
+
+#: src/pyams_default_theme/features/search/portlet/interfaces.py:35
+msgid "If 'no', results will not be paginated"
+msgstr "Si 'non', les résultats seront affichés sur une seule page"
+
+#: src/pyams_default_theme/features/search/portlet/templates/search-results.pt:10
+msgid "${count} result(s) found"
+msgstr "${count} résultat(s) trouvé(s)"
+
+#: src/pyams_default_theme/features/search/portlet/templates/search-results.pt:13
+msgid "No result found!"
+msgstr "Aucun résultat."
+
+#: src/pyams_default_theme/features/header/interfaces.py:28
+msgid "Apply on root?"
+msgstr "Appliquer sur l'accueil ?"
+
+#: src/pyams_default_theme/features/header/interfaces.py:29
+msgid ""
+"If 'no', header settings will not be applied on site root but only on inner "
+"sites"
+msgstr ""
+"Si 'non', l'en-tête de page ne sera pas utilisé à l'accueil du site, mais "
+"pourra être hérité dans les pages intérieures"
+
+#: src/pyams_default_theme/features/header/interfaces.py:34
 msgid "Banner image"
 msgstr "Bandeau"
 
-#: src/pyams_default_theme/features/header/interfaces.py:32
+#: src/pyams_default_theme/features/header/interfaces.py:35
 msgid "Image displayed as header background"
 msgstr "Image affichée en tête de page"
 
-#: src/pyams_default_theme/features/header/interfaces.py:35
+#: src/pyams_default_theme/features/header/interfaces.py:38
 msgid "Logo"
 msgstr "Logo"
 
-#: src/pyams_default_theme/features/header/interfaces.py:36
+#: src/pyams_default_theme/features/header/interfaces.py:39
 msgid "Logo displayed in header"
 msgstr "Logo superposé au bandeau"
 
-#: src/pyams_default_theme/features/header/zmi/__init__.py:81
-msgid "Top tabs"
-msgstr "Onglets de navigation"
+#: src/pyams_default_theme/features/header/interfaces.py:42
+msgid "Search form target"
+msgstr "Cible de la recherche"
 
-#: src/pyams_default_theme/features/header/skin/__init__.py:111
+#: src/pyams_default_theme/features/header/interfaces.py:43
+msgid "Site or folder handling site search"
+msgstr "Site ou rubrique qui prend en charge la recherche"
+
+#: src/pyams_default_theme/features/header/zmi/__init__.py:70
+msgid "Top menus"
+msgstr "Menus de navigation"
+
+#: src/pyams_default_theme/features/header/skin/__init__.py:120
 msgid "Hidden header"
 msgstr "NON affiché"
 
-#: src/pyams_default_theme/features/header/skin/__init__.py:134
+#: src/pyams_default_theme/features/header/skin/__init__.py:143
 msgid "PyAMS simple header with banner and tabs"
 msgstr "PyAMS: en-tête simple avec bandeau et onglets de navigation"
 
@@ -421,17 +548,22 @@
 msgid "Toggle navigation"
 msgstr "Menu de navigation"
 
-#~ msgid "Show illustration?"
-#~ msgstr "Afficher l'illustration ?"
+#: src/pyams_default_theme/features/header/skin/templates/simple-header.pt:57
+msgid "Search..."
+msgstr "Recherche..."
+
+#: src/pyams_default_theme/features/header/skin/templates/simple-header.pt:59
+msgid "Search"
+msgstr "Chercher"
+
+#~ msgid "Top tabs"
+#~ msgstr "Onglets de navigation"
 
 #~ msgid "If 'no', illustration will not be displayed"
 #~ msgstr ""
 #~ "Si 'non', l'illustration ne sera pas affichée même si un contenu a été "
 #~ "fourni"
 
-#~ msgid "Search..."
-#~ msgstr "Chercher..."
-
 #~ msgid "Hide menu"
 #~ msgstr "Masquer le menu"
 
--- a/src/pyams_default_theme/locales/pyams_default_theme.pot	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/locales/pyams_default_theme.pot	Tue Dec 04 15:53:25 2018 +0100
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE 1.0\n"
-"POT-Creation-Date: 2018-11-16 10:59+0100\n"
+"POT-Creation-Date: 2018-11-30 11:12+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -24,15 +24,19 @@
 msgid "Default grid gallery renderer"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/gallery/__init__.py:43
+#: ./src/pyams_default_theme/component/gallery/__init__.py:46
 msgid "Carousel gallery renderer"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/gallery/templates/renderer-carousel.pt:31
+#: ./src/pyams_default_theme/component/gallery/templates/renderer-carousel.pt:32
+#: ./src/pyams_default_theme/shared/view/portlet/templates/view-items-list.pt:47
+#: ./src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-carousel.pt:32
 msgid "Previous"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/gallery/templates/renderer-carousel.pt:35
+#: ./src/pyams_default_theme/component/gallery/templates/renderer-carousel.pt:36
+#: ./src/pyams_default_theme/shared/view/portlet/templates/view-items-list.pt:53
+#: ./src/pyams_default_theme/features/menu/portlet/navigation/templates/simple-carousel.pt:37
 msgid "Next"
 msgstr ""
 
@@ -48,19 +52,19 @@
 msgid "Vertical list"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/illustration/__init__.py:170
+#: ./src/pyams_default_theme/component/illustration/__init__.py:162
 msgid "Centered illustration before text"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/illustration/__init__.py:181
+#: ./src/pyams_default_theme/component/illustration/__init__.py:173
 msgid "Small illustration on the left"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/illustration/__init__.py:193
+#: ./src/pyams_default_theme/component/illustration/__init__.py:187
 msgid "Small illustration on the right"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/illustration/__init__.py:205
+#: ./src/pyams_default_theme/component/illustration/__init__.py:201
 msgid "Centered illustration after text"
 msgstr ""
 
@@ -115,30 +119,43 @@
 msgid "Default verbatim renderer"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/html.py:35
+#: ./src/pyams_default_theme/component/paragraph/html.py:40
 msgid "Default raw HTML renderer"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/html.py:49
+#: ./src/pyams_default_theme/component/paragraph/html.py:65
+msgid "Formatted source code renderer"
+msgstr ""
+
+#: ./src/pyams_default_theme/component/paragraph/html.py:97
 msgid "Default rich text renderer"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/contact.py:80
+#: ./src/pyams_default_theme/component/paragraph/contact.py:82
 msgid "Default contact renderer"
 msgstr ""
 
+#. Default: Contact
+#: ./src/pyams_default_theme/component/paragraph/contact.py:96
+msgid "contact-button-label"
+msgstr ""
+
 #: ./src/pyams_default_theme/component/paragraph/zmi/map.py:62
 msgid "Don't use default map configuration"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/portlet/__init__.py:40
+#: ./src/pyams_default_theme/component/paragraph/portlet/__init__.py:39
 msgid "Default paragraphs renderer"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/portlet/__init__.py:67
+#: ./src/pyams_default_theme/component/paragraph/portlet/__init__.py:96
 msgid "Default paragraphs navigation"
 msgstr ""
 
+#: ./src/pyams_default_theme/component/paragraph/portlet/templates/content.pt:13
+msgid "Previous and next topics"
+msgstr ""
+
 #: ./src/pyams_default_theme/component/paragraph/interfaces/map.py:34
 msgid "Don't use default configuration?"
 msgstr ""
@@ -149,13 +166,13 @@
 
 #: ./src/pyams_default_theme/component/paragraph/interfaces/frame.py:25
 #: ./src/pyams_default_theme/component/paragraph/interfaces/verbatim.py:22
-#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:29
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:25
 msgid "Left"
 msgstr ""
 
 #: ./src/pyams_default_theme/component/paragraph/interfaces/frame.py:26
 #: ./src/pyams_default_theme/component/paragraph/interfaces/verbatim.py:23
-#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:30
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:26
 msgid "Right"
 msgstr ""
 
@@ -197,28 +214,36 @@
 "columns count; full width counts for 12 columns"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:40
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:36
 msgid "Show photo?"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:41
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:37
 msgid "Display contact photo"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:45
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:41
 msgid "Photo position"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:52
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:48
 msgid "Show location map?"
 msgstr ""
 
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:49
+msgid "If 'no', location map will not be displayed"
+msgstr ""
+
 #: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:53
-msgid "If 'no', location map will not be displayed"
+msgid "Map position"
 msgstr ""
 
-#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:57
-msgid "Map position"
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:60
+msgid "Contact button label"
+msgstr ""
+
+#: ./src/pyams_default_theme/component/paragraph/interfaces/contact.py:61
+msgid "Custom label of the contact button displayed by front-office template"
 msgstr ""
 
 #: ./src/pyams_default_theme/component/association/__init__.py:44
@@ -264,7 +289,8 @@
 msgstr ""
 
 #: ./src/pyams_default_theme/shared/common/summary.py:38
-#: ./src/pyams_default_theme/shared/site/link.py:64
+#: ./src/pyams_default_theme/shared/site/link.py:70
+#: ./src/pyams_default_theme/shared/site/link.py:108
 msgid "Consult content"
 msgstr ""
 
@@ -272,7 +298,7 @@
 msgid "Default title renderer"
 msgstr ""
 
-#: ./src/pyams_default_theme/shared/common/portlet/head.py:38
+#: ./src/pyams_default_theme/shared/common/portlet/head.py:33
 msgid "Default header renderer"
 msgstr ""
 
@@ -284,10 +310,34 @@
 msgid "WARNING: items displayed in this preview are out of context!!"
 msgstr ""
 
-#: ./src/pyams_default_theme/shared/view/portlet/__init__.py:38
+#: ./src/pyams_default_theme/shared/view/portlet/__init__.py:48
 msgid "Simple vertical view"
 msgstr ""
 
+#: ./src/pyams_default_theme/shared/view/portlet/interfaces.py:24
+msgid "Display illustrations?"
+msgstr ""
+
+#: ./src/pyams_default_theme/shared/view/portlet/interfaces.py:25
+msgid "If 'no', view contents will not display illustrations"
+msgstr ""
+
+#: ./src/pyams_default_theme/shared/view/portlet/interfaces.py:29
+msgid "Paginate?"
+msgstr ""
+
+#: ./src/pyams_default_theme/shared/view/portlet/interfaces.py:30
+msgid "If 'no', results pagination will be disabled"
+msgstr ""
+
+#: ./src/pyams_default_theme/shared/view/portlet/interfaces.py:34
+msgid "Page size"
+msgstr ""
+
+#: ./src/pyams_default_theme/shared/view/portlet/interfaces.py:35
+msgid "Number of items per page, if pagination is enabled"
+msgstr ""
+
 #: ./src/pyams_default_theme/shared/imagemap/__init__.py:52
 msgid "Default imagemap renderer"
 msgstr ""
@@ -297,14 +347,19 @@
 msgstr ""
 
 #: ./src/pyams_default_theme/shared/site/folder.py:60
-#: ./src/pyams_default_theme/features/search/__init__.py:64
+#: ./src/pyams_default_theme/features/search/__init__.py:77
 msgid "Consult folder"
 msgstr ""
 
-#: ./src/pyams_default_theme/shared/site/portlet/__init__.py:35
+#: ./src/pyams_default_theme/shared/site/portlet/__init__.py:48
 msgid "Site container summary"
 msgstr ""
 
+#: ./src/pyams_default_theme/shared/site/portlet/__init__.py:58
+#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:86
+msgid "Vertical panels with panoramic illustrations"
+msgstr ""
+
 #: ./src/pyams_default_theme/shared/logo/__init__.py:34
 msgid "Default logos renderer"
 msgstr ""
@@ -317,19 +372,32 @@
 msgid "Hidden content"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:49
+#: ./src/pyams_default_theme/features/share/portlet/__init__.py:35
+msgid "Default toolbox"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/share/portlet/templates/toolbox.pt:7
+#: ./src/pyams_default_theme/features/share/portlet/templates/toolbox.pt:9
+msgid "Print page"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:53
 msgid "Horizontal list with vertical illustrations"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:59
+#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:64
 msgid "Horizontal list with tabs and horizontal illustrations"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:72
+#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:75
+msgid "Horizontal carousel with full width illustrations"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:100
 msgid "Vertical list with small horizontal menus illustrations"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:95
+#: ./src/pyams_default_theme/features/menu/portlet/navigation/__init__.py:123
 msgid "Double-level selection navigation"
 msgstr ""
 
@@ -369,34 +437,96 @@
 msgid "PyAMS simple footer with links"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/header/interfaces.py:31
+#: ./src/pyams_default_theme/features/search/portlet/__init__.py:52
+msgid "Default search results"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/search/portlet/interfaces.py:24
+msgid "Display results count?"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/search/portlet/interfaces.py:25
+msgid "If 'no', results count will not be displayed"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/search/portlet/interfaces.py:29
+msgid "Allow results sorting?"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/search/portlet/interfaces.py:30
+msgid "If 'no', results will not be sortable"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/search/portlet/interfaces.py:34
+msgid "Allow pagination?"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/search/portlet/interfaces.py:35
+msgid "If 'no', results will not be paginated"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/search/portlet/templates/search-results.pt:10
+msgid "${count} result(s) found"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/search/portlet/templates/search-results.pt:13
+msgid "No result found!"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/header/interfaces.py:28
+msgid "Apply on root?"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/header/interfaces.py:29
+msgid ""
+"If 'no', header settings will not be applied on site root but only on inner "
+"sites"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/header/interfaces.py:34
 msgid "Banner image"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/header/interfaces.py:32
+#: ./src/pyams_default_theme/features/header/interfaces.py:35
 msgid "Image displayed as header background"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/header/interfaces.py:35
+#: ./src/pyams_default_theme/features/header/interfaces.py:38
 msgid "Logo"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/header/interfaces.py:36
+#: ./src/pyams_default_theme/features/header/interfaces.py:39
 msgid "Logo displayed in header"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/header/zmi/__init__.py:81
-msgid "Top tabs"
+#: ./src/pyams_default_theme/features/header/interfaces.py:42
+msgid "Search form target"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/header/skin/__init__.py:111
+#: ./src/pyams_default_theme/features/header/interfaces.py:43
+msgid "Site or folder handling site search"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/header/zmi/__init__.py:70
+msgid "Top menus"
+msgstr ""
+
+#: ./src/pyams_default_theme/features/header/skin/__init__.py:120
 msgid "Hidden header"
 msgstr ""
 
-#: ./src/pyams_default_theme/features/header/skin/__init__.py:134
+#: ./src/pyams_default_theme/features/header/skin/__init__.py:143
 msgid "PyAMS simple header with banner and tabs"
 msgstr ""
 
 #: ./src/pyams_default_theme/features/header/skin/templates/simple-header.pt:13
 msgid "Toggle navigation"
 msgstr ""
+
+#: ./src/pyams_default_theme/features/header/skin/templates/simple-header.pt:57
+msgid "Search..."
+msgstr ""
+
+#: ./src/pyams_default_theme/features/header/skin/templates/simple-header.pt:59
+msgid "Search"
+msgstr ""
--- a/src/pyams_default_theme/resources/css/pyams-default.css	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/resources/css/pyams-default.css	Tue Dec 04 15:53:25 2018 +0100
@@ -13,59 +13,7 @@
 body {
   font-family: Lato, Helvetica, Arial, sans-serif;
   margin: 0 auto;
-}
-body .header-simple .regularbanner {
-  position: relative;
-}
-body .header-simple .regularbanner picture.regularbanner__media,
-body .header-simple .regularbanner img.regularbanner__media {
-  width: 100%;
-}
-body .header-simple .regularbanner picture.logo,
-body .header-simple .regularbanner img.logo {
-  position: absolute;
-  top: 10px;
-  left: 10px;
-  max-height: calc(100% - 20px);
-}
-body .affix {
-  top: 0;
-  width: 100%;
-  z-index: 9999 !important;
-  opacity: 0.95;
-  transition: all 0.5s ease-in-out;
-}
-body .affix ~ .container-fluid {
-  position: relative;
-  top: 50px;
-}
-body .navbar {
-  margin-bottom: 20px;
-  background-color: white;
-  border: 1px solid #39413b;
-  font-family: Oswald, Helvetica, Arial, Sans-Serif;
-  transition: all 0.5s ease-in-out;
-}
-body .navbar a,
-body .navbar a:active,
-body .navbar a:visited {
-  color: #39413b;
-}
-body .navbar li.active,
-body .navbar .icon-bar {
-  background-color: #a5bcaa;
-}
-body .navbar.affix {
-  background-color: #39413b;
-}
-body .navbar.affix a {
-  color: white;
-}
-body .navbar.affix:hover a:hover {
-  color: #39413b;
-}
-body .navbar.affix .icon-bar {
-  background-color: white;
+  overflow-x: hidden;
 }
 h1,
 h2,
@@ -75,6 +23,78 @@
 h6 {
   font-family: Oswald, Helvetica, Arial, Sans-Serif;
 }
+hr.simple {
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
+hr.noborder {
+  border: 0;
+}
+/**
+ * Header styles
+ */
+.header-simple .regularbanner {
+  position: relative;
+}
+.header-simple .regularbanner picture.regularbanner__media,
+.header-simple .regularbanner img.regularbanner__media {
+  width: 100%;
+}
+.header-simple .regularbanner picture.logo,
+.header-simple .regularbanner img.logo {
+  position: absolute;
+  top: 10px;
+  left: 10px;
+  max-height: calc(100% - 20px);
+}
+.affix {
+  top: 0;
+  width: 100%;
+  z-index: 9999 !important;
+  opacity: 0.95;
+  transition: all 0.5s ease-in-out;
+}
+.affix ~ .container-fluid {
+  position: relative;
+  top: 50px;
+}
+.navbar {
+  margin-bottom: 20px;
+  background-color: white;
+  border: 1px solid #39413b;
+  font-family: Oswald, Helvetica, Arial, Sans-Serif;
+  transition: all 0.5s ease-in-out;
+}
+.navbar a,
+.navbar a:active,
+.navbar a:visited {
+  color: #39413b;
+}
+.navbar li.active,
+.navbar .icon-bar {
+  background-color: #a5bcaa;
+}
+.navbar.affix {
+  background-color: #39413b;
+}
+.navbar.affix a {
+  color: white;
+}
+.navbar.affix .dropdown-menu a {
+  color: #39413b;
+}
+.navbar.affix:hover a:hover {
+  color: #39413b;
+}
+.navbar.affix .icon-bar {
+  background-color: white;
+}
+.breadcrumb {
+  margin-bottom: 1rem;
+}
+.page-header {
+  margin-top: 2rem;
+}
 @media only screen and (min-width: 1200px) {
   .portal-page .slot.col-lg-0 {
     display: none;
@@ -95,6 +115,49 @@
     display: none;
   }
 }
+.toolbox {
+  display: flex;
+  flex-direction: column;
+}
+.toolbox button {
+  text-align: left;
+  display: flex;
+  align-items: center;
+}
+.toolbox button i.fa {
+  display: inline-block;
+  margin-right: 1rem;
+}
+@media only screen and (min-width: 1340px) {
+  .col-lg-12 .portlet > section.wrapper {
+    margin-left: calc(0vw);
+    margin-right: calc(0vw);
+  }
+}
+@media only screen and (min-width: 1052px) {
+  .col-md-12 .portlet > section.wrapper {
+    margin-left: calc(0vw);
+    margin-right: calc(0vw);
+  }
+}
+@media only screen and (max-width: 1051px) {
+  .col-sm-12 .portlet > section.wrapper {
+    margin-left: calc(0vw);
+    margin-right: calc(0vw);
+  }
+}
+@media only screen and (max-width: 767px) {
+  .navbar.affix .dropdown-menu {
+    background-color: #39413b;
+  }
+  .navbar.affix .dropdown-menu a {
+    color: white;
+  }
+  .col-xs-12 .portlet > section.wrapper {
+    margin-left: calc(0vw);
+    margin-right: calc(0vw);
+  }
+}
 /**
  * Summary styles
  */
@@ -113,6 +176,25 @@
   border-left: 5px solid #ddd;
 }
 /**
+ * Panels
+ */
+.panels {
+  margin-top: 2rem;
+}
+/**
+ * Search results
+ */
+.search-results .breadcrumb:empty {
+  margin: 0;
+  padding: 0;
+}
+.search-results .thumbnail.pull-left {
+  margin-right: 3rem;
+}
+.search-results .tags span {
+  margin: 0 0.2rem;
+}
+/**
  * Images gallery
  */
 .illustration {
@@ -203,4 +285,10 @@
 .verbatim .panel-body .author {
   margin-top: 0.5em;
 }
+/**
+ * Source code
+ */
+.source pre {
+  font-family: 'Anonymous Pro', monospace;
+}
 /*# sourceMappingURL=pyams-default.css.map */
\ No newline at end of file
--- a/src/pyams_default_theme/resources/css/pyams-default.css.map	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/resources/css/pyams-default.css.map	Tue Dec 04 15:53:25 2018 +0100
@@ -1,1 +1,1 @@
-{"version":3,"sources":["../../../../../../../../../home/tflorac/Dropbox/src/PyAMS/pyams_default_theme/src/pyams_default_theme/resources/less/pyams-default.less"],"names":[],"mappings":";;;AAIC,cAAC;EACA,mBAAA;;AAED,cAAC;EACA,mBAAA;;;;;AASF;EACC,+CAAA;EACA,cAAA;;AAFD,IAIC,eACC;EACC,kBAAA;;AAIC,IANH,eACC,eAGC,QAEE;AAAD,IANH,eACC,eAIC,IACE;EACA,WAAA;;AAED,IATH,eACC,eAGC,QAKE;AAAD,IATH,eACC,eAIC,IAIE;EACA,kBAAA;EACA,SAAA;EACA,UAAA;EACA,6BAAA;;AAjBL,IAsBC;EACC,MAAA;EACA,WAAA;EACA,wBAAA;EACA,aAAA;EACA,gCAAA;;AA3BF,IA6BC,OAAO;EACN,kBAAA;EACA,SAAA;;AA/BF,IAiCC;EACC,mBAAA;EACA,uBAAA;EACA,yBAAA;EACA,iDAAA;EACA,gCAAA;;AAtCF,IAiCC,QAOC;AAxCF,IAiCC,QAQC,EAAC;AAzCH,IAiCC,QASC,EAAC;EACA,cAAA;;AA3CH,IAiCC,QAYC,GAAE;AA7CJ,IAiCC,QAaC;EACC,yBAAA;;AAED,IAhBD,QAgBE;EACA,yBAAA;;AADD,IAhBD,QAgBE,MAGA;EACC,YAAA;;AAED,IAtBF,QAgBE,MAMC,MACA,EAAC;EACA,cAAA;;AARH,IAhBD,QAgBE,MAWA;EACC,uBAAA;;AAMJ;AACA;AACA;AACA;AACA;AACA;EACC,iDAAA;;AAKC,wBAA2C;EAC1C,YAFF,MAEG;IACA,aAAA;;;AAGF,wBAA0C,uBAAwB;EACjE,YAPF,MAOG;IACA,aAAA;;;AAGF,wBAA0C,uBAAuB;EAChE,YAZF,MAYG;IACA,aAAA;;;AAGF,wBAA0C;EACzC,YAjBF,MAiBG;IACA,aAAA;;;;;;AAaF,QADD,WACE;EACA,kBAAA;;AAKH;EACC,gBAAA;EACA,sBAAA;EACA,2BAAA;;AAEA,UAAC;EACA,eAAA;EACA,gBAAA;EACA,sBAAA;EACA,2BAAA;;;;;AAQF;EACC,mBAAA;;AADD,aAGC;EACC,kBAAA;EACA,gBAAA;EACA,kBAAA;;AAGF;EACC,aAAA;EACA,eAAA;;AAFD,QAIC;EACC,oBAAA;;AALF,QAOC;EACC,6CAAA;EACG,kBAAA;EACH,QAAQ,WAAR;EACA,gCAAA;;AAEA,QAND,IAME;EACA,YAAA;;AAdH,QAiBC;EACC,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;;AAIF;EACC,eAAA;EACA,gBAAA;EACA,aAAA;;AAHD,cAKC;EACC,cAAA;EACA,2BAAA;EACA,kBAAA;EACA,gBAAA;;;;;AASF,cACC;EACC,WAAA;;;;;AAQF;EACC,aAAA;EACA,6BAAA;;AAFD,WAIC;EACC,iBAAA;EACA,gBAAA;;;;;AAWA,aADD,OACE;EACA,iBAAA;;AAED,aAJD,OAIE;EACA,gBAAA;;AANH,aASC;EACC,iBAAA;EACA,oBAAA;;;;;AASF,SACC;EACC,kBAAA;EACA,iBAAA;;AAEA,SAJD,YAIE;EACA,SAAS,GAAT;EACA,kBAAA;EACA,WAAA;EACA,MAAA;EACA,cAAA;;AAVH,SACC,YAWC;EACC,iBAAA","file":"pyams-default.css"}
\ No newline at end of file
+{"version":3,"sources":["../less/pyams-default.less"],"names":[],"mappings":";;;AAIC,cAAC;EACA,mBAAA;;AAED,cAAC;EACA,mBAAA;;;;;AASF;EACC,+CAAA;EACA,cAAA;EACA,kBAAA;;AAGD;AACA;AACA;AACA;AACA;AACA;EACC,iDAAA;;AAIA,EAAC;EACA,gBAAA;EACA,mBAAA;;AAED,EAAC;EACA,SAAA;;;;;AAQF,cACC;EACC,kBAAA;;AAIC,cALF,eAGC,QAEE;AAAD,cALF,eAIC,IACE;EACA,WAAA;;AAED,cARF,eAGC,QAKE;AAAD,cARF,eAIC,IAIE;EACA,kBAAA;EACA,SAAA;EACA,UAAA;EACA,6BAAA;;AAKJ;EACC,MAAA;EACA,WAAA;EACA,wBAAA;EACA,aAAA;EACA,gCAAA;;AAED,MAAO;EACN,kBAAA;EACA,SAAA;;AAED;EACC,mBAAA;EACA,uBAAA;EACA,yBAAA;EACA,iDAAA;EACA,gCAAA;;AALD,OAOC;AAPD,OAQC,EAAC;AARF,OASC,EAAC;EACA,cAAA;;AAVF,OAYC,GAAE;AAZH,OAaC;EACC,yBAAA;;AAED,OAAC;EACA,yBAAA;;AADD,OAAC,MAGA;EACC,YAAA;;AAJF,OAAC,MAMA,eACC;EACC,cAAA;;AAGF,OAXA,MAWC,MACA,EAAC;EACA,cAAA;;AAbH,OAAC,MAgBA;EACC,uBAAA;;AAKH;EACC,mBAAA;;AAGD;EACC,gBAAA;;AAKC,wBAA2C;EAC1C,YAFF,MAEG;IACA,aAAA;;;AAGF,wBAA0C,uBAAwB;EACjE,YAPF,MAOG;IACA,aAAA;;;AAGF,wBAA0C,uBAAuB;EAChE,YAZF,MAYG;IACA,aAAA;;;AAGF,wBAA0C;EACzC,YAjBF,MAiBG;IACA,aAAA;;;AAMJ;EACC,aAAA;EACA,sBAAA;;AAFD,QAIC;EACC,gBAAA;EACA,aAAA;EACA,mBAAA;;AAPF,QAIC,OAKC,EAAC;EACA,qBAAA;EACA,kBAAA;;AAKH,wBAA2C;EAC1C,UAAW,SAAS,UAAS;IAC5B,aAAa,SAAb;IACA,cAAc,SAAd;;;AAIF,wBAA2C;EAC1C,UAAW,SAAS,UAAS;IAC5B,aAAa,SAAb;IACA,cAAc,SAAd;;;AAIF,wBAA2C;EAC1C,UAAW,SAAS,UAAS;IAC5B,aAAa,SAAb;IACA,cAAc,SAAd;;;AAIF,wBAA0C;EAExC,OAAC,MACA;IACC,yBAAA;;EAFF,OAAC,MACA,eAGC;IACC,YAAA;;EAMJ,UAAW,SAAS,UAAS;IAC5B,aAAa,SAAb;IACA,cAAc,SAAd;;;;;;AAWA,QADD,WACE;EACA,kBAAA;;AAKH;EACC,gBAAA;EACA,sBAAA;EACA,2BAAA;;AAEA,UAAC;EACA,eAAA;EACA,gBAAA;EACA,sBAAA;EACA,2BAAA;;;;;AAQF;EACC,gBAAA;;;;;AAQD,eACC,YAAW;EACV,SAAA;EACA,UAAA;;AAGA,eADD,WACE;EACA,kBAAA;;AAPH,eAUC,MACC;EACC,gBAAA;;;;;AAUH;EACC,mBAAA;;AADD,aAGC;EACC,kBAAA;EACA,gBAAA;EACA,kBAAA;;AAGF;EACC,aAAA;EACA,eAAA;;AAFD,QAIC;EACC,oBAAA;;AALF,QAOC;EACC,6CAAA;EACG,kBAAA;EACH,QAAQ,WAAR;EACA,gCAAA;;AAEA,QAND,IAME;EACA,YAAA;;AAdH,QAiBC;EACC,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;;AAIF;EACC,eAAA;EACA,gBAAA;EACA,aAAA;;AAHD,cAKC;EACC,cAAA;EACA,2BAAA;EACA,kBAAA;EACA,gBAAA;;;;;AASF,cACC;EACC,WAAA;;;;;AAQF;EACC,aAAA;EACA,6BAAA;;AAFD,WAIC;EACC,iBAAA;EACA,gBAAA;;;;;AAWA,aADD,OACE;EACA,iBAAA;;AAED,aAJD,OAIE;EACA,gBAAA;;AANH,aASC;EACC,iBAAA;EACA,oBAAA;;;;;AASF,SACC;EACC,kBAAA;EACA,iBAAA;;AAEA,SAJD,YAIE;EACA,SAAS,GAAT;EACA,kBAAA;EACA,WAAA;EACA,MAAA;EACA,cAAA;;AAVH,SACC,YAWC;EACC,iBAAA;;;;;AAUH,OACC;EACC,aAAa,0BAAb","file":"pyams-default.css"}
\ No newline at end of file
--- a/src/pyams_default_theme/resources/css/pyams-default.min.css	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/resources/css/pyams-default.min.css	Tue Dec 04 15:53:25 2018 +0100
@@ -1,1 +1,1 @@
-.margin-bottom-10{margin-bottom:10px}.margin-bottom-20{margin-bottom:20px}body{font-family:Lato,Helvetica,Arial,sans-serif;margin:0 auto}body .header-simple .regularbanner{position:relative}body .header-simple .regularbanner img.regularbanner__media,body .header-simple .regularbanner picture.regularbanner__media{width:100%}body .header-simple .regularbanner img.logo,body .header-simple .regularbanner picture.logo{position:absolute;top:10px;left:10px;max-height:calc(100% - 20px)}body .affix{top:0;width:100%;z-index:9999!important;opacity:.95;transition:all .5s ease-in-out}body .affix~.container-fluid{position:relative;top:50px}body .navbar{margin-bottom:20px;background-color:#fff;border:1px solid #39413b;font-family:Oswald,Helvetica,Arial,Sans-Serif;transition:all .5s ease-in-out}body .navbar a,body .navbar a:active,body .navbar a:visited{color:#39413b}body .navbar .icon-bar,body .navbar li.active{background-color:#a5bcaa}body .navbar.affix{background-color:#39413b}body .navbar.affix a{color:#fff}body .navbar.affix:hover a:hover{color:#39413b}body .navbar.affix .icon-bar{background-color:#fff}h1,h2,h3,h4,h5,h6{font-family:Oswald,Helvetica,Arial,Sans-Serif}@media only screen and (min-width:1200px){.portal-page .slot.col-lg-0{display:none}}@media only screen and (min-width:992px) and (max-width:1199px){.portal-page .slot.col-md-0{display:none}}@media only screen and (min-width:768px) and (max-width:991px){.portal-page .slot.col-sm-0{display:none}}@media only screen and (max-width:767px){.portal-page .slot.col-xs-0{display:none}}.summary .thumbnail.pull-left{margin-right:15px}blockquote{margin-top:2rem;border:1px solid #ddd;border-left:5px solid #ddd}blockquote.pull-right{padding:0 15px;text-align:left;border:1px solid #ddd;border-left:5px solid #ddd}.illustration{margin-bottom:1rem}.illustration .author{padding-top:.2em;font-size:.9em;font-style:italic}.gallery{display:flex;flex-wrap:wrap}.gallery .legend{margin-bottom:.2em}.gallery img{box-shadow:0 2px 6px 2px rgba(0,0,0,.75);margin-bottom:5px;filter:grayscale();transition:all ease-in-out .5s}.gallery img:hover{filter:none}.gallery .author{margin-bottom:15px;text-align:right;font-style:italic;font-size:.8em}.ekko-lightbox{position:fixed;top:0!important;height:100vh}.ekko-lightbox .modal-footer{padding-top:0;text-align:right!important;font-style:italic;font-size:.8em}.video-wrapper iframe{width:100%}.milestones{display:flex;justify-content:space-around}.milestones .arrow{font-weight:700;font-size:1.5em}.contact-card .photo.pull-left{margin-right:1em}.contact-card .photo.pull-right{margin-left:1em}.contact-card .address{margin-top:.5em;margin-bottom:.5em}.verbatim .panel-body{position:relative;margin-left:50px}.verbatim .panel-body::before{content:'«';position:absolute;left:-30px;top:0;font-size:4em}.verbatim .panel-body .author{margin-top:.5em}
+.margin-bottom-10{margin-bottom:10px}.margin-bottom-20{margin-bottom:20px}body{font-family:Lato,Helvetica,Arial,sans-serif;margin:0 auto;overflow-x:hidden}h1,h2,h3,h4,h5,h6{font-family:Oswald,Helvetica,Arial,Sans-Serif}hr.simple{margin-top:10px;margin-bottom:10px}hr.noborder{border:0}.header-simple .regularbanner{position:relative}.header-simple .regularbanner img.regularbanner__media,.header-simple .regularbanner picture.regularbanner__media{width:100%}.header-simple .regularbanner img.logo,.header-simple .regularbanner picture.logo{position:absolute;top:10px;left:10px;max-height:calc(100% - 20px)}.affix{top:0;width:100%;z-index:9999!important;opacity:.95;transition:all .5s ease-in-out}.affix~.container-fluid{position:relative;top:50px}.navbar{margin-bottom:20px;background-color:#fff;border:1px solid #39413b;font-family:Oswald,Helvetica,Arial,Sans-Serif;transition:all .5s ease-in-out}.navbar a,.navbar a:active,.navbar a:visited{color:#39413b}.navbar .icon-bar,.navbar li.active{background-color:#a5bcaa}.navbar.affix{background-color:#39413b}.navbar.affix a{color:#fff}.navbar.affix .dropdown-menu a{color:#39413b}.navbar.affix:hover a:hover{color:#39413b}.navbar.affix .icon-bar{background-color:#fff}.breadcrumb{margin-bottom:1rem}.page-header{margin-top:2rem}@media only screen and (min-width:1200px){.portal-page .slot.col-lg-0{display:none}}@media only screen and (min-width:992px) and (max-width:1199px){.portal-page .slot.col-md-0{display:none}}@media only screen and (min-width:768px) and (max-width:991px){.portal-page .slot.col-sm-0{display:none}}@media only screen and (max-width:767px){.portal-page .slot.col-xs-0{display:none}}.toolbox{display:flex;flex-direction:column}.toolbox button{text-align:left;display:flex;align-items:center}.toolbox button i.fa{display:inline-block;margin-right:1rem}@media only screen and (min-width:1340px){.col-lg-12 .portlet>section.wrapper{margin-left:calc(0vw);margin-right:calc(0vw)}}@media only screen and (min-width:1052px){.col-md-12 .portlet>section.wrapper{margin-left:calc(0vw);margin-right:calc(0vw)}}@media only screen and (max-width:1051px){.col-sm-12 .portlet>section.wrapper{margin-left:calc(0vw);margin-right:calc(0vw)}}@media only screen and (max-width:767px){.navbar.affix .dropdown-menu{background-color:#39413b}.navbar.affix .dropdown-menu a{color:#fff}.col-xs-12 .portlet>section.wrapper{margin-left:calc(0vw);margin-right:calc(0vw)}}.summary .thumbnail.pull-left{margin-right:15px}blockquote{margin-top:2rem;border:1px solid #ddd;border-left:5px solid #ddd}blockquote.pull-right{padding:0 15px;text-align:left;border:1px solid #ddd;border-left:5px solid #ddd}.panels{margin-top:2rem}.search-results .breadcrumb:empty{margin:0;padding:0}.search-results .thumbnail.pull-left{margin-right:3rem}.search-results .tags span{margin:0 .2rem}.illustration{margin-bottom:1rem}.illustration .author{padding-top:.2em;font-size:.9em;font-style:italic}.gallery{display:flex;flex-wrap:wrap}.gallery .legend{margin-bottom:.2em}.gallery img{box-shadow:0 2px 6px 2px rgba(0,0,0,.75);margin-bottom:5px;filter:grayscale();transition:all ease-in-out .5s}.gallery img:hover{filter:none}.gallery .author{margin-bottom:15px;text-align:right;font-style:italic;font-size:.8em}.ekko-lightbox{position:fixed;top:0!important;height:100vh}.ekko-lightbox .modal-footer{padding-top:0;text-align:right!important;font-style:italic;font-size:.8em}.video-wrapper iframe{width:100%}.milestones{display:flex;justify-content:space-around}.milestones .arrow{font-weight:700;font-size:1.5em}.contact-card .photo.pull-left{margin-right:1em}.contact-card .photo.pull-right{margin-left:1em}.contact-card .address{margin-top:.5em;margin-bottom:.5em}.verbatim .panel-body{position:relative;margin-left:50px}.verbatim .panel-body::before{content:'«';position:absolute;left:-30px;top:0;font-size:4em}.verbatim .panel-body .author{margin-top:.5em}.source pre{font-family:'Anonymous Pro',monospace}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/resources/img/print-button.svg	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="45px" height="45px" viewBox="0 0 45 45" style="enable-background:new 0 0 45 45;" xml:space="preserve">
+<g>
+	<path d="M42.5,19.408H40V1.843c0-0.69-0.561-1.25-1.25-1.25H6.25C5.56,0.593,5,1.153,5,1.843v17.563H2.5
+		c-1.381,0-2.5,1.119-2.5,2.5v20c0,1.381,1.119,2.5,2.5,2.5h40c1.381,0,2.5-1.119,2.5-2.5v-20C45,20.525,43.881,19.408,42.5,19.408z
+		 M32.531,38.094H12.468v-5h20.063V38.094z M37.5,19.408H35c-1.381,0-2.5,1.119-2.5,2.5v5h-20v-5c0-1.381-1.119-2.5-2.5-2.5H7.5
+		V3.093h30V19.408z M32.5,8.792h-20c-0.69,0-1.25-0.56-1.25-1.25s0.56-1.25,1.25-1.25h20c0.689,0,1.25,0.56,1.25,1.25
+		S33.189,8.792,32.5,8.792z M32.5,13.792h-20c-0.69,0-1.25-0.56-1.25-1.25s0.56-1.25,1.25-1.25h20c0.689,0,1.25,0.56,1.25,1.25
+		S33.189,13.792,32.5,13.792z M32.5,18.792h-20c-0.69,0-1.25-0.56-1.25-1.25s0.56-1.25,1.25-1.25h20c0.689,0,1.25,0.56,1.25,1.25
+		S33.189,18.792,32.5,18.792z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
--- a/src/pyams_default_theme/resources/js/ext/ekko-lightbox.min.js	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/resources/js/ext/ekko-lightbox.min.js	Tue Dec 04 15:53:25 2018 +0100
@@ -1,1 +1,1 @@
-!function(t){"use strict";var e=function(){function o(t,e){for(var i=0;i<e.length;i++){var o=e[i];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(t,e,i){return e&&o(t.prototype,e),i&&o(t,i),t}}();var c,i,o,l,a;c=jQuery,i="ekkoLightbox",o=c.fn[i],l={title:"",footer:"",maxWidth:9999,maxHeight:9999,showArrows:!0,wrapping:!0,type:null,alwaysShowClose:!1,loadingMessage:'<div class="ekko-lightbox-loader"><div><div></div><div></div></div></div>',leftArrow:"<span>&#10094;</span>",rightArrow:"<span>&#10095;</span>",strings:{close:"Close",fail:"Failed to load image:",type:"Could not detect remote target type. Force the type using data-type"},doc:document,onShow:function(){},onShown:function(){},onHide:function(){},onHidden:function(){},onNavigate:function(){},onContentLoaded:function(){}},a=function(){function n(t,e){var i=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,n),this._config=c.extend({},l,e),this._$modalArrows=null,this._galleryIndex=0,this._galleryName=null,this._padding=null,this._border=null,this._titleIsShown=!1,this._footerIsShown=!1,this._wantedWidth=0,this._wantedHeight=0,this._touchstartX=0,this._touchendX=0,this._modalId="ekkoLightbox-"+Math.floor(1e3*Math.random()+1),this._$element=t instanceof jQuery?t:c(t),this._isBootstrap3=3==c.fn.modal.Constructor.VERSION[0];var o='<h4 class="modal-title">'+(this._config.title||"&nbsp;")+"</h4>",a='<button type="button" class="close" data-dismiss="modal" aria-label="'+this._config.strings.close+'"><span aria-hidden="true">&times;</span></button>',s='<div class="modal-dialog" role="document"><div class="modal-content">'+('<div class="modal-header'+(this._config.title||this._config.alwaysShowClose?"":" hide")+'">'+(this._isBootstrap3?a+o:o+a)+"</div>")+'<div class="modal-body"><div class="ekko-lightbox-container"><div class="ekko-lightbox-item fade in show"></div><div class="ekko-lightbox-item fade"></div></div></div>'+('<div class="modal-footer'+(this._config.footer?"":" hide")+'">'+(this._config.footer||"&nbsp;")+"</div>")+"</div></div>";c(this._config.doc.body).append('<div id="'+this._modalId+'" class="ekko-lightbox modal fade" tabindex="-1" tabindex="-1" role="dialog" aria-hidden="true">'+s+"</div>"),this._$modal=c("#"+this._modalId,this._config.doc),this._$modalDialog=this._$modal.find(".modal-dialog").first(),this._$modalContent=this._$modal.find(".modal-content").first(),this._$modalBody=this._$modal.find(".modal-body").first(),this._$modalHeader=this._$modal.find(".modal-header").first(),this._$modalFooter=this._$modal.find(".modal-footer").first(),this._$lightboxContainer=this._$modalBody.find(".ekko-lightbox-container").first(),this._$lightboxBodyOne=this._$lightboxContainer.find("> div:first-child").first(),this._$lightboxBodyTwo=this._$lightboxContainer.find("> div:last-child").first(),this._border=this._calculateBorders(),this._padding=this._calculatePadding(),this._galleryName=this._$element.data("gallery"),this._galleryName&&(this._$galleryItems=c(document.body).find('*[data-gallery="'+this._galleryName+'"]'),this._galleryIndex=this._$galleryItems.index(this._$element),c(document).on("keydown.ekkoLightbox",this._navigationalBinder.bind(this)),this._config.showArrows&&1<this._$galleryItems.length&&(this._$lightboxContainer.append('<div class="ekko-lightbox-nav-overlay"><a href="#">'+this._config.leftArrow+'</a><a href="#">'+this._config.rightArrow+"</a></div>"),this._$modalArrows=this._$lightboxContainer.find("div.ekko-lightbox-nav-overlay").first(),this._$lightboxContainer.on("click","a:first-child",function(t){return t.preventDefault(),i.navigateLeft()}),this._$lightboxContainer.on("click","a:last-child",function(t){return t.preventDefault(),i.navigateRight()}),this.updateNavigation())),this._$modal.on("show.bs.modal",this._config.onShow.bind(this)).on("shown.bs.modal",function(){return i._toggleLoading(!0),i._handle(),i._config.onShown.call(i)}).on("hide.bs.modal",this._config.onHide.bind(this)).on("hidden.bs.modal",function(){return i._galleryName&&(c(document).off("keydown.ekkoLightbox"),c(window).off("resize.ekkoLightbox")),i._$modal.remove(),i._config.onHidden.call(i)}).modal(this._config),c(window).on("resize.ekkoLightbox",function(){i._resize(i._wantedWidth,i._wantedHeight)}),this._$lightboxContainer.on("touchstart",function(){i._touchstartX=event.changedTouches[0].screenX}).on("touchend",function(){i._touchendX=event.changedTouches[0].screenX,i._swipeGesure()})}return e(n,null,[{key:"Default",get:function(){return l}}]),e(n,[{key:"element",value:function(){return this._$element}},{key:"modal",value:function(){return this._$modal}},{key:"navigateTo",value:function(t){if(t<0||t>this._$galleryItems.length-1)return this;this._galleryIndex=t,this.updateNavigation(),this._$element=c(this._$galleryItems.get(this._galleryIndex)),this._handle()}},{key:"navigateLeft",value:function(){if(this._$galleryItems&&1!==this._$galleryItems.length){if(0===this._galleryIndex){if(!this._config.wrapping)return;this._galleryIndex=this._$galleryItems.length-1}else this._galleryIndex--;return this._config.onNavigate.call(this,"left",this._galleryIndex),this.navigateTo(this._galleryIndex)}}},{key:"navigateRight",value:function(){if(this._$galleryItems&&1!==this._$galleryItems.length){if(this._galleryIndex===this._$galleryItems.length-1){if(!this._config.wrapping)return;this._galleryIndex=0}else this._galleryIndex++;return this._config.onNavigate.call(this,"right",this._galleryIndex),this.navigateTo(this._galleryIndex)}}},{key:"updateNavigation",value:function(){if(!this._config.wrapping){var t=this._$lightboxContainer.find("div.ekko-lightbox-nav-overlay");0===this._galleryIndex?t.find("a:first-child").addClass("disabled"):t.find("a:first-child").removeClass("disabled"),this._galleryIndex===this._$galleryItems.length-1?t.find("a:last-child").addClass("disabled"):t.find("a:last-child").removeClass("disabled")}}},{key:"close",value:function(){return this._$modal.modal("hide")}},{key:"_navigationalBinder",value:function(t){return 39===(t=t||window.event).keyCode?this.navigateRight():37===t.keyCode?this.navigateLeft():void 0}},{key:"_detectRemoteType",value:function(t,e){return!(e=e||!1)&&this._isImage(t)&&(e="image"),!e&&this._getYoutubeId(t)&&(e="youtube"),!e&&this._getVimeoId(t)&&(e="vimeo"),!e&&this._getInstagramId(t)&&(e="instagram"),("audio"==e||"video"==e||!e&&this._isMedia(t))&&(e="media"),(!e||["image","youtube","vimeo","instagram","media","url"].indexOf(e)<0)&&(e="url"),e}},{key:"_getRemoteContentType",value:function(t){return c.ajax({type:"HEAD",url:t,async:!1}).getResponseHeader("Content-Type")}},{key:"_isImage",value:function(t){return t&&t.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)}},{key:"_isMedia",value:function(t){return t&&t.match(/(\.(mp3|mp4|ogg|webm|wav)((\?|#).*)?$)/i)}},{key:"_containerToUse",value:function(){var t=this,e=this._$lightboxBodyTwo,i=this._$lightboxBodyOne;return this._$lightboxBodyTwo.hasClass("in")&&(e=this._$lightboxBodyOne,i=this._$lightboxBodyTwo),i.removeClass("in show"),setTimeout(function(){t._$lightboxBodyTwo.hasClass("in")||t._$lightboxBodyTwo.empty(),t._$lightboxBodyOne.hasClass("in")||t._$lightboxBodyOne.empty()},500),e.addClass("in show"),e}},{key:"_handle",value:function(){var t=this._containerToUse();this._updateTitleAndFooter();var e=this._$element.attr("data-remote")||this._$element.attr("href"),i=this._detectRemoteType(e,this._$element.attr("data-type")||!1);if(["image","youtube","vimeo","instagram","media","url"].indexOf(i)<0)return this._error(this._config.strings.type);switch(i){case"image":this._preloadImage(e,t),this._preloadImageByIndex(this._galleryIndex,3);break;case"youtube":this._showYoutubeVideo(e,t);break;case"vimeo":this._showVimeoVideo(this._getVimeoId(e),t);break;case"instagram":this._showInstagramVideo(this._getInstagramId(e),t);break;case"media":this._showHtml5Media(e,t);break;default:this._loadRemoteContent(e,t)}return this}},{key:"_getYoutubeId",value:function(t){if(!t)return!1;var e=t.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/);return!(!e||11!==e[2].length)&&e[2]}},{key:"_getVimeoId",value:function(t){return!!(t&&0<t.indexOf("vimeo"))&&t}},{key:"_getInstagramId",value:function(t){return!!(t&&0<t.indexOf("instagram"))&&t}},{key:"_toggleLoading",value:function(t){return(t=t||!1)?(this._$modalDialog.css("display","none"),this._$modal.removeClass("in show"),c(".modal-backdrop").append(this._config.loadingMessage)):(this._$modalDialog.css("display","block"),this._$modal.addClass("in show"),c(".modal-backdrop").find(".ekko-lightbox-loader").remove()),this}},{key:"_calculateBorders",value:function(){return{top:this._totalCssByAttribute("border-top-width"),right:this._totalCssByAttribute("border-right-width"),bottom:this._totalCssByAttribute("border-bottom-width"),left:this._totalCssByAttribute("border-left-width")}}},{key:"_calculatePadding",value:function(){return{top:this._totalCssByAttribute("padding-top"),right:this._totalCssByAttribute("padding-right"),bottom:this._totalCssByAttribute("padding-bottom"),left:this._totalCssByAttribute("padding-left")}}},{key:"_totalCssByAttribute",value:function(t){return parseInt(this._$modalDialog.css(t),10)+parseInt(this._$modalContent.css(t),10)+parseInt(this._$modalBody.css(t),10)}},{key:"_updateTitleAndFooter",value:function(){var t=this._$element.data("title")||"",e=this._$element.data("footer")||"";return this._titleIsShown=!1,t||this._config.alwaysShowClose?(this._titleIsShown=!0,this._$modalHeader.css("display","").find(".modal-title").html(t||"&nbsp;")):this._$modalHeader.css("display","none"),this._footerIsShown=!1,e?(this._footerIsShown=!0,this._$modalFooter.css("display","").html(e)):this._$modalFooter.css("display","none"),this}},{key:"_showYoutubeVideo",value:function(t,e){var i=this._getYoutubeId(t),o=0<t.indexOf("&")?t.substr(t.indexOf("&")):"",a=this._$element.data("width")||560,s=this._$element.data("height")||a/(560/315);return this._showVideoIframe("//www.youtube.com/embed/"+i+"?badge=0&autoplay=1&html5=1"+o,a,s,e)}},{key:"_showVimeoVideo",value:function(t,e){var i=this._$element.data("width")||500,o=this._$element.data("height")||i/(560/315);return this._showVideoIframe(t+"?autoplay=1",i,o,e)}},{key:"_showInstagramVideo",value:function(t,e){var i=this._$element.data("width")||612,o=i+80;return t="/"!==t.substr(-1)?t+"/":t,e.html('<iframe width="'+i+'" height="'+o+'" src="'+t+'embed/" frameborder="0" allowfullscreen></iframe>'),this._resize(i,o),this._config.onContentLoaded.call(this),this._$modalArrows&&this._$modalArrows.css("display","none"),this._toggleLoading(!1),this}},{key:"_showVideoIframe",value:function(t,e,i,o){return i=i||e,o.html('<div class="embed-responsive embed-responsive-16by9"><iframe width="'+e+'" height="'+i+'" src="'+t+'" frameborder="0" allowfullscreen class="embed-responsive-item"></iframe></div>'),this._resize(e,i),this._config.onContentLoaded.call(this),this._$modalArrows&&this._$modalArrows.css("display","none"),this._toggleLoading(!1),this}},{key:"_showHtml5Media",value:function(t,e){var i=this._getRemoteContentType(t);if(!i)return this._error(this._config.strings.type);var o="";o=0<i.indexOf("audio")?"audio":"video";var a=this._$element.data("width")||560,s=this._$element.data("height")||a/(560/315);return e.html('<div class="embed-responsive embed-responsive-16by9"><'+o+' width="'+a+'" height="'+s+'" preload="auto" autoplay controls class="embed-responsive-item"><source src="'+t+'" type="'+i+'">'+this._config.strings.type+"</"+o+"></div>"),this._resize(a,s),this._config.onContentLoaded.call(this),this._$modalArrows&&this._$modalArrows.css("display","none"),this._toggleLoading(!1),this}},{key:"_loadRemoteContent",value:function(t,e){var i=this,o=this._$element.data("width")||560,a=this._$element.data("height")||560,s=this._$element.data("disableExternalCheck")||!1;return this._toggleLoading(!1),s||this._isExternal(t)?(e.html('<iframe src="'+t+'" frameborder="0" allowfullscreen></iframe>'),this._config.onContentLoaded.call(this)):e.load(t,c.proxy(function(){return i._$element.trigger("loaded.bs.modal")})),this._$modalArrows&&this._$modalArrows.css("display","none"),this._resize(o,a),this}},{key:"_isExternal",value:function(t){var e=t.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/);return"string"==typeof e[1]&&0<e[1].length&&e[1].toLowerCase()!==location.protocol||"string"==typeof e[2]&&0<e[2].length&&e[2].replace(new RegExp(":("+{"http:":80,"https:":443}[location.protocol]+")?$"),"")!==location.host}},{key:"_error",value:function(t){return console.error(t),this._containerToUse().html(t),this._resize(300,300),this}},{key:"_preloadImageByIndex",value:function(t,e){if(this._$galleryItems){var i=c(this._$galleryItems.get(t),!1);if(void 0!==i){var o=i.attr("data-remote")||i.attr("href");return("image"===i.attr("data-type")||this._isImage(o))&&this._preloadImage(o,!1),0<e?this._preloadImageByIndex(t+1,e-1):void 0}}}},{key:"_preloadImage",value:function(t,e){var i=this;e=e||!1;var o,a=new Image;return e&&(o=setTimeout(function(){e.append(i._config.loadingMessage)},200),a.onload=function(){o&&clearTimeout(o),o=null;var t=c("<img />");return t.attr("src",a.src),t.addClass("img-fluid"),t.css("width","100%"),e.html(t),i._$modalArrows&&i._$modalArrows.css("display",""),i._resize(a.width,a.height),i._toggleLoading(!1),i._config.onContentLoaded.call(i)},a.onerror=function(){return i._toggleLoading(!1),i._error(i._config.strings.fail+"  "+t)}),a.src=t,a}},{key:"_swipeGesure",value:function(){return this._touchendX<this._touchstartX?this.navigateRight():this._touchendX>this._touchstartX?this.navigateLeft():void 0}},{key:"_resize",value:function(t,e){e=e||t;var i=(this._wantedWidth=t)/(this._wantedHeight=e),o=this._padding.left+this._padding.right+this._border.left+this._border.right,a=575<this._config.doc.body.clientWidth?20:0,s=575<this._config.doc.body.clientWidth?0:20,n=Math.min(t+o,this._config.doc.body.clientWidth-a,this._config.maxWidth);n<t+o?(e=(n-o-s)/i,t=n):t+=o;var l=0,r=0;this._footerIsShown&&(r=this._$modalFooter.outerHeight(!0)||55),this._titleIsShown&&(l=this._$modalHeader.outerHeight(!0)||67);var d=this._padding.top+this._padding.bottom+this._border.bottom+this._border.top,h=parseFloat(this._$modalDialog.css("margin-top"))+parseFloat(this._$modalDialog.css("margin-bottom")),g=Math.min(e,c(window).height()-d-h-l-r,this._config.maxHeight-d-l-r);g<e&&(t=Math.ceil(g*i)+o),this._$lightboxContainer.css("height",g),this._$modalDialog.css("flex",1).css("maxWidth",t);var _=this._$modal.data("bs.modal");if(_)try{_._handleUpdate()}catch(t){_.handleUpdate()}return this}}],[{key:"_jQueryInterface",value:function(i){var o=this;return i=i||{},this.each(function(){var t=c(o),e=c.extend({},n.Default,t.data(),"object"==typeof i&&i);new n(o,e)})}}]),n}(),c.fn[i]=a._jQueryInterface,c.fn[i].Constructor=a,c.fn[i].noConflict=function(){return c.fn[i]=o,a._jQueryInterface}}(jQuery);
++function(t){"use strict";function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var i=function(){function t(t,e){for(var i=0;i<e.length;i++){var o=e[i];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,i,o){return i&&t(e.prototype,i),o&&t(e,o),e}}();!function(t){var o="ekkoLightbox",a=t.fn[o],s={title:"",footer:"",maxWidth:9999,maxHeight:9999,showArrows:!0,wrapping:!0,type:null,alwaysShowClose:!1,loadingMessage:'<div class="ekko-lightbox-loader"><div><div></div><div></div></div></div>',leftArrow:"<span>&#10094;</span>",rightArrow:"<span>&#10095;</span>",strings:{close:"Close",fail:"Failed to load image:",type:"Could not detect remote target type. Force the type using data-type"},doc:document,onShow:function(){},onShown:function(){},onHide:function(){},onHidden:function(){},onNavigate:function(){},onContentLoaded:function(){}},n=function(){function o(i,a){var n=this;e(this,o),this._config=t.extend({},s,a),this._$modalArrows=null,this._galleryIndex=0,this._galleryName=null,this._padding=null,this._border=null,this._titleIsShown=!1,this._footerIsShown=!1,this._wantedWidth=0,this._wantedHeight=0,this._touchstartX=0,this._touchendX=0,this._modalId="ekkoLightbox-"+Math.floor(1e3*Math.random()+1),this._$element=i instanceof jQuery?i:t(i),this._isBootstrap3=3==t.fn.modal.Constructor.VERSION[0];var l='<h4 class="modal-title">'+(this._config.title||"&nbsp;")+"</h4>",r='<button type="button" class="close" data-dismiss="modal" aria-label="'+this._config.strings.close+'"><span aria-hidden="true">&times;</span></button>',d='<div class="modal-dialog" role="document"><div class="modal-content">'+('<div class="modal-header'+(this._config.title||this._config.alwaysShowClose?"":" hide")+'">'+(this._isBootstrap3?r+l:l+r)+"</div>")+'<div class="modal-body"><div class="ekko-lightbox-container"><div class="ekko-lightbox-item fade in show"></div><div class="ekko-lightbox-item fade"></div></div></div>'+('<div class="modal-footer'+(this._config.footer?"":" hide")+'">'+(this._config.footer||"&nbsp;")+"</div>")+"</div></div>";t(this._config.doc.body).append('<div id="'+this._modalId+'" class="ekko-lightbox modal fade" tabindex="-1" tabindex="-1" role="dialog" aria-hidden="true">'+d+"</div>"),this._$modal=t("#"+this._modalId,this._config.doc),this._$modalDialog=this._$modal.find(".modal-dialog").first(),this._$modalContent=this._$modal.find(".modal-content").first(),this._$modalBody=this._$modal.find(".modal-body").first(),this._$modalHeader=this._$modal.find(".modal-header").first(),this._$modalFooter=this._$modal.find(".modal-footer").first(),this._$lightboxContainer=this._$modalBody.find(".ekko-lightbox-container").first(),this._$lightboxBodyOne=this._$lightboxContainer.find("> div:first-child").first(),this._$lightboxBodyTwo=this._$lightboxContainer.find("> div:last-child").first(),this._border=this._calculateBorders(),this._padding=this._calculatePadding(),this._galleryName=this._$element.data("gallery"),this._galleryName&&(this._$galleryItems=t(document.body).find('*[data-gallery="'+this._galleryName+'"]'),this._galleryIndex=this._$galleryItems.index(this._$element),t(document).on("keydown.ekkoLightbox",this._navigationalBinder.bind(this)),this._config.showArrows&&this._$galleryItems.length>1&&(this._$lightboxContainer.append('<div class="ekko-lightbox-nav-overlay"><a href="#">'+this._config.leftArrow+'</a><a href="#">'+this._config.rightArrow+"</a></div>"),this._$modalArrows=this._$lightboxContainer.find("div.ekko-lightbox-nav-overlay").first(),this._$lightboxContainer.on("click","a:first-child",function(t){return t.preventDefault(),n.navigateLeft()}),this._$lightboxContainer.on("click","a:last-child",function(t){return t.preventDefault(),n.navigateRight()}),this.updateNavigation())),this._$modal.on("show.bs.modal",this._config.onShow.bind(this)).on("shown.bs.modal",function(){return n._toggleLoading(!0),n._handle(),n._config.onShown.call(n)}).on("hide.bs.modal",this._config.onHide.bind(this)).on("hidden.bs.modal",function(){return n._galleryName&&(t(document).off("keydown.ekkoLightbox"),t(window).off("resize.ekkoLightbox")),n._$modal.remove(),n._config.onHidden.call(n)}).modal(this._config),t(window).on("resize.ekkoLightbox",function(){n._resize(n._wantedWidth,n._wantedHeight)}),this._$lightboxContainer.on("touchstart",function(){n._touchstartX=event.changedTouches[0].screenX}).on("touchend",function(){n._touchendX=event.changedTouches[0].screenX,n._swipeGesure()})}return i(o,null,[{key:"Default",get:function(){return s}}]),i(o,[{key:"element",value:function(){return this._$element}},{key:"modal",value:function(){return this._$modal}},{key:"navigateTo",value:function(e){if(e<0||e>this._$galleryItems.length-1)return this;this._galleryIndex=e,this.updateNavigation(),this._$element=t(this._$galleryItems.get(this._galleryIndex)),this._handle()}},{key:"navigateLeft",value:function(){if(this._$galleryItems&&1!==this._$galleryItems.length){if(0===this._galleryIndex){if(!this._config.wrapping)return;this._galleryIndex=this._$galleryItems.length-1}else this._galleryIndex--;return this._config.onNavigate.call(this,"left",this._galleryIndex),this.navigateTo(this._galleryIndex)}}},{key:"navigateRight",value:function(){if(this._$galleryItems&&1!==this._$galleryItems.length){if(this._galleryIndex===this._$galleryItems.length-1){if(!this._config.wrapping)return;this._galleryIndex=0}else this._galleryIndex++;return this._config.onNavigate.call(this,"right",this._galleryIndex),this.navigateTo(this._galleryIndex)}}},{key:"updateNavigation",value:function(){if(!this._config.wrapping){var t=this._$lightboxContainer.find("div.ekko-lightbox-nav-overlay");0===this._galleryIndex?t.find("a:first-child").addClass("disabled"):t.find("a:first-child").removeClass("disabled"),this._galleryIndex===this._$galleryItems.length-1?t.find("a:last-child").addClass("disabled"):t.find("a:last-child").removeClass("disabled")}}},{key:"close",value:function(){return this._$modal.modal("hide")}},{key:"_navigationalBinder",value:function(t){return 39===(t=t||window.event).keyCode?this.navigateRight():37===t.keyCode?this.navigateLeft():void 0}},{key:"_detectRemoteType",value:function(t,e){return!(e=e||!1)&&this._isImage(t)&&(e="image"),!e&&this._getYoutubeId(t)&&(e="youtube"),!e&&this._getVimeoId(t)&&(e="vimeo"),!e&&this._getInstagramId(t)&&(e="instagram"),("audio"==e||"video"==e||!e&&this._isMedia(t))&&(e="media"),(!e||["image","youtube","vimeo","instagram","media","url"].indexOf(e)<0)&&(e="url"),e}},{key:"_getRemoteContentType",value:function(e){return t.ajax({type:"HEAD",url:e,async:!1}).getResponseHeader("Content-Type")}},{key:"_isImage",value:function(t){return t&&t.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)}},{key:"_isMedia",value:function(t){return t&&t.match(/(\.(mp3|mp4|ogg|webm|wav)((\?|#).*)?$)/i)}},{key:"_containerToUse",value:function(){var t=this,e=this._$lightboxBodyTwo,i=this._$lightboxBodyOne;return this._$lightboxBodyTwo.hasClass("in")&&(e=this._$lightboxBodyOne,i=this._$lightboxBodyTwo),i.removeClass("in show"),setTimeout(function(){t._$lightboxBodyTwo.hasClass("in")||t._$lightboxBodyTwo.empty(),t._$lightboxBodyOne.hasClass("in")||t._$lightboxBodyOne.empty()},500),e.addClass("in show"),e}},{key:"_handle",value:function(){var t=this._containerToUse();this._updateTitleAndFooter();var e=this._$element.attr("data-remote")||this._$element.attr("href"),i=this._detectRemoteType(e,this._$element.attr("data-type")||!1);if(["image","youtube","vimeo","instagram","media","url"].indexOf(i)<0)return this._error(this._config.strings.type);switch(i){case"image":this._preloadImage(e,t),this._preloadImageByIndex(this._galleryIndex,3);break;case"youtube":this._showYoutubeVideo(e,t);break;case"vimeo":this._showVimeoVideo(this._getVimeoId(e),t);break;case"instagram":this._showInstagramVideo(this._getInstagramId(e),t);break;case"media":this._showHtml5Media(e,t);break;default:this._loadRemoteContent(e,t)}return this}},{key:"_getYoutubeId",value:function(t){if(!t)return!1;var e=t.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/);return!(!e||11!==e[2].length)&&e[2]}},{key:"_getVimeoId",value:function(t){return!!(t&&t.indexOf("vimeo")>0)&&t}},{key:"_getInstagramId",value:function(t){return!!(t&&t.indexOf("instagram")>0)&&t}},{key:"_toggleLoading",value:function(e){return(e=e||!1)?(this._$modalDialog.css("display","none"),this._$modal.removeClass("in show"),t(".modal-backdrop").append(this._config.loadingMessage)):(this._$modalDialog.css("display","block"),this._$modal.addClass("in show"),t(".modal-backdrop").find(".ekko-lightbox-loader").remove()),this}},{key:"_calculateBorders",value:function(){return{top:this._totalCssByAttribute("border-top-width"),right:this._totalCssByAttribute("border-right-width"),bottom:this._totalCssByAttribute("border-bottom-width"),left:this._totalCssByAttribute("border-left-width")}}},{key:"_calculatePadding",value:function(){return{top:this._totalCssByAttribute("padding-top"),right:this._totalCssByAttribute("padding-right"),bottom:this._totalCssByAttribute("padding-bottom"),left:this._totalCssByAttribute("padding-left")}}},{key:"_totalCssByAttribute",value:function(t){return parseInt(this._$modalDialog.css(t),10)+parseInt(this._$modalContent.css(t),10)+parseInt(this._$modalBody.css(t),10)}},{key:"_updateTitleAndFooter",value:function(){var t=this._$element.data("title")||"",e=this._$element.data("footer")||"";return this._titleIsShown=!1,t||this._config.alwaysShowClose?(this._titleIsShown=!0,this._$modalHeader.css("display","").find(".modal-title").html(t||"&nbsp;")):this._$modalHeader.css("display","none"),this._footerIsShown=!1,e?(this._footerIsShown=!0,this._$modalFooter.css("display","").html(e)):this._$modalFooter.css("display","none"),this}},{key:"_showYoutubeVideo",value:function(t,e){var i=this._getYoutubeId(t),o=t.indexOf("&")>0?t.substr(t.indexOf("&")):"",a=this._$element.data("width")||560,s=this._$element.data("height")||a/(560/315);return this._showVideoIframe("//www.youtube.com/embed/"+i+"?badge=0&autoplay=1&html5=1"+o,a,s,e)}},{key:"_showVimeoVideo",value:function(t,e){var i=this._$element.data("width")||500,o=this._$element.data("height")||i/(560/315);return this._showVideoIframe(t+"?autoplay=1",i,o,e)}},{key:"_showInstagramVideo",value:function(t,e){var i=this._$element.data("width")||612,o=i+80;return t="/"!==t.substr(-1)?t+"/":t,e.html('<iframe width="'+i+'" height="'+o+'" src="'+t+'embed/" frameborder="0" allowfullscreen></iframe>'),this._resize(i,o),this._config.onContentLoaded.call(this),this._$modalArrows&&this._$modalArrows.css("display","none"),this._toggleLoading(!1),this}},{key:"_showVideoIframe",value:function(t,e,i,o){return i=i||e,o.html('<div class="embed-responsive embed-responsive-16by9"><iframe width="'+e+'" height="'+i+'" src="'+t+'" frameborder="0" allowfullscreen class="embed-responsive-item"></iframe></div>'),this._resize(e,i),this._config.onContentLoaded.call(this),this._$modalArrows&&this._$modalArrows.css("display","none"),this._toggleLoading(!1),this}},{key:"_showHtml5Media",value:function(t,e){var i=this._getRemoteContentType(t);if(!i)return this._error(this._config.strings.type);var o="";o=i.indexOf("audio")>0?"audio":"video";var a=this._$element.data("width")||560,s=this._$element.data("height")||a/(560/315);return e.html('<div class="embed-responsive embed-responsive-16by9"><'+o+' width="'+a+'" height="'+s+'" preload="auto" autoplay controls class="embed-responsive-item"><source src="'+t+'" type="'+i+'">'+this._config.strings.type+"</"+o+"></div>"),this._resize(a,s),this._config.onContentLoaded.call(this),this._$modalArrows&&this._$modalArrows.css("display","none"),this._toggleLoading(!1),this}},{key:"_loadRemoteContent",value:function(e,i){var o=this,a=this._$element.data("width")||560,s=this._$element.data("height")||560,n=this._$element.data("disableExternalCheck")||!1;return this._toggleLoading(!1),n||this._isExternal(e)?(i.html('<iframe src="'+e+'" frameborder="0" allowfullscreen></iframe>'),this._config.onContentLoaded.call(this)):i.load(e,t.proxy(function(){return o._$element.trigger("loaded.bs.modal")})),this._$modalArrows&&this._$modalArrows.css("display","none"),this._resize(a,s),this}},{key:"_isExternal",value:function(t){var e=t.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/);return"string"==typeof e[1]&&e[1].length>0&&e[1].toLowerCase()!==location.protocol||"string"==typeof e[2]&&e[2].length>0&&e[2].replace(new RegExp(":("+{"http:":80,"https:":443}[location.protocol]+")?$"),"")!==location.host}},{key:"_error",value:function(t){return console.error(t),this._containerToUse().html(t),this._resize(300,300),this}},{key:"_preloadImageByIndex",value:function(e,i){if(this._$galleryItems){var o=t(this._$galleryItems.get(e),!1);if(void 0!==o){var a=o.attr("data-remote")||o.attr("href");return("image"===o.attr("data-type")||this._isImage(a))&&this._preloadImage(a,!1),i>0?this._preloadImageByIndex(e+1,i-1):void 0}}}},{key:"_preloadImage",value:function(e,i){var o=this;i=i||!1;var a=new Image;return i&&function(){var s=setTimeout(function(){i.append(o._config.loadingMessage)},200);a.onload=function(){s&&clearTimeout(s),s=null;var e=t("<img />");return e.attr("src",a.src),e.addClass("img-fluid"),e.css("width","100%"),i.html(e),o._$modalArrows&&o._$modalArrows.css("display",""),o._resize(a.width,a.height),o._toggleLoading(!1),o._config.onContentLoaded.call(o)},a.onerror=function(){return o._toggleLoading(!1),o._error(o._config.strings.fail+"  "+e)}}(),a.src=e,a}},{key:"_swipeGesure",value:function(){return this._touchendX<this._touchstartX?this.navigateRight():this._touchendX>this._touchstartX?this.navigateLeft():void 0}},{key:"_resize",value:function(e,i){i=i||e,this._wantedWidth=e,this._wantedHeight=i;var o=e/i,a=this._padding.left+this._padding.right+this._border.left+this._border.right,s=this._config.doc.body.clientWidth>575?20:0,n=this._config.doc.body.clientWidth>575?0:20,l=Math.min(e+a,this._config.doc.body.clientWidth-s,this._config.maxWidth);e+a>l?(i=(l-a-n)/o,e=l):e+=a;var r=0,d=0;this._footerIsShown&&(d=this._$modalFooter.outerHeight(!0)||55),this._titleIsShown&&(r=this._$modalHeader.outerHeight(!0)||67);var h=this._padding.top+this._padding.bottom+this._border.bottom+this._border.top,g=parseFloat(this._$modalDialog.css("margin-top"))+parseFloat(this._$modalDialog.css("margin-bottom")),_=Math.min(i,t(window).height()-h-g-r-d,this._config.maxHeight-h-r-d);i>_&&(e=Math.ceil(_*o)+a),this._$lightboxContainer.css("height",_),this._$modalDialog.css("flex",1).css("maxWidth",e);var c=this._$modal.data("bs.modal");if(c)try{c._handleUpdate()}catch(t){c.handleUpdate()}return this}}],[{key:"_jQueryInterface",value:function(e){var i=this;return e=e||{},this.each(function(){var a=t(i),s=t.extend({},o.Default,a.data(),"object"==typeof e&&e);new o(i,s)})}}]),o}();t.fn[o]=n._jQueryInterface,t.fn[o].Constructor=n,t.fn[o].noConflict=function(){return t.fn[o]=a,n._jQueryInterface}}(jQuery)}(jQuery);
--- a/src/pyams_default_theme/resources/less/pyams-default.less	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/resources/less/pyams-default.less	Tue Dec 04 15:53:25 2018 +0100
@@ -18,68 +18,7 @@
 body {
 	font-family: Lato, Helvetica, Arial, sans-serif;
 	margin: 0 auto;
-
-	.header-simple {
-		.regularbanner {
-			position: relative;
-
-			picture,
-			img {
-				&.regularbanner__media {
-					width: 100%;
-				}
-				&.logo {
-					position: absolute;
-					top: 10px;
-					left: 10px;
-					max-height: ~"calc(100% - 20px)";
-				}
-			}
-		}
-	}
-	.affix {
-		top: 0;
-		width: 100%;
-		z-index: 9999 !important;
-		opacity: 0.95;
-		transition: all .5s ease-in-out;
-	}
-	.affix ~ .container-fluid {
-		position: relative;
-		top: 50px;
-	}
-	.navbar {
-		margin-bottom: 20px;
-		background-color: white;
-		border: 1px solid #39413b;
-		font-family: Oswald, Helvetica, Arial, Sans-Serif;
-		transition: all .5s ease-in-out;
-
-		a,
-		a:active,
-		a:visited {
-			color: #39413b;
-		}
-		li.active,
-		.icon-bar {
-			background-color: #a5bcaa;
-		}
-		&.affix {
-			background-color: #39413b;
-
-			a {
-				color: white;
-			}
-			&:hover {
-				a:hover {
-					color: #39413b;
-				}
-			}
-			.icon-bar {
-				background-color: white;
-			}
-		}
-	}
+	overflow-x: hidden;
 }
 
 h1,
@@ -91,6 +30,95 @@
 	font-family: Oswald, Helvetica, Arial, Sans-Serif;
 }
 
+hr {
+	&.simple {
+		margin-top: 10px;
+		margin-bottom: 10px;
+	}
+	&.noborder {
+		border: 0;
+	}
+}
+
+
+/**
+ * Header styles
+ */
+.header-simple {
+	.regularbanner {
+		position: relative;
+
+		picture,
+		img {
+			&.regularbanner__media {
+				width: 100%;
+			}
+			&.logo {
+				position: absolute;
+				top: 10px;
+				left: 10px;
+				max-height: ~"calc(100% - 20px)";
+			}
+		}
+	}
+}
+.affix {
+	top: 0;
+	width: 100%;
+	z-index: 9999 !important;
+	opacity: 0.95;
+	transition: all .5s ease-in-out;
+}
+.affix ~ .container-fluid {
+	position: relative;
+	top: 50px;
+}
+.navbar {
+	margin-bottom: 20px;
+	background-color: white;
+	border: 1px solid #39413b;
+	font-family: Oswald, Helvetica, Arial, Sans-Serif;
+	transition: all .5s ease-in-out;
+
+	a,
+	a:active,
+	a:visited {
+		color: #39413b;
+	}
+	li.active,
+	.icon-bar {
+		background-color: #a5bcaa;
+	}
+	&.affix {
+		background-color: #39413b;
+
+		a {
+			color: white;
+		}
+		.dropdown-menu {
+			a {
+				color: #39413b;
+			}
+		}
+		&:hover {
+			a:hover {
+				color: #39413b;
+			}
+		}
+		.icon-bar {
+			background-color: white;
+		}
+	}
+}
+
+.breadcrumb {
+	margin-bottom: 1rem;
+}
+
+.page-header {
+	margin-top: 2rem;
+}
+
 .portal-page {
 	.slot {
 		@media only screen and (min-width: 1200px) {
@@ -116,6 +144,62 @@
 	}
 }
 
+.toolbox {
+	display: flex;
+	flex-direction: column;
+
+	button {
+		text-align: left;
+		display: flex;
+		align-items: center;
+
+		i.fa {
+			display: inline-block;
+			margin-right: 1rem;
+		}
+	}
+}
+
+@media only screen and (min-width: 1340px) {
+	.col-lg-12 .portlet > section.wrapper {
+		margin-left: calc(-50vw + 50%);
+		margin-right: calc(-50vw + 50%);
+	}
+}
+
+@media only screen and (min-width: 1052px) {
+	.col-md-12 .portlet > section.wrapper {
+		margin-left: calc(-50vw + 50%);
+		margin-right: calc(-50vw + 50%);
+	}
+}
+
+@media only screen and (max-width: 1051px) {
+	.col-sm-12 .portlet > section.wrapper {
+		margin-left: calc(-50vw + 50%);
+		margin-right: calc(-50vw + 50%);
+	}
+}
+
+@media only screen and (max-width: 767px) {
+	.navbar {
+		&.affix {
+			.dropdown-menu {
+				background-color: #39413b;
+
+				a {
+					color: white;
+				}
+			}
+		}
+	}
+
+	.col-xs-12 .portlet > section.wrapper {
+		margin-left: calc(-50vw + 50%);
+		margin-right: calc(-50vw + 50%);
+	}
+}
+
 
 /**
  * Summary styles
@@ -142,6 +226,37 @@
 	}
 }
 
+
+/**
+ * Panels
+ */
+.panels {
+	margin-top: 2rem;
+}
+
+
+/**
+ * Search results
+ */
+
+.search-results {
+	.breadcrumb:empty {
+		margin: 0;
+		padding: 0;
+	}
+	.thumbnail {
+		&.pull-left {
+			margin-right: 3rem;
+		}
+	}
+	.tags {
+		span {
+			margin: 0 0.2rem;
+		}
+	}
+}
+
+
 /**
  * Images gallery
  */
@@ -260,3 +375,14 @@
 		}
 	}
 }
+
+
+/**
+ * Source code
+ */
+
+.source {
+	pre {
+		font-family: 'Anonymous Pro', monospace;
+	}
+}
--- a/src/pyams_default_theme/shared/common/portlet/head.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/shared/common/portlet/head.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,19 +12,14 @@
 
 __docformat__ = 'restructuredtext'
 
+from zope.interface import Interface
 
-# import standard library
-
-# import interfaces
 from pyams_content.shared.common.portlet.interfaces import ISharedContentHeaderPortletSettings
 from pyams_portal.interfaces import IPortalContext, IPortletRenderer
+from pyams_portal.portlet import PortletRenderer
 from pyams_skin.layer import IPyAMSLayer
-
-# import packages
-from pyams_portal.portlet import PortletRenderer
 from pyams_template.template import template_config
 from pyams_utils.adapter import adapter_config
-from zope.interface import Interface
 
 from pyams_default_theme import _
 
--- a/src/pyams_default_theme/shared/site/link.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/shared/site/link.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,8 +12,9 @@
 
 __docformat__ = 'restructuredtext'
 
-from pyams_content.shared.site.interfaces import IContentLink
-from pyams_default_theme.interfaces import IContentSummaryInfo
+from pyams_content.component.illustration import ILinkIllustration
+from pyams_content.shared.site.interfaces import IContentLink, IExternalContentLink
+from pyams_default_theme.interfaces import IContentNavigationIllustration, IContentSummaryInfo
 from pyams_i18n.interfaces import II18n
 from pyams_skin.layer import IPyAMSUserLayer
 from pyams_utils.adapter import ContextRequestAdapter, adapter_config
@@ -22,6 +23,10 @@
 from pyams_default_theme import _
 
 
+#
+# Content link adapters
+#
+
 @adapter_config(context=(IContentLink, IPyAMSUserLayer), provides=IRelativeURL)
 def content_link_relative_url(context, request):
     """Content link relative URL"""
@@ -64,3 +69,46 @@
         if not title:
             title = _("Consult content")
         return self.request.localizer.translate(title)
+
+
+@adapter_config(context=(IContentLink, IPyAMSUserLayer), provides=IContentNavigationIllustration)
+def content_link_illustration_factory(context, request):
+    """Content link illustration factory"""
+    target = context.target
+    if target is not None:
+        return request.registry.queryMultiAdapter((target, request), IContentNavigationIllustration)
+
+
+#
+# External content link adapters
+#
+
+@adapter_config(context=(IExternalContentLink, IPyAMSUserLayer), provides=IRelativeURL)
+class ExternalContentLinkRelativeUrl(ContextRequestAdapter):
+    """External content link relative URL"""
+
+    def get_url(self, display_context=None, view_name=None, query=None):
+        return self.context.url
+
+
+@adapter_config(context=(IExternalContentLink, IPyAMSUserLayer), provides=IContentSummaryInfo)
+class ExternalContentLinkSummaryAdapter(ContextRequestAdapter):
+    """External content link summary adapter"""
+
+    @property
+    def title(self):
+        return II18n(self.context).query_attribute('navigation_title', request=self.request)
+
+    @property
+    def header(self):
+        return II18n(self.context).query_attribute('navigation_header', request=self.request)
+
+    @property
+    def button_title(self):
+        return self.request.localizer.translate(_("Consult content"))
+
+
+@adapter_config(context=(IExternalContentLink, IPyAMSUserLayer), provides=IContentNavigationIllustration)
+def external_content_link_illustration_factory(context, request):
+    """External content link illustration factory"""
+    return request.registry.queryAdapter(context, ILinkIllustration)
--- a/src/pyams_default_theme/shared/site/portlet/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/shared/site/portlet/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -26,13 +26,8 @@
 from pyams_default_theme import _
 
 
-@adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, ISiteContainerSummaryPortletSettings),
-                provides=IPortletRenderer)
-@template_config(template='templates/site-summary.pt', layer=IPyAMSLayer)
-class SiteContainerSummaryPortletDefaultRenderer(PortletRenderer):
-    """Site container summary portlet default renderer"""
-
-    label = _("Site container summary")
+class BaseSiteSummaryPortletRenderer(PortletRenderer):
+    """Base site summary portlet renderer"""
 
     @property
     def visible_items(self):
@@ -42,3 +37,22 @@
             yield from filter(lambda x: x is not None,
                               [registry.queryMultiAdapter((item, self.request), IContentSummaryInfo)
                                for item in container.get_visible_items(self.request)])
+
+
+@adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, ISiteContainerSummaryPortletSettings),
+                provides=IPortletRenderer)
+@template_config(template='templates/site-summary.pt', layer=IPyAMSLayer)
+class SiteContainerSummaryPortletDefaultRenderer(BaseSiteSummaryPortletRenderer):
+    """Site container summary portlet default renderer"""
+
+    label = _("Site container summary")
+
+
+@adapter_config(name='summary-panels',
+                context=(IPortalContext, IPyAMSLayer, Interface, ISiteContainerSummaryPortletSettings),
+                provides=IPortletRenderer)
+@template_config(template='templates/site-panels.pt', layer=IPyAMSLayer)
+class SiteContainerSummaryPortletPanelsRenderer(BaseSiteSummaryPortletRenderer):
+    """Site container summary portlet panels renderer"""
+
+    label = _("Vertical panels with panoramic illustrations")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/shared/site/portlet/templates/site-panels.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,35 @@
+<div class="panels" i18n:domain="pyams_default_theme"
+	 tal:define="settings view.settings;
+				 button_title i18n:settings.button_title;">
+	<h2 tal:condition="settings.title">${i18n:settings.title}</h2>
+	<div tal:repeat="item view.visible_items"
+		 class="col-sm-4">
+		<tal:var define="target tales:relative_url(item.context)">
+			<div class="thumbnail pull-left hidden-xs">
+				<a tal:define="illustration tales:pyams_illustration(item.context)"
+				   tal:condition="illustration"
+				   href="${target}">
+					<tal:if define="image i18n:illustration.data;
+									alt i18n:illustration.alt_title;"
+							condition="image">
+						${structure:tales:picture(image, lg_thumb='pano', lg_width=4, md_thumb='pano', md_width=4,
+												  sm_thumb='pano', sm_width=4, xs_thumb='pano', xs_width=12, alt=alt)}
+					</tal:if>
+				</a>
+			</div>
+			<div>
+				<a href="${target}">
+					<h3>${item.title}</h3>
+				</a>
+				<div class="header">${structure:tales:html(item.header)}</div>
+				<div class="action">
+					<a tal:condition="button_title"
+					   href="${target}">
+						<span i18n:translate="">${button_title}</span>
+					</a>
+				</div>
+			</div>
+		</tal:var>
+	</div>
+	<div class="clearfix"></div>
+</div>
\ No newline at end of file
--- a/src/pyams_default_theme/shared/site/portlet/templates/site-summary.pt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/shared/site/portlet/templates/site-summary.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -1,6 +1,7 @@
 <div i18n:domain="pyams_default_theme"
 	 tal:define="settings view.settings;
 				 button_title i18n:settings.button_title;">
+	<h2 tal:condition="settings.title">${i18n:settings.title}</h2>
 	<div class="summary">
 		<div tal:repeat="item view.visible_items">
 			<tal:var define="target tales:relative_url(item.context)">
@@ -17,7 +18,9 @@
 					</a>
 				</div>
 				<div>
-					<h2>${item.title}</h2>
+					<a href="${target}">
+						<h3>${item.title}</h3>
+					</a>
 					<div class="header">${structure:tales:html(item.header)}</div>
 					<div class="action">
 						<a href="${target}">
--- a/src/pyams_default_theme/shared/view/portlet/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/shared/view/portlet/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,23 +12,33 @@
 
 __docformat__ = 'restructuredtext'
 
+from persistent import Persistent
+from zope.container.contained import Contained
+from zope.interface import Interface, implementer
+from zope.schema.fieldproperty import FieldProperty
 
-# import standard library
-
-# import interfaces
 from pyams_content.shared.view.portlet.interfaces import IViewItemsPortletSettings
+from pyams_default_theme.shared.view.portlet.interfaces import IViewItemsPortletVerticalRendererSettings
 from pyams_portal.interfaces import IPortalContext, IPortletRenderer
+from pyams_portal.portlet import PortletRenderer
 from pyams_skin.layer import IPyAMSLayer
-
-# import packages
-from pyams_portal.portlet import PortletRenderer
 from pyams_template.template import template_config
 from pyams_utils.adapter import adapter_config
-from zope.interface import Interface
+from pyams_utils.factory import factory_config
 
 from pyams_default_theme import _
 
 
+@factory_config(provided=IViewItemsPortletVerticalRendererSettings)
+@implementer(IViewItemsPortletVerticalRendererSettings)
+class ViewItemsPortletVerticalRendererSettings(Persistent, Contained):
+    """View items portlet renderer settings"""
+
+    display_illustrations = FieldProperty(IViewItemsPortletVerticalRendererSettings['display_illustrations'])
+    paginate = FieldProperty(IViewItemsPortletVerticalRendererSettings['paginate'])
+    page_size = FieldProperty(IViewItemsPortletVerticalRendererSettings['page_size'])
+
+
 @adapter_config(context=(IPortalContext, IPyAMSLayer, Interface, IViewItemsPortletSettings),
                 provides=IPortletRenderer)
 @template_config(template='templates/view-items-list.pt', layer=IPyAMSLayer)
@@ -36,3 +46,6 @@
     """View items portlet renderer"""
 
     label = _("Simple vertical view")
+    weight = 0
+
+    settings_interface = IViewItemsPortletVerticalRendererSettings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_default_theme/shared/view/portlet/interfaces.py	Tue Dec 04 15:53:25 2018 +0100
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2008-2018 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+from zope.interface import Interface
+from zope.schema import Bool, Int
+
+from pyams_default_theme import _
+
+
+class IViewItemsPortletVerticalRendererSettings(Interface):
+    """View items portlet vertical renderer settings interface"""
+
+    display_illustrations = Bool(title=_("Display illustrations?"),
+                                 description=_("If 'no', view contents will not display illustrations"),
+                                 required=True,
+                                 default=True)
+
+    paginate = Bool(title=_("Paginate?"),
+                    description=_("If 'no', results pagination will be disabled"),
+                    required=True,
+                    default=True)
+
+    page_size = Int(title=_("Page size"),
+                    description=_("Number of items per page, if pagination is enabled"),
+                    required=False,
+                    default=10)
--- a/src/pyams_default_theme/shared/view/portlet/templates/view-items-list.pt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/shared/view/portlet/templates/view-items-list.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -1,6 +1,60 @@
-<ul>
-	<li tal:repeat="item view.settings.get_items(request)">
-		<a tal:attributes="href tales:relative_url(item)"
-		   tal:content="i18n:item.title">Title</a>
-	</li>
-</ul>
+<div tal:define="settings view.settings;
+				 renderer_settings view.renderer_settings;"
+	 i18n:domain="pyams_default_theme">
+	<h2>${i18n:settings.title}</h2>
+	<div class="search-results"
+		 tal:define="start int(request.params.get('start', 0));
+					 limit (start + renderer_settings.page_size) if renderer_settings.paginate else 999;
+					 items settings.get_items(request, limit);
+					 global count 0;">
+		<tal:loop repeat="item items">
+			<div tal:define="global count count +1;
+							 target tales:relative_url(item);">
+				<tal:if condition="renderer_settings.display_illustrations">
+					<div class="thumbnail pull-left col-lg-3 col-md-3 col-sm-4 hidden-xs"
+						 tal:define="illustration tales:pyams_illustration(item)"
+						 tal:condition="illustration">
+						<a href="${target}">
+							<tal:if define="image i18n:illustration.data;
+											alt i18n:illustration.alt_title;"
+									condition="image">
+								${structure:tales:picture(image, lg_thumb='pano', lg_width=3, md_thumb='pano', md_width=3, sm_thumb='pano',
+														  sm_width=4, xs_thumb='pano', xs_width=12, alt=alt, css_class='result_media')}
+							</tal:if>
+						</a>
+					</div>
+				</tal:if>
+				<div>
+					<a href="${target}">
+						<h3>${i18n:item.title}</h3>
+					</a>
+					<div class="breadcrumbs">${structure:tales:breadcrumbs(item)}</div>
+					<div class="tags">${structure:tales:tags(item)}</div>
+					<div class="header"
+						 tal:define="header i18n:item.header">
+						${structure:tales:html(header)}
+					</div>
+				</div>
+			</div>
+			<div class="clearfix"></div>
+		</tal:loop>
+		<footer tal:condition="renderer_settings.paginate">
+			<ul class="pager">
+				<li class="previous"
+					tal:condition="start > 0">
+					<a href="${request.path_url}?start=${start - renderer_settings.page_size}">
+						<span aria-hidden="true">&larr;</span>
+						<i18n:var translate="">Previous</i18n:var>
+					</a>
+				</li>
+				<li class="next"
+					tal:condition="count == renderer_settings.page_size">
+					<a href="${request.path_url}?start=${start + count}">
+						<i18n:var translate="">Next</i18n:var>
+						<span aria-hidden="true">&rarr;</span>
+					</a>
+				</li>
+			</ul>
+		</footer>
+	</div>
+</div>
--- a/src/pyams_default_theme/viewlet/breadcrumb/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/viewlet/breadcrumb/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -12,36 +12,29 @@
 
 __docformat__ = 'restructuredtext'
 
-from pyramid.location import lineage
 from zope.interface import Interface
+from zope.location import ILocation
 
-from pyams_skin.interfaces.viewlet import IBreadcrumbItem
+from pyams_skin.interfaces.viewlet import IBreadcrumbs
 from pyams_skin.layer import IPyAMSUserLayer
-from pyams_skin.viewlet.breadcrumb import BreadcrumbsContentProvider as BaseBreadcrumbsContentProvider
-from pyams_template.template import template_config
+from pyams_skin.viewlet.breadcrumb import BreadcrumbsContentProvider, BreadcrumbsAdapter as BaseBreadcrumbsAdapter
+from pyams_template.template import override_template
+from pyams_utils.adapter import adapter_config
 from pyams_utils.interfaces.url import DISPLAY_CONTEXT
-from pyams_viewlet.viewlet import contentprovider_config
 
 
-@contentprovider_config(name='pyams.breadcrumbs', layer=IPyAMSUserLayer, view=Interface)
-@template_config(template='breadcrumbs.pt', layer=IPyAMSUserLayer)
-class BreadcrumbsContentProvider(BaseBreadcrumbsContentProvider):
-    """Breadcrumbs content provider"""
+@adapter_config(context=(ILocation, IPyAMSUserLayer, Interface), provides=IBreadcrumbs)
+class BreadcrumbsAdapter(BaseBreadcrumbsAdapter):
+    """Breadcrumbs adapter"""
 
     @property
     def items(self):
-        source = None
-        registry = self.request.registry
+        source = self.request.annotations.get(DISPLAY_CONTEXT)
         if source is None:
-            source = self.request.annotations.get(DISPLAY_CONTEXT)
-            if source is None:
-                source = self.request.context
+            source = self.request.context
         if source is not None:
-            for context in reversed(tuple(lineage(source))):
-                item = registry.queryMultiAdapter((context, self.request, self.view), IBreadcrumbItem)
-                if item is None:
-                    item = registry.queryMultiAdapter((context, self.request), IBreadcrumbItem)
-                    if item is None:
-                        item = registry.queryAdapter(context, IBreadcrumbItem)
-                if item is not None:
-                    yield item
+            yield from self.get_items(source)
+
+
+override_template(context=BreadcrumbsContentProvider, layer=IPyAMSUserLayer,
+                  template='breadcrumbs.pt')
--- a/src/pyams_default_theme/viewlet/breadcrumb/breadcrumbs.pt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/viewlet/breadcrumb/breadcrumbs.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -1,6 +1,5 @@
-<ol class="breadcrumb">
-	<li tal:repeat="item view.items">
-		<a class="${'active' if repeat.item.end else None}"
-		   href="${item.url}">${item.label}</a>
-	</li>
-</ol>
\ No newline at end of file
+<ol class="breadcrumb"><li
+	tal:repeat="item view.items"><a
+		tal:omit-tag="not:item.label"
+		class="${'active' if repeat.item.end else None}"
+		   href="${item.url}">${item.label}</a></li></ol>
\ No newline at end of file
--- a/src/pyams_default_theme/viewlet/tag/__init__.py	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/viewlet/tag/__init__.py	Tue Dec 04 15:53:25 2018 +0100
@@ -10,16 +10,18 @@
 # FOR A PARTICULAR PURPOSE.
 #
 
-
 __docformat__ = 'restructuredtext'
 
 from pyramid.decorator import reify
+from zope.contentprovider.interfaces import IContentProvider
 from zope.interface import Interface
 
 from pyams_content.component.theme import ITagsInfo, ITagsManager
 from pyams_sequence.reference import get_reference_target
 from pyams_skin.layer import IPyAMSLayer, IPyAMSUserLayer
 from pyams_template.template import template_config
+from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
+from pyams_utils.interfaces.tales import ITALESExtension
 from pyams_viewlet.viewlet import ViewContentProvider, contentprovider_config
 
 
@@ -49,3 +51,19 @@
     def tags(self):
         tags = self.tags_info.tags or ()
         yield from sorted(tags, key=lambda x: (x.order or 999, x.alt or x.label))
+
+
+@adapter_config(name='tags', context=(Interface, Interface, Interface), provides=ITALESExtension)
+class TagsTalesExtension(ContextRequestViewAdapter):
+    """tales:tags(context) TALES extension"""
+
+    def render(self, context=None):
+        if context is None:
+            context = self.context
+        provider = self.request.registry.queryMultiAdapter((context, self.request, self.view), IContentProvider,
+                                                           name='pyams.tags')
+        if provider is not None:
+            provider.update()
+            return provider.render()
+        else:
+            return ''
--- a/src/pyams_default_theme/viewlet/tag/templates/tags.pt	Tue Nov 20 15:19:28 2018 +0100
+++ b/src/pyams_default_theme/viewlet/tag/templates/tags.pt	Tue Dec 04 15:53:25 2018 +0100
@@ -1,12 +1,12 @@
 <div i18n:domain="pyams_default_theme"
 	 tal:define="target view.search_target">
 	<tal:loop repeat="tag view.tags">
-		<span class="label label-primary">
-			<a tal:omit-tag="target is None"
-			   tal:define="href tales:absolute_url(target)"
-			   href="${href}/++tag++${tag.label}">
-				${tag.alt or tag.label}
-			</a>
-		</span>
+		<a tal:omit-tag="target is None"
+		   tal:define="href tales:absolute_url(target)"
+		   href="${href}?tag=${tag.label}">
+			<span class="badge badge-primary">
+				#${tag.alt or tag.label}
+			</span>
+		</a>
 	</tal:loop>
 </div>
\ No newline at end of file