/**
 * BFCM Hub — `/bfcm/`.
 *
 * Ported from the Claude Design artboard `BFCM.dc.html`. That artboard is
 * written in the design system's own component classes — `.card`, `.badge`,
 * `.btn`, `.stat-n`, `.icon-circle` — plus lucide icons pulled from a CDN at
 * run time. None of that is carried across:
 *
 *   - `.card`, `.badge` and `.stat-*` are a plain bordered box, a pill and a
 *     figure-over-label pair. `.zpx-card` is already the first, and the other
 *     two are ten lines each below. Importing a third component library to get
 *     them would have put this page's look at the mercy of a kit no other page
 *     loads.
 *   - `.btn btn--primary` is `zpx_cta()`, to the gradient and the shadow.
 *   - The lucide CDN script is one icon on this page — a gift glyph — which is
 *     now in `zipify2026_icon()` and costs no request.
 *
 * What is genuinely this page's own is here: the offer card, the app shelf,
 * the scrolling resource rails and the numbered step heads.
 */

/* ==========================================================================
   SHARED: badges and stat pairs
   Small enough that a private copy is cheaper than a dependency.
   ========================================================================== */

.zpb-badge {
	display:inline-flex; align-items:center; gap:6px;
	padding:5px 11px; border-radius:var(--r-pill);
	font-size:11px; font-weight:800; letter-spacing:.04em;
	line-height:1.2; white-space:nowrap;
	background:var(--ink-100); color:var(--ink-700);
}
.zpb-badge--blue   { background:rgba(45,107,228,.1); color:var(--blue-700); }
.zpb-badge--pink   { background:rgba(240,48,90,.1); color:var(--pink-500); }
.zpb-badge--live   { background:rgba(240,48,90,.1); color:var(--pink-500); }
.zpb-badge--zipify { background:rgba(255,215,72,.16); color:#8a5a00; }
.zpb-badge__dot { width:6px; height:6px; border-radius:50%; background:currentColor; }

/* ==========================================================================
   §1 HERO
   ========================================================================== */

.zpb-hero .zpx-wrap { padding-block:112px 88px; text-align:center; }
.zpb-hero__head .zpx-h2 { font-size:clamp(36px,4.6vw,64px); letter-spacing:var(--ls-tight); line-height:1.02; }
/* The artboard sets `text-wrap:nowrap` on a 22ch measure, which only holds at
   the width it was drawn at. `balance` keeps the two-line shape and wraps
   instead of clipping. */
.zpb-hero__head .zpx-h2 { text-wrap:balance; }
.zpb-hero__accent { display:inline-block; }
.zpb-hero__cta { display:flex; justify-content:center; margin-bottom:56px; }

.zpb-stats {
	display:flex; align-items:stretch; justify-content:center;
	flex-wrap:wrap; gap:56px; margin:0;
	padding-top:40px; border-top:1px solid rgba(255,255,255,.1);
}
.zpb-stat { display:flex; flex-direction:column-reverse; gap:8px; }
.zpb-stat__value { margin:0; font-size:38px; font-weight:900; letter-spacing:var(--ls-tight); line-height:1; color:var(--zip-yellow); }
.zpb-stat__label { font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:rgba(255,255,255,.6); }

/* The sticky table of contents. Offsets from the header's own declared
   height rather than a literal, so the two cannot drift apart. */
.zpb-jump {
	position:sticky; top:var(--zp-header-h); z-index:20;
	background:rgba(255,255,255,.92); backdrop-filter:blur(6px);
	border-bottom:1px solid var(--border);
}
.zpb-jump__inner {
	max-width:1180px; margin:0 auto; padding:14px 48px;
	display:flex; align-items:center; justify-content:center;
	flex-wrap:wrap; gap:8px;
}
.zpb-jump__k {
	margin-right:8px; font-size:11px; font-weight:700;
	letter-spacing:var(--ls-eyebrow); text-transform:uppercase; color:var(--fg-3);
}
.zpb-jump__link {
	padding:8px 16px; border-radius:var(--r-pill);
	background:var(--ink-050); border:1px solid var(--border);
	font-size:13px; font-weight:600; color:var(--fg-2);
	transition:background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.zpb-jump__link:hover { background:var(--surface); color:var(--fg); border-color:var(--ink-300); }
/* Marked on the first pill server-side and moved by `bfcm.js` as the reader
   crosses into each band. The transition is already declared above, so the
   fill slides rather than snaps.

   EACH BAND HAS ITS OWN FILL. One ink fill moving along the bar says which
   pill is pressed but reads as a pressed button, not as a position — and the
   bar is stuck to the top of the window for the whole page, where a change of
   colour is caught out of the corner of the eye and a change of position two
   pills over is not. So `.is-active` paints from the pill's own `data-tone`,
   which `zipify2026_bfcm_nav()` sets per band. Ink is the default, for a band
   added without a tone. */
.zpb-jump__link.is-active {
	background:var(--zpb-tone,var(--ink-900));
	border-color:var(--zpb-tone,var(--ink-900));
	color:var(--zpb-tone-fg,#fff);
}
.zpb-jump__link.is-active:hover { filter:brightness(1.08); color:var(--zpb-tone-fg,#fff); }
.zpb-jump__link[data-tone="pink"]   { --zpb-tone:var(--pink-500); }
.zpb-jump__link[data-tone="blue"]   { --zpb-tone:var(--blue-500); }
.zpb-jump__link[data-tone="royal"]  { --zpb-tone:var(--zip-royal); }
.zpb-jump__link[data-tone="orange"] { --zpb-tone:var(--orange-500); }
/* Yellow is the one fill white type cannot sit on. */
.zpb-jump__link[data-tone="yellow"] { --zpb-tone:var(--zip-yellow); --zpb-tone-fg:var(--ink-900); }

/* Anchored sections clear the sticky nav as well as the header. */
.zpb-step, .zpb-webinar, .zpb-bundle, .zpb-shelf, .zpb-plus, .zpb-close { scroll-margin-top:calc(var(--zp-header-h) + 56px); }

/* ==========================================================================
   §2 THE WEBINAR CARD
   ========================================================================== */

.zpb-wcard {
	display:grid; grid-template-columns:minmax(0,340px) minmax(0,1fr);
	align-items:stretch; overflow:hidden;
	border-radius:20px; border:1px solid var(--ink-200); background:var(--surface);
	box-shadow:var(--sh-2);
}
.zpb-wcard__shot { height:100%; border-radius:0; --zpx-slot-ratio:3/4; }
/* The art is a 16:9 thumbnail and this box is portrait, so a centred crop
   would sit on the microphone and push the host off the left edge. 34%
   puts him in the middle of the crop, which is the point of the shot. The
   rule is harmless once the box turns 16:9 below 1023px — nothing is
   cropped there for a position to move. */
.zpb-wcard__shot .zpx-slot__img { object-position:34% center; }
.zpb-wcard__body { padding:26px 32px; }
.zpb-wcard__when { display:flex; align-items:center; gap:12px; margin:0 0 16px; flex-wrap:wrap; }
.zpb-wcard__date { font-size:13px; font-weight:600; color:var(--fg-2); }
.zpb-wcard__head { margin-bottom:20px; }
.zpb-wcard__head .zpx-h2 { font-size:26px; letter-spacing:var(--ls-tight); line-height:1.14; }
.zpb-wcard__head .zpx-lede { font-size:15px; max-width:52ch; }

.zpb-host { display:flex; align-items:center; gap:16px; margin-bottom:20px; }
.zpb-host__face { width:44px; height:44px; border-radius:var(--r-pill); object-fit:cover; border:1px solid var(--border); flex:0 0 auto; }
.zpb-host__name { margin:0 0 2px; font-size:12px; font-weight:700; letter-spacing:var(--ls-eyebrow); text-transform:uppercase; color:var(--fg); }
.zpb-host__bio { margin:0; font-size:13px; line-height:1.5; color:var(--fg-2); }

.zpb-gift {
	display:flex; align-items:center; gap:12px; margin:0 0 20px;
	padding:12px 16px; border-radius:var(--r-md); background:var(--ink-050);
	font-size:14px; line-height:1.5; color:var(--fg-2);
}
.zpb-gift strong { font-weight:600; color:var(--fg); }
.zpb-gift__icon {
	display:flex; align-items:center; justify-content:center;
	width:28px; height:28px; flex:0 0 auto; border-radius:var(--r-pill);
	background:var(--blue-900); color:var(--zip-yellow);
}
.zpb-gift__icon svg { width:17px; height:17px; }

.zpb-wcard__cta { display:flex; align-items:center; gap:20px; flex-wrap:wrap; }
.zpb-wcard__note { font-size:13px; color:var(--fg-2); }

/* ==========================================================================
   §3 THE BUNDLE OFFER
   ========================================================================== */

.zpb-offer {
	max-width:520px; margin:0 auto; text-align:left; overflow:hidden;
	border-radius:20px; background:var(--surface);
	box-shadow:0 32px 70px rgba(0,0,0,.45);
}
.zpb-offer__body { padding:32px 32px 24px; }
.zpb-offer__k { margin:0 0 8px; font-size:12px; font-weight:700; letter-spacing:var(--ls-eyebrow); text-transform:uppercase; color:var(--fg-2); }
.zpb-offer__price { display:flex; align-items:baseline; gap:8px; margin:0 0 24px; }
.zpb-offer__amount { font-size:46px; font-weight:900; letter-spacing:var(--ls-tight); line-height:1; color:var(--fg); }
.zpb-offer__per { font-size:17px; color:var(--fg-2); }

.zpb-offer__lead {
	display:flex; align-items:center; gap:16px;
	padding:16px; border-radius:var(--r-md); background:var(--ink-050);
	color:var(--fg); transition:background var(--dur-base) var(--ease-out);
}
.zpb-offer__lead:hover { background:var(--ink-100); color:var(--fg); }
.zpb-offer__mark { display:block; width:28px; height:28px; flex:0 0 auto; background-repeat:no-repeat; background-position:center; background-size:contain; }
.zpb-offer__leadtext { flex:1 1 auto; min-width:0; }
.zpb-offer__leadname { display:block; font-size:16px; font-weight:700; line-height:1.25; color:var(--fg); }
.zpb-offer__leadsub { display:block; font-size:14px; line-height:1.35; color:var(--fg-2); }

.zpb-offer__more { margin:24px 0 16px; font-size:11px; font-weight:700; letter-spacing:var(--ls-eyebrow); text-transform:uppercase; color:var(--accent); }
/* One column, not the artboard's 2x2: Smart Bundles left the bundle and three
   rows in a two-column grid leave a hole. Full-width rows also stop the longer
   app names hitting the ellipsis below. */
.zpb-offer__grid { display:grid; grid-template-columns:minmax(0,1fr); gap:12px; }
.zpb-offer__row {
	display:flex; align-items:center; gap:12px;
	padding:12px 16px; border-radius:var(--r-md);
	border:1px solid var(--ink-200); color:var(--fg);
	font-size:15px; font-weight:700; line-height:1.3;
	transition:border-color var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out);
}
.zpb-offer__row:hover { border-color:var(--ink-400); background:var(--ink-050); color:var(--fg); }
.zpb-offer__row span { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.zpb-offer__tick { flex:0 0 auto; color:var(--orange-500); }

.zpb-offer__cta { padding:0 32px 32px; }
.zpb-offer__btn { display:block; width:100%; text-align:center; }
.zpb-offer__code {
	margin:0; padding:16px 32px; background:var(--ink-050);
	border-top:1px solid var(--ink-200); font-size:14px; color:var(--fg-2);
}
.zpb-offer__code strong { font-weight:700; color:var(--fg); }

/* ==========================================================================
   §4 THE APP SHELF
   Four apps behind one row of pills — see the section's header.
   ========================================================================== */


/* `product.css` styles `.zpx-tab` for the dark grounds the other tab groups
   sit on — translucent white borders over ink. This band is `subtle`, so the
   pills are restated here as the artboard draws them: a light card that fills
   to ink when selected. Only the painted properties are overridden; the
   helper's layout, transition and focus ring carry through. */
.zpb-shelf .zpx-head { margin-bottom:16px; }
.zpb-pills { justify-content:center; padding-block:32px; margin-bottom:16px; }
/* The artboard's pill row spans the band, not the 1000px column the panel sits
   in, so five pills stay on one line at desktop widths. Centred on the column
   and allowed past it; `max-width` lets it wrap before it hits the gutters. */
@media (min-width:720px) {
	.zpb-pills { position:relative; left:50%; translate:-50% 0; width:max-content; max-width:calc(100vw - 96px); }
}
button.zpx-tab.zpb-pill {
	display:flex; align-items:center; gap:12px;
	padding:10px 20px 10px 12px;
	border:1.5px solid var(--ink-200); background:var(--surface);
	box-shadow:var(--sh-1); color:var(--fg-2); font-weight:600;
	transition:background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out),
		border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
button.zpx-tab.zpb-pill:hover { border-color:var(--ink-400); color:var(--fg); }
button.zpx-tab.zpb-pill[aria-selected="true"] {
	background:var(--ink-900); border-color:var(--ink-900); color:#fff; box-shadow:var(--sh-3);
}
button.zpx-tab.zpb-pill[aria-selected="true"]:hover { color:#fff; }
button.zpx-tab.zpb-pill:focus-visible { box-shadow:0 0 0 3px rgba(45,107,228,.4); }
.zpb-pill__well {
	display:flex; align-items:center; justify-content:center;
	width:34px; height:34px; flex:0 0 auto;
	border-radius:50%; background:var(--ink-900);
	transition:background var(--dur-base) var(--ease-out);
}
.zpb-pill[aria-selected="true"] .zpb-pill__well { background:rgba(255,255,255,.12); }
/* The marks are dark-on-light SVGs, so the selected pill inverts them rather
   than shipping a second file per app. */
.zpb-pill__mark {
	display:block; width:20px; height:20px;
	background-repeat:no-repeat; background-position:center; background-size:contain;
	transition:filter var(--dur-base) var(--ease-out);
}
/* The marks are not optically centred in their own viewBoxes; nudge each. */
#zpb-app-tab-perfectmatch .zpb-pill__mark { translate:1px 0; }
#zpb-app-tab-pages .zpb-pill__mark { translate:0 1px; }
#zpb-app-tab-shoprank .zpb-pill__mark { translate:-1px 0; }
#zpb-app-tab-ocu .zpb-pill__mark { translate:1px 0; }
.zpb-pill__name { font-size:15px; line-height:1.2; white-space:nowrap; }

.zpb-app__shot { border-radius:18px; border:1px solid var(--ink-200); margin-bottom:32px; }
.zpb-app__grid { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.15fr); gap:56px; align-items:start; }
.zpb-app__h { margin:0 0 24px; font-size:34px; letter-spacing:var(--ls-tight); line-height:1.1; }
/* Both CTAs on one line. They are a pair — install it, or read about it first
   — and stacked they read as two separate offers.
   `product.css` sizes `.zpx-btn` for a band's main call to action, at which
   size these two do not fit the panel's left column side by side. The artboard
   uses its `btn--sm` here for the same reason, so the two are restated at that
   size rather than the row being allowed to wrap. */
.zpb-app__cta { display:flex; flex-wrap:nowrap; align-items:center; gap:12px; }
.zpb-app__cta .zpx-btn { padding:12px 20px; font-size:13px; }
.zpb-app__cta .zpx-btn--outline { padding:11px 19px; }
.zpb-app__body { margin:0 0 24px; font-size:17px; line-height:1.65; color:var(--fg-2); }
.zpb-app__proof { display:flex; align-items:center; gap:20px; margin:0; flex-wrap:wrap; }
.zpb-app__stat { display:flex; align-items:center; gap:8px; }
.zpb-app__figure { font-size:26px; font-weight:900; letter-spacing:var(--ls-tight); line-height:1; }
.zpb-app__statlabel { font-size:14px; line-height:1.3; color:var(--fg-2); }
.zpb-app__already { margin:12px 0 0; font-size:13px; color:var(--fg-2); }
.zpb-app__already a { margin-left:4px; font-weight:600; color:var(--blue-700); }

/* ==========================================================================
   §5 THE STEP RAILS
   ========================================================================== */

.zpb-step .zpx-wrap { padding-block:56px; }
.zpb-step__wrap { max-width:1180px; }
.zpb-step__head { display:flex; align-items:center; gap:20px; margin-bottom:32px; }
.zpb-step__n {
	display:flex; align-items:center; justify-content:center;
	width:46px; height:46px; flex-shrink:0; border-radius:var(--r-pill);
	background:var(--blue-900); color:var(--zip-yellow);
	font-size:15px; font-weight:900; letter-spacing:0;
}
.zpb-step__h { margin:0; font-size:clamp(26px,3vw,34px); letter-spacing:var(--ls-tight); line-height:1.1; }
/* The rail's prev/next, pushed to the head's far end. Same box as
   `.zpp-rail-btn` on /apps/pages/, restated here because the two pages do not
   share a stylesheet. A disabled arrow stays in place, dimmed, so the pair
   never shifts as the rail reaches an end. */
.zpb-rail-nav { display:flex; gap:10px; margin-left:auto; flex-shrink:0; }
.zpb-rail-btn {
	display:flex; align-items:center; justify-content:center;
	width:48px; height:48px; border:1px solid var(--ink-200); border-radius:var(--r-pill);
	background:var(--surface); color:var(--ink-700); font-size:16px; cursor:pointer;
	transition:background var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.zpb-rail-btn:hover { background:var(--ink-100); }
.zpb-rail-btn:focus-visible { outline:3px solid var(--blue-500); outline-offset:2px; }
.zpb-rail-btn:disabled { opacity:.35; cursor:default; }
.zpb-rail-btn:disabled:hover { background:var(--surface); }

.zpb-rail {
	display:flex; gap:20px; min-width:0;
	overflow-x:auto; scrollbar-width:none;
	scroll-snap-type:x proximity; padding-bottom:8px;
}
.zpb-rail::-webkit-scrollbar { display:none; }
/* A scroll container has to be reachable from the keyboard, or its content is
   stranded for anyone not using a pointer. */
.zpb-rail:focus-visible { outline:3px solid var(--blue-500); outline-offset:4px; }

.zpb-res {
	display:flex; flex-direction:column; overflow:hidden;
	flex:0 0 calc((100% - 40px) / 3.35); min-width:240px;
	scroll-snap-align:start;
	border-radius:16px; border:1px solid var(--ink-200); background:var(--surface);
	box-shadow:var(--sh-1); color:var(--fg);
	transition:box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
a.zpb-res:hover { box-shadow:var(--sh-3); transform:translateY(-2px); color:var(--fg); }
.zpb-res__shot { flex-shrink:0; border-radius:0; }
.zpb-res__body { display:flex; flex-direction:column; gap:12px; flex:1; padding:24px; }
.zpb-res__tags { display:flex; align-items:center; gap:12px; flex-wrap:wrap; }
.zpb-res__topic { font-size:11px; font-weight:700; letter-spacing:var(--ls-eyebrow); text-transform:uppercase; color:var(--fg-2); }
.zpb-res__title { font-size:17px; font-weight:800; letter-spacing:-0.01em; line-height:1.3; color:var(--fg); }
.zpb-res__meta { font-size:13px; color:var(--fg-2); }
.zpb-res__open { margin-top:auto; font-size:13px; font-weight:800; color:var(--zip-royal); }

/* ==========================================================================
   §6 PLUS AND THE CASE STUDIES
   ========================================================================== */

.zpb-plus__grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:56px; align-items:center; }
.zpb-plus__cta { display:flex; flex-wrap:wrap; gap:12px; }
.zpb-plus__side { display:grid; gap:20px; }
.zpb-plus__shot { border-radius:20px; }
.zpb-plus__stats { display:flex; gap:16px; margin:0; }
.zpb-plus__stat { display:flex; flex:1 1 0; min-width:0; flex-direction:column; gap:6px; margin:0; text-align:center; }
.zpb-plus__statvalue { font-size:30px; font-weight:900; letter-spacing:var(--ls-tight); line-height:1; color:var(--zip-yellow); }
.zpb-plus__statlabel { font-size:12px; line-height:1.4; color:rgba(255,255,255,.66); }

.zpb-cases { margin-top:72px; padding-top:56px; border-top:1px solid rgba(255,255,255,.14); }
.zpb-cases__h { margin:0 0 28px; }
.zpb-cases__list { list-style:none; margin:0; padding:0; display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:20px; }
.zpb-case {
	display:flex; align-items:center; gap:16px; height:100%;
	padding:20px; border-radius:16px;
	border:1px solid rgba(255,255,255,.12); background:rgba(255,255,255,.05);
	transition:border-color var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out),
		transform var(--dur-base) var(--ease-out);
}
a.zpb-case:hover {
	border-color:rgba(255,255,255,.28); background:rgba(255,255,255,.09);
	transform:translateY(-2px);
}
a.zpb-case:hover .zpb-case__line strong { color:#fff; }
.zpb-case__shot { flex:0 0 56px; width:56px; border-radius:12px; }
/* A logotype is not a photograph: it gets the white ground it was drawn for,
   room to breathe inside the chip, and `contain`, because a wordmark cropped
   to fill a square is a broken wordmark. The two cases with no logotype fall
   through to their case study's featured image and stay `cover`. */
.zpb-case__shot--logo { background:#fff; padding:8px; }
/* Set by `zipify2026_bfcm_shot()`'s `fit` argument. `product.css` gives every
   slot image `cover`, which is right for a screenshot and wrong for a mark. */
.zpx-slot__img--contain { object-fit:contain; }
.zpb-case__line { display:block; margin:0; font-size:15px; line-height:1.55; color:rgba(255,255,255,.78); text-wrap:pretty; }
.zpb-case__line strong { color:#fff; font-weight:800; }
.zpb-case__figure { font-weight:900; color:var(--zip-yellow); }

/* ==========================================================================
   §7 CLOSING
   ========================================================================== */

.zpb-close__grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:56px; align-items:center; }
.zpb-close__cta { display:flex; flex-wrap:wrap; gap:12px; }

.zpb-manifest { padding:28px; border-radius:20px; border:1px solid rgba(255,255,255,.14); background:rgba(255,255,255,.05); }
.zpb-manifest__k { margin:0 0 18px; font-size:11px; font-weight:800; letter-spacing:var(--ls-eyebrow); text-transform:uppercase; color:var(--zip-yellow); }
.zpb-manifest__list { list-style:none; margin:0 0 18px; padding:0; display:flex; flex-direction:column; gap:12px; }
.zpb-manifest__list li { display:flex; align-items:center; gap:12px; }
.zpb-manifest__mark {
	display:block; width:24px; height:24px; flex:0 0 auto;
	background-repeat:no-repeat; background-position:center; background-size:contain;
}
.zpb-manifest__name { flex:1 1 auto; font-size:15px; font-weight:700; color:#fff; }
.zpb-manifest__term { font-size:13px; color:rgba(255,255,255,.66); white-space:nowrap; }
.zpb-manifest__fine { margin:0; padding-top:16px; border-top:1px solid rgba(255,255,255,.12); font-size:13px; line-height:1.5; color:rgba(255,255,255,.6); }

/* ==========================================================================
   §8 THE REGISTRATION MODAL
   A `<dialog>`, so the top layer, the backdrop and focus containment come from
   the element rather than from a z-index and a script. See the section's own
   header for why the form inside it is empty until the button is pressed.
   ========================================================================== */

.zpb-optin {
	/* `100%` here is the viewport, not a parent — a top-layer element has no
	   containing block but the window — so the gutter has to come off it. */
	width:min(440px,calc(100% - 40px)); max-height:90vh; padding:0;
	border:0; border-radius:var(--r-xl); background:var(--surface);
	box-shadow:var(--sh-4); color:var(--fg); overflow:visible;
}
.zpb-optin::backdrop { background:rgba(6,10,26,.72); backdrop-filter:blur(6px); }
.zpb-optin__card { position:relative; padding:32px; max-height:90vh; overflow-y:auto; border-radius:inherit; }

.zpb-optin__close {
	position:absolute; top:16px; right:16px;
	display:flex; align-items:center; justify-content:center;
	width:34px; height:34px; padding:0;
	border:0; border-radius:var(--r-pill); cursor:pointer;
	background:var(--ink-100); color:var(--ink-600);
	transition:background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.zpb-optin__close:hover { background:var(--ink-200); color:var(--fg); }
.zpb-optin__close svg { width:12px; height:12px; }
/* `showModal()` moves focus into the dialog, and the close button is the first
   thing in it — so this ring is what the reader sees on every open. The
   browser default is a hard black circle over the card; this is the same ring
   the rest of the page uses. */
.zpb-optin__close:focus-visible {
	outline:none; background:var(--ink-200); color:var(--fg);
	box-shadow:0 0 0 3px rgba(45,107,228,.4);
}

.zpb-optin__badge { margin:0 0 16px; }
.zpb-optin__h { margin:0 0 8px; font-size:26px; font-weight:800; letter-spacing:var(--ls-tight); line-height:1.1; color:var(--fg); }
.zpb-optin__when { margin:0 0 24px; font-size:15px; color:var(--fg-2); }
.zpb-optin__loading { margin:0; font-size:14px; color:var(--fg-2); }
.zpb-optin__fine { margin:12px 0 0; font-size:13px; line-height:1.5; text-align:center; color:var(--ink-400); }

/* HubSpot builds these fields client-side and ships its own unstyled markup,
   so the class names below are theirs, not ours. Restated against this page's
   tokens — same treatment the opt-in page on `lp.zipify.com` gives them — so
   the embed does not land in the middle of the card looking like a different
   website. */
.zpb-optin .hs-form-field { margin-bottom:16px; }
/* HubSpot wraps every label's text in a `<span>` of its own, so the type has
   to be set on both or the span keeps the browser default. */
.zpb-optin .hs-form-field > label,
.zpb-optin .hs-form-field > label > span {
	display:block; font-size:14px; font-weight:700; line-height:1.3; color:var(--fg);
}
.zpb-optin .hs-form-field > label { margin-bottom:6px; }
.zpb-optin .hs-form-field > label .hs-form-required { display:inline; color:var(--pink-500); }
.zpb-optin input[type="text"],
.zpb-optin input[type="email"],
.zpb-optin input[type="tel"],
.zpb-optin input[type="number"],
.zpb-optin select,
.zpb-optin textarea {
	width:100%; padding:12px 14px;
	border:1.5px solid var(--ink-200); border-radius:var(--r-md);
	background:var(--surface); font:inherit; font-size:15px; color:var(--fg);
}
.zpb-optin input:focus, .zpb-optin select:focus, .zpb-optin textarea:focus {
	outline:none; border-color:var(--blue-500); box-shadow:0 0 0 3px rgba(45,107,228,.18);
}
.zpb-optin input::placeholder { color:var(--ink-400); }
.zpb-optin .hs-button, .zpb-optin input[type="submit"] {
	width:100%; margin-top:4px; padding:14px 20px;
	border:0; border-radius:var(--r-pill); cursor:pointer;
	font:inherit; font-size:15px; font-weight:800; color:#fff;
	background:linear-gradient(90deg,var(--orange-500),var(--pink-500));
	transition:filter var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.zpb-optin .hs-button:hover, .zpb-optin input[type="submit"]:hover { filter:brightness(1.08); transform:translateY(-1px); }
.zpb-optin .hs-error-msgs { list-style:none; margin:6px 0 0; padding:0; }
.zpb-optin .hs-error-msgs label { font-size:13px; color:var(--pink-500); text-transform:none; letter-spacing:0; }
.zpb-optin .legal-consent-container,
.zpb-optin .hs-richtext { font-size:13px; line-height:1.5; color:var(--fg-2); }

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */

@media (max-width:1023px) {
	.zpb-wcard { grid-template-columns:minmax(0,1fr); }
	.zpb-wcard__shot { height:auto; --zpx-slot-ratio:16/9; }
	.zpb-app__grid { grid-template-columns:minmax(0,1fr); gap:32px; }
	.zpb-plus__grid,
	.zpb-close__grid { grid-template-columns:minmax(0,1fr); gap:36px; }
	.zpb-res { flex-basis:calc((100% - 20px) / 2.15); }
}

@media (max-width:719px) {
	.zpb-hero .zpx-wrap { padding-block:88px 64px; }

	.zpb-hero__cta .zpx-btn { width:100%; }
	.zpb-stats { gap:28px; flex-direction:column; align-items:flex-start; text-align:left; }
	.zpb-jump__inner { padding:12px 20px; justify-content:flex-start; overflow-x:auto; flex-wrap:nowrap; scrollbar-width:none; }
	.zpb-jump__inner::-webkit-scrollbar { display:none; }
	.zpb-jump__link { white-space:nowrap; }
	.zpb-offer__grid { grid-template-columns:minmax(0,1fr); }
	.zpb-offer__body, .zpb-offer__cta { padding-inline:24px; }
	.zpb-wcard__body { padding:24px; }
	.zpb-res { flex-basis:80%; min-width:0; }
	/* On a phone the arrows move under the rail, centred, the way the Pages
	   rails place theirs. The head is `display:contents` so its number, title
	   and arrows lay out as siblings of the rail in one grid on the wrap:
	   number beside title, rail full width, arrows last. The markup stays in
	   source order for the desktop head. */
	.zpb-step__wrap {
		display:grid; grid-template-columns:auto minmax(0,1fr);
		column-gap:16px; align-items:center;
	}
	.zpb-step__head { display:contents; }
	/* The head's bottom margin moves onto its two visible children, since a
	   `display:contents` box has no margin of its own. */
	.zpb-step__n { width:40px; height:40px; font-size:14px; margin-bottom:24px; }
	.zpb-step__h { margin-bottom:24px; }
	.zpb-rail { grid-column:1 / -1; }
	/* `order` puts the arrows after the rail; in source they sit before it,
	   inside the head. */
	.zpb-rail-nav { grid-column:1 / -1; order:1; justify-content:center; margin:20px 0 0; gap:10px; }
	.zpb-rail-btn { width:42px; height:42px; }
	.zpb-plus__stats { flex-wrap:wrap; row-gap:20px; }
	.zpb-plus__stat { flex:1 1 auto; }
	/* Four pills do not fit across a phone. They scroll, like the jump bar
	   above and the resource rails below, rather than wrapping into four rows
	   and pushing the panel off the screen. */
	.zpb-shelf .zpx-head { margin-bottom:0; }
	.zpb-pills {
		flex-wrap:nowrap; justify-content:flex-start;
		overflow-x:auto; scrollbar-width:none;
		margin-inline:-20px; padding-inline:20px;
	}
	.zpb-pills::-webkit-scrollbar { display:none; }
	.zpb-pill { flex:0 0 auto; }
	#zpb-app-panel-pages .zpb-app__proof,
	#zpb-app-panel-perfectmatch .zpb-app__proof { flex-direction:column; align-items:flex-start; gap:12px; }
	#zpb-app-panel-pages .zpb-app__stat,
	#zpb-app-panel-perfectmatch .zpb-app__stat { width:100%; gap:12px; }
	#zpb-app-panel-pages .zpb-app__statlabel,
	#zpb-app-panel-perfectmatch .zpb-app__statlabel { flex:1 1 auto; }
	/* Stacked here and only here: at this width the two buttons side by side
	   are each too narrow to read. */
	.zpb-app__cta { flex-wrap:wrap; }
	.zpb-optin__card { padding:28px 20px; }
	.zpb-optin__h { font-size:22px; }
}
