/* Zipify Home — the shared section vocabulary (design spec §6).
   Requires tokens.css and theme.css. Registered as `zp-home`; enqueued by
   page-home.php alone, so it never loads on another page.

   Elementor generated Home's layout CSS from container settings. This file
   carries it instead, transcribed from the artboard extracts in
   .superpowers/sdd/2026-09-10-native-home-templates/design/.

   WHAT WAS DROPPED, NOT LOST. About fifteen rules in the plugin's
   assets/css/zp-widgets.css existed only to out-specify Elementor. There is no
   Elementor stylesheet and no Elementor kit in this render path, so they are
   deliberately absent:

   * `.elementor-widget-button.zp-cta` (the wrapper reset) and the eight
     `.elementor-widget-button.zp-cta .elementor-button` descendant rules that
     re-applied the button treatment to the anchor Elementor built for itself.
     `zp_cta()` now puts `.zp-cta` on the anchor, so one rule does the job.
   * the `.elementor-widget.zp-eyebrow` and
     `.zp-on-dark .elementor-widget.zp-eyebrow` specificity crutches. A
     single-class rule is enough now.
   * every rule repainting headings, text editors and icon lists away from the
     kit's `--e-global-color-primary` / `--e-global-color-accent`, and the
     `--zp-heading` custom property invented to carry them past a (0,2,0) tie.
   * the whole `.elementor-widget-accordion` block: Home's FAQ is not an
     accordion widget.
   * `[class^="zp-"] * { box-sizing:border-box }` — theme.css already sets it
     globally.

   `.zp-on-dark` survives, because it names a real ground-dependent copy role
   rather than a fight with a stylesheet.

   Keyframes, `[data-zp-reveal]` and `prefers-reduced-motion` are not here:
   they belong to the widget that animates, and move with it.

   Colours resolve to tokens.css custom properties. The permitted exception is
   the muted grey #6b6e7a, a corrected contrast value with no token behind it.
   The artboard's own eyebrow grey is --ink-500, which measures 3.9:1 on
   --ink-050 and so fails WCAG AA's 4.5:1 floor at 11px; --ink-600 passes but is
   a visibly darker grey. #6b6e7a is --ink-500 darkened just far enough, at
   4.82:1 on --ink-050 and 5.08:1 on --surface. Do not restore the artboard
   value: a test in tests/theme/test-home-render.php rejects it by literal, so
   it must not appear in this file even inside a comment. Alpha-over-ground
   whites and the two shadow tints have no token form; theme.css uses the same
   literals. */

/* --- Bands ---------------------------------------------------------------- */

.zp-section { background:var(--zp-section-bg,var(--bg)); }
/* --ground-dark is the artboard's own hero, trust and closing-CTA ground, so a
   dark band needs no `bg` of its own. zp_section_open()'s `bg` still sets
   --zp-section-bg inline and wins over this, which is how the light bands pick
   between --ink-050 and --surface. */
.zp-section--dark { --zp-section-bg:var(--ground-dark); }
.zp-section--gradient { --zp-section-bg:var(--grad-zipify); }
/* The artboard's rule between two same-coloured bands. */
.zp-section--seam { border-top:1px solid var(--ink-200); }

.zp-wrap { max-width:1180px; margin:0 auto; padding:112px 48px; }

/* --- Type ----------------------------------------------------------------- */

/* Block, not inline: every eyebrow on the artboard is a block with a bottom
   margin under it, and zp_eyebrow() emits a <span>. The margin itself belongs
   to the section, which chooses 8px, 16px or 18px depending on the band. */
