/*
 * ads/googleads/ads.css - Ad slot layout + CLS height reservation.
 *
 * Loaded (deferred) by googleads_bootstrap() in ads.php. Its only jobs:
 *   1) Reserve a stable min-height per slot format so the injected <ins> never
 *      shifts the page when AdSense fills it (Core Web Vitals / CLS).
 *   2) Toggle the top-banner desktop vs mobile <ins> by viewport (ads-init.js
 *      only initializes the visible one).
 *   3) Style the discreet operator preview placeholder (?noads=1 cookie).
 *
 * Design tokens (var(--...)) come from css/site.css and are theme-aware; every
 * value has a hard fallback so the file also works if it loads before site.css.
 */

/* Base slot: block, centered, contained, never overflows a narrow screen. */
.ad-slot {
  display: block;
  width: 100%;
  max-width: 100%;
  margin-inline: auto;
  overflow: hidden;
  text-align: center;
  box-sizing: border-box;
}

/* CLS HEIGHT RESERVATION (owner decree 18/Jul/2026, OVERRIDES Round 12b's "no
   reserve"). Each responsive slot reserves the height its format typically fills, so
   the injected <ins> never pushes content down when AdSense fills it (Core Web Vitals
   / CLS). A unit that genuinely cannot fill still collapses to ZERO via the
   [data-ad-status="unfilled"] rule below (and the rail's :has() collapse), so an
   unfilled slot leaves no empty box. Heights track the docs/43 formats. The operator
   preview placeholders (.ad-slot-preview.*, later) carry a 2-class selector, so their
   own compact heights win over these single-class reservations. */
.ad-slot--header-banner,
.ad-slot--tight,
.ad-top-ad--desktop,
.ad-top-ad--mobile {
  min-height: 90px;            /* horizontal leaderboard */
}
.ad-slot--result-box,
.ad-slot--below-tool,
.ad-slot--bottom-page,
.ad-slot--multiplex,
.ad-slot--vertical-inline {
  min-height: 250px;           /* responsive rectangle / multiplex / in-content vertical */
}
.ad-slot--mobile-anchor,
.ad-slot--fixed {
  min-height: 100px;           /* fixed 320x100 */
}

.ad-in-article {
  margin-block: 1.6rem;
  min-height: 250px;
}

.googleads-lazy-slot {
  display: block;              /* the format class on the same/inner slot reserves the height */
}

/* Collapse a real ad unit AdSense could not fill, so no empty box is left. The
   filled state is untouched (the ad shows at its own size). */
ins.adsbygoogle[data-ad-status="unfilled"],
ins.adsbygoogle[data-ad-status="empty"] {
  display: none !important;
}

/* DENSITY GUARD (ads.php, googleads_emit_density_guard): a slot the guard
   collapsed because it sat within one viewport-height of the previous visible
   slot. The guard sets inline display:none (works before this stylesheet is
   applied); this rule is the belt so the collapse also survives any later
   inline-style reset. Diagnostic: data-ad-density-gap carries the measured px. */
[data-ad-suppressed="density"] {
  display: none !important;
}

/* Top-banner responsive toggle. Inline styles set desktop=block / mobile=none;
   below the breakpoint we flip them (!important beats the inline style). */
@media (max-width: 700px) {
  .ad-top-ad--desktop { display: none !important; }
  .ad-top-ad--mobile  { display: inline-block !important; }
  .ad-slot--header-banner,
  .ad-slot--tight { min-height: 100px; }
}

/* ============================================================================
 * "PUBLICIDADE" LABEL WRAPPER (ported from contadordeprazo .cdp-ad-disclosure)
 *
 * docs/43: "TODO ad renderizado DEVE ter o rotulo Publicidade visivel. Nenhum ad
 * pode aparecer sem indicador." One implementation for every placement: the
 * wrapper emitted by npds_render_ad_slot()/npds_close_ad_shift() draws the label
 * with ::before, so no call site spells it out.
 *
 * Style is the ecosystem standard (docs/43, decree 22/Jun/2026): discreet NEUTRAL
 * GREY text, uppercase, small, in normal flow. Never a coloured pill (research:
 * a garish disclosure lowers trust and Google does not reward it) and never so
 * faint it reads as the background (that would be cloaking = policy violation).
 * ==========================================================================*/
