/* =========================================================================
   Alvva — D2C marketing design system
   marketing.css

   Committed, no build step (same rationale as for-lawyers.css and
   attorney-partners.css): public/css/** is gitignored, so a skipped
   `npm run production` on the droplet would otherwise ship naked pages.

   Art direction — "the paperwork, made human":
   The audience is immigrant families, usually on a phone, often reading in
   Spanish, and usually anxious about a government process. So: generous type,
   warm paper, plenty of air, and one honest number or fact per section rather
   than decoration. Everything states what happens next.

   Scoped under `.mkt` so it can coexist with the Tailwind build during the
   flagged rollout, when old and new pages are both live.

   Spanish sets 15–20% longer than English. Every measure is set in `ch`,
   every heading clamps down as well as up, and nothing is sized so tightly
   that a translated string breaks the layout.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;700&family=Poppins:wght@400;500;600&display=swap');

/* ---------- Tokens ---------- */
.mkt {
    /* paper — warmer than the attorney page; this audience is not a law firm */
    --m-paper:      #FDFCF9;
    --m-card:       #FFFFFF;
    --m-sunk:       #F4F2EC;

    /* ink — brand text100 and its softer steps */
    --m-ink:        #052122;
    --m-ink-2:      #3B4B4C;
    /* The lightest text step. #6F7A7A put the trust labels at 4.32:1 on paper,
       under AA for body size. */
    --m-ink-3:      #66716F;

    /* The inverted bands (footer, closing CTA, testimonials) are a SURFACE,
       not text. They used --m-ink, which is the same value in light mode but
       flips to near-white in dark mode, so those blocks would have rendered
       light-on-light. They get their own token. */
    --m-invert:     #052122;

    --m-rule:       #E4E1D8;
    --m-rule-2:     #CFCCC2;

    /* brand teal */
    --m-teal:       #00B8C1;
    /* The filled-button ground. #00858B put white label text at 4.44:1, just
       under AA, which is the kind of near-miss nobody catches by eye. Darkened
       until it clears 4.5. */
    --m-teal-mid:   #00787E;
    --m-deep:       #00595D;
    --m-wash:       #C7F2F4;
    --m-wash-soft:  #EAFBFC;

    /* warm signal — used for emphasis on outcomes, never for chrome */
    --m-amber:      #FF9A42;
    --m-amber-soft: #FFF1E3;

    --m-display:    'Archivo', 'Helvetica Neue', Arial, sans-serif;
    --m-sans:       'Poppins', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;

    --m-shadow:     0 1px 2px rgba(5, 33, 34, .04), 0 20px 44px -30px rgba(5, 33, 34, .28);
    --m-shadow-lg:  0 2px 5px rgba(5, 33, 34, .05), 0 44px 84px -44px rgba(5, 33, 34, .34);

    --m-r:          14px;
    --m-r-sm:       10px;
    --m-r-lg:       24px;

    --m-gutter:     20px;
    --m-max:        1200px;

    overflow-x: hidden;

    background: var(--m-paper);
    color: var(--m-ink);
    font-family: var(--m-sans);
    font-size: 17px;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

@media (min-width: 640px) { .mkt { --m-gutter: 28px; } }

/* Base rules stay weak on purpose: `.mkt img` (0,1,1) would outrank any
   single-class component rule, which is how a logo silently ignores its
   height or a button loses its label colour. */
.mkt img { max-width: 100%; display: block; }
.mkt a:not([class]) { color: var(--m-deep); }

.mkt :focus-visible {
    outline: 2px solid var(--m-deep);
    outline-offset: 3px;
    border-radius: 3px;
}

/* Scoping the system under .mkt also scopes the reset. Without this,
   .mkt-wrap's width:100% plus its gutters resolve to parent + 40px, and every
   section overflows the viewport by exactly the padding. Tailwind's preflight
   used to supply this; the standalone layout does not load it. */
.mkt, .mkt *, .mkt *::before, .mkt *::after { box-sizing: border-box; }

/* ---------- Layout primitives ---------- */
.mkt-wrap {
    width: 100%;
    max-width: var(--m-max);
    margin: 0 auto;
    padding-left: var(--m-gutter);
    padding-right: var(--m-gutter);
}

.mkt-section { padding: 64px 0; }
.mkt-section--tight { padding: 48px 0; }

@media (min-width: 880px) {
    .mkt-section { padding: 92px 0; }
    .mkt-section--tight { padding: 68px 0; }
}

/* Two band colours, and that is the whole set. The page reads top to bottom in
   one sitting, so every extra full-width background is a moment where a visitor
   feels they have landed somewhere else. The home page was running five —
   paper, this sunk grey, a peach notice, a mint wash and a near-black
   testimonial band — and the mint one was carrying no meaning the grey could
   not. Amber stays, because it marks the USCIS warning and is functional; the
   near-black stays, because it closes the page.

   `--wash-soft` is still a token: it tints the cost-card header, the card icons
   and the featured directory cell. It is no longer a full-width band, which is
   why there is no `.mkt-section--wash`. */
.mkt-section--sunk { background: var(--m-sunk); }

/* ---------- Type ---------- */
.mkt-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-size: .8125rem;
    font-weight: 500;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--m-deep);
    margin: 0 0 18px;
}

.mkt-eyebrow::before {
    content: "";
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: var(--m-teal);
    flex: none;
}

.mkt-h1 {
    font-family: var(--m-display);
    font-optical-sizing: auto;
    font-weight: 700;
    font-size: clamp(2.1rem, 4.6vw, 3.5rem);
    line-height: 1.06;
    letter-spacing: -.03em;
    margin: 0 0 22px;
    max-width: 20ch;
}

/* Spanish headlines run 15 to 20% longer than English and the measure is set
   in ch, which scales with the font: at ANY size a 46-character Spanish h1
   wraps to three lines inside 20ch, so shrinking the type could never fix it.
   The Spanish pages get a wider measure and a slightly smaller cap so the
   line fits the hero column, which brings every current es headline back to
   the two lines the English ones get. */
html[lang="es"] .mkt-h1 {
    max-width: 24ch;
    /* Measured, not derived: the longest Spanish headline holds two lines up
       to exactly 3rem at every desktop width and breaks to three at 3.1. The
       cap sits a hair under the cliff for rendering variance. */
    font-size: clamp(2rem, 4.1vw, 2.95rem);
}

.mkt-h2 {
    font-family: var(--m-display);
    font-optical-sizing: auto;
    font-weight: 600;
    font-size: clamp(1.72rem, 3.1vw, 2.5rem);
    line-height: 1.16;
    letter-spacing: -.026em;
    margin: 0 0 18px;
    max-width: 24ch;
}

.mkt-h3 {
    font-size: 1.0625rem;
    font-weight: 600;
    line-height: 1.4;
    margin: 0 0 7px;
}

.mkt-lede {
    font-size: clamp(1.02rem, 1.4vw, 1.2rem);
    line-height: 1.62;
    color: var(--m-ink-2);
    margin: 0;
    max-width: 60ch;
}

.mkt-p { margin: 0 0 1em; color: var(--m-ink-2); max-width: 66ch; }

/* A single unbreakable token, an email address or a URL, is wider than a phone
   and pushes the whole page sideways. about-us scrolled 102px at 360 because of
   exactly one address in one paragraph. Declared for every text block rather
   than the one that happened to have it, since copy is edited in the admin and
   in lang files by people who will not know this rule exists. */
.mkt p, .mkt li, .mkt h1, .mkt h2, .mkt h3, .mkt blockquote, .mkt figcaption, .mkt dd {
    overflow-wrap: break-word;
}

.mkt-center { margin-left: auto; margin-right: auto; text-align: center; }
.mkt-center .mkt-h2, .mkt-center .mkt-lede { margin-left: auto; margin-right: auto; }

/* ---------- Buttons ---------- */
.mkt-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    font-family: var(--m-sans);
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.2;
    text-align: center;
    padding: 16px 30px;
    border: 1px solid var(--m-teal-mid);
    border-radius: 999px;
    background: var(--m-teal-mid);
    color: #FFF;
    text-decoration: none;
    cursor: pointer;
    transition: background .18s ease, border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}

.mkt-btn:hover {
    background: var(--m-deep);
    border-color: var(--m-deep);
    transform: translateY(-1px);
    box-shadow: 0 10px 24px -12px rgba(0, 89, 93, .55);
}

/* The press: the button gives under the finger instead of switching states.
   Scale, not colour, because most of this audience is on a touchscreen where
   there is no hover state and :active is the only physical feedback there is. */
.mkt-btn:active { transform: translateY(0) scale(.97); box-shadow: none; }

.mkt-btn--lg { font-size: 1.06rem; padding: 19px 38px; }

/* On the two large CTAs the arrow rides in its own chip, tucked into the right
   padding. It gives the arrow's hover travel a visible track to move inside,
   and marks the page's primary action apart from every other button without a
   second accent colour. The negative vertical margin keeps the chip from
   stretching the button. */
.mkt-btn--lg .mkt-btn__arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    margin: -7px -18px -7px 2px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .16);
}

.mkt-btn--lg:hover .mkt-btn__arrow { transform: translateX(3px) scale(1.05); }

/* Closing band: that button is teal with dark text, so the chip flips dark. */
.mkt-cta .mkt-btn--lg .mkt-btn__arrow { background: rgba(4, 40, 42, .14); }

.mkt-btn--ghost {
    background: transparent;
    color: var(--m-ink);
    border-color: var(--m-rule-2);
    box-shadow: none;
}
.mkt-btn--ghost:hover {
    background: transparent;
    color: var(--m-deep);
    border-color: var(--m-deep);
    box-shadow: none;
}

.mkt-btn__arrow { transition: transform .18s ease; }
.mkt-btn:hover .mkt-btn__arrow { transform: translateX(3px); }

.mkt-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px 18px;
}

/* ---------- Header ---------- */
.mkt-head {
    position: sticky;
    top: 0;
    z-index: 50;
    background: rgba(253, 252, 249, .9);
    backdrop-filter: saturate(1.6) blur(12px);
    -webkit-backdrop-filter: saturate(1.6) blur(12px);
    border-bottom: 1px solid var(--m-rule);
}

