/* ═══════════════════════════════════════════════════════════════════
   Marketing shared styles — fixed brand hue + editorial display face

   SINGLE SOURCE OF TRUTH for the marketing shell (nav, footer, layout,
   shared utilities). Consumed by:
     * React  — frontend/src/shared/components/marketing/MarketingLayout.tsx
                (and frontend-marketing/app/root.tsx via ?url)
     * Jinja  — app/templates/marketing/_layout.html links the served copy
                at /static/tokens/marketing.css (see app/configuration/app.py:
                /static/tokens/... maps to packages/tokens/).

   Only depends on the --dz-* and --brand-* design tokens defined in
   packages/tokens/theme.css + brand.css, so it works standalone as a
   linked stylesheet on the server-rendered pages too.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Marketing-specific tokens ───────────────────────────────────── */
.mkt-layout {
  /* ── Brand hue pin ──────────────────────────────────────────────
     Marketing does NOT follow the visitor's house. --dz-accent is
     re-pinned to the fixed brand ember for the whole public site, so
     every downstream rule that already reads --dz-accent (the .lp
     landing styles, .fp feature pages, nav, footer, docs) inherits the
     brand hue without needing to know about this. Product surfaces are
     unaffected — they are outside .mkt-layout and keep data-house.
     Dark-mode values are re-pinned in the dark block below. */
  --dz-accent: var(--brand-marketing-accent);
  --dz-accent-hover: var(--brand-marketing-accent-hover);
  --dz-accent-fg: var(--brand-marketing-accent-fg);
  --dz-accent-faint: color-mix(in srgb, var(--dz-accent) 4%, transparent);
  --dz-accent-subtle: color-mix(in srgb, var(--dz-accent) 8%, transparent);
  --dz-accent-soft: color-mix(in srgb, var(--dz-accent) 10%, transparent);
  --dz-accent-light: color-mix(in srgb, var(--dz-accent) 12%, transparent);
  --dz-accent-medium: color-mix(in srgb, var(--dz-accent) 15%, transparent);
  --dz-accent-glow: color-mix(in srgb, var(--dz-accent) 20%, transparent);
  --dz-accent-emphasis: color-mix(in srgb, var(--dz-accent) 30%, transparent);
  --dz-accent-soft-border: color-mix(
    in srgb,
    var(--dz-accent) 28%,
    transparent
  );

  /* ── Editorial display face ─────────────────────────────────────
     Display headings on marketing are set in the serif; body, nav and
     UI stay in the sans. Inter is the single most-used typeface in
     SaaS, so an all-Inter site reads as competent and anonymous — the
     serif is what makes a heading recognisably ours, and it suits
     accounting (trust, permanence) better than a neon-futurist sans.
     Newsreader was already in the repo, used only as a reading
     preference; this puts it to work as a brand asset. */
  --mkt-display-font: var(--brand-font-serif);
  --mkt-display-thin: 400;
  --mkt-display-heavy: 700;
  /* The emphatic clause of a two-tone heading. 500, not 700: at
     display size the contrast that reads is 400-vs-500 plus a colour
     shift, and 700 next to 400 at 5rem looks like two headings. */
  --mkt-display-lift: 500;

  /* The quiet clause of a two-tone heading. At 25% of the text colour
     it dissolved into the page at 3rem+, so it became a real colour —
     but --dz-text-secondary (#4b5468 against #1b2433 primary) is a
     body-copy step, and at 5rem the two clauses read as one. Mixing
     the ink halfway into the page colour opens a gap you can actually
     see at display size while staying an opaque colour.

     Only ever used on display type (.lp-thin, .fp-hero-title), so the
     3:1 large-text contrast floor applies, not 4.5:1 — this lands
     comfortably above both. */
  --mkt-thin: color-mix(in srgb, var(--dz-text-primary) 50%, var(--dz-bg-page));
  --mkt-light: color-mix(in srgb, var(--dz-text-primary) 50%, transparent);

  /* ── Primary actions ─────────────────────────────────────────
     Nav Get Started, lp-btn, pricing CTAs, modals.

     A CTA is always the inverse of the ground it sits on — never the
     accent. Ember stays a colour the page uses to POINT at things
     (eyebrows, rules, the forecast line); the moment it also fills
     every button it stops pointing at anything. Both sides read off
     the semantic pair, so the rule holds in dark theme for free, and
     .mkt-invert re-pins them for a dark band on a light page. */
  --mkt-btn-bg: var(--dz-text-primary);
  --mkt-btn-text: var(--dz-bg-primary);
  --mkt-btn-hover: color-mix(
    in srgb,
    var(--dz-text-primary) 82%,
    var(--dz-bg-primary)
  );

  /* Tracks the pinned brand accent. The --mkt-hero-glow, --mkt-grain-tint
     and --mkt-grid-line siblings went with the halo, grain and grid
     they tinted. */
  --mkt-accent: var(--dz-accent);

  --mkt-cta-bg: var(--mkt-btn-bg);
  --mkt-cta-bg-hover: var(--mkt-btn-hover);
  --mkt-cta-text: var(--mkt-btn-text);

  /* ── Named type scale ────────────────────────────────────────
     Eight steps plus a micro label. Every marketing heading picks a
     step; nothing declares its own clamp(). Before this the same
     visual heading was written as clamp(2rem, 4vw, 3rem) in six
     places and clamp(1.75rem, 3.5vw, 2.5rem) in two more, with no
     reason for the spread.

     Display steps run LIGHT and TIGHT — 400 weight, negative
     tracking, line-height near 1.06. That pairing is what carries
     scale on a big heading; reaching for 700 at 5rem just shouts.
     Newsreader tops out at 700 and has no 300, so 400 is also the
     lightest real weight available — no faux-synthesis.

     Assigned to heading classes in "The scale, applied" below. There
     are deliberately no .mkt-t1-style utility classes: the marketing
     pages are plain semantic CSS, and a parallel utility vocabulary
     would just give every heading two places to be defined.

     Display ceilings and tracking follow the same curve the big
     commerce marketing sites use: the top step is allowed to get
     genuinely large (6rem, not 5.25rem) and tracking tightens as size
     grows rather than sitting at one value for the whole ramp. The
     numbers below are the -0.025 / -0.02 / -0.01 ladder — tight enough
     to bind a display line together, loose enough that Newsreader's
     thin strokes don't collide at 6rem. */
  --mkt-dsp: clamp(3rem, 6.8vw, 6rem);
  --mkt-dsp-lh: 1.05;
  --mkt-dsp-ls: -0.025em;
  --mkt-dsp-w: 400;

  --mkt-t1: clamp(2.375rem, 4.8vw, 4rem);
  --mkt-t1-lh: 1.08;
  --mkt-t1-ls: -0.02em;
  --mkt-t1-w: 400;

  --mkt-t2: clamp(1.9375rem, 3.1vw, 2.625rem);
  --mkt-t2-lh: 1.14;
  --mkt-t2-ls: -0.014em;
  --mkt-t2-w: 400;

  --mkt-t3: clamp(1.5rem, 2.1vw, 1.9375rem);
  --mkt-t3-lh: 1.22;
  --mkt-t3-ls: -0.01em;
  --mkt-t3-w: 400;

  --mkt-t4: 1.3125rem;
  --mkt-t4-lh: 1.34;
  --mkt-t4-ls: -0.008em;
  --mkt-t4-w: 500;

  /* Body steps run at 500, not 400, with a small POSITIVE track.

     This is the one borrowed move that does the most work. Inter at
     400 goes limp against a 400-weight Newsreader display line — the
     heading and the paragraph under it read as the same weight at
     different sizes. Nudging body to 500 and opening the tracking a
     hair (+0.015em) separates the two voices without touching either
     colour, and it is what makes Inter look deliberate rather than
     defaulted. --brand-font-sans is already Inter, so this costs no
     new webfont.

     These two are applied by the prose rule further down ("Body copy"),
     not by the t5–t7 steps below — those steps only ever get read for
     their font-size, so hanging weight and tracking off them would put
     the values somewhere nothing looks. */
  --mkt-body-w: 500;
  --mkt-body-ls: 0.015em;

  --mkt-t5: 1.125rem;
  --mkt-t5-lh: 1.5;
  --mkt-t5-w: var(--mkt-body-w);

  --mkt-t6: 1.0625rem;
  --mkt-t6-lh: 1.62;
  --mkt-t6-w: var(--mkt-body-w);

  --mkt-t7: 0.9375rem;
  --mkt-t7-lh: 1.58;
  --mkt-t7-w: var(--mkt-body-w);

  --mkt-micro: 0.75rem;
  --mkt-micro-ls: 0.072em;

  /* ── Rhythm ──────────────────────────────────────────────────
     Three radii and one vertical step. The landing page was mixing
     6/8/10/12/14/16/18/20px corners; a fixed set is most of what
     reads as "considered" on a marketing page. */
  --mkt-r-sm: 6px;
  --mkt-r-md: 10px;
  --mkt-r-lg: 14px;
  /* Controls — CTAs, nav buttons, chips, filter toggles. Was a full
     9999px pill; the consulting-led repositioning sharpened it to a
     barely-rounded corner (the ledger reads as an instrument, not an
     app). The token keeps its historical name so every existing
     reference picks the new geometry up from here. Controls still sit
     one step tighter than cards, so the interactive thing on a band
     keeps its contrast against the 10px panels behind it. */
  --mkt-r-pill: 4px;

  /* Band rhythm. Sections breathe harder than they used to (5rem →
     8rem rather than 4.5 → 7.5): with the ambient photograph gone,
     whitespace is what separates one band from the next, so it has to
     carry weight the backdrop used to. */
  --mkt-band-y: clamp(5rem, 9vw, 8rem);
  --mkt-gutter: clamp(1.25rem, 4vw, 2.5rem);
  /* One band width for every full-width marketing section. Was 72rem
     hardcoded in ~15 places across three stylesheets; now it is a
     token and it is wider. Narrow prose columns (60–66rem) are a
     separate, deliberate measure and are NOT folded into this. */
  --mkt-band-w: 90rem;

  /* Footer chrome. Light theme tracks the standard semantic tokens; the dark
     footer uses a dedicated deep palette (overridden below) so the literals
     live in ONE place instead of scattered across every footer rule. */
  --mkt-footer-bg: var(--dz-bg-secondary);
  --mkt-footer-fg: var(--dz-text-primary);
  --mkt-footer-border: var(--dz-border-subtle);
  --mkt-footer-divider: var(--dz-border-subtle);
  /* Slightly stronger than --dz-text-muted so 0.7rem footer labels meet 4.5:1. */
  --mkt-footer-label: var(--dz-text-secondary);
  --mkt-footer-link: var(--dz-text-secondary);
  --mkt-footer-muted: var(--dz-text-secondary);
  --mkt-footer-faint: var(--dz-text-secondary);
  --mkt-footer-social-border: var(--dz-border);
  --mkt-footer-social-border-hover: var(--dz-border-hover);
  /* Footer accent text follows the pinned brand accent, like the nav
     CTAs and the hero title. */
  --mkt-footer-accent-stop: var(--mkt-accent);
}

