/* ==============================================================================================
   /mortgage-websites/ -- Mortgage Websites + SEO (template-mortgage-websites.php)

   The page is OM components throughout: the hero, the Mortgage AI page's alternating row, the
   dark bands, the FAQ and the closing band all come from design-om + design-om-extras. This
   file carries only what is new, and nearly all of it is one thing -- the six row visuals.

   WHY THERE ARE DRAWINGS HERE AND NOT PNGs. The AI page's rows carry screenshots of the product.
   There are none for this one: HomeMagnet's own site ships illustrations rather than captures,
   and nothing in this repo can reach a built customer site to photograph. So each row's visual
   is drawn, which is the call the texting page already made for its SMS thread.

   Every one of them is aria-hidden in the template. They are decoration standing in for a
   screenshot, and a screen reader reading out a fabricated review is worse than silence.

   REPLACE THEM when real screenshots exist. `.om-ai-row__shot img` already styles an <img> the
   way the AI page does, so a capture drops into the same slot and everything from `.hm-mock`
   down can go.

   Each mock is built on one shared frame -- `.hm-mock` -- so the six keep the same card, border,
   radius and shadow as an AI-page screenshot would, and only their contents differ.
   ============================================================================================== */

/* ---- The shared frame ------------------------------------------------------------------------
   Matching .om-ai-row__shot img in page-mortgage-ai.css: same width, border, radius and shadow,
   so a row here and a row there sit at the same visual weight. */
#mortgage-websites .hm-shot { display: flex; justify-content: center; }
#mortgage-websites .hm-mock {
    width: 80%;
    min-width: 0;
    box-sizing: border-box;
    padding: 18px;
    border: 1px solid var(--line, #dbe0e6);
    border-radius: 12px;
    box-shadow: 0 18px 40px #15304c14;
    background: #fff;
    font-size: 13px;
    line-height: 1.45;
    color: var(--ink, #0b2545);
}
/* The grey bars that stand in for text. One rule, because six mocks using six slightly
   different greys is how a page stops looking drawn by one hand. */
#mortgage-websites .hm-mock .hm-site__nav span,
#mortgage-websites .hm-mock .hm-site__hero i,
#mortgage-websites .hm-mock .hm-site__hero u,
#mortgage-websites .hm-mock .hm-site__cards p,
#mortgage-websites .hm-mock .hm-review__line,
#mortgage-websites .hm-mock .hm-asst__line,
#mortgage-websites .hm-mock .hm-seo__url,
#mortgage-websites .hm-mock .hm-seo__title,
#mortgage-websites .hm-mock .hm-seo__line,
#mortgage-websites .hm-mock .hm-seo__kw span,
#mortgage-websites .hm-mock .hm-cal__head span {
    display: block;
    background: #e4e9ef;
    border-radius: 3px;
}

/* ---- 1. The website: a browser frame around a mortgage site ---------------------------------- */
#mortgage-websites .hm-win { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
#mortgage-websites .hm-win__dots { display: flex; gap: 5px; }
#mortgage-websites .hm-win__dots i { width: 8px; height: 8px; border-radius: 50%; background: #e4e9ef; }
#mortgage-websites .hm-win__bar { flex: 1; height: 10px; border-radius: 5px; background: #f1f4f8; }
#mortgage-websites .hm-site { border: 1px solid #eef1f5; border-radius: 8px; overflow: hidden; }
#mortgage-websites .hm-site__nav {
    display: flex; align-items: center; gap: 9px;
    padding: 9px 11px; border-bottom: 1px solid #eef1f5;
}
#mortgage-websites .hm-site__logo {
    width: 22px; height: 10px; border-radius: 2px;
    background: var(--orange, #f5a623) !important;
}
#mortgage-websites .hm-site__nav span { width: 26px; height: 6px; }
#mortgage-websites .hm-site__nav em {
    margin-left: auto; width: 40px; height: 14px; border-radius: 3px;
    background: var(--orange, #f5a623);
}
/* The hero block reads as a hero because of the navy, which is the one place colour does real
   work in this drawing -- without it the whole mock is grey bars and says nothing. */
