/**
 * lbai-phase-f.css — Phase F additive UI/UX and accessibility layer.
 *
 * WHY THIS FILE EXISTS
 * The stylesheets that own most of the surfaces Phase F touches are frozen by earlier phases
 * (core.css, dashboard.css, dashboard-ui.css, single-listing-v2.css). Corrections that belong to
 * those surfaces are applied additively from here, after them in the cascade, so ordinary cascade
 * order is enough and broad !important is not used.
 *
 * ─────────────────────────────────────────────────────────────────────────────────────────────────
 * WHAT THIS FILE DELIBERATELY DOES **NOT** CONTAIN, AND WHY
 * ─────────────────────────────────────────────────────────────────────────────────────────────────
 * The first draft of this layer carried spacing, radius, modal and dark-mode blocks. Measuring the
 * product in a real browser (pf_css_audit.mjs, pf_geom.mjs, pf_geom2.mjs) showed 91 of its 129
 * selectors matched nothing at all, and that the rules which DID match were either restating what
 * the product already does or quietly redesigning approved geometry. Every one of those blocks was
 * removed. What the measurements found:
 *
 *   F10 spacing ladder — ALREADY CORRECT. .site-container measured 16px gutters and a 1200px cap at
 *       390px, and 24px gutters at 1280px, without this layer. The draft rules restated those exact
 *       numbers, and their mobile card-padding rule would have changed the home card from 10px to
 *       12px and the search list card from 0px to 12px — an unrequested visual change. Removed.
 *
 *   F11 card consistency — ALREADY CORRECT. .lbai-card measured a 14px radius already. Removed.
 *
 *   F12 one modal/sheet contract — ALREADY CORRECT. With the filter sheet open at 390px the panel
 *       measured top=127 height=717 fully inside the viewport, and .ail-srch__sheet-body reported
 *       overflow-y:auto and was genuinely scrollable. The draft's selectors (.ail-modal__dialog,
 *       .ail-sheet__panel …) do not exist in this product at all. Removed.
 *
 *   F13 dark mode — ALREADY OWNED. listing-card.css and core.css implement a complete dark palette
 *       with recorded contrast decisions (#16213e card surface, per-pill pairs, 4.5:1 notes) and use
 *       !important on text colour to defeat an inline rule in header.php. The draft would have
 *       repainted those surfaces with a DIFFERENT palette — a second dark-mode system fighting the
 *       first. Removed; dark mode is verified rather than overridden.
 *
 *   F6 target size, partially — ALREADY OWNED for three controls. .lbai-card__fav::after,
 *       .lbai-badges__more::after and .ail-lhdr__btn::after already deliver enlarged hit areas, and
 *       an earlier phase (P33) deliberately CONSTRAINED the badges one after measuring that its
 *       overhang was swallowing taps meant for the rating row. Re-expanding them here would undo a
 *       ratified decision, so they are left exactly as they are and their residual numbers are
 *       reported instead of silently changed.
 *
 * Scope discipline: every selector below was verified to match real elements on a real page.
 *
 * @package listing-by-atul-ingale
 */

/* =====================================================================
   TOKENS — local to this layer.
   ===================================================================== */