/* ── Display headings ─────────────────────────────────────────────
   ONE rule for every marketing display heading, spanning both class
   systems — .lp-* (landing, pricing, compare) and .fp-* (feature
   pages) — and all three runtimes that mount .mkt-layout: the SPA,
   the SSR marketing app, and the Jinja shells.

   These two prefixes grew separately and drifted: near-identical
   headings were declaring tracking anywhere from -0.02em to -0.035em
   with no reason for the spread. Family and tracking now live here;
   the page files keep only what is genuinely local to them (size,
   line-height, margins). Add new heading classes to this list rather
   than restating the family per page.

   Tracking loosens to -0.02em: -0.035em was tuned for Inter, and a
   serif at display size closes its counters up and turns muddy under
   that much negative tracking. */
.mkt-layout
:is(
  .lp-hero-title,
  .lp-features-heading,
  .lp-cfo-heading,
  .lp-platform-heading,
  .lp-compare-heading,
  .lp-faq-heading,
  .lp-previews-heading,
  .lp-proof-heading,
  .lp-final-cta-heading,
  .lp-ua-heading,
  .lp-agents-heading,
  .fp-hero-title,
  .fp-section-heading,
  .fp-feat-heading,
  .fp-advisor-heading,
  .fp-deck-cover-title,
  /* The /ai hero and the docs hero were the two marketing headings
     still set in the sans — not a decision, just pages written after
     this list. The docs hero also asked for weight 800, which
     Newsreader would have faux-bolded; its scale step sets 400. */
  .ai-hero-title,
  .docs-hero h1
) {
  font-family: var(--mkt-display-font);
  letter-spacing: -0.02em;
}

/* Newsreader stops at 700, so an 800/900 declaration would be
   faux-bolded by the browser — smeared strokes on the largest text on
   the page. This used to clamp .lp-final-cta-heading (900) and
   .fp-deck-cover-title (800) back to 700; both now take a scale step
   that sets weight 400 outright, so there is nothing left to clamp.
   --mkt-display-heavy is kept for body-level emphasis. */

/* ── The scale, applied ───────────────────────────────────────────
   Each heading class is assigned a step. Size, line-height, tracking
   and weight all arrive together — a step is a complete typographic
   setting, not just a font-size, which is why the page files no
   longer declare any of the four.

   These win over the page files on specificity ((0,2,0) beats a bare
   single-class selector), so a leftover font-size in a page file
   would be silently dead. They were removed rather than left to rot.

   This is the whole public marketing surface: the landing, pricing
   and compare family, the ~20 feature pages, the AI page and the
   docs hero. Every display heading a visitor can reach is now one of
   four steps. Add new heading classes to a group here rather than
   declaring a size on the page. */