#mortgage-websites .hm-site__hero { padding: 16px 12px; background: var(--navy, #032d60); }
#mortgage-websites .hm-site__hero b { display: block; width: 58%; height: 11px; border-radius: 3px; background: #ffffff; }
#mortgage-websites .hm-site__hero i { width: 80%; height: 6px; margin-top: 8px; background: #ffffff59 !important; }
#mortgage-websites .hm-site__hero u { width: 54px; height: 15px; margin-top: 11px; border-radius: 3px; background: var(--orange, #f5a623) !important; }
#mortgage-websites .hm-site__row { display: grid; grid-template-columns: 96px 1fr; gap: 10px; padding: 12px; }
#mortgage-websites .hm-site__calc {
    padding: 9px; border: 1px solid #eef1f5; border-radius: 6px; background: #fbfcfd;
}
#mortgage-websites .hm-site__calc span { font-size: 9px; letter-spacing: .04em; text-transform: uppercase; color: #7c8b9c; }
#mortgage-websites .hm-site__calc strong { display: block; width: 52px; height: 12px; margin: 5px 0 7px; border-radius: 3px; background: var(--navy, #032d60); }
#mortgage-websites .hm-site__calc em { display: block; height: 5px; margin-top: 5px; border-radius: 2px; background: #e4e9ef; }
#mortgage-websites .hm-site__cards { display: grid; gap: 7px; align-content: start; }
#mortgage-websites .hm-site__cards p { height: 20px; margin: 0; border-radius: 4px; }

/* ---- 2. The assistant: a request, the work, and the MCP line --------------------------------- */
#mortgage-websites .hm-asst__ask {
    margin: 0 0 12px; padding: 9px 12px;
    border-radius: 12px 12px 12px 3px;
    background: var(--navy, #032d60); color: #fff;
}
#mortgage-websites .hm-asst__work { padding: 11px; border: 1px solid #eef1f5; border-radius: 8px; background: #fbfcfd; }
#mortgage-websites .hm-asst__badge {
    display: inline-block; margin-bottom: 9px; padding: 2px 8px;
    border-radius: 999px; font-size: 10px; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: #8a5a00; background: #fdf0d8;
}
#mortgage-websites .hm-asst__line { height: 6px; margin-bottom: 6px; }
#mortgage-websites .hm-asst__line--short { width: 56%; margin-bottom: 0; }
/* The MCP line is the one claim in any of these drawings that a reader might not believe, so it
   is set as a status rather than as a bar: a label, a state, and nothing decorative. */
#mortgage-websites .hm-asst__mcp {
    display: flex; align-items: center; gap: 8px;
    margin: 12px 0 0; font-size: 12px; color: #52637a;
}
#mortgage-websites .hm-asst__mcp span {
    padding: 2px 7px; border-radius: 4px; font-size: 10px; font-weight: 700;
    letter-spacing: .06em; color: #fff; background: #1b7f5a;
}

/* ---- 3. Reviews: four sources, one flagged --------------------------------------------------- */
#mortgage-websites .hm-reviews { display: grid; gap: 10px; }
#mortgage-websites .hm-review {
    padding: 10px 12px; border: 1px solid #eef1f5; border-radius: 8px; background: #fbfcfd;
}
#mortgage-websites .hm-review.is-flagged { border-color: #f3d2a8; background: #fffaf2; }
#mortgage-websites .hm-review__src { font-size: 11px; font-weight: 700; color: #52637a; }
#mortgage-websites .hm-review__stars { margin-left: 7px; font-size: 12px; letter-spacing: 1px; color: var(--orange, #f5a623); }
#mortgage-websites .hm-review__line { height: 6px; margin-top: 8px; }
#mortgage-websites .hm-review__line--short { width: 62%; }
#mortgage-websites .hm-review__flag {
    display: inline-block; margin-top: 9px; padding: 2px 8px;
    border-radius: 999px; font-size: 10px; font-weight: 700; color: #8a5a00; background: #fdf0d8;
}

