/* ============================================================
   Shared marketing-site primitives.
   Lifted from the design handoff's per-page <helmet> blocks so
   every page shares one definition. Token source of truth stays
   colors_and_type.css.
   ============================================================ */

/* The `hidden` attribute must beat an element's own inline `display`.
   Without !important a `<div hidden style="display:flex">` stays visible —
   the UA rule `[hidden]{display:none}` loses to any inline declaration. */
[hidden] {
    display: none !important;
}

/* Background embellishment — always 10% opacity, never above content. */
.emb {
    position: absolute;
    pointer-events: none;
    opacity: .1;
}

/*
   "Never above content" is only true while the layout is wide. Stacked on a
   phone, a flourish positioned for a column beside the copy lands on top of
   it instead — and because it is a later sibling it paints over the text.
   Two of the homepage's four did exactly that at 375px, one across both hero
   buttons. They are decoration; on a phone they go.
*/
@media (max-width: 760px) {
    .emb { display: none !important; }
}

/* Hand-drawn lime marker bar behind an emphasized phrase.
   The negative inline margin cancels the horizontal padding so the
   bar does not shift surrounding text. line-height:1 keeps it tight —
   it should barely protrude above the glyphs. */
.hl {
    display: inline-block;
    line-height: 1;
    padding: .02em .22em .04em;
    margin: 0 -.22em;
    background-image: url('/images/marketing/accents/highlight-bar.svg');
    background-size: 100% 100%;
    background-repeat: no-repeat;
    background-position: center;
    color: var(--cs-retention-navy);
}

/* Visually hidden, still read by screen readers. For labels on inputs that
   the design shows with only an icon. */
.cs-sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Same-page CTAs (handoff §3 "smooth-scroll to this page's section"). The
   offset clears the fixed header so the section heading is not hidden under
   it; reduced-motion users get an instant jump via the block further down. */
html {
    scroll-behavior: smooth;
}

[id] {
    scroll-margin-top: 130px;
}

/* Section shell — the standard content column. */
.cs-section {
    max-width: 1240px;
    margin: 0 auto;
    padding: 0 32px;
}

/* Standard section H2. White only on navy surfaces. */
.cs-h2 {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: clamp(30px, 3.6vw, 46px);
    line-height: 1.12;
    color: var(--cs-retention-navy);
    margin: 0;
}

.on-navy .cs-h2,
.cs-h2--on-dark {
    color: #fff;
}

@media (prefers-reduced-motion: reduce) {
    .emb {
        animation: none !important;
    }
}

/* ============================================================
   ANIMATION KEYFRAMES
   Per the animation spec. Loops are CSS-only; steps(1) is used
   wherever a hard cut is intended rather than a fade.
   ============================================================ */

/* Blinking caret in input mocks — must cut, not fade. */
@keyframes cs-caret { 0%, 49% { opacity: 1 } 50%, 100% { opacity: 0 } }

/* Live-status dots. The only pulsing element on the site. */
@keyframes cs-pulse { 0%, 100% { opacity: .35 } 50% { opacity: 1 } }

/* Retain hero on-site nudge: rises in, holds, drifts out. */
@keyframes cs-nudge {
    0%        { transform: translateY(6px);  opacity: 0 }
    12%, 88%  { transform: translateY(0);    opacity: 1 }
    100%      { transform: translateY(-6px); opacity: 0 }
}

