Language selector: move it into the visible top bar on every page that loads lang.js

The EN | DE | ES switcher existed but rendered into the footer slot, so a
visitor had to scroll to the bottom of the page to find it (measured live:
y=5582 on /, y=5498 on /odoo-erp-automation-bootcamp/). The user asked for a
selector a visitor can actually see.

- index.html, de/index.html, es/index.html: the slot is now the first child of
  .hero .container, right-aligned in flow above the kicker. In flow, not a
  fixed pill, so it cannot collide with the absolute .hero-notice.
- odoo-erp-automation-bootcamp/index.html: the slot is now the last child of
  .bc-topbar .container, right of the nav links, behind a hairline brass
  divider; .bc-topbar-links gets margin-left:auto so the brand stays left.
- One [data-lang-switcher] per page; the footer slot is removed everywhere.
- Styling follows the CI: Inter 12px / .06em / uppercase codes (the existing
  .lang-switch rules), active language in --brass on these midnight surfaces,
  the other two in the surrounding text colour. CSS-only, in each page's
  inline <style>; lang.js is untouched, so its redirect behaviour is unchanged.
- The rules are recorded in work/i18n/I18N-BUILD-PLAN.md §3 for the phase-2
  pages (de|es/odoo-hosting-2027.html, de|es/support.html).
This commit is contained in:
oliver committed 2026-10-24 21:51:08 +00:00
1 parent 7b2d241330
commit 0721804aab
4 files changed
+45 -4

No files matched your search

