← All sections
Drop Countdown
A cinematic launch stage with a live rolling countdown, promo code and one clear CTA.
Install
One file: sections/mf-drop-countdown.liquid. It appears in the theme editor as EX · Drop countdown.
- Connect EXPERAISE Sections to Claude (once). In Claude Code:In the Claude app: Settings → Connectors → Add custom connector →
claude mcp add --transport http experaise-sections https://sections.experaise.com/api/mcphttps://sections.experaise.com/api/mcp. Full setup - Ask Claude. It fetches
sections/mf-drop-countdown.liquid, pushes only that file to your theme with Shopify CLI, and tells you where to find it.Install the EXPERAISE Sections section "Drop Countdown" (drop-countdown) on my Shopify store your-store.myshopify.com. Put it on an unpublished copy of my live theme, then tell me how to add it in the theme editor. - Customize. Online Store → Themes → Customize → Add section → EX · Drop countdown. Every text, color and product is a setting.
{%- liquid
assign s = section.settings
assign heading_tag = s.heading_tag | default: 'h2'
assign drop_product = s.product
if drop_product == blank and product != blank
assign drop_product = product
endif
assign show_art = true
if s.visual == 'product'
if s.image != blank or drop_product.featured_media != blank
assign show_art = false
endif
endif
assign cta_url = s.button_link
if cta_url == blank
if drop_product != blank
assign cta_url = drop_product.url
else
assign cta_url = routes.all_products_collection_url
endif
endif
assign accent_brightness = s.color_accent | color_brightness
if accent_brightness > 150
assign cta_fg = '#170d07'
else
assign cta_fg = '#ffffff'
endif
comment
Server-side first paint of the clock (JavaScript takes over on load, so
cached pages never show a stale value for more than a frame).
endcomment
assign off_str = s.utc_offset | default: '+00:00'
assign off_sign = off_str | slice: 0
assign off_h = off_str | slice: 1, 2 | plus: 0
assign off_m = off_str | slice: 4, 2 | plus: 0
assign off_secs = off_h | times: 3600
assign off_min_secs = off_m | times: 60
assign off_secs = off_secs | plus: off_min_secs
if off_sign == '-'
assign off_secs = 0 | minus: off_secs
endif
assign now_ts = 'now' | date: '%s' | plus: 0
assign end_raw = s.end_date | strip
assign end_iso = end_raw | replace: ' ', 'T' | append: ':00' | append: off_str
assign left = 0
assign is_ended = false
if s.mode == 'daily'
assign local_ts = now_ts | plus: off_secs
assign day_secs = local_ts | modulo: 86400
assign cut_secs = s.cutoff_hour | times: 3600
assign left = cut_secs | minus: day_secs
if left <= 0
assign left = left | plus: 86400
endif
else
assign end_ts = end_iso | date: '%s' | plus: 0
if end_ts > 1000000000
assign left = end_ts | minus: now_ts
endif
if left <= 0
assign left = 0
assign is_ended = true
endif
endif
assign t_days = left | divided_by: 86400
assign t_hours = left | modulo: 86400 | divided_by: 3600
assign t_minutes = left | modulo: 3600 | divided_by: 60
assign t_seconds = left | modulo: 60
assign h_short = s.label_hours | slice: 0 | downcase
assign m_short = s.label_minutes | slice: 0 | downcase
-%}
<mf-drop-countdown
class="mf-drop mf-drop--{{ s.layout }} mf-drop--{{ s.mode }}{% if is_ended %} mf-drop--ended{% endif %}{% if s.ended_behavior == 'hide' %} mf-drop--hide-ended{% endif %}{% if request.design_mode %} mf-drop--editor{% endif %}"
data-mode="{{ s.mode }}"
data-end="{{ end_raw | escape }}"
data-offset="{{ off_str }}"
data-cutoff="{{ s.cutoff_hour }}"
data-ended="{{ s.ended_behavior }}"
data-label-days="{{ s.label_days | escape }}"
data-label-hours="{{ s.label_hours | escape }}"
data-label-minutes="{{ s.label_minutes | escape }}"
data-copied="{{ s.copied_label | escape }}"
data-copy-fallback="{{ s.copy_fallback | escape }}"
style="--mf-drop-bg: {{ s.color_bg }}; --mf-drop-fg: {{ s.color_text }}; --mf-drop-accent: {{ s.color_accent }}; --mf-drop-accent-60: {{ s.color_accent | color_modify: 'alpha', 0.6 }}; --mf-drop-accent-35: {{ s.color_accent | color_modify: 'alpha', 0.35 }}; --mf-drop-accent-18: {{ s.color_accent | color_modify: 'alpha', 0.18 }}; --mf-drop-glow: {{ s.color_glow }}; --mf-drop-glow-40: {{ s.color_glow | color_modify: 'alpha', 0.4 }}; --mf-drop-cta-fg: {{ cta_fg }}; --mf-drop-pt: {{ s.padding_top }}px; --mf-drop-pb: {{ s.padding_bottom }}px;"
>
<div class="mf-drop__bg" aria-hidden="true">
<div class="mf-drop__rays"></div>
</div>
<div class="mf-drop__inner">
<div class="mf-drop__head">
{%- if s.eyebrow != blank -%}
<p class="mf-drop__eyebrow mf-drop__reveal" style="--mf-drop-i: 0;"><i aria-hidden="true"></i>{{ s.eyebrow | escape }}</p>
{%- endif -%}
{%- if s.heading != blank -%}
<{{ heading_tag }} class="mf-drop__title mf-drop__reveal" style="--mf-drop-i: 1;">{{ s.heading }}</{{ heading_tag }}>
{%- endif -%}
{%- if s.text != blank -%}
<div class="mf-drop__text mf-drop__reveal" style="--mf-drop-i: 2;">{{ s.text }}</div>
{%- endif -%}
</div>
<div class="mf-drop__stage">
<div class="mf-drop__halo" aria-hidden="true"></div>
{%- if s.show_embers -%}
<div class="mf-drop__embers" aria-hidden="true">
{%- for i in (1..14) -%}
{%- liquid
assign ex = i | times: 37 | modulo: 88 | plus: 6
assign ed = i | times: 7 | modulo: 11
assign et = i | times: 3 | modulo: 5 | plus: 7
assign es = i | modulo: 3 | plus: 2
assign edx = i | times: 13 | modulo: 40 | minus: 20
-%}
<span style="--x: {{ ex }}%; --d: -{{ ed }}s; --t: {{ et }}s; --s: {{ es }}px; --dx: {{ edx }}px;"></span>
{%- endfor -%}
</div>
{%- endif -%}
<div class="mf-drop__frame" aria-hidden="true">
<div class="mf-drop__beam"></div>
<div class="mf-drop__window{% if show_art %} mf-drop__window--art{% endif %}">
{%- if show_art -%}
<div class="mf-drop__art">
<div class="mf-drop__orb"></div>
<div class="mf-drop__bottle">
<span class="mf-drop__bulb"></span>
<span class="mf-drop__collar"></span>
<span class="mf-drop__glass">
<span class="mf-drop__liquid"></span>
<span class="mf-drop__pipette"></span>
<span class="mf-drop__glint"></span>
</span>
</div>
<div class="mf-drop__plinth"></div>
</div>
{%- elsif s.image != blank -%}
{{
s.image
| image_url: width: 1200
| image_tag:
loading: 'lazy',
sizes: '(min-width: 990px) 36vw, (min-width: 750px) 44vw, 78vw',
widths: '400, 600, 800, 1000, 1200',
class: 'mf-drop__img'
}}
{%- else -%}
{{
drop_product.featured_media
| image_url: width: 1200
| image_tag:
loading: 'lazy',
sizes: '(min-width: 990px) 36vw, (min-width: 750px) 44vw, 78vw',
widths: '400, 600, 800, 1000, 1200',
class: 'mf-drop__img'
}}
{%- endif -%}
<span class="mf-drop__sweep"></span>
</div>
</div>
<div class="mf-drop__floor" aria-hidden="true"></div>
{%- if s.show_product_info and drop_product != blank -%}
<p class="mf-drop__tag">
<span class="mf-drop__tag-name">{{ drop_product.title | escape }}</span>
<span class="mf-drop__tag-price">
{{- drop_product.price | money -}}
{%- if drop_product.compare_at_price > drop_product.price %} <s>{{ drop_product.compare_at_price | money }}</s>{% endif -%}
</span>
</p>
{%- endif -%}
</div>
<div class="mf-drop__body">
<div class="mf-drop__clock mf-drop__reveal" style="--mf-drop-i: 3;">
<div class="mf-drop__units" aria-hidden="true">
{%- for i in (1..4) -%}
{%- if i == 1 and s.mode == 'daily' -%}{%- continue -%}{%- endif -%}
{%- liquid
case i
when 1
assign u_key = 'days'
assign u_val = t_days
assign u_label = s.label_days
when 2
assign u_key = 'hours'
assign u_val = t_hours
assign u_label = s.label_hours
when 3
assign u_key = 'minutes'
assign u_val = t_minutes
assign u_label = s.label_minutes
else
assign u_key = 'seconds'
assign u_val = t_seconds
assign u_label = s.label_seconds
endcase
if u_val < 10
assign u_str = u_val | prepend: '0'
else
assign u_str = u_val | append: ''
endif
assign u_chars = u_str | split: ''
-%}
<div class="mf-drop__unit mf-drop__unit--{{ u_key }}" data-mf-unit="{{ u_key }}">
<span class="mf-drop__tile">
<span class="mf-drop__digits" data-mf-digits>
{%- for c in u_chars -%}
<span class="mf-drop__slot"><span class="mf-drop__d">{{ c }}</span></span>
{%- endfor -%}
</span>
</span>
<span class="mf-drop__label">{{ u_label | escape }}</span>
</div>
{%- endfor -%}
</div>
<p class="mf-drop__sr" role="timer" data-mf-sr>
{%- if s.mode != 'daily' %}{{ t_days }} {{ s.label_days | escape }}, {% endif -%}
{{ t_hours }} {{ s.label_hours | escape }}, {{ t_minutes }} {{ s.label_minutes | escape }}
</p>
{%- if s.mode == 'daily' -%}
{%- if s.daily_text != blank -%}
{%- assign daily_parts = s.daily_text | split: '[time]' -%}
<p class="mf-drop__note mf-drop__note--daily">
<svg viewBox="0 0 20 20" width="16" height="16" aria-hidden="true"><path d="M2.5 6.5h9v7h-9zM11.5 9h3.2l2.8 2.6v1.9h-6M5.5 16a1.6 1.6 0 1 0 0-.1M14.5 16a1.6 1.6 0 1 0 0-.1" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg>
<span>
{{- daily_parts[0] | escape -}}
<strong data-mf-inline>{{ t_hours }}{{ h_short }} {{ t_minutes }}{{ m_short }}</strong>
{{- daily_parts[1] | escape -}}
</span>
</p>
{%- endif -%}
{%- elsif s.ends_label != blank -%}
<p class="mf-drop__note">
<svg viewBox="0 0 20 20" width="16" height="16" aria-hidden="true"><circle cx="10" cy="10" r="7.2" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M10 6v4.4l2.8 1.7" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>
<span>
{{- s.ends_label | escape }}
<time datetime="{{ end_iso }}" data-mf-ends>{{ end_raw | date: '%a %e %b, %H:%M' }} (UTC{{ off_str }})</time>
</span>
</p>
{%- endif -%}
</div>
<div class="mf-drop__ended">
<span class="mf-drop__ended-mark" aria-hidden="true"></span>
<p>{{ s.ended_message | escape }}</p>
</div>
<div class="mf-drop__actions mf-drop__reveal" style="--mf-drop-i: 4;">
{%- if s.promo_code != blank -%}
<div class="mf-drop__promo">
{%- if s.promo_label != blank -%}
<span class="mf-drop__promo-label">{{ s.promo_label | escape }}</span>
{%- endif -%}
<span class="mf-drop__code" data-mf-code>{{ s.promo_code | escape }}</span>
<button type="button" class="mf-drop__copy" data-mf-copy data-code="{{ s.promo_code | escape }}">
<svg class="mf-drop__copy-icon" viewBox="0 0 20 20" width="15" height="15" aria-hidden="true"><rect x="6.5" y="6.5" width="10" height="10" rx="2.4" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M13.5 4.2A2.2 2.2 0 0 0 11.4 3H5.2A2.2 2.2 0 0 0 3 5.2v6.2a2.2 2.2 0 0 0 1.2 2" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
<svg class="mf-drop__check-icon" viewBox="0 0 20 20" width="15" height="15" aria-hidden="true"><path d="m4.5 10.5 3.6 3.5 7.4-8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
<span data-mf-copy-label>{{ s.copy_label | escape }}</span>
<span class="mf-drop__visually-hidden">{{ s.promo_code | escape }}</span>
</button>
</div>
{%- endif -%}
{%- if s.button_label != blank -%}
<a class="mf-drop__cta" href="{{ cta_url }}">
<span>{{ s.button_label | escape }}</span>
<svg viewBox="0 0 20 20" width="18" height="18" aria-hidden="true"><path d="M4 10h11m-4.5-5 5 5-5 5" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg>
</a>
{%- endif -%}
</div>
<p class="mf-drop__visually-hidden" role="status" aria-live="polite" data-mf-status></p>
</div>
</div>
</mf-drop-countdown>
{% stylesheet %}
.mf-drop {
--mf-drop-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
--mf-drop-gx: 27%;
position: relative;
isolation: isolate;
display: block;
overflow: hidden;
padding: var(--mf-drop-pt, 104px) 0 var(--mf-drop-pb, 104px);
background: var(--mf-drop-bg, #0b0807);
color: var(--mf-drop-fg, #f7efe6);
font-family: inherit;
}
.mf-drop[hidden],
.mf-drop--ended.mf-drop--hide-ended:not(.mf-drop--editor) {
display: none;
}
.mf-drop--right {
--mf-drop-gx: 73%;
}
.mf-drop *,
.mf-drop *::before,
.mf-drop *::after {
box-sizing: border-box;
}
/* Layered background: ember glow, cool counter-glow, spotlight rays, grain */
.mf-drop__bg {
position: absolute;
z-index: -1;
inset: 0;
pointer-events: none;
}
.mf-drop__bg::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(34% 52% at var(--mf-drop-gx) 56%, var(--mf-drop-accent-35), transparent 72%),
radial-gradient(38% 46% at calc(100% - var(--mf-drop-gx)) 4%, var(--mf-drop-glow-40), transparent 70%),
radial-gradient(70% 40% at 50% 112%, var(--mf-drop-glow-40), transparent 70%),
linear-gradient(180deg, rgba(255, 255, 255, 0.025), transparent 38%, rgba(0, 0, 0, 0.35));
}
.mf-drop__bg::after {
content: "";
position: absolute;
inset: 0;
opacity: 0.16;
mix-blend-mode: overlay;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.mf-drop__rays {
position: absolute;
top: -30%;
left: calc(var(--mf-drop-gx) - 30%);
width: 60%;
height: 120%;
background: conic-gradient(from 180deg at 50% 0%, transparent 158deg, var(--mf-drop-accent-18) 170deg, transparent 176deg, var(--mf-drop-accent-18) 184deg, transparent 190deg, var(--mf-drop-accent-18) 196deg, transparent 204deg);
filter: blur(6px);
-webkit-mask-image: linear-gradient(180deg, #000 20%, transparent 85%);
mask-image: linear-gradient(180deg, #000 20%, transparent 85%);
transform-origin: 50% 0;
animation: mf-drop-sway 11s ease-in-out infinite;
}
.mf-drop__inner {
display: grid;
grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
grid-template-areas: "stage head" "stage body";
column-gap: clamp(40px, 7vw, 116px);
align-items: center;
width: min(100% - 40px, 1240px);
margin: 0 auto;
}
.mf-drop--right .mf-drop__inner {
grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
grid-template-areas: "head stage" "body stage";
}
.mf-drop__head {
grid-area: head;
align-self: end;
}
.mf-drop__body {
grid-area: body;
align-self: start;
}
/* Copy */
.mf-drop__eyebrow {
display: inline-flex;
align-items: center;
gap: 10px;
margin: 0 0 26px;
padding: 8px 15px 8px 12px;
border: 1px solid rgba(255, 255, 255, 0.14);
border-radius: 999px;
background: rgba(255, 255, 255, 0.04);
color: currentColor;
font: 500 11px/1.3 ui-monospace, SFMono-Regular, Menlo, monospace;
letter-spacing: 0.18em;
text-transform: uppercase;
}
.mf-drop__eyebrow i {
position: relative;
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--mf-drop-accent);
box-shadow: 0 0 12px var(--mf-drop-accent);
}
.mf-drop__eyebrow i::after {
content: "";
position: absolute;
inset: -4px;
border-radius: 50%;
border: 1px solid var(--mf-drop-accent);
animation: mf-drop-ping 1.8s ease-out infinite;
}
.mf-drop__title {
margin: 0;
max-width: 12ch;
font-family: inherit;
font-size: clamp(44px, 6.4vw, 94px);
font-weight: 600;
line-height: 0.94;
letter-spacing: -0.045em;
text-transform: none;
color: currentColor;
}
.mf-drop__title em {
display: inline-block;
padding-right: 0.08em;
font-family: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
font-style: italic;
font-weight: 400;
letter-spacing: -0.035em;
color: transparent;
background: linear-gradient(100deg, #fff4e8 0%, var(--mf-drop-accent) 58%, #ffd9bf 100%);
-webkit-background-clip: text;
background-clip: text;
}
.mf-drop__text {
max-width: 46ch;
margin-top: 22px;
font-size: 17px;
line-height: 1.6;
letter-spacing: 0;
opacity: 0.74;
}
.mf-drop__text p {
margin: 0;
}
.mf-drop__text p + p {
margin-top: 10px;
}
/* Stage: arch display case with a rotating rim light */
.mf-drop__stage {
grid-area: stage;
position: relative;
display: grid;
place-items: center;
padding: 34px 0 44px;
}
.mf-drop__halo {
position: absolute;
width: 92%;
aspect-ratio: 1;
border-radius: 50%;
background: radial-gradient(circle, var(--mf-drop-accent-60), transparent 64%);
filter: blur(46px);
opacity: 0.8;
animation: mf-drop-breathe 6s ease-in-out infinite;
}
.mf-drop__frame {
position: relative;
z-index: 1;
width: min(100%, 430px);
aspect-ratio: 4 / 5;
padding: 2px;
border-radius: 999px 999px 34px 34px;
overflow: hidden;
isolation: isolate;
background: rgba(255, 255, 255, 0.14);
box-shadow: 0 0 70px -12px var(--mf-drop-accent-35), 0 50px 110px -40px var(--mf-drop-accent-60), 0 30px 70px -30px rgba(0, 0, 0, 0.9);
}
.mf-drop__beam {
position: absolute;
top: 50%;
left: 50%;
width: 170%;
aspect-ratio: 1;
background: conic-gradient(from 0deg, transparent 0 38%, var(--mf-drop-accent) 56%, #fff 64%, var(--mf-drop-accent) 72%, transparent 88%);
transform: translate(-50%, -50%);
animation: mf-drop-spin 7s linear infinite;
}
.mf-drop__window {
position: relative;
z-index: 1;
height: 100%;
border-radius: 999px 999px 32px 32px;
overflow: hidden;
background: #140e0b;
}
.mf-drop__window::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
background: linear-gradient(180deg, transparent 55%, rgba(12, 7, 5, 0.45)), radial-gradient(120% 70% at 50% 110%, var(--mf-drop-accent-35), transparent 60%);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1), inset 22px 0 44px -30px var(--mf-drop-accent), inset -22px 0 44px -30px var(--mf-drop-accent), inset 0 30px 60px -30px rgba(255, 255, 255, 0.35);
}
.mf-drop__img {
display: block;
width: 100%;
height: 100%;
max-width: none;
object-fit: cover;
}
.mf-drop__sweep {
position: absolute;
z-index: 2;
inset: -20% -60%;
background: linear-gradient(105deg, transparent 42%, rgba(255, 255, 255, 0.28) 50%, transparent 58%);
transform: translateX(-60%);
pointer-events: none;
}
.mf-drop__floor {
position: absolute;
bottom: 16px;
width: 62%;
height: 46px;
border-radius: 50%;
background: radial-gradient(closest-side, var(--mf-drop-accent-60), transparent);
filter: blur(14px);
}
.mf-drop__embers {
position: absolute;
inset: 0;
z-index: 2;
pointer-events: none;
}
.mf-drop__embers span {
position: absolute;
bottom: 12%;
left: var(--x);
width: var(--s);
height: var(--s);
border-radius: 50%;
background: #ffe3c9;
box-shadow: 0 0 8px 1px var(--mf-drop-accent);
opacity: 0;
animation: mf-drop-rise var(--t) linear var(--d) infinite;
}
/* Fallback art: a glowing dropper bottle in a lit niche */
.mf-drop__window--art {
background: radial-gradient(80% 60% at 50% 42%, var(--mf-drop-accent-18), transparent 70%), linear-gradient(180deg, #1c1310, #0b0706 78%);
}
.mf-drop__art {
position: absolute;
inset: 0;
}
.mf-drop__orb {
position: absolute;
top: 16%;
left: 50%;
width: 64%;
aspect-ratio: 1;
border-radius: 50%;
background: radial-gradient(circle at 50% 45%, var(--mf-drop-accent-60), var(--mf-drop-accent-18) 45%, transparent 68%);
filter: blur(6px);
transform: translateX(-50%);
}
.mf-drop__bottle {
position: absolute;
left: 50%;
bottom: 17%;
width: 38%;
height: 66%;
transform: translateX(-50%);
filter: drop-shadow(0 26px 30px rgba(0, 0, 0, 0.6));
}
.mf-drop__bulb {
position: absolute;
top: 0;
left: 33%;
width: 34%;
height: 20%;
border-radius: 48% 48% 14% 14% / 62% 62% 14% 14%;
background: linear-gradient(90deg, #1a1210, #4a3a33 40%, #2a1e1a 70%, #120c0a);
}
.mf-drop__collar {
position: absolute;
top: 19%;
left: 27%;
width: 46%;
height: 11%;
border-radius: 6px;
background: linear-gradient(90deg, #7a5427, #f3cf8d 32%, #fff1cf 44%, #b98a4b 70%, #6a4520);
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.35);
}
.mf-drop__glass {
position: absolute;
top: 29%;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
border-radius: 24% 24% 16% 16% / 16% 16% 10% 10%;
background: linear-gradient(90deg, rgba(120, 52, 18, 0.95), rgba(214, 112, 46, 0.72) 30%, rgba(255, 176, 104, 0.5) 50%, rgba(196, 96, 38, 0.78) 72%, rgba(96, 38, 12, 0.96));
box-shadow: inset 0 0 0 1px rgba(255, 220, 190, 0.35), inset 0 -30px 40px -10px rgba(40, 12, 2, 0.8), 0 0 60px -6px var(--mf-drop-accent-60);
}
.mf-drop__liquid {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 64%;
background: linear-gradient(180deg, rgba(255, 196, 120, 0.9), rgba(255, 128, 52, 0.55) 30%, rgba(150, 50, 10, 0.4));
box-shadow: inset 0 2px 0 rgba(255, 236, 200, 0.85);
}
.mf-drop__pipette {
position: absolute;
top: -2%;
left: 45%;
width: 10%;
height: 78%;
border-radius: 0 0 40% 40% / 0 0 8% 8%;
background: linear-gradient(90deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.42), rgba(255, 255, 255, 0.1));
}
.mf-drop__glint {
position: absolute;
top: 8%;
left: 12%;
width: 9%;
height: 72%;
border-radius: 999px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.85), rgba(255, 255, 255, 0.1));
filter: blur(0.5px);
}
.mf-drop__plinth {
position: absolute;
left: 50%;
bottom: 10%;
width: 64%;
height: 7%;
border-radius: 50%;
background: radial-gradient(closest-side, rgba(255, 190, 140, 0.35), rgba(0, 0, 0, 0.4) 70%, transparent);
transform: translateX(-50%);
}
/* Product tag */
.mf-drop__tag {
position: absolute;
z-index: 3;
bottom: 22px;
left: 50%;
display: inline-flex;
align-items: center;
gap: 14px;
margin: 0;
transform: translateX(-50%);
padding: 11px 18px;
border: 1px solid rgba(255, 255, 255, 0.14);
border-radius: 999px;
background: rgba(18, 12, 10, 0.62);
-webkit-backdrop-filter: blur(14px) saturate(1.3);
backdrop-filter: blur(14px) saturate(1.3);
box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.9);
font-size: 14px;
line-height: 1.2;
letter-spacing: 0;
white-space: nowrap;
}
.mf-drop__tag-name {
font-weight: 600;
}
.mf-drop__tag-price {
display: inline-flex;
align-items: baseline;
gap: 8px;
padding-left: 14px;
border-left: 1px solid rgba(255, 255, 255, 0.18);
color: var(--mf-drop-accent);
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.mf-drop__tag-price s {
color: currentColor;
font-size: 12px;
font-weight: 400;
opacity: 0.55;
color: var(--mf-drop-fg);
}
/* Clock */
.mf-drop__clock {
margin-top: clamp(30px, 3.4vw, 44px);
}
.mf-drop__units {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: clamp(8px, 1.1vw, 14px);
max-width: 540px;
}
.mf-drop--daily .mf-drop__units {
grid-template-columns: repeat(3, minmax(0, 1fr));
max-width: 412px;
}
.mf-drop__unit {
display: grid;
justify-items: center;
gap: 11px;
min-width: 0;
}
.mf-drop__tile {
position: relative;
display: flex;
justify-content: center;
width: 100%;
padding: clamp(14px, 1.7vw, 22px) 0;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 18px;
overflow: hidden;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.085), rgba(255, 255, 255, 0.02) 52%, rgba(255, 255, 255, 0.045));
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 24px 44px -26px rgba(0, 0, 0, 0.9);
}
.mf-drop__tile::before {
content: "";
position: absolute;
z-index: 2;
left: 0;
right: 0;
top: 50%;
height: 1px;
background: rgba(0, 0, 0, 0.5);
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06);
}
.mf-drop__tile::after {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(90% 60% at 50% 115%, var(--mf-drop-accent-35), transparent 70%);
pointer-events: none;
}
.mf-drop__unit--seconds .mf-drop__tile {
border-color: var(--mf-drop-accent-35);
}
.mf-drop__digits {
position: relative;
z-index: 1;
display: flex;
font-size: clamp(40px, 4.7vw, 68px);
font-weight: 600;
line-height: 1;
letter-spacing: 0;
font-variant-numeric: tabular-nums;
color: #fff8f1;
text-shadow: 0 0 20px var(--mf-drop-accent-60), 0 0 54px var(--mf-drop-accent-35);
}
.mf-drop__slot {
position: relative;
display: block;
width: 0.62em;
height: 1.08em;
}
.mf-drop__d {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
}
.mf-drop__d--in {
animation: mf-drop-in 0.62s var(--mf-drop-ease) both;
}
.mf-drop__d--out {
animation: mf-drop-out 0.62s var(--mf-drop-ease) both;
}
.mf-drop__label {
font-size: 11px;
font-weight: 500;
line-height: 1.2;
letter-spacing: 0.18em;
text-transform: uppercase;
opacity: 0.58;
}
.mf-drop__note {
display: flex;
align-items: center;
gap: 9px;
margin: 20px 0 0;
font-size: 14px;
line-height: 1.45;
letter-spacing: 0;
opacity: 0.72;
}
.mf-drop__note svg {
flex-shrink: 0;
color: var(--mf-drop-accent);
}
.mf-drop__note time {
font-weight: 600;
}
.mf-drop__note--daily {
font-size: 15px;
opacity: 0.86;
}
.mf-drop__note strong {
color: var(--mf-drop-accent);
font-weight: 700;
font-variant-numeric: tabular-nums;
}
/* Ended state */
.mf-drop__ended {
display: none;
align-items: center;
gap: 14px;
max-width: 520px;
margin-top: clamp(30px, 3.4vw, 44px);
padding: 20px 22px;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 18px;
background: rgba(255, 255, 255, 0.04);
}
.mf-drop__ended p {
margin: 0;
font-size: 16px;
line-height: 1.5;
letter-spacing: 0;
}
.mf-drop__ended-mark {
flex-shrink: 0;
width: 10px;
height: 10px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.35);
}
.mf-drop--ended .mf-drop__ended {
display: flex;
}
.mf-drop--ended .mf-drop__clock,
.mf-drop--ended .mf-drop__promo,
.mf-drop--ended .mf-drop__eyebrow i {
display: none;
}
/* Actions */
.mf-drop__actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 14px;
margin-top: clamp(28px, 3vw, 38px);
}
.mf-drop__promo {
display: inline-flex;
align-items: center;
gap: 12px;
min-height: 54px;
padding: 6px 6px 6px 18px;
border: 1px dashed rgba(255, 255, 255, 0.3);
border-radius: 999px;
background: rgba(255, 255, 255, 0.04);
}
.mf-drop__promo-label {
font-size: 11px;
font-weight: 500;
line-height: 1.2;
letter-spacing: 0.14em;
text-transform: uppercase;
opacity: 0.6;
}
.mf-drop__code {
font: 600 15px/1 ui-monospace, SFMono-Regular, Menlo, monospace;
letter-spacing: 0.12em;
color: #fff;
-webkit-user-select: all;
user-select: all;
}
.mf-drop__copy {
-webkit-appearance: none;
appearance: none;
display: inline-flex;
align-items: center;
gap: 7px;
min-height: 42px;
margin: 0;
padding: 0 16px;
border: 0;
border-radius: 999px;
background: rgba(255, 255, 255, 0.1);
color: currentColor;
font: inherit;
font-size: 13px;
font-weight: 600;
line-height: 1;
letter-spacing: 0;
text-transform: none;
cursor: pointer;
transition: background 0.25s ease, color 0.25s ease, transform 0.2s ease;
}
.mf-drop__copy:hover {
background: rgba(255, 255, 255, 0.18);
}
.mf-drop__copy:active {
transform: scale(0.96);
}
.mf-drop__check-icon {
display: none;
}
.mf-drop__copy[data-state="done"] {
background: var(--mf-drop-accent);
color: var(--mf-drop-cta-fg);
}
.mf-drop__copy[data-state="done"] .mf-drop__check-icon {
display: block;
}
.mf-drop__copy[data-state="done"] .mf-drop__copy-icon,
.mf-drop__copy[data-state="manual"] .mf-drop__copy-icon {
display: none;
}
.mf-drop__cta {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 14px;
min-height: 54px;
padding: 0 28px;
overflow: hidden;
border-radius: 999px;
background: var(--mf-drop-accent);
color: var(--mf-drop-cta-fg);
font-size: 15px;
font-weight: 700;
line-height: 1;
letter-spacing: 0;
text-decoration: none;
text-transform: none;
box-shadow: 0 18px 44px -14px var(--mf-drop-accent-60), inset 0 1px 0 rgba(255, 255, 255, 0.45);
transition: transform 0.25s var(--mf-drop-ease), box-shadow 0.25s ease;
}
.mf-drop__cta::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, 0.5) 50%, transparent 65%);
transform: translateX(-110%);
transition: transform 0.7s var(--mf-drop-ease);
}
.mf-drop__cta svg {
transition: transform 0.25s var(--mf-drop-ease);
}
.mf-drop__cta:hover {
transform: translateY(-2px);
box-shadow: 0 24px 54px -14px var(--mf-drop-accent-60), inset 0 1px 0 rgba(255, 255, 255, 0.45);
}
.mf-drop__cta:hover::after {
transform: translateX(110%);
}
.mf-drop__cta:hover svg {
transform: translateX(4px);
}
.mf-drop__cta:focus-visible,
.mf-drop__copy:focus-visible {
outline: 2px solid var(--mf-drop-fg);
outline-offset: 3px;
}
.mf-drop__sr,
.mf-drop__visually-hidden {
position: absolute !important;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0 0 0 0);
white-space: nowrap;
border: 0;
}
/* Entrance (only when JS confirms motion is welcome) */
.mf-drop--js .mf-drop__reveal {
opacity: 0;
transform: translateY(22px);
transition: opacity 0.8s ease, transform 0.9s var(--mf-drop-ease);
transition-delay: calc(var(--mf-drop-i, 0) * 90ms + 120ms);
}
.mf-drop--js .mf-drop__frame {
opacity: 0;
transform: translateY(30px) scale(0.96);
transition: opacity 1s ease, transform 1.2s var(--mf-drop-ease);
}
.mf-drop--js.mf-drop--in .mf-drop__reveal,
.mf-drop--js.mf-drop--in .mf-drop__frame {
opacity: 1;
transform: none;
}
.mf-drop--js.mf-drop--in .mf-drop__sweep {
animation: mf-drop-sweep 1.6s 0.5s var(--mf-drop-ease) both;
}
@keyframes mf-drop-spin {
to { transform: translate(-50%, -50%) rotate(360deg); }
}
@keyframes mf-drop-breathe {
0%, 100% { transform: scale(0.94); opacity: 0.7; }
50% { transform: scale(1.04); opacity: 0.95; }
}
@keyframes mf-drop-sway {
0%, 100% { transform: rotate(-4deg); }
50% { transform: rotate(4deg); }
}
@keyframes mf-drop-ping {
0% { transform: scale(0.6); opacity: 0.9; }
100% { transform: scale(1.9); opacity: 0; }
}
@keyframes mf-drop-rise {
0% { transform: translate3d(0, 0, 0); opacity: 0; }
12% { opacity: 0.95; }
75% { opacity: 0.5; }
100% { transform: translate3d(var(--dx), -380px, 0); opacity: 0; }
}
@keyframes mf-drop-sweep {
from { transform: translateX(-60%); }
to { transform: translateX(60%); }
}
@keyframes mf-drop-in {
from { transform: translateY(-62%) scale(0.92); opacity: 0; filter: blur(5px); }
to { transform: none; opacity: 1; filter: blur(0); }
}
@keyframes mf-drop-out {
from { transform: none; opacity: 1; filter: blur(0); }
to { transform: translateY(58%) scale(0.92); opacity: 0; filter: blur(5px); }
}
@media screen and (max-width: 989px) {
.mf-drop__inner,
.mf-drop--right .mf-drop__inner {
column-gap: 36px;
}
.mf-drop__actions {
flex-direction: column;
align-items: stretch;
}
.mf-drop__promo {
justify-content: space-between;
}
}
@media screen and (max-width: 749px) {
.mf-drop {
--mf-drop-gx: 50%;
padding-top: min(var(--mf-drop-pt, 104px), 64px);
padding-bottom: min(var(--mf-drop-pb, 104px), 64px);
}
.mf-drop__inner,
.mf-drop--right .mf-drop__inner {
grid-template-columns: minmax(0, 1fr);
grid-template-areas: "head" "stage" "body";
text-align: center;
}
.mf-drop__bg::before {
background:
radial-gradient(70% 34% at 50% 44%, var(--mf-drop-accent-35), transparent 72%),
radial-gradient(80% 30% at 90% 0%, var(--mf-drop-glow-40), transparent 70%),
radial-gradient(90% 30% at 50% 104%, var(--mf-drop-glow-40), transparent 70%);
}
.mf-drop__eyebrow {
margin-bottom: 20px;
}
.mf-drop__title {
max-width: none;
font-size: clamp(40px, 12.4vw, 60px);
}
.mf-drop__text {
margin: 16px auto 0;
font-size: 16px;
}
.mf-drop__stage {
padding: 30px 0 40px;
}
.mf-drop__frame {
width: min(74vw, 320px);
}
.mf-drop__tag {
bottom: 20px;
font-size: 13px;
padding: 10px 16px;
}
.mf-drop__clock {
margin-top: 10px;
}
.mf-drop__units,
.mf-drop--daily .mf-drop__units {
margin: 0 auto;
}
.mf-drop__tile {
border-radius: 14px;
}
.mf-drop__digits {
font-size: clamp(32px, 10vw, 46px);
}
.mf-drop__label {
font-size: 10px;
letter-spacing: 0.14em;
}
.mf-drop__note {
justify-content: center;
text-align: left;
}
.mf-drop__ended {
margin-left: auto;
margin-right: auto;
text-align: left;
}
.mf-drop__promo {
padding-left: 16px;
}
.mf-drop__promo-label {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
.mf-drop__rays,
.mf-drop__halo,
.mf-drop__beam,
.mf-drop__embers span,
.mf-drop__eyebrow i::after,
.mf-drop__d--in,
.mf-drop__d--out,
.mf-drop--js.mf-drop--in .mf-drop__sweep {
animation: none;
}
.mf-drop__embers {
display: none;
}
.mf-drop__beam {
transform: translate(-50%, -50%) rotate(200deg);
}
.mf-drop__cta,
.mf-drop__cta::after,
.mf-drop__cta svg,
.mf-drop__copy,
.mf-drop--js .mf-drop__reveal,
.mf-drop--js .mf-drop__frame {
transition: none;
}
.mf-drop--js .mf-drop__reveal,
.mf-drop--js .mf-drop__frame {
opacity: 1;
transform: none;
}
}
{% endstylesheet %}
{% javascript %}
if (!customElements.get('mf-drop-countdown')) {
customElements.define(
'mf-drop-countdown',
class extends HTMLElement {
connectedCallback() {
this.mode = this.dataset.mode === 'daily' ? 'daily' : 'fixed';
this.reduce = window.matchMedia('(prefers-reduced-motion: reduce)');
this.units = {};
this.querySelectorAll('[data-mf-unit]').forEach((unit) => {
const digits = unit.querySelector('[data-mf-digits]');
if (digits) this.units[unit.dataset.mfUnit] = digits;
});
this.sr = this.querySelector('[data-mf-sr]');
this.inline = this.querySelector('[data-mf-inline]');
this.endsEl = this.querySelector('[data-mf-ends]');
this.copyBtn = this.querySelector('[data-mf-copy]');
this.status = this.querySelector('[data-mf-status]');
this.offset = this.parseOffset(this.dataset.offset);
this.cutoff = Math.min(23, Math.max(0, parseInt(this.dataset.cutoff, 10) || 0));
this.lastMinute = null;
this.first = true;
if (this.mode === 'fixed') {
this.target = this.parseEnd(this.dataset.end);
if (window.__MF_PREVIEW__ && !(this.target > Date.now())) {
// Preview only: keep the demo alive with a believable deadline.
this.target = Date.now() + ((2 * 24 + 14) * 60 + 32) * 60000 + 18000;
}
if (this.target > Date.now()) this.classList.remove('mf-drop--ended');
this.localizeEnds();
}
if (this.copyBtn) {
this.copyLabel = this.copyBtn.querySelector('[data-mf-copy-label]');
this.copyText = this.copyLabel ? this.copyLabel.textContent : '';
this.onCopy = this.onCopy.bind(this);
this.copyBtn.addEventListener('click', this.onCopy);
}
if (!this.reduce.matches && 'IntersectionObserver' in window) {
this.classList.add('mf-drop--js');
this.io = new IntersectionObserver(
(entries) => {
if (entries.some((e) => e.isIntersecting)) {
this.classList.add('mf-drop--in');
this.io.disconnect();
}
},
{ threshold: 0.12 }
);
this.io.observe(this);
}
this.tick = this.tick.bind(this);
this.tick();
}
disconnectedCallback() {
clearTimeout(this.timer);
clearTimeout(this.copyTimer);
if (this.io) this.io.disconnect();
if (this.copyBtn && this.onCopy) this.copyBtn.removeEventListener('click', this.onCopy);
}
parseOffset(value) {
const m = String(value || '').match(/^([+-])(\d{2}):(\d{2})$/);
if (!m) return 0;
const minutes = Number(m[2]) * 60 + Number(m[3]);
return m[1] === '-' ? -minutes : minutes;
}
parseEnd(value) {
const m = String(value || '').trim().match(/^(\d{4})-(\d{1,2})-(\d{1,2})(?:[ T](\d{1,2}):(\d{2}))?/);
if (!m) return NaN;
const utc = Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4] || 0), Number(m[5] || 0));
return utc - this.offset * 60000;
}
nextCutoff(now) {
const shift = this.offset * 60000;
const local = new Date(now + shift);
let cut = Date.UTC(local.getUTCFullYear(), local.getUTCMonth(), local.getUTCDate(), this.cutoff, 0) - shift;
if (cut <= now) cut += 86400000;
return cut;
}
localizeEnds() {
if (!this.endsEl || !(this.target > 0)) return;
try {
const date = new Date(this.target);
const fmt = new Intl.DateTimeFormat(document.documentElement.lang || undefined, {
weekday: 'short',
day: 'numeric',
month: 'short',
hour: '2-digit',
minute: '2-digit',
timeZoneName: 'short',
});
this.endsEl.textContent = fmt.format(date);
this.endsEl.setAttribute('datetime', date.toISOString());
} catch (e) {
/* keep the server-rendered date */
}
}
tick() {
const now = Date.now();
const target = this.mode === 'daily' ? this.nextCutoff(now) : this.target;
if (!(target > 0)) return;
const left = Math.max(0, target - now);
const total = Math.ceil(left / 1000);
const d = Math.floor(total / 86400);
const h = Math.floor((total % 86400) / 3600);
const m = Math.floor((total % 3600) / 60);
const sec = total % 60;
this.setUnit('days', d);
this.setUnit('hours', h);
this.setUnit('minutes', m);
this.setUnit('seconds', sec);
this.first = false;
const minuteKey = d + ':' + h + ':' + m;
if (minuteKey !== this.lastMinute) {
this.lastMinute = minuteKey;
const ds = this.dataset;
if (this.sr) {
this.sr.textContent =
(this.mode === 'daily' ? '' : d + ' ' + ds.labelDays + ', ') +
h + ' ' + ds.labelHours + ', ' + m + ' ' + ds.labelMinutes;
}
if (this.inline) {
const hs = (ds.labelHours || 'h').charAt(0).toLowerCase();
const ms = (ds.labelMinutes || 'm').charAt(0).toLowerCase();
this.inline.textContent = h + hs + ' ' + m + ms;
}
}
if (this.mode === 'fixed' && left <= 0) {
this.classList.add('mf-drop--ended');
return;
}
this.timer = setTimeout(this.tick, 1000 - (Date.now() % 1000) + 12);
}
setUnit(key, value) {
const el = this.units[key];
if (!el) return;
const str = String(value).padStart(2, '0');
if (el.dataset.value === str) return;
el.dataset.value = str;
const animate = !this.first && !this.reduce.matches;
let slots = el.children;
while (slots.length < str.length) {
const slot = document.createElement('span');
slot.className = 'mf-drop__slot';
slot.innerHTML = '<span class="mf-drop__d"></span>';
el.insertBefore(slot, el.firstChild);
}
while (slots.length > str.length) el.removeChild(el.firstChild);
for (let i = 0; i < str.length; i++) {
const slot = slots[i];
const current = slot.lastElementChild;
if (current && current.textContent === str[i]) continue;
slot.querySelectorAll('.mf-drop__d--out').forEach((n) => n.remove());
if (!animate || !current) {
if (current) current.textContent = str[i];
continue;
}
const next = document.createElement('span');
next.className = 'mf-drop__d mf-drop__d--in';
next.textContent = str[i];
current.classList.remove('mf-drop__d--in');
current.classList.add('mf-drop__d--out');
slot.appendChild(next);
setTimeout(() => current.remove(), 700);
}
}
onCopy() {
const code = this.copyBtn.dataset.code || '';
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(code).then(
() => this.copied(true, code),
() => this.copyFallback(code)
);
} else {
this.copyFallback(code);
}
}
copyFallback(code) {
const node = this.querySelector('[data-mf-code]');
let ok = false;
try {
const range = document.createRange();
range.selectNodeContents(node);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
ok = document.execCommand('copy');
} catch (e) {
ok = false;
}
this.copied(ok, code);
}
copied(ok, code) {
const message = ok ? this.dataset.copied : this.dataset.copyFallback;
this.copyBtn.dataset.state = ok ? 'done' : 'manual';
if (this.copyLabel) this.copyLabel.textContent = message;
if (this.status) this.status.textContent = ok ? message + ': ' + code : message;
clearTimeout(this.copyTimer);
this.copyTimer = setTimeout(() => {
delete this.copyBtn.dataset.state;
if (this.copyLabel) this.copyLabel.textContent = this.copyText;
}, ok ? 2200 : 4200);
}
}
);
}
{% endjavascript %}
{% schema %}
{
"name": "EX · Drop countdown",
"tag": "section",
"class": "mf-section",
"disabled_on": {
"groups": ["header", "footer"]
},
"settings": [
{
"type": "header",
"content": "Content"
},
{
"type": "text",
"id": "eyebrow",
"label": "Eyebrow",
"default": "Limited drop · 500 units"
},
{
"type": "inline_richtext",
"id": "heading",
"label": "Heading",
"info": "Wrap words in italics to render them in the glowing serif accent.",
"default": "The Solstice <em>Edition</em>"
},
{
"type": "select",
"id": "heading_tag",
"label": "Heading HTML tag",
"info": "Use H1 only when this is the first section of the page.",
"options": [
{ "value": "h1", "label": "H1" },
{ "value": "h2", "label": "H2" }
],
"default": "h2"
},
{
"type": "richtext",
"id": "text",
"label": "Text",
"default": "<p>Our cult vitamin C serum in hand-blown amber glass with a gilded dropper. 500 numbered bottles, released once and never restocked.</p>"
},
{
"type": "header",
"content": "Countdown"
},
{
"type": "select",
"id": "mode",
"label": "Countdown type",
"options": [
{ "value": "fixed", "label": "Fixed date" },
{ "value": "daily", "label": "Daily cutoff" }
],
"default": "fixed"
},
{
"type": "text",
"id": "end_date",
"label": "End date and time",
"info": "Fixed date only. Format YYYY-MM-DD HH:MM on a 24-hour clock, e.g. 2026-12-21 20:00.",
"default": "2026-12-21 20:00"
},
{
"type": "select",
"id": "utc_offset",
"label": "Time zone",
"info": "Applies to the end date and the daily cutoff. Pick the summer or winter offset that is in force on that date.",
"options": [
{ "value": "-10:00", "label": "UTC−10:00 · Honolulu" },
{ "value": "-09:00", "label": "UTC−09:00 · Anchorage" },
{ "value": "-08:00", "label": "UTC−08:00 · Los Angeles (winter)" },
{ "value": "-07:00", "label": "UTC−07:00 · Los Angeles (summer), Denver" },
{ "value": "-06:00", "label": "UTC−06:00 · Chicago (winter)" },
{ "value": "-05:00", "label": "UTC−05:00 · New York (winter)" },
{ "value": "-04:00", "label": "UTC−04:00 · New York (summer)" },
{ "value": "-03:00", "label": "UTC−03:00 · São Paulo" },
{ "value": "+00:00", "label": "UTC±00:00 · London (winter)" },
{ "value": "+01:00", "label": "UTC+01:00 · Paris, Berlin (winter), London (summer)" },
{ "value": "+02:00", "label": "UTC+02:00 · Paris, Berlin (summer)" },
{ "value": "+03:00", "label": "UTC+03:00 · Istanbul" },
{ "value": "+04:00", "label": "UTC+04:00 · Dubai" },
{ "value": "+05:30", "label": "UTC+05:30 · Mumbai" },
{ "value": "+07:00", "label": "UTC+07:00 · Bangkok" },
{ "value": "+08:00", "label": "UTC+08:00 · Singapore" },
{ "value": "+09:00", "label": "UTC+09:00 · Tokyo, Seoul" },
{ "value": "+10:00", "label": "UTC+10:00 · Sydney (winter)" },
{ "value": "+11:00", "label": "UTC+11:00 · Sydney (summer)" },
{ "value": "+12:00", "label": "UTC+12:00 · Auckland" }
],
"default": "+01:00"
},
{
"type": "range",
"id": "cutoff_hour",
"label": "Daily cutoff hour",
"info": "Daily cutoff only. The clock restarts toward this hour every day.",
"min": 0,
"max": 23,
"step": 1,
"unit": "h",
"default": 15
},
{
"type": "text",
"id": "daily_text",
"label": "Daily cutoff message",
"info": "[time] becomes the live time left, e.g. 3h 12m.",
"default": "Order in the next [time] for same-day dispatch"
},
{
"type": "text",
"id": "ends_label",
"label": "End date label",
"info": "Fixed date only. Shown before the end date, in the visitor's own time zone.",
"default": "Drop closes"
},
{
"type": "text",
"id": "label_days",
"label": "Days label",
"default": "Days"
},
{
"type": "text",
"id": "label_hours",
"label": "Hours label",
"default": "Hours"
},
{
"type": "text",
"id": "label_minutes",
"label": "Minutes label",
"default": "Minutes"
},
{
"type": "text",
"id": "label_seconds",
"label": "Seconds label",
"default": "Seconds"
},
{
"type": "header",
"content": "When the countdown ends"
},
{
"type": "select",
"id": "ended_behavior",
"label": "After the end date",
"info": "The section always stays visible in the theme editor.",
"options": [
{ "value": "hide", "label": "Hide the section" },
{ "value": "message", "label": "Show the ended message" }
],
"default": "message"
},
{
"type": "text",
"id": "ended_message",
"label": "Ended message",
"default": "This drop has closed. Join the list to hear about the next release first."
},
{
"type": "header",
"content": "Offer"
},
{
"type": "text",
"id": "promo_label",
"label": "Promo code label",
"default": "Early access"
},
{
"type": "text",
"id": "promo_code",
"label": "Promo code",
"info": "Leave empty to hide the code pill. Create the discount in Shopify admin first.",
"default": "SOLSTICE15"
},
{
"type": "text",
"id": "copy_label",
"label": "Copy button label",
"default": "Copy"
},
{
"type": "text",
"id": "copied_label",
"label": "Copied confirmation",
"default": "Copied"
},
{
"type": "text",
"id": "copy_fallback",
"label": "Manual copy hint",
"info": "Shown when the browser blocks clipboard access. The code is selected for the visitor.",
"default": "Selected: press Ctrl+C"
},
{
"type": "text",
"id": "button_label",
"label": "Button label",
"default": "Shop the drop"
},
{
"type": "url",
"id": "button_link",
"label": "Button link",
"info": "Defaults to the featured product."
},
{
"type": "header",
"content": "Visual"
},
{
"type": "select",
"id": "visual",
"label": "Visual",
"options": [
{ "value": "product", "label": "Product photo" },
{ "value": "art", "label": "Glowing bottle art" }
],
"default": "product"
},
{
"type": "product",
"id": "product",
"label": "Featured product",
"info": "On a product page, the current product is used when this is empty."
},
{
"type": "image_picker",
"id": "image",
"label": "Custom image",
"info": "Optional. Replaces the product photo inside the arch. Portrait 4:5 works best."
},
{
"type": "checkbox",
"id": "show_product_info",
"label": "Show product name and price",
"default": true
},
{
"type": "checkbox",
"id": "show_embers",
"label": "Show floating embers",
"default": true
},
{
"type": "select",
"id": "layout",
"label": "Visual position on desktop",
"options": [
{ "value": "left", "label": "Left" },
{ "value": "right", "label": "Right" }
],
"default": "left"
},
{
"type": "header",
"content": "Layout"
},
{
"type": "range",
"id": "padding_top",
"label": "Top padding",
"min": 0,
"max": 200,
"step": 8,
"unit": "px",
"default": 104
},
{
"type": "range",
"id": "padding_bottom",
"label": "Bottom padding",
"min": 0,
"max": 200,
"step": 8,
"unit": "px",
"default": 104
},
{
"type": "header",
"content": "Colors"
},
{
"type": "color",
"id": "color_bg",
"label": "Background",
"default": "#0b0807"
},
{
"type": "color",
"id": "color_text",
"label": "Text",
"default": "#f7efe6"
},
{
"type": "color",
"id": "color_accent",
"label": "Accent (digits glow, button)",
"default": "#ff8a4c"
},
{
"type": "color",
"id": "color_glow",
"label": "Background glow",
"default": "#5b2bd6"
}
],
"presets": [
{
"name": "EX · Drop countdown"
}
]
}
{% endschema %}
Why it converts
A real deadline and a visibly ticking clock give fence-sitters a reason to buy now instead of saving the tab for later.
Specs
About this section
Drop Countdown is a free Shopify Online Store 2.0 section for limited drops, launches and promotions. The featured product sits in a lit arch display case on a dark, layered background of ember and violet glows, soft spotlight rays and film grain, with a rim light that travels around the arch and embers drifting upward. Beside it, an eyebrow, a heading with a glowing serif accent and rich text lead into four glass tiles for days, hours, minutes and seconds; each digit rolls into place when it changes. Two modes are available: a fixed end date entered as YYYY-MM-DD HH:MM with a UTC offset, or a daily cutoff that restarts every day at a chosen hour and fills a live sentence such as Order in the next 3h 12m for same-day dispatch. Under the clock, the end date is shown in the visitor's own time zone. When a fixed countdown ends, the section either hides itself or swaps the clock for an ended message. A dashed promo-code pill copies the code with one tap, confirms it visually and to screen readers, and selects the code when the browser blocks clipboard access. The call-to-action button defaults to the product page. The product, a custom image or a CSS-drawn glowing bottle, the colors, padding and side are all theme-editor settings. The conversion principle is honest urgency: a visible deadline shortens deliberation. The section is one self-contained .liquid file, renders the first clock value on the server, and stops every animation for visitors who prefer reduced motion.
Questions
How do I set the end date and time zone?
Type the date in the End date and time setting as YYYY-MM-DD HH:MM on a 24-hour clock (for example 2026-12-21 20:00) and pick the matching UTC offset in Time zone. The countdown is exact for every visitor, and the date under the clock is shown in their own local time.
What does the Daily cutoff mode do?
It counts down to the next occurrence of the Daily cutoff hour in your time zone, then restarts for the following day, so it never ends. Days are hidden, and the Daily cutoff message replaces [time] with the live time left, e.g. Order in the next 3h 12m for same-day dispatch.
What happens when the countdown reaches zero?
Choose in After the end date: Hide the section removes it from your live store, while Show the ended message replaces the clock and promo code with your own text and keeps the button. In the theme editor the section always stays visible so you can still edit it.
Is the countdown accessible?
Yes. The digits are decorative for screen readers; a separate timer text announces days, hours and minutes without reading every second. The Copy button is a real button with a polite live-region confirmation, and all motion, including the rolling digits, stops when the visitor prefers reduced motion.
More sections
Pro