/* Third-party embed code pasted into privacy_policy_snippet/cookie_policy_snippet (e.g. a
   vendor's own button snippet) commonly loads its own vendor CSS/JS from its own CDN,
   completely outside our control, and that vendor markup is sometimes appended straight to
   <body> rather than nested inside our banner — occasionally with an off-screen/oversized
   element that silently makes the whole page horizontally scrollable. On many mobile
   browsers, our own position:fixed banner then visibly drifts as the page is scrolled
   sideways, even though the banner's own CSS is unaffected. Scoped to :has(.kconsensio)
   so it only engages on pages where this plugin actually rendered a banner. */
html:has(.kconsensio) {
    overflow-x: hidden;
}

/* Defensive reset: the host template's CSS may not set border-box globally, in which
   case padding on our buttons/panels adds to their width instead of being contained by
   it, causing overflow (e.g. the modal action buttons spilling past the panel edge). */
.kconsensio,
.kconsensio *,
.kconsensio-modal,
.kconsensio-modal *,
.kconsensio-persistent {
    box-sizing: border-box;
}

/* Defensive reset: most templates style plain tags (h1-h6, p, span, li, label...)
   globally for their content areas — color, font-family, possibly more. Any such element
   here that doesn't set its own explicit value for one of those properties (e.g. <h2> in
   the preferences panel) silently picks up the host page's own styling instead of ours,
   since an inherited value never competes with a page rule that targets the tag
   directly — it loses even though our wrapper already declares both further up/below.
   This does NOT include <a> or button elements, which set their own accent colors
   deliberately further below. Kept broad and generic (not tied to any one template,
   e.g. Astroid) since this plugin has to look right regardless of the site's theme.
   Also covers strong/b/em/i/ul/ol/blockquote: banner_text and category descriptions go
   through Joomla's "safehtml" filter (not plain text), so an admin can legitimately format
   them with bold/italic/lists — those tags need the same protection as p/span/li. */
.kconsensio h1, .kconsensio h2, .kconsensio h3, .kconsensio h4, .kconsensio h5, .kconsensio h6,
.kconsensio p, .kconsensio span, .kconsensio label, .kconsensio li,
.kconsensio strong, .kconsensio b, .kconsensio em, .kconsensio i, .kconsensio ul, .kconsensio ol, .kconsensio blockquote,
.kconsensio-modal__panel h1, .kconsensio-modal__panel h2, .kconsensio-modal__panel h3,
.kconsensio-modal__panel p, .kconsensio-modal__panel span, .kconsensio-modal__panel label, .kconsensio-modal__panel li,
.kconsensio-modal__panel strong, .kconsensio-modal__panel b, .kconsensio-modal__panel em, .kconsensio-modal__panel i,
.kconsensio-modal__panel ul, .kconsensio-modal__panel ol, .kconsensio-modal__panel blockquote {
    color: inherit;
    font-family: inherit;
}

/* Same safehtml-formatted content: a <ul>/<ol> the admin created in banner_text or a
   category description needs to actually look like a list regardless of the template —
   many themes globally strip list-style/margin/padding on bare ul/ol (a common nav-reset
   pattern), which would otherwise silently flatten an admin's bullet/numbered list into
   plain unmarked paragraphs. */
.kconsensio__text ul, .kconsensio-modal__category-desc ul {
    list-style: disc;
}

.kconsensio__text ol, .kconsensio-modal__category-desc ol {
    list-style: decimal;
}

.kconsensio__text ul, .kconsensio__text ol,
.kconsensio-modal__category-desc ul, .kconsensio-modal__category-desc ol {
    margin: 0 0 0.5rem;
    padding-left: 1.25rem;
}

/* Theme variables — light by default, overridden by .kconsensio--theme-dark, or by
   prefers-color-scheme when .kconsensio--theme-auto is present. Shared between the
   banner/card and the preferences modal panel so both follow the same admin setting. */