.mkt-head__inner {
    display: flex;
    align-items: center;
    gap: 18px;
    height: 68px;
    min-width: 0;
}

.mkt-head__logo { height: 24px; width: auto; flex: none; }

.mkt-head__nav {
    display: none;
    align-items: center;
    gap: 26px;
    margin-left: 14px;
}

@media (min-width: 1000px) { .mkt-head__nav { display: flex; } }

.mkt-head__link {
    font-size: .9375rem;
    font-weight: 400;
    color: var(--m-ink-2);
    text-decoration: none;
    padding: 6px 0;
    border-bottom: 2px solid transparent;
    transition: color .16s ease, border-color .16s ease;
    white-space: nowrap;
}

/* ---------- Nav dropdowns ----------
   Built on <details>, like the mobile menu, so the nav needs no JavaScript
   framework to work. The links are in the DOM whether the panel is open or
   not, which matters here: these are the site's only outbound links to
   blog.alvva.co and tools.alvva.co, and a crawler must see them. */
.mkt-drop { position: relative; }

.mkt-drop__btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .9375rem;
    color: var(--m-ink-2);
    padding: 6px 0;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    list-style: none;
    white-space: nowrap;
    transition: color .16s ease, border-color .16s ease;
}

.mkt-drop__btn::-webkit-details-marker { display: none; }
.mkt-drop__btn:hover { color: var(--m-ink); }
.mkt-drop[open] > .mkt-drop__btn { color: var(--m-ink); border-bottom-color: var(--m-teal); }
.mkt-drop__caret { transition: transform .18s ease; flex: none; }
.mkt-drop[open] .mkt-drop__caret { transform: rotate(180deg); }

.mkt-drop__panel {
    position: absolute;
    top: calc(100% + 12px);
    left: -14px;
    z-index: 60;
    min-width: 250px;
    display: grid;
    gap: 2px;
    padding: 10px;
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r);
    background: var(--m-card);
    box-shadow: var(--m-shadow-lg);
}

/* The Spanish resource list is ten items; two columns keep the panel from
   running off the bottom of a laptop screen. */
.mkt-drop__panel--wide { min-width: 420px; grid-template-columns: 1fr 1fr; }
.mkt-drop__panel--wide .mkt-drop__sep,
.mkt-drop__panel--wide .mkt-drop__link--all { grid-column: 1 / -1; }

.mkt-drop__link {
    display: block;
    padding: 9px 12px;
    border-radius: var(--m-r-sm);
    font-size: .9375rem;
    color: var(--m-ink-2);
    text-decoration: none;
    white-space: nowrap;
    transition: background .14s ease, color .14s ease;
}

.mkt-drop__link:hover { background: var(--m-sunk); color: var(--m-ink); }
.mkt-drop__link--all { color: var(--m-deep); font-weight: 500; }
.mkt-drop__sep { height: 1px; background: var(--m-rule); margin: 6px 4px; }

.mkt-head__link:hover { color: var(--m-ink); border-bottom-color: var(--m-teal); }

.mkt-head__spacer { flex: 1 1 auto; }

.mkt-head__side {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: none;
}

.mkt-lang {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--m-rule-2);
    border-radius: 999px;
    overflow: hidden;
}

.mkt-lang__opt {
    font-size: .8125rem;
    font-weight: 500;
    letter-spacing: .03em;
    padding: 6px 12px;
    color: var(--m-ink-3);
    text-decoration: none;
    transition: background .16s ease, color .16s ease;
}

.mkt-lang__opt[aria-current="true"] { background: var(--m-invert); color: #FFF; }
.mkt-lang__opt:not([aria-current="true"]):hover { background: var(--m-sunk); color: var(--m-ink); }

.mkt-head__cta { display: none; }
@media (min-width: 720px) { .mkt-head__cta { display: inline-flex; padding: 11px 22px; font-size: .9375rem; } }

/* Mobile disclosure — a details/summary so it works with no JS at all. */
.mkt-menu { position: relative; }
@media (min-width: 1000px) { .mkt-menu { display: none; } }

.mkt-menu__btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: .9375rem;
    font-weight: 500;
    color: var(--m-ink);
    background: transparent;
    border: 1px solid var(--m-rule-2);
    border-radius: 999px;
    padding: 9px 16px;
    cursor: pointer;
    list-style: none;
}
.mkt-menu__btn::-webkit-details-marker { display: none; }

.mkt-menu__panel {
    position: absolute;
    right: 0;
    top: calc(100% + 10px);
    width: min(84vw, 300px);
    background: var(--m-card);
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r);
    box-shadow: var(--m-shadow-lg);
    padding: 10px;
    display: flex;
    flex-direction: column;
}

.mkt-menu__link {
    padding: 11px 12px;
    border-radius: var(--m-r-sm);
    color: var(--m-ink);
    text-decoration: none;
    font-size: .975rem;
}
.mkt-menu__link:hover { background: var(--m-sunk); }

.mkt-menu__sep { height: 1px; background: var(--m-rule); margin: 8px 4px; }

/* The trigger's label is what tips the header over 390px once translated —
   "Qué preparamos" is twice the width of "What we prepare"'s abbreviation.
   Below that width the icon carries it, with the label kept for screen
   readers via aria-label. */
@media (max-width: 560px) {
    .mkt-menu__label { display: none; }
    .mkt-menu__btn { padding: 10px 13px; }
    .mkt-head__inner { gap: 12px; }
    .mkt-eyebrow { font-size: .75rem; }
}

/* ---------- Hero ---------- */
.mkt-hero { padding: 44px 0 12px; }
@media (min-width: 880px) { .mkt-hero { padding: 76px 0 28px; } }

.mkt-hero__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 40px;
    align-items: center;
}

/* Top-aligned, not centred. The media column is a photograph plus the cost
   card, which together run close to twice the height of the headline column;
   centring the short column against the tall one pushed the h1 roughly 450px
   down the page, so the first thing on screen was empty paper and the CTA sat
   below the fold. Aligning to the top puts the headline and the photograph on
   the same line and gives the hero back its first screen. */
@media (min-width: 980px) {
    .mkt-hero__grid { grid-template-columns: 1.05fr .95fr; gap: 60px; align-items: start; }
}

.mkt-hero__note {
    margin: 22px 0 0;
    font-size: .9375rem;
    color: var(--m-ink-3);
}

/* ---------- Trust strip ---------- */
.mkt-trust {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
    margin-top: 34px;
    border-top: 1px solid var(--m-rule);
    padding-top: 22px;
}

@media (min-width: 720px) { .mkt-trust { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; } }

/* Six-tile variant (home trust strip): three per row keeps both rows full
   instead of a 4 + 2 orphan row.

   The row gap is set separately and generously. At an even 20px the two rows
   sat 65px apart while the labels themselves wrap to two lines, so the six
   claims ran together as one block of text with no way to tell where one ended
   and the next began. */
@media (min-width: 720px) {
    .mkt-trust--6 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 30px 24px; }
}

/* Standing on its own below the hero rather than crammed inside it, the strip
   no longer needs the rule and the top margin that separated it from the CTAs.

   It does still need the section gap. This block used to say `padding-top: 0`
   on the grounds that "the section supplies its own spacing", but zeroing the
   padding is what removed that spacing: the strip inherited nothing, the hero
   contributes only 12px of bottom padding (28px at desktop), and the six claims
   ended up 14px under the cost card at every width while every other section
   break on the page has 64 to 92px. The tiles read as falling out of the bottom
   of the card rather than as a band of their own.

   Set a little tighter than a full `--tight` section (48/68) on purpose: the
   strip is the hero's supporting evidence, so it should sit closer to it than
   two unrelated sections sit to each other, but not touching. */
.mkt-trustband { padding-top: 40px; }
.mkt-trustband .mkt-trust { margin-top: 0; border-top: 0; padding-top: 0; }

@media (min-width: 880px) { .mkt-trustband { padding-top: 64px; } }
.mkt-trustband .mkt-trust__value { font-size: clamp(1.15rem, 1.7vw, 1.4rem); }

.mkt-trust__item { display: flex; flex-direction: column; gap: 2px; }

.mkt-trust__value {
    font-family: var(--m-display);
    font-size: clamp(1.05rem, 1.5vw, 1.22rem);
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -.01em;
}

.mkt-trust__label { font-size: .8125rem; color: var(--m-ink-3); line-height: 1.35; }

/* ---------- Trust panel ----------
   The six claims in one contained card rather than floating on the paper: a
   single piece of evidence, in the same card language as the pay options and
   the product packet, so the panel reads as the site's established "answer"
   surface. Compound selector on purpose — `.mkt-trustband .mkt-trust` above
   zeroes border-top and padding-top at (0,2,0), so the panel has to match that
   specificity and sit later in the file to keep its own edge.

   No glyphs on the tiles: a row of six stock pictograms is the fastest way to
   make a stat strip look templated. Each claim gets a short accent rule on its
   left edge instead — the page's one accent used as structure — so the eye can
   tell where one claim ends and the next begins while the display-face number
   stays the loudest thing in the panel. */
.mkt-trust.mkt-trust--panel {
    background: var(--m-card);
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r-lg);
    box-shadow: var(--m-shadow);
    padding: 26px 22px;
}

@media (min-width: 720px) {
    .mkt-trust.mkt-trust--panel { padding: 34px 32px; }
}

.mkt-trust.mkt-trust--panel .mkt-trust__item {
    border-left: 2px solid var(--m-deep);
    padding-left: 14px;
}

/* ---------- Price card (the hero artifact) ----------
   The single most-asked question on this page is "what does it cost?", so the
   hero answers it instead of selling around it. */
.mkt-price {
    background: var(--m-card);
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r-lg);
    box-shadow: var(--m-shadow-lg);
    overflow: hidden;
}

.mkt-price__head {
    padding: 22px 24px 18px;
    border-bottom: 1px solid var(--m-rule);
    background: linear-gradient(180deg, var(--m-wash-soft), transparent);
}