:root {
   --pf-target: 44px;
   /* The product's own focus colour, so this layer does not introduce a second accent. */
   --pf-focus: var(--primary-color, #6d5efc);
}

/* =====================================================================
   F5 — SKIP LINK
   This element is created by this phase (functions.php, wp_body_open), so
   nothing else styles it. Off-screen until focused, then pinned top-left so
   a keyboard user can see where they have landed.
   ===================================================================== */
.lbai-skip-link {
   position: absolute;
   left: -9999px;
   top: 0;
   z-index: 100000;
   padding: 12px 20px;
   min-height: var(--pf-target);
   display: inline-flex;
   align-items: center;
   background: #ffffff;
   color: #111827;
   border: 2px solid var(--pf-focus);
   border-radius: 0 0 8px 0;
   font-weight: 700;
   text-decoration: none;
}

.lbai-skip-link:focus,
.lbai-skip-link:focus-visible {
   left: 0;
   outline: 3px solid var(--pf-focus);
   outline-offset: 2px;
}

body.dark-mode .lbai-skip-link {
   background: #16213e;
   /* the dark surface already approved elsewhere in the product */
   color: #f1f5f9;
}

/* =====================================================================
   F5 — VISIBLE FOCUS WHERE THE PRODUCT SHOWS NONE
   =====================================================================
   Measured with this layer disabled, at 390px on the homepage:
     .ail-fav-btn          outline: solid 2px rgb(83,42,234)   — already good
     .lbai-card__title-link outline: auto 1px                  — browser default only
     .ail-field-input      outline-style: NONE                 — no focus indicator at all
   So the gap is real but partial. :focus-visible is used so a mouse user never
   sees a ring they did not ask for, and the colour is the product's own accent
   rather than a new one.
   ===================================================================== */
a:focus-visible,
button:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible {
   outline: 3px solid var(--pf-focus);
   outline-offset: 2px;
   border-radius: 4px;
}

/* Text inputs are the measured worst case: core.css sets outline:none on .ail-field-input, which
   removes the only indicator a keyboard user had. The ring is restored and paired with a soft glow
   so it reads as focus rather than as a validation error. */
input:focus-visible,
.ail-field-input:focus,
.ail-field-input:focus-visible {
   outline: 3px solid var(--pf-focus);
   outline-offset: 1px;
}

/* F14 — the two search fields the rule above could not reach.
   ------------------------------------------------------------------
   Measured with a keyboard on the authenticated dashboard at 1440px: `input[type="search"]`
   in the header and `#ail-city-search` in the city picker both matched :focus-visible yet
   computed `outline-style: none`, while `#lbaid-search` in the dashboard topbar showed the
   ring correctly. The difference is not the cascade order — it is where the competing
   declaration lives:

     header.php:825  .ail-hdr-search input { outline: none; }   (inline <style>, frozen)
     core.css:177    .ail-search-input input { outline: none; }

   Both are (0,1,1), the same weight as `input:focus-visible` above, and header.php's block
   is printed after wp_head() so at equal specificity it wins on order. Raising the weight
   here settles it without touching a frozen file and without a blanket !important: the
   child selectors below are (0,2,1) and the id is (1,0,0), so each outranks its competitor
   outright. Scope is deliberately narrow — only these two fields, only on focus. */
.ail-hdr-search>input:focus-visible,
.ail-search-input>input:focus-visible,
#lbaid-search:focus-visible {
   outline: 3px solid var(--pf-focus);
   outline-offset: 1px;
}

/* Two controls put the suppression in an inline `style` attribute, which specificity cannot
   settle. Both are emitted by footer.php, which is frozen:

     footer.php:137  <input type="text" id="ail-city-search" ... style="...outline:none;...">
     footer.php:628  <button id="ail-back-to-top" ... style="outline:none; border:none;">

   An inline declaration outranks every selector in every stylesheet, so no id, no descendant
   chain and no load order reaches it. `!important` is the only mechanism CSS provides, which is
   why it appears here and nowhere else in this file. Each rule is scoped to one id in one state,
   so neither can leak.

   The city field is the primary control of the city picker. Back-to-top was found by walking the
   dashboard BACKWARDS with Shift+Tab (F14): it sits late enough in the document that a forward
   Tab sweep of the first two dozen stops never reaches it, so it had gone unmeasured while being
   fully keyboard reachable. Its accessible name was already correct (aria-label="Scroll to top");
   only the indicator was missing. */
#ail-city-search:focus-visible,
#ail-back-to-top:focus-visible {
   outline: 3px solid var(--pf-focus) !important;
   outline-offset: 2px;
}

body.dark-mode a:focus-visible,
body.dark-mode button:focus-visible,
body.dark-mode input:focus-visible,
body.dark-mode select:focus-visible,
body.dark-mode textarea:focus-visible,
body.dark-mode [tabindex]:focus-visible,
body.dark-mode [role="button"]:focus-visible,
body.dark-mode .ail-field-input:focus,
body.dark-mode .ail-field-input:focus-visible,
body.dark-mode .ail-hdr-search>input:focus-visible,
body.dark-mode .ail-search-input>input:focus-visible,
body.dark-mode #lbaid-search:focus-visible {
   outline-color: #c4b5fd;
   /* the product's dark accent family */
}