.np-ad-disclosure {
  display: block;
  margin: 32px 0 24px;
  padding: 0;
  border: none;
  background: transparent;
  text-align: center;
  overflow: visible;
  box-sizing: border-box;
}
.np-ad-disclosure::before {
  content: 'Publicidade';
  display: block;
  margin-bottom: 6px;
  font: 600 0.62rem/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  color: var(--muted, #94a3b8);
}
.np-ad-disclosure > .ad-slot,
.np-ad-disclosure > ins.adsbygoogle,
.np-ad-disclosure > .googleads-lazy-slot {
  margin-inline: auto;
}

/* Collapse the WHOLE wrapper (label included) when the real unit reports that it
   could not fill. Without this the ::before would survive its collapsed <ins> and
   leave a stray "PUBLICIDADE" floating on the page - which is exactly what every
   slot would do today, since the AdSense units are still SLOT_ID_TBD_*. Preview
   placeholders are <div>s with no data-ad-status, so ?noads keeps its frames. */
.np-ad-disclosure:has(ins.adsbygoogle[data-ad-status="unfilled"]),
.np-ad-disclosure:has(ins.adsbygoogle[data-ad-status="empty"]) {
  display: none !important;
}

/* ---- Operator preview placeholder (?noads=1 cookie). Discreet, no real ad. ---- */
/* Operator preview frame: the owner wants to SEE the FULL frame of every slot, in
   the real area the ad will occupy. The previous tint (brand-ink at 6% over a
   #ffffff --card) computed to #fdf5f0 with a pale peach dash: against this site's
   white paper that read as an empty white column ("sidebar ads esta branco").
   Ported from the contadordeprazo preview visual instead (solid slate fill + grey
   dashed frame), but mixed off the SITE TOKENS rather than hardcoded hex, so the
   frame follows the theme on its own with no media query. --muted is grey in both
   themes, so the fill lands just off the paper either way (light: a slate tint on
   white; dark: a lift off the dark paper) and stays clearly visible without a
   second rule to keep in sync. Preview-only (?noads=1); the real <ins> in
   production is untouched. */
.ad-slot-preview {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
  justify-content: center;
  padding: 16px;
  border: 1px dashed var(--muted, #94a3b8);
  border-radius: 6px;
  background: color-mix(in srgb, var(--muted, #94a3b8) 16%, var(--paper, #ffffff));
  color: var(--ink-2, #475569);
  min-height: 70px;
}

/* In-content preview placeholders are kept compact so the operator review does not
   read as giant gaps between topics (round 12). The real production <ins> sizes
   itself to the served ad or collapses when unfilled; this height is preview-only.
   The sidebar rail sets its own tall reservation on .np-ad-rail .ad-slot. */
.ad-slot-preview.ad-slot--result-box,
.ad-slot-preview.ad-slot--below-tool,
.ad-slot-preview.ad-slot--bottom-page,
.ad-slot-preview.ad-slot--multiplex,
.ad-slot-preview.ad-slot--vertical-inline {
  min-height: 120px;
}

.ad-slot-preview.ad-slot--mobile-anchor,
.ad-slot-preview.ad-slot--fixed {
  min-height: 100px;
}

/* Caption line 1: which placement this frame is. Line 2: which unit it resolves
   to + the footprint the live ad will take (label, WxH, slot id) - so the owner
   can audit the inventory straight from the page under ?noads. */
.ad-slot-preview__meta {
  font: 700 0.82rem/1.2 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brand-ink, #e8590c);
  opacity: 1;
  text-align: center;
}

.ad-slot-preview__size {
  max-width: 100%;
  font: 500 0.68rem/1.35 ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  color: inherit;
  opacity: 0.8;
  text-align: center;
  overflow-wrap: anywhere;
}

/* ============================================================================
 * DESKTOP AD ASIDE (round 11, ADS LATERAIS reform)
 *
 * The round-10 position:fixed gutter rail was replaced by the contadordeprazo
 * "shifted-tool" layout: after the full-width hero, the page content sits in a
 * 2-column grid whose second child is the ad aside. The GRID + the sticky
 * positioning + the 1440px breakpoint live in css/site.css (.np-shift /
 * .np-shift__aside). This file only styles what is INSIDE the aside: the
 * "Publicidade" label and the vertical ad unit's CLS height reservation, so both
 * stylesheets keep their original responsibilities (ads.css reserves heights).
 * ==========================================================================*/
/* The rail's inner box IS a .np-ad-disclosure (same wrapper, same ::before
   label as every other slot), so it needs no label rule of its own. It only
   overrides the shared vertical rhythm: inside the sticky aside the ad is the
   column's only content, so the wrapper's 32px/24px page margins would just
   push it down away from the sticky top. */
.np-ad-rail__in {
  display: flex;
  flex-direction: column;    /* label ABOVE the ad, never beside it (docs/43) */
  align-items: stretch;
  margin: 0;
  min-height: 0;             /* wrapper stays flexible; the inner .ad-slot reserves 600px (CLS) */
  border-radius: 12px;
}

/* If the rail's ad did not fill, hide the whole rail (label included) so the
   right gutter is clean, not a tall empty labelled box. Preview mode keeps the
   rail because its placeholder is not an <ins> (no data-ad-status).
   The .np-ad-rail class is emitted on the <aside> by npds_close_ad_shift();
   before this port it was never emitted, so this rule matched nothing. */
.np-ad-rail:has(ins.adsbygoogle[data-ad-status="unfilled"]),
.np-ad-rail:has(ins.adsbygoogle[data-ad-status="empty"]) {
  display: none !important;
}

/* ...and the SHIFT has to collapse with it. `display:none` on the <aside> removes
   the ITEM, never the COLUMN: grid-template-columns still reads "1080px 300px", so
   the content stayed pinned left with a 383px void on the right (measured at
   1500px: body left 37 / right 1117). Re-center on the content width whenever the
   rail is gone, so an unfilled ad costs nothing visually. Same media query as the
   base grid in css/site.css; this file loads last, so no !important is needed.
   Note: :has() may NOT be nested inside :has() (invalid, drops the whole rule), so
   this matches the <ins> as a DESCENDANT of the rail in one :has(). */
@media (min-width: 1440px) {
  .np-shift:has(.np-ad-rail ins.adsbygoogle[data-ad-status="unfilled"]),
  .np-shift:has(.np-ad-rail ins.adsbygoogle[data-ad-status="empty"]) {
    grid-template-columns: minmax(0, var(--body-max));
    max-width: var(--shell);
  }
}

/* The vertical unit inside the aside fills the column width and RESERVES the
   half-page height (CLS decree 18/Jul/2026) so the sticky ad never shifts the
   column on fill. If it does not fill, the rail's :has() collapse above removes the
   whole aside (and the shift re-centers), so the reservation costs nothing when empty. */
.np-ad-rail__in .ad-slot,
.np-ad-rail__in .ad-slot--vertical-inline {
  width: 100%;
  min-height: 600px;
}

/* Operator preview placeholder inside the aside: same tall reservation. */
.np-ad-rail__in .ad-slot-preview {
  min-height: 600px;
}