.mkt-price__label {
    font-size: .8125rem;
    font-weight: 500;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--m-deep);
    margin: 0 0 6px;
}

.mkt-price__title {
    font-family: var(--m-display);
    font-size: 1.4rem;
    font-weight: 600;
    letter-spacing: -.012em;
    margin: 0;
}

.mkt-price__rows { list-style: none; margin: 0; padding: 0; }

.mkt-price__row {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 15px 24px;
    border-bottom: 1px solid var(--m-rule);
}

.mkt-price__row:last-child { border-bottom: none; }

.mkt-price__step {
    width: 26px;
    height: 26px;
    flex: none;
    border-radius: 50%;
    background: var(--m-wash);
    color: var(--m-deep);
    font-size: .8125rem;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-top: 1px;
}

.mkt-price__text { min-width: 0; }
.mkt-price__rowtitle { display: block; font-size: .9875rem; font-weight: 500; margin: 0 0 2px; }
.mkt-price__rowdesc { display: block; font-size: .875rem; color: var(--m-ink-3); margin: 0; line-height: 1.5; }

.mkt-price__foot {
    padding: 18px 24px 22px;
    background: var(--m-sunk);
    border-top: 1px solid var(--m-rule);
}

.mkt-price__foot .mkt-btn { width: 100%; }

.mkt-price__fine { margin: 12px 0 0; font-size: .8125rem; color: var(--m-ink-3); text-align: center; }

/* ---------- Steps ---------- */
.mkt-steps {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
    border-top: 1px solid var(--m-rule);
    margin-top: 8px;
}

@media (min-width: 760px) { .mkt-steps { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1040px) { .mkt-steps { grid-template-columns: repeat(4, 1fr); border-top: none; } }

.mkt-step { padding: 24px 0; border-bottom: 1px solid var(--m-rule); }

@media (min-width: 1040px) {
    .mkt-step {
        padding: 26px 26px 30px 0;
        border-top: 1px solid var(--m-rule);
        border-bottom: none;
    }
}

.mkt-step__no {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--m-invert);
    color: #FFF;
    font-size: .8125rem;
    font-weight: 600;
    margin-bottom: 14px;
}

.mkt-step__title { font-size: 1.0625rem; font-weight: 600; margin: 0 0 6px; }
.mkt-step__desc { margin: 0; color: var(--m-ink-2); font-size: .9375rem; max-width: 38ch; }

/* ---------- Cards ---------- */
.mkt-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
}

@media (min-width: 660px) { .mkt-cards { grid-template-columns: 1fr 1fr; gap: 20px; } }
@media (min-width: 1000px) { .mkt-cards--3 { grid-template-columns: repeat(3, 1fr); } }

/* In the two-column band a three-variant leaves its last card beside an empty
   cell; the grid must come out full, so the third spans the row until three
   columns exist. */
@media (min-width: 660px) and (max-width: 999px) {
    .mkt-cards--3 > :nth-child(3) { grid-column: span 2; }
}

/* A four-variant stays two-up. A single row of four equal cards is the shape
   every generated landing page reaches for, and at 1400px it squeezed each
   reason into a 250px column where the heading wrapped and the sentence below
   it ran to five lines. Two-up gives each one a readable measure and reads as a
   considered pair of pairs rather than a row of tiles. */
@media (min-width: 1000px) { .mkt-cards--4 { gap: 22px 24px; } }

.mkt-card {
    background: var(--m-card);
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r);
    padding: 24px 22px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.mkt-card__desc { margin: 0; color: var(--m-ink-2); font-size: .9375rem; }

/* The accent rule as the card's left edge: the same mark the home trust panel
   puts on a claim, where a generated page would put a pictogram. One mark,
   used in two places, reads as the site's signature. */
.mkt-card--marked { border-left: 2px solid var(--m-deep); }

/* ---------- Split feature ---------- */
.mkt-split {
    display: grid;
    grid-template-columns: 1fr;
    gap: 34px;
    align-items: center;
}

@media (min-width: 940px) { .mkt-split { grid-template-columns: 1fr 1fr; gap: 64px; } }

/* Centring only reads as balance when the two columns are a similar height.
   Where one side is a tall photograph, it pushes the other side's heading into
   the middle of nowhere, so those sections top-align instead. */
.mkt-split--top { align-items: start; }

/* Grid and flex children default to min-width:auto, which means a track refuses
   to shrink below its content's max-content width. `.mkt-p` is capped at 66ch,
   which is about 462px, so on a 390px phone the column stayed 462px wide and
   the whole page scrolled sideways. Every measure in this system is set in ch
   for readability, so this has to be declared once for all of them rather than
   chased per component. */
.mkt-split > *,
.mkt-cards > *,
.mkt-directory > *,
.mkt-steps > *,
.mkt-track > *,
.mkt-praise__rail > *,
.mkt-walk__grid > *,
.mkt-notice__grid > *,
.mkt-hero__grid > * { min-width: 0; }

.mkt-list { list-style: none; margin: 22px 0 0; padding: 0; }

/* No rule under each item. A hairline per row is the laziest way to separate a
   list, and this page ran three of them: the checklist here, the cost card, and
   the process directory. The tick already marks where each item starts, so the
   dividers were doing no work that the icon and the spacing were not. */
.mkt-list__item {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 9px 0;
    color: var(--m-ink-2);
    font-size: .975rem;
}

.mkt-list__check {
    width: 20px;
    height: 20px;
    flex: none;
    border-radius: 50%;
    background: var(--m-wash);
    color: var(--m-deep);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-top: 2px;
}

.mkt-list__check svg { width: 11px; height: 11px; }

/* ---------- Quote ---------- */
.mkt-quote {
    background: var(--m-card);
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r);
    padding: 26px 24px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.mkt-quote__text {
    font-family: var(--m-display);
    font-size: 1.14rem;
    font-weight: 400;
    line-height: 1.5;
    letter-spacing: -.008em;
    margin: 0;
}

.mkt-quote__who { display: flex; flex-direction: column; gap: 1px; }
.mkt-quote__name { font-size: .9375rem; font-weight: 600; }
.mkt-quote__meta { font-size: .8125rem; color: var(--m-ink-3); }

/* ---------- Partner logos ---------- */
.mkt-logos {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 26px 44px;
    margin-top: 26px;
}

/* Each mark gets the same box and is contained inside it, rather than every
   mark getting the same height.

   The three backer logos have aspect ratios of 6.8, 2.85 and 1.91. Setting a
   common height made Google for Startups 313px wide against AWS's 88px — one
   logo three and a half times the visual weight of another, which reads as a
   mistake rather than as a row of equals. Constraining both axes evens out the
   width, which is the dimension the eye actually compares in a horizontal row. */
.mkt-logos a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 150px;
    height: 40px;
}

/* Two of the three marks are wrapped in <picture> for their webp source. Left
   alone, the <picture> is the flex item and the img's `max-height: 100%`
   resolves against it rather than against the box, so those two overflowed to
   96px and 64px inside a 50px box while the unwrapped SVG obeyed. `contents`
   drops the wrapper out of the box model and lets the img be the flex item. */
.mkt-logos picture { display: contents; }

.mkt-logos img,
.mkt-logos svg {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    opacity: .55;
    filter: grayscale(1);
    transition: opacity .2s ease, filter .2s ease;
}

.mkt-logos a:hover img { opacity: .9; filter: grayscale(0); }

/* ---------- Closing CTA ---------- */
.mkt-cta {
    background: var(--m-invert);
    color: #EAF2F1;
    border-radius: var(--m-r-lg);
    padding: 44px 26px;
    text-align: center;
}

@media (min-width: 880px) { .mkt-cta { padding: 64px 48px; } }