.kconsensio,
.kconsensio-modal__panel,
.kconsensio-persistent {
    --jcg-bg: #ffffff;
    --jcg-fg: #1b1f27;
    --jcg-muted: #6b7280;
    --jcg-border: rgba(0, 0, 0, 0.12);
    --jcg-accent: #2f6fed;
    --jcg-accent-fg: #ffffff;
    --jcg-shadow: 0 4px 24px rgba(0, 0, 0, 0.18);
}

.kconsensio--theme-dark,
.kconsensio-modal--theme-dark .kconsensio-modal__panel,
.kconsensio-persistent--theme-dark {
    --jcg-bg: #1b1f27;
    --jcg-fg: #f2f3f5;
    --jcg-muted: #9aa1ac;
    --jcg-border: rgba(255, 255, 255, 0.14);
    --jcg-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
}

@media (prefers-color-scheme: dark) {
    .kconsensio--theme-auto,
    .kconsensio-modal--theme-auto .kconsensio-modal__panel,
    .kconsensio-persistent--theme-auto {
        --jcg-bg: #1b1f27;
        --jcg-fg: #f2f3f5;
        --jcg-muted: #9aa1ac;
        --jcg-border: rgba(255, 255, 255, 0.14);
        --jcg-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
    }
}

.kconsensio {
    position: fixed;
    z-index: 2147483000;
    background: #202020;
    color: #f2f3f5;
    box-shadow: var(--jcg-shadow);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 0.9rem;
    line-height: 1.45;
}

.kconsensio[hidden] {
    display: none;
}

/* Purely visual emphasis behind the initial banner, never the preferences modal (which
   already has its own always-on backdrop below — that one is fine to block interaction with
   since opening it is the visitor's own optional choice, not the first, unavoidable prompt).
   pointer-events: none is load-bearing, not decorative: without it this would function as a
   click-blocking overlay on the very first, non-optional prompt, which is what makes a
   "cookie wall" non-compliant (Garante Privacy / EDPB dark-pattern guidance) — the page
   underneath must stay fully usable while this is visible. */
.kconsensio-backdrop {
    position: fixed;
    inset: 0;
    z-index: 2147482999;
    pointer-events: none;
}

.kconsensio-backdrop[hidden] {
    display: none;
}

.kconsensio-backdrop--dim {
    background: rgba(0, 0, 0, 0.45);
}

