/* public/css/ads.css — ad-unit placement wrappers.
 *
 * Sticky ads DO NOT overlay content. Instead, ads.js measures the rendered
 * wrapper height, sets it as a CSS custom property (--ad-sticky-bottom-h or
 * --ad-sticky-top-h), and adds a body class that applies matching padding
 * to the body so page content and the footer are pushed out of the ad's
 * way. This keeps the entire site usable at all scroll positions without
 * covering any content.
 *
 * Because there's no close button, the ad stays visible for the whole
 * session — site owner's deliberate choice. AdSense program policy allows
 * this provided the ad does not cover essential page content, which our
 * space-reservation pattern guarantees.
 */

.ad-inline { margin: 16px 0; text-align: center; }

/* ------------------------------------------------------------------
   Sticky / floating wrappers
   ------------------------------------------------------------------ */

/* Wrapper itself is TRANSPARENT (no background, no border, no shadow).
   Most AdSense creatives bring their own opaque background, so this
   looks identical when filled. When unfilled or pre-fill (during AdSense
   review), the wrapper disappears against the site background instead
   of showing a big empty white panel. The body padding still reserves
   the 90px so layout doesn't jump when an ad eventually fills.
   The floating-corner placement is the exception — it keeps a card
   background because it floats over content. */
.ad-sticky, .ad-float {
    position: fixed;
    z-index: 850;                   /* above page content, below modals (1100+) */
    padding: 6px 10px;
    max-width: 100%;
    box-sizing: border-box;
}

/* Bottom-stuck banner pins itself to the bottom of the viewport. Body
   padding (set below) keeps page content from scrolling underneath it. */
.ad-sticky--bottom {
    bottom: 0;
    left: 0;
    right: 0;
}

/* Top-stuck banner pins to top:0 ABOVE the site header. The header is
   already position:sticky — we push it down by the ad's height so the
   two stack cleanly. */
.ad-sticky--top {
    top: 0;
    left: 0;
    right: 0;
    z-index: 1001;                  /* above the sticky header */
}

/* Floating-corner is a card overlay — keeps its background so it remains
   visually distinct from the page content underneath. */