.mkt-cta .mkt-h2 { color: #FFF; margin-left: auto; margin-right: auto; }
.mkt-cta .mkt-lede { color: rgba(234, 242, 241, .74); margin-left: auto; margin-right: auto; }
.mkt-cta .mkt-actions { justify-content: center; margin-top: 28px; }

.mkt-cta .mkt-btn { background: var(--m-teal); border-color: var(--m-teal); color: #04282A; }
.mkt-cta .mkt-btn:hover { background: #7BE6EC; border-color: #7BE6EC; }

/* ---------- Footer ---------- */
.mkt-foot {
    background: var(--m-invert);
    color: rgba(234, 242, 241, .66);
    padding: 52px 0 40px;
    font-size: .9375rem;
}

.mkt-foot__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 30px;
}

/* Four groups, so three columns orphaned Resources onto a second row under the
   blurb and left two thirds of the footer empty beside it. Two-up in the middle
   range, four-up once there is room for all of them on one line. */
@media (min-width: 760px) { .mkt-foot__grid { grid-template-columns: 1.4fr 1fr 1fr; gap: 40px 44px; } }
@media (min-width: 1000px) { .mkt-foot__grid { grid-template-columns: 1.6fr 1fr 1fr 1fr; } }

.mkt-foot__logo { height: 22px; width: auto; opacity: .92; margin-bottom: 14px; }
.mkt-foot__blurb { margin: 0; max-width: 34ch; font-size: .9375rem; line-height: 1.6; }

.mkt-foot__title {
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgba(234, 242, 241, .5);
    margin: 0 0 12px;
}

.mkt-foot__links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
/* `.mkt` prefix is load-bearing. The footer links carry no class attribute, so
   the base rule `.mkt a:not([class])` matches them, and `:not([class])` counts
   as an attribute selector: (0,2,1) against this rule's (0,1,1). Without the
   prefix the base rule wins and the footer renders deep teal on near-black at
   2.07:1. Dark mode hid it, because --m-deep flips light there. */
.mkt .mkt-foot__links a { color: rgba(234, 242, 241, .8); text-decoration: none; }
.mkt .mkt-foot__links a:hover { color: #FFF; }

.mkt-foot__fine {
    margin: 34px 0 0;
    padding-top: 22px;
    border-top: 1px solid rgba(234, 242, 241, .14);
    font-size: .8125rem;
    line-height: 1.6;
    color: rgba(234, 242, 241, .5);
    max-width: 92ch;
}

/* ---------- Reveal ----------
   22px over 700ms, not 14px over 600. At 14px the movement finished inside the
   eye's saccade and the reveal read as a flicker rather than an entrance; a
   heavier travel on the same curve is what makes the motion legible. The curve
   front-loads the speed, so the longer duration reads as settling, not lag. */
.js .mkt [data-reveal] {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity .7s cubic-bezier(.22, .61, .36, 1), transform .7s cubic-bezier(.22, .61, .36, 1);
}

.js .mkt [data-reveal].is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
    .js .mkt [data-reveal] {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
    .mkt *, .mkt *::before, .mkt *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
    }
}

/* =========================================================================
   Product pages
   -------------------------------------------------------------------------
   These pages answer two questions the home page cannot: what am I actually
   filing, and what happens after I mail it. Both are rendered as real
   artifacts rather than marketing blocks — the packet is the stack of USCIS
   forms with their real numbers, and the timeline is honest about which part
   Alvva controls and which part is USCIS waiting time.
   ========================================================================= */

/* ---------- The packet ---------- */
.mkt-packet {
    background: var(--m-card);
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r-lg);
    box-shadow: var(--m-shadow-lg);
    overflow: hidden;
}

.mkt-packet__head {
    padding: 20px 24px 16px;
    border-bottom: 1px solid var(--m-rule);
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.mkt-packet__title {
    font-family: var(--m-display);
    font-size: 1.22rem;
    font-weight: 600;
    letter-spacing: -.012em;
    margin: 0;
}

.mkt-packet__count {
    font-size: .8125rem;
    font-weight: 500;
    color: var(--m-deep);
    background: var(--m-wash);
    border-radius: 999px;
    padding: 4px 11px;
    white-space: nowrap;
    /* Tabular figures stop the count jittering between locales. */
    font-variant-numeric: tabular-nums;
}

.mkt-packet__list { list-style: none; margin: 0; padding: 0; }

.mkt-packet__form {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    gap: 4px 14px;
    padding: 13px 24px;
    border-bottom: 1px solid var(--m-rule);
}

.mkt-packet__no {
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--m-ink);
    font-variant-numeric: tabular-nums;
    background: var(--m-sunk);
    border-radius: 6px;
    padding: 4px 9px;
    white-space: nowrap;
}

.mkt-packet__name { font-size: .9375rem; color: var(--m-ink-2); }

.mkt-packet__foot {
    padding: 16px 24px 20px;
    background: var(--m-sunk);
    font-size: .875rem;
    color: var(--m-ink-3);
    line-height: 1.55;
}

/* ---------- After you file ----------
   Deliberately two-tone: the steps Alvva is responsible for read in ink, the
   ones that are USCIS waiting read in teal outline. Nobody else on the page
   tells people which part is out of everyone's hands. */
.mkt-track { list-style: none; margin: 26px 0 0; padding: 0; position: relative; }

.mkt-track::before {
    content: "";
    position: absolute;
    left: 13px;
    top: 8px;
    bottom: 8px;
    width: 2px;
    background: linear-gradient(180deg, var(--m-ink) 0%, var(--m-teal) 45%, var(--m-rule-2) 100%);
    border-radius: 2px;
}

@media (min-width: 900px) {
    .mkt-track {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 24px;
        margin-top: 34px;
    }
    .mkt-track::before {
        left: 0; right: 0; top: 13px; bottom: auto;
        width: auto; height: 2px;
        background: linear-gradient(90deg, var(--m-ink) 0%, var(--m-teal) 45%, var(--m-rule-2) 100%);
    }
}

.mkt-track__stop { position: relative; padding: 0 0 24px 42px; }

@media (min-width: 900px) { .mkt-track__stop { padding: 40px 16px 0 0; } }

.mkt-track__dot {
    position: absolute;
    left: 6px; top: 4px;
    width: 16px; height: 16px;
    border-radius: 50%;
    background: var(--m-invert);
    border: 3px solid var(--m-paper);
    box-shadow: 0 0 0 2px var(--m-ink);
}

@media (min-width: 900px) { .mkt-track__dot { left: 0; top: 6px; } }

.mkt-track__stop--wait .mkt-track__dot {
    background: var(--m-paper);
    box-shadow: 0 0 0 2px var(--m-teal-mid);
}

.mkt-track__who {
    display: inline-block;
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--m-deep);
    margin-bottom: 5px;
}

.mkt-track__stop--wait .mkt-track__who { color: var(--m-ink-3); }

.mkt-track__title { font-size: 1rem; font-weight: 600; margin: 0 0 4px; }
.mkt-track__desc { margin: 0; font-size: .9375rem; color: var(--m-ink-2); max-width: 34ch; }

/* ---------- FAQ ---------- */
.mkt-faqs { border-top: 1px solid var(--m-rule); max-width: 58rem; margin-top: 8px; }

.mkt-faq { border-bottom: 1px solid var(--m-rule); }

.mkt-faq summary {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 20px;
    /* 44px minimum touch target, per the app UI guidance. */
    padding: 20px 0;
    min-height: 44px;
    cursor: pointer;
    list-style: none;
    font-family: var(--m-display);
    font-size: 1.16rem;
    font-weight: 600;
    letter-spacing: -.01em;
    transition: color .16s ease;
}

.mkt-faq summary::-webkit-details-marker { display: none; }
.mkt-faq summary:hover { color: var(--m-deep); }

.mkt-faq__sign {
    font-size: 1.4rem;
    font-weight: 400;
    color: var(--m-ink-3);
    flex: none;
    line-height: 1;
    transform: translateY(2px);
    transition: transform .2s ease, color .2s ease;
}

.mkt-faq[open] .mkt-faq__sign { transform: translateY(2px) rotate(45deg); color: var(--m-deep); }

/* Opening: the answer rises in rather than snapping. The keyframe runs in
   every browser (a <details> renders its content on open, which restarts the
   animation); the real height glide underneath is progressive enhancement for
   engines with interpolate-size, and everywhere else the fade carries it. The
   global reduced-motion block zeroes both. */
.mkt-faq[open] .mkt-faq__body { animation: mkt-faq-open .38s cubic-bezier(.22, .61, .36, 1); }

@keyframes mkt-faq-open {
    from { opacity: 0; transform: translateY(-5px); }
}

@supports (interpolate-size: allow-keywords) {
    .mkt-faqs { interpolate-size: allow-keywords; }

    .mkt-faq::details-content {
        block-size: 0;
        overflow-y: clip;
        transition: content-visibility .38s allow-discrete, block-size .38s cubic-bezier(.22, .61, .36, 1);
    }

    .mkt-faq[open]::details-content { block-size: auto; }
}

.mkt-faq__body { margin: 0; padding: 0 0 22px; color: var(--m-ink-2); max-width: 62ch; }

/* Answers are written in the admin's rich-text editor, so the body is markup,
   not a sentence: paragraphs, lists and links all arrive from CKEditor. The
   editor emits bare tags with no classes, hence the element selectors here —
   this is the one block in the system that styles what someone else authored. */
.mkt-faq__body > :first-child { margin-top: 0; }
.mkt-faq__body > :last-child { margin-bottom: 0; }
.mkt-faq__body p { margin: 0 0 12px; }
.mkt-faq__body ul,
.mkt-faq__body ol { margin: 0 0 12px; padding-left: 1.25em; }
.mkt-faq__body li { margin: 4px 0; }
.mkt-faq__body ul { list-style: disc; }
.mkt-faq__body ol { list-style: decimal; }
.mkt-faq__body strong, .mkt-faq__body b { font-weight: 600; color: var(--m-ink); }
/* Three classes deep on purpose. These anchors are typed by an admin, so they
   never carry a class, which puts them in range of `.mkt a:not([class])` at
   (0,2,1) — a plain `.mkt-faq__body a` would lose to it and these declarations
   would silently do nothing. */
.mkt .mkt-faqs .mkt-faq__body a { color: var(--m-deep); text-decoration: underline; text-underline-offset: 2px; }
.mkt .mkt-faqs .mkt-faq__body a:hover { color: var(--m-teal-mid); }

/* Same story for anchors written inside lang-file copy (the recruiting email
   on about-us): no class, so they need to outrank `.mkt a:not([class])` at
   (0,2,1) — equal specificity, later in the file, wins on order. */
.mkt .mkt-p a { color: var(--m-deep); text-decoration: underline; text-underline-offset: 2px; }
.mkt .mkt-p a:hover { color: var(--m-teal-mid); }

/* ---------- Announcement banner ----------
   Sits above the header, so it is the first thing on the page and has to look
   deliberate rather than like a cookie bar. Deep teal ground: white on
   #00595D is 8.1:1, which leaves room for the underlined link to stay legible
   at small size. */
.mkt-banner {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 10px calc(var(--m-gutter) + 4px);
    background: var(--m-deep);
    color: #fff;
}

.mkt-banner[hidden] { display: none; }

.mkt-banner__text {
    flex: 1 1 auto;
    margin: 0;
    text-align: center;
    font-size: .95rem;
    line-height: 1.45;
}