.mkt-layout :is(.lp-hero-title, .fp-hero-title, .ai-hero-title) {
  font-size: var(--mkt-dsp);
  line-height: var(--mkt-dsp-lh);
  letter-spacing: var(--mkt-dsp-ls);
  font-weight: var(--mkt-dsp-w);
}

.mkt-layout
  :is(
    .lp-features-heading,
    .lp-cfo-heading,
    .lp-platform-heading,
    .lp-compare-heading,
    .lp-faq-heading,
    .lp-previews-heading
  ) {
  font-size: var(--mkt-t1);
  line-height: var(--mkt-t1-lh);
  letter-spacing: var(--mkt-t1-ls);
  font-weight: var(--mkt-t1-w);
}

.mkt-layout
  :is(
    .lp-proof-heading,
    .lp-final-cta-heading,
    .fp-section-heading,
    .fp-deck-cover-title,
    .docs-hero h1
  ) {
  font-size: var(--mkt-t2);
  line-height: var(--mkt-t2-lh);
  letter-spacing: var(--mkt-t2-ls);
  font-weight: var(--mkt-t2-w);
}

.mkt-layout
  :is(
    .lp-ua-heading,
    .lp-agents-heading,
    .fp-feat-heading,
    .fp-advisor-heading
  ) {
  font-size: var(--mkt-t3);
  line-height: var(--mkt-t3-lh);
  letter-spacing: var(--mkt-t3-ls);
  font-weight: var(--mkt-t3-w);
}

/* ── Eyebrows ─────────────────────────────────────────────────────
   The small uppercase label above a heading. It had drifted into four
   treatments across the site — an accent-tinted pill, a bordered
   blurred pill, a mono label and a plain muted one — at three sizes
   (0.7/0.72/0.75rem), two weights and four tracking values.

   One treatment now, on the micro step: bare uppercase text, no pill.
   The pills were doing a job the tracking already does; dropping them
   also stops a page opening with two rounded rectangles stacked above
   the headline.

   Two roles, because they are not the same thing:
     accent — one per section, marks what the section is about
     quiet  — repeated inside a grid, labels a cell
   The second is muted rather than ember; ember on every card is ember
   nowhere. */
.mkt-layout
:is(
  .lp-hero-eyebrow,
  .lp-cfo-eyebrow,
  .lp-previews-eyebrow,
  .lp-proof-eyebrow,
  .fp-hero-eyebrow,
  .ai-hero-eyebrow,
  .lp-audience-badge,
  .fp-feat-eyebrow,
  .fp-advisor-eyebrow
) {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0;
  border: 0;
  background: none;
  backdrop-filter: none;
  border-radius: 0;
  font-family: var(--brand-font-sans);
  font-size: var(--mkt-micro);
  font-weight: 500;
  letter-spacing: var(--mkt-micro-ls);
  text-transform: uppercase;
}

.mkt-layout
  :is(
    .lp-hero-eyebrow,
    .lp-cfo-eyebrow,
    .lp-previews-eyebrow,
    .lp-proof-eyebrow,
    .fp-hero-eyebrow,
    .ai-hero-eyebrow,
    .lp-audience-badge
  ) {
  color: var(--mkt-accent);
}

.mkt-layout :is(.fp-feat-eyebrow, .fp-advisor-eyebrow) {
  color: var(--dz-text-secondary);
}

/* ── Heading emphasis ─────────────────────────────────────────────
   One device for the emphatic clause of a heading, everywhere.

   The landing pages express it as `.lp-heavy`; the feature pages
   author `<em>` inline. Both used to be a different thing: .lp-heavy
   was 700 (and, until this pass, filled with an animated accent
   gradient), while `<em>` was an ink→ember gradient at weight 900 on
   the hero and 800 on section headings — weights Newsreader tops out
   below, so the browser faux-bolded them into smeared strokes at 4rem.

   All of it is now --mkt-display-lift on ink: 400-vs-500 plus the
   colour step against --mkt-thin. Restraint is the point, and a
   gradient inside a headline reads as decoration on a page whose
   hierarchy is carried by size and tracking. */
.mkt-layout :is(.fp-hero-title, .fp-section-heading, .fp-feat-heading) em {
  font-style: normal;
  font-weight: var(--mkt-display-lift);
  color: var(--dz-text-primary);
  background: none;
  -webkit-text-fill-color: currentColor;
}

/* ── Inverted bands ───────────────────────────────────────────────
   A dark section on a light page. Re-pinning these four tokens flips
   every CTA, accent and quiet-clause inside the band — nothing in the
   band needs to know it is dark. Mirrors how the dark theme block
   below re-pins the same names for the whole page.

   Ember lifts to the dark-mode ramp for the same reason it does in
   dark theme: the light-mode ember does not carry on a dark ground. */
.mkt-layout .mkt-invert {
  --dz-accent: var(--brand-marketing-accent-dark);
  --dz-accent-hover: var(--brand-marketing-accent-hover-dark);
  --mkt-accent: var(--brand-marketing-accent-dark);

  /* Literals, not the semantic pair: this band is dark in BOTH themes,
     so --dz-text-primary would resolve light-on-light once the page
     itself goes dark and the button would vanish. */
  --mkt-btn-bg: #fff;
  --mkt-btn-text: #171210;
  --mkt-btn-hover: rgba(255, 255, 255, 0.82);

  --mkt-cta-bg: var(--mkt-btn-bg);
  --mkt-cta-bg-hover: var(--mkt-btn-hover);
  --mkt-cta-text: var(--mkt-btn-text);

  --mkt-thin: rgba(255, 255, 255, 0.62);
}

/* ── Alternating bands ────────────────────────────────────────────
   The quiet half of the band system. .mkt-invert is the loud flip (a
   dark section on a light page); this is the one-step tonal shift
   that lets two consecutive light sections read as separate without
   a rule line or a shadow between them.

   Tracks --dz-bg-secondary rather than a literal so it inverts with
   the page theme for free. Full-bleed by design: the band paints edge
   to edge and the inner container holds the content to --mkt-band-w,
   which is what gives the page its horizon lines now that the fixed
   photograph is gone. */
.mkt-layout .mkt-band-alt {
  background: var(--dz-bg-secondary);
}

/* ── Body copy ────────────────────────────────────────────────────
   The 500-weight, positively-tracked body treatment described up at
   --mkt-body-w. Scoped to prose elements so it cannot reach a heading
   — every display step sets its own weight and negative tracking, and
   inheriting a positive track into those would undo the whole point
   of the ladder.

   Docs pages mount .mkt-layout too and are included on purpose: Inter
   at 400 is exactly as limp in a reference page as it is on a landing
   band. */
.mkt-layout :is(p, li, dd, blockquote) {
  font-weight: var(--mkt-body-w);
  letter-spacing: var(--mkt-body-ls);
}

