Shopify theme files
The deals page, as Shopify code
One section with settings and product blocks, two snippets and a page template. The section reads products with all_products[handle], so prices and stock come from Shopify when the page loads, and the countdown runs on the store's time zone.
sections/gbc-holiday-deals.liquid
{%- comment -%}
GBC holiday deals section. Generated by The Great Brick Company campaign factory for campaign demo-northfold-bfcm-2026.
Prices, compare-at prices, stock and images are read live from Shopify (product blocks / all_products).
Offer copy, codes and dates come from the approved brief. Edit them in the theme editor if the brief changes.
{%- endcomment -%}
{%- liquid
assign s = section.settings
if s.use_theme_fonts
assign f_head = 'var(--font-heading-family, inherit)'
assign f_body = 'var(--font-body-family, inherit)'
else
assign f_head = s.heading_font.family | append: ', ' | append: s.heading_font.fallback_families
assign f_body = s.body_font.family | append: ', ' | append: s.body_font.fallback_families
endif
assign product_blocks = section.blocks | where: 'type', 'product'
assign offer_blocks = section.blocks | where: 'type', 'offer'
assign faq_blocks = section.blocks | where: 'type', 'faq'
assign first_offer = offer_blocks | first
assign hero_product = s.spotlight_product
-%}
{%- unless s.use_theme_fonts -%}
<style>{{ s.heading_font | font_face: font_display: 'swap' }}{{ s.body_font | font_face: font_display: 'swap' }}</style>
{%- endunless -%}
<div class="gbc" id="gbc-{{ section.id }}" style="--gbc-bg:{{ s.color_bg }};--gbc-surface:{{ s.color_surface }};--gbc-text:{{ s.color_text }};--gbc-muted:{{ s.color_muted }};--gbc-primary:{{ s.color_primary }};--gbc-primary-text:{{ s.color_primary_text }};--gbc-accent:{{ s.color_accent }};--gbc-accent-text:{{ s.color_accent_text }};--gbc-sale:{{ s.color_sale }};--gbc-border:{{ s.color_border }};--gbc-badge-bg:{{ s.color_primary }};--gbc-badge-text:{{ s.color_primary_text }};--gbc-font-heading:{{ f_head }};--gbc-font-body:{{ f_body }}">
<div class="gbc-bar" data-gbc-bar role="status">
{%- if first_offer -%}<strong>{{ first_offer.settings.headline | escape }}</strong> · {{ first_offer.settings.starts_short | escape }} to {{ first_offer.settings.ends_short | escape }}{%- endif -%}
</div>
{%- liquid
assign hero_src = blank
if s.hero_image != blank
assign hero_src = s.hero_image | image_url: width: 2400
assign hero_alt = s.hero_image.alt | default: s.hero_image_alt
elsif s.hero_image_url != blank
assign hero_src = s.hero_image_url
assign hero_alt = s.hero_image_alt
elsif hero_product.featured_image != blank
assign hero_src = hero_product.featured_image | image_url: width: 2400
assign hero_alt = hero_product.featured_image.alt | default: hero_product.title
endif
-%}
<section class="gbc-hero{% if hero_src == blank %} gbc-hero--noimg{% endif %}">
{%- if hero_src != blank -%}
<div class="gbc-hero__media"><img src="{{ hero_src }}" alt="{{ hero_alt | escape }}" width="1600" height="1000" fetchpriority="high"></div>
{%- endif -%}
<div class="gbc-hero__inner">
<div>
{%- if s.eyebrow != blank -%}<p class="gbc-eyebrow">{{ s.eyebrow | escape }}</p>{%- endif -%}
<h1 class="gbc-h">{{ s.headline | escape }}</h1>
{%- if s.subhead != blank -%}<p class="gbc-hero__sub">{{ s.subhead | escape }}</p>{%- endif -%}
<div class="gbc-ctas">
<a class="gbc-btn" href="#gbc-products-{{ section.id }}">{{ s.cta_label | escape }}</a>
<a class="gbc-btn gbc-btn--ghost" href="#gbc-offers-{{ section.id }}">See every offer</a>
</div>
</div>
<div class="gbc-hero__panel">{% render 'gbc-countdown', fallback: s.fine_print %}</div>
</div>
</section>
<section class="gbc-section gbc-offers" id="gbc-offers-{{ section.id }}">
<div class="gbc-wrap">
<div class="gbc-head"><div><h2 class="gbc-h">{{ s.offers_heading | escape }}</h2></div></div>
<div class="gbc-offers__list">
{%- for block in offer_blocks -%}
<article class="gbc-offer" data-gbc-offer="{{ block.id }}" {{ block.shopify_attributes }}>
<span class="gbc-pill" data-gbc-status><i aria-hidden="true"></i><span>{{ block.settings.starts_short | escape }} to {{ block.settings.ends_short | escape }}</span></span>
<h3 class="gbc-h">{{ block.settings.headline | escape }}</h3>
{%- if block.settings.details != blank -%}<p class="gbc-offer__meta">{{ block.settings.details | escape }}</p>{%- endif -%}
<p class="gbc-offer__meta">Ends {{ block.settings.ends_label | escape }}</p>
{%- if block.settings.code != blank -%}
<div class="gbc-code"><span>{{ block.settings.code | escape }}</span><button type="button" data-gbc-copy="{{ block.settings.code | escape }}">Copy code</button></div>
{%- elsif block.settings.offer_type != 'no_discount' -%}
<p class="gbc-auto">No code needed. Applied at checkout.</p>
{%- endif -%}
</article>
{%- endfor -%}
</div>
</div>
</section>
<section class="gbc-section" id="gbc-products-{{ section.id }}">
<div class="gbc-wrap">
<div class="gbc-head">
<div><h2 class="gbc-h">{{ s.products_heading | escape }}</h2>{%- if s.products_intro != blank -%}<p class="gbc-muted">{{ s.products_intro | escape }}</p>{%- endif -%}</div>
{%- if s.show_filters -%}
<div class="gbc-filters" role="group" aria-label="Filter by price">
<button type="button" class="gbc-chip" data-gbc-band="all" aria-pressed="true">All</button>
<button type="button" class="gbc-chip" data-gbc-band="0-50" aria-pressed="false">Under {{ 5000 | money_without_trailing_zeros }}</button>
<button type="button" class="gbc-chip" data-gbc-band="50-100" aria-pressed="false">{{ 5000 | money_without_trailing_zeros }} to {{ 10000 | money_without_trailing_zeros }}</button>
<button type="button" class="gbc-chip" data-gbc-band="100" aria-pressed="false">{{ 10000 | money_without_trailing_zeros }} and up</button>
</div>
{%- endif -%}
</div>
<ul class="gbc-grid">
{%- if product_blocks.size > 0 -%}
{%- for block in product_blocks -%}
{%- assign p = block.settings.product -%}
{%- if p == blank -%}{%- continue -%}{%- endif -%}
{% render 'gbc-product-card', p: p, blurb: block.settings.blurb, attrs: block.shopify_attributes, threshold: s.low_stock_threshold, index: forloop.index %}
{%- endfor -%}
{%- else -%}
{%- assign handles = s.fallback_handles | split: ',' -%}
{%- for h in handles -%}
{%- assign handle = h | strip -%}
{%- assign p = all_products[handle] -%}
{%- if p == blank or p.id == blank -%}{%- continue -%}{%- endif -%}
{% render 'gbc-product-card', p: p, blurb: '', attrs: '', threshold: s.low_stock_threshold, index: forloop.index %}
{%- endfor -%}
{%- endif -%}
</ul>
</div>
</section>
{%- if hero_product != blank -%}
<section class="gbc-section" style="padding-top:0">
<div class="gbc-wrap"><div class="gbc-spot">
<div class="gbc-spot__media">{%- if hero_product.featured_image -%}{%- assign spot_alt = hero_product.featured_image.alt | default: hero_product.title -%}{{ hero_product.featured_image | image_url: width: 1200 | image_tag: loading: 'lazy', alt: spot_alt, widths: '600, 900, 1200' }}{%- endif -%}</div>
<div class="gbc-spot__body">
<p class="gbc-eyebrow">Spotlight</p>
<h2 class="gbc-h">{{ s.spotlight_heading | default: hero_product.title | escape }}</h2>
{%- if s.spotlight_body != blank -%}<p>{{ s.spotlight_body | escape }}</p>{%- endif -%}
<p class="gbc-price">
<span class="gbc-price__now{% if hero_product.compare_at_price > hero_product.price %} is-sale{% endif %}">{% if hero_product.price_varies %}From {% endif %}{{ hero_product.price | money }}</span>
{%- if hero_product.compare_at_price > hero_product.price -%}<s class="gbc-price__was"><span class="gbc-sr">Regular price </span>{{ hero_product.compare_at_price | money }}</s>{%- endif -%}
</p>
<div><a class="gbc-btn" href="{{ hero_product.url }}">Shop now</a></div>
</div>
</div></div>
</section>
{%- endif -%}
{%- if faq_blocks.size > 0 -%}
<section class="gbc-section" style="padding-top:0">
<div class="gbc-wrap"><div class="gbc-faq">
<div><h2 class="gbc-h">Good to know</h2></div>
<div>
{%- for block in faq_blocks -%}
<details {% if forloop.first %}open{% endif %} {{ block.shopify_attributes }}>
<summary>{{ block.settings.question | escape }}</summary>
<div>{%- assign lines = block.settings.answer | newline_to_br | split: '<br />' -%}{%- for l in lines -%}{%- assign t = l | strip -%}{%- if t != blank -%}<p>{{ t | escape }}</p>{%- endif -%}{%- endfor -%}</div>
</details>
{%- endfor -%}
</div>
</div></div>
</section>
{%- endif -%}
<section class="gbc-closing">
<div class="gbc-wrap">
<h2 class="gbc-h">{{ s.closing_headline | escape }}</h2>
{%- if s.closing_body != blank -%}<p>{{ s.closing_body | escape }}</p>{%- endif -%}
{% render 'gbc-countdown', fallback: s.fine_print %}
<div class="gbc-ctas"><a class="gbc-btn" href="#gbc-products-{{ section.id }}">{{ s.cta_label | escape }}</a></div>
</div>
</section>
{%- if s.fine_print != blank -%}
<div class="gbc-wrap"><div class="gbc-fine">
{%- assign lines = s.fine_print | newline_to_br | split: '<br />' -%}
{%- for l in lines -%}{%- assign t = l | strip -%}{%- if t != blank -%}<p>{{ t | escape }}</p>{%- endif -%}{%- endfor -%}
<p>Discounts apply at checkout.</p>
</div></div>
{%- endif -%}
<script type="application/json" data-gbc-offers>
[
{%- for block in offer_blocks -%}
{"id":{{ block.id | json }},"headline":{{ block.settings.headline | json }},"type":{{ block.settings.offer_type | json }},"code":{{ block.settings.code | default: '' | json }},"starts":{{ block.settings.starts_at | json }},"ends":{{ block.settings.ends_at | json }},"starts_label":{{ block.settings.starts_label | json }},"ends_label":{{ block.settings.ends_label | json }},"starts_short":{{ block.settings.starts_short | json }},"ends_short":{{ block.settings.ends_short | json }}}{% unless forloop.last %},{% endunless %}
{%- endfor -%}
]
</script>
</div>
{% stylesheet %}
.gbc{--gbc-r:16px;background:var(--gbc-bg);color:var(--gbc-text);font-family:var(--gbc-font-body);font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
.gbc *,.gbc *::before,.gbc *::after{box-sizing:border-box}
.gbc img{max-width:100%;height:auto;display:block}
.gbc a{color:inherit}
.gbc [hidden]{display:none!important}
.gbc-wrap{max-width:1280px;margin:0 auto;padding:0 20px}
@media(min-width:900px){.gbc-wrap{padding:0 40px}}
.gbc-h{font-family:var(--gbc-font-heading);font-weight:500;letter-spacing:-.022em;line-height:1.02;margin:0;text-wrap:balance}
.gbc-eyebrow{display:inline-block;font-size:12px;line-height:1.2;letter-spacing:.18em;text-transform:uppercase;font-weight:600;margin:0 0 14px}
.gbc-muted{color:var(--gbc-muted)}
.gbc-sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.gbc-bar{background:var(--gbc-primary);color:var(--gbc-primary-text);font-size:13px;line-height:1.4;text-align:center;padding:10px 16px;letter-spacing:.02em}
.gbc-bar strong{font-weight:700}
.gbc-bar code{font-family:inherit;font-weight:700;letter-spacing:.08em;border-bottom:1px dashed currentColor}
.gbc-hero{position:relative;display:flex;align-items:flex-end;min-height:min(88vh,780px);overflow:hidden;background:var(--gbc-primary);color:var(--gbc-hero-text,#fff)}
.gbc-hero--noimg{color:var(--gbc-primary-text);min-height:auto}
.gbc-hero__media{position:absolute;inset:0}
.gbc-hero__media img{width:100%;height:100%;object-fit:cover;transform:scale(1.02)}
.gbc-hero__media::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(10,10,8,.10) 0%,rgba(10,10,8,.30) 42%,rgba(10,10,8,.80) 100%)}
.gbc-hero__inner{position:relative;width:100%;max-width:1280px;margin:0 auto;padding:140px 20px 36px}
@media(min-width:900px){.gbc-hero__inner{padding:180px 40px 64px;display:grid;grid-template-columns:1.25fr .75fr;gap:48px;align-items:end}}
.gbc-hero h1{font-size:clamp(46px,10.5vw,112px);max-width:11ch}
.gbc-hero__sub{font-size:clamp(17px,1.6vw,20px);max-width:40ch;margin:18px 0 0;opacity:.94}
.gbc-hero__panel{margin-top:28px}
@media(min-width:900px){.gbc-hero__panel{margin-top:0;justify-self:end;text-align:left;max-width:420px;width:100%}}
.gbc-cd__label{font-size:12px;letter-spacing:.16em;text-transform:uppercase;font-weight:600;opacity:.9;margin:0 0 10px}
.gbc-cd{display:flex;gap:8px}
.gbc-cd__u{flex:1;min-width:0;padding:12px 6px 10px;border-radius:14px;text-align:center;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.24);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
.gbc-hero--noimg .gbc-cd__u,.gbc-closing .gbc-cd__u{background:rgba(255,255,255,.08);border-color:currentColor}
.gbc-cd__n{display:block;font-family:var(--gbc-font-heading);font-size:clamp(28px,4vw,40px);line-height:1;font-variant-numeric:tabular-nums}
.gbc-cd__l{display:block;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;margin-top:6px;opacity:.85}
.gbc-cd-fallback{font-weight:600;margin:0}
.gbc-ctas{display:flex;flex-wrap:wrap;gap:10px;margin-top:22px}
.gbc-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:52px;padding:0 28px;border-radius:999px;border:0;background:var(--gbc-accent);color:var(--gbc-accent-text);font:inherit;font-weight:600;font-size:16px;letter-spacing:.01em;text-decoration:none;cursor:pointer;transition:transform .18s ease,box-shadow .18s ease,opacity .18s}
.gbc-btn:hover{transform:translateY(-1px);box-shadow:0 10px 26px -12px rgba(0,0,0,.55)}
.gbc-btn:focus-visible,.gbc-chip:focus-visible,.gbc-code button:focus-visible,.gbc-faq summary:focus-visible{outline:3px solid var(--gbc-accent);outline-offset:3px}
.gbc-btn--ghost{background:transparent;color:inherit;box-shadow:inset 0 0 0 1.5px currentColor}
.gbc-btn--block{width:100%}
.gbc-btn[disabled]{opacity:.45;cursor:not-allowed;transform:none;box-shadow:none}
.gbc-section{padding:64px 0}
@media(min-width:900px){.gbc-section{padding:96px 0}}
.gbc-head{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:18px;margin-bottom:28px}
.gbc-head h2{font-size:clamp(34px,5.4vw,64px)}
.gbc-head p{margin:10px 0 0;max-width:46ch}
.gbc-offers{padding-top:48px;padding-bottom:8px}
.gbc-offers__list{display:grid;gap:14px;grid-auto-flow:column;grid-auto-columns:minmax(260px,84%);overflow-x:auto;scroll-snap-type:x mandatory;padding:2px 2px 12px;margin:0 -2px;scrollbar-width:thin}
@media(min-width:760px){.gbc-offers__list{grid-auto-flow:row;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));overflow:visible}}
.gbc-offer{scroll-snap-align:start;display:flex;flex-direction:column;gap:12px;padding:24px;border-radius:var(--gbc-r);background:var(--gbc-surface);border:1px solid var(--gbc-border);transition:background .3s,color .3s}
.gbc-offer.is-live{background:var(--gbc-primary);color:var(--gbc-primary-text);border-color:transparent}
.gbc-offer.is-ended{opacity:.55}
.gbc-offer h3{font-size:clamp(26px,2.6vw,32px)}
.gbc-offer__meta{font-size:14px;margin:0;opacity:.88}
.gbc-pill{display:inline-flex;align-items:center;gap:7px;width:max-content;font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;padding:5px 11px;border-radius:999px;box-shadow:inset 0 0 0 1px currentColor}
.gbc-pill i{width:7px;height:7px;border-radius:50%;background:currentColor;display:block}
.gbc-offer.is-live .gbc-pill i{animation:gbc-pulse 1.6s ease-in-out infinite}
@keyframes gbc-pulse{50%{opacity:.25}}
.gbc-code{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:auto;padding:6px 6px 6px 16px;border:1.5px dashed currentColor;border-radius:12px}
.gbc-code span{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:16px;font-weight:700;letter-spacing:.1em}
.gbc-code button{font:inherit;font-size:13px;font-weight:600;border:0;border-radius:8px;padding:9px 12px;cursor:pointer;background:var(--gbc-text);color:var(--gbc-bg)}
.gbc-offer.is-live .gbc-code button{background:var(--gbc-primary-text);color:var(--gbc-primary)}
.gbc-auto{margin-top:auto;font-size:14px;font-weight:600}
.gbc-filters{display:flex;gap:8px;overflow-x:auto;padding:2px;scrollbar-width:none}
.gbc-chip{font:inherit;font-size:14px;white-space:nowrap;padding:9px 16px;border-radius:999px;border:1px solid var(--gbc-border);background:transparent;color:inherit;cursor:pointer}
.gbc-chip[aria-pressed="true"]{background:var(--gbc-text);color:var(--gbc-bg);border-color:var(--gbc-text)}
.gbc-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:28px 14px;list-style:none;margin:0;padding:0}
@media(min-width:760px){.gbc-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:44px 24px}}
@media(min-width:1140px){.gbc-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
.gbc-card{display:flex;flex-direction:column;gap:10px;min-width:0}
.gbc-card__media{position:relative;display:block;aspect-ratio:4/5;border-radius:var(--gbc-r);overflow:hidden;background:var(--gbc-surface)}
.gbc-card__media img{width:100%;height:100%;object-fit:cover;transition:transform .6s cubic-bezier(.2,.7,.2,1)}
.gbc-card:hover .gbc-card__media img{transform:scale(1.04)}
.gbc-badge{position:absolute;top:10px;left:10px;font-size:12px;font-weight:700;letter-spacing:.02em;padding:5px 10px;border-radius:999px;background:var(--gbc-badge-bg);color:var(--gbc-badge-text)}
.gbc-stock{position:absolute;left:10px;bottom:10px;font-size:12px;font-weight:600;padding:5px 10px;border-radius:999px;background:#FFFFFF;color:#1A1915}
.gbc-card.is-soldout .gbc-card__media img{filter:grayscale(.7);opacity:.7}
.gbc-card__title{margin:2px 0 0;font-size:16px;font-weight:600;line-height:1.3}
.gbc-card__title a{text-decoration:none}
.gbc-card__blurb{margin:0;font-size:14px;line-height:1.45;color:var(--gbc-muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.gbc-price{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;margin:0}
.gbc-price__now{font-weight:700;font-size:17px}
.gbc-price__now.is-sale{color:var(--gbc-sale)}
.gbc-price__was{font-size:14px;color:var(--gbc-muted);text-decoration:line-through}
.gbc-card form{margin:auto 0 0}
.gbc-card .gbc-btn{min-height:46px;font-size:14.5px;padding:0 16px;width:100%;margin-top:auto}
.gbc-card .gbc-btn--ghost{box-shadow:inset 0 0 0 1px var(--gbc-border)}
.gbc-spot{display:grid;border-radius:calc(var(--gbc-r)*1.5);overflow:hidden;background:var(--gbc-surface)}
@media(min-width:900px){.gbc-spot{grid-template-columns:1.1fr 1fr}}
.gbc-spot__media{aspect-ratio:1/1;overflow:hidden}
.gbc-spot__media img{width:100%;height:100%;object-fit:cover}
.gbc-spot__body{display:flex;flex-direction:column;justify-content:center;gap:18px;padding:32px 24px 36px}
@media(min-width:900px){.gbc-spot__body{padding:64px}}
.gbc-spot h2{font-size:clamp(36px,4.8vw,64px)}
.gbc-spot p{margin:0;font-size:17px;max-width:42ch}
.gbc-spot .gbc-price__now{font-size:22px}
.gbc-faq{display:grid;gap:28px}
@media(min-width:900px){.gbc-faq{grid-template-columns:.8fr 1.2fr;gap:64px}}
.gbc-faq h2{font-size:clamp(34px,4.6vw,56px)}
.gbc-faq details{border-top:1px solid var(--gbc-border);padding:4px 0}
.gbc-faq details:last-child{border-bottom:1px solid var(--gbc-border)}
.gbc-faq summary{list-style:none;cursor:pointer;display:flex;justify-content:space-between;align-items:center;gap:16px;padding:18px 0;font-size:18px;font-weight:600}
.gbc-faq summary::-webkit-details-marker{display:none}
.gbc-faq summary::after{content:"+";font-size:26px;font-weight:300;line-height:1;transition:transform .25s}
.gbc-faq details[open] summary::after{transform:rotate(45deg)}
.gbc-faq details>div{padding:0 0 20px;color:var(--gbc-muted);max-width:60ch}
.gbc-faq details>div p{margin:0 0 8px}
.gbc-closing{background:var(--gbc-primary);color:var(--gbc-primary-text);text-align:center;padding:80px 0}
.gbc-closing h2{font-size:clamp(38px,6.4vw,84px);margin:0 auto;max-width:16ch}
.gbc-closing p{max-width:46ch;margin:16px auto 0;opacity:.92}
.gbc-closing .gbc-cd{max-width:420px;margin:28px auto 0}
.gbc-closing .gbc-ctas{justify-content:center}
.gbc-fine{font-size:13px;color:var(--gbc-muted);padding:28px 0 40px;margin:0}
.gbc-fine p{margin:0 0 6px}
@media(prefers-reduced-motion:reduce){.gbc *{transition:none!important;animation:none!important}}
{% endstylesheet %}
{% javascript %}
(function(){
function nowMs(){ return window.GBC_NOW ? Date.parse(window.GBC_NOW) + (Date.now() - (window.GBC_T0 || Date.now())) : Date.now(); }
function pad(n){ return (n < 10 ? '0' : '') + n; }
function state(o, t){ var s = Date.parse(o.starts), e = Date.parse(o.ends); return t < s ? 'upcoming' : (t >= e ? 'ended' : 'live'); }
function rank(o){ return /percent|fixed_amount|bundle|gift_with_purchase/.test(o.type) ? 0 : 1; }
function init(root){
if (!root || root.__gbc) return; root.__gbc = true;
var el = root.querySelector('[data-gbc-offers]'); if (!el) return;
var offers; try { offers = JSON.parse(el.textContent); } catch (e) { return; }
offers = offers.filter(function(o){ return !isNaN(Date.parse(o.starts)) && !isNaN(Date.parse(o.ends)); });
if (!offers.length) return;
function tick(){
var t = nowMs();
var live = offers.filter(function(o){ return state(o, t) === 'live'; }).sort(function(a, b){ return rank(a) - rank(b) || Date.parse(b.starts) - Date.parse(a.starts); });
var up = offers.filter(function(o){ return state(o, t) === 'upcoming'; }).sort(function(a, b){ return Date.parse(a.starts) - Date.parse(b.starts); });
var main = live[0], target = null, label = '';
if (main) { target = Date.parse(main.ends); label = main.headline + ' ends in'; }
else if (up[0]) { target = Date.parse(up[0].starts); label = up[0].headline + ' starts in'; }
root.querySelectorAll('[data-gbc-offer]').forEach(function(card){
var o = offers.filter(function(x){ return x.id === card.getAttribute('data-gbc-offer'); })[0]; if (!o) return;
var st = state(o, t);
card.classList.toggle('is-live', st === 'live'); card.classList.toggle('is-ended', st === 'ended');
var pill = card.querySelector('[data-gbc-status]');
if (pill) pill.lastChild.textContent = st === 'live' ? 'Live now' : (st === 'upcoming' ? 'Starts ' + o.starts_short : 'Ended');
});
root.querySelectorAll('[data-gbc-countdown]').forEach(function(cd){
var fb = cd.parentNode.querySelector('[data-gbc-cd-fallback]');
var lab = cd.parentNode.querySelector('[data-gbc-cd-label]');
if (!target) { cd.hidden = true; if (lab) lab.hidden = true; if (fb) { fb.hidden = false; fb.textContent = 'This sale has ended. Thanks for shopping with us.'; } return; }
var d = Math.max(0, target - t), s = Math.floor(d / 1000);
var v = [Math.floor(s / 86400), Math.floor(s % 86400 / 3600), Math.floor(s % 3600 / 60), s % 60];
var n = cd.querySelectorAll('[data-n]');
for (var i = 0; i < n.length; i++) n[i].textContent = pad(v[i]);
cd.hidden = false; if (fb) fb.hidden = true; if (lab) { lab.hidden = false; lab.textContent = label; }
cd.setAttribute('aria-label', label + ' ' + v[0] + ' days ' + v[1] + ' hours ' + v[2] + ' minutes');
});
root.querySelectorAll('[data-gbc-bar]').forEach(function(bar){
var o = main || up[0];
if (!o) { bar.textContent = 'This sale has ended.'; return; }
bar.innerHTML = '';
var b = document.createElement('strong'); b.textContent = o.headline; bar.appendChild(b);
if (main) { if (o.code) { bar.appendChild(document.createTextNode(' with code ')); var c = document.createElement('code'); c.textContent = o.code; bar.appendChild(c); } bar.appendChild(document.createTextNode(' · Ends ' + o.ends_label)); }
else bar.appendChild(document.createTextNode(' · Starts ' + o.starts_label));
});
}
tick(); setInterval(tick, 1000);
root.querySelectorAll('[data-gbc-copy]').forEach(function(btn){
btn.addEventListener('click', function(){
var code = btn.getAttribute('data-gbc-copy'), done = function(){ var t = btn.textContent; btn.textContent = 'Copied'; setTimeout(function(){ btn.textContent = t; }, 1600); };
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(code).then(done, done); else done();
});
});
var chips = root.querySelectorAll('[data-gbc-band]');
function inBand(card, band){ var p = parseFloat(card.getAttribute('data-gbc-price')), r = band.split('-'), lo = parseFloat(r[0]), hi = r[1] ? parseFloat(r[1]) : Infinity; return p >= lo && p < hi; }
var cards = root.querySelectorAll('[data-gbc-price]'), shown = 0;
chips.forEach(function(chip){
var band = chip.getAttribute('data-gbc-band'); if (band === 'all') return;
var n = 0; cards.forEach(function(c){ if (inBand(c, band)) n++; });
if (!n) chip.hidden = true; else shown++;
});
if (shown < 2) { var bar = root.querySelector('.gbc-filters'); if (bar) bar.hidden = true; }
chips.forEach(function(chip){
chip.addEventListener('click', function(){
var band = chip.getAttribute('data-gbc-band');
chips.forEach(function(c){ c.setAttribute('aria-pressed', c === chip ? 'true' : 'false'); });
cards.forEach(function(card){ card.hidden = band !== 'all' && !inBand(card, band); });
});
});
}
function boot(){ document.querySelectorAll('.gbc').forEach(init); }
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); else boot();
document.addEventListener('shopify:section:load', function(e){ init(e.target.querySelector('.gbc')); });
})();
{% endjavascript %}
{% schema %}
{
"name": "GBC holiday deals",
"tag": "section",
"class": "gbc-holiday-section",
"max_blocks": 40,
"settings": [
{
"type": "header",
"content": "Copy"
},
{
"type": "text",
"id": "eyebrow",
"label": "Eyebrow",
"default": "Black Friday and Cyber Monday"
},
{
"type": "text",
"id": "headline",
"label": "Headline",
"default": "The holiday sale"
},
{
"type": "textarea",
"id": "subhead",
"label": "Subheading",
"default": "Every offer, code and end date is listed on this page."
},
{
"type": "text",
"id": "cta_label",
"label": "Button label",
"default": "Shop the sale"
},
{
"type": "text",
"id": "offers_heading",
"label": "Offers heading",
"default": "Offers this week"
},
{
"type": "text",
"id": "products_heading",
"label": "Products heading",
"default": "On sale now"
},
{
"type": "text",
"id": "products_intro",
"label": "Products intro",
"default": "Picked from what is in stock."
},
{
"type": "text",
"id": "spotlight_heading",
"label": "Spotlight heading"
},
{
"type": "textarea",
"id": "spotlight_body",
"label": "Spotlight text"
},
{
"type": "text",
"id": "closing_headline",
"label": "Closing headline",
"default": "The sale ends soon"
},
{
"type": "textarea",
"id": "closing_body",
"label": "Closing text"
},
{
"type": "textarea",
"id": "fine_print",
"label": "Fine print",
"info": "One line per offer. Generated from the approved brief."
},
{
"type": "header",
"content": "Media and products"
},
{
"type": "image_picker",
"id": "hero_image",
"label": "Hero image"
},
{
"type": "text",
"id": "hero_image_url",
"label": "Hero image URL (fallback)",
"info": "Used when no hero image is picked. If both are empty, the spotlight product image is used."
},
{
"type": "text",
"id": "hero_image_alt",
"label": "Hero image alt text"
},
{
"type": "product",
"id": "spotlight_product",
"label": "Spotlight product"
},
{
"type": "textarea",
"id": "fallback_handles",
"label": "Product handles (fallback)",
"info": "Comma-separated handles, used only when the section has no product blocks."
},
{
"type": "range",
"id": "low_stock_threshold",
"label": "Show \"Low stock\" at or below",
"min": 0,
"max": 20,
"step": 1,
"default": 5,
"info": "Uses real Shopify inventory. 0 turns the note off."
},
{
"type": "checkbox",
"id": "show_filters",
"label": "Show price filters",
"default": true
},
{
"type": "header",
"content": "Colors"
},
{
"type": "color",
"id": "color_bg",
"label": "Background",
"default": "#FBF8F3"
},
{
"type": "color",
"id": "color_surface",
"label": "Card background",
"default": "#F2ECE2"
},
{
"type": "color",
"id": "color_text",
"label": "Text",
"default": "#1A1915"
},
{
"type": "color",
"id": "color_muted",
"label": "Secondary text",
"default": "#5C574E"
},
{
"type": "color",
"id": "color_primary",
"label": "Brand band",
"default": "#1F2A24"
},
{
"type": "color",
"id": "color_primary_text",
"label": "Text on brand band",
"default": "#FFFFFF"
},
{
"type": "color",
"id": "color_accent",
"label": "Button",
"default": "#1F2A24"
},
{
"type": "color",
"id": "color_accent_text",
"label": "Button text",
"default": "#FFFFFF"
},
{
"type": "color",
"id": "color_sale",
"label": "Sale price",
"default": "#8A3A14"
},
{
"type": "color",
"id": "color_border",
"label": "Lines",
"default": "#DCD6CC"
},
{
"type": "header",
"content": "Fonts"
},
{
"type": "checkbox",
"id": "use_theme_fonts",
"label": "Use the theme fonts",
"default": true,
"info": "Turn off to use the fonts below."
},
{
"type": "font_picker",
"id": "heading_font",
"label": "Heading font",
"default": "helvetica_n4"
},
{
"type": "font_picker",
"id": "body_font",
"label": "Body font",
"default": "helvetica_n4"
}
],
"blocks": [
{
"type": "offer",
"name": "Offer",
"settings": [
{
"type": "text",
"id": "headline",
"label": "Offer (as the customer reads it)",
"default": "Offer headline"
},
{
"type": "select",
"id": "offer_type",
"label": "Type",
"options": [
{
"value": "percent",
"label": "percent"
},
{
"value": "fixed_amount",
"label": "fixed amount"
},
{
"value": "free_shipping",
"label": "free shipping"
},
{
"value": "gift_with_purchase",
"label": "gift with purchase"
},
{
"value": "bundle",
"label": "bundle"
},
{
"value": "no_discount",
"label": "no discount"
}
],
"default": "percent"
},
{
"type": "text",
"id": "code",
"label": "Discount code",
"info": "Leave empty for an automatic discount."
},
{
"type": "text",
"id": "details",
"label": "Applies to"
},
{
"type": "text",
"id": "starts_at",
"label": "Starts (ISO 8601 with offset)",
"info": "Example: 2026-11-27T00:00:00-05:00. Store time."
},
{
"type": "text",
"id": "ends_at",
"label": "Ends (ISO 8601 with offset)"
},
{
"type": "text",
"id": "starts_label",
"label": "Start label",
"info": "Example: Friday, Nov 27 at 12 AM ET"
},
{
"type": "text",
"id": "ends_label",
"label": "End label"
},
{
"type": "text",
"id": "starts_short",
"label": "Start date (short)"
},
{
"type": "text",
"id": "ends_short",
"label": "End date (short)"
}
]
},
{
"type": "product",
"name": "Product",
"settings": [
{
"type": "product",
"id": "product",
"label": "Product"
},
{
"type": "text",
"id": "blurb",
"label": "Short line under the title"
}
]
},
{
"type": "faq",
"name": "Question",
"settings": [
{
"type": "text",
"id": "question",
"label": "Question",
"default": "Question"
},
{
"type": "textarea",
"id": "answer",
"label": "Answer",
"info": "One paragraph per line."
}
]
}
],
"presets": [
{
"name": "GBC holiday deals"
}
]
}
{% endschema %}
snippets/gbc-product-card.liquid
{%- comment -%} GBC product card. Live price, compare-at, stock and image from Shopify. {%- endcomment -%}
{%- liquid
assign v = p.selected_or_first_available_variant
assign on_sale = false
if p.compare_at_price > p.price
assign on_sale = true
assign save = p.compare_at_price | minus: p.price | times: 100 | divided_by: p.compare_at_price
endif
assign low = false
if p.available and threshold > 0 and v.inventory_management == 'shopify' and v.inventory_policy == 'deny' and v.inventory_quantity <= threshold and v.inventory_quantity > 0
assign low = true
endif
assign band_price = p.price | divided_by: 100.0
-%}
<li class="gbc-card{% unless p.available %} is-soldout{% endunless %}" id="p-{{ p.handle }}" data-gbc-price="{{ band_price }}" {{ attrs }}>
<a class="gbc-card__media" href="{{ p.url }}" tabindex="-1" aria-hidden="true">
{%- if p.featured_image -%}
{%- assign loading = 'lazy' -%}{%- if index <= 4 -%}{%- assign loading = 'eager' -%}{%- endif -%}
{%- assign img_alt = p.featured_image.alt | default: p.title -%}
{{ p.featured_image | image_url: width: 1080 | image_tag: loading: loading, widths: '360, 540, 720, 1080', sizes: '(min-width: 1140px) 25vw, (min-width: 760px) 33vw, 50vw', alt: img_alt }}
{%- endif -%}
{%- if p.available == false -%}<span class="gbc-badge">Sold out</span>{%- elsif on_sale and save >= 5 -%}<span class="gbc-badge">Save {{ save }}%</span>{%- endif -%}
{%- if low -%}<span class="gbc-stock">Low stock</span>{%- endif -%}
</a>
<h3 class="gbc-card__title"><a href="{{ p.url }}">{{ p.title | escape }}</a></h3>
{%- if blurb != blank -%}<p class="gbc-card__blurb">{{ blurb | escape }}</p>{%- endif -%}
<p class="gbc-price">
<span class="gbc-price__now{% if on_sale %} is-sale{% endif %}">{% if p.price_varies %}From {% endif %}{{ p.price | money }}</span>
{%- if on_sale -%}<s class="gbc-price__was"><span class="gbc-sr">Regular price </span>{{ p.compare_at_price | money }}</s>{%- endif -%}
</p>
{%- if p.available == false -%}
<button class="gbc-btn gbc-btn--ghost" type="button" disabled>Sold out</button>
{%- elsif p.has_only_default_variant -%}
{%- form 'product', p -%}
<input type="hidden" name="id" value="{{ v.id }}">
<button class="gbc-btn" type="submit" name="add">Add to cart</button>
{%- endform -%}
{%- else -%}
<a class="gbc-btn gbc-btn--ghost" href="{{ p.url }}">Choose options</a>
{%- endif -%}
</li>
snippets/gbc-countdown.liquid
{%- comment -%} GBC countdown. Hidden until JS runs; the fallback text shows without JS. {%- endcomment -%}
<div class="gbc-cd-wrap">
<p class="gbc-cd__label" data-gbc-cd-label hidden></p>
<div class="gbc-cd" data-gbc-countdown role="timer" aria-live="off" hidden>
<div class="gbc-cd__u"><span class="gbc-cd__n" data-n>00</span><span class="gbc-cd__l">Days</span></div>
<div class="gbc-cd__u"><span class="gbc-cd__n" data-n>00</span><span class="gbc-cd__l">Hours</span></div>
<div class="gbc-cd__u"><span class="gbc-cd__n" data-n>00</span><span class="gbc-cd__l">Min</span></div>
<div class="gbc-cd__u"><span class="gbc-cd__n" data-n>00</span><span class="gbc-cd__l">Sec</span></div>
</div>
<p class="gbc-cd-fallback" data-gbc-cd-fallback>{{ fallback | newline_to_br | split: '<br />' | first | strip | escape }}</p>
</div>
templates/page.gbc-holiday.json
/*
* Generated by the GBC campaign factory for demo-northfold-bfcm-2026. Assign this template to the page /pages/holiday-deals.
*/
{
"sections": {
"main": {
"type": "gbc-holiday-deals",
"blocks": {
"offer_1": {
"type": "offer",
"settings": {
"headline": "Early access: 20% off everything",
"offer_type": "percent",
"code": "EARLYFOLD",
"details": "On everything in the store",
"starts_at": "2026-11-24T08:00:00-05:00",
"ends_at": "2026-11-26T23:59:00-05:00",
"starts_label": "Tuesday, Nov 24 at 8 AM ET",
"ends_label": "Thursday, Nov 26 at 11:59 PM ET",
"starts_short": "Tue, Nov 24",
"ends_short": "Thu, Nov 26"
}
},
"offer_2": {
"type": "offer",
"settings": {
"headline": "25% off sitewide",
"offer_type": "percent",
"code": "FOLD25",
"details": "On everything in the store",
"starts_at": "2026-11-27T00:00:00-05:00",
"ends_at": "2026-11-29T23:59:00-05:00",
"starts_label": "Friday, Nov 27 at 12 AM ET",
"ends_label": "Sunday, Nov 29 at 11:59 PM ET",
"starts_short": "Fri, Nov 27",
"ends_short": "Sun, Nov 29"
}
},
"offer_3": {
"type": "offer",
"settings": {
"headline": "30% off sitewide",
"offer_type": "percent",
"code": "CYBERFOLD30",
"details": "On everything in the store",
"starts_at": "2026-11-30T00:00:00-05:00",
"ends_at": "2026-12-01T23:59:00-05:00",
"starts_label": "Monday, Nov 30 at 12 AM ET",
"ends_label": "Tuesday, Dec 1 at 11:59 PM ET",
"starts_short": "Mon, Nov 30",
"ends_short": "Tue, Dec 1"
}
},
"offer_4": {
"type": "offer",
"settings": {
"headline": "Free shipping over $75",
"offer_type": "free_shipping",
"code": "",
"details": "On orders over $75.00",
"starts_at": "2026-11-24T00:00:00-05:00",
"ends_at": "2026-12-01T23:59:00-05:00",
"starts_label": "Tuesday, Nov 24 at 12 AM ET",
"ends_label": "Tuesday, Dec 1 at 11:59 PM ET",
"starts_short": "Tue, Nov 24",
"ends_short": "Tue, Dec 1"
}
},
"product_1": {
"type": "product",
"settings": {
"product": "ridgeline-leather-weekender",
"blurb": "Full-grain leather, brass hardware, room for three days of clothes."
}
},
"product_2": {
"type": "product",
"settings": {
"product": "highland-wool-camp-blanket",
"blurb": "Lambswool from a family mill. Porch in October, bed by December."
}
},
"product_3": {
"type": "product",
"settings": {
"product": "cast-iron-skillet-10",
"blurb": "Seasoned and ready the day it arrives. Stovetop, oven or campfire."
}
},
"product_4": {
"type": "product",
"settings": {
"product": "basecamp-folding-chair",
"blurb": "Folds flat in about two seconds and holds up to 300 lb."
}
},
"product_5": {
"type": "product",
"settings": {
"product": "hearth-oil-lantern",
"blurb": "One fill burns for about 15 hours."
}
},
"product_6": {
"type": "product",
"settings": {
"product": "walnut-serving-board",
"blurb": "One piece of black walnut, 18 by 10 inches."
}
},
"product_7": {
"type": "product",
"settings": {
"product": "enamel-camp-mug-set",
"blurb": "Two steel mugs. Camp stove or dishwasher, both fine."
}
},
"product_8": {
"type": "product",
"settings": {
"product": "cedar-smoke-soy-candle",
"blurb": "Cedarwood and birch tar, poured by hand into an amber jar."
}
},
"product_9": {
"type": "product",
"settings": {
"product": "trail-insulated-bottle-32",
"blurb": "Cold for 24 hours, hot for 12, and the lid does not leak."
}
},
"product_10": {
"type": "product",
"settings": {
"product": "field-journal-leather",
"blurb": "A refillable leather cover that darkens with use."
}
},
"product_11": {
"type": "product",
"settings": {
"product": "ribbed-merino-beanie",
"blurb": "Fine merino, so it is warm without the itch."
}
},
"faq_1": {
"type": "faq",
"settings": {
"question": "When does each offer end?",
"answer": "Early access: 20% off everything: Tue, Nov 24 to Thursday, Nov 26 at 11:59 PM ET.\n25% off sitewide: Fri, Nov 27 to Sunday, Nov 29 at 11:59 PM ET.\n30% off sitewide: Mon, Nov 30 to Tuesday, Dec 1 at 11:59 PM ET.\nFree shipping over $75: Tue, Nov 24 to Tuesday, Dec 1 at 11:59 PM ET."
}
},
"faq_2": {
"type": "faq",
"settings": {
"question": "Do I need a code?",
"answer": "For Early access: 20% off everything, enter EARLYFOLD at checkout.\nFor 25% off sitewide, enter FOLD25 at checkout.\nFor 30% off sitewide, enter CYBERFOLD30 at checkout.\nFree shipping over $75 is applied at checkout without a code."
}
},
"faq_3": {
"type": "faq",
"settings": {
"question": "Is shipping free?",
"answer": "Free shipping over $75: on orders over $75.00, from Tue, Nov 24 to Tuesday, Dec 1 at 11:59 PM ET."
}
},
"faq_4": {
"type": "faq",
"settings": {
"question": "What time zone are these times in?",
"answer": "All dates and times on this page are store time (America/New York)."
}
},
"faq_5": {
"type": "faq",
"settings": {
"question": "Where do I enter the code?",
"answer": "In the discount field at checkout. The buttons in our emails apply it for you."
}
}
},
"block_order": [
"offer_1",
"offer_2",
"offer_3",
"offer_4",
"product_1",
"product_2",
"product_3",
"product_4",
"product_5",
"product_6",
"product_7",
"product_8",
"product_9",
"product_10",
"product_11",
"faq_1",
"faq_2",
"faq_3",
"faq_4",
"faq_5"
],
"settings": {
"eyebrow": "Black Friday and Cyber Monday",
"headline": "Gear for the cold months, on sale this week",
"subhead": "Every code and end date is listed below. Free shipping over $75 for the whole event.",
"cta_label": "Shop the sale",
"offers_heading": "This week's offers",
"products_heading": "What we would pick",
"products_intro": "The things we reach for once it gets cold.",
"spotlight_heading": "Highland Wool Camp Blanket",
"spotlight_body": "Lambswool, woven at a family mill. It lives on the porch in October and on the bed by December.",
"closing_headline": "The sale ends Tue, Dec 1",
"closing_body": "Each offer stops at the time shown on its card. Store time, Eastern.",
"fine_print": "Early access: 20% off everything: Tuesday, Nov 24 at 8 AM ET to Thursday, Nov 26 at 11:59 PM ET. Code EARLYFOLD.\n25% off sitewide: Friday, Nov 27 at 12 AM ET to Sunday, Nov 29 at 11:59 PM ET. Code FOLD25.\n30% off sitewide: Monday, Nov 30 at 12 AM ET to Tuesday, Dec 1 at 11:59 PM ET. Code CYBERFOLD30.\nFree shipping over $75: Tuesday, Nov 24 at 12 AM ET to Tuesday, Dec 1 at 11:59 PM ET.",
"hero_image_url": "https://images.unsplash.com/photo-1631630259742-c0f0b17c6c10?w=1200&q=80&auto=format&fit=crop",
"hero_image_alt": "A wood stove and an armchair in a cabin room",
"spotlight_product": "highland-wool-camp-blanket",
"fallback_handles": "ridgeline-leather-weekender, highland-wool-camp-blanket, cast-iron-skillet-10, basecamp-folding-chair, hearth-oil-lantern, walnut-serving-board, enamel-camp-mug-set, cedar-smoke-soy-candle, trail-insulated-bottle-32, field-journal-leather, ribbed-merino-beanie",
"low_stock_threshold": 5,
"show_filters": true,
"color_bg": "#FBF8F3",
"color_surface": "#F2ECE2",
"color_text": "#1A1915",
"color_muted": "#5C574E",
"color_primary": "#1F3A2E",
"color_primary_text": "#FFFFFF",
"color_accent": "#B4491A",
"color_accent_text": "#FFFFFF",
"color_sale": "#B4491A",
"color_border": "#DCD9D4",
"use_theme_fonts": true
}
}
},
"order": [
"main"
]
}
INSTALL.md
# Install: Northfold Supply Co. holiday deals page Campaign: `demo-northfold-bfcm-2026`. Files in this folder: - `sections/gbc-holiday-deals.liquid`: the section (styles, countdown script and settings schema included) - `snippets/gbc-countdown.liquid` and `snippets/gbc-product-card.liquid`: used by the section - `templates/page.gbc-holiday.json`: a page template with the section already filled in (offers, products, copy, colors) Product prices, compare-at prices, stock and images are read live from Shopify. Offer text, codes and dates come from the approved brief. ## Automatic (preferred) `node factory/cli.mjs push-shopify demo-northfold` duplicates the live theme as **"GBC | demo-northfold-bfcm-2026 | preview"** (unpublished) and uploads the four files there with `themeFilesUpsert`. It never publishes a theme and refuses to write to the live theme. ## Manual 1. Shopify admin > Online Store > Themes. On the current theme, click **...** > **Duplicate**. Rename the copy to `GBC | demo-northfold-bfcm-2026 | preview`. 2. On the copy: **...** > **Edit code**. Add the two snippets, the section and the template with the exact file names above, and paste the contents. 3. Online Store > Pages > **Add page**. Title it, set the handle to `holiday-deals` (Search engine listing > URL) and choose the template **page.gbc-holiday**. Save it as **hidden** until launch. 4. Open the copy in the theme editor (Customize), go to the page and check offers, products, colors and fonts. Use **Preview** to share a link. 5. Check that each discount code below exists in Shopify (Discounts) and matches the dates: - Early access: 20% off everything: code `EARLYFOLD`, Tuesday, Nov 24 at 8 AM ET to Thursday, Nov 26 at 11:59 PM ET - 25% off sitewide: code `FOLD25`, Friday, Nov 27 at 12 AM ET to Sunday, Nov 29 at 11:59 PM ET - 30% off sitewide: code `CYBERFOLD30`, Monday, Nov 30 at 12 AM ET to Tuesday, Dec 1 at 11:59 PM ET - Free shipping over $75: automatic discount, Tuesday, Nov 24 at 12 AM ET to Tuesday, Dec 1 at 11:59 PM ET 6. The store owner (or we, after written approval) publishes the theme copy and makes the page visible on launch day. Publishing is never automatic. ## Notes - Countdown and offer states use the store time zone (America/New_York); dates carry the UTC offset so every visitor sees the same deadline. - Without JavaScript the page still shows every offer, code and end date; only the timer is hidden. - The "Low stock" note only appears when Shopify tracks inventory for the product and the quantity is at or below the threshold in the section settings. No numbers are invented. - If the theme does not define `--font-heading-family` / `--font-body-family` (Dawn and most Shopify themes do), turn off "Use the theme fonts" and pick fonts in the section settings.