.kconsensio-backdrop--blur {
    background: rgba(0, 0, 0, 0.2);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

/* Full-width bar, anchored to the bottom or top edge of the viewport. */
.kconsensio--bar-bottom,
.kconsensio--bar-top {
    left: 0;
    right: 0;
}

.kconsensio--bar-bottom {
    bottom: 0;
}

.kconsensio--bar-top {
    top: 0;
}

/* Floating card: centered popup, or anchored near the bottom/top edge (not full-width). */
.kconsensio--modal-center,
.kconsensio--modal-bottom,
.kconsensio--modal-top {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    max-width: 34rem;
    width: calc(100% - 2rem);
    border-radius: 0.75rem;
}

.kconsensio--modal-center {
    top: 50%;
    transform: translate(-50%, -50%);
}

/* The default side-by-side text+buttons layout (.kconsensio__panel) needs the wide
   90rem bar to fit text and three buttons on one row. In the narrow 30rem card variants
   there isn't room for that, so stack text above buttons instead — this is what was
   causing the "Accept all" button to spill past the card's right edge. */
.kconsensio--modal-center .kconsensio__panel,
.kconsensio--modal-bottom .kconsensio__panel,
.kconsensio--modal-top .kconsensio__panel {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
    padding: 1rem 1.25rem;
}

.kconsensio--modal-center .kconsensio__text,
.kconsensio--modal-bottom .kconsensio__text,
.kconsensio--modal-top .kconsensio__text {
    /* .kconsensio__text's base "flex: 1 1 20rem" sets a 20rem flex-basis meant for
       WIDTH in the row-based bar layout. Since this panel is flex-direction: column
       here, that same basis applies to HEIGHT instead, forcing a ~320px-tall text
       block regardless of how little text there is. Reset it to size to content. */
    flex: 0 1 auto;
    font-size: 0.875rem;
}

.kconsensio--modal-center .kconsensio__text p,
.kconsensio--modal-bottom .kconsensio__text p,
.kconsensio--modal-top .kconsensio__text p {
    margin: 0 0 0.35rem;
}

/* Side by side when they fit (short translated labels: Italian, English, ...), but each
   button grows to share whatever row it ends up on rather than staying content-sized —
   at 30rem max-width, three buttons with longer labels (e.g. German "Nicht essenzielle
   ablehnen", "Präferenzen verwalten") don't fit on one line, and flex-wrap alone (with
   content-sized buttons) left the last one spilling onto its own row, narrow and
   right-aligned. flex-grow here means whichever button(s) wrap to a row by themselves
   stretch to fill it instead of looking stranded — see kconsensio_options_suggestions
   for context: this replaces an earlier "always stacked vertically" version that fixed
   the bug but also flattened the row layout for languages that never had the problem. */
.kconsensio--modal-center .kconsensio__actions,
.kconsensio--modal-bottom .kconsensio__actions,
.kconsensio--modal-top .kconsensio__actions {
    flex: 0 0 auto;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.kconsensio--modal-center .kconsensio__btn,
.kconsensio--modal-bottom .kconsensio__btn,
.kconsensio--modal-top .kconsensio__btn {
    flex: 1 1 auto;
    min-width: 6rem;
    padding: 0.5rem 0.75rem;
    font-size: 0.8rem;
    text-align: center;
}

.kconsensio--modal-bottom {
    bottom: 1.5rem;
}

.kconsensio--modal-top {
    top: 1.5rem;
}

.kconsensio__panel {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    padding: 1.25rem 1.5rem;
    max-width: 90rem;
    margin: 0 auto;
}

.kconsensio__text {
    flex: 1 1 20rem;
    min-width: 0;
    overflow-wrap: break-word;
}

.kconsensio__title {
    font-weight: 600;
    font-size: 1.2rem;
    margin: 0 0 0.25rem;
}

.kconsensio__text p {
    margin: 0 0 0.5rem;
}

.kconsensio__text a {
    color: #ffb400;
}

.kconsensio a[href="/privacy"] {
    color: #ffb400 !important;
}

/* Contains whatever the pasted third-party snippet renders (see banner.php) to the
   banner's own width, and lets its contents wrap onto multiple lines/rows instead of
   forcing this element wider than the banner — the local counterpart to the
   html:has(.kconsensio) safety net above. */
.kconsensio__policy-snippets {
    max-width: 100%;
    overflow-x: hidden;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.kconsensio__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    flex: 0 0 auto;
}

.kconsensio__btn {
    border: 1px solid var(--jcg-border);
    background: transparent;
    color: var(--jcg-fg);
    padding: 0.5rem 0.9rem;
    border-radius: 0.4rem;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.85rem;
    line-height: inherit;
}

.kconsensio__btn:hover,
.kconsensio__btn:focus-visible {
    border-color: var(--jcg-accent);
}

.kconsensio__btn--accept {
    background: #ffb400;
    border-color: #ffb400;
    color: #1b1f27;
    font-weight: 600;
}

/* "Rifiuta tutto" must be exactly as visually prominent as "Accetta tutto" — a solid
   button of the same weight, not a plain/outlined one — per Garante Privacy guidance and
   the EDPB's "deceptive design patterns" guidelines (03/2022), both of which flag an
   accept button that visually outweighs reject as invalidating the freeness of consent.
   Uses the theme's own fg/bg (inverted) rather than a second accent color, so it reads as
   equally solid/prominent without competing with the accept button's brand color. */
.kconsensio__btn--reject {
    background: var(--jcg-fg);
    border-color: var(--jcg-fg);
    color: var(--jcg-bg);
    font-weight: 600;
}

.kconsensio-modal {
    position: fixed;
    inset: 0;
    z-index: 2147483001;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, 0.55);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.kconsensio-modal[hidden] {
    display: none;
}

.kconsensio-modal__panel {
    position: relative;
    background: var(--jcg-bg);
    color: var(--jcg-fg);
    width: min(34rem, calc(100% - 2rem));
    max-height: calc(100% - 4rem);
    overflow-y: auto;
    border-radius: 0.75rem;
    padding: 1.25rem 1.5rem;
    box-shadow: var(--jcg-shadow);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 0.9rem;
    line-height: 1.35;
}

.kconsensio-modal__panel h2 {
    font-size: 1.1rem;
    font-weight: 600;
    line-height: 1.3;
    margin: 0 1.5rem 0 0;
}

.kconsensio-modal__close {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    border: none;
    background: transparent;
    font-family: inherit;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    color: inherit;
}

.kconsensio-modal__categories {
    list-style: none;
    margin: 1rem 0;
    padding: 0;
}

.kconsensio-modal__category {
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--jcg-border);
}

.kconsensio-modal__category label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 600;
    cursor: pointer;
}

