Public Access
feat(bf): show the code on arrival and buy in one click on /odoo-black-friday/
The code was behind a reveal (click 'Open the Black Friday price'). Both offer cards are now always open: the price and HOST27 are readable without any interaction. The scroll animation (opacity/transform only, base state fully opaque, behind @supports) is presentation, never a gate. The hosting CTA is now a native form that posts the On the Rise product straight to the shop basket, so one click from the page lands in checkout with the plan in the cart — replacing a three-navigation detour (offers hub -> homepage trial -> pricing). Bootcamp box content is untouched; only its reveal gate was removed.
This commit is contained in:
1 parent
4801e09466
commit
3e2a7a71a6
1 file changed
+111
-79
+111
-79
@@ -152,56 +152,16 @@
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
/* Reveal mechanic — native <details>/<summary>: the panel is in the DOM in both states,
|
||||
keyboard-operable, and works with JavaScript disabled. CSS reveals it; JS only mirrors
|
||||
the open state to aria-expanded. The panel is never display:none by our stylesheet. */
|
||||
.bf-reveal {
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.bf-reveal-summary {
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
display: block;
|
||||
padding: 1.25rem 0 1rem;
|
||||
}
|
||||
.bf-reveal-summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
.bf-reveal-summary:focus-visible {
|
||||
outline: 2px solid var(--brass);
|
||||
outline-offset: 3px;
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
/* Both offer cards are always open: the Black Friday price and the code are readable on
|
||||
arrival, with no reveal and no click. The scroll animation further down is presentation
|
||||
only — the base state is fully visible, so the offer is complete with JavaScript off,
|
||||
under reduced motion, or if the animation never runs. */
|
||||
.bf-teaser {
|
||||
font-size: 1.02rem;
|
||||
color: var(--ink);
|
||||
line-height: 1.6;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
.bf-open-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-family: Inter, sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.82rem;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
color: var(--midnight);
|
||||
background: var(--brass);
|
||||
border-radius: var(--radius-pill);
|
||||
padding: 0.6rem 1.25rem;
|
||||
}
|
||||
.bf-open-label::after {
|
||||
content: "+";
|
||||
font-size: 1.05rem;
|
||||
line-height: 1;
|
||||
}
|
||||
/* closed state only: the label is the invitation, so it goes once the panel is open.
|
||||
`[open]` is set by the browser natively — this needs no JavaScript. */
|
||||
.bf-reveal[open] .bf-open-label {
|
||||
display: none;
|
||||
}
|
||||
.bf-panel {
|
||||
padding: 0.25rem 0 1.25rem;
|
||||
border-top: 1px solid var(--line);
|
||||
@@ -236,6 +196,62 @@
|
||||
.bf-mechanism strong {
|
||||
color: var(--midnight);
|
||||
}
|
||||
/* The code lives on the offer surface only. It is readable on arrival; the chip is easy to
|
||||
select so it can be copied at checkout. */
|
||||
.bf-code-wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
gap: 0.4rem 0.7rem;
|
||||
}
|
||||
.bf-code-label {
|
||||
font-family: Inter, sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--brass-deep);
|
||||
}
|
||||
.bf-code {
|
||||
font-family: Marcellus, Georgia, serif;
|
||||
font-size: 1.3rem;
|
||||
letter-spacing: 0.12em;
|
||||
color: var(--midnight);
|
||||
background: var(--brass);
|
||||
border-radius: var(--radius-pill);
|
||||
padding: 0.2rem 0.9rem;
|
||||
user-select: all;
|
||||
}
|
||||
.bf-code-note {
|
||||
font-size: 0.9rem;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
/* Presentation only: the code fades and rises a little as it scrolls into view. Opacity and
|
||||
transform only — never visibility. The base state is fully opaque, so a build where the
|
||||
animation never fires still shows the code. Everything here is behind @supports, so an
|
||||
unsupported browser renders the static, visible code. */
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
@supports (animation-timeline: view()) {
|
||||
.bf-code {
|
||||
animation-name: bf-code-in;
|
||||
animation-timing-function: linear;
|
||||
animation-fill-mode: both;
|
||||
animation-duration: auto;
|
||||
animation-timeline: view();
|
||||
animation-range: entry 0% cover 45%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes bf-code-in {
|
||||
from {
|
||||
opacity: 0.8;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
.bf-deadline {
|
||||
font-size: 0.85rem;
|
||||
color: var(--ink-soft);
|
||||
@@ -264,6 +280,41 @@
|
||||
outline: 3px solid var(--midnight);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
/* Hosting CTA: a native form that posts the plan straight to the shop basket, so one click
|
||||
from this page lands the visitor in checkout with the plan already in the cart. Works with
|
||||
JavaScript off (it is a plain form POST). */
|
||||
.bf-cta-form {
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
.bf-cta-form .btn {
|
||||
display: inline-block;
|
||||
font-family: Marcellus, Georgia, serif;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--midnight);
|
||||
background: var(--brass);
|
||||
border: 0;
|
||||
border-radius: var(--radius-pill);
|
||||
padding: 0.8rem 1.75rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.bf-cta-form .btn:hover {
|
||||
background: var(--brass-bright);
|
||||
color: var(--midnight);
|
||||
}
|
||||
.bf-cta-form .btn:focus-visible {
|
||||
outline: 3px solid var(--midnight);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.bf-cta-secondary {
|
||||
font-size: 0.85rem;
|
||||
margin: 0;
|
||||
}
|
||||
.bf-cta-secondary a {
|
||||
color: var(--brass-deep);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
|
||||
/* FAQ (native details/summary — no JS) */
|
||||
.cmp-faq-grid {
|
||||
@@ -523,20 +574,15 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- The two Black Friday offers — one section, two boxes, Bootcamp first. Each box carries the
|
||||
same reveal mechanic: a native <details class="bf-reveal"> with a closed teaser <summary>,
|
||||
then the open panel. -->
|
||||
<!-- The two Black Friday offers — one section, two boxes, Bootcamp first. Both cards are always
|
||||
open: the price and the code are readable on arrival, with no reveal and no click. -->
|
||||
<section class="section-light bf-box" id="offer">
|
||||
<div class="container">
|
||||
<!-- Box 1 — Bootcamp -->
|
||||
<div class="bf-box-inner">
|
||||
<h2 class="bf-box-title">Bootcamp: ten live sessions to a working system</h2>
|
||||
<details class="bf-reveal">
|
||||
<summary class="bf-reveal-summary" aria-expanded="false">
|
||||
<p class="bf-teaser">A working system for your business in ten live sessions, USD 595. Open to see the Black Friday offer.</p>
|
||||
<span class="bf-open-label">Open the Black Friday offer</span>
|
||||
</summary>
|
||||
<div class="bf-panel">
|
||||
<p class="bf-teaser">A working system for your business in ten live sessions, USD 595 — with a second hosted year added for Black Friday.</p>
|
||||
<p class="bf-price"><strong>USD 595.00</strong> for the full programme. Black Friday adds <strong>a second year of hosted Odoo Community Edition</strong>, on top of the one already included.</p>
|
||||
<p class="bf-included">Ten live Thursday sessions, 18:00–19:00 Central Time, starting Thursday 21 January 2027. Six seats, and no more. Your first hosted year is included as standard; the second year is the Black Friday add-on.</p>
|
||||
<!-- Bootcamp mechanism string — ONE reusable line, isolated exactly as the Hosting box's is
|
||||
@@ -549,27 +595,29 @@
|
||||
checkout host (20.odoo4projects.com) by odoo-dev. See wiki/concepts/conversion-tracking-contract. -->
|
||||
<p class="bf-cta"><a class="plausible-event-name=Buy" href="/odoo-erp-automation-bootcamp/">See the Bootcamp and what you build</a></p>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<!-- Box 2 — Hosting, On the Rise -->
|
||||
<div class="bf-box-inner">
|
||||
<h2 class="bf-box-title">Hosting: On the Rise</h2>
|
||||
<details class="bf-reveal">
|
||||
<summary class="bf-reveal-summary" aria-expanded="false">
|
||||
<p class="bf-teaser">Your whole business in one system, $395 a year. Open to see the Black Friday price.</p>
|
||||
<span class="bf-open-label">Open the Black Friday price</span>
|
||||
</summary>
|
||||
<div class="bf-panel">
|
||||
<p class="bf-teaser">Your whole business in one system. The Black Friday price is right here — no code to hunt for.</p>
|
||||
<p class="bf-price"><strong>$395.00</strong> a year — <strong>$295.00</strong> for your first year.</p>
|
||||
<p class="bf-included">Then it renews at the $395 list price. One yearly price, no per-user licence, no setup fee. We run the server, the backups, your certificate and the version upgrades for you.</p>
|
||||
<!-- mechanism string, used verbatim — see §3 -->
|
||||
<p class="bf-mechanism">Black Friday: <strong>$100 off your first year</strong> with code <strong>HOST27</strong>. One redemption per customer.</p>
|
||||
<!-- mechanism string, used verbatim — see §3. The code is the offer surface: it stays out
|
||||
of meta, alt text, structured data and build comments. -->
|
||||
<p class="bf-mechanism bf-code-wrap"><span class="bf-code-label">Your code</span><span class="bf-code">HOST27</span><span class="bf-code-note">takes $100 off your first year at checkout. One redemption per customer.</span></p>
|
||||
<p class="bf-deadline">Ends Monday 30 November 2026.</p>
|
||||
<!-- Buy = CLICK PROXY (offer-CTA click), NOT a sale (see the other box on this page). -->
|
||||
<p class="bf-cta"><a class="plausible-event-name=Buy" href="/odoo-hosting-offers/">See what a year of hosting includes</a></p>
|
||||
<!-- Buy = CLICK PROXY (offer-CTA click), NOT a sale (see the other box on this page).
|
||||
The form posts the On the Rise product (id 4) straight to the shop basket, so one
|
||||
click lands the visitor in checkout with the plan already in the cart. -->
|
||||
<form method="post" action="https://20.odoo4projects.com/shop/post_basket" target="_blank" class="bf-cta-form plausible-event-name=Buy">
|
||||
<input type="hidden" name="basket" value='[{"product_id":4,"qty":1}]' />
|
||||
<input type="hidden" name="clear" value="1" />
|
||||
<button type="submit" class="btn btn-brass btn-lg">Buy On the Rise — $295 first year</button>
|
||||
</form>
|
||||
<p class="bf-cta-secondary"><a href="/odoo-hosting-offers/">See everything a year of hosting includes</a></p>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -661,21 +709,5 @@
|
||||
<div class="fcopy">Copyright © ODOO4projects LLC</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
/* Enhancement only: mirror each reveal's open state to aria-expanded. Without JS the native
|
||||
<details> still toggles, keyboard-operable, and exposes its state. */
|
||||
(function () {
|
||||
var reveals = document.querySelectorAll(".bf-reveal");
|
||||
Array.prototype.forEach.call(reveals, function (reveal) {
|
||||
var summary = reveal.querySelector("summary");
|
||||
function sync() {
|
||||
if (summary) summary.setAttribute("aria-expanded", reveal.open ? "true" : "false");
|
||||
}
|
||||
sync();
|
||||
reveal.addEventListener("toggle", sync);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user