.zp-eyebrow { display:block; font-size:11px; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:#6b6e7a; }
.zp-eyebrow--blue { color:var(--blue-500); }

.zp-h2 { margin:0 0 14px; font-size:44px; font-weight:900; letter-spacing:-.022em; line-height:1.06; text-wrap:pretty; color:var(--ink-900); }
.zp-h3 { margin:0 0 12px; font-size:34px; font-weight:900; letter-spacing:-.024em; line-height:1.03; color:var(--ink-900); }
.zp-lede { margin:0; font-size:18px; line-height:1.6; color:var(--ink-700); }

/* --- Copy on each ground -------------------------------------------------- */

/* Below the type block on purpose: the eyebrow rule below depends on source
   order to beat the base `.zp-eyebrow`. */
.zp-on-dark { color:var(--fg-on-dark); }
.zp-on-dark .zp-h2, .zp-on-dark .zp-h3 { color:var(--fg-on-dark); }
.zp-on-dark .zp-lede { color:var(--fg-on-dark-2); }
/* `:where()` is load-bearing — do not "simplify" it to a descendant selector.
   A bare `.zp-on-dark .zp-eyebrow` is (0,2,0) and would outrank every widget's
   own single-class eyebrow rule: `.zp-perfectmatch-quiz__eyebrow` (translucent
   white on its own dark panel), `.zp-card-rail__eyebrow` and
   `.zp-revenue-calculator__eyebrow` are all (0,1,0), a gap no source order can
   close, and each would render yellow instead of its own colour. The rule this
   replaces was `.zp-on-dark .elementor-widget.zp-eyebrow`, which needed
   `.elementor-widget` ON the element and so only ever matched a section-level
   eyebrow; `:where()` reproduces that reach without the Elementor class.
   At (0,1,0) two ties are settled by source order, both correctly: this block
   sits after the base `.zp-eyebrow`, so a section eyebrow on a dark band goes
   yellow; and every widget stylesheet declares `zp-home` as a dependency, so it
   prints after this file and each widget keeps its own colour. */
:where(.zp-on-dark) .zp-eyebrow { color:var(--zip-yellow); }

/* --- Surfaces ------------------------------------------------------------- */

.zp-card { padding:30px; border-radius:20px; border:1px solid var(--ink-200); background:var(--surface); }

/* The 42px navy chip a 20px product mark sits inside. The mark is a
   background-image the section sets, so the `background` shorthand comes
   first — it resets background-size/repeat/position, and the longhands after
   it restore them. `flex:0 0 auto` because the chip is normally a flex item in
   a row beside a heading and would otherwise shrink below 42px. */
.zp-mark { display:flex; align-items:center; justify-content:center; flex:0 0 auto; width:42px; height:42px; border-radius:12px; background:var(--blue-900); background-size:20px auto; background-repeat:no-repeat; background-position:center; }
/* PostProfit's chip holds a logotype, not a glyph, so it is wide and sits on a
   translucent white rather than the navy — it is already on a dark ground. */
.zp-mark--wide { width:132px; background-color:rgba(255,255,255,.08); background-size:104px auto; }
/* The pricing card's chip, one step down: 36px on its own dark card. */
.zp-mark--sm { width:36px; height:36px; border-radius:10px; background-color:rgba(255,255,255,.1); background-size:17px auto; }

/* --- Grids ---------------------------------------------------------------- */

.zp-grid--2 { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:40px; }
.zp-grid--3 { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:20px; }
.zp-grid--4 { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:14px; }

/* --- Buttons -------------------------------------------------------------- */

.zp-cta { display:inline-block; padding:16px 30px; border-radius:10px; background:var(--grad-ocu); color:var(--zip-white); font-size:14px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; text-decoration:none; box-shadow:inset 0 1px 0 rgba(255,255,255,.18), 0 12px 28px rgba(240,48,90,.24); transition:filter var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out); }
.zp-cta:hover, .zp-cta:focus-visible { color:var(--zip-white); filter:brightness(1.07); transform:translateY(-1px); }
/* sec07's "Meet Zipify AI" is a flat yellow button, not the OCU gradient. */
.zp-cta--yellow { background:var(--zip-yellow); color:var(--ink-900); box-shadow:none; }
.zp-cta--yellow:hover, .zp-cta--yellow:focus-visible { color:var(--ink-900); filter:brightness(1.06); }
.zp-cta--ghost { background:transparent; box-shadow:none; border:1.5px solid var(--ink-300); color:var(--ink-900); }
.zp-cta--ghost:hover, .zp-cta--ghost:focus-visible { color:var(--ink-900); border-color:var(--ink-700); filter:none; }
.zp-on-dark .zp-cta--ghost { border-color:rgba(255,255,255,.24); color:rgba(255,255,255,.9); }
.zp-on-dark .zp-cta--ghost:hover, .zp-on-dark .zp-cta--ghost:focus-visible { color:var(--zip-white); border-color:rgba(255,255,255,.5); }
/* Zipify Plus's "Book a demo": a navy-outlined button that fills on hover, not
   the grey ghost. It sits inside a white card on a light band, so it needs a
   ground of its own rather than `transparent`. */
.zp-cta--outline-navy { background:var(--surface); box-shadow:none; border:2px solid var(--blue-900); color:var(--blue-900); }
.zp-cta--outline-navy:hover, .zp-cta--outline-navy:focus-visible { background:var(--blue-900); color:var(--zip-white); filter:none; }
/* The pricing card's CTA spans its column. */
.zp-cta--block { display:block; text-align:center; }

/* --- Responsive ----------------------------------------------------------- */

