/* =====================================================================
   UX Polish v1.0.0 — small, site-wide fixes (26.09.2026, UX fix pass).
   Every block below traces to a specific finding in
   reports/ux_review_20260926/. Uses deal-design-system's --ds-* tokens
   with literal fallbacks, same convention as every other plugin here.
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. Prevent horizontal page-drag, network-wide safety net.
   03_mobile_ux.md #4: a plugin's own pill row can grow past its
   container and drag the WHOLE PAGE sideways (measured
   document.documentElement.scrollWidth 545px on a 390px viewport). The
   real offending containers are fixed at their source (blog-deal-feed's
   own CSS), but this is a permanent backstop against the same class of
   bug recurring anywhere else, present or future. overflow-x:clip (not
   hidden) so it never fights position:sticky along the Y axis, and
   because it clips without creating a scroll container the way
   overflow-x:hidden technically can.
   --------------------------------------------------------------------- */
html {
    overflow-x: hidden; /* fallback for browsers without overflow-x:clip */
    overflow-x: clip;
    max-width: 100%;
}

body {
    overflow-x: hidden;
    overflow-x: clip;
    max-width: 100%;
}

/* ---------------------------------------------------------------------
   2. Back-to-top button: 31.5x31.5px -> >=44px, repositioned so it stops
   sitting on top of real content.
   03_mobile_ux.md #6: measured bounding box 31.5x31.5px (Astra's
   `#ast-scroll-top{width:2.1em;height:2.1em;font-size:15px}` = 31.5px),
   below the 44x44px WCAG 2.5.5 / Apple HIG minimum, and positioned flush
   against the last visible content (covering a category chip / discount
   badge / percentage figure depending on the page).
   --------------------------------------------------------------------- */
#ast-scroll-top {
    width: 48px !important;
    height: 48px !important;
    line-height: 48px !important;
    font-size: 20px !important;
    /* Nudge up + in from the corner so it doesn't sit flush against the
       last line of on-page content. */
    bottom: 24px !important;
    right: 16px !important;
    border-radius: 50% !important;
}

#ast-scroll-top .ast-icon.icon-arrow svg {
    width: 1.1em !important;
}

/* 27.09.2026 (vibecode audit workstream G): still overlapped the card's
   primary CTA on short mobile pages even after the size/position fix above
   — see js/ux-polish.js, which toggles this class via IntersectionObserver
   whenever a primary offer CTA is visible near the bottom of the viewport. */
#ast-scroll-top.uxp-cta-near {
    opacity: 0 !important;
    pointer-events: none !important;
    transition: opacity 0.15s ease;
}

/* ---------------------------------------------------------------------
   3. Footer heading-size consistency.
   01_visual_design.md #10: the middle footer column ("Oluline info")
   renders via an h2.widget-title (Astra default, 22px) while its
   neighbours ("Abi", "Kontakt") render via a Spectra/UAGB heading block
   (h5.uagb-heading-text) with a different size — a visibly inconsistent
   heading size once the columns stack on mobile. Force every heading in
   the footer widget area to the SAME size/weight regardless of which
   underlying block/markup produced it.
   --------------------------------------------------------------------- */