.mkt-banner__link { color: #fff; text-decoration: underline; text-underline-offset: 2px; }
.mkt-banner__link:hover { color: var(--m-wash); }
.mkt-banner__text p { margin: 0; display: inline; }

.mkt-banner__close {
    flex: none;
    /* 44px target on touch, without a 44px-tall bar on desktop: the padding
       does the work and the negative margin keeps the strip slim. */
    padding: 14px;
    margin: -14px -8px -14px 0;
    background: none;
    border: 0;
    color: #fff;
    opacity: .78;
    cursor: pointer;
    line-height: 0;
    transition: opacity .16s ease;
}

.mkt-banner__close:hover { opacity: 1; }
.mkt-banner__close:focus-visible { outline: 2px solid #fff; outline-offset: -2px; border-radius: 4px; }

@media (max-width: 640px) {
    .mkt-banner__text { text-align: left; font-size: .9rem; }
}

/* =========================================================================
   How it works — the time budget
   -------------------------------------------------------------------------
   The honest question behind "how does it work" is "how much of MY time does
   this take, and when am I just waiting". Each phase states its own cost in
   the visitor's time, which is the number nobody else publishes.
   ========================================================================= */

.mkt-budget { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--m-rule); }

.mkt-budget__row {
    display: grid;
    grid-template-columns: 1fr;
    gap: 6px;
    padding: 24px 0;
    border-bottom: 1px solid var(--m-rule);
}

@media (min-width: 820px) {
    .mkt-budget__row {
        grid-template-columns: 8.5rem minmax(0, 20rem) 1fr;
        gap: 32px;
        align-items: baseline;
    }
}

.mkt-budget__time {
    font-family: var(--m-display);
    font-size: 1.28rem;
    font-weight: 600;
    letter-spacing: -.012em;
    color: var(--m-ink);
    font-variant-numeric: tabular-nums;
}

.mkt-budget__time--wait { color: var(--m-ink-3); font-weight: 400; }

.mkt-budget__title { font-size: 1.0625rem; font-weight: 600; margin: 0; }
.mkt-budget__desc { margin: 0; color: var(--m-ink-2); font-size: .9375rem; max-width: 48ch; }

/* ---------- Comparison table ----------
   Honest by construction: every comparison carries a row for when the other
   option is the better one. A table that never says that is an advert. */
.mkt-compare { margin-top: 8px; border-top: 1px solid var(--m-rule); }

.mkt-compare__row {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
    padding: 22px 0;
    border-bottom: 1px solid var(--m-rule);
}

@media (min-width: 820px) {
    .mkt-compare__row {
        grid-template-columns: 13rem 1fr 1fr;
        gap: 30px;
        align-items: start;
    }
}

.mkt-compare__label {
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--m-ink-3);
}

.mkt-compare__cell { font-size: .9688rem; color: var(--m-ink-2); }

.mkt-compare__cell--ours {
    color: var(--m-ink);
    font-weight: 500;
}

.mkt-compare__who {
    display: block;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--m-deep);
    margin-bottom: 4px;
}

.mkt-compare__cell--other .mkt-compare__who { color: var(--m-ink-3); }

/* The row that admits the other option wins. */
.mkt-compare__row--honest {
    background: var(--m-amber-soft);
    border-radius: var(--m-r);
    padding: 22px 20px;
    border-bottom: none;
    margin-top: 8px;
}

@media (min-width: 820px) { .mkt-compare__row--honest { padding: 24px 26px; } }

.mkt-compare__row--honest .mkt-compare__label { color: #A9540F; }

/* ---------- Quote with a face ----------
   A real customer photograph next to a real approval date does more for trust
   than any headline. Sized and reserved so the layout does not shift as it
   loads. */
.mkt-quote__person { display: flex; align-items: center; gap: 13px; }

.mkt-quote__avatar {
    width: 46px;
    height: 46px;
    flex: none;
    border-radius: 50%;
    object-fit: cover;
    background: var(--m-sunk);
    border: 1px solid var(--m-rule);
}

/* ---------- Process directory ----------
   These rows carry what a person actually needs in order to choose: who the
   process is for, and which forms it involves — the same form numbers the
   product page then shows in full.

   Cards, not table rows. The previous build laid this out as a hairline table:
   a `1fr auto` grid with a border under every row. Two things were wrong with
   it. On desktop it was the third hairline list on the page, which is what made
   the most important section on the site read as filler. On a phone it broke
   outright — the `auto` column sized itself to the description, squeezing the
   product name into about 90px so "Marriage Green Card" wrapped onto three
   lines, and stacking the six form pills one per line underneath.

   The card grid fixes both at once, and it collapses to a single column by
   default rather than needing a breakpoint to undo a desktop layout. */
.mkt-directory {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
    margin-top: 10px;
}

/* The grid must come out full: a hole in the last row reads as a card that
   failed to load. The list is not always the same length, though — the home
   page and the product pages show five processes, the comparison pages show
   three — so the wide first cell is a quantity query rather than a blanket
   `:first-child`. `:first-child:nth-last-child(n)` matches only when the
   container holds exactly n children.

     two columns:  3 -> [wide] / [a][b]         5 -> [wide] / [a][b] / [c][d]
                   8 -> four full rows, no wide cell needed
     three columns: 3 -> [a][b][c]              5 -> [wide][a] / [b][c][d]
                   8 -> [wide][a] / [b][c][d] / [e][f][g]

   Marriage green card leads the list and is also the largest process by
   volume, so the cell that earns the extra width is the right one. */
@media (min-width: 700px) {
    .mkt-directory { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }

    .mkt-dir:first-child:nth-last-child(3),
    .mkt-dir:first-child:nth-last-child(5) { grid-column: span 2; }
}

@media (min-width: 1040px) {
    .mkt-directory { grid-template-columns: repeat(3, minmax(0, 1fr)); }

    /* Three fills a row on its own at this width, so the wide cell would put
       two holes in the second row. Five and eight still want it: eight at
       three columns is 3 + 3 + 2 with a hole, and the wide first cell turns
       it into three full rows. */
    .mkt-dir:first-child:nth-last-child(3) { grid-column: auto; }
    .mkt-dir:first-child:nth-last-child(5),
    .mkt-dir:first-child:nth-last-child(8) { grid-column: span 2; }
}

.mkt-dir {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 9px;
    padding: 24px 22px;
    background: var(--m-card);
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r);
    text-decoration: none;
    color: inherit;
    transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}

a.mkt-dir:hover {
    border-color: var(--m-rule-2);
    box-shadow: var(--m-shadow);
    transform: translateY(-2px);
}

/* A directory card without a page yet: same surface, no link affordance. */
.mkt-dir--static { cursor: default; }

.mkt-dir__name {
    font-family: var(--m-display);
    font-size: 1.28rem;
    font-weight: 600;
    letter-spacing: -.012em;
    margin: 0;
}

/* Grows so the form tags and the arrow settle on a common baseline across a
   row of cards whose descriptions run to different lengths. */
.mkt-dir__desc { margin: 0; color: var(--m-ink-2); font-size: .9375rem; max-width: 46ch; flex: 1 1 auto; }

.mkt-dir__forms { display: flex; flex-wrap: wrap; gap: 6px; }

.mkt-dir__tag {
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--m-ink-2);
    background: var(--m-sunk);
    border-radius: 5px;
    padding: 3px 8px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Shown at every width now. It used to be hidden below 860px because the table
   layout had nowhere to put it; inside a card there is room, and it is the only
   thing marking these as links rather than panels. */
.mkt-dir__go {
    color: var(--m-deep);
    flex: none;
    /* Bottom-right rather than under the tags on the left, where it read as a
       stray glyph the tag row had dropped. */
    align-self: flex-end;
    margin-top: 2px;
    transition: transform .16s ease;
}

a.mkt-dir:hover .mkt-dir__go { transform: translateX(4px); }

/* The wide cell carries a wash so a grid of five is not five identical white
   rectangles. The tint is the same one the card icons and the cost-card header
   already use, so it reads as the system rather than as decoration.

   It tracks the span exactly: a card that is not wider than its neighbours has
   not earned a different background, and tinting one of three otherwise equal
   cards just looks like a mistake. Hence the same quantity queries, and the
   three-item case dropping the tint at the width where it stops spanning. */
@media (min-width: 700px) {
    .mkt-dir:first-child:nth-last-child(3),
    .mkt-dir:first-child:nth-last-child(5) {
        background: linear-gradient(150deg, var(--m-wash) -18%, var(--m-wash-soft) 46%, var(--m-card) 92%);
        border-color: rgba(0, 120, 126, .18);
    }

    .mkt-dir:first-child:nth-last-child(3) .mkt-dir__desc,
    .mkt-dir:first-child:nth-last-child(5) .mkt-dir__desc { max-width: 52ch; }
}

@media (min-width: 1040px) {
    .mkt-dir:first-child:nth-last-child(3) {
        background: var(--m-card);
        border-color: var(--m-rule);
    }

    /* Eight spans only at three columns, so the tint arrives here too. */
    .mkt-dir:first-child:nth-last-child(8) {
        background: linear-gradient(150deg, var(--m-wash) -18%, var(--m-wash-soft) 46%, var(--m-card) 92%);
        border-color: rgba(0, 120, 126, .18);
    }

    .mkt-dir:first-child:nth-last-child(8) .mkt-dir__desc { max-width: 52ch; }
}

/* ---------- Praise ----------
   One real customer, at the size a real customer deserves. Padding a thin
   set of quotes into a three-card grid is how testimonial sections start
   looking invented. */
.mkt-praise { background: var(--m-invert); color: #EAF2F1; }

.mkt-praise__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 30px;
    align-items: center;
}

@media (min-width: 900px) { .mkt-praise__grid { grid-template-columns: auto 1fr; gap: 52px; } }

.mkt-praise__portrait {
    width: 132px;
    height: 132px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid rgba(199, 242, 244, .28);
    background: var(--m-ink-2);
}

@media (min-width: 900px) { .mkt-praise__portrait { width: 168px; height: 168px; } }

.mkt-praise .mkt-eyebrow { color: var(--m-teal); }
.mkt-praise .mkt-eyebrow::before { background: var(--m-teal); }

.mkt-praise__quote {
    font-family: var(--m-display);
    font-weight: 400;
    font-size: clamp(1.3rem, 2.5vw, 1.95rem);
    line-height: 1.34;
    letter-spacing: -.014em;
    color: #FFF;
    margin: 0 0 22px;
    max-width: 30ch;
}

.mkt-praise__name { font-size: 1rem; font-weight: 600; color: #FFF; margin: 0; }
.mkt-praise__meta { font-size: .9375rem; color: rgba(234, 242, 241, .68); margin: 2px 0 0; }

.mkt-praise__links { display: flex; flex-wrap: wrap; gap: 14px 24px; margin-top: 22px; }

.mkt-praise__link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: .9375rem;
    font-weight: 500;
    color: var(--m-teal);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    padding-bottom: 2px;
    /* 44px target with the padding above and below the label. */
    min-height: 44px;
}