/* ---- 4. SEO: a result, a score, three keywords ----------------------------------------------- */
#mortgage-websites .hm-seo { display: grid; grid-template-columns: 1fr 86px; gap: 14px; align-items: start; }
#mortgage-websites .hm-seo__serp { padding: 11px; border: 1px solid #eef1f5; border-radius: 8px; background: #fbfcfd; }
#mortgage-websites .hm-seo__url { width: 46%; height: 6px; }
#mortgage-websites .hm-seo__title { width: 78%; height: 10px; margin-top: 7px; background: #c9d6e4 !important; }
#mortgage-websites .hm-seo__line { height: 5px; margin-top: 7px; }
#mortgage-websites .hm-seo__line--short { width: 64%; }
#mortgage-websites .hm-seo__score { text-align: center; }
#mortgage-websites .hm-seo__score svg { width: 64px; height: 64px; transform: rotate(-90deg); }
#mortgage-websites .hm-seo__score circle { fill: none; stroke: #eef1f5; stroke-width: 3.4; }
/* 78 of 100 as a dash offset. No number is printed beside it on purpose -- a score nobody has
   measured should not be readable as a figure. */
#mortgage-websites .hm-seo__arc {
    stroke: #1b7f5a !important;
    stroke-linecap: round;
    stroke-dasharray: 78 100;
}
#mortgage-websites .hm-seo__score span { display: block; margin-top: 4px; font-size: 11px; color: #7c8b9c; }
#mortgage-websites .hm-seo__kw { grid-column: 1 / -1; list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
#mortgage-websites .hm-seo__kw li { display: flex; align-items: center; gap: 10px; }
#mortgage-websites .hm-seo__kw span { flex: 1; height: 6px; }
#mortgage-websites .hm-seo__kw em { font-style: normal; font-size: 12px; font-weight: 700; color: #1b7f5a; }

/* ---- 5. Chat: two turns and a booking ------------------------------------------------------- */
#mortgage-websites .hm-chat p { margin: 0 0 9px; padding: 9px 12px; max-width: 86%; }
#mortgage-websites .hm-chat__them { border-radius: 12px 12px 12px 3px; background: #f1f4f8; }
#mortgage-websites .hm-chat__us { margin-left: auto; border-radius: 12px 12px 3px 12px; background: var(--navy, #032d60); color: #fff; }
#mortgage-websites .hm-chat__booked {
    display: flex; align-items: center; gap: 8px; max-width: none; margin-bottom: 0;
    border-radius: 8px; border: 1px solid #cfe8dd; background: #f2faf6; color: #146245; font-weight: 600;
}
#mortgage-websites .hm-chat__booked span {
    display: grid; place-items: center; width: 18px; height: 18px;
    border-radius: 50%; background: #1b7f5a; color: #fff; font-size: 11px;
}

/* ---- 6. The calendar: a month with a few things scheduled ------------------------------------ */
#mortgage-websites .hm-cal__head { display: grid; grid-template-columns: repeat(5, 1fr); gap: 7px; margin-bottom: 9px; }
#mortgage-websites .hm-cal__head span { height: 6px; }
#mortgage-websites .hm-cal__grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 7px; }
#mortgage-websites .hm-cal__grid i {
    height: 30px; border-radius: 5px; border: 1px solid #eef1f5; background: #fbfcfd;
}
/* Three kinds of scheduled item, three fills. The point of the drawing is that the month is
   planned and not empty, so the filled cells have to be obviously different from the rest. */
#mortgage-websites .hm-cal__grid i.is-post   { border-color: #f3d2a8; background: #fdf0d8; }
#mortgage-websites .hm-cal__grid i.is-blog   { border-color: #b9ccdf; background: #e6eef7; }
#mortgage-websites .hm-cal__grid i.is-social { border-color: #cfe8dd; background: #e8f6ef; }

/* ---- The stats band --------------------------------------------------------------------------
   Three sourced figures under the hero, on .om-stats -- the component the texting page uses,
   which is built for exactly this: a figure, the claim, and the source in a <small> underneath
   where the visitor can see it.

   What is set here is the band's size and bleed; the cells, type and colour are the component,
   deliberately: a band that looked slightly different from the texting page's would be a second
   way of saying the same thing, and the figures want to read as the site's, not as this page's.

   The band is full-bleed: the pale strip runs edge to edge rather than sitting as an inset
   rectangle with white around it, so the section loses its padding and the container inside it
   loses its 1100px width. The figures themselves still stop at a readable width because the
   cells are fixed and centred. */
