/*
 * Site message strip — the full-width band between </header> and <main>.
 *
 * Two widths are in play and they are deliberately different: the band itself
 * is full bleed, the message inside it is held to the theme's content width,
 * and the dismiss cross is positioned against the *band*, so it sits at the
 * edge of the viewport rather than the edge of the text column.
 *
 * Rendered by PMutual\SiteMessageManager.
 */

.pm-site-messages {
    position: relative;
    width: 100%;

    /*
     * The gap belongs under the header, not under a particular block: it
     * separates the header from whatever comes next, which is the strip when one
     * is showing and the banner when one is not.
     *
     * So the strip keeps a gap above it and gives up the one below. The strip is
     * a flow sibling of <header> and <main> inside .wp-site-blocks, so
     * WordPress's block-gap rule would supply the top margin on its own, but it
     * is named here rather than inherited: this spacing is now load-bearing, and
     * it should not depend on which core selector happens to reach the element.
     */
    margin-block-start: var(--wp--style--block-gap, 24px);
    margin-block-end: 0;
}

/*
 * <main> owns the header gap whenever it is the first thing under the header.
 * When a message is showing, the strip has already provided it, and leaving both
 * in place stacked two gaps around the band and pushed the banner down 76px for
 * a 52px strip.
 *
 * Scoped to `:not([hidden])` so the moment the last message is dismissed — the
 * script sets `hidden` on the container — <main> takes the gap straight back and
 * the page returns to exactly its no-message spacing.
 *
 * A general sibling combinator, not adjacent: the strip is followed by its own
 * inline dismissal script, so `+ main` matches nothing at all.
 *
 * Core's own rule is `:where(.wp-site-blocks) > *`, which carries no
 * specificity, so this wins comfortably.
 */
.pm-site-messages:not([hidden]) ~ main {
    margin-block-start: 0;
}

.pm-site-messages[hidden],
.pm-site-message[hidden] {
    display: none;
}

/*
 * The band carries the site's root padding and the message inside it is
 * centred within that, which is exactly how the header is built:
 * .main-header-container is full width with 10px of padding, and its
 * constrained child holds the logo with none of its own.
 *
 * Mirroring that structure is what lines the message up with the logo. Putting
 * the gutter on the inner box instead — as this did first — indents the text by
 * the gutter twice over and leaves it 20px to the right of the logo at every
 * width.
 *
 * The absolutely positioned dismiss button is unaffected: an abspos box is laid
 * out against its containing block's padding edge, which here is still the
 * viewport edge.
 */
.pm-site-message {
    position: relative;
    /* width:100% plus the gutter would otherwise overrun the viewport, taking
       the dismiss button off the right-hand edge with it. */
    box-sizing: border-box;
    width: 100%;
    padding-inline:
        var(--wp--style--root--padding-left, 10px)
        var(--wp--style--root--padding-right, 10px);
    background: var(--pm-msg-bg);
    color: var(--pm-msg-fg);
    border-bottom: 1px solid var(--pm-msg-border, transparent);
}

/*
 * No inline padding of its own: the band above supplies the gutter, so this box
 * sits on precisely the same grid as the header's constrained inner container
 * and the message starts level with the logo.
 */
.pm-site-message__inner {
    box-sizing: border-box;
    max-width: var(--wp--style--global--content-size, 1200px);
    margin-inline: auto;
    padding-block: 0.875rem;
    font-size: 1rem;
    line-height: 1.45;
}

.is-aligned-left   { text-align: left; }
.is-aligned-center { text-align: center; }
.is-aligned-right  { text-align: right; }

/*
 * Urgency is carried by colour, which on its own is not a carrier at all for
 * anyone who cannot see it (WCAG 1.4.1). The level is announced instead.
 */