/* Weight is a poor signal in OpenDyslexic (it ships two weights and the
   bold is very heavy) and Lexend is already optically heavier than Inter
   at the same nominal weight. Both preferences drop back to 400 body so
   the accessible faces render as intended rather than as near-bold. */
[data-font="readable"] .mkt-layout,
[data-font="dyslexic"] .mkt-layout {
  --mkt-body-w: 400;
  --mkt-body-ls: normal;
}

/* Accessibility font preferences outrank the editorial serif. A visitor
   who picked Lexend or OpenDyslexic did so to be able to READ the page;
   --brand-font-sans is already remapped to their choice by theme.css, so
   pointing the display face at it honours the preference. */
[data-font="readable"] .mkt-layout,
[data-font="dyslexic"] .mkt-layout {
  --mkt-display-font: var(--brand-font-sans);
  --mkt-display-thin: 400;
  --mkt-display-heavy: 700;
}

/* Dark-theme overrides for the marketing token set. Centralises every
   white-on-dark footer/grid literal that used to be repeated per rule. */
:root.dark .mkt-layout,
[data-theme="dark"] .mkt-layout {
  /* Re-pin the accent to the LIFTED brand ember for dark marketing —
     the light-mode ember is too dark to read against the dark page.
     Tints re-derive from it automatically. */
  --dz-accent: var(--brand-marketing-accent-dark);
  --dz-accent-hover: var(--brand-marketing-accent-hover-dark);
  --dz-accent-fg: var(--brand-marketing-accent-fg-dark);

  /* Neutral slate band, not the earlier warm brown-black (#170f0a) —
     it clashed against the cool dark page ground. */
  --mkt-footer-bg: var(--dz-bg-secondary);
  --mkt-footer-fg: #fff;
  --mkt-footer-border: rgba(255, 255, 255, 0.06);
  --mkt-footer-divider: rgba(255, 255, 255, 0.1);
  /* 0.55, not 0.4 — the light-theme comment above promises 4.5:1 for the
     0.7rem footer labels, but this dark override delivered only 3.80:1. */
  --mkt-footer-label: rgba(255, 255, 255, 0.55);
  --mkt-footer-link: rgba(255, 255, 255, 0.65);
  --mkt-footer-muted: rgba(255, 255, 255, 0.45);
  --mkt-footer-faint: rgba(255, 255, 255, 0.3);
  --mkt-footer-social-border: rgba(255, 255, 255, 0.15);
  --mkt-footer-social-border-hover: rgba(255, 255, 255, 0.4);
  /* Keep the house accent on the dark footer too (brightened by theme.css). */
  --mkt-footer-accent-stop: var(--mkt-accent);
}

/* ── Layout ──────────────────────────────────────────────────────── */
.mkt-layout {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--brand-font-sans);
  color: var(--dz-text-primary);
  position: relative;
  /* ── Fixed "dawn sun" photograph — REMOVED ─────────────────────
     A sunrise photo used to be fixed to the viewport behind every
     marketing and docs page, under a 30%→100% page-colour veil.

     It went because it was doing the job that section structure
     should do. A backdrop that scrolls independently of the content
     means no band has a stable ground: a card that reads as white
     over the veiled sun reads as cream two scroll-positions later,
     and every band boundary is soft because the same image runs
     underneath all of them. The veil had already been pushed from 6%
     to 30% chasing exactly this problem — which is the tell that the
     photograph was fighting the page rather than supporting it.

     Bands are flat and opaque now, and separation comes from
     alternating band colour (.mkt-band-alt / .mkt-invert below) plus
     the widened --mkt-band-y rhythm. Every surface sits on a known
     ground, which is what lets the type scale carry the hierarchy.

     The dawn assets are still on disk (/static/brand/dayzero-dawn-*.jpg)
     and the hero can still opt into one locally if we want a single
     photographic moment — this only removes the site-wide wash. */
  background-color: var(--dz-bg-page);
  /* Full-bleed band washes (.lp-band-alt, .fp-section:nth-of-type(even))
     break out to 100vw behind a centred column, which overshoots the
     content box by the scrollbar width. Clipping here absorbs that so
     no marketing page can develop a phantom horizontal scroll.
     `clip` rather than `hidden` so it cannot become a scroll container
     and break the fixed nav's position. */
  overflow-x: clip;
}
/* ── Hero photo suppression — REMOVED ─────────────────────────────
   `.mkt-layout .lp-hero::before { display: none }` used to live here.
   It existed because the layout painted the sunrise across every page,
   so the landing hero's own copy of it would have stacked two of the
   same photograph.

   With the site-wide wash gone the hero backdrop is the only place the
   photograph appears, which is where it was always strongest: one
   photographic moment at the top of the page, flat bands underneath.
   That is also the shape the rest of this restyle assumes — imagery
   concentrated in the hero, hierarchy below it carried by the type
   scale and the alternating band colour rather than by atmosphere.

   The rule is deleted rather than inverted: nothing needs to opt the
   hero photo back in, it simply renders now.

   (`.lp::after` was also suppressed here once. That one was deleted at
   the source in frontend/src/pages/LandingPage.css instead.) */
.mkt-layout main {
  flex: 1;
  position: relative;
  z-index: 1;
}

/* Grain texture overlay — REMOVED.
   An accent-tinted fractal-noise layer used to sit fixed over the
   whole marketing surface at 6% (8% dark). It was the third texture
   competing with the grid and the ambient glow, and at display sizes
   it put visible speckle through the thin strokes of the serif. The
   dawn photograph is the texture the site keeps. */

.mkt-layout--locked {
  height: 100vh;
  overflow: hidden;
}

/* ── Light-grid backdrop — REMOVED ────────────────────────────────
   The public site used to opt into the 48px ruled grid by putting
   `dz-light-grid` on the layout element, which picked up the base
   `.dz-light-grid::after` in frontend/src/index.css; this file then
   re-tinted it with the brand ember. A ruled grid is a texture, and
   the restyle moved the job of holding a page together onto the type
   scale — keeping both meant two systems doing one job, and the grid
   won every screenshot.

   The class itself is gone from both shells (MarketingLayout.tsx and
   app/templates/marketing/_layout.html), so the whole stack that hung
   off it goes too: the `> *` position/z-index rule that flattened
   every child to stack above the grid, the .sdm-overlay/.csm-overlay
   exception that existed only to undo that flattening (both modals
   already declare `position: fixed; z-index: 1000` themselves), and
   the ember `--mkt-grid-line` tint.

   Product surfaces still use `.dz-light-grid` and are unaffected. */

/* ── Ambient accent glow — REMOVED ────────────────────────────────
   A 640px radial wash of the accent bled down from the top of every
   marketing and docs page, under the nav. With the grid gone and the
   headline no longer gradient-filled, it was the last thing tinting
   the top of the page, and it made the nav's translucent bar read as
   a smudge rather than a plane. Removed with the rest of the
   atmospherics; the dawn photograph on .mkt-layout is the one
   deliberate backdrop the site keeps. */