/* Defensive reset: nothing else in this file targets the checkbox itself, so without this
   its size/shape/tick color come entirely from the host template's own global
   input[type=checkbox] styling. Many templates (Bootstrap-based ones especially) reset
   native checkboxes with appearance:none plus custom background art, which can leave this
   one oversized, undersized, or effectively invisible. appearance:auto forces the native
   control back on regardless of such a reset; accent-color then recolors that native
   control to match the plugin's own theme instead of the browser/OS default blue. */
.kconsensio-modal__checkbox {
    appearance: auto;
    width: 1.1rem;
    height: 1.1rem;
    flex-shrink: 0;
    margin: 0;
    accent-color: var(--jcg-accent);
    cursor: pointer;
}

.kconsensio-modal__panel .kconsensio-modal__always-on {
    font-weight: 400;
    font-size: 0.8rem;
    color: var(--jcg-muted);
}

.kconsensio-modal__panel .kconsensio-modal__category-desc {
    margin: 0.35rem 0 0 1.75rem;
    font-size: 0.85rem;
    color: var(--jcg-muted);
}

/* Always stacked, one button per row, all equal width — unlike the banner bar's
   .kconsensio__actions (which allows side-by-side + grow-to-fill for short labels), this
   MUST NOT let a button end up alone on its own row and stretch to fill it: whichever
   button that turns out to be would then look far more prominent than the other two,
   e.g. long German labels ("Nicht essenzielle ablehnen" / "Präferenzen speichern")
   pushing "Alle akzeptieren" onto its own full-width row while Reject stays cramped next
   to Save — exactly the unequal-prominence dark pattern the EDPB/Garante guidance on
   .kconsensio__btn--reject above is written to avoid. Stacking removes the ambiguity: every
   language gets the same three equal-width rows regardless of label length. */
.kconsensio-modal__actions {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    margin-top: 1rem;
}

.kconsensio-modal__actions .kconsensio__btn {
    text-align: center;
}

.kconsensio-modal__credit {
    margin-top: 1rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--jcg-border);
    text-align: center;
}

.kconsensio-modal__credit a {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.78rem;
    color: var(--jcg-muted);
    text-decoration: none;
}

.kconsensio-modal__credit a:hover {
    text-decoration: underline;
}

.kconsensio-modal__credit-logo {
    flex-shrink: 0;
    border-radius: 4px;
}

.kconsensio-modal__credit {
    display: none !important;
}

/* Persistent "Cookie Settings" link — always visible, lets a visitor reopen the
   preferences panel at any time to change or withdraw consent already given. */