/* Elementor took this from its container breakpoints; it is explicit now. */
/* 899.98px, not 899px: a fractional or zoomed viewport can land between the two
   and would otherwise match neither this query nor the desktop rules. The
   attribute selector rather than an enumeration so a grid added in Tasks 6-9
   collapses without editing this block. */
@media (max-width:899.98px) {
  .zp-wrap { padding:72px 20px; }
  [class*="zp-grid--"] { grid-template-columns:minmax(0,1fr); }
  .zp-points { gap:8px; }
  .zp-h2 { font-size:38px; }
  .zp-hero__ctas { flex-direction:column; text-align:center; }
}

/* --- Points list (zp_points()) --------------------------------------------- */

.zp-points { list-style:none; margin:0 0 32px; padding:0; display:flex; flex-direction:column; gap:14px; }
.zp-points__item { display:flex; align-items:flex-start; gap:12px; font-size:16px; line-height:1.55; }
.zp-points__check { flex:0 0 auto; margin-top:4px; color:var(--zip-yellow); }
.zp-on-dark .zp-points__item { color:rgba(255,255,255,.84); }

/* --- Section 1: hero -------------------------------------------------------- */

/* No bottom padding: the trust marquee is the same band on the artboard, and
   56px here plus the marquee's own top padding opened a gap the artboard
   does not have under the "trusted by" line. */
.zp-hero .zp-wrap { padding:144px 48px 0; }
.zp-hero__head { max-width:1000px; margin:0 auto; text-align:center; }
/* The lede's three-control Elementor width workaround becomes one rule. */
.zp-hero__lede { max-width:600px; margin-inline:auto; text-align:center; font-size:20px; }
.zp-hero__ctas { display:flex; justify-content:center; gap:12px; flex-wrap:wrap; margin-top:40px; }
.zp-hero__rail { margin-top:64px; }
@media (max-width:899.98px) {
  .zp-hero .zp-wrap { padding:104px 20px 0; }
}

/* --- Section 2: trust marquee ----------------------------------------------- */

/* Full-bleed: the artboard's marquee has no side gutter and no max-width — the
   cards run to both viewport edges, which is what makes the loop read as
   continuous. The 1180px column clipped it to a centred strip. */
.zp-trust .zp-wrap { max-width:none; padding:24px 0 40px; }
@media (max-width:899.98px) {
  .zp-trust .zp-wrap { padding:24px 0 40px; }
}

/* --- Section 3: OCU ---------------------------------------------------------- */

.zp-ocu__head { max-width:760px; margin:0 0 52px; }
.zp-ocu__eyebrow-row { display:flex; align-items:center; gap:12px; margin-bottom:18px; }
/* The one eyebrow the artboard sets a size on: 12px here, 11px everywhere else. */
.zp-ocu__eyebrow-row .zp-eyebrow { font-size:12px; }
.zp-ocu__title { font-size:54px; letter-spacing:-.024em; line-height:1.03; margin:0 0 22px; }
.zp-ocu__head .zp-lede { font-size:20px; }
.zp-ocu__stats { margin-top:36px; gap:18px; }
.zp-ocu__stats .zp-card { padding:22px 24px; border-radius:16px; }
.zp-ocu__stat-value { margin:0 0 8px; font-size:32px; font-weight:900; letter-spacing:-.022em; line-height:1; color:var(--blue-700); }
.zp-ocu__stat-label { margin:0; font-size:14px; line-height:1.5; color:var(--ink-600); }
.zp-ocu__ctas { margin-top:36px; display:flex; flex-wrap:wrap; gap:12px; }
@media (max-width:899.98px) {
  .zp-ocu__ctas { gap:20px; }
}

/* --- Section 4: PostProfit ---------------------------------------------------- */

.zp-postprofit__top { align-items:center; gap:56px; margin-bottom:96px; }
.zp-postprofit__eyebrow-row { display:flex; align-items:center; gap:12px; margin-bottom:20px; }
.zp-postprofit__title { font-size:40px; margin:0 0 18px; }
/* `.zp-lede` is margin:0 site-wide, which ran the check list straight into
   the paragraph above it. 28px is the gap the artboard sets on this lede. */
.zp-postprofit__col .zp-lede { margin-bottom:28px; }
.zp-postprofit__media { display:flex; align-items:center; justify-content:center; }
.zp-postprofit__offers { max-width:460px; width:100%; height:auto; }

/* --- Section 5: pages ---------------------------------------------------------- */