/* Retain browser-tab alert mock — one 7s clock, hard cuts. */
@keyframes cs-tab-idle  { 0%, 40% { opacity: 1 } 42%, 74% { opacity: 0 } 76%, 100% { opacity: 1 } }
@keyframes cs-tab-alert { 0%, 40% { opacity: 0 } 42%, 74% { opacity: 1 } 76%, 100% { opacity: 0 } }
@keyframes cs-tab-me    { 0%, 32% { background: #fff } 34%, 72% { background: rgba(35,33,33,.05) } 74%, 100% { background: #fff } }
@keyframes cs-tab-inbox { 0%, 32% { background: rgba(35,33,33,.05) } 34%, 72% { background: #fff } 74%, 100% { background: rgba(35,33,33,.05) } }
@keyframes cs-cursor    { 0%, 24% { left: 52% } 34%, 62% { left: 13% } 72%, 100% { left: 52% } }
@keyframes cs-ring      { 0% { transform: scale(.5); opacity: .55 } 70% { opacity: 0 } 100% { transform: scale(1.9); opacity: 0 } }

/* Calculator results panel, once per mount. */
@keyframes cs-rise { from { opacity: 0; transform: translateY(14px) } to { opacity: 1; transform: none } }

/* Optimize score dials, once on reveal. */
@keyframes cs-dash { from { stroke-dashoffset: var(--from) } to { stroke-dashoffset: var(--to) } }

/* Homepage / vertical-page logo marquees. */
@keyframes brand-scroll { from { transform: translateX(0) } to { transform: translateX(-50%) } }

a { color: var(--link); }
a:hover { color: var(--cs-booking-breeze); }

@media (max-width: 1180px) {
    .hero-sms { display: none !important; }
}

/* Reduced motion: kill loops, zero out transitions. Selection states still
   change — instantly. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }
    .brand-track { animation: none !important; }
    html { scroll-behavior: auto; }
}

/* Conditional-content rule buttons (Recover personalization). */
.cs-rule-btn:hover { border-color: rgba(0,168,232,.5) !important; }

/* Reveal — the unmask scan sweep across an anonymous row. */
@keyframes cs-scan { 0% { transform: translateX(-110%) } 100% { transform: translateX(210%) } }

/* ============================================================
   SHARED RESPONSIVE GRID CLASSES
   Started life as the Solutions pages' <helmet> block (identical
   in Ecommerce / Hospitality / Ticketing) and is now the one place
   every page collapses a multi-column grid. Breakpoint is 1080px
   here, not the 960px used by the site chrome.

   Every track is minmax(0, 1fr) rather than a bare 1fr: a bare fr
   is minmax(auto, 1fr), so the track never shrinks below its
   content and the grid overflows instead of collapsing.
   ============================================================ */
@media (max-width: 1080px) {
    .two-col { grid-template-columns: minmax(0, 1fr) !important; }
    .hero-grid { grid-template-columns: minmax(0, 1fr) !important; }
    .plate { min-height: 0 !important; padding: 24px !important; }
    .obj {
        position: relative !important;
        left: 0 !important; right: 0 !important; top: 0 !important;
        margin: 0 !important; width: 100% !important;
    }
    .shell { grid-template-columns: minmax(0, 1fr) !important; }
    .side { display: none !important; }
    .hide-sm { display: none !important; }
    .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    .grid-3 { grid-template-columns: minmax(0, 1fr) !important; }
    .first { order: -1; }
}

/* ============================================================
   Calculator "email me" panels — the ROI calculators' results
   panel and the abandonment-rate calculator's. On a phone the
   send button wraps under the email field; without this it sits
   there at its natural width, pinned left, looking stranded.
   ============================================================ */
@media (max-width: 560px) {
    [data-email-send],
    [data-arc-email-send] { flex: 1 1 100%; }
}

/* ============================================================
   Mobile layout utilities.

   The design prototypes set most section layouts as inline grids
   with no phone rules at all, so on a phone a two- or three-column
   section kept its columns and squeezed its copy to one or two
   words a line. These classes are opt-in and applied only to the
   containers that break: a blanket rule over every inline grid was
   tried and rejected, because it also stacks the data tables and
   stat rows inside the product illustrations, which are meant to
   stay tabular.

   cs-m-stack  one column.
   cs-m-2up    two columns, then one on a narrow phone.
   cs-m-trail  icon | text | trailing link or figure: the trailing
               column drops under the text instead of taking a
               third of the width.
   cs-m-scroll the block keeps its width and scrolls sideways
               inside its own container, for things that cannot
               reflow — a timeline, a code line, a row of steps.
   ============================================================ */
/*
   The class is doubled on purpose. Page stylesheets load after this
   file and several set their own !important column counts on the
   same elements (Retain's .four-col is one); at equal specificity the
   later rule wins, so these have to outrank a single class.
*/
@media (max-width: 760px) {
    .cs-m-stack.cs-m-stack { grid-template-columns: minmax(0, 1fr) !important; }
    .cs-m-stack.cs-m-stack > * { grid-column: auto !important; }
    .cs-m-trail.cs-m-trail { grid-template-columns: auto minmax(0, 1fr) !important; }
    .cs-m-trail.cs-m-trail > :last-child { grid-column: 2 !important; justify-self: start !important; }
    .cs-m-flexstack.cs-m-flexstack { flex-direction: column !important; align-items: stretch !important; }
    .cs-m-scroll.cs-m-scroll { overflow-x: auto !important; -webkit-overflow-scrolling: touch; scrollbar-width: thin; }
}
/* Four across is already too tight on a tablet held upright, so two-up starts wider. */
@media (max-width: 1024px) {
    .cs-m-2up.cs-m-2up { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
}
@media (max-width: 520px) {
    .cs-m-2up.cs-m-2up { grid-template-columns: minmax(0, 1fr) !important; }
}

/* ============================================================
   Mobile: components that cannot simply stack.

   cs-m-table   a table or timeline that has to stay tabular. Below
                760px it scrolls sideways inside its own rounded
                frame; each row keeps a minimum width, set per table
                with --cs-m-min.
   cs-m-vtable  the identified-visitors rows on Reveal: four columns
                become two — contact over what they left, value on the
                right — and location, the least useful column, goes.
   ============================================================ */
@media (max-width: 900px) {
    .cs-m-vtable.cs-m-vtable { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: 8px !important; }
    .cs-m-vtable.cs-m-vtable > :nth-child(2) { display: none !important; }
    .cs-m-vtable.cs-m-vtable > :nth-child(3) { grid-column: 1 !important; grid-row: 2 !important; }
    .cs-m-vtable.cs-m-vtable > :nth-child(4) { grid-column: 2 !important; grid-row: 1 / span 2 !important; align-self: center; }
    .cs-m-vtable-head.cs-m-vtable-head > :nth-child(3) { display: none !important; }

    /*
       The same idea for the three-column identified-shopper rows on the
       solutions pages: who over what they left, cart value on the right.
       At 375px the three columns squeezed "Cart · 2 items abandoned at
       shipping" to one word a line and clipped the value off the edge.
    */
    .cs-m-vrow.cs-m-vrow { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: 6px !important; column-gap: 12px !important; }
    .cs-m-vrow.cs-m-vrow > :nth-child(2) { grid-column: 1 !important; grid-row: 2 !important; }
    .cs-m-vrow.cs-m-vrow > :nth-child(3) { grid-column: 2 !important; grid-row: 1 / span 2 !important; align-self: center; text-align: right; }
    .cs-m-vrow-head.cs-m-vrow-head > :nth-child(2) { display: none !important; }
}
@media (max-width: 760px) {
    .cs-m-table.cs-m-table { overflow-x: auto !important; -webkit-overflow-scrolling: touch; }
    .cs-m-table.cs-m-table > * { min-width: var(--cs-m-min, 640px); }
    .cs-m-table [style*="grid-template-columns:280px"] { grid-template-columns: 170px minmax(0, 1fr) !important; }

    .cs-m-vtable.cs-m-vtable { padding-left: 18px !important; padding-right: 18px !important; }

    /*
       Retain's stage rows used to scroll sideways; they stack now, so the
       pips go back to full size and the row reads as five stages down the
       card rather than two and a hint of a third.
    */
}

/* ============================================================
   Scroll-driven sections on Recover and Reveal.

   Each section pairs a block of copy with one card that animates
   between versions as you scroll past. The copy blocks carry a
   70-74vh min-height to give that effect room, and the card is
   pinned beside them.

   Neither works on a phone: the pinned card is stacked below all
   the copy, so nothing lines up, and the min-heights leave about
   300px of blank space under every section. Each section shows its
   own still of the card instead (built in the page's own script
   from a clone of it), the min-heights go, and the animated card
   is hidden.
   ============================================================ */
@media (max-width: 760px) {
    [data-stage],
    [data-hiw-step] { min-height: 0 !important; display: block !important; }
    [data-pers-visual],
    [data-hiw-visual] { display: none !important; }
    /*
       No display here: each still keeps whatever its source card was. Forcing
       flex turned Recover's card — a plain block — into a row, so its navy
       header ran down the side of the email instead of across the top.
    */
    [data-pers-still],
    [data-hiw-still] { margin: 24px 0 0 !important; }

    /* Both layers are read on a phone, so neither is dimmed. */
    [data-pers-layer] { opacity: 1 !important; }

    /*
       The min-heights were the only thing separating one section from the
       next. With them gone the following step's number sat right under the
       card, so the sections carry their own gap now.
    */
    [data-stage]:not(:last-child),
    [data-hiw-step]:not(:last-child) { padding-bottom: 56px !important; }
}

/* ============================================================
   Reveal's "CartStack vs everyone else" table.

   Three columns at a 560px floor, so on a phone it scrolled
   sideways and both answers sat off the edge — a comparison you
   cannot compare. It stacks instead: the feature, then each
   side's answer under its own column name, taken from data-col so
   the labels stay in the template with the rest of the copy.
   ============================================================ */
@media (max-width: 760px) {
    .cs-m-vs-head.cs-m-vs-head { display: none !important; }
    .cs-m-vs-row.cs-m-vs-row { grid-template-columns: minmax(0, 1fr) !important; padding: 4px 0 12px; }
    .cs-m-vs-row.cs-m-vs-row > * { border-left: 0 !important; padding: 6px 20px !important; }
    .cs-m-vs-row.cs-m-vs-row > :first-child { padding-top: 16px !important; }
    .cs-m-vs-row.cs-m-vs-row > [data-col] { display: block !important; }
    .cs-m-vs-row.cs-m-vs-row > [data-col]::before {
        content: attr(data-col);
        display: block;
        margin-bottom: 4px;
        font-size: 9.5px;
        font-weight: 700;
        letter-spacing: .09em;
        text-transform: uppercase;
        color: var(--fg-muted);
    }
    /* The checkmark rides with the text once the cell is no longer a flex row. */
    .cs-m-vs-row.cs-m-vs-row > [data-col] img { display: inline-block; vertical-align: -2px; margin-right: 6px; }
}

/* ============================================================
   "Where the revenue came from" on Recover.

   Label, bar, figure on one line. The label holds 120px and the
   figure sizes to its own text, so the bar took what was left and
   at 375px the figure was pushed off the card — "$133,692.2" with
   the last digit over the edge. On a phone the figure sits beside
   the label and the bar spans the full width underneath, which is
   also where a bar is easiest to compare.
   ============================================================ */
@media (max-width: 760px) {
    .cs-m-revrow.cs-m-revrow { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: 10px !important; column-gap: 12px !important; }
    .cs-m-revrow.cs-m-revrow > :nth-child(1) { grid-column: 1 !important; grid-row: 1 !important; }
    .cs-m-revrow.cs-m-revrow > :nth-child(3) { grid-column: 2 !important; grid-row: 1 !important; text-align: right; }
    .cs-m-revrow.cs-m-revrow > :nth-child(2) { grid-column: 1 / span 2 !important; grid-row: 2 !important; }
}

/* ============================================================
   The send-my-cart field in the exit-intent mock.

   A faked input beside its button. The field shrinks but the text
   inside it does not, so "dana@northmail.com" ran out through the
   border on a phone. It clips like a real input now, and at phone
   width the field takes its own line so it rarely has to.
   ============================================================ */
@media (max-width: 760px) {
    .cs-m-emailrow.cs-m-emailrow { flex-wrap: wrap !important; row-gap: 8px !important; }
    .cs-m-emailrow.cs-m-emailrow > :first-child { flex: 1 1 100% !important; }
}

/* ============================================================
   The email example crop on the templates page.

   A fixed 560px window over an image that is only as tall as its
   own width allows. In a desktop column the image fills it; in a
   phone column it is about 380px tall and the rest of the box was
   empty white under every example. On a phone the window hugs the
   image, which also means the whole email is visible.
   ============================================================ */
@media (max-width: 760px) {
    .cs-m-mailbox.cs-m-mailbox { height: auto !important; }
}

/* ============================================================
   Recover's sequence trigger row.

   Four items on one flex line: the dot, "Trigger · 0 min", the
   title, and "Starts the sequence". The first, second and fourth
   are nowrap, so at 375px the title was left with about 90px and
   broke to one word a line, running straight through the label
   beside it. The title takes its own line on a phone and the
   trailing label goes — the dashed pill already says it is the
   start.
   ============================================================ */
@media (max-width: 760px) {
    .cs-m-trigger.cs-m-trigger { flex-wrap: wrap !important; row-gap: 8px !important; border-radius: 18px !important; padding: 14px 18px !important; }
    .cs-m-trigger.cs-m-trigger > :nth-child(3) { flex: 1 1 100% !important; }
    .cs-m-trigger.cs-m-trigger > :nth-child(4) { display: none !important; }
}

/* ============================================================
   Sticky side columns, stacked.

   Roughly twenty blocks across the site pin a narrow column while
   the long column beside it scrolls — a pricing rail, a blog
   sidebar, the "rest of the platform" heading on each product
   page. Stacked on a phone the pinned block is full width and the
   content scrolls underneath it, so the heading sits on top of the
   rows it introduces.

   Scoped to main: the header's own fixed drawer and overlay are
   outside it and keep working.
   ============================================================ */
@media (max-width: 760px) {
    main [style*="position:sticky"] { position: static !important; }
}

/* ============================================================
   The abandonment funnel on the three solutions pages.

   The bars are sized in percentages tuned for a desktop column
   (58% down to 20%). At 375px those percentages fall below the
   width of their own label, so every bar bottoms out at its text
   and the funnel stops narrowing — the last bar, "Order 12", came
   out wider than "Checkout 34" above it. The label and the figure
   also met in the middle with nothing between them.

   On a phone the funnel starts at full width and steps down in
   even increments, and the type comes down with it, so the shape
   reads as a funnel the whole way to the bottom.
   ============================================================ */
@media (max-width: 760px) {
    .cs-m-funnel .cs-m-funnel-bar { min-width: 0 !important; gap: 12px; padding: 0 16px !important; height: 62px !important; }
    .cs-m-funnel > :nth-child(1) .cs-m-funnel-bar { flex-basis: 100% !important; }
    .cs-m-funnel > :nth-child(2) .cs-m-funnel-bar { flex-basis: 88% !important; }
    .cs-m-funnel > :nth-child(3) .cs-m-funnel-bar { flex-basis: 77% !important; }
    .cs-m-funnel > :nth-child(4) .cs-m-funnel-bar { flex-basis: 67% !important; }
    .cs-m-funnel > :nth-child(5) .cs-m-funnel-bar { flex-basis: 58% !important; }
    .cs-m-funnel > :nth-child(6) .cs-m-funnel-bar { flex-basis: 50% !important; }
    .cs-m-funnel .cs-m-funnel-bar > :first-child { font-size: 14px !important; }
    .cs-m-funnel .cs-m-funnel-bar > :last-child { font-size: 20px !important; }

    /* The drop-off note moves under its bar rather than fighting it for width. */
    .cs-m-funnel > * { flex-wrap: wrap; row-gap: 4px; }
    .cs-m-funnel > * > :last-child { padding-left: 16px; }
}

/* ============================================================
   Touch-sized hit area for small dot controls (the homepage case
   study carousel). The dot stays 8px; the target around it is
   about 32px, which is what a thumb needs.
   ============================================================ */
.cs-dot-hit { position: relative; }
.cs-dot-hit::before { content: ""; position: absolute; inset: -12px -6px; }

/* ============================================================
   Form fields at 16px on touch screens.

   iOS Safari zooms the whole page in when a field under 16px takes
   focus, and does not zoom back out when it loses it. Every form on
   this site set 13–15.5px, so tapping into any of them left the
   visitor on a zoomed, sideways-scrolling page. Scoped to coarse
   pointers so the desktop type scale is untouched.
   ============================================================ */
@media (pointer: coarse) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]),
    select,
    textarea { font-size: 16px !important; }
}

/* ============================================================
   Small-phone gutter.

   Sections carry padding:0 32px from the prototypes, which leaves
   296px of content on a 360px phone — and that is what pushed the
   last of the narrow columns, the CTA button rows and the Calendly
   embed (320px minimum) over the edge. 20px is the same gutter the
   header and footer already use down here.
   ============================================================ */
@media (max-width: 520px) {
    main [style*="padding:0 32px"] { padding-left: 20px !important; padding-right: 20px !important; }
}

/* Reveal's hero mock: three columns become contact over detail, value right. */
@media (max-width: 900px) {
    .cs-m-mock3.cs-m-mock3 { grid-template-columns: minmax(0, 1fr) auto !important; row-gap: 6px !important; }
    .cs-m-mock3.cs-m-mock3 > :nth-child(2) { grid-column: 1 !important; grid-row: 2 !important; }
    .cs-m-mock3.cs-m-mock3 > :nth-child(3) { grid-column: 2 !important; grid-row: 1 / span 2 !important; align-self: center; }
}
