[MERGE] Forward-port of branch 12.0 to 13.0

This commit is contained in:
Antoine Vandevenne (anv) 2021-05-28 17:31:45 +02:00
commit 4ca0d019c7
9 changed files with 225 additions and 147 deletions

View File

@ -60,7 +60,8 @@ Then set your email domain name in the General Settings.
Can I use an Office 365 server
------------------------------
You can use an Office 365 server if you run Odoo on-premise.
Office 365 SMTP relays are not compatible with Odoo Online.
Office 365 SMTP relays are not compatible with Odoo Online unless you configure
Odoo to force the outgoing "From" address (see below).
Please refer to `Microsoft's documentation <https://support.office.com/en-us/article/How-to-set-up-a-multifunction-device-or-application-to-send-email-using-Office-365-69f58e99-c550-4274-ad18-c805d654b4c4>`__
to configure a SMTP relay for your Odoo's IP address.
@ -108,6 +109,48 @@ Restriction
-----------
Please note that the port 25 is blocked for security reasons. Try using 587, 465 or 2525.
Choose allowed "From" email addresses
-------------------------------------
Sometimes, an email's "From" (outgoing) address can belong to a different
domain, and that can be a problem.
For example, if a customer with address *mary@customer.example.com* responds to
a message, Odoo will try to redistribute that same email to other subscribers
in the thread. But if the domain *customer.example.com* forbids that kind of
usage for security (kudos for that), the Odoo's redistributed email would get
rejected by some recipients' mail servers.
To avoid those kind of problems, you should make sure all emails use a "From"
address from your authorized domain.
If your MTA supports `SRS (Sender Rewriting Scheme)
<https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme>`_, you can enable it
to handle these situations. However, that is more complex and requires more
technical knowledge that is not meant to be covered by this documentation.
Instead, you can also configure Odoo to do something similar by itself:
#. Set your domain name in the General Settings.
.. image:: media/alias_domain.png
:align: center
#. In developer mode, go to :menuselection:`Settings --> Technical -->
Parameters --> System Parameters`.
#. Add one system parameter from these:
* If you want *all* your outgoing messages to use the same "From" address,
use the key ``mail.force.smtp.from`` and set that address as value
(such as ``outgoing@mycompany.example.com``).
* If you want to keep the original "From" address for emails that use your
same domain, but change it for emails that use a different domain, use
the key ``mail.dynamic.smtp.from`` and set as value the email address
that should be used in those cases (such as
``outgoing@mycompany.example.com``).
.. _discuss/email_servers/inbound_messages:
How to manage inbound messages

View File

@ -59,16 +59,23 @@ def resolve(old_resolve, tree, docname, *args, **kwargs):
_update_toctree_nodes(_subnode)
def _get_docname(_node):
"""
docname = a/b/c/the_page_being_rendered
""" Return the docname of the targeted document.
docname = some_common_root/foo/bar/the_page_being_rendered
_ref = ../../contributing/documentation
_path_parts = ['..', '..', 'contributing', 'documentation']
_res = ['a', 'contributing', 'documentation']
_docname = a/contributing/documentation
_res = ['some_common_root', 'contributing', 'documentation']
_docname = some_common_root/contributing/documentation
:return: The docname of the document targeted by `_node`, i.e. the relative path from the
documentation source directory (the `content/` directory)
:rtype: str
"""
_ref = _node['refuri'].replace('.html', '')
_parent_directory_occurrences = _ref.count('..')
if not _parent_directory_occurrences: # The ref is already the docname
if not _parent_directory_occurrences and '/' not in docname:
# The current document is at the root of the documentation source directory
# (e.g. docname == 'index'|'applications'|...). i.e., the ref is already the docname.
_docname = _ref
else:
_path_parts = _ref.split('/')

View File

@ -79,6 +79,10 @@
{%- set main_classes = main_classes + ['o_index'] %}
{%- endif %}
{%- if 'show-content' in meta %} {# The page is an accessible toctree #}
{%- set main_classes = main_classes + ['o_hide_toc'] %}
{%- endif %}
{%- if 'code-column' in meta %} {# The page contains a 'memento' (dynamic side block) #}
{%- set main_classes = main_classes + ['o_has_code_column'] %}
{%- endif %}
@ -110,7 +114,8 @@
{%- endif %}
</main>
{%- if 'hide-page-toc' not in meta %}
<aside id="o_page_toc" class="o_page_toc">
{# Shown when the JS has properly set all the classes on the TOC elements #}
<aside id="o_page_toc" class="o_page_toc" hidden>
{%- include "layout_templates/page_toc.html" %}
</aside>
{%- endif %}

View File

@ -1,7 +1,7 @@
<div id="o_content">
<section class="o_content_fw_banner row">
<div class="col-lg-6">
<h2 class="text-white">Odoo Documentation</h2>
<h1 class="text-white">Odoo Documentation</h1>
<p class="text-white">The comprehensive guide for Odoo users. Easily find the tutorial and helpful tips that suit your needs.</p>
<div class="mt-3">
<a href="https://odoo.com/trial" class="btn btn-primary mb-2">Try Odoo for FREE</a>
@ -9,16 +9,11 @@
</div>
</section>
<section>
<div class="row gx-lg-5 border-bottom">
<div class="col-lg-6 order-lg-2">
<div class="o_cat_banner mb-5">
<img src="{{ pathto('_static/img/banner-applications.png', 1) }}" alt="">
</div>
</div>
<div class="col-lg-6 order-lg-1">
<h3>Applications</h3>
<p>Master any app thanks to their end-user guides. Our wide array of functional workflows and processes are designed to help you unleash Odoo's potential.</p>
<h5 class="pt-3 text-uppercase fw_semibold">Top Links</h5>
<div class="row gx-lg-5">
<div class="col-lg-6">
<h2><i class="i-doc-apps d-lg-none me-2"></i>Applications</h2>
<p class="text-muted">Master any app thanks to their end-user guides. Our wide array of functional workflows and processes are designed to help you unleash Odoo's potential.</p>
<h5 class="text-muted pt-3 text-uppercase fw_semibold">Top Links</h5>
<ul class="list-unstyled">
<li>
<a href="{{ pathto('applications/finance/accounting/overview/main_concepts/in_odoo') }}" class="stretched-link">
@ -42,15 +37,10 @@
</li>
</ul>
</div>
</div>
<div class="row gx-lg-5">
<div class="col-lg-6 py-5 border-bottom">
<div class="o_cat_banner mb-4 p-lg-4">
<i class="i-doc-admin"></i>
</div>
<h3>Administration</h3>
<p>Easily setup your first Odoo installation. From downloads to day-to-day database administration, the dedicated tutorials have got you covered.</p>
<h5 class="pt-3 text-uppercase fw_semibold">Top Links</h5>
<div class="col-lg-6">
<h2 class="border-top pt-4 pt-lg-0"><i class="i-doc-admin d-lg-none me-2"></i>Administration</h2>
<p class="text-muted">Easily setup your first Odoo installation. From downloads to day-to-day database administration, the dedicated tutorials have got you covered.</p>
<h5 class="text-muted pt-3 text-uppercase fw_semibold">Top Links</h5>
<ul class="list-unstyled">
<li>
<a href=" {{ pathto('administration/install') }} " class="stretched-link">
@ -74,13 +64,12 @@
</li>
</ul>
</div>
<div class="col-lg-6 py-5 border-bottom">
<div class="o_cat_banner mb-4 p-lg-4 o-bg-violet-light">
<i class="i-doc-dev"></i>
</div>
<h3>Developer</h3>
<p>Learn to develop in Odoo by reading the framework references and programmer tutorials.</p>
<h5 class="pt-3 text-uppercase fw_semibold">Top Links</h5>
</div>
<div class="row gx-lg-5">
<div class="col-lg-6">
<h2 class="border-top pt-4"><i class="i-doc-dev d-lg-none me-2"></i>Developer</h2>
<p class="text-muted">Learn to develop in Odoo by reading the framework references and programmer tutorials.</p>
<h5 class="text-muted pt-3 text-uppercase fw_semibold">Top Links</h5>
<ul class="list-unstyled">
<li>
<a href="{{ pathto('developer/reference/orm') }}" class="stretched-link">
@ -104,16 +93,10 @@
</li>
</ul>
</div>
</div>
<div class="row gx-lg-5">
{# If changelog exists add class border-bottom #}
<div class="col-lg-6 pt-5">
<div class="o_cat_banner mb-4 p-lg-4 o-bg-violet-light">
<i class="i-doc-services"></i>
</div>
<h3>Services</h3>
<p>Find out how to open a support ticket should you need to contact a Customer Service Representative.</p>
<h5 class="pt-3 text-uppercase fw_semibold">Top Links</h5>
<div class="col-lg-6">
<h2 class="border-top pt-4"><i class="i-doc-services d-lg-none me-2"></i>Services</h2>
<p class="text-muted">Find out how to open a support ticket should you need to contact a Customer Service Representative.</p>
<h5 class="text-muted pt-3 text-uppercase fw_semibold">Top Links</h5>
<ul class="list-unstyled">
<li>
<a href="{{ pathto('services/support/where_can_i_get_support') }}" class="stretched-link">
@ -132,14 +115,12 @@
</li>
</ul>
</div>
{# If changelog exists add class border-bottom #}
<div class="col-lg-6 pt-5">
<div class="o_cat_banner mb-4 p-lg-4">
<i class="i-doc-contribute"></i>
</div>
<h3>Contributing</h3>
<p>You want to contribute to Odoo but don't know where to start? The tutorials and guidelines are there to help you make Odoo even better.</p>
<h5 class="pt-3 text-uppercase fw_semibold">Top Links</h5>
</div>
<div class="row gx-lg-5">
<div class="col-lg-6">
<h2 class="border-top pt-4"><i class="i-doc-contribute d-lg-none me-2"></i>Contributing</h2>
<p class="text-muted">You want to contribute to Odoo but don't know where to start? The tutorials and guidelines are there to help you make Odoo even better.</p>
<h5 class="text-muted pt-3 text-uppercase fw_semibold">Top Links</h5>
<ul class="list-unstyled">
<li>
<a href="{{ pathto('contributing/documentation/introduction_guide') }}" class="stretched-link">

View File

@ -1,6 +1,6 @@
<div class="o_versions row gx-2 me-3">
<div class="col col-form-label">
<label class="fw_bold small me-2">Version</label>
<label class="fw_bold small ms-2">Version</label>
</div>
<div class="col">
<div class="dropdown">

View File

@ -47,14 +47,21 @@
}
};
document.addEventListener('scroll', () => {
// Allow to hide the searchbar when the page is scrolled in mobile.
_flagHeaderWithScrollPosition();
});
/**
* Mobile: Toggle open/close sidebar on click of nav button (&& on swipe left to right?).
*
*
* `o_active_toc_entry` class, and their related (parent) TOC entry list (<ul> elements) receive
* the `show` (Bootstrap) class.
* Also, the deepest TOC entry receives the `o_deepest_active_toc_entry` class, and its child
* Sidebar receives the `o-mobile-show` class.
* Add/Remove the class `o_header_scrolled` on the header according to the scroll position.
*/
const _flagHeaderWithScrollPosition = () => {
const header = document.querySelector('.o_main_header');
if (this.scrollY > 0) {
header.classList.add('o_header_scrolled');
} else {
header.classList.remove('o_header_scrolled');
}
};
})();

View File

@ -22,6 +22,9 @@
// Allow to hide the TOC entry referring the title (<h1> heading)
_flagFirstHeadingRef();
// Show hidden menu when the css classes have been properly specified
this.pageToc.removeAttribute('hidden');
}
});

View File

@ -173,7 +173,7 @@ $o-inverse-dark: #5b7687;
$o-inverse-darker: #485761;
$color-alpha: #00A19B;
$color-alpha-dark: #00807D;
$color-alpha-dark: #017e84;
$color-alpha-light: #26d1af;
$color-alpha-lightest: #2aebc4;
@ -205,8 +205,6 @@ $gray-light: #d5d5d5;
$gray: #888888;
$gray-dark: #707070;
$gray-darker: #282F33;
$gray-darkest: shade-color($gray-darker, 30%);
$primary: $color-alpha-dark;
$secondary: $o-violet-dark;

View File

@ -14,15 +14,18 @@ body {
a:not(:hover), a.o_logo {
text-decoration: none !important;
}
dd {
margin-left: 1rem;
}
// This fixes the scroll position on all elements, including refs
:target {
&:before {
@include o-scroll-padding()
}
}
abbr[title="Pull Request"] {
@include o-easter-egg();
}
@ -37,7 +40,7 @@ body {
// Header with logo, searchbar and switchers
//------------------------------------------------------------------------------
header.o_main_header{
header.o_main_header {
width: 100%;
height: $o-header-mobile-height;
position: fixed;
@ -50,13 +53,16 @@ header.o_main_header{
height: $o-header-height;
padding-right: 3rem;
}
.o_logo_wrapper {
padding: 0 1rem;
> .o_logo {
img {
margin-bottom: -2px;
vertical-align: baseline;
}
span {
@include font-size($font-size-base);
color: $o-violet;
@ -73,36 +79,56 @@ header.o_main_header{
}
.o_search_wrapper {
display: flex;
opacity: 1;
@include transition(opacity .3s);
@include media-breakpoint-down(lg) {
display: block;
position: absolute;
width: 100%;
padding: 0 10px;
top: calc(100% + 30px);
top: calc(100% + 15px);
}
}
&.o_header_scrolled {
.o_search_wrapper {
@include media-breakpoint-down(lg) {
opacity: 0;
}
}
}
.highlight-link {
@media only screen and (max-width: 1242px) and (min-width: 992px){
position: absolute;
bottom: 0;
}
margin-bottom: 0;
padding: 0 1rem;
text-align: center;
align-self: center;
a {
@include font-size($font-size-secondary);
}
}
.navbar-toggler {
border: none;
&[aria-expanded="true"] {
.icon-bar {
&:nth-of-type(1) {
@include o-transform(rotate(45deg));;
@include o-transform-origin(10%, 10%)
}
&:nth-of-type(2) {
opacity: 0;
filter: alpha(opacity=0);
}
&:nth-of-type(3) {
@include o-transform(rotate(-45deg));
@include o-transform-origin(10%, 90%)
@ -115,20 +141,25 @@ header.o_main_header{
height: 2px;
background-color: $gray-dark;
@include o-transition(all, .2s);
&+ .icon-bar {
margin-top: 4px;
}
&:nth-of-type(1) {
@include o-transform(rotate(0));
}
&:nth-of-type(2) {
opacity: 1;
filter: alpha(opacity=100);
}
&:nth-of-type(3) {
@include o-transform(rotate(0));
}
}
&:focus {
box-shadow: none;
outline:none;
@ -149,7 +180,8 @@ header.o_main_header{
@include media-breakpoint-up(lg) {
max-width: 500px;
}
.btn{
.btn {
@include o-position-absolute($top: 50%, $right: 1rem);
@include o-transform (translateY(-50%)) ;
padding: 0;
@ -170,6 +202,7 @@ header.o_main_header{
position: fixed;
top: -100%;
left:0;
&.show {
top: $o-header-mobile-height;
}
@ -181,7 +214,7 @@ header.o_main_header{
padding-left: 3rem;
}
@include o-transition(all, .3s);
padding-top: 1rem;
padding-top: 4rem;
padding-left: 1rem;
background-color: lighten($o-violet-dark, 70%) ;
z-index: 10;
@ -193,37 +226,35 @@ header.o_main_header{
padding-bottom: .5rem;
}
.toctree-l1 > ul {
padding-left: 1.5rem;
}
ul {
.o_deepest_active_toc_entry {
background-color: $gray-lightest;
background-color: $gray-lighter;
border-left: 3px solid $gray-lighter;
margin-left: -3px;
}
> .toctree-l1 {
&[class*="o_menu_"] > .o_toc_entry_wrapper > i {
opacity: .75;
&:before {
@include o-inline-icon($i-doc-apps, 0 1rem 0 0);
color: $o-violet-dark;
margin-right: 0.5rem;
}
&[class*="o_menu_"] > .o_toc_entry_wrapper > i:before {
@include o-inline-icon($i-doc-apps, 0 5px 0 0);
color: $o-violet-dark;
}
&.o_menu_applications > .o_toc_entry_wrapper > i:before{
content:'#{$i-doc-apps}';
}
&.o_menu_administration > .o_toc_entry_wrapper > i:before{
content:'#{$i-doc-admin}';
}
&.o_menu_developer > .o_toc_entry_wrapper > i:before{
content:'#{$i-doc-dev}';
}
&.o_menu_services > .o_toc_entry_wrapper > i:before{
content:'#{$i-doc-services}';
}
&.o_menu_contributing > .o_toc_entry_wrapper > i:before{
content:'#{$i-doc-contribute}';
}
@ -232,12 +263,15 @@ header.o_main_header{
}
scrollbar-width: thin;
scrollbar-color: $o-violet-darker transparent;
&::-webkit-scrollbar {
width: 5px;
}
&::-webkit-scrollbar-track {
background: $white;
}
&::-webkit-scrollbar-thumb {
background-color: $o-violet-darker ;
border-radius: 0;
@ -250,21 +284,28 @@ header.o_main_header{
padding-left: 1rem;
li {
padding-left: .2rem;
&.toctree_l2 {
padding-left: .2rem;
}
> a.reference {
padding-left: 1.2rem;
padding-left: .8rem;
}
a {
display: inline-block;
padding: .5rem 0;
padding: .4rem 0;
color: inherit;
opacity: .75;
&.current, &:hover {
opacity: 1;
}
}
> .o_toc_entry_wrapper i {
opacity: .75;
}
&:not(.toctree-l1) {
.o_toc_entry_wrapper {
&:not(.o_page_toc_title) {
@ -276,6 +317,7 @@ header.o_main_header{
display: inline-block;
margin-right: .2rem;
@include o-transition(rotate, .3s);
font-size: .75rem;
font-weight: $fw_bold;
color: inherit;
@ -285,19 +327,21 @@ header.o_main_header{
}
}
}
&.o_active_toc_entry {
&:not(.toctree-l1) > .o_toc_entry_wrapper {
i[class^="i-"]:not(.collapsed) {
@include o-transform(rotate(90deg));
}
}
> a , > .o_toc_entry_wrapper a {
> a , > .o_toc_entry_wrapper a, > .o_toc_entry_wrapper i {
font-weight: $fw_bold;
opacity: 1;
}
}
}
}
> ul { //is first ul in toc
padding-left: 0;
}
@ -332,11 +376,12 @@ header.o_main_header{
a {
font-weight: $fw_regular;
color: $gray-darkest;
color: $gray-darker;
}
.o_page_toc_title {
display:none;
+ ul {
padding-left: 0;
}
@ -349,7 +394,6 @@ header.o_main_header{
#wrap {
margin-top: $o-header-mobile-height;
@include media-breakpoint-up(lg) {
display: flex;
justify-content: space-between;
@ -378,7 +422,6 @@ header.o_main_header{
padding-top: 7rem;
}
padding-bottom: 3rem;
@include media-breakpoint-up(lg) {
left: $o-side-nav-width;
max-width: calc(100vw - (#{$o-side-nav-width} + var(--bs-gutter-x, 1.5rem)) - #{$o-on-page-width});
@ -404,14 +447,16 @@ header.o_main_header{
margin: -3rem -3rem 3rem;
padding: 2rem 3rem;
}
.btn-primary {
background-color: #00A09D;
border-color: #00A09D;
}
}
p, h5 {
color: $gray;
.row:first-of-type h2.border-top {
@include media-breakpoint-up(lg) {
border-top: 0 solid transparent !important;
}
}
h5 {
@ -424,33 +469,14 @@ header.o_main_header{
padding-bottom: .5rem;
display: flex;
align-items: center;
&:before {
@include o-inline-icon($i-article, 0 .2rem 0 0);
color: $gray-light;
}
}
}
.o_cat_banner {
background-color: $o-violet;
border-radius: 5px;
text-align: center;
background-repeat: no-repeat;
background-size: 90%;
background-position: center;
i {
font-size: 100px;
color: $white;
}
&.o-bg-violet-light {
background-color: lighten($o-violet, 20%);
}
&:not(.shadow){
background-image: url('img/bg-cat.svg');
}
&.shadow {
box-shadow: 0px 2px 25px rgba(19, 28, 40, .08) !important;
}
}
.o_changelog {
.row:last-of-type > .border-bottom {
border: none !important;
@ -459,7 +485,6 @@ header.o_main_header{
}
// pages with full width: Legal
&.o_fullwidth_page {
.toctree-l1 > a {
display: block;
@ -472,11 +497,9 @@ header.o_main_header{
}
// pages with column for code on the right
&.o_has_code_column {
article.doc-body {
> *{
> * {
max-width: 100%;
}
@ -507,13 +530,11 @@ header.o_main_header{
@include o-code-col();
}
.o_git_link {
right: calc(#{$o-codecol-width} + 2rem);
}
section {
section {
> * {
width: $o-halfpage-width;
float: left;
@ -554,13 +575,34 @@ header.o_main_header{
}
}
article.doc-body {
position: relative;
// hide ugly toctree on "in between" pages (e.g.: /applications.html, /administration.html, ...)
&.o_hide_toc {
.toctree-wrapper {
display: none;
}
}
.toctree-wrapper {
> ul {
padding-left: 0;
list-style: none;
}
.toctree-l1 > a[href="#"] {
font-size: 1.2rem;
font-weight: 600;
border-bottom: 2px solid $gray-darker;
}
a[href="#"] {
pointer-events: none;
cursor: default;
color: $gray-darker;
font-weight: $fw_regular;
}
}
article.doc-body {
position: relative;
.o_git_link {
@include font-size($font-size-secondary);
@ -572,6 +614,7 @@ header.o_main_header{
margin-right: .2rem;
}
}
.command {
font-family: var(--bs-font-monospace);
}
@ -611,7 +654,7 @@ header.o_main_header{
> h2 {
font-family: $font-family-serif;
color: $gray-darker;
margin-top: 3rem;
margin-top: 2rem;
margin-bottom: 1rem;
padding-bottom: .3rem;
border-bottom: 1px solid $gray-light;
@ -647,14 +690,17 @@ header.o_main_header{
}
.figure {
.caption, .caption-text {
font-weight: $fw_semibold;
color: $gray;
}
.caption, .caption-text, .legend, .legend p{
.caption, .caption-text, .legend, .legend p {
font-style: italic;
margin: 0 auto;
}
@include media-breakpoint-up(md) {
&:not([class^="col"]) .legend {
max-width: 60%;
@ -666,9 +712,11 @@ header.o_main_header{
text-decoration: none;
font-size: 0;
visibility: hidden !important;
&:before {
content: "\a0";
}
&:after {
content: '#{$i-link}';
font-family: icomoon !important;
@ -680,11 +728,13 @@ header.o_main_header{
@include o-transition(all, .1s)
}
}
*:hover > a.headerlink:after{
*:hover > a.headerlink:after {
// This makes permalinks only visible on hover.
visibility: visible;
opacity: 1;
}
table.table {
@include media-breakpoint-down(lg){
display: block;
@ -693,10 +743,8 @@ header.o_main_header{
overflow-wrap: break-word;
}
}
}
}
}
div[class^="highlight"] {
@ -704,7 +752,6 @@ header.o_main_header{
overflow-x: auto;
border: 1px solid $gray-light;
margin: 1px 0 24px 0;
/* max-width: 90vw; */
div[class^="highlight"] {
padding: 0px;
@ -719,7 +766,7 @@ header.o_main_header{
overflow: auto;
}
}
// fixes on pages
.guilabel, .menuselection {
font-weight: $fw_semibold;
}
@ -763,19 +810,7 @@ header.o_main_header{
text-align: left;
}
// restyle numbers on lists
ol {
/* list-style: none;
counter-reset: a;
> li {
position: relative;
counter-increment: a;
&:before {
content: counter(a) '.';
font-weight: $fw_semibold;
@include o-position-absolute(auto, auto, auto, -1.8rem);
}
} */
ol {
list-style: lower-alpha;
> li:before {
@ -804,7 +839,7 @@ header.o_main_header{
background-color: $white !important;
}
> p , > ul{
> p , > ul {
margin-bottom: .5rem;
}
> *:last-child {
@ -849,8 +884,6 @@ header.o_main_header{
content: '#{$i-note}';
}
}
}
&.alert-tip, &.tip {
@ -909,7 +942,8 @@ header.o_main_header{
@include media-breakpoint-up(lg){
display: inline-block;
width: calc(50% - 1rem);
}s
}
a {
color: $o-violet-dark;
}
@ -932,7 +966,7 @@ footer {
.o_get_help {
padding-top: 3rem;
padding-bottom: 3rem;
background: $gray-100;
background: $gray-lighter;
@include media-breakpoint-up(lg) {
padding-left: calc(#{$o-side-nav-width} + 3rem)
}
@ -945,4 +979,4 @@ footer {
}
}
}
}