/* ── Gradient + shimmer hero headings — REMOVED ───────────────────
   The heavy clause of every hero title was filled with an
   accent→ink→accent gradient clipped to the text, sweeping back and
   forth on a 9s loop. It is the single loudest thing the old page
   did, and it fought the restyle on three counts: it re-introduced
   the accent as the largest coloured element after CTAs stopped
   using it; `color: transparent` meant the headline had no real text
   colour, so the 400/500 two-tone could not read at all; and a
   permanently animating headline is the opposite of the restraint
   the rest of the system now buys.

   The hero reads as the hero because of size, weight and tracking —
   which is what the dsp step is for. Nothing replaces this. */

/* ── Nav ──────────────────────────────────────────────────────────── */
.mkt-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  /* Stronger, more trustworthy header surface: higher opacity + a hairline
     base border so the bar reads as a deliberate plane (not a floating blur)
     even before the visitor scrolls. */
  background: color-mix(in srgb, var(--dz-bg-page) 88%, transparent);
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  border-bottom: 1px solid color-mix(in srgb, var(--dz-border) 45%, transparent);
  transition:
    border-color 0.2s,
    background 0.2s,
    box-shadow 0.2s;
}
/* The bar is fixed, so anything scrolled to by fragment (#product, #faq,
   the "See it live" hero link) would otherwise land with its heading
   tucked under the nav. Offset every in-page anchor target by the bar
   height plus a breath. Keep the 4.25rem in step with .mkt-nav-inner. */
.mkt-layout main [id] {
  scroll-margin-top: calc(4.25rem + 1rem);
}

/* One visible focus ring for every marketing control. The product UI
   styles its own focus states per component; the marketing surfaces
   (links, CTAs, the FAQ and switcher buttons, nav) had nothing beyond
   the browser default, which several of the reset rules suppress. */
.mkt-layout
:is(a, button, [role="tab"], input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--dz-accent);
  outline-offset: 3px;
}

/* The `.mkt-layout > .mkt-nav { z-index: 100 }` override that sat here
   existed only to beat `.dz-light-grid > * { z-index: 1 }`, which
   flattened every layout child so it stacked above the grid. Both the
   grid and that flattening rule are gone, and .mkt-nav already
   declares z-index: 100 itself. */
.mkt-nav-scrolled {
  background: color-mix(in srgb, var(--dz-bg-page) 94%, transparent);
  border-bottom-color: var(--dz-border);
  box-shadow:
    0 1px 0 rgba(0, 0, 0, 0.02),
    0 8px 24px -16px rgba(0, 0, 0, 0.25);
}
.mkt-nav-inner {
  /* Full-bleed bar: the logo hugs the far-left edge and the
     Cosmetics/auth cluster the far-right, while the grid keeps the
     primary links centered in the viewport. */
  max-width: none;
  margin: 0;
  padding: 0 2rem;
  height: 4.25rem;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  /* Guaranteed separation between the centered links and the side columns
     (logo / Cosmetics+auth) so "Docs" never butts up against the Cosmetics
     button — especially with the wider readable/dyslexic fonts. */
  column-gap: 1.75rem;
}
.mkt-nav-logo {
  display: inline-flex;
  align-items: center;
  color: var(--dz-text-primary);
  text-decoration: none;
  justify-self: start;
  border-radius: var(--mkt-r-sm);
  padding: 0.25rem 0.4rem 0.25rem 0;
  margin-left: -0.1rem;
  transition: opacity 0.15s;
}
.mkt-nav-logo:hover {
  opacity: 0.85;
}

/* Legacy raster logo (still used by the server-rendered Jinja marketing nav,
   app/templates/marketing/_marketing_nav.html). Kept so those pages render
   identically while the React nav uses the SVG lockup below. */
.mkt-nav-logo-img {
  height: 24px;
  width: auto;
  display: block;
}
:root.dark .mkt-nav-logo-img,
[data-theme="dark"] .mkt-nav-logo-img {
  filter: invert(1);
}

/* ── Brand lockup (mark + wordmark + category cue) ───────────────── */
.mkt-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  color: var(--dz-text-primary);
}
.mkt-logo-mark {
  display: block;
  flex: none;
  /* Soft seat under the ink tile so the mark feels grounded, not pasted. */
  border-radius: var(--mkt-r-sm);
  box-shadow: 0 2px 8px -3px
    color-mix(in srgb, var(--dz-text-primary) 35%, transparent);
}
/* Theme-swapped mark: dark tile on light backgrounds, light tile on dark. */
.mkt-logo-mark--on-dark {
  display: none;
}
[data-theme="dark"] .mkt-logo-mark--on-light,
.dark .mkt-logo-mark--on-light {
  display: none;
}
[data-theme="dark"] .mkt-logo-mark--on-dark,
.dark .mkt-logo-mark--on-dark {
  display: block;
}
.mkt-logo-text {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-width: 0;
}
.mkt-logo-word {
  font-family: var(--brand-font-sans);
  font-weight: 800;
  /* Larger + darker + tighter than before so the wordmark reads as a
     deliberate logotype rather than default nav text. */
  font-size: 1.62rem;
  line-height: 1;
  letter-spacing: -0.035em;
  color: var(--dz-text-primary);
  white-space: nowrap;
}
.mkt-logo-divider {
  width: 1px;
  height: 1.5rem;
  background: var(--dz-border);
  flex: none;
}
.mkt-logo-cue {
  font-family: var(--brand-font-sans);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dz-text-secondary);
  white-space: nowrap;
}

/* The category cue + divider need horizontal room the bar only has on wide
   displays; below the threshold the bar forced a horizontal scrollbar across
   the whole marketing site. With the wordmark retired the lockup is ~110px
   narrower, so the cue now fits down to ~1400px (1440 laptops keep it; the
   bar collapses to the hamburger at 1280 anyway). Below that keep just the
   mark. */
@media (max-width: 1399px) {
  .mkt-logo-divider,
  .mkt-logo-cue {
    display: none;
  }
}
@media (max-width: 600px) {
  .mkt-logo-word {
    font-size: 1.1rem;
  }
}
.mkt-nav-links {
  display: flex;
  gap: 2rem;
  font-size: 1rem;
  font-weight: 500;
  color: var(--dz-text-secondary);
  justify-self: center;
  white-space: nowrap;
}
.mkt-nav-links a {
  text-decoration: none;
  color: inherit;
  transition: color 0.15s;
}
.mkt-nav-links a:hover {
  color: var(--dz-text-primary);
}

/* The compact top bar can't absorb the extra letter/word spacing the
   readable + dyslexic fonts add on <html>, and OpenDyslexic's wide glyphs
   push the links into the Cosmetics/auth cluster. Reset that spacing inside
   the bar and tighten the gaps so the links stay clear of the right side. */