#mortgage-websites .hm-proof { padding: 0; }
#mortgage-websites .hm-proof > .om-container { width: 100%; max-width: none; margin: 0; }
/* Thinner than the component's 223px/365px fixed box, which is built for three terse labels and
   leaves a lot of air once the lines are one sentence tall. */
#mortgage-websites .hm-stats {
    height: auto;
    min-height: 0;
    gap: clamp(32px, 6vw, 90px);
    padding: 22px 24px;
}
#mortgage-websites .hm-stats div { width: 270px; }
#mortgage-websites .hm-stats span { line-height: 1.45; }
/* The source line is a <small> inside the claim's <span>, and .om-stats leaves it inline -- so
   without this it runs straight on from the last word: "...before choosing oneBrightLocal
   Consumer Search Behavior". Same rule the texting page carries for the same reason. */
#mortgage-websites .hm-stats small {
    display: block;
    margin-top: 6px;
    color: #8a929c;
    font-size: 10px;
}

/* The attribution under a row's points, where a row leans on research rather than on the
   product. One row does -- reputation -- and it carries three figures, which is too many to name
   inline without the sentences becoming a bibliography. */
/* Tucked straight under the last bullet, indented to the bullet's text column rather than to
   the list edge: it is that sentence's source, not a note about the row. .om-ai-points carries
   30px below it, which is pulled back to leave a source-line gap instead of a paragraph one. */
#mortgage-websites .hm-note {
    margin: -22px 0 22px 16px;
    font-size: 10px;
    color: #8a929c;
}

/* ---- Points without icons --------------------------------------------------------------------
   .om-ai-points is drawn around a 60px icon column. This page has no icon set of its own, and
   borrowing the AI page's eleven mortgage icons for website features would have put a picture of
   a loan file beside a sentence about reviews. The column is removed rather than filled. */
#mortgage-websites .hm-points li { grid-template-columns: 1fr; padding-left: 16px; position: relative; }
#mortgage-websites .hm-points li::before {
    content: ''; position: absolute; left: 0; top: 9px;
    width: 6px; height: 6px; border-radius: 50%; background: var(--orange, #f5a623);
}

/* ---- Narrow screens -------------------------------------------------------------------------- */
@media (max-width: 1024px) {
    #mortgage-websites .hm-mock { width: 100%; }
    #mortgage-websites .hm-stats { flex-direction: column; gap: 24px; padding: 24px 20px; }
    #mortgage-websites .hm-stats div { width: auto; max-width: 420px; }
}
@media (max-width: 600px) {
    #mortgage-websites .hm-seo { grid-template-columns: 1fr; }
    #mortgage-websites .hm-seo__score { justify-self: start; }
}

/* ---- 7. API and MCP: real calls, and a connection state --------------------------------------
   The five paths are real routes from leadfactory's routes/api.php. Drawn as text rather than as
   grey bars, unlike every other mock here, and deliberately: this is the one row whose reader
   will want to see the actual shape of the thing, and bars would tell them nothing. */
#mortgage-websites .hm-api__calls {
    padding: 12px 13px; border: 1px solid #eef1f5; border-radius: 8px; background: #fbfcfd;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12px; line-height: 1.9;
}
#mortgage-websites .hm-api__calls p { margin: 0; color: #52637a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#mortgage-websites .hm-api__calls b {
    display: inline-block; min-width: 46px; margin-right: 8px;
    font-size: 10px; font-weight: 700; letter-spacing: .04em; color: var(--navy, #032d60);
}
#mortgage-websites .hm-api__mcp {
    display: flex; align-items: center; gap: 8px;
    margin: 12px 0 0; font-size: 12px; color: #52637a;
}
#mortgage-websites .hm-api__mcp span {
    padding: 2px 7px; border-radius: 4px; font-size: 10px; font-weight: 700;
    letter-spacing: .06em; color: #fff; background: #1b7f5a;
}

/* ---- Motion ----------------------------------------------------------------------------------
   Two pieces, both armed by assets/js/mortgage-websites.js as they scroll into view: the site
   mock assembles itself, and the three figures count up.

   The contract is the texting page's, for the same reasons. Nothing here hides anything until
   `is-armed` lands, which only JS adds and only when IntersectionObserver exists and the visitor
   has not asked for reduced motion. A broken script tag or an old browser therefore shows the
   finished mock, not an empty card.

   WHY THE SITE MOCK AND NOT THE OTHERS. The row it sits in claims a site is live in under 15
   minutes. Watching the frame, the nav, the hero and the cards arrive in that order says it;
   fading the same drawing in as one block would only be decoration. The total is ~1s, which is
   slower than the texting rail's .45s on purpose -- this one is the point rather than a polish,
   and it runs once. */