.zp-pages__head { max-width:760px; margin:0 0 52px; }
.zp-pages__eyebrow-row { display:flex; align-items:center; gap:12px; margin-bottom:18px; }
.zp-pages__title { font-size:54px; letter-spacing:-.024em; line-height:1.03; margin:0 0 22px; }
.zp-pages__head .zp-lede { font-size:20px; }
.zp-pages__cards { gap:24px; }
/* The frame around the shot carries the border and shadow, so the card itself
   is only a stack: a `.zp-card` box here would draw a second outline. */
.zp-pages__card { display:flex; flex-direction:column; gap:18px; }
.zp-pages__frame { border-radius:20px; overflow:hidden; border:1px solid var(--ink-200); background:var(--ink-050); box-shadow:0 8px 22px rgba(13,31,78,.08); transition:transform 420ms var(--ease-out), box-shadow 420ms var(--ease-out); }
.zp-pages__card:hover .zp-pages__frame { transform:translateY(-6px); box-shadow:0 22px 48px rgba(13,31,78,.16); }
.zp-pages__shot { display:block; width:100%; aspect-ratio:4/5; object-fit:cover; object-position:top; transition:transform 600ms var(--ease-out); }
.zp-pages__card:hover .zp-pages__shot { transform:scale(1.04); }
.zp-pages__cards .zp-h3, .zp-pages__card-title { margin:0 0 6px; font-size:19px; font-weight:800; letter-spacing:-.015em; }
.zp-pages__card-caption { margin:0; font-size:15px; line-height:1.55; color:var(--ink-600); }
.zp-pages__foot { margin-top:44px; display:flex; flex-wrap:wrap; align-items:center; gap:20px; }
.zp-pages__note { font-size:15px; color:var(--ink-600); }
@media (max-width:899.98px) {
  .zp-pages__cards { gap:60px; }
  .zp-pages__card-copy { padding:0 8px; }
}

/* --- Section 6: shoprank -------------------------------------------------------- */
/* Hosts the pinned ShopRank Demo, and owns the pin rather than delegating it to
   the widget: the artboard pins the whole composition, and pinning only the
   panel stuck it while the heading beside it scrolled off the top. The widget
   is rendered with `pin => 'no'` here.
   `overflow` appears once, on `__sticky` itself. That is the element that
   sticks, so it is not one of its own ancestors and the pin survives it;
   nothing else in this block sets a scroll-clipping property. */

.zp-shoprank__track { position:relative; height:200vh; }
.zp-shoprank__sticky { position:sticky; top:var(--zp-header-h,72px); height:calc(100vh - var(--zp-header-h,72px)); display:flex; flex-direction:column; justify-content:center; overflow:hidden; padding-inline:40px; margin-inline:-40px; }
.zp-shoprank__foot { margin-top:24px; }
.zp-shoprank__head { display:grid; grid-template-columns:1fr 1fr; gap:40px; align-items:center; margin:0 0 20px; }
.zp-shoprank__title { font-size:34px; letter-spacing:-.024em; line-height:1.03; margin:0 0 12px; }
.zp-shoprank__copy .zp-lede { font-size:16px; line-height:1.55; }
.zp-shoprank__eyebrow-row { display:flex; align-items:center; gap:12px; margin-bottom:18px; }
.zp-shoprank__copy { min-width:0; }
.zp-shoprank__copy .zp-h2 { margin-top:0; }
/* sec05 puts the four points beside the copy as a 2x2 of bordered cards, not
   under it as a check list. They collapse to one column with the head. */
.zp-shoprank__points { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; }
.zp-shoprank__point { padding:16px 18px; border-radius:16px; border:1px solid var(--ink-200); background:var(--surface); font-size:14px; line-height:1.45; color:var(--ink-700); }

/* The pin needs a viewport tall enough to hold the whole composition. Below
   that it unpins and the band scrolls like any other. Same thresholds as the
   PerfectMatch band, and as the widget's own rules used before the pin moved. */
@media (max-width:1023px), (max-height:820px) {
  .zp-shoprank__track { height:auto; }
  .zp-shoprank__sticky { position:static; height:auto; overflow:visible; padding-inline:0; margin-inline:0; }
}
@media (prefers-reduced-motion: reduce) {
  .zp-shoprank__track { height:auto; }
  .zp-shoprank__sticky { position:static; height:auto; overflow:visible; padding-inline:0; margin-inline:0; }
}
/* The 2x2 of points beside the copy has no room left on a phone: at 390px the
   head's two columns are 155px each and the points' are 71px, which breaks the
   card text to one word a line and spills it past the borders. Both collapse
   together, which is what the comment above `__points` already describes. */
@media (max-width:899.98px) {
  .zp-shoprank__head { grid-template-columns:1fr; gap:32px; }
  .zp-shoprank__points { grid-template-columns:1fr; }
}