[data-font="readable"] .mkt-nav-inner,
[data-font="dyslexic"] .mkt-nav-inner {
  letter-spacing: normal;
  word-spacing: normal;
}
[data-font="readable"] .mkt-nav-links,
[data-font="dyslexic"] .mkt-nav-links {
  gap: 1.5rem;
}
[data-font="dyslexic"] .mkt-nav-links {
  gap: 1.35rem;
  font-size: 0.78rem;
}

/* ── Product dropdown ───────────────────────────────────────── */
.mkt-nav-dropdown {
  position: relative;
}
.mkt-nav-dropdown-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  background: transparent;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--dz-text-secondary);
  cursor: pointer;
  transition: color 0.15s;
}
.mkt-nav-dropdown-trigger:hover,
.mkt-nav-dropdown-trigger-open {
  color: var(--dz-text-primary);
}
.mkt-nav-dropdown-trigger svg {
  opacity: 0.65;
  transition: transform 0.18s ease;
}
.mkt-nav-dropdown-trigger-open svg {
  transform: rotate(180deg);
}
.mkt-nav-dropdown-panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: 50%;
  min-width: 22rem;
  display: flex;
  flex-direction: column;
  padding: 0.4rem;
  border-radius: var(--mkt-r-md);
  background: var(--dz-bg-primary);
  border: 1px solid var(--dz-border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
  z-index: 200;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -4px);
  pointer-events: none;
  transition:
    opacity 0.14s ease-out,
    transform 0.14s ease-out,
    visibility 0s linear 0.14s;
}
/* Invisible bridge across the 0.5rem gap between the trigger and the panel
   so the cursor stays "inside" the dropdown while transiting between them. */
.mkt-nav-dropdown-panel::before {
  content: "";
  position: absolute;
  top: -0.5rem;
  left: 0;
  right: 0;
  height: 0.5rem;
}
.mkt-nav-dropdown-panel-open {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  pointer-events: auto;
  transition:
    opacity 0.14s ease-out,
    transform 0.14s ease-out;
}
.mkt-nav-dropdown-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--mkt-r-sm);
  text-decoration: none;
  transition: background 0.12s;
  /* Reset the nowrap inherited from `.mkt-nav-links` so the multi-word
     titles/subs wrap inside their column instead of overflowing the panel. */
  white-space: normal;
  overflow-wrap: anywhere;
}
.mkt-nav-dropdown-item:hover {
  background: var(--dz-bg-secondary);
}
.mkt-nav-dropdown-item-title {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--dz-text-primary);
  letter-spacing: -0.005em;
}
.mkt-nav-dropdown-item-sub {
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--dz-text-secondary);
  line-height: 1.4;
}

/* ── Product mega-menu (grouped, multi-column) ──────────────── */
/* The product list outgrew a single-column dropdown, so the panel
   becomes a grouped 3-column grid.

   Left-aligned to its trigger rather than centered under it. Capping the
   width to the viewport does not stop a centered panel from hanging off the
   edge: the nav's side columns are lopsided (small logo, wide auth cluster),
   so the link row sits well left of centre and a 46rem panel centred on
   "Product" started at a negative x on 1280–1400px displays. Anchoring the
   left edge to the trigger keeps the whole panel on screen at every desktop
   width, and the cursor now drops straight from the trigger into the panel. */
.mkt-nav-dropdown-panel.mkt-nav-mega {
  left: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.1rem 0.85rem;
  width: min(46rem, calc(100vw - 2rem));
  min-width: 0;
  padding: 0.85rem;
  transform: translate(0, -4px);
  align-items: start;
}
.mkt-nav-dropdown-panel.mkt-nav-mega.mkt-nav-dropdown-panel-open {
  transform: translate(0, 0);
}
.mkt-nav-mega-col {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.mkt-nav-mega-label {
  padding: 0.45rem 0.8rem 0.35rem;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dz-text-secondary);
}
@media (max-width: 820px) {
  .mkt-nav-dropdown-panel.mkt-nav-mega {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    width: min(32rem, calc(100vw - 2rem));
  }
}

.mkt-nav-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  justify-self: end;
  white-space: nowrap;
}

/* Desktop cluster (theme + auth). Stays in the bar on mobile beside the hamburger. */
.mkt-nav-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Hamburger toggle — hidden on desktop, revealed at the mobile breakpoint. */
.mkt-nav-burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin-right: -0.35rem;
  padding: 0;
  border: none;
  border-radius: var(--mkt-r-sm);
  background: transparent;
  color: var(--dz-text-primary);
  cursor: pointer;
  transition: background 0.15s;
}
.mkt-nav-burger:hover {
  background: var(--dz-bg-secondary);
}

/* Control buttons (theme, font, cosmetics) */
.mkt-control-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  height: 38px;
  padding: 0 1.1rem;
  border-radius: var(--mkt-r-pill);
  border: 1px solid var(--dz-border);
  background: transparent;
  color: var(--dz-text-secondary);
  font-size: 0.95rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}
.mkt-control-btn:hover {
  color: var(--dz-text-primary);
  background: var(--dz-bg-secondary);
}

/* Font picker */
.mkt-font-picker {
  position: relative;
}
.mkt-font-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 180px;
  border-radius: var(--mkt-r-sm);
  border: 1px solid var(--dz-border);
  background: var(--dz-bg-primary);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
  padding: 0.35rem;
  z-index: 200;
}
.mkt-font-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0.45rem 0.65rem;
  border: none;
  border-radius: var(--mkt-r-sm);
  background: transparent;
  color: var(--dz-text-secondary);
  font-family: var(--brand-font-sans);
  font-size: 0.8125rem;
  cursor: pointer;
  transition: all 0.12s;
}
.mkt-font-option:hover {
  background: var(--dz-bg-secondary);
  color: var(--dz-text-primary);
}
.mkt-font-option.active {
  color: var(--dz-text-primary);
  font-weight: 600;
}
.mkt-font-tag {
  font-size: 0.65rem;
  font-weight: 500;
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  background: var(--dz-bg-tertiary);
  color: var(--dz-text-muted);
}

.mkt-nav-signin {
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--dz-text-secondary);
  text-decoration: none;
  padding: 0.45rem 1rem;
  border-radius: var(--mkt-r-pill);
  transition:
    color 0.15s,
    background 0.15s;
}
.mkt-nav-signin:hover {
  color: var(--dz-text-primary);
  background: var(--dz-bg-secondary);
}
.mkt-nav-cta {
  font-size: 0.95rem;
  font-weight: 600;
  padding: 0.5rem 1.35rem;
  border-radius: var(--mkt-r-pill);
  background: var(--mkt-cta-bg);
  color: var(--mkt-cta-text);
  text-decoration: none;
  transition:
    background 0.2s,
    opacity 0.2s;
}
.mkt-nav-cta:hover {
  background: var(--mkt-cta-bg-hover);
}