#mortgage-websites .hm-mock--site.is-armed .hm-win,
#mortgage-websites .hm-mock--site.is-armed .hm-site__nav > *,
#mortgage-websites .hm-mock--site.is-armed .hm-site__hero > *,
#mortgage-websites .hm-mock--site.is-armed .hm-site__calc,
#mortgage-websites .hm-mock--site.is-armed .hm-site__cards p { opacity: 0; }
#mortgage-websites .hm-mock--site.is-armed .hm-site {
    opacity: 0;
    transform: scale(.985);
}

#mortgage-websites .hm-mock--site.is-in .hm-site {
    animation: hm-frame-in .35s ease-out both;
}
#mortgage-websites .hm-mock--site.is-in .hm-win,
#mortgage-websites .hm-mock--site.is-in .hm-site__nav > *,
#mortgage-websites .hm-mock--site.is-in .hm-site__hero > *,
#mortgage-websites .hm-mock--site.is-in .hm-site__calc,
#mortgage-websites .hm-mock--site.is-in .hm-site__cards p {
    animation: hm-part-in .3s ease-out both;
}
/* The build order, in the order a page is actually made: chrome, navigation, hero, then the
   blocks underneath. The numbers are delays in one list rather than a loop so the sequence can
   be read and retimed here, without touching the JS. */
#mortgage-websites .hm-mock--site.is-in .hm-win                  { animation-delay: .00s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__nav > *:nth-child(1) { animation-delay: .22s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__nav > *:nth-child(2) { animation-delay: .28s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__nav > *:nth-child(3) { animation-delay: .32s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__nav > *:nth-child(4) { animation-delay: .36s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__nav > *:nth-child(5) { animation-delay: .42s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__hero > b       { animation-delay: .52s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__hero > i       { animation-delay: .60s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__hero > u       { animation-delay: .68s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__calc           { animation-delay: .80s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__cards p:nth-child(1) { animation-delay: .86s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__cards p:nth-child(2) { animation-delay: .92s; }
#mortgage-websites .hm-mock--site.is-in .hm-site__cards p:nth-child(3) { animation-delay: .98s; }

@keyframes hm-frame-in {
    from { opacity: 0; transform: scale(.985); }
    to   { opacity: 1; transform: none; }
}
@keyframes hm-part-in {
    from { opacity: 0; transform: translateY(5px); }
    to   { opacity: 1; transform: none; }
}

/* Belt and braces: the JS already refuses to arm under reduced motion, so this only matters if
   the preference changes after the class has landed. */
@media (prefers-reduced-motion: reduce) {
    #mortgage-websites .hm-mock--site.is-armed .hm-win,
    #mortgage-websites .hm-mock--site.is-armed .hm-site,
    #mortgage-websites .hm-mock--site.is-armed .hm-site__nav > *,
    #mortgage-websites .hm-mock--site.is-armed .hm-site__hero > *,
    #mortgage-websites .hm-mock--site.is-armed .hm-site__calc,
    #mortgage-websites .hm-mock--site.is-armed .hm-site__cards p {
        opacity: 1;
        transform: none;
        animation: none;
    }
}

/* ---- The SEO mock: the arc sweeps, the keyword rows arrive ------------------------------------
   The score is drawn as an arc with no number beside it -- the decision made when the mock was
   built, because a site score nobody has measured should not be readable as a figure. That holds
   here: what animates is the sweep, not a counter. The arc is 78 of 100 as a dash offset, so
   sweeping it is animating stroke-dasharray from 0.

   Loops while the row is on screen, like the site mock -- on its own timer, so the two never
   blink together. See LOOPS in assets/js/mortgage-websites.js; the run figure there has to
   track the last delay below plus its duration. */
