/**
 * lbai-ux-fix.css — post-certification UX remediation layer.
 *
 * WHY THIS FILE EXISTS
 * Two of the three issues in this pass live on surfaces whose owners are FROZEN by the
 * frozen manifest (template-dashboard.php, dashboard.css, dashboard-ui.css, core.css,
 * header.php). The Frozen File Exception register requires a ratified entry before any of
 * them may be edited, and no such entry exists for a UX pass, so the corrections ship
 * additively from here — after those stylesheets in the cascade — exactly as Phase F did.
 *
 * The third issue (Staff Management density) is NOT handled here: its owners are
 * booking-card.css and staff-manager.js, neither of which is frozen, so it is corrected in
 * place where it belongs rather than being overridden from a layer.
 *
 * `!important` is used ONLY where the declaration being corrected is an INLINE style in the
 * frozen template, or is itself an `!important` dark-mode rule printed by header.php. An
 * inline declaration cannot be beaten any other way. Every other rule here relies on plain
 * cascade order.
 *
 * NO business logic, no visibility rule, no pricing, no booking, no database read or write.
 *
 * @package listing-by-atul-ingale
 */

/* =====================================================================================
   ISSUE 1 — VENDOR LISTING: MOBILE CLIPPING
   =====================================================================================
   ROOT CAUSE, in the order it bites:

   1. `.lbaid-mllist` (dashboard-ui.css:327/331) sizes its tracks with `1fr`, which is
      `minmax(auto, 1fr)`. The automatic minimum is the CARD's min-content width, so an
      over-wide row makes the TRACK grow rather than making the card shrink — a grid
      blowout that pushes documentElement.scrollWidth past the viewport. This is the exact
      failure P35 already diagnosed and fixed for `.lbaid-rev__list`, which uses
      `minmax(0, 1fr)`; the My Listings grid never received the same correction.

   2. The card root (template line 1581) is an INLINE `display:flex;align-items:center`
      with no `flex-wrap`, so image + text + actions are locked onto one line at every
      width.

   3. The actions wrapper (template line 1668) is an INLINE
      `display:flex;gap:8px;flex-shrink:0`. Being unshrinkable it reserves its full
      min-content width unconditionally, so 100% of the shrink pressure lands on
      `.ail-vl-info` — the only shrinkable column.

   4. The text actions carry an inline `height:34px` with NO `white-space:nowrap`, so
      "Resume Payment" wraps to two lines inside a 34px box and is vertically clipped.

   5. `.lbaid-mltabs` (dashboard-ui.css:321-323) is `overflow-x:auto` with the scrollbar
      hidden in both engines, and its pills are `flex:0 0 auto`. Five pills exceed 320px,
      so "Expired" sits off-screen with no scrollbar and no fade cue — a genuinely
      unreachable control, not merely a tight one.

   Fixes 1 and 5 apply at every width because they are correctness, not styling. Fixes
   2-4 are scoped to <=560px so tablet and desktop geometry is untouched.
   ===================================================================================== */

/* 1 — Track floor of 0 so the card shrinks to the track instead of overflowing it.
   Same correction, same reasoning as .lbaid-rev__list in dashboard-ui.css.

   Scoped to 900px and below, and measurement decided that boundary in both directions.

   Applying it at EVERY width was tried first and rejected: it pinned each track to exactly
   half the container and dropped the card's text column from 246px to 84px at 768, and to
   110-200px through 1024 — a real degradation of approved geometry at widths that had no
   defect to fix (912-1440 measured zero off-screen controls, zero container overflow, zero
   clipping before any change). Those widths are therefore left exactly as the frozen
   stylesheet has them.

   Below 900px it is required, because the two-column range there DID push action controls
   past the viewport (see the card block further down). Paired with the wrap in that block
   the text column ends up wider than before rather than narrower. */