/* ── Mobile menu (hamburger) ─────────────────────────────────────── */
.mkt-nav-mobile-overlay {
  position: fixed;
  inset: 4.25rem 0 0;
  z-index: 95;
  background: color-mix(in srgb, var(--dz-bg-page) 45%, transparent);
  backdrop-filter: blur(2px);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.2s ease,
    visibility 0.2s ease;
}
.mkt-nav-mobile-overlay-open {
  opacity: 1;
  visibility: visible;
}

.mkt-nav-mobile {
  position: fixed;
  top: 4.25rem;
  left: 0;
  right: 0;
  z-index: 96;
  max-height: calc(100dvh - 4.25rem);
  overflow-y: auto;
  background: var(--dz-bg-page);
  border-bottom: 1px solid var(--dz-border);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.14);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-0.5rem);
  pointer-events: none;
  transition:
    opacity 0.2s ease,
    transform 0.2s ease,
    visibility 0.2s ease;
}
.mkt-nav-mobile-open {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
}

.mkt-nav-mobile-inner {
  display: flex;
  flex-direction: column;
  padding: 0.75rem 1.25rem 1.5rem;
}

.mkt-nav-mobile-group {
  display: flex;
  flex-direction: column;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--dz-border);
}

.mkt-nav-mobile-label {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--dz-text-muted);
  padding: 0.4rem 0;
}

.mkt-nav-mobile-link {
  padding: 0.75rem 0;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--dz-text-primary);
  text-decoration: none;
}
.mkt-nav-mobile-link:active {
  color: var(--dz-accent);
}

.mkt-nav-mobile-actions {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding-top: 1.25rem;
}
.mkt-nav-mobile-signin,
.mkt-nav-mobile-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  border-radius: var(--mkt-r-pill);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
}
.mkt-nav-mobile-signin {
  border: 1px solid var(--dz-border);
  color: var(--dz-text-primary);
}
.mkt-nav-mobile-cta {
  background: var(--mkt-cta-bg);
  color: var(--mkt-cta-text);
}

@media (max-width: 1024px) {
  .mkt-layout {
    font-size: 106.25%;
  }
}

/* Small laptop / tablet / phone: hamburger for nav links; cosmetics + auth
   stay in the bar.

   This collapses at 1279px rather than 1024px because the centered link row
   (548px) plus the auth cluster (472px) plus the logo needs ~1277px of bar
   before anything can wrap — below that the row used to overflow the viewport
   instead of giving way to the hamburger. */
@media (max-width: 1279px) {
  .mkt-nav-links {
    display: none;
  }
  .mkt-nav-burger {
    display: inline-flex;
  }
  .mkt-nav-inner {
    grid-template-columns: 1fr auto;
    padding: 0 1rem;
    gap: 0.5rem;
  }
  .mkt-nav-right {
    gap: 0.35rem;
    min-width: 0;
  }
  .mkt-nav-actions {
    gap: 0.35rem;
    min-width: 0;
    flex-shrink: 1;
  }
  .mkt-nav-cosmetics .mkt-control-btn {
    height: 32px;
    padding: 0 0.55rem;
    font-size: 0.7rem;
  }
  /* One primary CTA in the bar; Sign In is in the hamburger menu. */
  .mkt-nav-signin {
    display: none;
  }
  .mkt-nav-cta {
    padding: 0.35rem 0.85rem;
    font-size: 0.75rem;
    white-space: nowrap;
  }
}

@media (max-width: 640px) {
  .mkt-layout {
    font-size: 112.5%;
  }
  .mkt-nav-inner {
    padding: 0 0.85rem;
  }
  .mkt-nav-cosmetics .mkt-control-btn-label {
    display: none;
  }
  .mkt-nav-cosmetics .mkt-control-btn {
    width: 32px;
    padding: 0;
    gap: 0;
  }
  .mkt-nav-cosmetics .mkt-control-btn-icon {
    margin: 0;
  }
}

@media (max-width: 400px) {
  .mkt-nav-cta {
    padding: 0.35rem 0.65rem;
    font-size: 0.7rem;
  }
}

.mkt-nav-mobile-auth {
  padding: 1rem 0 0.25rem;
  border-top: 1px solid var(--dz-border);
  margin-top: 0.25rem;
}
.mkt-nav-mobile-signin-link {
  display: block;
  padding: 0.75rem 0;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--dz-text-secondary);
  text-decoration: none;
}
.mkt-nav-mobile-signin-link:hover {
  color: var(--dz-text-primary);
}

/* Keep the menu out of the way once we're back on a desktop-width canvas.
   Mirrors the hamburger breakpoint above — the two must stay in sync or the
   open menu lingers on widths that no longer have a burger to close it. */
@media (min-width: 1280px) {
  .mkt-nav-mobile,
  .mkt-nav-mobile-overlay {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mkt-nav-mobile,
  .mkt-nav-mobile-overlay {
    transition: none;
  }
}

/* ── Footer ──────────────────────────────────────────────────────── */
.mkt-footer {
  background: var(--mkt-footer-bg);
  color: var(--mkt-footer-fg);
  border-top: 1px solid var(--mkt-footer-border);
  padding: 2.25rem 2rem 1.5rem;
}
.mkt-footer-inner {
  max-width: 72rem;
  margin: 0 auto;
}

/* The brand block sits above the link columns rather than beside them.
   Five columns of labels ("Practice Management", "For growing businesses")
   need the full inner width to keep each label on one line; sharing the row
   with the headline left them ~130px apiece, and because every link is an
   inline-flex box that will not shrink below its longest word, each column's
   text overflowed onto the next one. */
.mkt-footer-top {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--mkt-footer-divider);
}
/* Headline left, CTA stack right — the headline wraps at 18ch, so stacking
   the buttons under it would leave the right half of the row empty. */