#mortgage-websites .hm-mock--seo.is-armed .hm-seo__arc { stroke-dasharray: 0 100; }
#mortgage-websites .hm-mock--seo.is-armed .hm-seo__kw li { opacity: 0; }
#mortgage-websites .hm-mock--seo.is-in .hm-seo__arc { animation: hm-arc-in .9s ease-out both; }
#mortgage-websites .hm-mock--seo.is-in .hm-seo__kw li { animation: hm-part-in .3s ease-out both; }
#mortgage-websites .hm-mock--seo.is-in .hm-seo__kw li:nth-child(1) { animation-delay: .45s; }
#mortgage-websites .hm-mock--seo.is-in .hm-seo__kw li:nth-child(2) { animation-delay: .60s; }
#mortgage-websites .hm-mock--seo.is-in .hm-seo__kw li:nth-child(3) { animation-delay: .75s; }
@keyframes hm-arc-in {
    from { stroke-dasharray: 0 100; }
    to   { stroke-dasharray: 78 100; }
}

/* ---- The reviews mock: stars fill, then the flagged card asks once ----------------------------
   The stars are one <i> each so they can land in sequence -- the only reason the markup wraps
   them. Source by source, left to right, and then the Yelp card pulses a single time.

   One pulse per run, and no colour change. The flag is the row's point (what needs a reply is
   flagged rather than found by accident), and a badge that blinks on and on reads as an error
   state on a page selling reputation management. The run repeats on the loop, but with the
   pause between runs doing the work a second pulse would have done badly. */