.mkt-praise__link:hover { color: #9DEEF3; border-bottom-color: #9DEEF3; }

/* The no-testimonials fallback: the same strip on paper rather than a
   full-width inversion. It sits between two light sections, so it is separated
   by rules instead of by a colour change, and the link and eyebrow revert to
   the on-paper teal — `--m-teal` at .9375rem on near-white is well under AA,
   which is exactly the near-miss the token comments at the top of this file
   warn about. `--m-deep` is the step that clears it. */
.mkt-praise--slim {
    background: transparent;
    color: var(--m-ink);
    border-top: 1px solid var(--m-rule);
    border-bottom: 1px solid var(--m-rule);
    padding-top: 30px;
    padding-bottom: 30px;
}

.mkt-praise--slim .mkt-eyebrow { color: var(--m-deep); margin-bottom: 6px; }
.mkt-praise--slim .mkt-eyebrow::before { background: var(--m-teal); }
.mkt-praise--slim .mkt-praise__link { color: var(--m-deep); }
.mkt-praise--slim .mkt-praise__link:hover { color: var(--m-ink); border-bottom-color: var(--m-ink); }

/* Inline Trustpilot mark inside a praise link. */
.mkt-tp { display: inline-flex; align-items: center; gap: 6px; }
.mkt-tp__star { display: block; border-radius: 3px; }
.mkt-tp__word { font-weight: 700; letter-spacing: -.01em; }

/* =========================================================================
   The USCIS "no second chance" notice
   -------------------------------------------------------------------------
   The one section on the site that carries a warning, so it is the one place
   the amber token appears. Functional colour, never decorative: it is paired
   with a shape (the triangle) and with words, so it still reads for anyone who
   cannot separate amber from the paper behind it.

   Deliberately not red and not a full-bleed alarm. The audience is people
   already anxious about a legal filing; the job is to make a real change
   legible, not to frighten someone into converting.
   ========================================================================= */
.mkt-notice {
    background: var(--m-amber-soft);
    border-top: 1px solid rgba(255, 154, 66, .38);
    border-bottom: 1px solid rgba(255, 154, 66, .38);
}

.mkt-notice__grid { display: grid; grid-template-columns: 1fr; gap: 32px; }

@media (min-width: 940px) {
    .mkt-notice__grid { grid-template-columns: 1.35fr 1fr; gap: 56px; align-items: start; }
}

/* A status pill, not an eyebrow: it states a dated policy change rather than
   naming the section, which is why it survives the one-per-three cap. */
.mkt-notice__flag {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 16px;
    padding: 7px 14px 7px 12px;
    border-radius: 999px;
    background: #7A3B06;
    color: #FFF3E6;
    font-size: .8125rem;
    font-weight: 600;
}

.mkt-notice__h2 { margin: 0 0 14px; max-width: 20ch; }

.mkt-notice__source {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-top: 20px;
    color: #8A4708;
    font-size: .9375rem;
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid rgba(138, 71, 8, .34);
    padding-bottom: 2px;
}

.mkt-notice__source:hover { color: #5E3005; border-bottom-color: #5E3005; }

.mkt-notice__points { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }

/* The grid top-aligns both columns, so three short consequences beside five
   lines of policy left about 190px of bare amber under the last card. Stretched
   and spaced, they read as a column against the explanation rather than as a
   block that ran out. Only above the breakpoint: stacked, there is nothing to
   distribute. */
@media (min-width: 940px) {
    .mkt-notice__points { align-self: stretch; align-content: space-between; }
}

.mkt-notice__point {
    padding: 16px 18px;
    border-radius: var(--m-r);
    background: rgba(255, 255, 255, .74);
    border: 1px solid rgba(255, 154, 66, .3);
    font-size: .96875rem;
    line-height: 1.55;
    color: var(--m-ink-2);
}

.mkt-notice__close {
    margin-top: 36px;
    padding-top: 28px;
    border-top: 1px solid rgba(255, 154, 66, .34);
    display: grid;
    gap: 20px;
}

@media (min-width: 940px) {
    .mkt-notice__close { grid-template-columns: 1fr auto; gap: 40px; align-items: center; }
}

.mkt-notice__closetext { margin: 0; max-width: 66ch; font-size: 1rem; line-height: 1.62; color: var(--m-ink-2); }

/* ---------- Several testimonials ----------
   One testimonial keeps the portrait-and-large-quote treatment above. Two or
   three become a rail of quotes, because a single card floating in a wide dark
   band looks like the other two failed to load.

   Deliberately not a carousel: the one on the old pages auto-rotates every 5s
   and is built on fixed pixel widths (800px per slide), so on a phone it both
   hides most of the proof and has to be re-measured on resize. Three quotes
   side by side are all readable at once and need no JavaScript. */
.mkt-praise__h2 { color: #FFF; margin: 6px 0 0; max-width: 22ch; }

/* A snap strip, not a grid. Admins add quotes in the Backpack CRUD and the
   band has to absorb however many exist: the grid put four or five cards into
   uneven rows with an orphan, and nothing ever moved. As a strip, up to three
   fit exactly as the grid did; past three the extras sit off the right edge,
   the layout script advances the strip while nobody is interacting with it,
   and a swipe works everywhere. Cards keep their width instead of dividing
   into whatever columns the count allows.

   The scrollbar is hidden on purpose: the rotation and the mobile peek are the
   affordance, and the rail is keyboard-reachable via tabindex in the template. */
.mkt-praise__rail {
    display: flex;
    gap: 18px;
    margin-top: 34px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 4px;
}

.mkt-praise__rail::-webkit-scrollbar { display: none; }

/* 86vw on a phone leaves the next card peeking in from the edge, which is what
   tells a thumb the strip scrolls. */
.mkt-praise__card { flex: 0 0 min(86vw, 340px); scroll-snap-align: start; }

@media (min-width: 760px) { .mkt-praise__card { flex-basis: calc((100% - 18px) / 2); } }
@media (min-width: 1060px) { .mkt-praise__card { flex-basis: calc((100% - 36px) / 3); } }

/* Named under the block on purpose. `.mkt-quote` above is the inline
   testimonial that sits on a light section (home, about-us); these cards live
   on the dark band and set white text. Reusing that name put a later rule of
   equal specificity on top of it and turned those quotes white-on-cream. */
.mkt-praise__card {
    margin: 0;
    padding: 26px 26px 22px;
    border: 1px solid rgba(234, 242, 241, .16);
    border-radius: var(--m-r-lg);
    background: rgba(255, 255, 255, .04);
    display: flex;
    flex-direction: column;
    gap: 18px;
}

/* Long quotes are the admin's business, not the layout's — the card grows
   rather than truncating behind a "read more" nobody clicks. */
.mkt-praise__cardquote {
    margin: 0;
    font-size: 1.0625rem;
    line-height: 1.62;
    color: rgba(234, 242, 241, .92);
}

.mkt-praise__by {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: auto;
    padding-top: 4px;
}

.mkt-praise__face {
    width: 48px;
    height: 48px;
    border-radius: 999px;
    object-fit: cover;
    flex: none;
    background: rgba(234, 242, 241, .1);
}

.mkt-praise__cardname { display: block; font-size: .9375rem; font-weight: 600; color: #FFF; }
.mkt-praise__cardmeta { display: block; font-size: .8125rem; color: rgba(234, 242, 241, .6); margin-top: 1px; }

/* ---------- Backer logos ----------
   Were rendering at 26px and 55% opacity, which read as an apology. These are
   real accelerators and worth showing at a legible size.

   Scale is set on the anchor box, never on the image height: the base rule
   further up explains why a shared height makes a 6.8:1 wordmark three and a
   half times the width of a 1.91:1 one. This block only enlarges the box and
   lifts the opacity. */
.mkt-logos { gap: 30px 52px; margin-top: 30px; }

.mkt-logos a { width: 164px; height: 44px; }

.mkt-logos img, .mkt-logos svg { opacity: .8; filter: grayscale(1); }

.mkt-logos a:hover img, .mkt-logos a:hover svg { opacity: 1; filter: none; }

@media (min-width: 720px) {
    .mkt-logos a { width: 184px; height: 50px; }
}

/* ---------- Hero media ----------
   A photograph of people. On product pages the packet card overlaps its lower
   edge; the home hero shows the photograph alone since the cost card moved
   off the page. The photo is the cropped subject from
   assets/hero_section_en.png — the original composite also bakes an old app
   mockup and price claims into the pixels. */
.mkt-hero__media { position: relative; }

/* The source frame is shot against a salmon backdrop, which sits badly beside
   the teal accent and the warm paper: three unrelated hues in the first screen.
   Correcting it rather than replacing the asset — saturate() pulls the backdrop
   toward the paper while leaving skin tones alone, where a tint overlay would
   have greyed the faces out. */
.mkt-hero__photo {
    width: 100%;
    height: auto;
    aspect-ratio: 5 / 4;
    object-fit: cover;
    object-position: center 28%;
    border-radius: var(--m-r-lg);
    background: var(--m-sunk);
    box-shadow: var(--m-shadow);
    filter: saturate(.82) contrast(1.02);
}

/* Flush at every width, for the reason in the desktop block below: an inset
   card leaves a strip of the photograph's backdrop showing down both sides,
   and on a phone that strip is the widest thing competing with the price.

   The one hero artifact left is the packet on the six product pages — a
   photograph with the page's one concrete answer riding up over its lower
   edge. */
.mkt-hero__media .mkt-packet {
    position: relative;
    margin: -52px auto 0;
    width: 100%;
}

@media (min-width: 560px) {
    .mkt-hero__media .mkt-packet { margin-top: -64px; }
}

/* 4:3 at desktop — the asset's native frame. The old 3:2 crop existed to
   keep the photo short enough that the cost card stayed on the first screen;
   with the card gone the photo can breathe, and 4:3 still holds the media
   column near the headline column's height. */
@media (min-width: 980px) {
    .mkt-hero__photo { aspect-ratio: 4 / 3; }
}

/* =========================================================================
   Motion
   -------------------------------------------------------------------------
   Transform and opacity only, so nothing animates layout. Entrances ease out
   over 500ms; lists stagger 45ms per item, which reads as one movement rather
   than a queue. Everything below is disabled wholesale under
   prefers-reduced-motion by the block at the end of this file.
   ========================================================================= */

/* A list or grid whose children arrive in sequence. The index is set inline
   per item so the delay survives any DOM order the template produces.

   65ms per item, up from 45: below ~50ms the steps blur into one movement and
   the sequence stops reading as a sequence. Travel and duration scale up with
   the base reveal for the same legibility reason. */
.js .mkt [data-stagger] > * {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .6s cubic-bezier(.22, .61, .36, 1), transform .6s cubic-bezier(.22, .61, .36, 1);
    transition-delay: calc(var(--i, 0) * 65ms);
}

.js .mkt [data-stagger].is-visible > * { opacity: 1; transform: none; }

/* The hero plays once on load rather than on scroll — it is already in view,
   and waiting for an observer would make it flash. */
.js .mkt-hero__intro > * {
    opacity: 0;
    transform: translateY(14px);
    animation: mkt-rise .62s cubic-bezier(.22, .61, .36, 1) forwards;
}

.js .mkt-hero__intro > *:nth-child(1) { animation-delay: .04s; }
.js .mkt-hero__intro > *:nth-child(2) { animation-delay: .10s; }
.js .mkt-hero__intro > *:nth-child(3) { animation-delay: .16s; }
.js .mkt-hero__intro > *:nth-child(4) { animation-delay: .22s; }
.js .mkt-hero__intro > *:nth-child(5) { animation-delay: .28s; }
.js .mkt-hero__intro > *:nth-child(6) { animation-delay: .34s; }

.js .mkt-hero__media {
    opacity: 0;
    transform: translateY(18px) scale(.985);
    animation: mkt-rise-media .72s cubic-bezier(.22, .61, .36, 1) .12s forwards;
}

@keyframes mkt-rise { to { opacity: 1; transform: none; } }
@keyframes mkt-rise-media { to { opacity: 1; transform: none; } }

/* Staggered rows inside the hero artifact (the packet's forms on product
   pages) wait for the card itself to land before they start: the media
   column's rise runs .12s + .72s, so the first row begins as it settles. The
   90ms cadence is deliberately slower than the page default. These rows are
   the artifact's content, and the slower beat reads as the card being filled
   in rather than as a list arriving. */
.js .mkt-hero__media [data-stagger] > * {
    transition-delay: calc(.55s + var(--i, 0) * 90ms);
}

/* ---------- Trust strip: claim first, caption second ----------
   The six tiles drop the generic fade-up for a two-beat entrance: the value
   ("Up to 5x less") lands, and its caption follows 140ms behind. The delay
   between the beats is what makes each claim read as a claim with support
   rather than as two lines of text arriving together.

   The tile itself stops animating so the beats are not nested inside a third
   movement. Same specificity as the base [data-stagger] rule, so order in this
   file is what makes these win; they must stay below it. The spans inherit
   --i from the tile's inline style. */
.js .mkt-trustband [data-stagger] > * {
    opacity: 1;
    transform: none;
    transition: none;
}

.js .mkt-trustband [data-stagger] .mkt-trust__value,
.js .mkt-trustband [data-stagger] .mkt-trust__label {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity .6s cubic-bezier(.22, .61, .36, 1), transform .6s cubic-bezier(.22, .61, .36, 1);
    transition-delay: calc(var(--i, 0) * 90ms);
}

.js .mkt-trustband [data-stagger] .mkt-trust__label {
    transform: translateY(10px);
    transition-delay: calc(var(--i, 0) * 90ms + 140ms);
}

.js .mkt-trustband [data-stagger].is-visible .mkt-trust__value,
.js .mkt-trustband [data-stagger].is-visible .mkt-trust__label {
    opacity: 1;
    transform: none;
}

/* ---------- Headline word reveal ----------
   The page-load signature, and the only element on the site with choreography
   of its own: the hero headline arrives a word at a time.

   The heading is hidden before paint (`.js` is set in <head>) and the script in
   layouts/marketing.blade.php swaps its text for per-word spans. If that script
   never runs, never gets that far, or throws, the headline is marked visible and
   simply appears — nothing here is load-bearing for reading the page.

   Words, not characters. Per-character splitting turns a nine-word Spanish
   headline into sixty animating elements, which reads as a gimmick and takes
   long enough that the first thing a visitor does is wait. Keeping the spaces
   as real text nodes also means the browser finds the same break opportunities
   it always did, so the heading wraps identically and nothing shifts. */
.js .mkt [data-split] { opacity: 0; }
.js .mkt [data-split].is-split,
.js .mkt [data-split].is-visible { opacity: 1; }

.js .mkt [data-split].is-split .mkt-word {
    display: inline-block;
    opacity: 0;
    transform: translateY(.4em) rotate(1.5deg);
    animation: mkt-word-in .56s cubic-bezier(.22, .61, .36, 1) forwards;
    animation-delay: calc(var(--i, 0) * 42ms);
}

@keyframes mkt-word-in { to { opacity: 1; transform: none; } }

/* The home hero animates its children as blocks. The headline opts out of that
   so the words carry the movement instead of the whole line sliding up under
   them. Specificity is the point: `.js .mkt-hero__intro > *` (0,2,0) sets both
   properties, so this rule (0,3,0) has to outrank it — while deliberately not
   touching opacity, which the [data-split] rules above own. */
.js .mkt-hero__intro > [data-split] { animation: none; transform: none; }

/* Cards and directory rows lift slightly on hover — the only motion that is
   not an entrance, and it exists to say "this is a link". */
.mkt-card { transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
a.mkt-card:hover { transform: translateY(-2px); box-shadow: var(--m-shadow); border-color: var(--m-rule-2); }

@media (prefers-reduced-motion: reduce) {
    .js .mkt [data-stagger] > *,
    .js .mkt-trustband [data-stagger] .mkt-trust__value,
    .js .mkt-trustband [data-stagger] .mkt-trust__label,
    .js .mkt-hero__intro > *,
    .js .mkt-hero__media,
    .js .mkt [data-split],
    .js .mkt [data-split] .mkt-word {
        opacity: 1 !important;
        transform: none !important;
        animation: none !important;
        transition: none !important;
    }
}

/* ---------- Section photography ----------
   A default ratio is load-bearing. Without one, a bare `.mkt-photo` falls back
   to the source's own proportions: the home "why" frame is 1200x900, so at full
   container width it rendered about 860px tall and swallowed the section it was
   meant to introduce. The modifiers below still override it.

   The same saturation correction as the hero, for the same reason: the stock
   frames run warm and orange, and at full width they pull the whole section
   away from the paper and the teal. */
.mkt-photo {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    /* A ratio alone is not enough at full container width: 16:9 across 1152px
       is still 648px of photograph introducing a section that is mostly text
       under it. The cap turns the ratio into an upper bound, and object-fit
       crops rather than squashes once it bites. */
    max-height: 460px;
    border-radius: var(--m-r-lg);
    object-fit: cover;
    /* Faces sit above centre in all three of these frames; a straight centre
       crop takes the top of someone's head off once max-height applies. */
    object-position: center 38%;
    background: var(--m-sunk);
    box-shadow: var(--m-shadow);
    filter: saturate(.86);
}

.mkt-photo--wide { aspect-ratio: 3 / 2; }

/* Portrait, and always in a column rather than across the container, so it gets
   its own taller cap. */
.mkt-photo--tall { aspect-ratio: 4 / 5; max-height: 620px; }

/* Section photographs settle as they arrive: a 3% scale that resolves to rest
   while the image travels up the first half of the viewport, driven by scroll
   position rather than a timer. CSS-only via a view timeline; engines without
   it simply show the photo at rest, and reduced-motion never enters the block.
   Hero photos are excluded — they already have a load entrance. */
@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        .js .mkt-photo {
            animation: mkt-photo-settle linear both;
            animation-timeline: view();
            animation-range: entry 0% cover 42%;
        }
    }
}

@keyframes mkt-photo-settle {
    from { transform: scale(1.03); }
    to   { transform: scale(1); }
}

@media (max-width: 939px) { .mkt-photo { aspect-ratio: 3 / 2; } }

/* =========================================================================
   Dark mode
   -------------------------------------------------------------------------
   Follows the system preference; there is no toggle, because nothing on these
   pages depends on the user choosing a mode.

   The palette is re-derived, not inverted. Alvva's teal is the brand and stays
   the brand: on dark paper the deep teal used for links would disappear, so
   the scale moves up rather than being desaturated into grey. Filled buttons
   flip to dark text on bright teal, which is the only way a saturated brand
   colour keeps both its identity and AA contrast on a dark surface.

   The inverted bands read as a distinct surface here too, sitting slightly
   lighter than the page rather than darker than it.
   ========================================================================= */
@media (prefers-color-scheme: dark) {
    .mkt {
        color-scheme: dark;

        --m-paper:      #071312;
        --m-card:       #0E1E1E;
        --m-sunk:       #0B1918;
        --m-invert:     #122523;

        --m-ink:        #E8F1F0;
        --m-ink-2:      #AFC2C1;
        --m-ink-3:      #859998;

        --m-rule:       #1E302F;
        --m-rule-2:     #2C403E;

        --m-teal:       #2FD8E0;
        --m-teal-mid:   #1BBCC4;
        /* --m-deep is the link and eyebrow colour, so on dark it has to be the
           LIGHTEST teal, not the darkest. Button hover is overridden below,
           because that rule used --m-deep as a fill. */
        --m-deep:       #86EAF0;
        --m-wash:       #10393B;
        --m-wash-soft:  #0B2527;

        --m-amber:      #FFB169;
        --m-amber-soft: #241608;

        --m-shadow:     0 1px 2px rgba(0, 0, 0, .5), 0 20px 44px -30px rgba(0, 0, 0, .85);
        --m-shadow-lg:  0 2px 5px rgba(0, 0, 0, .55), 0 44px 84px -44px rgba(0, 0, 0, .9);
    }

    /* Filled buttons: bright teal, dark label. White on teal does not reach AA
       at body size, and the CTA has to pop as hard here as it does in light. */
    .mkt-btn {
        background: var(--m-teal-mid);
        border-color: var(--m-teal-mid);
        color: #04201F;
    }
    .mkt-btn:hover {
        background: var(--m-teal);
        border-color: var(--m-teal);
        box-shadow: 0 10px 24px -12px rgba(47, 216, 224, .45);
    }
    .mkt-btn--ghost { background: transparent; color: var(--m-ink); border-color: var(--m-rule-2); }
    .mkt-btn--ghost:hover { background: transparent; color: var(--m-deep); border-color: var(--m-deep); }

    .mkt-head { background: rgba(7, 19, 18, .86); }

    /* The USCIS notice keeps its warning identity on a dark amber ground. */
    .mkt-notice { border-top-color: rgba(255, 177, 105, .3); border-bottom-color: rgba(255, 177, 105, .3); }
    .mkt-notice__flag { background: #FFB169; color: #241608; }
    .mkt-notice__source { color: #FFC58F; border-bottom-color: rgba(255, 197, 143, .38); }
    .mkt-notice__source:hover { color: #FFE0C4; border-bottom-color: #FFE0C4; }
    .mkt-notice__point { background: rgba(255, 255, 255, .05); border-color: rgba(255, 177, 105, .24); }
    .mkt-notice__close { border-top-color: rgba(255, 177, 105, .26); }

    .mkt-compare__row--honest .mkt-compare__label { color: #FFB169; }

    /* Photography carries its own light. Knocking it back stops the images
       glowing out of a dark page. */
    .mkt-hero__photo, .mkt-photo { filter: brightness(.92) contrast(1.02); }
}

/* =========================================================================
   Product walkthrough (/how-it-works)
   -------------------------------------------------------------------------
   Real screenshots of the application, presented as tabs. Not a carousel: a
   rotation hides two thirds of the proof at any moment and forces a visitor to
   wait for the screen they wanted. The steps auto-advance, but every panel is
   in the DOM, keyboard reachable, and stops advancing the moment anyone
   interacts.

   The frame is a plain rounded border, deliberately not fake browser chrome.
   Drawn-on toolbars around a real screenshot make it look like a mockup.
   ========================================================================= */
.mkt-walk__grid { display: grid; grid-template-columns: 1fr; gap: 26px; margin-top: 34px; }

@media (min-width: 980px) {
    .mkt-walk__grid { grid-template-columns: 21rem 1fr; gap: 44px; align-items: start; }
}

.mkt-walk__steps { display: grid; gap: 10px; }

.mkt-walk__step {
    position: relative;
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 14px;
    text-align: left;
    padding: 16px 18px;
    border: 1px solid transparent;
    border-radius: var(--m-r);
    background: transparent;
    font-family: inherit;
    cursor: pointer;
    overflow: hidden;
    transition: background .18s ease, border-color .18s ease;
}

.mkt-walk__step:hover { background: var(--m-card); }

.mkt-walk__step[aria-selected="true"] {
    background: var(--m-card);
    border-color: var(--m-rule);
    box-shadow: var(--m-shadow);
}

.mkt-walk__no {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 999px;
    background: var(--m-wash);
    color: var(--m-deep);
    font-size: .8125rem;
    font-weight: 600;
    flex: none;
}

.mkt-walk__step[aria-selected="true"] .mkt-walk__no { background: var(--m-teal-mid); color: #FFF; }

.mkt-walk__text { display: grid; gap: 3px; min-width: 0; }
.mkt-walk__title { font-weight: 600; font-size: 1rem; color: var(--m-ink); }
.mkt-walk__desc { font-size: .875rem; line-height: 1.5; color: var(--m-ink-3); }

/* Progress for the auto-advance, so the movement is explained rather than
   surprising. Width is driven from the script. */
.mkt-walk__bar {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 0;
    background: var(--m-teal);
}

.mkt-walk__screens { position: relative; }

.mkt-walk__screen { margin: 0; }

/* One fixed box for every screen, matching the 1280x760 the sources are
   captured at. Without it the panel resizes as the tabs advance, which reads as
   the page breaking. The ratio deliberately equals the source ratio: a wider
   box plus object-fit:cover silently shaved the module sidebar off the left of
   the question screen. */
.mkt-walk__screen img {
    width: 100%;
    /* height:auto is load-bearing. The base `.mkt img` reset deliberately omits
       it (a global height:auto was overriding the masthead logo), so without it
       here the HTML height attribute is used literally and aspect-ratio never
       applies: the box came out 764x760 instead of 764x454. */
    height: auto;
    aspect-ratio: 1280 / 760;
    object-fit: cover;
    object-position: top left;
    border: 1px solid var(--m-rule);
    border-radius: var(--m-r-lg);
    box-shadow: var(--m-shadow-lg);
    background: var(--m-card);
}

/* The section promises "the screens you will actually be looking at", and on a
   phone it delivered a grey smudge: a 1280x760 capture scaled into a 350px
   panel puts the interface type at roughly four pixels tall. Below 900px the
   figure scrolls sideways at a width where the screen is legible instead.

   The scroll is contained: `overscroll-behavior-x` stops a flick inside the
   panel from turning into a browser back-navigation, and `.mkt-walk__grid > *`
   already carries `min-width: 0`, so the wide child cannot push the page
   itself sideways. The fade on the trailing edge is the only affordance that
   there is more to the right — the alternative, a text label, would be one more
   small string on a page that has too many already. */
@media (max-width: 899px) {
    .mkt-walk__screen {
        overflow-x: auto;
        overscroll-behavior-x: contain;
        -webkit-overflow-scrolling: touch;
        /* Room for the image's own shadow, which the scroll box would clip. */
        padding-bottom: 6px;
    }

    .mkt-walk__screen img { min-width: 680px; }

    .mkt-walk__screens {
        position: relative;
        /* Fades the trailing edge without covering it: the overlay sits above
           the image but takes no pointer events, so the panel still scrolls
           under it. */
        --m-fade: var(--m-sunk);
    }

    .mkt-walk__screens::after {
        content: "";
        position: absolute;
        top: 0;
        right: 0;
        bottom: 6px;
        width: 44px;
        pointer-events: none;
        border-radius: 0 var(--m-r-lg) var(--m-r-lg) 0;
        background: linear-gradient(90deg, transparent, var(--m-fade));
    }
}

.js .mkt-walk__screen.is-current { animation: mkt-walk-in .42s cubic-bezier(.22, .61, .36, 1); }

@keyframes mkt-walk-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .js .mkt-walk__screen.is-current { animation: none; }
    .mkt-walk__bar { display: none; }
}

/* =========================================================================
   Mobile compliance
   -------------------------------------------------------------------------
   Applied at the phone breakpoint only, so the desktop rhythm is untouched.

   Two things drive everything here. Tap targets must clear 44x44: the audit
   found the language switcher at 41x33, the menu button at 44x38, and every
   link inside the footer and the nav dropdowns at 22px tall. And body copy
   must not drop below 16px, because iOS silently zooms the page when a control
   near text is smaller and it is simply hard to read on a phone held at arm's
   length. Several component styles sat at 14px.
   ========================================================================= */
/* Tap targets key off the POINTER, not the viewport width. A tablet at 768px
   or a touchscreen laptop is still a finger, and a width breakpoint would have
   left every one of these at 22 to 40px tall on an iPad. */
/* Both conditions on purpose. `pointer: coarse` is the correct signal and
   catches tablets and touch laptops, but headless browsers report a fine
   pointer, so a width query is paired with it to keep the phone case
   verifiable in an automated pass. */
@media (pointer: coarse), (max-width: 767px) {
    .mkt-lang__opt { min-width: 48px; min-height: 44px; display: grid; place-items: center; }
    .mkt-menu__btn { min-height: 44px; min-width: 44px; }

    /* Links stacked in a list need vertical room between them, not just
       inside them, or the 8px separation rule fails even when each is 44 tall. */
    .mkt-foot__links li { margin-bottom: 2px; }
    .mkt-foot__links a,
    .mkt-menu__link,
    .mkt-drop__link {
        display: flex;
        align-items: center;
        min-height: 44px;
    }

    .mkt-notice__source,
    .mkt-praise__link,
    .mkt-btn { min-height: 44px; }

    /* The masthead logo is a link home. Its image is 24px tall, so the anchor
       was a 70x24 tap target on every page. The partner logo strip has the
       same problem at 40px. */
    .mkt-head__inner > a,
    .mkt-logos a { display: inline-flex; align-items: center; min-height: 44px; }
}

@media (max-width: 767px) {
    /* ---- Readable body copy ---- */
    .mkt { font-size: 16px; }
    .mkt-lede { font-size: 1.0625rem; }
    .mkt-price__rowdesc,
    .mkt-step__desc,
    .mkt-dir__desc,
    .mkt-walk__desc,
    .mkt-track__desc,
    .mkt-budget__desc,
    .mkt-notice__point,
    .mkt-praise__cardquote,
    .mkt-card__desc,
    .mkt-packet__name,
    .mkt-compare__cell { font-size: 1rem; line-height: 1.55; }

    .mkt-price__rowtitle,
    .mkt-quote__text { font-size: 1rem; }

    /* Supporting labels sat at 13px, which is below the floor even for
       secondary copy on a phone. */
    .mkt-trust__label,
    .mkt-quote__meta,
    .mkt-praise__cardmeta,
    .mkt-praise__meta,
    .mkt-dir__tag { font-size: .875rem; }

    /* Fine print stays smaller by intent, but not below 14px. */
    .mkt-price__fine,
    .mkt-foot__fine,
    .mkt-notice__closetext { font-size: .875rem; }

    /* ---- Measure ----
       35 to 60 characters is the readable range on a phone. The desktop caps
       are set in ch and are far wider than a 390px screen, so they stop
       applying here and the gutter does the work instead. */
    .mkt-h1, .mkt-h2, .mkt-lede, .mkt-p { max-width: none; }
}