.mkt-footer-brand {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 0.75rem 2.5rem;
}
/* Spans the CTA / note / socials stack beside it. */
.mkt-footer-brand .mkt-footer-headline {
  grid-row: 1 / span 3;
}
.mkt-footer-headline {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  font-weight: 900;
  line-height: 1.1;
  letter-spacing: -0.03em;
  margin: 0;
  max-width: 18ch;
}
.mkt-footer-accent {
  background: linear-gradient(
    135deg,
    var(--mkt-footer-fg) 0%,
    var(--mkt-footer-accent-stop) 100%
  );
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.mkt-footer-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.mkt-footer-cta-note {
  font-size: 0.75rem;
  color: var(--mkt-footer-muted);
  margin: -0.35rem 0 0;
}
.mkt-footer-cols {
  display: grid;
  /* Product · Solutions · Compare · Menu · Legal. auto-fit rather than five
     fixed tracks: as the viewport narrows the columns wrap onto another row
     instead of being crushed below the width of their own labels. The 9.5rem
     floor is the widest label ("For growing businesses") at this font size,
     so nothing overflows its column and the footer never widens the page. */
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 1.75rem 1.5rem;
}
/* The server-rendered footer (app/templates/marketing/_marketing_footer.html)
   has no .mkt-footer-top/.mkt-footer-brand wrapper to supply the gap, so its
   columns sat flush against the headline's descenders. */
.mkt-footer-headline + .mkt-footer-cols {
  margin-top: 2rem;
}
/* Product carries ~15 links to every other column's three-to-five. Give it a
   double-width track and list it two-up so the footer is not as tall as its
   single longest column. */
.mkt-footer-cols > .mkt-footer-col:first-child {
  grid-column: span 2;
}
.mkt-footer-cols > .mkt-footer-col:first-child .mkt-footer-link-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 1.5rem;
}
.mkt-footer-label {
  display: block;
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--mkt-footer-label);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 0.4rem;
}
.mkt-footer-link-grid {
  display: grid;
  /* One link per row. A second track inside an already-narrow footer column
     halved the space each label had and wrapped nearly all of them. */
  grid-template-columns: minmax(0, 1fr);
  /* Row gap gives adjacent touch targets enough spacing for Lighthouse. */
  gap: 0.25rem;
}
.mkt-footer-link-grid a {
  display: flex;
  align-items: center;
  min-height: 24px;
  /* Last-resort guard: a label longer than its track wraps rather than
     bleeding across the column boundary. */
  overflow-wrap: anywhere;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--mkt-footer-link);
  text-decoration: none;
  transition: color 0.15s;
  padding: 0.25rem 0;
  line-height: 1.3;
}
.mkt-footer-link-grid a:hover {
  color: var(--mkt-footer-fg);
}
.mkt-footer-socials {
  display: flex;
  gap: 0.75rem;
}
.mkt-footer-socials a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--mkt-footer-social-border);
  color: var(--mkt-footer-muted);
  text-decoration: none;
  transition:
    color 0.15s,
    border-color 0.15s;
}
.mkt-footer-socials a:hover {
  color: var(--mkt-footer-fg);
  border-color: var(--mkt-footer-social-border-hover);
}

.mkt-footer-bottom {
  padding-top: 1rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.mkt-footer-copy {
  font-size: 0.7rem;
  color: var(--mkt-footer-faint);
}
.mkt-footer-careers {
  font-size: 0.7rem;
  color: var(--mkt-footer-muted);
  margin: 0;
}

/* Below this the headline and the CTA stack are both too wide to share a row.
   The link columns need no matching breakpoint: .mkt-footer-cols is auto-fit,
   so they reflow on their own (5 → 4 → 3 → 2 as the viewport narrows). */
@media (max-width: 860px) {
  .mkt-footer-brand {
    grid-template-columns: minmax(0, 1fr);
  }
  .mkt-footer-brand .mkt-footer-headline {
    grid-row: auto;
  }
}
@media (max-width: 640px) {
  .mkt-footer {
    padding: 2.5rem 1.25rem 1.5rem;
  }
  .mkt-footer-cols {
    gap: 1.5rem 1.25rem;
  }
  .mkt-footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
  }
}

/* ── Shared utilities (docs/guides/other marketing pages) ────────── */
.mkt-container {
  max-width: var(--mkt-band-w);
  margin: 0 auto;
  padding: 0 2rem;
}
.mkt-section-header {
  text-align: center;
  max-width: 40rem;
  margin: 0 auto 3.5rem;
}
.mkt-section-tag {
  display: inline-block;
  font-size: 0.65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--dz-text-secondary);
  border: 1px solid var(--dz-border);
  padding: 0.25rem 0.75rem;
  border-radius: 100px;
  margin-bottom: 1rem;
}
.mkt-section-title {
  font-size: clamp(1.75rem, 4vw, 2.5rem);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.025em;
  color: var(--dz-text-primary);
}
.mkt-section-sub {
  margin-top: 1rem;
  font-size: 1.05rem;
  color: var(--dz-text-secondary);
  line-height: 1.7;
}

/* Buttons */
.mkt-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--brand-font-sans);
  font-weight: 600;
  font-size: 0.9375rem;
  /* CTA padding tuned when these were full pills; the generous
     horizontal step still reads right on the sharpened corner. */
  padding: 0.625rem 1.5rem;
  border-radius: var(--mkt-r-pill);
  transition: all 0.2s;
  cursor: pointer;
  border: none;
  text-decoration: none;
}
.mkt-btn-primary {
  background: var(--mkt-btn-bg);
  color: var(--mkt-btn-text);
}
.mkt-btn-primary:hover {
  opacity: 0.8;
  transform: translateY(-1px);
}
.mkt-btn-ghost {
  background: transparent;
  color: var(--dz-text-secondary);
  border: 1px solid var(--dz-border);
}
.mkt-btn-ghost:hover {
  color: var(--dz-text-primary);
  border-color: var(--dz-border-hover);
}
.mkt-btn-lg {
  padding: 0.75rem 2rem;
  font-size: 1rem;
}

/* Contact / demo modals — same monochrome fill as page CTAs */
.mkt-layout .csm-btn-primary {
  background: var(--mkt-btn-bg);
  color: var(--mkt-btn-text);
}
.mkt-layout .sdm-btn-primary {
  background: var(--mkt-btn-bg);
  color: var(--mkt-btn-text);
}
.mkt-layout .sdm-chip-active {
  background: var(--mkt-btn-bg);
  color: var(--mkt-btn-text);
  border-color: var(--mkt-btn-bg);
}
.mkt-layout .sdm-chip-active:hover {
  color: var(--mkt-btn-text);
}

/* Page-specific CTA classes that don't use lp-btn / mkt-btn */
.mkt-layout .imp-cta-btn,
.mkt-layout .irm-btn-primary {
  background: var(--mkt-btn-bg);
  color: var(--mkt-btn-text);
}
.mkt-layout .lp-ua-deploy-btn {
  background: var(--mkt-btn-bg);
  color: var(--mkt-btn-text);
  border-color: var(--mkt-btn-bg);
}

/* Cards */
.mkt-card {
  padding: 1.75rem;
  border-radius: var(--mkt-r-md);
  border: 1px solid var(--dz-border);
  background: var(--dz-bg-primary);
  transition: all 0.25s;
}
.mkt-card:hover {
  border-color: var(--dz-border-hover);
  transform: translateY(-2px);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
}
.mkt-card h3 {
  font-size: 1rem;
  font-weight: 700;
  margin-bottom: 0.4rem;
  color: var(--dz-text-primary);
}
.mkt-card p {
  font-size: 0.8125rem;
  color: var(--dz-text-secondary);
  line-height: 1.65;
}

/* Scroll reveal */
.mkt-reveal {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}
.mkt-reveal.visible {
  opacity: 1;
  transform: translateY(0);
}
.mkt-reveal-delay-1 {
  transition-delay: 0.1s;
}
.mkt-reveal-delay-2 {
  transition-delay: 0.2s;
}