#mortgage-websites .hm-mock--reviews.is-armed .hm-review__stars i { opacity: 0; }
#mortgage-websites .hm-mock--reviews.is-armed .hm-review__flag { opacity: 0; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review__stars i {
    display: inline-block;
    animation: hm-star-in .28s ease-out both;
}
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(1) .hm-review__stars i:nth-child(1) { animation-delay: 0.05s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(1) .hm-review__stars i:nth-child(2) { animation-delay: 0.12s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(1) .hm-review__stars i:nth-child(3) { animation-delay: 0.19s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(1) .hm-review__stars i:nth-child(4) { animation-delay: 0.26s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(1) .hm-review__stars i:nth-child(5) { animation-delay: 0.33s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(2) .hm-review__stars i:nth-child(1) { animation-delay: 0.25s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(2) .hm-review__stars i:nth-child(2) { animation-delay: 0.32s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(2) .hm-review__stars i:nth-child(3) { animation-delay: 0.39s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(2) .hm-review__stars i:nth-child(4) { animation-delay: 0.46s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(2) .hm-review__stars i:nth-child(5) { animation-delay: 0.53s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(3) .hm-review__stars i:nth-child(1) { animation-delay: 0.45s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(3) .hm-review__stars i:nth-child(2) { animation-delay: 0.52s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(3) .hm-review__stars i:nth-child(3) { animation-delay: 0.59s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(3) .hm-review__stars i:nth-child(4) { animation-delay: 0.66s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review:nth-child(3) .hm-review__stars i:nth-child(5) { animation-delay: 0.73s; }
#mortgage-websites .hm-mock--reviews.is-in .hm-review__flag {
    animation: hm-part-in .3s ease-out .95s both, hm-flag-pulse 1.1s ease-out 1.25s 1;
}
@keyframes hm-star-in {
    from { opacity: 0; transform: scale(.4); }
    to   { opacity: 1; transform: none; }
}
@keyframes hm-flag-pulse {
    0%        { box-shadow: 0 0 0 0 #f5a62366; }
    60%, 100% { box-shadow: 0 0 0 10px #f5a62300; }
}

@media (prefers-reduced-motion: reduce) {
    #mortgage-websites .hm-mock--seo.is-armed .hm-seo__arc { stroke-dasharray: 78 100; }
    #mortgage-websites .hm-mock--seo.is-armed .hm-seo__kw li,
    #mortgage-websites .hm-mock--reviews.is-armed .hm-review__stars i,
    #mortgage-websites .hm-mock--reviews.is-armed .hm-review__flag {
        opacity: 1;
        transform: none;
        animation: none;
    }
}


/* ---- The chat mock: two turns, then the booking ----------------------------------------------
   Same contract as the three above. The order is the conversation's: the visitor asks, the reply
   comes back, and the booking lands last, which is the row's point. The gap before the reply is
   longer than the others on purpose -- it reads as an answer rather than as two lines appearing
   together. */
#mortgage-websites .hm-mock--chat.is-armed .hm-chat p { opacity: 0; }
#mortgage-websites .hm-mock--chat.is-in .hm-chat p { animation: hm-msg-in .32s ease-out both; }
#mortgage-websites .hm-mock--chat.is-in .hm-chat__them   { animation-delay: .10s; }
#mortgage-websites .hm-mock--chat.is-in .hm-chat__us     { animation-delay: .70s; }
#mortgage-websites .hm-mock--chat.is-in .hm-chat__booked { animation-delay: 1.20s; }
@keyframes hm-msg-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

/* ---- The API mock: the calls arrive, then the connection ------------------------------------
   The five routes land top to bottom like a log, which is what they are, and the MCP line comes
   last: it is a state, and a state that appears before the calls it describes is a lie about
   the order of things. */
#mortgage-websites .hm-mock--api.is-armed .hm-api__calls p,
#mortgage-websites .hm-mock--api.is-armed .hm-api__mcp { opacity: 0; }
#mortgage-websites .hm-mock--api.is-in .hm-api__calls p,
#mortgage-websites .hm-mock--api.is-in .hm-api__mcp { animation: hm-part-in .26s ease-out both; }
#mortgage-websites .hm-mock--api.is-in .hm-api__calls p:nth-child(1) { animation-delay: .05s; }
#mortgage-websites .hm-mock--api.is-in .hm-api__calls p:nth-child(2) { animation-delay: .17s; }
#mortgage-websites .hm-mock--api.is-in .hm-api__calls p:nth-child(3) { animation-delay: .29s; }
#mortgage-websites .hm-mock--api.is-in .hm-api__calls p:nth-child(4) { animation-delay: .41s; }
#mortgage-websites .hm-mock--api.is-in .hm-api__calls p:nth-child(5) { animation-delay: .53s; }
#mortgage-websites .hm-mock--api.is-in .hm-api__mcp { animation-delay: .75s; }

/* ---- The calendar mock: the month fills in ---------------------------------------------------
   The empty cells are left alone -- they are the grid, not the content. Only the six scheduled
   items arrive, in date order, which is the row's claim: the site keeps publishing without
   anybody sitting down to it. Their nth-child numbers are the fixed $filled keys in
   bnt_hm_mock() plus one; move a scheduled cell there and these move with it. */
#mortgage-websites .hm-mock--calendar.is-armed .hm-cal__head span,
#mortgage-websites .hm-mock--calendar.is-armed .hm-cal__grid i.is-post,
#mortgage-websites .hm-mock--calendar.is-armed .hm-cal__grid i.is-blog,
#mortgage-websites .hm-mock--calendar.is-armed .hm-cal__grid i.is-social { opacity: 0; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__head span { animation: hm-part-in .24s ease-out both; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__head span:nth-child(1) { animation-delay: .02s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__head span:nth-child(2) { animation-delay: .07s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__head span:nth-child(3) { animation-delay: .12s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__head span:nth-child(4) { animation-delay: .17s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__head span:nth-child(5) { animation-delay: .22s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i.is-post,
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i.is-blog,
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i.is-social {
    animation: hm-cell-in .3s ease-out both;
}
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i:nth-child(2)  { animation-delay: .35s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i:nth-child(5)  { animation-delay: .47s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i:nth-child(8)  { animation-delay: .59s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i:nth-child(12) { animation-delay: .71s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i:nth-child(14) { animation-delay: .83s; }
#mortgage-websites .hm-mock--calendar.is-in .hm-cal__grid i:nth-child(18) { animation-delay: .95s; }
@keyframes hm-cell-in {
    from { opacity: 0; transform: scale(.6); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    #mortgage-websites .hm-mock--chat.is-armed .hm-chat p,
    #mortgage-websites .hm-mock--api.is-armed .hm-api__calls p,
    #mortgage-websites .hm-mock--api.is-armed .hm-api__mcp,
    #mortgage-websites .hm-mock--calendar.is-armed .hm-cal__head span,
    #mortgage-websites .hm-mock--calendar.is-armed .hm-cal__grid i {
        opacity: 1;
        transform: none;
        animation: none;
    }
}