.kconsensio-persistent {
    position: fixed;
    left: 1rem;
    bottom: 1rem;
    z-index: 2147482900;
    background: var(--jcg-bg);
    color: var(--jcg-fg);
    border: 1px solid var(--jcg-border);
    border-radius: 999px;
    padding: 0.5rem 1rem;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: 0.8rem;
    cursor: pointer;
    box-shadow: var(--jcg-shadow);
}

.kconsensio-persistent:hover,
.kconsensio-persistent:focus-visible {
    border-color: var(--jcg-accent);
}

.kconsensio-persistent--right {
    left: auto;
    right: 1rem;
}

.kconsensio-persistent--icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border-radius: 50%;
}

/* Icon + visible label side by side — keeps the base pill's padding/border-radius (unlike
   --icon above, which turns it into a round icon-only button with no room for text). */
.kconsensio-persistent--icon-text {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.kconsensio-persistent--icon-text svg {
    flex: 0 0 auto;
}

/* Set on <html> by kconsensio.js right when a visitor clicks a third-party button
   pasted into privacy_policy_snippet/cookie_policy_snippet (e.g. a pasted vendor's own
   Privacy Policy / Cookie Policy popup buttons): our own elements normally sit at an extreme
   z-index so nothing on the host page can ever cover them, but that also means they'd
   cover a third-party popup opened from inside our own banner. Yielding drops us below
   virtually anything so that popup can render above us instead. */
html.kconsensio-yield-stacking .kconsensio,
html.kconsensio-yield-stacking .kconsensio-modal,
html.kconsensio-yield-stacking .kconsensio-persistent {
    z-index: 1;
}

/* Blocked iframe placeholder: buildBlockedOverlays() in kconsensio.js wraps the iframe
   in .kconsensio-embed-wrap and lays .kconsensio-embed-overlay on top of it, so the
   visitor can enable it without hunting for the persistent "Cookie Settings" link elsewhere
   on the page. The flat background on the iframe itself is only a fallback for the brief
   moment before the overlay is attached (or if JS somehow fails). */
iframe.kconsensio-blocked {
    background: #f2f3f5;
    min-height: 8rem;
    max-width: 100%;
    height: auto;
}

/* Default: an iframe with no surrounding flex context (e.g. a plain fixed-size embed
   dropped into article text) is natively an inline replaced element sized by its own
   width/height attributes — inline-block here reproduces that shrink-to-fit sizing so
   the placeholder matches the iframe's own natural size instead of stretching full width. */
.kconsensio-embed-wrap {
    position: relative;
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
}

/* Added by buildBlockedOverlays() (JS) only when the iframe's original parent is itself a
   flex container — a common responsive-embed pattern (e.g. Bootstrap/Astroid's "d-flex" +
   "w-100") that sizes the iframe by making it a direct flex item stretching to fill both
   axes (width via a "w-100" utility class, height via the flex container's default
   align-items: stretch). Wrapping moves that role onto this div instead, so it has to
   reproduce the same fill behavior explicitly, and the nested iframe is forced to 100%/100%
   to inherit that space in turn — otherwise both collapse to the iframe's tiny intrinsic
   default size (observed as a ~300x300 square). Left off for non-flex iframes specifically
   so THEY keep their natural size instead of incorrectly stretching full width too. */
.kconsensio-embed-wrap--fill {
    display: block;
    flex: 1 1 auto;
    width: 100%;
    height: 100%;
}

.kconsensio-embed-wrap--fill iframe.kconsensio-blocked {
    display: block;
    width: 100%;
    height: 100%;
}

.kconsensio-embed-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 1rem;
    text-align: center;
    background: rgba(242, 243, 245, 0.96);
    color: #1b1f27;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.kconsensio-embed-overlay__icon {
    width: 2rem;
    height: 2rem;
    color: #6b7280;
    flex: 0 0 auto;
}