/* Has to match the !important above, or the dark ring loses to the light declaration. */
body.dark-mode #ail-city-search:focus-visible,
body.dark-mode #ail-back-to-top:focus-visible {
   outline-color: #c4b5fd !important;
}

/* =====================================================================
   F5 — HONEYPOTS
   The JS layer removes them from the tab order and hides them from assistive
   technology. This makes them unreachable by pointer as well, without relying
   on the owning template's inline style. Two ids only; !important is required
   here solely to defeat that inline style.
   ===================================================================== */
#catp-q-hp,
#ail-enquiry-company-url {
   position: absolute !important;
   left: -9999px;
   width: 1px;
   height: 1px;
   opacity: 0;
   pointer-events: none;
}

/* =====================================================================
   F5 — LISTING CARD TITLE, AFTER THE NESTING INVERSION
   =====================================================================
   This phase moved the link INSIDE the heading (it used to be
   <a><h3>…<button>…</button></h3></a>, which nested a button inside a link).
   The heading is now the flex parent that the badge cluster's `flex: 0 0 100%`
   relies on to take its own row, and the link must still read as the title.
   ===================================================================== */
.lbai-card__title {
   display: flex;
   flex-wrap: wrap;
   align-items: baseline;
}

.lbai-card__title>.lbai-card__title-link {
   color: inherit;
   font: inherit;
   text-decoration: none;
}

.lbai-card__title>.lbai-card__title-link:hover,
.lbai-card__title>.lbai-card__title-link:focus-visible {
   text-decoration: underline;
}

/* =====================================================================
   F6 — 44x44 TARGETS
   =====================================================================
   Measured box sizes with this layer disabled, at 390px:
     .ail-sheet-close-btn  28x30      the × on every bottom sheet
     .ail-hdr-heart        22x22      header saved-items icon
     .ail-open-login       28x28      header sign-in icon
     .ail-srch__back       22x22      search page back arrow
     .ail-srch__sheet-clear 20x17     "Clear" in the filter sheet head
     .ail-srch__ctrl-btn   90x33      Filters / Sort buttons
     .lbai-hslider__nav    38x38      slider arrows
     .ail-catp__bookmark   40x40      category hero bookmark
     .ail-catp__viewall    52x16      section "View all" link
     .ail-catp__tag        67x32      category tag chips
     .ail-auth-tab        171x36      Sign In / Sign Up tabs
     .ail-srch__empty-btn 318x40      empty-state actions
   Two techniques, chosen per control by whether growing the box would reflow
   anything:
     DIRECT  used where the control is absolutely positioned, full-width, or has
             room in its row — the box itself becomes 44px.
     OVERLAY used where growing the box would move neighbours — a centred,
             transparent pseudo-element carries the hit area and the visible
             control keeps its exact size. This is the same technique
             .lbai-card__fav::after already uses in listing-card.css.
   ===================================================================== */

/* ── DIRECT ─────────────────────────────────────────────────────────── */

/* Absolutely positioned: nothing reflows. */
.lbai-hslider__nav,
.ail-catp__bookmark {
   min-width: var(--pf-target);
   min-height: var(--pf-target);
}

/* Sheet close button: top-right of a sheet header with space around it. */
.ail-sheet-close-btn {
   min-width: var(--pf-target);
   min-height: var(--pf-target);
   display: inline-flex;
   align-items: center;
   justify-content: center;
   line-height: 1;
}

/* Full-width or near-full-width buttons: extra height costs no horizontal room and nothing beside
   them moves. Measured heights before this rule: .ail-auth-tab 36, .ail-srch__empty-btn 40,
   .ail-action-btn 36, .ail-srch__fb-btn 37, .ail-footer-pwa-btn 37. */
.ail-auth-tab,
.ail-srch__empty-btn,
.ail-action-btn,
.ail-srch__fb-btn,
.ail-footer-pwa-btn {
   min-height: var(--pf-target);
}

/* The back arrow leads the search row; the search field next to it is flex:1 and absorbs the
   extra width, so this cannot squeeze anything. */
.ail-srch__back {
   min-width: var(--pf-target);
   min-height: var(--pf-target);
   align-items: center;
   justify-content: center;
}