+7 -1
View File
@@ -116,6 +116,12 @@
.hero::after{content:'';position:absolute;inset:0;background:linear-gradient(135deg,var(--midnight) 50%,rgba(13,27,46,.4) 100%);opacity:.5;z-index:0} .hero::after{content:'';position:absolute;inset:0;background:linear-gradient(135deg,var(--midnight) 50%,rgba(13,27,46,.4) 100%);opacity:.5;z-index:0}
.hero-bg{position:absolute;inset:0;z-index:0;overflow:hidden}.hero-bg-slide{position:absolute;inset:0;background-size:cover;background-position:center;background-repeat:no-repeat;opacity:.25;filter:brightness(1.15)saturate(1.1)} .hero-bg{position:absolute;inset:0;z-index:0;overflow:hidden}.hero-bg-slide{position:absolute;inset:0;background-size:cover;background-position:center;background-repeat:no-repeat;opacity:.25;filter:brightness(1.15)saturate(1.1)}
.hero .container{position:relative;z-index:1;flex:1;display:flex;flex-direction:column;justify-content:center} .hero .container{position:relative;z-index:1;flex:1;display:flex;flex-direction:column;justify-content:center}
/* Language selector — top-right of the hero's own top area (page has no site header). CI §1/§2:
brass marks the active language, body colour for the other two; lang.js owns the markup. */
.hero .lang-switch-slot{display:flex;justify-content:flex-end;margin-bottom:1rem}
.hero .lang-switch{color:rgba(255,255,255,.65)}
.hero .lang-switch a:hover,.hero .lang-switch a:focus-visible{color:var(--brass-bright)}
.hero .lang-switch a[aria-current="true"]{color:var(--brass);text-decoration:underline;text-underline-offset:3px}
.hero-kicker{font-family:Inter,sans-serif;font-size:.72rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--brass);margin-bottom:.75rem} .hero-kicker{font-family:Inter,sans-serif;font-size:.72rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--brass);margin-bottom:.75rem}
.hero h1{color:#fff;max-width:700px;margin-bottom:1rem;font-weight:400}.hero h1 span{color:var(--brass)} .hero h1{color:#fff;max-width:700px;margin-bottom:1rem;font-weight:400}.hero h1 span{color:var(--brass)}
.hero-sub{font-size:1.05rem;color:rgba(255,255,255,.7);max-width:560px;line-height:1.7;margin-bottom:1.5rem} .hero-sub{font-size:1.05rem;color:rgba(255,255,255,.7);max-width:560px;line-height:1.7;margin-bottom:1.5rem}
@@ -241,6 +247,7 @@
<button type="button" class="hero-notice-close" aria-label="Benachrichtigung schließen">&times;</button> <button type="button" class="hero-notice-close" aria-label="Benachrichtigung schließen">&times;</button>
</div> </div>
<div class="container"> <div class="container">
<div data-lang-switcher class="lang-switch-slot"></div>
<div class="hero-kicker">Vollständig verwaltetes Odoo Community Hosting</div> <div class="hero-kicker">Vollständig verwaltetes Odoo Community Hosting</div>
<h1>Odoo in <span>5 Minuten</span> einsatzbereit — vollständig verwaltetes Hosting</h1> <h1>Odoo in <span>5 Minuten</span> einsatzbereit — vollständig verwaltetes Hosting</h1>
<p class="hero-sub">Starten Sie Ihr System in Minuten — Backups laufen automatisch, Ihre Web-Adresse ist mit SSL gesichert, Module installieren wir auf Wunsch dazu. Kein Techniker nötig.</p> <p class="hero-sub">Starten Sie Ihr System in Minuten — Backups laufen automatisch, Ihre Web-Adresse ist mit SSL gesichert, Module installieren wir auf Wunsch dazu. Kein Techniker nötig.</p>
@@ -663,7 +670,6 @@
</div> </div>
<div class="fcopy">Copyright &copy; ODOO4projects LLC</div> <div class="fcopy">Copyright &copy; ODOO4projects LLC</div>
</div> </div>
<div data-lang-switcher class="lang-switch-slot"></div>
</footer> </footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
+7 -1
View File
@@ -116,6 +116,12 @@
.hero::after{content:'';position:absolute;inset:0;background:linear-gradient(135deg,var(--midnight) 50%,rgba(13,27,46,.4) 100%);opacity:.5;z-index:0} .hero::after{content:'';position:absolute;inset:0;background:linear-gradient(135deg,var(--midnight) 50%,rgba(13,27,46,.4) 100%);opacity:.5;z-index:0}
.hero-bg{position:absolute;inset:0;z-index:0;overflow:hidden}.hero-bg-slide{position:absolute;inset:0;background-size:cover;background-position:center;background-repeat:no-repeat;opacity:.25;filter:brightness(1.15)saturate(1.1)} .hero-bg{position:absolute;inset:0;z-index:0;overflow:hidden}.hero-bg-slide{position:absolute;inset:0;background-size:cover;background-position:center;background-repeat:no-repeat;opacity:.25;filter:brightness(1.15)saturate(1.1)}
.hero .container{position:relative;z-index:1;flex:1;display:flex;flex-direction:column;justify-content:center} .hero .container{position:relative;z-index:1;flex:1;display:flex;flex-direction:column;justify-content:center}
/* Language selector — top-right of the hero's own top area (page has no site header). CI §1/§2:
brass marks the active language, body colour for the other two; lang.js owns the markup. */
.hero .lang-switch-slot{display:flex;justify-content:flex-end;margin-bottom:1rem}
.hero .lang-switch{color:rgba(255,255,255,.65)}
.hero .lang-switch a:hover,.hero .lang-switch a:focus-visible{color:var(--brass-bright)}
.hero .lang-switch a[aria-current="true"]{color:var(--brass);text-decoration:underline;text-underline-offset:3px}
.hero-kicker{font-family:Inter,sans-serif;font-size:.72rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--brass);margin-bottom:.75rem} .hero-kicker{font-family:Inter,sans-serif;font-size:.72rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--brass);margin-bottom:.75rem}
.hero h1{color:#fff;max-width:700px;margin-bottom:1rem;font-weight:400}.hero h1 span{color:var(--brass)} .hero h1{color:#fff;max-width:700px;margin-bottom:1rem;font-weight:400}.hero h1 span{color:var(--brass)}
.hero-sub{font-size:1.05rem;color:rgba(255,255,255,.7);max-width:560px;line-height:1.7;margin-bottom:1.5rem} .hero-sub{font-size:1.05rem;color:rgba(255,255,255,.7);max-width:560px;line-height:1.7;margin-bottom:1.5rem}
@@ -241,6 +247,7 @@
<button type="button" class="hero-notice-close" aria-label="Cerrar notificación">&times;</button> <button type="button" class="hero-notice-close" aria-label="Cerrar notificación">&times;</button>
</div> </div>
<div class="container"> <div class="container">
<div data-lang-switcher class="lang-switch-slot"></div>
<div class="hero-kicker">Hosting de Odoo Community totalmente gestionado</div> <div class="hero-kicker">Hosting de Odoo Community totalmente gestionado</div>
<h1>Odoo en marcha en <span>5 minutos</span> — hosting gestionado</h1> <h1>Odoo en marcha en <span>5 minutos</span> — hosting gestionado</h1>
<p class="hero-sub">Ponga su sistema en marcha en minutos: las copias de seguridad se ejecutan solas, su dirección web va con SSL y los módulos los instalamos nosotros. Sin informáticos.</p> <p class="hero-sub">Ponga su sistema en marcha en minutos: las copias de seguridad se ejecutan solas, su dirección web va con SSL y los módulos los instalamos nosotros. Sin informáticos.</p>
@@ -663,7 +670,6 @@
</div> </div>
<div class="fcopy">Copyright &copy; ODOO4projects LLC</div> <div class="fcopy">Copyright &copy; ODOO4projects LLC</div>
</div> </div>
<div data-lang-switcher class="lang-switch-slot"></div>
</footer> </footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
+7 -1
View File
@@ -116,6 +116,12 @@
.hero::after{content:'';position:absolute;inset:0;background:linear-gradient(135deg,var(--midnight) 50%,rgba(13,27,46,.4) 100%);opacity:.5;z-index:0} .hero::after{content:'';position:absolute;inset:0;background:linear-gradient(135deg,var(--midnight) 50%,rgba(13,27,46,.4) 100%);opacity:.5;z-index:0}
.hero-bg{position:absolute;inset:0;z-index:0;overflow:hidden}.hero-bg-slide{position:absolute;inset:0;background-size:cover;background-position:center;background-repeat:no-repeat;opacity:.25;filter:brightness(1.15)saturate(1.1)} .hero-bg{position:absolute;inset:0;z-index:0;overflow:hidden}.hero-bg-slide{position:absolute;inset:0;background-size:cover;background-position:center;background-repeat:no-repeat;opacity:.25;filter:brightness(1.15)saturate(1.1)}
.hero .container{position:relative;z-index:1;flex:1;display:flex;flex-direction:column;justify-content:center} .hero .container{position:relative;z-index:1;flex:1;display:flex;flex-direction:column;justify-content:center}
/* Language selector — top-right of the hero's own top area (page has no site header). CI §1/§2:
brass marks the active language, body colour for the other two; lang.js owns the markup. */
.hero .lang-switch-slot{display:flex;justify-content:flex-end;margin-bottom:1rem}
.hero .lang-switch{color:rgba(255,255,255,.65)}
.hero .lang-switch a:hover,.hero .lang-switch a:focus-visible{color:var(--brass-bright)}
.hero .lang-switch a[aria-current="true"]{color:var(--brass);text-decoration:underline;text-underline-offset:3px}
.hero-kicker{font-family:Inter,sans-serif;font-size:.72rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--brass);margin-bottom:.75rem} .hero-kicker{font-family:Inter,sans-serif;font-size:.72rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--brass);margin-bottom:.75rem}
.hero h1{color:#fff;max-width:700px;margin-bottom:1rem;font-weight:400}.hero h1 span{color:var(--brass)} .hero h1{color:#fff;max-width:700px;margin-bottom:1rem;font-weight:400}.hero h1 span{color:var(--brass)}
.hero-sub{font-size:1.05rem;color:rgba(255,255,255,.7);max-width:560px;line-height:1.7;margin-bottom:1.5rem} .hero-sub{font-size:1.05rem;color:rgba(255,255,255,.7);max-width:560px;line-height:1.7;margin-bottom:1.5rem}
@@ -241,6 +247,7 @@
<button type="button" class="hero-notice-close" aria-label="Dismiss notification">&times;</button> <button type="button" class="hero-notice-close" aria-label="Dismiss notification">&times;</button>
</div> </div>
<div class="container"> <div class="container">
<div data-lang-switcher class="lang-switch-slot"></div>
<div class="hero-kicker">Fully Managed Odoo Community Hosting</div> <div class="hero-kicker">Fully Managed Odoo Community Hosting</div>
<h1>Deploy Odoo in <span>5 Minutes</span> — Fully Managed Hosting</h1> <h1>Deploy Odoo in <span>5 Minutes</span> — Fully Managed Hosting</h1>
<p class="hero-sub">Launch a production-ready Odoo Community instance with automatic backups, free SSL, and Git-based module management. No DevOps required.</p> <p class="hero-sub">Launch a production-ready Odoo Community instance with automatic backups, free SSL, and Git-based module management. No DevOps required.</p>
@@ -662,7 +669,6 @@
</div> </div>
<div class="fcopy">Copyright &copy; ODOO4projects LLC</div> <div class="fcopy">Copyright &copy; ODOO4projects LLC</div>
</div> </div>
<div data-lang-switcher class="lang-switch-slot"></div>
</footer> </footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
+24 -1
View File
@@ -76,6 +76,29 @@
.bc-topbar-links a:hover { .bc-topbar-links a:hover {
color: var(--brass); color: var(--brass);
} }
/* Language selector — slides into the top-bar row, right of the links, behind a hairline brass divider.
CI §1/§2: brass marks the active language; lang.js owns the markup. */
.bc-topbar-links {
margin-left: auto;
}
.bc-topbar .lang-switch-slot {
display: flex;
align-items: center;
padding-left: 1rem;
border-left: 1px solid rgba(201, 162, 39, 0.45);
}
.bc-topbar .lang-switch {
color: rgba(255, 255, 255, 0.7);
}
.bc-topbar .lang-switch a:hover,
.bc-topbar .lang-switch a:focus-visible {
color: var(--brass-bright);
}
.bc-topbar .lang-switch a[aria-current="true"] {
color: var(--brass);
text-decoration: underline;
text-underline-offset: 3px;
}
/* Hero */ /* Hero */
.bc-hero { .bc-hero {
@@ -484,6 +507,7 @@
<a href="/index.html#pricing">Plans &amp; pricing</a> <a href="/index.html#pricing">Plans &amp; pricing</a>
<a href="/support.html">Support</a> <a href="/support.html">Support</a>
</nav> </nav>
<div data-lang-switcher class="lang-switch-slot"></div>
</div> </div>
</div> </div>
@@ -788,7 +812,6 @@
</div> </div>
<div class="fcopy">Copyright &copy; ODOO4projects LLC</div> <div class="fcopy">Copyright &copy; ODOO4projects LLC</div>
</div> </div>
<div data-lang-switcher class="lang-switch-slot"></div>
</footer> </footer>
<script defer src="/static/lang.js"></script> <script defer src="/static/lang.js"></script>
</body> </body>