.kconsensio-embed-overlay__text {
    margin: 0;
    font-size: 0.85rem;
    max-width: 22rem;
}

.kconsensio-embed-overlay__btn {
    background: var(--jcg-accent, #2f6fed);
    border-color: var(--jcg-accent, #2f6fed);
    color: #ffffff;
    font-weight: 600;
}

/* Follows the plugin's own "Tema" (banner_theme) admin setting — same light/dark/auto
   resolution as .kconsensio/.kconsensio-modal__panel — rather than the browser's raw
   prefers-color-scheme unconditionally. The overlay is injected by JS wherever a blocked
   iframe happens to sit in the page, nowhere near the banner/modal DOM, so it can't just
   inherit the --jcg-bg/--jcg-fg custom properties (those are scoped to those elements);
   the theme class is applied directly to it instead (see buildBlockedOverlays() in
   kconsensio.js). Without this, a site explicitly set to "Light" or "Dark" (not "Auto")
   would still have this one element flip based on the visitor's OS/browser preference,
   which is what made it render differently across browsers with different color-scheme
   settings even though the plugin's theme option was the same. */
.kconsensio-embed-overlay--theme-dark {
    background: rgba(27, 31, 39, 0.96);
    color: #f2f3f5;
}

.kconsensio-embed-overlay--theme-dark .kconsensio-embed-overlay__icon {
    color: #9aa1ac;
}

@media (prefers-color-scheme: dark) {
    .kconsensio-embed-overlay--theme-auto {
        background: rgba(27, 31, 39, 0.96);
        color: #f2f3f5;
    }

    .kconsensio-embed-overlay--theme-auto .kconsensio-embed-overlay__icon {
        color: #9aa1ac;
    }
}

/* Small screens (phones): tighten spacing further and make every button full-width for
   easier tapping, instead of relying on flex-wrap to fit multiple buttons on one row. */
@media (max-width: 480px) {
    .kconsensio__panel {
        padding: 1rem;
        gap: 0.6rem;
    }

    .kconsensio__actions {
        flex-direction: column;
        align-items: stretch;
        width: 100%;
    }

    .kconsensio__btn {
        width: 100%;
        text-align: center;
        padding: 0.6rem 0.9rem;
    }

    .kconsensio--modal-center,
    .kconsensio--modal-bottom,
    .kconsensio--modal-top {
        width: calc(100% - 1.5rem);
    }

    .kconsensio--modal-bottom {
        bottom: 0.75rem;
    }

    .kconsensio--modal-top {
        top: 0.75rem;
    }

    .kconsensio-modal__panel {
        padding: 1rem;
        width: calc(100% - 1.5rem);
        max-height: calc(100% - 2rem);
    }

    /* env(safe-area-inset-*) pushes the badge clear of the iOS home-indicator gesture bar
       (bottom) and of a landscape notch (left/right); it's a no-op (defaults to 0) on any
       device/browser without a safe area, so it's safe to apply unconditionally, regardless
       of persistent_link_style (text/icon/icon_text keep whatever the admin configured — see
       renderPersistentLink() — this only tightens spacing and clears the safe area). */
    .kconsensio-persistent {
        left: calc(0.5rem + env(safe-area-inset-left));
        bottom: calc(0.5rem + env(safe-area-inset-bottom));
        padding: 0.4rem 0.8rem;
        font-size: 0.75rem;
    }

    .kconsensio-persistent--right {
        left: auto;
        right: calc(0.5rem + env(safe-area-inset-right));
    }

    /* 44px (2.75rem, same as the desktop size — not shrunk further) is the minimum
       comfortable touch target (WCAG 2.5.5 / Apple HIG / Material): this control must stay
       easy to tap, since withdrawing consent needs to stay as easy as giving it. */
    .kconsensio-persistent--icon {
        width: 2.75rem;
        height: 2.75rem;
        padding: 0;
    }
}