/* ── OVERLAY ────────────────────────────────────────────────────────── */
/* The search page's sticky control row (.ail-srch__loc 143x33, .ail-srch__nearme 94x33,
   .ail-srch__ctrl-btn 90x33) and the voice button inside the search field (30x30) all get the hit
   area without growing: raising their height would raise the sticky header of the whole results
   page, which is approved geometry. */
.ail-hdr-heart,
.ail-open-login,
.ail-srch__sheet-clear,
.ail-srch__ctrl-btn,
.ail-srch__loc,
.ail-srch__nearme,
.ail-voice-search-btn,
.ail-catp__viewall,
.ail-catp__tag {
   position: relative;
}

.ail-hdr-heart::after,
.ail-open-login::after,
.ail-srch__sheet-clear::after,
.ail-srch__ctrl-btn::after,
.ail-srch__loc::after,
.ail-srch__nearme::after,
.ail-voice-search-btn::after,
.ail-catp__viewall::after,
.ail-catp__tag::after {
   content: "";
   position: absolute;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -50%);
   width: 100%;
   height: 100%;
   min-width: var(--pf-target);
   min-height: var(--pf-target);
   /* No paint: this exists only to be tappable. */
}

/* =====================================================================
   F13 — DARK-MODE CONTRAST REPAIRS WHOSE OWNER IS FROZEN
   =====================================================================
   The homepage, category and search dark-mode gaps were fixed at source, in the editable stylesheets
   that own those components (home.css, category-page.css, search-page.css, listing-card.css). Four
   measured failures are left, and each one is produced by a file this phase may not edit, so they are
   corrected here instead. Every value comes from the palette the product already uses in dark mode.

   Measured before these rules, at 390px in dark mode:
     a#ail-show-forgot        #2563eb on #16213e  3.08   "Forgot Password?"   owner footer.php (frozen)
     a.ail-gps-btn            #3b82f6 on #16213e  4.32   "Use My Current Location"  built by core.js (frozen)
     span.ail-loc-title/-sub  #1f2937 on #16213e  1.08   DARK text on the dark header, owner core.css (frozen)
     .ail-pwa-btn-icon/-text  #f1f5f9 on #8b7dff  2.96   "Install App"        owner core.css (frozen)
   ===================================================================== */

/* footer.php sets this colour in a style ATTRIBUTE, so only !important can reach it. Scoped to one id. */
body.dark-mode #ail-show-forgot,
body.dark-mode #ail-back-signin {
   color: #93c5fd !important;
}

body.dark-mode .ail-gps-btn {
   color: #93c5fd !important;
}

/* "Missing your city? Request it →" at the foot of the city sheet. footer.php:281 sets
   `style="color:#3b82f6"` inline, which measured 4.32:1 on the sheet surface — just under 4.5. An
   inline declaration can only be reached with !important, and the selector is scoped to that one
   mailto link inside the city sheet. */
body.dark-mode #ail-city-sheet a[href^="mailto:"] {
   color: #93c5fd !important;
}

/* The header's own dark surface is correct; only this pair of labels kept a near-black colour, which
   header.php's forced light-text rule does not reach because a more specific rule wins. */
body.dark-mode .ail-loc-title,
body.dark-mode .ail-loc-sub {
   color: #f1f5f9 !important;
}

/* White on the dark-mode accent #8b7dff measures 2.96:1. The deeper violet from the same approved
   family clears 4.5:1 and keeps the button's identity. */
body.dark-mode .ail-footer-pwa-btn {
   background: #4c1d95 !important;
   border-color: #6d28d9 !important;
}

/* =====================================================================
   REDUCED MOTION
   The Escape/focus contract added in this phase is motion-free; these are the
   surfaces it opens and closes, so they must not animate for a visitor who has
   asked for less motion.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {

   .ail-booking-sheet,
   .ail-srch__sheet,
   .ail-sheet-overlay,
   .ail-srch__overlay,
   .lbai-badges__panel {
      transition: none !important;
      /* scoped to five sheet/overlay classes: the transition it overrides is itself declared
		   with a shorthand in frozen CSS, and honouring the user's motion preference is not
		   something a later rule should be able to re-enable by accident. */
      animation: none !important;
   }
}