.ad-float--corner {
    bottom: 16px;
    right: 16px;
    width: 320px;
    max-width: calc(100vw - 32px);
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 6px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

.ad-sticky-body {
    text-align: center;     /* centre the fixed-size sticky banner */
}
.ad-float--corner .ad-sticky-body { min-height: 100px; }

/* ------------------------------------------------------------------
   Per-format sizing (class-driven, per breakpoint)
   ------------------------------------------------------------------
   The renderer emits every <ins> with .slm-ad--desktop-{token} and
   .slm-ad--mobile-{token} classes, and every wrapper with the matching
   .slm-wrap--desktop-{token} / .slm-wrap--mobile-{token} pair. Sizes
   below use !important to beat the inline width/height the server
   emits as the SSR-first fallback (AdSense needs a real slot size at
   push time even if this stylesheet hasn't yet been applied).

   Tokens are the same as AdSenseManager::FORMATS keys. Update both if
   you add or rename a format. */

/* Desktop breakpoint --------------------------------------------------- */
@media (min-width: 768px) {
    /* <ins> dims — fixed-pixel formats */
    .slm-ad--desktop-size-728x90  { width: 728px !important; height:  90px !important; display: inline-block !important; }
    .slm-ad--desktop-size-970x90  { width: 970px !important; height:  90px !important; display: inline-block !important; }
    .slm-ad--desktop-size-970x250 { width: 970px !important; height: 250px !important; display: inline-block !important; }
    .slm-ad--desktop-size-468x60  { width: 468px !important; height:  60px !important; display: inline-block !important; }
    .slm-ad--desktop-size-320x50  { width: 320px !important; height:  50px !important; display: inline-block !important; }
    .slm-ad--desktop-size-320x100 { width: 320px !important; height: 100px !important; display: inline-block !important; }
    .slm-ad--desktop-size-300x250 { width: 300px !important; height: 250px !important; display: inline-block !important; }
    .slm-ad--desktop-size-336x280 { width: 336px !important; height: 280px !important; display: inline-block !important; }
    .slm-ad--desktop-size-250x250 { width: 250px !important; height: 250px !important; display: inline-block !important; }
    .slm-ad--desktop-size-200x200 { width: 200px !important; height: 200px !important; display: inline-block !important; }
    .slm-ad--desktop-size-120x600 { width: 120px !important; height: 600px !important; display: inline-block !important; }
    .slm-ad--desktop-size-160x600 { width: 160px !important; height: 600px !important; display: inline-block !important; }
    .slm-ad--desktop-size-300x600 { width: 300px !important; height: 600px !important; display: inline-block !important; }
    /* .slm-ad--desktop-responsive keeps whatever inline style the server emitted
       (display:block; width:100%; min-height:50px) so Google measures the container. */

    /* Wrapper min-heights — match the format's height plus a small pad */
    .slm-wrap--desktop-size-728x90  { min-height:  90px !important; }
    .slm-wrap--desktop-size-970x90  { min-height:  90px !important; }
    .slm-wrap--desktop-size-970x250 { min-height: 250px !important; }
    .slm-wrap--desktop-size-468x60  { min-height:  60px !important; }
    .slm-wrap--desktop-size-320x50  { min-height:  50px !important; }
    .slm-wrap--desktop-size-320x100 { min-height: 100px !important; }
    .slm-wrap--desktop-size-300x250 { min-height: 250px !important; }
    .slm-wrap--desktop-size-336x280 { min-height: 280px !important; }
    .slm-wrap--desktop-size-250x250 { min-height: 250px !important; }
    .slm-wrap--desktop-size-200x200 { min-height: 200px !important; }
    .slm-wrap--desktop-size-120x600 { min-height: 600px !important; }
    .slm-wrap--desktop-size-160x600 { min-height: 600px !important; }
    .slm-wrap--desktop-size-300x600 { min-height: 600px !important; }
    .slm-wrap--desktop-responsive   { min-height:  90px !important; }
}

/* Mobile breakpoint ---------------------------------------------------- */
@media (max-width: 767px) {
    /* <ins> dims */
    .slm-ad--mobile-size-728x90  { width: 728px !important; height:  90px !important; display: inline-block !important; }
    .slm-ad--mobile-size-970x90  { width: 970px !important; height:  90px !important; display: inline-block !important; }
    .slm-ad--mobile-size-970x250 { width: 970px !important; height: 250px !important; display: inline-block !important; }
    .slm-ad--mobile-size-468x60  { width: 468px !important; height:  60px !important; display: inline-block !important; }
    .slm-ad--mobile-size-320x50  { width: 320px !important; height:  50px !important; display: inline-block !important; }
    .slm-ad--mobile-size-320x100 { width: 320px !important; height: 100px !important; display: inline-block !important; }
    .slm-ad--mobile-size-300x250 { width: 300px !important; height: 250px !important; display: inline-block !important; }
    .slm-ad--mobile-size-336x280 { width: 336px !important; height: 280px !important; display: inline-block !important; }
    .slm-ad--mobile-size-250x250 { width: 250px !important; height: 250px !important; display: inline-block !important; }
    .slm-ad--mobile-size-200x200 { width: 200px !important; height: 200px !important; display: inline-block !important; }
    .slm-ad--mobile-size-120x600 { width: 120px !important; height: 600px !important; display: inline-block !important; }
    .slm-ad--mobile-size-160x600 { width: 160px !important; height: 600px !important; display: inline-block !important; }
    .slm-ad--mobile-size-300x600 { width: 300px !important; height: 600px !important; display: inline-block !important; }
    /* .slm-ad--mobile-responsive keeps display:block; width:100% */

    /* Wrapper min-heights */
    .slm-wrap--mobile-size-728x90  { min-height:  90px !important; }
    .slm-wrap--mobile-size-970x90  { min-height:  90px !important; }
    .slm-wrap--mobile-size-970x250 { min-height: 250px !important; }
    .slm-wrap--mobile-size-468x60  { min-height:  60px !important; }
    .slm-wrap--mobile-size-320x50  { min-height:  50px !important; }
    .slm-wrap--mobile-size-320x100 { min-height: 100px !important; }
    .slm-wrap--mobile-size-300x250 { min-height: 250px !important; }
    .slm-wrap--mobile-size-336x280 { min-height: 280px !important; }
    .slm-wrap--mobile-size-250x250 { min-height: 250px !important; }
    .slm-wrap--mobile-size-200x200 { min-height: 200px !important; }
    .slm-wrap--mobile-size-120x600 { min-height: 600px !important; }
    .slm-wrap--mobile-size-160x600 { min-height: 600px !important; }
    .slm-wrap--mobile-size-300x600 { min-height: 600px !important; }
    .slm-wrap--mobile-responsive   { min-height:  90px !important; }
}

/* ------------------------------------------------------------------
   Space reservation — the wrapper is position:fixed, so body content
   needs padding to lift clear of it. AdSenseManager::autoInjectHtml
   emits a small inline <script> that sets:
       --ad-sticky-top-h-desktop, --ad-sticky-top-h-mobile,
       --ad-sticky-bottom-h-desktop, --ad-sticky-bottom-h-mobile
   from each unit's configured desktop/mobile format heights. The media
   queries below pick the right one for the current breakpoint.
   ads.js later refines --ad-sticky-*-h to the actual rendered wrapper
   height once measured; that variable takes precedence when set.
   ------------------------------------------------------------------ */

@media (min-width: 768px) {
    body.has-ad-sticky-bottom {
        padding-bottom: var(--ad-sticky-bottom-h, var(--ad-sticky-bottom-h-desktop, 0px));
    }
    body.has-ad-sticky-top {
        padding-top: var(--ad-sticky-top-h, var(--ad-sticky-top-h-desktop, 0px));
    }
    body.has-ad-sticky-top .site-header {
        top: var(--ad-sticky-top-h, var(--ad-sticky-top-h-desktop, 0px));
    }
}
@media (max-width: 767px) {
    body.has-ad-sticky-bottom {
        padding-bottom: var(--ad-sticky-bottom-h, var(--ad-sticky-bottom-h-mobile, 0px));
    }
    body.has-ad-sticky-top {
        padding-top: var(--ad-sticky-top-h, var(--ad-sticky-top-h-mobile, 0px));
    }
    body.has-ad-sticky-top .site-header {
        top: var(--ad-sticky-top-h, var(--ad-sticky-top-h-mobile, 0px));
    }
}

/* ------------------------------------------------------------------
   Auto-hide empty wrappers
   ------------------------------------------------------------------ */

/* When AdSense reports the slot as unfilled (data-ad-status="unfilled"),
   hide the wrapper so it doesn't take up reserved space. AdSense needs
   the wrapper to be VISIBLE with real dimensions while it's trying to
   fill — hiding pre-emptively causes "No slot size for availableWidth=0".
   Wrappers carrying backfill HTML (.ad-has-backfill) are EXEMPT: ads.js
   reveals the backfill block instead so the slot still has content. */
.ad-sticky:not(.ad-has-backfill):has(ins.adsbygoogle[data-ad-status="unfilled"]),
.ad-float:not(.ad-has-backfill):has(ins.adsbygoogle[data-ad-status="unfilled"]) {
    display: none !important;
}
/* NOTE: we intentionally do NOT hide wrappers when marketing consent is
   denied. Consent Mode v2 tells AdSense to serve non-personalised
   "limited ads" in that case, so ads still show and the site still earns
   revenue. AdSense throws "No slot size" if the wrapper is display:none,
   so we keep it visible and let Google's own consent signals govern
   whether a personalised or limited ad is shown. */

/* ------------------------------------------------------------------
   Backfill block — admin-supplied house ad shown when AdSense doesn't
   fill (or hasn't yet during site review). ads.js toggles `hidden`.
   ------------------------------------------------------------------ */

.ad-backfill {
    display: block;
    width: 100%;
    height: 100%;
}
.ad-backfill[hidden] { display: none; }

/* The backfill is layered OVER the <ins> rather than replacing it, because
   the <ins> must never be display:none — hiding it before AdSense resolves
   the request cancels the request outright ("No ad requested because of
   display:none on the adsbygoogle tag"), which made the slot permanently
   unfillable. See the long note in ads.js.

   Consequence: every placement needs a positioned wrapper with reserved
   height, so the filled / unfilled / backfill states all occupy exactly the
   same space and nothing reflows when they swap. The sticky and float
   wrappers already reserve height via min-height in their inline styles;
   inline placements need it declaring here. */
.ad-inline {
    position: relative;
    min-height: 90px;
}
.ad-inline .ad-backfill {
    position: absolute;
    inset: 0;
}

/* style.css hides an unfilled <ins> outright to collapse dead space. That is
   safe on its own (the attribute is only set after the request resolves), but
   a display:none tag can never be filled by a later AdSense refresh either.
   Where a house backfill is layered over the slot we don't need to collapse
   anything — the backfill already covers the reserved space — so keep the
   <ins> in the layout and let it stay refreshable. ads.css loads after
   style.css, so this override wins. */
.ad-has-backfill ins.adsbygoogle[data-ad-status="unfilled"] {
    display: block !important;
}
.ad-has-backfill ins.adsbygoogle.ad-sticky-ins[data-ad-status="unfilled"] {
    display: inline-block !important;
}
/* In sticky / floating placements, absolute-position the backfill so it
   covers the ENTIRE wrapper edge-to-edge. The wrapper is fixed-position
   and 90px tall (min-height); without this rule the backfill div sat in
   normal flow at the top and only took the height its content needed
   (~50-60px). The gap below was transparent wrapper space, through which
   page text was visible while scrolling. Absolute-positioning with
   `inset:0` makes the opaque placeholder cover the full reserved area,
   so nothing leaks through. The <ins> sibling is unaffected — when
   AdSense fills, the backfill stays hidden and the <ins> shows the ad. */
.ad-sticky .ad-backfill,
.ad-float .ad-backfill {
    position: absolute;
    inset: 0;
    /* Backfill HTML is admin-supplied and often carries its own hardcoded
       min-heights (e.g. min-height:90px on the outer element). In a sticky
       wrapper sized per-format — a mobile 320×50 slot is only 50px tall —
       any hardcoded 90px inside would push content above the wrapper's
       top edge and appear to bleed into the page. Clip to the wrapper's
       reserved area so the backfill visually respects the configured
       shape regardless of what the pasted HTML declares. */
    overflow: hidden;
}

/* Dark theme: only the floating-corner card needs a dark surface (the
   sticky variants are transparent so they inherit page colours). */
[data-theme="dark"] .ad-float--corner {
    background: #1f2937;
    border-color: #374151;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

/* Print — ads never visible in printed output */
@media print {
    .ad-inline, .ad-sticky, .ad-float { display: none !important; }
}