.pm-site-message__level {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.pm-site-message__text > p {
    margin: 0;
}

.pm-site-message__text > p + p {
    margin-block-start: 0.35rem;
}

/*
 * Links take the message's own colour and rely on the underline to stand out.
 * Any fixed link colour would have to clear contrast against all five schemes;
 * inheriting clears it by construction.
 */
.pm-site-message__text a {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 0.15em;
    text-decoration-thickness: from-font;
}

.pm-site-message__text a:hover,
.pm-site-message__text a:focus-visible {
    text-decoration-thickness: 2px;
}

.pm-site-message__text a:focus-visible,
.pm-site-message__dismiss:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

/* --- Dismiss control ---------------------------------------------------- */

/*
 * Hidden until the inline script confirms scripting is available, so a visitor
 * without JavaScript is never shown a cross that cannot do anything.
 */
.pm-site-message__dismiss {
    display: none;
}

.pm-site-messages--js .pm-site-message--dismissible .pm-site-message__dismiss {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-end: max(0.25rem, env(safe-area-inset-right, 0px));
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    cursor: pointer;
    transition: background-color 150ms ease;
}

.pm-site-messages--js .pm-site-message--dismissible .pm-site-message__dismiss:hover {
    background: color-mix(in srgb, currentColor 18%, transparent);
}

@media (prefers-reduced-motion: reduce) {
    .pm-site-message__dismiss {
        transition: none;
    }
}

/*
 * The cross overlaps the text column only on viewports narrow enough for the
 * two to meet. Past that width the content box is already clear of it, and
 * reserving a gutter there would shrink the message for no reason.
 *
 * The breakpoint is where the gap either side of a 1200px content box first
 * falls below the button's 56px footprint: 1200 + (2 x 56) = 1312px.
 */
@media (max-width: 1312px) {
    .pm-site-messages--js .pm-site-message--dismissible .pm-site-message__inner {
        padding-inline-end: 3.5rem;
    }

    /* Padding on one side only would push centred text off centre. */
    .pm-site-messages--js .pm-site-message--dismissible .pm-site-message__inner.is-aligned-center {
        padding-inline: 3.5rem;
    }
}

@media (max-width: 600px) {
    .pm-site-message__inner {
        padding-block: 0.75rem;
        font-size: 0.9375rem;
    }
}

/* --- Colour schemes ------------------------------------------------------ */

/*
 * Preset pairs only. Each background is matched with a foreground that clears
 * WCAG AA against it, so no choice available in the admin can produce an
 * unreadable strip.
 *
 * Palette variables are used only where the slug exists in both themes, and
 * every one carries a literal fallback: an unresolved var() drops the whole
 * declaration silently, which is how the shared icon set once ended up painting
 * nothing at all.
 */

.pm-site-message--scheme-critical {
    --pm-msg-bg: #b3261e;
    --pm-msg-fg: #ffffff;
    --pm-msg-border: rgba(0, 0, 0, 0.2);
}

/* Brand navy: #012169 on Police Mutual, #243868 on Forces. White clears on both. */
.pm-site-message--scheme-urgent {
    --pm-msg-bg: var(--wp--preset--color--secondary-accent, #012169);
    --pm-msg-fg: #ffffff;
    --pm-msg-border: rgba(0, 0, 0, 0.2);
}

.pm-site-message--scheme-warning {
    --pm-msg-bg: #fbc02d;
    --pm-msg-fg: #1a1a1a;
    --pm-msg-border: rgba(0, 0, 0, 0.15);
}

.pm-site-message--scheme-neutral {
    --pm-msg-bg: #2f3437;
    --pm-msg-fg: #ffffff;
    --pm-msg-border: rgba(0, 0, 0, 0.2);
}

/*
 * The one pale scheme, and the only one that needs a visible edge: against a
 * white header it would otherwise have no boundary at all.
 */
.pm-site-message--scheme-info {
    --pm-msg-bg: var(--wp--preset--color--secondary-base, #e6f9fd);
    --pm-msg-fg: var(--wp--preset--color--primary-foreground, #000000);
    --pm-msg-border: rgba(0, 0, 0, 0.18);
}

/* --- Ticker --------------------------------------------------------------
 *
 * The same band as the strip, scrolling. Two copies of the text sit in one
 * track translated by exactly half its width, which is what makes the loop
 * seamless; the second copy is `inert` in the markup so it is neither read out
 * nor focusable.
 */

.pm-site-message__ticker {
    overflow: hidden;
    /* Fades the text into the band at both ends rather than cutting it off
       mid-letter, which is what an overflow clip on its own looks like. */
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 2.5rem, #000 calc(100% - 2.5rem), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 2.5rem, #000 calc(100% - 2.5rem), transparent);
}

.pm-site-message__ticker-track {
    display: flex;
    /* Without this the flex track is only as wide as the box and both copies
       shrink to fit it, so the animation slides an already-truncated line. */
    width: max-content;
    animation: pm-site-message-ticker 34s linear infinite;
}

.pm-site-message__ticker-track > .pm-site-message__text {
    /* The gap between the end of one copy and the start of the next. It is part
       of the copy's own width, so translating by -50% still lands exactly on
       the start of the second one. */
    padding-inline-end: 4rem;
    white-space: nowrap;
}

@keyframes pm-site-message-ticker {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/*
 * Three ways to stop it, and they agree because all three resolve to the same
 * declaration. Hover and focus-within are what make a link inside a moving line
 * clickable at all; `is-paused` is the button, which is the one that satisfies
 * WCAG 2.2.2 because it is the only one a keyboard or touch user can rely on.
 */
.pm-site-message--ticker:hover .pm-site-message__ticker-track,
.pm-site-message--ticker:focus-within .pm-site-message__ticker-track,
.pm-site-message--ticker.is-paused .pm-site-message__ticker-track {
    animation-play-state: paused;
}

.pm-site-message__pause {
    display: none;
}

.pm-site-messages--js .pm-site-message--ticker .pm-site-message__pause {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-end: max(0.25rem, env(safe-area-inset-right, 0px));
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    cursor: pointer;
    transition: background-color 150ms ease;
}

/* Sits inboard of the cross when there is one. */
.pm-site-messages--js .pm-site-message--ticker.pm-site-message--dismissible .pm-site-message__pause {
    inset-inline-end: calc(max(0.25rem, env(safe-area-inset-right, 0px)) + 44px);
}

.pm-site-messages--js .pm-site-message--ticker .pm-site-message__pause:hover {
    background: color-mix(in srgb, currentColor 18%, transparent);
}

.pm-site-message__glyph--play {
    display: none;
}

.pm-site-message--ticker.is-paused .pm-site-message__glyph--pause {
    display: none;
}

.pm-site-message--ticker.is-paused .pm-site-message__glyph--play {
    display: block;
}

/*
 * Room for the controls, on the same terms as the static strip above: reserved
 * only once the content box is narrow enough to reach them, not at every width.
 *
 * Reserving it unconditionally is wrong here in a way it would not be for a
 * static line. The track is masked at both ends, so on a wide screen the fade
 * on the left would start 2.5rem in while the text on the right vanished nine
 * rem early — the band would read as visibly lopsided, and the ticker would be
 * narrower than the message above and below it for no reason.
 *
 * Two breakpoints because there are two button counts. A ticker carries a pause
 * control always and a cross only when it is dismissible: 1200 + (2 x 56) for
 * one button, and enough for two 44px buttons plus clearance for both.
 */
@media (max-width: 1312px) {
    .pm-site-messages--js .pm-site-message--ticker .pm-site-message__inner {
        padding-inline-end: 3.5rem;
    }
}

@media (max-width: 1400px) {
    .pm-site-messages--js .pm-site-message--ticker.pm-site-message--dismissible .pm-site-message__inner {
        padding-inline-end: 6.5rem;
    }
}

/*
 * Reduced motion gets a plain strip, not a slower ticker: the second copy is
 * removed, the line is allowed to wrap, and the edge fade goes with the
 * movement it existed to soften.
 */
@media (prefers-reduced-motion: reduce) {
    .pm-site-message__ticker-track {
        animation: none;
    }

    .pm-site-message__ticker {
        -webkit-mask-image: none;
        mask-image: none;
    }

    .pm-site-message__ticker-track > .pm-site-message__text {
        white-space: normal;
    }

    .pm-site-message__ticker-track > .pm-site-message__text[inert] {
        display: none;
    }

    .pm-site-messages--js .pm-site-message--ticker .pm-site-message__pause {
        display: none;
    }

    .pm-site-message__pause {
        transition: none;
    }
}

/* --- Floating roundel ----------------------------------------------------
 *
 * A second surface: a badge fixed to the corner of the viewport, so one of
 * these and one strip can be live together.
 *
 * Bottom RIGHT is not a preference. CookieYes parks its consent-revisit button
 * at the bottom left of every page (`cky-revisit-bottom-l`) at z-index 999999,
 * and the two would sit on top of each other. The z-index here is deliberately
 * far below that: the cookie banner is a legal control and must stay clickable
 * over anything this plugin puts on the page.
 */
.pm-site-roundels {
    position: fixed;
    z-index: 900;
    inset-block-end: max(1rem, env(safe-area-inset-bottom, 0px));
    inset-inline-end: max(1rem, env(safe-area-inset-right, 0px));
}

.pm-site-roundels[hidden],
.pm-site-roundel[hidden] {
    display: none;
}

.pm-site-roundel {
    position: relative;
}

.pm-site-roundel {
    /* Diameter in one place. The inset and the dismiss button's rim position are
       both fractions of it, so they follow it. */
    --pm-roundel-size: 216px;

    /* The type's base size, and deliberately NOT a fraction of the diameter.
       It was one until the badge came down from 256px to 200px with a brief to
       leave the words where they were — so the two are now separate knobs, and
       this holds the base the type was tuned at (256/13). Resizing the badge no
       longer resizes the text, which is the point, and is what let the circle
       go up 8% to 216px on its own. Every line inside, the terms link included,
       is an em off this one value.
       
       What that costs: the fit is no longer self-maintaining. The words occupy
       roughly 123 x 136px and the square inscribed in a 216px circle is 153px.
       Change either value and check it. */
    --pm-roundel-type: 19.7px;
}

/*
 * The circle is a plain box, not the link.
 *
 * It used to be the <a> itself, which was simpler and worked right up until the
 * badge needed a second destination in it. An <a> cannot contain another <a> —
 * a browser handed one closes the outer link early and the rest of the badge
 * stops being clickable — so the offer link now stretches over this box with a
 * pseudo-element and the terms link sits above that overlay.
 */
.pm-site-roundel__card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    /* min() is an overflow guard, not a design breakpoint: on any screen wider
       than about 248px this is simply 216px. */
    width: min(var(--pm-roundel-size), calc(100vw - 2rem));
    height: min(var(--pm-roundel-size), calc(100vw - 2rem));
    /* Every line inside is an em off this. */
    font-size: var(--pm-roundel-type);
    /* Percentage inset, not a fixed padding. The text has to fit the square
       inscribed in the circle — about 0.71 of the diameter — and that budget
       scales with the badge. */
    padding: 0.4em 13%;
    border: 3px solid var(--wp--preset--color--primary-accent, #f95b00);
    border-radius: 50%;
    background: var(--pm-msg-bg);
    color: var(--pm-msg-fg);
    text-align: center;
    box-shadow: 0 10px 26px rgba(1, 33, 105, 0.34);
    transition: transform 150ms ease;
}

.pm-site-roundel__card:hover {
    transform: translateY(-2px);
}

.pm-site-roundel__link {
    color: inherit;
    text-decoration: none;
}

/*
 * The offer link's hit area: the whole circle, minus whatever sits above it.
 * `border-radius` matters — without it the corners of the square would be
 * clickable, which on a badge that floats over the page means catching clicks
 * meant for the content behind it.
 */
.pm-site-roundel__link::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
}

/*
 * The focus ring belongs on the stretched overlay, not on the link box — the
 * link box is only as big as the four lines of text, so a ring there would
 * outline the words rather than the thing being activated.
 */
.pm-site-roundel__link:focus-visible {
    outline: none;
}

.pm-site-roundel__link:focus-visible::after {
    outline: 3px solid currentColor;
    outline-offset: 3px;
}

.pm-site-roundel__face {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.1;
}

.pm-site-roundel__eyebrow {
    font-size: 0.62em;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
}

.pm-site-roundel__figure {
    margin-block-start: 0.08em;
    font-size: 2.9em;
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.02em;
}

.pm-site-roundel__detail {
    font-size: 0.76em;
    font-weight: 700;
}

.pm-site-roundel__footer {
    margin-block-start: 0.5em;
    padding-block-start: 0.45em;
    border-block-start: 1px solid color-mix(in srgb, currentColor 32%, transparent);
    font-size: 0.56em;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

/*
 * The terms line. `position: relative` lifts it out from under the offer link's
 * stretched overlay — without it the click would land on the offer, which is
 * the whole failure this structure exists to avoid.
 *
 * Quieter than the four lines above it by size and weight, but underlined and
 * at full colour: it is the one piece of small print in the badge, and small
 * print that does not look like a link does not get read.
 */
.pm-site-roundel__terms {
    position: relative;
    z-index: 1;
    margin-block-start: 0.4em;
    color: inherit;
    /* An em off the badge's type base, like the four lines above it, so the
       badge is still governed by two values and this line moves with the rest.
       
       The ratio is 0.7rem divided by the 19.7px base: it lands on 11.2px today,
       which is where an absolute 0.7rem put it, but it will now follow
       --pm-roundel-type instead of standing still while everything else moves.
       The odd-looking number is the price of matching that size exactly rather
       than rounding to a tidier ratio and shifting the line. */
    font-size: 0.56853em;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-decoration: underline;
    text-underline-offset: 0.18em;
}

.pm-site-roundel__terms:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
    border-radius: 2px;
}

/* Hidden until the inline script confirms scripting, as the strip's cross is. */
.pm-site-roundel__dismiss {
    display: none;
}

.pm-site-roundels--js .pm-site-roundel--dismissible .pm-site-roundel__dismiss {
    position: absolute;
    /* Above the offer link's stretched overlay, which reaches the corners of
       the badge's box and would otherwise swallow the cross. */
    z-index: 2;
    /* Sat on the rim at 45 degrees, not tucked into the bounding box's corner.
       The corner of the box is 0.414r clear of the circle — 41px at this size —
       so a button placed there floats in space with nothing behind it.
       
       The offset from each edge to the button's CENTRE is r - r/√2, which is
       0.1465 of the diameter; subtracting half the button turns that into an
       inset. Written as a calc rather than a flat percentage because the button
       is a fixed 36px while the badge is not: a percentage alone is only
       correct at one diameter, and was silently wrong the moment this dropped
       from 256px to 200px. */
    inset-block-start: calc(14.65% - 18px);
    inset-inline-end: calc(14.65% - 18px);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 2px solid var(--pm-msg-bg);
    border-radius: 50%;
    background: var(--pm-msg-fg);
    color: var(--pm-msg-bg);
    cursor: pointer;
}

.pm-site-roundels--js .pm-site-roundel--dismissible .pm-site-roundel__dismiss .pm-site-message__cross {
    width: 18px;
    height: 18px;
}

/*
 * No phone step-down. The badge holds 216px everywhere, which is the point of
 * it — at 128px the four lines inside were there but not readable, and shrinking
 * it again on the screen where it matters most would put that back.
 *
 * What that costs is worth saying plainly: on a 375px handset this covers a
 * little over half the width at the bottom of the screen. It is dismissible, and
 * it sits clear of CookieYes on the other side, but it is a deliberate
 * imposition rather than an incidental one.
 */

@media (prefers-reduced-motion: reduce) {
    .pm-site-roundel__card {
        transition: none;
    }

    .pm-site-roundel__card:hover {
        transform: none;
    }
}