.footer-widget-area h1,
.footer-widget-area h2,
.footer-widget-area h3,
.footer-widget-area h4,
.footer-widget-area h5,
.footer-widget-area h6,
.site-footer .widget-title,
.site-footer .uagb-heading-text {
    font-size: 1.05rem !important;
    font-weight: 700 !important;
    line-height: 1.3 !important;
    margin: 0 0 12px !important;
    color: var(--ds-ink, #1a2332) !important;
}

/* ---------------------------------------------------------------------
   4. Header search placeholder contrast.
   01_visual_design.md #10: "Otsi soodukaid..." (Astra's built-in header
   search, .search-field) renders pale-green-on-white, close to failing
   WCAG AA. --ds-muted is the network's own AA-checked secondary-text
   token (see deal-design-system's own contrast notes).
   --------------------------------------------------------------------- */
.search-field::placeholder {
    color: var(--ds-muted, #5C6A7F) !important;
    opacity: 1 !important;
}

.search-field:-ms-input-placeholder {
    color: var(--ds-muted, #5C6A7F) !important;
    opacity: 1 !important;
}

/* ---------------------------------------------------------------------
   5. "pakkumise d" mid-word hyphenation bug.
   01_visual_design.md #10: a stat label ("Hooajalised pakkumised")
   overflows its card and browser auto-hyphenation splits it mid-word
   ("pakkumise" / "d"). Disabling automatic hyphenation site-wide is a
   safe, low-risk default for this project (no page here relies on
   justified, hyphenated body copy) and directly kills this bug
   regardless of which component's CSS turned hyphenation on.
   --------------------------------------------------------------------- */
body, body * {
    -webkit-hyphens: none !important;
    -ms-hyphens: none !important;
    hyphens: none !important;
}

/* ---------------------------------------------------------------------
   6. Styled WordPress search-results page
   03_mobile_ux.md #9. Card list matching the rest of the site's card
   language (logo tile via the shared .ds-logo primitive, name, optional
   excerpt) instead of Astra's bare default.
   --------------------------------------------------------------------- */
.uxp-search-primary {
    max-width: 800px;
    margin: 0 auto;
    padding: 24px 1rem 48px;
    box-sizing: border-box;
}

.uxp-search-header {
    margin-bottom: 16px;
}

.uxp-search-title {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--ds-ink, #1a2332);
    margin: 0 0 6px;
}

.uxp-search-title span {
    color: var(--ds-money-ink, #0F766E);
}

.uxp-search-count {
    font-size: 0.9rem;
    color: var(--ds-muted, #5C6A7F);
    margin: 0 0 16px;
}

/* WP core's get_search_form() output — light touch, matches site inputs */
.uxp-search-primary .search-form {
    display: flex;
    gap: 8px;
    margin: 0 0 24px;
}

.uxp-search-primary .search-form .search-field {
    flex: 1;
    min-width: 0;
    padding: 10px 14px;
    border: 1.5px solid var(--ds-line, #e0e7ee);
    border-radius: var(--ds-r, 12px);
    font-size: 0.95rem;
    box-sizing: border-box;
}

.uxp-search-primary .search-form .search-submit {
    padding: 10px 18px;
    border: none;
    border-radius: var(--ds-r, 12px);
    background: var(--ds-money-solid, #0F766E);
    color: #fff;
    font-weight: 600;
    cursor: pointer;
}

.uxp-sr-grid {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.uxp-sr-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--ds-surface, #fff);
    border: 1px solid var(--ds-line, #e6e9ef);
    border-radius: var(--ds-r-lg, 16px);
    box-shadow: var(--ds-shadow, 0 1px 2px rgba(16,24,40,.04));
    text-decoration: none !important;
    transition: box-shadow .15s ease, border-color .15s ease;
}

.uxp-sr-card:hover,
.uxp-sr-card:focus-visible {
    border-color: var(--ds-money-solid, #0F766E);
    box-shadow: 0 4px 16px rgba(16,24,40,.10);
    outline: none;
}

.uxp-sr-card:focus-visible {
    outline: 2px solid var(--ds-money-solid, #0F766E);
    outline-offset: 2px;
}

.uxp-sr-logo {
    flex-shrink: 0;
}

.uxp-sr-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.uxp-sr-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--ds-ink, #1a2332);
}

.uxp-sr-excerpt {
    font-size: 0.85rem;
    color: var(--ds-muted, #5C6A7F);
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.uxp-sr-empty {
    text-align: center;
    padding: 48px 16px;
    color: var(--ds-muted, #5C6A7F);
}

.uxp-sr-empty-cta {
    display: inline-block;
    margin-top: 12px;
    padding: 10px 20px;
    border-radius: var(--ds-r, 12px);
    background: var(--ds-money-solid, #0F766E);
    color: #fff !important;
    font-weight: 600;
    text-decoration: none !important;
}

@media (prefers-color-scheme: dark) {
    .uxp-search-title,
    .uxp-sr-title {
        color: var(--ds-ink, #e6e9ef);
    }
}

/* ---------------------------------------------------------------------
   7. Cookie/privacy consent panel (wpconsent-cookies-banner-privacy-suite)
   burying offer content on mobile.
   Owner-reported (26.09.2026), evidence in
   reports/ux_review_20260926/after/C/ee_boozt_mobile_top.png and
   ee_home_mobile.png: a panel titled "Kuidas teie andmeid kasutatakse?"
   sits over the first offer card on a short mobile viewport.

   ROOT CAUSE (found by reading the plugin's own source over SSH, not
   guessed): wpconsent renders its banner/preferences UI inside an OPEN
   shadow DOM rooted at #wpconsent-container (see
   wp-content/plugins/wpconsent-cookies-banner-privacy-suite/
   src/frontend/banner.js -> attachShadow({mode:'open'})). Its
   src/frontend/banner.css sets `.wpconsent-banner { max-height:
   calc(100vh - 20px); }` — effectively UNCAPPED. On a short phone
   viewport, wpconsent's own (site-owner-editable, GDPR-required) consent
   text is long enough to push the banner to nearly full viewport height,
   burying the header, hero and first offer card behind it.

   FIX: cap that height. Because the UI lives in a shadow root, ordinary
   selectors like `.wpconsent-banner{...}` from this stylesheet CANNOT
   reach it — shadow DOM blocks normal CSS combinators by design. wpconsent
   deliberately exposes every meaningful element via a `part="..."`
   attribute for exactly this purpose (verified directly in
   includes/class-wpconsent-banner.php: `part="wpconsent-banner"`,
   `part="wpconsent-preferences-content"`, etc.) — `::part()` is the
   ONE sanctioned, update-safe way page CSS can style into an open shadow
   root, and it is what wpconsent's own docs point site owners at.

   This changes ONLY layout (a fixed cap + internal scroll for whatever
   text doesn't fit). It does not touch the plugin's files, does not
   change any consent default, does not remove or relabel any button, and
   does not touch the IAB TCF/AdSense integration — the banner, its
   Accept/Reject/Manage controls and the required legal text all still
   render and function exactly as before; a long paragraph now scrolls
   inside its own box instead of pushing the whole banner over the
   screen. The small always-visible "reopen preferences" icon
   (#wpconsent-consent-floating, a normal light-DOM element, NOT inside
   the shadow root) is untouched — it is already `position:fixed` with a
   24px icon in a small corner button and does not by itself cover
   card-sized content. Deployed only to sites that run this plugin (EE,
   LV, SI, RO — confirmed via `wp plugin list --status=active`; NOT
   present on SK/LT/DK/ES, where this rule is simply inert/no-op since
   #wpconsent-container never exists there).
   --------------------------------------------------------------------- */
#wpconsent-container::part(wpconsent-banner) {
    max-height: min(70vh, 560px) !important;
    overflow-y: auto !important;
}

#wpconsent-container::part(wpconsent-preferences-content) {
    max-height: 85vh !important;
}

/* Give the required consent text room to breathe inside its now-scrollable
   box rather than clipping mid-sentence at the very edge of the panel. */
#wpconsent-container::part(wpconsent-banner-body) {
    padding-bottom: 8px;
}

/* ---------------------------------------------------------------------
   8. Google's own consent panel ("Ako sa používajú vaše údaje" / shield
      icon) overlapping the hero on desktop.
   Owner-reported (27.09.2026), evidence in
   reports/vibecode_audit_20260927/after/E/SK_desktop_home.png: a small
   floating panel with a shield icon sits over the LEFT of the hero on
   SK's desktop homepage. This is NOT wpconsent (confirmed via
   `wp plugin list --status=active` — wpconsent is not active on SK) —
   the "Spravované Googlom. Spĺňa rámec transparentnosti a súhlasu
   združenia IAB." footer line identifies it as Google's own Funding
   Choices / AdSense consent management tool, injected client-side by
   Google's script — the SAME third-party surface CLAUDE.md's
   05.09.2026 dark-mode note and 04_detail.md finding #6 already flag as
   "not fixable from our CSS" for its THEMING. Positioning is a
   different, narrower question: Funding Choices renders its persistent
   icon + panel as plain (non-shadow-root) elements under well-documented
   root classes, so an ordinary CSS rule CAN reach them — it just cannot
   be verified live in this session (the automated browser used for
   verification never triggered the consent flow — no EU-consent cookie
   state, no ad-blocker-free real Chrome session with an EU-geo IP — so
   this is applied defensively, not confirmed against a live render).
   SCOPE, to stay inside "position only, never touch consent logic": no
   selector below is a button, a click handler, or anything that changes
   a default; every rule only constrains WIDTH/POSITION so the panel
   docks to a corner instead of spanning over hero text, exactly like the
   wpconsent fix above. If a given site's Funding Choices version doesn't
   use these class names, this is a silent no-op (same safety property as
   the wpconsent block, which is inert on SK/LT/DK/ES). */
.fc-consent-root {
    max-width: min(360px, calc(100vw - 32px)) !important;
}
.fc-ab-root {
    max-width: min(360px, calc(100vw - 32px)) !important;
}

/* ---------------------------------------------------------------------
   9. Unfilled Google Auto Ads slot leaving a reserved blank band.
   Owner-reported (27.09.2026), evidence in the same screenshot: ~150px
   of blank white space between the header and the nav bar, and ~250px
   between the homepage's closing paragraph and the footer — both are the
   footprint of an Auto Ads container that reserved height before
   resolving, then never got a fill (or Google's own auto-collapse script
   didn't run in time/at all).
   Deal Ad Slots (deal-ad-slots.php, this workstream's own plugin)
   already proved the right pattern for exactly this failure mode
   (v1.3.0, 26.09.2026): watch data-ad-status via MutationObserver and
   collapse the WHOLE container once AdSense marks it unfilled — but that
   plugin only auto-places on BRAND pages (SECTION_END:brand_offers marker)
   and is only active on EE/LV, so it does nothing for a homepage gap on
   SK/other sites. This generalises the same technique network-wide,
   site-wide, for whatever container Auto Ads (not deal-ad-slots) injects,
   without touching a single FILLED ad — a slot Google actually served
   into is completely untouched by this rule.
   Targets the standard Google Publisher Tag / Auto Ads containers
   (documented ids/classes): a `google_ads_iframe_*` wrapper div, an
   `ins.adsbygoogle` left with no rendered ad, and the generic
   `.google-auto-placed` wrapper class Auto Ads uses for its own inserted
   units. Mirrors deal-ad-slots' own collapse condition
   (`data-ad-status="unfilled"`) plus a zero-height fallback for a
   completely empty container (no iframe child at all) so a slot that
   never even attempts to resolve doesn't sit there as permanent dead
   space either. */
ins.adsbygoogle[data-ad-status="unfilled"] {
    display: none !important;
}
div[id^="google_ads_iframe_"]:empty,
div.google-auto-placed:empty {
    display: none !important;
    height: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
}
/* 27.09.2026 follow-up: reproduced live on dinerabatkode.dk (coordinator,
   real Chrome + getBoundingClientRect) — the actual wrapper is
   `div.google-auto-placed > ins.adsbygoogle[data-ad-status="unfilled"]`,
   which is NEVER `:empty` (it has the <ins> as a child), so the rule
   above never matched it. `:has()` (supported since Chrome 105, i.e.
   effectively all real traffic) closes that gap as a CSS-only backstop;
   js/ux-polish.js's MutationObserver is the primary mechanism (handles
   the case below, and it doesn't need `:has()` support). */
div.google-auto-placed:has(> ins.adsbygoogle[data-ad-status="unfilled"]) {
    display: none !important;
    height: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
}