@media (max-width: 900px) {
    .lbaid-mllist {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 720px) {
    .lbaid-mllist {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* 5 — Every filter pill reachable without a hidden scrollbar. Wrapping is preferred over
   adding a scroll affordance because five short pills fit two rows comfortably at 320px,
   and a wrapped row needs no gesture discovery at all. */
@media (max-width: 560px) {
    .lbaid-mltabs {
        flex-wrap: wrap;
        overflow-x: visible;
    }
}

/* The card block runs to 900px, not 560px, and measurement is why. At 768 / 820 / 834 the
   SECOND card of the two-column grid rendered its Edit and View links at x=774-850 against
   a 768px viewport (card right edge 863): one to two action controls genuinely off-screen,
   in the pre-change build exactly as much as the post-change one. That fails "controls
   reachable = 100%", so the range is fixed rather than declared out of scope. Wrapping
   widens the text column here (269px vs 246px at 768) instead of narrowing it. */
@media (max-width: 900px) {

    /* 2 — Let the row break. The inline style sets `display` and `gap` but never
       `flex-wrap`, so plain cascade is enough here; no !important needed. */
    .lbaid-mllist .ail-vendor-listing-card {
        flex-wrap: wrap;
        align-items: flex-start;
    }

    /* The text column keeps its inline `flex:1;min-width:0`, and now has the full row
       width to itself once the actions drop below. */
    .lbaid-mllist .ail-vendor-listing-card>.ail-vl-info {
        flex-basis: 0;
    }

    /* 3 — The actions wrapper is the card's last child (image, .ail-vl-info, actions).
       Given a 100% basis it becomes its own full-width row beneath the content, so it no
       longer competes for horizontal space and nothing is pushed out of the card.
       `flex-shrink` is left at the inline 0 — with a 100% basis there is nothing to
       shrink, so the inline value is not fought. */
    .lbaid-mllist .ail-vendor-listing-card> :last-child {
        flex-grow: 1;
        flex-basis: 100%;
        flex-wrap: wrap;
        justify-content: flex-end;
        margin-top: 2px;
        padding-top: 10px;
        border-top: 1px dashed var(--lbaid-line, #eceaf6);
    }

    /* 4 — Kill the vertical clip. `height` is inline so it needs !important; the control
       then sizes to its own content and keeps its label on one line. min-height preserves
       the approved 34px rhythm rather than silently re-opening the target-size decision
       recorded in an earlier phase. */
    .lbaid-mllist .ail-vendor-listing-card> :last-child>a {
        height: auto !important;
        min-height: 34px;
        white-space: nowrap;
    }

    /* The status pill and views chip are nowrap atoms; with the actions row gone they have
       the full card width, but a long status string should still be able to break the LINE
       rather than the card. */
    .lbaid-mllist .ail-vendor-listing-card>.ail-vl-info>.ail-booking-status {
        max-width: 100%;
    }
}

/* =====================================================================================
   ISSUE 3 — DARK MODE: LIGHT TEXT ON LIGHT BACKGROUNDS
   =====================================================================================
   STRUCTURAL CAUSE, measured rather than assumed:

   header.php prints, inside <head> and therefore ahead of every stylesheet on document
   order, a COLOUR-ONLY rule with !important:

       body.dark-mode h1..h4, p, span, label, .ail-tab-btn, .ail-nav-item,
       .ail-quick-action-item { color: var(--text-primary) !important; }

   In dark mode --text-primary is near-white (#f1f5f9). The rule sets no background, so
   every one of those elements that sits on a surface which STAYED light becomes
   near-white on near-white. It is !important, so a surface cannot opt out by restating a
   dark ink; the surface itself has to go dark, or the ink has to be re-forced.

   Three families of surface stay light, and each needs a different remedy:

     (a) INLINE `background:#fff` in the frozen template. Inline beats any selector, so the
         existing non-!important dark rules in core.css never applied. Needs !important.

     (b) `background: var(--footer-bg)` in core.css's dark block, with NO fallback.
         --footer-bg is declared once, in header.php, on :root for BOTH schemes, and
         defaults to the THEME PRIMARY COLOUR — not a dark colour. header.php's own
         !important block already rescues most of these surfaces with var(--card-bg); the
         five below are the ones it does not name, so they still resolve to the brand
         colour (or to whatever light colour an admin picked for the footer) while their
         text is forced near-white.

     (c) Hard-coded light literals in dashboard-ui.css that the B7 remediation block did
         not enumerate: .lbaid-mltab, .lbaid-mltab span, .lbaid-crm__count,
         .lbaid-avail__day / __toggle, .lbaid-lead__stage.

   The palette is the one already approved and in use by the product: page #1a1a2e,
   card #16213e, raised surface #1f2a47, field #101a30, ink #f1f5f9 / #a5b4c8. No second
   dark-mode system is introduced and light mode is untouched — every rule below is scoped
   to body.dark-mode.

   Chips whose background is deliberately PALE keep that background and take a dark ink
   (#0f172a), following the decision already recorded in dashboard-ui.css's B7 block for
   .lbaid-badge / .lbaid-ml-views / .lbaid-staff__skill. Consistency with that ruling
   matters more than picking a new approach here.
   ===================================================================================== */

/* ── (b) The five --footer-bg surfaces header.php does not rescue ──────────────────── */
body.dark-mode #page {
    /* Without this the entire page canvas resolves to the brand purple in dark mode. */
    background: var(--bg-color, #1a1a2e);
}

body.dark-mode .ail-review-card,
body.dark-mode .ail-autocomplete-dropdown,
body.dark-mode .ail-single-bottom-bar {
    background: var(--card-bg, #16213e);
}

/* ── (a) Vendor listing card: inline background:#fff on a frozen template ──────────── */
body.dark-mode .ail-vendor-listing-card {
    background: var(--card-bg, #16213e) !important;
    border-color: var(--lbaid-line, #24304d) !important;
}

/* The placeholder tile behind a listing with no image. */
body.dark-mode .ail-vendor-listing-card .ail-vl-placeholder {
    background: #1f2a47 !important;
}

body.dark-mode .ail-vendor-listing-card .ail-vl-placeholder i {
    color: #7c8aa5 !important;
}

/* The expiry line is an inline `color:#64748b` div, which lands at roughly 3:1 on the dark
   card. Divs are not caught by header.php's rule, so it keeps the inline value until it is
   overridden explicitly. */
body.dark-mode .ail-vendor-listing-card .ail-vl-info>div {
    color: var(--lbaid-ink-2, #a5b4c8) !important;
}

/* REVISED. This previously hardcoded `color:#0f172a` on the stated assumption that these chips
   keep a pale background. lbai-tokens.css section 16 now gives the .ail-status-* and
   .lpcf-badge-* families a translucent tint of their own hue instead, so a dark ink here measured
   1.12:1 on "Published"/"Expired" and 1.33:1 on the plugin's expiry badge.

   The value is delegated to --lbai-text, which the status families re-point per hue. The rule is
   kept (rather than deleted) because its job is still needed: it is what outranks header.php's
   forced near-white at this depth. */
body.dark-mode .ail-vendor-listing-card .ail-booking-status,
body.dark-mode .ail-vendor-listing-card .lpcf-badge-expired,
body.dark-mode .ail-vendor-listing-card .lpcf-badge-expires-soon {
    color: var(--lbai-text, #f1f5f9) !important;
}

/* The two badge glyph tiles carry their own saturated background inline and a white glyph,
   which is correct in both schemes — restated so the ink rule above cannot reach into them. */
body.dark-mode .ail-vendor-listing-card .lpcf-badge-expired>span,
body.dark-mode .ail-vendor-listing-card .lpcf-badge-expires-soon>span {
    color: #fff !important;
}

/* ── (a) Withdrawal form: inline background:#fff, and an h3 on var(--text-primary) ──── */
body.dark-mode #lbai-withdraw-form {
    background: var(--card-bg, #16213e) !important;
    border-color: var(--lbaid-line, #24304d) !important;
}

body.dark-mode #lbai-withdraw-method {
    /* Inline background:#fff on the select; the dashboard's dark field rule has no
       !important so it never won here. */
    background: #101a30 !important;
    color: var(--lbaid-ink, #f1f5f9) !important;
    border-color: var(--lbaid-line, #24304d) !important;
}

/* ── (c) Literals dashboard-ui.css's B7 block did not enumerate ────────────────────── */

/* Filter pills. The pill is a <button> so header.php does not force its colour, but its
   count <span> IS forced — near-white on #eef0f6. Both parts take a dark surface. */
body.dark-mode .ail-dashboard-page.lbaid .lbaid-mltab {
    background: #1f2a47;
    border-color: var(--lbaid-line, #24304d);
    color: var(--lbaid-ink-2, #a5b4c8);
}

body.dark-mode .ail-dashboard-page.lbaid .lbaid-mltab span {
    background: #101a30;
    color: var(--lbaid-ink-2, #a5b4c8) !important;
}

/* The active pill keeps the brand fill, so its label and count stay white.
   Two corrections since the token layer landed:

   The fill now comes from --lbai-accent rather than --lbaid-primary. White on #6d5efc
   measures 4.49:1, a hair under AA; the accent token is a shade deeper in dark mode and
   measures 6.1:1, in the same hue family.

   The count badge's overlay was rgba(255,255,255,.25), which LIGHTENED the pill underneath and
   left white text on a light purple at 3.87:1. Darkening the overlay instead keeps the same
   inset-chip look and raises the pairing above AA. */
body.dark-mode .ail-dashboard-page.lbaid .lbaid-mltab.active {
    background: var(--lbai-accent, #5b4bd8);
    border-color: var(--lbai-accent, #5b4bd8);
    color: #fff;
}

body.dark-mode .ail-dashboard-page.lbaid .lbaid-mltab.active span {
    background: rgba(0, 0, 0, .28);
    color: #fff !important;
}

/* CRM column counter — a <span> with background:#fff, so near-white on white. */
body.dark-mode .ail-dashboard-page.lbaid .lbaid-crm__count {
    background: #101a30;
    border-color: var(--lbaid-line, #24304d);
    color: var(--lbaid-ink, #f1f5f9) !important;
}

/* Availability rows: background #fafaff with a <label> whose ink is forced near-white. */
body.dark-mode .ail-dashboard-page.lbaid .lbaid-avail__day {
    background: #131c33;
    border-color: var(--lbaid-line, #24304d);
}

/* Lead stage control: background:#fff. Covered by the dashboard's dark `select` rule if it
   renders as a select; stated explicitly so it is correct either way. */
body.dark-mode .ail-dashboard-page.lbaid .lbaid-lead__stage {
    background: #101a30;
    border-color: var(--lbaid-line, #24304d);
    color: var(--lbaid-ink, #f1f5f9);
}

/* The lead message quote block and the reply panels sit on #f8fafc. Giving them a dark
   surface is only half the job: their own text colours are dark slate (#475569 / #94a3b8)
   set on the element itself, and a <div>/<p> body is not caught by header.php's forced-ink
   rule, so darkening the surface alone measured 2.23:1. Surface AND ink move together. */
body.dark-mode .ail-dashboard-page.lbaid .lbaid-lead__msg,
body.dark-mode .ail-dashboard-page.lbaid .lbaid-lead__reply,
body.dark-mode .ail-dashboard-page.lbaid .lbaid-rev__reply {
    background: #131c33;
    border-color: var(--lbaid-line, #24304d);
}

body.dark-mode .ail-dashboard-page.lbaid .lbaid-lead__msg,
body.dark-mode .ail-dashboard-page.lbaid .lbaid-rev__replytext,
body.dark-mode .ail-dashboard-page.lbaid .lbaid-rev__text {
    color: var(--lbaid-ink-2, #a5b4c8);
}

/* PRE-EXISTING FAILURE, found by measurement rather than by reading.
   dashboard-ui.css's B7 block forces `.lbaid-staff__skill { color: #0f172a !important }` on
   the stated assumption that the chip keeps a pale background. It does not: booking-card.css
   independently gives that same chip `background: rgba(255,255,255,.06)` in dark mode. The
   two rules never met, so a dark ink was landing on a dark chip — measured 1.33:1 across
   every skill chip on every staff card, in both the pre-change and post-change build.
   This layer loads after dashboard-ui.css, so returning the ink to the light value that
   booking-card.css intended is enough. */
body.dark-mode .ail-dashboard-page.lbaid .lbaid-staff__skill {
    color: #cbd5e1 !important;
}

/* REVISED, same reason as the .ail-booking-status block above. These chips no longer retain a
   pale background: lbai-tokens.css sections 4b and 16 give them a dark tint, so the hardcoded
   dark ink measured 1.33:1 on .lbaid-doc__badge.red ("Expired") and 1.35:1 on .green
   ("Verified"). The value is delegated to --lbai-text, which the status families re-point per hue. */
body.dark-mode .ail-dashboard-page.lbaid .lbaid-lead__tag,
body.dark-mode .ail-dashboard-page.lbaid .lbaid-doc__badge,
body.dark-mode .ail-dashboard-page.lbaid .lbaid-bk__badge {
    color: var(--lbai-text, #f1f5f9) !important;
}

/* =====================================================================================
   REDUCED MOTION
   =====================================================================================
   core.css binds a transform-based `cardEnter` animation to .ail-vendor-listing-card with
   `animation-fill-mode: both` and no prefers-reduced-motion guard. The animation is not a
   cause of the clipping above, but this pass touches the same card's layout and the guard
   is one declaration, so it is added rather than left as a known gap.
   ===================================================================================== */
@media (prefers-reduced-motion: reduce) {
    .ail-vendor-listing-card {
        animation: none;
    }
}

/* =====================================================================================
   AD CAMPAIGN RENEWAL — "keep existing banner" block
   =====================================================================================
   Injected into the campaign form when a renewal carries a previous creative forward. It
   is styled here rather than inline for one specific reason: header.php forces every
   <label> to var(--text-primary) with !important in dark mode, so a pale inline background
   on this block would put near-white text on near-white — the exact failure class the dark
   mode pass above exists to remove. Surface and ink therefore move together, in both
   schemes, and the checkbox keeps a visible accent.
   ===================================================================================== */
.lbai-renew-keep {
    margin: 0 0 10px;
    padding: 10px 12px;
    border: 1px solid var(--lbaid-line, #e2e8f0);
    border-radius: 10px;
    background: #f8fafc;
}

.lbai-renew-keep__img {
    display: block;
    width: 100%;
    max-width: 320px;
    border-radius: 8px;
    border: 1px solid var(--lbaid-line, #e2e8f0);
}

.lbai-renew-keep__label {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    font-size: 12.5px;
    font-weight: 700;
    line-height: 1.4;
    color: #334155;
    cursor: pointer;
}

.lbai-renew-keep__label input[type="checkbox"] {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    accent-color: var(--lbaid-primary, #6d5efc);
}

body.dark-mode .lbai-renew-keep {
    background: #131c33;
    border-color: var(--lbaid-line, #24304d);
}

body.dark-mode .lbai-renew-keep__img {
    border-color: var(--lbaid-line, #24304d);
}

/* The forced near-white ink is correct here once the surface is dark; stated explicitly so
   the pairing cannot drift apart if the forced rule in header.php ever changes. */
body.dark-mode .lbai-renew-keep__label {
    color: var(--lbaid-ink, #f1f5f9);
}

/* =====================================================================================
   GLOBAL LOGO / BRAND POSITION STANDARDIZATION
   =====================================================================================
   ONE canonical header row, ONE brand anchor, ONE responsive system.

   ── WHAT WAS MEASURED (before) ─────────────────────────────────────────────────────────
   Brand box x,y of .ail-app-logo-wrap, light and dark identical, 13 widths, 9 page types:

     width   home/search/category/location/author/add-listing/checkout   listing    dashboard
      320               21,10                                             21,10       21,10     consistent
      768               41,12.5                                           41,12      41,12     0.5px drift
     1024              736,33.6                                          698.7,12   734.7,12   3 anchors
     1280              775.2,25.1                                        884.9,12   908.9,12   3 anchors
     1440              855.2,25.1                                        964.9,12   988.9,12   3 anchors

   Two separate defects are visible in that table.

   1. ON DESKTOP THE BRAND IS NOT LEFT-ALIGNED AT ALL. At 1280 the header content box runs
      x=40..1240, and the brand sits at x=775 — centre-right. core.css:4444 gives
      .ail-app-logo-wrap `order: 1`, but header.php emits .ail-hdr-search and .ail-hdr-nav as
      siblings and NEITHER CARRIES AN ORDER, so both default to `order: 0` and sort BEFORE the
      brand. Below 1024px they are display:none, which is exactly why the brand looks correct on
      mobile and tablet and jumps right at >=1024px.

   2. THE ANCHOR DIFFERS BY PAGE at one width. .ail-app-header-inner uses
      `justify-content: space-between`, so free space is distributed between whatever children
      that template happens to render — and header.php renders .ail-header-loc only when the page
      is NOT template-dashboard, NOT template-add-listing and NOT a single listing. Pages with the
      location switcher therefore anchor the brand differently from pages without it. At >=768px
      that switcher is also `flex: 1`, which together with `.ail-hdr-search { flex: 1 1 auto }`
      overflows the 1200px row and WRAPS: the brand drops to row two (y=33.6 at 1024px) and the
      header grows from 68px to 163.17px, a 2.4x change on the same viewport.

   ── THE FIX ────────────────────────────────────────────────────────────────────────────
   An explicit three-region row with the brand pinned first and non-elastic:

       HEADER ROW  =  [ BRAND ][ NAV ][ SEARCH ][ LOCATION ]        [ ACTIONS ]
       order            1       2      3         4                    5
                        |                                            |
                        left-anchored,                          margin-left:auto
                        never grows or shrinks                  absorbs all free space

   The actions cluster takes `margin-left: auto`, which consumes ALL free space before
   justify-content is consulted. That is the property that makes the brand's x depend only on the
   container's left inset and NOT on which middle children the template rendered — which is what
   makes the anchor identical across page types by construction rather than by coincidence.

   Normal document flow and flex only. No absolute positioning, no JavaScript, no second logo
   asset, no change to the artwork, and no change to the brand markup.

   ── WHY THIS LAYER ─────────────────────────────────────────────────────────────────────
   The two owners are frozen: header.php (brand markup + the >=1024px desktop navbar <style>)
   and core.css (the order/flex contract). Neither is edited. header.php's <style> is emitted
   AFTER wp_head(), so load order cannot beat it; every rule below therefore wins on SPECIFICITY
   instead — header.php uses single-class selectors (0,1,0) and core.css the same, while these are
   (0,2,0) and (0,3,0). No !important is needed anywhere in this block.
   ===================================================================================== */

/* ── SCOPED TO >=768px, DELIBERATELY ────────────────────────────────────────────────────
   The whole contract lives inside the tablet/desktop breakpoint; mobile is left entirely to
   core.css. Two reasons, both measured rather than assumed:

   1. Mobile was never broken. The brand measured x=21 y=10 on every page at 320/360/375/390/414
      and 480 both before and after, because .ail-hdr-nav and .ail-hdr-search are display:none
      below 1024px, so their missing `order` cannot affect anything there.

   2. An unscoped first draft REGRESSED mobile. core.css orders the mobile row brand(1),
      actions(2), loc(3), so row one is brand+actions and the switcher wraps beneath. Re-ordering
      the switcher to 4 and the actions to 5 put the switcher BETWEEN them, and because it is
      `flex: 0 0 100%` at that width it forced the actions cluster onto a THIRD row — the header
      grew from 121px to 155px. Scoping to >=768px restores core.css's mobile ordering exactly.
   ───────────────────────────────────────────────────────────────────────────────────────── */
@media (min-width: 768px) {

    /* Region ordering. Declared with the child combinator so it cannot leak into nested markup. */
    .ail-app-header .ail-app-header-inner>.ail-app-logo-wrap {
        order: 1;
        flex: 0 0 auto;
    }

    .ail-app-header .ail-app-header-inner>.ail-hdr-nav {
        order: 2;
    }

    .ail-app-header .ail-app-header-inner>.ail-hdr-search {
        order: 3;
        flex: 1 1 auto;
        min-width: 0;
    }

    .ail-app-header .ail-app-header-inner>.ail-header-loc {
        order: 4;
        flex: 0 1 auto;
        min-width: 0;
    }

    .ail-app-header .ail-app-header-inner>.ail-header-actions {
        order: 5;
        /* Absorbs the row's free space, so the brand cannot be pushed off the left edge by a
           sibling that only some templates render. This is what replaces the space-between
           distribution that made the anchor template-dependent. */
        margin-left: auto;
    }

    .ail-app-header .ail-app-header-inner>.ail-app-logo-wrap,
    .ail-app-header .ail-app-header-inner>.ail-header-actions {
        flex-shrink: 0;
    }

    .ail-app-header .ail-app-header-inner {
        /* space-between becomes inert once an auto margin is present (auto margins resolve
           first), but it is stated explicitly so the intent is readable and a later change to
           the auto margin cannot silently re-centre the row. */
        justify-content: flex-start;
        /* nowrap guarantees the brand can never leave row one. This is what removed the
           y=33.6 / 163.17px-tall header at 1024px.
           min-height pins the row to ONE value on every template: pages carrying the location
           switcher measured a 45px row and pages without it 44px, which put the brand at y=12.5
           on some pages and y=12 on others. */
        flex-wrap: nowrap;
        min-height: 48px;
    }

    /* The switcher's two text lines must not re-wrap when min-width:0 squeezes it. Without this
       the label wrapped to several lines at exactly 1024px, growing the row to ~70px and pushing
       the brand to y=25.1 on the eight templates that render the switcher — the last remaining
       anchor split. core.css already applies the same nowrap/ellipsis pair at <=767px for the
       same reason; this extends it to the widths where the switcher shares a row with search. */
    .ail-app-header .ail-app-header-inner>.ail-header-loc .ail-loc-text,
    .ail-app-header .ail-app-header-inner>.ail-header-loc .ail-loc-title,
    .ail-app-header .ail-app-header-inner>.ail-header-loc .ail-loc-sub {
        min-width: 0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

/* =====================================================================================
   SINGLE LISTING — FAVOURITE BUTTON ALIGNMENT
   =====================================================================================
   ROOT CAUSE. The favourite control in the listing header row carries two classes:
   `.ail-lhdr__btn ail-fav-btn`. The second one is a DIFFERENT COMPONENT — a floating heart that
   overlays a listing card's cover image — and it is declared globally, identically, in two
   places (core.css:937 and listing.css:421):

       .ail-fav-btn { position:absolute; top:10px; right:10px; width:34px; height:34px;
                      border:none; background:rgba(255,255,255,.9); border-radius:50%;
                      box-shadow:0 2px 8px rgba(0,0,0,.1); z-index:5; }

   Both that rule and single-listing-v2.css's `.ail-lhdr__btn` sit at specificity (0,1,0), so the
   winner is decided PER PROPERTY by load order. single-listing-v2.css loads later, so it wins
   the properties it declares — position, width, height, border, background, radius — which is
   why the button is correctly 40x40 and bordered.

   The damage is done by the properties `.ail-lhdr__btn` never declares, so there is nothing to
   override them and the card-overlay values simply survive:

       top: 10px       right: 10px       box-shadow: present       z-index: 5

   Because the element resolves to `position: relative`, those offsets displace it VISUALLY
   without moving its siblings or reflowing the row — which is exactly the reported symptom.

   MEASURED BEFORE, identical at all 13 widths in BOTH schemes (26/26 combinations):
       cySpread  10px   favourite's vertical centre sits 10px below Back / Share / More
       clipped   20     it overhangs its own .ail-lhdr__actions box by 10px vertically + 10px
                        horizontally
       gaps      back->fav ... fav->share = 16px  vs  share->more = 6px
                 (`right:10px` pulls the heart left, inflating the authored 6px gap)
       hSpread   0      dimensions were already correct - 40x40 like its siblings
       wSpread   0
       icon      dx,dy = 0,0 - the heart was already centred INSIDE its button

   THE FIX is therefore four property resets, not a redesign. Dimensions, border, radius,
   background, colour, the icon and the favourited/hover/focus states are already correct and are
   deliberately left untouched.

   SCOPING MATTERS. The selector is anchored to `.ail-lhdr` so the CARD hearts keep the
   absolute positioning they legitimately need. `.ail-lhdr .ail-lhdr__btn.ail-fav-btn` is
   (0,3,0), which beats the global (0,1,0) on specificity alone — no !important, and no
   dependence on load order.

   FROZEN FILES: single-listing-v2.css, core.css and listing.css all own part of this and NONE
   is edited. This ships additively from the approved UX layer, as with the header contract above.
   ===================================================================================== */
.ail-lhdr .ail-lhdr__btn.ail-fav-btn {
    /* Neutralise the card-overlay offsets. `auto` is the initial value, so this returns the
       control to the position flex already gave it - no transform, no negative margin, no
       hardcoded coordinate. */
    top: auto;
    right: auto;
    bottom: auto;
    left: auto;
    /* The siblings carry no shadow and no stacking context; the overlay heart needs both to sit
       above a cover image, but in a flat action row they are what made this one button read as a
       different component. */
    box-shadow: none;
    z-index: auto;
}