/* --- Section 7: perfectmatch ------------------------------------------------------ */
/* Hosts the PerfectMatch Quiz, and owns the pin rather than delegating it to the
   widget: sec06 pins the whole composition, and pinning only the quiz would
   stick it while the copy in the column beside it scrolled away. The widget is
   rendered with `pin => 'no'` here.
   `overflow` appears once, on `__sticky` itself. That is the element that
   sticks, so it is not one of its own ancestors and the pin survives it;
   nothing else in this block sets a scroll-clipping property. */

.zp-perfectmatch__track { position:relative; height:250vh; }
.zp-perfectmatch__sticky { position:sticky; top:var(--zp-header-h,72px); height:calc(100vh - var(--zp-header-h,72px)); display:flex; flex-direction:column; justify-content:center; gap:24px; overflow:hidden; padding-inline:40px; margin-inline:-40px; }
.zp-perfectmatch__split { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:56px; align-items:center; }
.zp-perfectmatch__copy { min-width:0; }
.zp-perfectmatch__eyebrow-row { display:flex; align-items:center; gap:12px; margin-bottom:18px; }
.zp-perfectmatch__copy .zp-h2 { margin:0 0 22px; }
.zp-perfectmatch__title { font-size:52px; letter-spacing:-.024em; line-height:1.03; }
.zp-perfectmatch__copy .zp-lede { font-size:20px; }
.zp-perfectmatch__case { padding:18px; border-radius:16px; border:1px solid var(--ink-200); background:var(--surface); box-shadow:var(--sh-1); }
.zp-perfectmatch__case-title { margin:0 0 6px; font-size:18px; font-weight:800; letter-spacing:-.015em; }
.zp-perfectmatch__case-desc { margin:0; font-size:14px; line-height:1.5; color:var(--ink-600); }
.zp-perfectmatch__foot { display:flex; flex-wrap:wrap; align-items:center; gap:20px; }

/* The pin needs a viewport tall enough to hold the whole composition. Below
   that it unpins and the band scrolls like any other. */
@media (max-width:1023px), (max-height:820px) {
  .zp-perfectmatch__track { height:auto; }
  .zp-perfectmatch__sticky { position:static; height:auto; overflow:visible; padding-inline:0; margin-inline:0; }
}
@media (prefers-reduced-motion: reduce) {
  .zp-perfectmatch__track { height:auto; }
  .zp-perfectmatch__sticky { position:static; height:auto; overflow:visible; padding-inline:0; margin-inline:0; }
}
/* Unpinning alone is not enough: the split stayed two columns, so on a phone
   the quiz got 147px and clipped its own "Add to cart" and profile column
   against `__sticky`'s overflow. The copy and the quiz stack instead. */
@media (max-width:899.98px) {
  .zp-perfectmatch__split { grid-template-columns:1fr; gap:40px; }
}

/* --- Section 8: ai --------------------------------------------------------------- */
/* Centred copy over the AI Constellation. Nothing is pinned in this band.
   The constellation's own rules live in assets/css/widgets/ai-constellation.css. */

.zp-ai__head { max-width:760px; margin:0 auto 12px; text-align:center; }
.zp-ai__title { font-size:46px; letter-spacing:-.024em; line-height:1.05; margin:0 0 18px; }
.zp-ai__head .zp-lede { max-width:640px; margin:0 auto 30px; }
/* The lede's own 30px bottom margin is the whole gap on the artboard. */
.zp-ai__foot { margin-top:0; text-align:center; }

/* --- Section 9: plus --------------------------------------------------------------- */

.zp-plus__ring { position:relative; padding:3px; border-radius:30px; background:var(--grad-plus); box-shadow:0 26px 60px rgba(253,62,93,.16), 0 6px 16px rgba(13,31,78,.08); }
/* The tier pill straddles the ring's top edge, so it is a child of the ring
   and not of the clipped card inside it. */
.zp-plus__badge { position:absolute; top:-14px; left:44px; z-index:2; display:inline-flex; align-items:center; gap:8px; padding:7px 16px; border-radius:var(--r-pill); background:var(--grad-plus); color:var(--ink-900); font-size:11px; font-weight:900; letter-spacing:.12em; text-transform:uppercase; box-shadow:0 6px 16px rgba(253,62,93,.28); }
.zp-plus__card { position:relative; border-radius:27px; overflow:hidden; background:var(--surface); color:var(--ink-900); }
/* Clipped by the card's own overflow; the two panels below sit above it. */
.zp-plus__wash { position:absolute; top:-190px; right:-150px; width:560px; height:560px; pointer-events:none; border-radius:999px; background:radial-gradient(circle,rgba(253,62,93,.09) 0%,rgba(253,62,93,0) 68%); }
.zp-plus__head, .zp-plus__body { position:relative; }
.zp-plus__title { font-size:40px; letter-spacing:-.024em; margin:0 0 14px; }
.zp-plus__head { padding:54px 48px 40px; display:grid; grid-template-columns:minmax(0,1.25fr) auto; gap:44px; align-items:end; border-bottom:1px solid var(--ink-200); }
.zp-plus__eyebrow-row { display:flex; align-items:center; gap:12px; margin-bottom:20px; }
.zp-plus__head-copy .zp-lede { max-width:620px; }
.zp-plus__head-ctas { display:flex; flex-direction:column; gap:12px; justify-self:end; }
.zp-plus__body { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
.zp-plus__quote { padding:40px 44px; display:flex; flex-direction:column; gap:20px; border-right:1px solid var(--ink-200); }
.zp-plus__quote-logo { height:38px; width:auto; align-self:flex-start; }
.zp-plus__quote-text { margin:0; font-size:20px; line-height:1.5; letter-spacing:-.01em; color:var(--ink-900); }
.zp-plus__quote-person { display:flex; align-items:center; gap:14px; margin-top:auto; }
.zp-plus__avatar { width:48px; height:48px; border-radius:999px; object-fit:cover; flex:0 0 auto; }
.zp-plus__quote-name { font-size:15px; font-weight:800; letter-spacing:-.01em; color:var(--ink-900); }
.zp-plus__quote-role { margin:0; font-size:14px; color:var(--ink-600); }
.zp-plus__gap { padding:40px 44px; display:flex; flex-direction:column; gap:22px; background:var(--ink-050); }
.zp-plus__gap-figures { display:flex; align-items:center; gap:22px; }
.zp-plus__gap-figure { min-width:0; }
.zp-plus__gap-label { font-size:12px; font-weight:900; letter-spacing:.06em; text-transform:uppercase; margin-bottom:8px; color:#6b6e7a; }
.zp-plus__gap-label--after { color:var(--blue-900); }
.zp-plus__gap-value { font-size:34px; font-weight:900; letter-spacing:-.025em; line-height:1; white-space:nowrap; }
/* #82858f is the artboard's muted "before" figure and clears AA's 3:1 large-text
   floor at 34px (3.50:1 on --ink-050). The unit suffix inside it is 17px, which is
   NOT large text, so it takes the darker #6b6e7a — the same split the pre-port
   stylesheet made with `.zp-compare--before .zp-compare-unit`, and which this port
   dropped. Lighthouse caught it: the label and the unit both failed at 3.50:1. */
.zp-plus__gap-value--before { color:#82858f; }
.zp-plus__gap-value--before .zp-plus__gap-unit { color:#6b6e7a; }
.zp-plus__gap-value--after { color:var(--blue-900); }
.zp-plus__gap-unit { font-size:17px; font-weight:800; }
.zp-plus__gap-arrow { padding-inline:32px; font-size:24px; font-weight:900; color:var(--pink-500); }
.zp-plus__gap-total { margin-top:auto; padding-top:24px; border-top:1px solid var(--ink-200); }
.zp-plus__gap-total-value { font-size:54px; font-weight:900; letter-spacing:-.03em; line-height:1; background:var(--grad-ocu); -webkit-background-clip:text; background-clip:text; color:transparent; }
.zp-plus__gap-total-label { font-size:15px; line-height:1.5; color:var(--ink-700); margin-top:10px; }
@media (max-width:899.98px) {
  .zp-plus__head, .zp-plus__quote, .zp-plus__gap { padding-inline:32px; }
  .zp-plus__head { grid-template-columns:1fr; align-items:start; }
  .zp-plus__head-ctas { justify-self:start; flex-direction:row; flex-wrap:wrap; }
  .zp-plus__body { grid-template-columns:1fr; }
  .zp-plus__quote { border-right:none; border-bottom:1px solid var(--ink-200); }
  .zp-plus__gap-figures { gap:4px; justify-content:space-between; }
  .zp-plus__gap-arrow { padding-inline:0; }
  .zp-plus__gap-value { font-size:28px; letter-spacing:0; }
  .zp-plus__gap-total-value { font-size:42px; }
}

/* --- Section 12: quotes -------------------------------------------------------------- */
/* Card Rail supplies the card and head layout (assets/css/widgets/card-rail.css).
   What this band owns is the bleed: the artboard keeps the heading and arrows
   inside the 1180px column but lets the rail itself run to the viewport edge,
   so the next card is always half-visible. The wrap therefore gives up its
   max-width and side padding, and hands both to the two children.
   `.zp-card-rail--rail` is in the track selector because the widget stylesheet
   prints after this file and its own `padding-bottom` is (0,2,0). */

.zp-quotes .zp-wrap { max-width:none; padding-left:0; padding-right:0; }
.zp-quotes .zp-card-rail__head { max-width:1180px; margin:0 auto 40px; padding:0 48px; }
/* One line. The widget's 620px measure broke "Let our customers speak for
   us." across two, and the head is a row with the arrows, so the width to
   give it is the column minus those. Released below 900px, where the
   clamp's 30px floor no longer fits the viewport. */
.zp-quotes .zp-card-rail__heading { max-width:none; white-space:nowrap; }
/* `scroll-padding` moves the snapport in by the same gutter. Without it the
   widget's `scroll-snap-type:x mandatory` immediately snaps the first card's
   start edge to the scrollport edge, which scrolls the 48px gutter away and
   leaves the first card cut off against the viewport. */
.zp-quotes .zp-card-rail--rail .zp-card-rail__track { padding:0 48px; scroll-padding-left:48px; }

/* --- Section 10: founder ------------------------------------------------------------- */

.zp-founder__grid { display:grid; grid-template-columns:1.1fr .9fr; gap:56px; align-items:center; }
.zp-founder__copy .zp-h2 { margin:0 0 20px; }
.zp-founder__copy .zp-lede + .zp-lede { margin-top:18px; }
.zp-founder__ctas { display:flex; flex-wrap:wrap; gap:12px; margin-top:28px; }
.zp-founder__media { border-radius:24px; overflow:hidden; box-shadow:0 24px 60px rgba(13,31,78,.18); }
.zp-founder__portrait { display:block; width:100%; aspect-ratio:4/3; object-fit:cover; object-position:center; }
@media (max-width:899.98px) {
  .zp-founder__grid { grid-template-columns:1fr; }
}

/* --- Section 11: academy -------------------------------------------------------------- */

/* Copy left, "Browse the Academy" right, baselines aligned — the artboard's
   own head. The button used to sit under the card grid. */
.zp-academy__head { display:flex; align-items:flex-end; justify-content:space-between; gap:32px; margin:0 0 40px; }
.zp-academy__head-copy { max-width:620px; }
.zp-academy__head .zp-h2 { margin:0 0 16px; }
.zp-academy__head .zp-cta { flex:0 0 auto; white-space:nowrap; }

/* --- Section 13: pricing -------------------------------------------------------------- */

.zp-pricing__head { max-width:700px; margin:0 0 44px; }
.zp-pricing__offer-head { display:flex; align-items:center; gap:11px; margin-bottom:20px; }
.zp-pricing__row { display:grid; grid-template-columns:1.15fr .85fr; gap:18px; align-items:stretch; }
.zp-pricing__offer { position:relative; padding:34px 32px; border-radius:22px; background:var(--grad-zipify); box-shadow:inset 0 1px 0 rgba(255,255,255,.17), 0 24px 60px rgba(13,31,78,.24); }
.zp-pricing__price { display:flex; align-items:baseline; gap:10px; margin:0 0 8px; }
.zp-pricing__price-value { font-size:52px; font-weight:900; letter-spacing:-.03em; line-height:1; color:var(--zip-white); }
.zp-pricing__price-suffix { font-size:16px; font-weight:600; color:rgba(255,255,255,.6); }
.zp-pricing__offer-text { margin:0 0 26px; font-size:16px; line-height:1.55; color:rgba(255,255,255,.7); }
/* #f8f9fb, not the white --surface `.zp-card` gives it: this band is white now,
   so a white card on it would have only its border to stand on. */
.zp-pricing__reassurance { display:flex; flex-direction:column; justify-content:space-between; padding:34px 32px; gap:20px; border-radius:22px; background:var(--ink-050); }
.zp-pricing__reassurance .zp-points { margin:0; }

/* The eight-tier "Pay As You Grow" ladder. Plain spans, brightened left to
   right by opacity rather than eight separate colours — the design has no
   named stop between --zip-yellow at full strength and the translucent white
   the bar starts from, so opacity is the one-token way to interpolate. */
.zp-ladder { display:flex; gap:4px; margin:0 0 12px; }
.zp-ladder span { flex:1 1 0; height:7px; border-radius:var(--r-pill); background:var(--zip-yellow); }
.zp-ladder span:nth-child(1) { opacity:.32; }
.zp-ladder span:nth-child(2) { opacity:.41; }
.zp-ladder span:nth-child(3) { opacity:.50; }
.zp-ladder span:nth-child(4) { opacity:.59; }
.zp-ladder span:nth-child(5) { opacity:.68; }
.zp-ladder span:nth-child(6) { opacity:.77; }
.zp-ladder span:nth-child(7) { opacity:.86; }
.zp-ladder span:nth-child(8) { opacity:.95; }

/* Corrected contrast value: rgba(255,255,255,.6), not the artboard's .45. */
.zp-scale { display:flex; justify-content:space-between; font-size:12px; color:rgba(255,255,255,.6); }

@media (max-width:899.98px) {
  .zp-pricing__row { grid-template-columns:1fr; }
}

/* --- Section 15: faq --------------------------------------------------------------- */

.zp-faq-section__wrap { max-width:860px; }
.zp-faq-section__title { font-size:40px; }
.zp-faq-section__wrap .zp-h2 { margin:0 0 34px; }

.zp-faq { display:flex; flex-direction:column; }
.zp-faq__item { padding:16px 0; border-top:1px solid var(--ink-200); }
.zp-faq__item:last-child { border-bottom:1px solid var(--ink-200); }
.zp-faq__q { display:block; margin:0; padding:12px 0; font-size:19px; font-weight:800; letter-spacing:-.01em; color:var(--ink-900); cursor:pointer; list-style:none; transition:color var(--dur-fast) var(--ease-out); }
.zp-faq__q:hover { color:var(--blue-500); }
/* `list-style:none` alone leaves the disclosure triangle in Safari. */
.zp-faq__q::-webkit-details-marker { display:none; }
.zp-faq__q::marker { content:""; }
.zp-faq__q:focus-visible { outline:none; border-radius:4px; box-shadow:var(--focus-ring); }
.zp-faq__a { margin:0; padding-bottom:12px; font-size:16px; line-height:1.6; color:var(--ink-600); }

/* --- Section 14: closing cta -------------------------------------------------------------- */

.zp-closing-cta__wrap { max-width:900px; margin:0 auto; text-align:center; }
.zp-closing-cta__wrap .zp-h2 { margin:0 auto 20px; }
.zp-closing-cta__title { font-size:56px; letter-spacing:-.025em; line-height:1.04; }
.zp-closing-cta__lede { max-width:560px; margin:0 auto 34px; font-size:19px; }
.zp-closing-cta__ctas { display:flex; justify-content:center; flex-wrap:wrap; gap:12px; }
/* sec13 closes the band with the lockup at 26px and .8 opacity. The SVG's own
   width is 999px and zp_img() forces `full` for an SVG, so the height here is
   what sizes it. */
.zp-closing-cta__lockup { display:block; height:26px; width:auto; margin:34px auto 0; opacity:.8; }

/* --- Responsive: per-band paddings ------------------------------------------ */
/* The global `.zp-wrap` mobile rule is (0,1,0) and every per-band padding above
   is (0,2,0), so each band that sets its own has to give it back here. Kept in
   one block rather than a mobile query per section: the value is the same for
   all of them, and a split would go stale the next time a band is added. */
@media (max-width:899.98px) {
  .zp-postprofit__top { margin-bottom:56px; }

  /* The rail keeps its bleed; only the gutter shrinks. */
  .zp-quotes .zp-wrap { padding:72px 0 0; }
  .zp-quotes .zp-card-rail__head { padding:0 20px; }
  .zp-quotes .zp-card-rail__heading { white-space:normal; }
  .zp-quotes .zp-card-rail--rail .zp-card-rail__track { padding:0 20px 72px; scroll-padding-left:20px; }

  /* Copy over button once the row has no width to split. */
  .zp-academy__head { flex-direction:column; align-items:flex-start; }

  .zp-ai__head { margin-bottom:24px; }

  .zp-pricing__offer-head .zp-eyebrow { text-wrap:balance; }
  .zp-pricing__price-value { font-size:48px; }
  .zp-pricing__reassurance { gap:28px; }
  .zp-pricing__reassurance .zp-eyebrow { margin-bottom:16px; }
}

/* The artboard's display sizes are set for a 1440px column. Below that they
   are clamped so a 54px heading does not overrun a 380px phone. */
@media (max-width:1023.98px) {
  .zp-ocu__title,
  .zp-pages__title { font-size:clamp(32px,5.2vw,54px); }
  .zp-perfectmatch__title { font-size:clamp(32px,5vw,52px); }
  .zp-closing-cta__title { font-size:clamp(34px,5.4vw,56px); }
  .zp-ai__title { font-size:clamp(30px,4.6vw,46px); }
  .zp-plus__title,
  .zp-postprofit__title,
  .zp-faq-section__title { font-size:clamp(28px,4vw,40px); text-wrap:pretty; }
}
