/**
 * Niblo runtime styles.
 *
 * ---------------------------------------------------------------------------
 * The surface contract
 *
 * Every format shares one look, and it comes from tokens rather than from
 * values typed into each format's own rules. Anything a reader taps or reads
 * in the page - an answer, a poll row, a side of a matchup, a cover, a button
 * - is drawn with:
 *
 *     border:        var(--niblo-border) solid var(--niblo-line)
 *     border-radius: var(--niblo-radius)
 *     box-shadow:    var(--niblo-shadow) var(--niblo-shadow) 0 var(--niblo-line)
 *     background:    var(--niblo-paper)     (only where no picture fills it)
 *
 * and reacts with the shared keyframes: niblo-pop when it is picked or right,
 * niblo-nudge when it is wrong, niblo-mark for the tick or cross.
 *
 * The panel contract
 *
 * Over a full-bleed photograph the takeover keeps its own surface: it is white
 * text on a picture, and the article's paper cards would either hide the photo
 * or be unreadable on it. Five tokens carry whichever treatment the site picked
 * under Design > Colours - frosted glass by default, or solid, or the page's
 * own cards:
 *
 *     background:        var(--niblo-imm-fill)
 *     border:            var(--niblo-border) solid var(--niblo-imm-line)
 *     box-shadow:        var(--niblo-imm-lift)
 *     color:             var(--niblo-imm-text)
 *     backdrop-filter:   var(--niblo-imm-blur)
 *
 * Everything else about the takeover - its ground, its chrome, its muted type -
 * is worked out from the full-screen background in
 * niblo_immersive_custom_properties(), so one colour repaints the lot.
 *
 * A verdict is the exception: right and wrong are drawn at full strength, never
 * mixed into the panel, because a washed-out green is the opposite of what a
 * right answer is for.
 *
 * A new format joins by using these tokens. Anything that hardcodes a colour,
 * a radius or a border is a format that will quietly stop matching the rest the
 * first time somebody changes a setting - which is exactly what had happened to
 * the poll, the matchup and the rating cover.
 * ---------------------------------------------------------------------------
 *
 * Self-contained and scoped under .niblo, so the plugin does not depend on the
 * theme and cannot be broken by it. Sizes come from custom properties, which is
 * the single place to adjust the look per site.
 *
 * Images always carry width and height, and answer rows have a minimum height,
 * so advancing a question never shifts the layout.
 */

.niblo {
    /*
     * An editorial palette rather than a dashboard one.
     *
     * The greys it replaced were the reason a quiz read as a form: a hairline
     * outline on white says "field", a full-weight ink outline on warm paper
     * says "poster". Nothing here moved - the border was already two pixels
     * wide, it was simply the colour of nothing.
     *
     * Every one of these is a setting. A site that has picked its own keeps it.
     */
    --niblo-accent: #4b46e8;
    --niblo-correct: #191515;
    --niblo-correct-fill: #58c96b;
    --niblo-correct-ink: #191515;
    --niblo-wrong: #191515;
    --niblo-wrong-fill: #f04444;
    --niblo-wrong-ink: #fffdf8;
    --niblo-bg: #f5f0e8;
    --niblo-paper: #fffdf8;
    --niblo-fg: #191515;
    --niblo-muted: #756d68;
    --niblo-line: #191515;
    --niblo-radius: 18px;
    /* Border width is the one shape value that changes a button's size. */
    --niblo-border: 2px;
    --niblo-shadow: 3px;
    --niblo-gap: 12px;

    background: var(--niblo-bg);
    box-sizing: border-box;
    color: var(--niblo-fg);
    font-size: 17px;
    line-height: 1.5;
    margin: 2rem 0;
    /*
     * No container-type here. It applies inline-size containment, and inside a
     * flex or grid parent that makes the element size as if it were empty - it
     * collapses to min-content and every word wraps to its own line.
     */
    max-width: 100%;
    min-width: 0;
    width: 100%;
}

.niblo *,
.niblo *::before,
.niblo *::after {
    box-sizing: border-box;
}

/*
 * The same system after dark: paper becomes ink and the outline becomes paper,
 * so the drawing is identical and only the ground has changed.
 */
@media (prefers-color-scheme: dark) {
    .niblo {
        --niblo-bg: #191515;
        --niblo-paper: #241f1f;
        --niblo-fg: #fffdf8;
        --niblo-muted: #a89f99;
        --niblo-line: #fffdf8;
        --niblo-correct: #fffdf8;
        --niblo-correct-fill: #2e6b39;
        --niblo-correct-ink: #eafbee;
        --niblo-wrong: #fffdf8;
        --niblo-wrong-fill: #8f2020;
        --niblo-wrong-ink: #ffecec;
    }
}

/* ---- progress ---- */

.niblo-progress {
    background: var(--niblo-line);
    border-radius: 999px;
    height: 6px;
    margin-bottom: 1.25rem;
    overflow: hidden;
}

.niblo-progress-bar {
    background: var(--niblo-accent);
    height: 100%;
    width: 0;
    /* Transform-free width animation is fine here: it is the only moving part. */
    transition: width 260ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---- question ---- */

.niblo-q {
    animation: niblo-in 200ms ease-out;
}

@keyframes niblo-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .niblo-q { animation: none; }
    .niblo-progress-bar { transition: none; }
}

.niblo-q-count {
    color: var(--niblo-muted);
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    margin: 0 0 0.4rem;
    text-transform: uppercase;
}

.niblo-q-title {
    font-size: var(--niblo-question-size, clamp(1.3rem, 1.1rem + 1.2vw, 1.9rem));
    line-height: 1.25;
    margin: 0 0 1rem;
}

.niblo-q-media {
    margin: 0 0 1.25rem;
}

.niblo-q-media img {
    border-radius: var(--niblo-radius);
    display: block;
    height: auto;
    max-width: 100%;
    width: 100%;
}

/* ---- answers ---- */

/*
 * Themes style ul, li and button aggressively, and a quiz dropped into post
 * content inherits all of it. Everything below is deliberately over-specified
 * and resets the properties a theme is most likely to have opinions about.
 */
.niblo .niblo-answers {
    display: grid;
    gap: var(--niblo-gap);
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

.niblo .niblo-answers-media {
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.niblo .niblo-a {
    background: none;
    border: 0;
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

.niblo .niblo-a::before,
.niblo .niblo-a::marker {
    content: none;
}

.niblo .niblo-a-btn {
    align-items: center;
    background: var(--niblo-paper);
    border: var(--niblo-border) solid var(--niblo-line);
    border-radius: var(--niblo-radius);
    /*
     * The offset shadow is the whole editorial cue, and it costs no layout: a
     * box-shadow takes up no room, so every answer sits exactly where it did.
     */
    box-shadow: var(--niblo-shadow) var(--niblo-shadow) 0 var(--niblo-line);
    color: inherit;
    cursor: pointer;
    display: flex;
    font: inherit;
    gap: 0.75rem;
    letter-spacing: normal;
    line-height: 1.4;
    margin: 0;
    min-height: 56px;
    overflow: hidden;
    padding: 0.85rem 1rem;
    text-align: left;
    text-transform: none;
    transition: border-color 140ms ease, background-color 140ms ease,
        box-shadow 140ms ease, transform 140ms ease;
    width: 100%;
}

.niblo .niblo-answers-media .niblo-a-btn {
    display: block;
    padding: 0;
}

/*
 * Hover fills rather than merely outlining, and the card lifts off its own
 * shadow. Two pixels, on a pointer only: a touch device has no hover state to
 * hold, and the lift would fire on the way to a tap.
 */
@media (hover: hover) {
    .niblo .niblo-a-btn:hover {
        background: var(--niblo-accent);
        border-color: var(--niblo-line);
        box-shadow: calc(var(--niblo-shadow) + 2px) calc(var(--niblo-shadow) + 2px) 0 var(--niblo-line);
        color: #fffdf8;
        transform: translateY(-2px);
    }
}

.niblo .niblo-a-btn:active {
    box-shadow: calc(var(--niblo-shadow) - 2px) calc(var(--niblo-shadow) - 2px) 0 var(--niblo-line);
    transform: translateY(1px);
}

@media (prefers-reduced-motion: reduce) {
    .niblo .niblo-a-btn { transition: none; }
    .niblo .niblo-a-btn:hover,
    .niblo .niblo-a-btn:active { transform: none; }
}

.niblo .niblo-a-btn:focus-visible {
    outline: 3px solid var(--niblo-accent);
    outline-offset: 2px;
}

.niblo-a-img {
    display: block;
    height: auto;
    width: 100%;
}

.niblo-answers-media .niblo-a-text {
    display: block;
    padding: 0.7rem 0.9rem;
}

/* Once answered, the buttons stop being interactive but stay readable. */
.niblo .niblo-answers.is-answered .niblo-a-btn {
    cursor: default;
    pointer-events: none;
}

.niblo .niblo-answers.is-answered .niblo-a-btn:not(.is-correct):not(.is-wrong):not(.is-chosen) {
    opacity: 0.55;
}

.niblo .niblo-a-btn.is-correct {
    background: var(--niblo-correct-fill);
    border-color: var(--niblo-correct);
    color: var(--niblo-correct-ink);
    font-weight: 600;
}

.niblo .niblo-a-btn.is-wrong {
    background: var(--niblo-wrong-fill);
    border-color: var(--niblo-wrong);
    color: var(--niblo-wrong-ink);
    font-weight: 600;
}

/* A revealed answer stays fully legible even though it is no longer active. */
.niblo .niblo-answers.is-answered .niblo-a-btn.is-correct,
.niblo .niblo-answers.is-answered .niblo-a-btn.is-wrong {
    opacity: 1;
}

.niblo .niblo-a-btn.is-chosen {
    background: var(--niblo-accent);
    border-color: var(--niblo-line);
    color: #fffdf8;
}

/* ---- next / again ---- */

.niblo .niblo-next,
.niblo .niblo-again {
    background: var(--niblo-accent);
    border: 0;
    border-radius: 999px;
    /* Shadow only. A border would change the button's size, and nothing moves. */
    box-shadow: var(--niblo-shadow) var(--niblo-shadow) 0 var(--niblo-line);
    color: #fffdf8;
    cursor: pointer;
    display: inline-block;
    font: inherit;
    font-weight: 600;
    margin-top: 1.25rem;
    padding: 0.8rem 1.9rem;
}

.niblo .niblo-next:hover,
.niblo .niblo-again:hover {
    filter: brightness(1.08);
}

/* ---- result ---- */

.niblo-result {
    animation: niblo-in 240ms ease-out;
    text-align: center;
}

.niblo-result-score {
    color: var(--niblo-muted);
    font-size: 0.85rem;
    letter-spacing: 0.06em;
    margin: 0 0 0.5rem;
    text-transform: uppercase;
}

.niblo-result-media img {
    border-radius: var(--niblo-radius);
    display: block;
    height: auto;
    margin: 0 auto 1rem;
    max-width: 100%;
}

.niblo-result-title {
    font-size: var(--niblo-result-size, clamp(1.5rem, 1.2rem + 1.6vw, 2.2rem));
    margin: 0 0 0.75rem;
}

.niblo-result-desc {
    color: var(--niblo-muted);
    margin: 0 auto;
    max-width: 60ch;
}


/* ---- shared buttons ---- */

.niblo .niblo-btn {
    background: transparent;
    border: 2px solid var(--niblo-line);
    border-radius: 999px;
    color: inherit;
    cursor: pointer;
    display: inline-block;
    font: inherit;
    font-weight: 600;
    letter-spacing: normal;
    line-height: 1.2;
    margin: 0;
    padding: 0.8rem 1.8rem;
    text-decoration: none;
    text-transform: none;
    transition: filter 140ms ease, border-color 140ms ease;
}

.niblo .niblo-btn-primary {
    background: var(--niblo-accent);
    border-color: var(--niblo-accent);
    color: #fff;
}

.niblo .niblo-btn:hover {
    filter: brightness(1.08);
}

.niblo .niblo-next {
    margin-top: 1.25rem;
}

/* ---- start screen ---- */

.niblo-start {
    text-align: center;
}

.niblo-start-media img {
    border-radius: var(--niblo-radius);
    display: block;
    height: auto;
    margin: 0 auto 1.25rem;
    max-width: 100%;
    width: 100%;
}

.niblo-start-text {
    margin: 0 auto 1rem;
    max-width: 60ch;
}

.niblo-start-count {
    color: var(--niblo-muted);
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    margin: 0 0 1.25rem;
    text-transform: uppercase;
}

/* ---- answer markers ---- */

.niblo .niblo-a-mark {
    align-items: center;
    border: 2px solid var(--niblo-line);
    border-radius: 8px;
    display: flex;
    flex: 0 0 auto;
    font-size: 0.8rem;
    font-weight: 700;
    height: 28px;
    justify-content: center;
    width: 28px;
}

.niblo .niblo-answers-media .niblo-a-mark {
    display: none;
}

.niblo .niblo-a-btn.is-correct .niblo-a-mark {
    background: var(--niblo-correct);
    border-color: var(--niblo-correct);
    color: #fff;
    font-size: 0;
}

.niblo .niblo-a-btn.is-correct .niblo-a-mark::after {
    content: "\2713";
    font-size: 15px;
}

.niblo .niblo-a-btn.is-wrong .niblo-a-mark {
    background: var(--niblo-wrong);
    border-color: var(--niblo-wrong);
    color: #fff;
    font-size: 0;
}

.niblo .niblo-a-btn.is-wrong .niblo-a-mark::after {
    content: "\2715";
    font-size: 15px;
}

/* A pick with reveal held back: acknowledged, but not judged. */
.niblo .niblo-a-btn.is-chosen:not(.is-correct):not(.is-wrong) {
    background: var(--niblo-accent);
    border-color: var(--niblo-line);
    color: #fffdf8;
}

/* On a filled row the mark has to invert, or it is accent on accent. */
.niblo .niblo-a-btn.is-chosen:not(.is-correct):not(.is-wrong) .niblo-a-mark {
    background: #fffdf8;
    border-color: #fffdf8;
    color: var(--niblo-accent);
}

/* ---- result actions ---- */

.niblo-actions {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
    margin-top: 1.5rem;
}

.niblo-share {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.niblo .niblo-btn-share {
    font-size: 0.85rem;
    padding: 0.6rem 1.1rem;
}

/* ---- end-of-quiz review ---- */

.niblo-review {
    border-top: 1px solid var(--niblo-line);
    margin-top: 2rem;
    padding-top: 1.5rem;
    text-align: left;
}

.niblo-review-title {
    font-size: 0.8rem;
    letter-spacing: 0.06em;
    margin: 0 0 1rem;
    text-transform: uppercase;
}

.niblo-review-q {
    margin-bottom: 1.25rem;
}

.niblo-review-qt {
    font-weight: 600;
    margin: 0 0 0.4rem;
}

.niblo .niblo-review-answers {
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

.niblo .niblo-review-a {
    border-left: 3px solid transparent;
    color: var(--niblo-muted);
    list-style: none !important;
    margin: 0 0 2px !important;
    padding: 4px 10px !important;
}

.niblo .niblo-review-a.is-correct {
    border-left-color: var(--niblo-correct);
    color: var(--niblo-fg);
    font-weight: 600;
}

.niblo .niblo-review-a.is-wrong {
    border-left-color: var(--niblo-wrong);
    color: var(--niblo-fg);
    text-decoration: line-through;
}

.niblo-review-holder {
    margin-top: 1.5rem;
}

.niblo .niblo-btn-review {
    border-color: var(--niblo-accent);
    color: var(--niblo-accent);
}

/* ==========================================================================
   Hot or not — cover in the page, immersive takeover on tap

   Colours come from the theme's own palette, injected as custom properties on
   the overlay by the runtime. Every one has a neutral fallback, so a theme that
   declares nothing still renders. No fixed brand colours, no frosted glass:
   solid surfaces read better over photography and cost nothing to paint.
   ========================================================================== */

.niblo-hot-imm,
.niblo-imm {
    --niblo-accent: #1a73e8;
    --niblo-hot: #d93025;
    --niblo-cold: #1a73e8;
    --niblo-surface: #191515;
    --niblo-ink: #ffffff;
    /* Solid chrome. Translucent white over a photo is the frosted-glass look
       even without a backdrop filter, and it muddies against a busy image. */
    --niblo-raise: #1e2024;
    --niblo-raise-hi: #2b2e35;
    --niblo-edge: #3a3e46;
    --niblo-soft: #a9aeb8;
}

/* ---- the cover that sits in the post ---- */

.niblo-cover-card {
    aspect-ratio: 4 / 5;
    /* The same outline every other surface has; the picture supplies the fill. */
    border: var(--niblo-border) solid var(--niblo-line);
    border-radius: var(--niblo-radius);
    box-shadow: var(--niblo-shadow) var(--niblo-shadow) 0 var(--niblo-line);
    color: #fff;
    display: flex;
    isolation: isolate;
    max-height: 70vh;
    max-height: 70dvh;
    overflow: hidden;
    position: relative;
}

.niblo-cover-bg {
    animation: niblo-kenburns 12s ease-in-out infinite alternate;
    background: center/cover no-repeat;
    inset: -4%;
    position: absolute;
}

@keyframes niblo-kenburns {
    from { transform: scale(1); }
    to   { transform: scale(1.08); }
}

.niblo-cover-scrim {
    background: linear-gradient(to top, rgba(0,0,0,.92) 0%, rgba(0,0,0,.25) 55%, rgba(0,0,0,.5) 100%);
    inset: 0;
    position: absolute;
}

.niblo-cover-inner {
    align-self: flex-end;
    padding: 24px;
    position: relative;
    width: 100%;
    z-index: 1;
}

.niblo-eyebrow {
    color: var(--niblo-soft);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .2em;
    margin: 0 0 8px;
    text-transform: uppercase;
}

.niblo-cover-title {
    color: #fff;
    font-size: clamp(1.25rem, 1rem + 1.2vw, 1.75rem);
    font-weight: 500;
    line-height: 1.1;
    margin: 0 0 6px;
}

.niblo-cover-count { color: var(--niblo-soft); margin: 0 0 18px; }

/* In the page it is a surface like any other; full screen it sits on a photo. */
.niblo .niblo-cta {
    box-shadow: var(--niblo-shadow) var(--niblo-shadow) 0 var(--niblo-line);
}

.niblo .niblo-cta,
.niblo-imm .niblo-cta {
    background: var(--niblo-accent);
    border: 0;
    border-radius: 999px;
    color: #fff;
    cursor: pointer;
    display: inline-block;
    font: inherit;
    font-size: .95rem;
    font-weight: 700;
    padding: 14px 30px;
    text-decoration: none;
    transition: transform 140ms ease, filter 140ms ease;
}

.niblo .niblo-cta:hover,
.niblo-imm .niblo-cta:hover { filter: brightness(1.1); }
.niblo .niblo-cta:active { transform: scale(.96); }

.niblo-cta-sm { font-size: .85rem; padding: 10px 22px; }

.niblo-imm .niblo-ghost {
    background: var(--niblo-raise);
    border: 1px solid var(--niblo-edge);
    border-radius: 999px;
    color: #fff;
    cursor: pointer;
    font: inherit;
    font-size: .85rem;
    font-weight: 600;
    padding: 10px 20px;
}

.niblo-imm .niblo-ghost:hover { background: var(--niblo-raise-hi); }

/* ---- the takeover ---- */

body.niblo-imm-open { overflow: hidden; }

.niblo-imm {
    background: var(--niblo-surface);
    color: var(--niblo-ink);
    inset: 0;
    position: fixed;
    z-index: 100000;
}

.niblo-imm-ambient {
    background: center/cover no-repeat;
    display: none;
    filter: blur(60px) brightness(.35) saturate(1.1);
    inset: 0;
    position: absolute;
    transform: scale(1.2);
    transition: background-image .4s ease;
}

.niblo-imm-brand {
    align-items: center;
    display: flex;
    height: 60px;
    justify-content: center;
    left: 0;
    padding-top: env(safe-area-inset-top, 0px);
    pointer-events: none;
    position: absolute;
    right: 0;
    top: 0;
    z-index: 3;
}

.niblo-imm-name {
    font-size: 15px;
    font-weight: 800;
    letter-spacing: .03em;
    text-shadow: 0 1px 10px rgba(0, 0, 0, .6);
}

.niblo-imm-logo { display: block; max-height: 28px; width: auto; }

.niblo-imm-close {
    backdrop-filter: var(--niblo-imm-blur, none);
    background: var(--niblo-imm-fill, #fffdf8);
    border: var(--niblo-border, 1px) solid var(--niblo-imm-line, #191515);
    border-radius: 50%;
    box-shadow: var(--niblo-imm-lift, none);
    color: var(--niblo-imm-text, #191515);
    cursor: pointer;
    height: 38px;
    position: absolute;
    right: 14px;
    top: calc(env(safe-area-inset-top, 0px) + 11px);
    width: 38px;
    z-index: 5;
}

.niblo-imm-close::before,
.niblo-imm-close::after {
    background: #fff;
    content: "";
    height: 2px;
    left: 50%;
    position: absolute;
    top: 50%;
    width: 15px;
}

.niblo-imm-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.niblo-imm-close::after  { transform: translate(-50%, -50%) rotate(-45deg); }

.niblo-imm-frame {
    align-items: center;
    display: flex;
    gap: 22px;
    /* vh first: an engine without dvh drops that line and keeps this one.
       Without a fallback the height is auto and every slide collapses. */
    height: 100vh;
    height: 100dvh;
    justify-content: center;
    position: relative;
    z-index: 1;
}

.niblo-imm-shell {
    background: #000;
    height: 100vh;
    height: 100dvh;
    max-width: 430px;
    overflow: hidden;
    position: relative;
    width: 100%;
}

.niblo-imm-shell.is-shaking { animation: niblo-shake 700ms cubic-bezier(.36, .07, .19, .97); }

@keyframes niblo-shake {
    10%, 90% { transform: translate3d(-2px, 0, 0); }
    20%, 80% { transform: translate3d(4px, 0, 0); }
    30%, 50%, 70% { transform: translate3d(-7px, 0, 0); }
    40%, 60% { transform: translate3d(7px, 0, 0); }
}

.niblo-feed {
    height: 100%;
    overflow-y: scroll;
    scroll-behavior: smooth;
    scroll-snap-type: y mandatory;
    scrollbar-width: none;
    /*
     * Vertical is the browser's, horizontal is ours.
     *
     * Without this a rightward drag is the browser's own "go back" gesture and
     * the swipe never reaches the page at all.
     */
    overscroll-behavior: contain;
    touch-action: pan-y;
}

.niblo-feed::-webkit-scrollbar { display: none; }

/* ---- a slide ---- */

.niblo-slide {
    /*
     * Border box, always. The height is fixed to one viewport, so any padding
     * added inside must come out of that height rather than on top of it -
     * otherwise the slide runs past the fold and the next one starts early.
     */
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    height: 100%;
    justify-content: flex-end;
    overflow: hidden;
    position: relative;
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

.niblo-slide-bg {
    animation: niblo-kenburns 9s ease-in-out infinite alternate;
    background: center/cover no-repeat;
    inset: -4%;
    position: absolute;
}

.niblo-slide-bg.is-dim { animation: none; filter: brightness(.35) blur(2px); }

.niblo-slide-scrim {
    background: linear-gradient(to bottom,
        rgba(0,0,0,.5) 0%, rgba(0,0,0,.02) 24%, rgba(0,0,0,.1) 45%, rgba(0,0,0,.92) 100%);
    inset: 0;
    position: absolute;
    z-index: 1;
}

.niblo-slide-foot {
    padding: 0 20px calc(env(safe-area-inset-bottom, 0px) + 26px);
    position: relative;
    z-index: 4;
}

.niblo-slide-title {
    font-size: 1.05rem;
    font-weight: 500;
    margin: 0 0 4px;
    text-shadow: 0 1px 6px rgba(0, 0, 0, .6);
}

.niblo-slide-caption {
    color: rgba(255, 255, 255, .85);
    font-size: .95rem;
    line-height: 1.4;
    margin: 0 0 10px;
    text-shadow: 0 1px 6px rgba(0, 0, 0, .6);
}

.niblo-slide-meta {
    align-items: center;
    display: flex;
    gap: 14px;
    justify-content: space-between;
}

.niblo-slide-index {
    color: var(--niblo-soft);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .14em;
}

.niblo-imm .niblo-slide-share {
    background: var(--niblo-raise);
    border: 1px solid var(--niblo-edge);
    border-radius: 999px;
    color: #fff;
    cursor: pointer;
    font: inherit;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    padding: 7px 14px;
    text-transform: uppercase;
}

.niblo-imm .niblo-slide-share:hover { background: var(--niblo-raise-hi); }

/* ---- the two reactions ---- */

.niblo-imm .niblo-vote {
    align-items: center;
    /*
     * The emoji is the button.
     *
     * A panel around it made a rating look like a form with two grey pills on
     * it; the reaction is the whole point and it should be the only thing
     * there. The tap target is still the full 62px - it is just not drawn.
     */
    background: none;
    border: 0;
    border-radius: 50%;
    color: var(--niblo-ink, #fff);
    cursor: pointer;
    display: flex;
    height: 62px;
    justify-content: center;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    transition: transform 150ms ease, opacity 200ms ease, background 200ms ease;
    width: 62px;
    z-index: 6;
}

.niblo-imm .niblo-vote:active { transform: translateY(-50%) scale(.88); }

/*
 * The same pop the page gives an answer. On a control with no panel it is the
 * only acknowledgement there is, so it is bigger here and it lands on the
 * emoji rather than on a box.
 */
.niblo-imm .niblo-vote.is-chosen {
    animation: niblo-vote-pop 380ms cubic-bezier(.34, 1.5, .64, 1);
    background: none;
}

@keyframes niblo-vote-pop {
    0%   { transform: translateY(-50%) scale(1); }
    35%  { transform: translateY(-50%) scale(1.35); }
    100% { transform: translateY(-50%) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
    .niblo-imm .niblo-vote.is-chosen { animation: none; }
}
.niblo-vote-hot { left: 14px; }
.niblo-vote-not { right: 14px; }

/* A super side reads as the loaded one before it is even pressed. */
.niblo-imm .niblo-vote.is-super .niblo-vote-emoji {
    filter: drop-shadow(0 0 10px var(--niblo-hot)) drop-shadow(0 0 22px var(--niblo-hot));
}

.niblo-imm .niblo-vote-not.is-super .niblo-vote-emoji {
    filter: drop-shadow(0 0 10px var(--niblo-cold)) drop-shadow(0 0 22px var(--niblo-cold));
}

.niblo-vote-emoji {
    font-size: 40px;
    line-height: 1;
    /* Its own shadow, because there is no panel between it and the photo. */
    filter: drop-shadow(0 2px 10px rgba(0, 0, 0, .55));
    transition: filter 200ms ease;
}

.niblo-vote-emoji::before {
    content: var(--niblo-emoji, "");
    font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
}

.niblo-vote-count {
    bottom: -21px;
    color: var(--niblo-soft);
    font-size: 10.5px;
    font-weight: 800;
    position: absolute;
}

.niblo-imm .niblo-vote.is-faded { opacity: .3; pointer-events: none; }
.niblo-imm .niblo-vote.is-chosen { background: var(--niblo-accent); border-color: transparent; }
.niblo-slide.is-answered .niblo-vote { pointer-events: none; }

/* ---- burst ---- */

.niblo-burst {
    align-items: center;
    display: flex;
    inset: 0;
    justify-content: center;
    pointer-events: none;
    position: absolute;
    z-index: 20;
}

.niblo-burst-mark {
    animation: niblo-burst 900ms cubic-bezier(.17, .89, .32, 1.49) forwards;
    filter: drop-shadow(0 8px 24px rgba(0, 0, 0, .55));
    font-size: clamp(5rem, 26vw, 7rem);
    line-height: 1;
}

.niblo-burst-mark::before,
.niblo-storm-mark::before {
    content: var(--niblo-emoji, "");
    font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
}

@keyframes niblo-burst {
    0%   { opacity: 0; transform: scale(.3); }
    28%  { opacity: 1; transform: scale(1.15); }
    45%  { opacity: 1; transform: scale(.95); }
    62%  { opacity: 1; transform: scale(1.05); }
    100% { opacity: 0; transform: scale(1.25); }
}

/* ---- super: a storm of them, rising ---- */

.niblo-burst.is-storm { align-items: flex-end; }

.niblo-storm-mark {
    animation: niblo-storm 1900ms cubic-bezier(.22, .61, .36, 1) forwards;
    bottom: 0;
    filter: drop-shadow(0 6px 18px rgba(0, 0, 0, .5));
    font-size: clamp(2.2rem, 9vw, 3.4rem);
    left: var(--x, 50%);
    line-height: 1;
    opacity: 0;
    position: absolute;
}

@keyframes niblo-storm {
    0%   { opacity: 0; transform: translate(-50%, 20%) scale(calc(var(--scale, 1) * .4)); }
    15%  { opacity: 1; }
    70%  { opacity: 1; }
    100% {
        opacity: 0;
        transform: translate(calc(-50% + var(--drift, 0px)), -85vh) scale(var(--scale, 1)) rotate(18deg);
    }
}

/* ---- ads ---- */

/*
 * The slide keeps its default bottom-aligned layout so the ad's copy sits where
 * a caption sits on every other slide. Centring the whole column floated the
 * text into the middle of the creative.
 */
.niblo-ad { background: #000; }

.niblo-ad-flag {
    background: rgba(0, 0, 0, .6);
    border-radius: 4px;
    color: var(--niblo-soft);
    font-size: 10px;
    font-weight: 800;
    left: 14px;
    letter-spacing: .14em;
    padding: 4px 8px;
    position: absolute;
    text-transform: uppercase;
    top: calc(env(safe-area-inset-top, 0px) + 70px);
    z-index: 5;
}

.niblo-ad-media {
    display: block;
    height: 100%;
    inset: 0;
    object-fit: cover;
    position: absolute;
    width: 100%;
}

/* The AdSense unit is the one thing that does want centring. */
.niblo-ad-unit { display: block; margin: auto; width: 100%; }

.niblo-ad-sound {
    background: rgba(0, 0, 0, .6);
    border-radius: 999px;
    bottom: 50%;
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    left: 50%;
    padding: 6px 14px;
    position: absolute;
    transform: translateX(-50%);
    z-index: 5;
}

.niblo-ad .niblo-slide-foot { z-index: 6; }

/*
 * A creative is a full-bleed image with no idea what is written over it, so the
 * bottom of an ad slide gets a heavier scrim than a rating item needs.
 */
.niblo-ad .niblo-slide-scrim {
    background: linear-gradient(to top, rgba(0, 0, 0, .92) 0%, rgba(0, 0, 0, .55) 34%, rgba(0, 0, 0, 0) 62%);
}

/* ---- news ---- */

.niblo-news-title {
    font-size: clamp(1.3rem, 1.05rem + 1.4vw, 1.8rem);
    font-weight: 800;
    line-height: 1.15;
    margin: 0 0 8px;
    text-shadow: 0 1px 8px rgba(0, 0, 0, .6);
}

.niblo-news-actions {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 6px;
}

/* ---- summary ---- */

.niblo-summary { align-items: center; justify-content: center; text-align: center; }
.niblo-summary-inner { padding: 0 26px; position: relative; z-index: 4; }

.niblo-summary-title {
    color: #fff;
    font-size: clamp(1.7rem, 1.2rem + 2.4vw, 2.2rem);
    font-weight: 900;
    margin: 0 0 20px;
}

.niblo-bar-split {
    border: 1px solid var(--niblo-edge);
    border-radius: 10px;
    display: flex;
    height: 14px;
    margin: 0 auto 10px;
    max-width: 280px;
    overflow: hidden;
}

.niblo-bar-hot { background: var(--niblo-hot); }
.niblo-bar-not { background: var(--niblo-cold); }

.niblo-bar-labels {
    color: var(--niblo-soft);
    display: flex;
    font-size: 12.5px;
    font-weight: 700;
    justify-content: space-between;
    margin: 0 auto 26px;
    max-width: 280px;
}

.niblo-bar-label { align-items: center; display: inline-flex; gap: 4px; }

.niblo-emoji::before {
    content: var(--niblo-emoji, "");
    font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
}

/* ---- desktop: a windowed card on the ambient backdrop ---- */

.niblo-imm-nav { display: none; flex-direction: column; gap: 14px; }

.niblo-imm-arrow {
    background: rgba(0, 0, 0, .5);
    border: 1px solid var(--niblo-edge);
    border-radius: 50%;
    cursor: pointer;
    height: 46px;
    position: relative;
    transition: background 200ms ease, transform 150ms ease;
    width: 46px;
}

.niblo-imm-arrow:hover { background: var(--niblo-accent); }
.niblo-imm-arrow:active { transform: scale(.92); }

.niblo-imm-arrow::before {
    border-left: 2px solid #fff;
    border-top: 2px solid #fff;
    content: "";
    height: 10px;
    left: 50%;
    position: absolute;
    top: 50%;
    width: 10px;
}

.niblo-imm-prev::before { transform: translate(-50%, -30%) rotate(45deg); }
.niblo-imm-next::before { transform: translate(-50%, -70%) rotate(-135deg); }

@media (min-width: 701px) {
    .niblo-imm-ambient { display: block; }
    .niblo-imm-nav { display: flex; }

    .niblo-imm-shell {
        border-radius: 18px;
        box-shadow: 0 30px 80px rgba(0, 0, 0, .6), 0 0 0 1px rgba(255, 255, 255, .07);
        height: min(86vh, 860px);
        height: min(86dvh, 860px);
    }

    .niblo-imm-frame { padding-top: 60px; }
    .niblo-imm .niblo-vote { height: 68px; width: 68px; }
    .niblo-vote-emoji { font-size: 32px; }

    /*
     * Inside the shell, as on mobile. Hanging them over the edge only worked in
     * theory: the slide clips its overflow for the rounded corners, so half of
     * each button was cut away.
     */
    .niblo-vote-hot { left: 18px; }
    .niblo-vote-not { right: 18px; }
}

@media (prefers-reduced-motion: reduce) {
    .niblo-slide-bg,
    .niblo-cover-bg { animation: none; }
    .niblo-feed { scroll-behavior: auto; }
    .niblo-imm-shell.is-shaking { animation: none; }
    .niblo-storm-mark { animation-duration: 1200ms; }
}

/* ==========================================================================
   The quiz ad break

   A full slide is the right shape inside the immersive feed; inside a post it
   is not. The break is a card in the flow of the quiz with one clear way on,
   so a reader is never stranded on an advert.
   ========================================================================== */

.niblo-adbreak {
    border: 1px solid var(--niblo-line, #e5e5e7);
    border-radius: var(--niblo-radius);
    padding: 18px;
    text-align: center;
}

.niblo-adbreak .niblo-ad-flag {
    display: inline-block;
    margin-bottom: 12px;
    position: static;
}

.niblo-adbreak-media {
    align-items: center;
    display: flex;
    justify-content: center;
    position: relative;
}

/* Bounded: an ad may not push the quiz off the screen. */
.niblo-adbreak-media .niblo-ad-media {
    border-radius: calc(var(--niblo-radius) - 2px);
    display: block;
    height: auto;
    inset: auto;
    max-height: 320px;
    max-width: 100%;
    object-fit: contain;
    position: static;
    width: auto;
}

.niblo-adbreak-media .niblo-ad-unit { display: block; width: 100%; }

/*
 * A quiz break is in normal flow, so the frame must be too.
 *
 * The frame is absolute by design: in the rating feed it holds the ad between
 * the brand bar and the foot of a fixed-height slide, so a tall creative cannot
 * stretch it. A quiz break has no such height to be measured against - its
 * parent is sized by its children - so an absolutely positioned frame took
 * itself out of flow, the parent collapsed to nothing, and the unit rendered
 * into a box with no height. Which is exactly "the ads do not show".
 *
 * The picture case was already corrected this way; the AdSense case was not.
 */
.niblo-adbreak-media .niblo-ad-frame {
    display: block;
    inset: auto;
    overflow: visible;
    position: static;
    width: 100%;
    z-index: auto;
}

/* It still needs a box before the fill arrives, or Google measures nothing. */
.niblo-adbreak-media .niblo-ad-frame .niblo-ad-unit {
    max-height: none;
    min-height: 250px;
}

.niblo-adbreak-title {
    font-size: 1.15rem;
    font-weight: 700;
    margin: 14px 0 0;
}

.niblo-adbreak-desc { margin: 6px 0 0; opacity: .8; }

.niblo-adbreak-actions {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
    margin-top: 16px;
}

/* The ghost button is styled for the dark overlay; in the post it follows the
   page instead. */
.niblo .niblo-adbreak-skip {
    background: transparent;
    border: 1px solid currentColor;
    border-radius: 999px;
    color: inherit;
    cursor: pointer;
    font: inherit;
    font-size: .9rem;
    font-weight: 600;
    opacity: .75;
    padding: 10px 22px;
}

.niblo .niblo-adbreak-skip:hover { opacity: 1; }

/* ==========================================================================
   Countdown for surfaces that move on by themselves

   An ad or a post break that vanishes without warning feels like a glitch. The
   bar is the warning: it says "this is going, here is how long".
   ========================================================================== */

.niblo-timer {
    background: rgba(255, 255, 255, .22);
    height: 3px;
    left: 0;
    position: absolute;
    right: 0;
    top: 0;
    z-index: 8;
}

.niblo-timer-fill {
    animation-fill-mode: forwards;
    animation-name: niblo-timer;
    animation-play-state: paused;
    animation-timing-function: linear;
    background: var(--niblo-accent, #1a73e8);
    display: block;
    height: 100%;
    transform-origin: left center;
    width: 100%;
}

.niblo-timer.is-running .niblo-timer-fill { animation-play-state: running; }

@keyframes niblo-timer {
    from { transform: scaleX(1); }
    to   { transform: scaleX(0); }
}

/* In the post the break is a card, so the bar rides its top edge. */
.niblo-adbreak {
    overflow: hidden;
    position: relative;
}

.niblo-adbreak .niblo-timer { background: rgba(0, 0, 0, .12); }

/*
 * An AdSense unit is an empty box until Google fills it. Without a floor it
 * collapses to nothing and there is no slot left to fill.
 */
.niblo-ad-unit { min-height: 250px; }

/*
 * The creative is kept clear of the brand bar at the top of the shell, and
 * clipped to the slide. Google sizes the unit and the iframe inside it from its
 * own inventory, with no knowledge of the box it landed in, so a tall creative
 * would otherwise run over the logo and into the next slide.
 */
/*
 * The frame holds the ad out of flow, between the brand bar and the bottom of
 * the slide. Nothing inside it can change the slide's height.
 */
.niblo-ad-frame {
    align-items: center;
    bottom: 0;
    display: flex;
    justify-content: center;
    left: 0;
    overflow: hidden;
    position: absolute;
    right: 0;
    top: calc(env(safe-area-inset-top, 0px) + 76px);
    z-index: 2;
}

.niblo-ad-frame .niblo-ad-unit {
    margin: 0;
    max-height: 100%;
    min-height: 250px;
    overflow: hidden;
    width: 100%;
}

.niblo-ad-unit iframe {
    display: block;
    max-height: 100%;
    max-width: 100%;
}

/* The logo has to stay readable over whatever the creative turns out to be. */
.niblo-imm-brand {
    background: linear-gradient(to bottom, rgba(0, 0, 0, .55), rgba(0, 0, 0, 0));
}

/* ==========================================================================
   Typography overrides

   Every value falls back to what the element already used, so a site that sets
   nothing looks exactly as before. The family falls back to inherit: the run
   should wear the site's font unless somebody names another.

   Set under Niblo > Settings > Customization.
   ========================================================================== */

.niblo-cover-title,
.niblo-imm .niblo-slide-title,
.niblo-imm .niblo-news-title,
.niblo .niblo-q-title,
.niblo .niblo-adbreak-title {
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-weight: var(--niblo-heading-weight, 500);
    letter-spacing: var(--niblo-heading-spacing, normal);
    text-transform: var(--niblo-heading-transform, none);
}

.niblo-cover-title { font-size: var(--niblo-heading-size, clamp(1.25rem, 1rem + 1.2vw, 1.75rem)); }
.niblo-imm .niblo-slide-title { font-size: var(--niblo-heading-size, 1.05rem); }
.niblo-imm .niblo-news-title { font-size: var(--niblo-heading-size, clamp(1.1rem, 0.95rem + 0.9vw, 1.45rem)); }
.niblo .niblo-adbreak-title { font-size: var(--niblo-heading-size, 1.15rem); }

.niblo-eyebrow,
.niblo-imm .niblo-slide-index,
.niblo-ad-flag,
.niblo .niblo-adbreak .niblo-ad-flag {
    font-family: var(--niblo-eyebrow-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-eyebrow-size, 11px);
    font-weight: var(--niblo-eyebrow-weight, 800);
    letter-spacing: var(--niblo-eyebrow-spacing, .2em);
    text-transform: var(--niblo-eyebrow-transform, uppercase);
}

.niblo-imm .niblo-slide-caption,
.niblo-cover-count,
.niblo .niblo-adbreak-desc {
    font-family: var(--niblo-excerpt-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-excerpt-size, 1rem);
    font-weight: var(--niblo-excerpt-weight, 400);
    letter-spacing: var(--niblo-excerpt-spacing, normal);
    text-transform: var(--niblo-excerpt-transform, none);
}

.niblo .niblo-cta,
.niblo-imm .niblo-cta {
    font-family: var(--niblo-cta-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-cta-size, .95rem);
    font-weight: var(--niblo-cta-weight, 700);
    letter-spacing: var(--niblo-cta-spacing, normal);
    text-transform: var(--niblo-cta-transform, none);
}

.niblo .niblo-cta-sm,
.niblo-imm .niblo-cta-sm { font-size: var(--niblo-cta-size, .85rem); }

.niblo-imm .niblo-ghost,
.niblo .niblo-adbreak-skip {
    font-family: var(--niblo-ghost-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-ghost-size, .85rem);
    font-weight: var(--niblo-ghost-weight, 600);
    letter-spacing: var(--niblo-ghost-spacing, normal);
    text-transform: var(--niblo-ghost-transform, none);
}

/* ---- poll ----------------------------------------------------------------
 *
 * A stack of self-contained cards. Voting in one reveals that card and leaves
 * the others alone, so a post can carry ten polls and each behaves as its own.
 *
 * Every result is drawn inside the option row rather than added beneath it: the
 * bar is a layer behind the label and the percentage occupies a slot that is
 * reserved from the start. Revealing a poll therefore changes no height, and a
 * reader halfway down a page of them does not have the page move under them.
 */

.niblo-poll {
    display: grid;
    gap: 2.25rem;
}

.niblo-poll-q + .niblo-poll-q {
    border-top: 1px solid var(--niblo-line);
    padding-top: 2.25rem;
}

.niblo-poll-count {
    color: var(--niblo-muted);
    font-family: var(--niblo-eyebrow-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-eyebrow-size, 0.8rem);
    font-weight: var(--niblo-eyebrow-weight, 700);
    letter-spacing: var(--niblo-eyebrow-spacing, 0.08em);
    margin: 0 0 0.5rem;
    text-transform: uppercase;
}

.niblo-poll-title {
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-heading-size, 1.45rem);
    font-weight: var(--niblo-heading-weight, 500);
    letter-spacing: var(--niblo-heading-spacing, -0.01em);
    line-height: 1.25;
    margin: 0 0 0.5rem;
}

.niblo-poll-caption {
    color: var(--niblo-muted);
    margin: 0 0 1rem;
}

.niblo-poll-media {
    border-radius: var(--niblo-radius);
    margin: 0 0 1.25rem;
    overflow: hidden;
}

.niblo-poll-media img {
    display: block;
    height: auto;
    width: 100%;
}

.niblo .niblo-poll-options {
    display: grid;
    gap: var(--niblo-gap);
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

.niblo .niblo-poll-options-media {
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}

.niblo .niblo-poll-opt {
    background: none;
    border: 0;
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

.niblo .niblo-poll-opt::before,
.niblo .niblo-poll-opt::marker {
    content: none;
}

.niblo .niblo-poll-btn {
    align-items: center;
    background: var(--niblo-paper);
    border: var(--niblo-border) solid var(--niblo-line);
    border-radius: var(--niblo-radius);
    box-shadow: var(--niblo-shadow) var(--niblo-shadow) 0 var(--niblo-line);
    color: inherit;
    cursor: pointer;
    display: flex;
    font: inherit;
    gap: 0.75rem;
    letter-spacing: normal;
    line-height: 1.4;
    margin: 0;
    min-height: 58px;
    overflow: hidden;
    padding: 0;
    position: relative;
    text-align: left;
    text-transform: none;
    transition: border-color 140ms ease, background-color 140ms ease,
        box-shadow 140ms ease, transform 140ms ease;
    width: 100%;
}

@media (hover: hover) {
    .niblo .niblo-poll-btn:hover:not(:disabled) {
        background: var(--niblo-accent);
        border-color: var(--niblo-line);
        box-shadow: calc(var(--niblo-shadow) + 2px) calc(var(--niblo-shadow) + 2px) 0 var(--niblo-line);
        color: #fffdf8;
        transform: translateY(-2px);
    }
}

.niblo .niblo-poll-btn:active:not(:disabled) {
    box-shadow: calc(var(--niblo-shadow) - 2px) calc(var(--niblo-shadow) - 2px) 0 var(--niblo-line);
    transform: translateY(1px);
}

/* The pick lands the same way an answer does. */
.niblo .niblo-poll-btn.is-chosen {
    animation: niblo-pop 240ms cubic-bezier(.34, 1.4, .64, 1);
}

.niblo .niblo-poll-btn:focus-visible {
    outline: 3px solid var(--niblo-accent);
    outline-offset: 2px;
}

/*
 * A revealed option is no longer a control, but disabled buttons are dimmed by
 * default and this one is now the result the reader came for.
 */
.niblo .niblo-poll-btn:disabled {
    cursor: default;
    opacity: 1;
}

/*
 * The bar. Width, not transform: it starts at zero and there is nothing else
 * moving in the card, so the simpler property is the honest one here.
 */
.niblo-poll-fill {
    background: color-mix(in srgb, var(--niblo-accent) 14%, transparent);
    bottom: 0;
    left: 0;
    position: absolute;
    top: 0;
    transition: width 620ms cubic-bezier(0.22, 1, 0.36, 1);
    width: 0;
}

.niblo-poll-btn.is-leader .niblo-poll-fill {
    background: color-mix(in srgb, var(--niblo-accent) 24%, transparent);
}

.niblo-poll-btn.is-chosen {
    border-color: var(--niblo-accent);
}

.niblo-poll-body {
    align-items: center;
    display: flex;
    gap: 0.75rem;
    justify-content: space-between;
    padding: 0.85rem 1rem;
    position: relative;
    width: 100%;
    z-index: 1;
}

.niblo-poll-text {
    flex: 1 1 auto;
    min-width: 0;
}

/*
 * The reader's own pick is marked, not just tinted. Colour alone would leave
 * the one fact they most want back out of reach of anyone who cannot see it.
 */
.niblo-poll-btn.is-chosen .niblo-poll-text::after {
    color: var(--niblo-accent);
    content: ' \2713';
    font-weight: 700;
}

.niblo-poll-pct {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    /*
     * Reserved before there is anything to put in it. Without the width the
     * label shifts left as the number arrives, on every row at once.
     */
    min-width: 3ch;
    opacity: 0;
    text-align: right;
    transition: opacity 240ms ease 260ms;
}

.niblo-poll-q.is-voted .niblo-poll-pct {
    opacity: 1;
}

.niblo-poll-img {
    display: block;
    height: auto;
    width: 100%;
}

.niblo .niblo-poll-options-media .niblo-poll-btn {
    display: block;
    padding: 0;
}

.niblo .niblo-poll-options-media .niblo-poll-body {
    padding: 0.7rem 0.85rem;
}

/*
 * The line is empty until a vote is cast, so it holds its own height in advance
 * - and that reservation has to be exactly one line box. At 1.3em it was 2.9px
 * short of the 1.5 line-height it inherits, and every poll below the one being
 * voted in slid down by that much at the moment of the reveal.
 */
.niblo-poll-total {
    color: var(--niblo-muted);
    font-size: 0.9rem;
    line-height: 1.5;
    margin: 0.85rem 0 0;
    min-height: 1.5em;
}

/* ---- versus --------------------------------------------------------------
 *
 * Two sides and a badge between them. The split is reported by a fill that
 * grows up from the foot of each side, which reads as the two of them filling
 * against each other rather than as two unrelated bars.
 */

.niblo-vs-count {
    color: var(--niblo-muted);
    font-family: var(--niblo-eyebrow-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-eyebrow-size, 0.8rem);
    font-weight: var(--niblo-eyebrow-weight, 700);
    letter-spacing: var(--niblo-eyebrow-spacing, 0.08em);
    margin: 0 0 0.5rem;
    text-transform: uppercase;
}

.niblo-vs-title {
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-heading-size, 1.5rem);
    font-weight: var(--niblo-heading-weight, 500);
    letter-spacing: var(--niblo-heading-spacing, -0.01em);
    line-height: 1.2;
    margin: 0 0 1.25rem;
}

.niblo-vs-pair {
    align-items: stretch;
    display: grid;
    gap: 10px;
    grid-template-columns: 1fr 1fr;
    position: relative;
}

.niblo .niblo-vs-side {
    background: var(--niblo-line);
    border: var(--niblo-border) solid var(--niblo-line);
    border-radius: var(--niblo-radius);
    box-shadow: var(--niblo-shadow) var(--niblo-shadow) 0 var(--niblo-line);
    color: #fff;
    cursor: pointer;
    display: block;
    font: inherit;
    letter-spacing: normal;
    margin: 0;
    /*
     * An aspect ratio rather than a height: the pair has to hold its shape from
     * a phone to a wide desktop column, and a fixed height turns into a letterbox
     * at one end and a strip at the other.
     */
    aspect-ratio: 3 / 4;
    overflow: hidden;
    padding: 0;
    position: relative;
    text-align: left;
    text-transform: none;
    transition: border-color 160ms ease, transform 160ms ease;
    width: 100%;
}

.niblo .niblo-vs-side:hover:not(:disabled) {
    transform: translateY(-3px);
}

.niblo .niblo-vs-side:focus-visible {
    outline: 3px solid var(--niblo-accent);
    outline-offset: 3px;
}

.niblo .niblo-vs-side:disabled {
    cursor: default;
    opacity: 1;
}

.niblo-vs-media {
    background: center/cover no-repeat;
    inset: 0;
    position: absolute;
    transition: transform 400ms ease;
}

.niblo .niblo-vs-side:hover:not(:disabled) .niblo-vs-media {
    transform: scale(1.04);
}

/*
 * Enough of a floor to keep white type legible over an unknown photograph, and
 * the whole panel where there is no photograph at all.
 */
.niblo-vs-scrim {
    background: linear-gradient(to top, rgba(0, 0, 0, 0.88), rgba(0, 0, 0, 0.1) 55%, rgba(0, 0, 0, 0.25));
    inset: 0;
    position: absolute;
}

.niblo-vs-fill {
    background: color-mix(in srgb, var(--niblo-accent) 55%, transparent);
    bottom: 0;
    height: 0;
    left: 0;
    position: absolute;
    right: 0;
    transition: height 700ms cubic-bezier(0.22, 1, 0.36, 1);
}

.niblo-vs-body {
    bottom: 0;
    display: block;
    left: 0;
    padding: 0.9rem 1rem 1rem;
    position: absolute;
    right: 0;
    z-index: 2;
}

.niblo-vs-label {
    display: block;
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-size: 1.05rem;
    font-weight: 800;
    line-height: 1.2;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.55);
}

.niblo-vs-pct {
    display: block;
    font-size: 2rem;
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    line-height: 1.1;
    /*
     * Grown into rather than dropped in. The row above it is already positioned
     * from the bottom, so an animated height moves nothing but this number.
     */
    max-height: 0;
    opacity: 0;
    overflow: hidden;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.55);
    transition: max-height 320ms ease 300ms, opacity 320ms ease 300ms;
}

.niblo-vs.is-voted .niblo-vs-pct {
    max-height: 2.4em;
    opacity: 1;
}

.niblo-vs-side.is-chosen {
    animation: niblo-pop 240ms cubic-bezier(.34, 1.4, .64, 1);
    border-color: var(--niblo-accent);
}

.niblo-vs-side.is-leader .niblo-vs-fill {
    background: color-mix(in srgb, var(--niblo-accent) 78%, transparent);
}

/* The side nobody is picking steps back rather than disappearing. */
.niblo-vs.is-voted .niblo-vs-side:not(.is-chosen):not(.is-leader) {
    opacity: 0.82;
}

/*
 * The badge sits over the gap between the two sides. It is centred on the grid
 * rather than nested in either one, so it stays on the seam at every width.
 */
.niblo-vs-badge {
    align-items: center;
    background: var(--niblo-accent);
    border: 3px solid var(--niblo-bg);
    border-radius: 999px;
    color: #fff;
    display: flex;
    font-size: 0.95rem;
    font-weight: 800;
    height: 54px;
    justify-content: center;
    left: 50%;
    letter-spacing: 0.02em;
    pointer-events: none;
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 54px;
    z-index: 3;
}

.niblo-vs-caption {
    color: var(--niblo-muted);
    margin: 1rem 0 0;
}

.niblo-vs-total {
    color: var(--niblo-muted);
    font-size: 0.9rem;
    line-height: 1.5;
    margin: 1rem 0 0;
    min-height: 1.5em;
}

.niblo-vs-actions {
    margin-top: 1rem;
    text-align: center;
}

/*
 * Two portrait panels side by side stop working on a narrow phone: each is
 * roughly 150px wide and 200px tall, and the title has nowhere to go. Below
 * that they stack, and the badge moves to the seam between them.
 */
@media (max-width: 480px) {
    .niblo-vs-pair {
        grid-template-columns: 1fr;
    }

    .niblo .niblo-vs-side {
        aspect-ratio: 16 / 10;
    }
}

/* ---- versus recap ---- */

.niblo-vs-recap-title {
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-heading-size, 1.5rem);
    font-weight: var(--niblo-heading-weight, 500);
    margin: 0 0 1.5rem;
    text-align: center;
}

.niblo .niblo-vs-recap-list {
    display: grid;
    gap: 1.5rem;
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

.niblo .niblo-vs-recap-row {
    list-style: none !important;
    margin: 0 !important;
    padding: 0 !important;
}

.niblo .niblo-vs-recap-row::before,
.niblo .niblo-vs-recap-row::marker {
    content: none;
}

.niblo-vs-recap-round {
    font-weight: 700;
    margin: 0 0 0.5rem;
}

.niblo-vs-recap-bar {
    border-radius: 999px;
    display: flex;
    font-size: 0.85rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    min-height: 34px;
    overflow: hidden;
}

.niblo-vs-recap-seg {
    align-items: center;
    color: #fff;
    display: flex;
    justify-content: center;
    /*
     * A side that took a handful of the votes is a sliver, and the number does
     * not fit in it. Hiding the overflow keeps it from spilling over its
     * neighbour and reading as that side's figure.
     */
    overflow: hidden;
    padding: 0 0.4rem;
    white-space: nowrap;
}

.niblo-vs-recap-a {
    background: var(--niblo-accent);
}

.niblo-vs-recap-b {
    background: color-mix(in srgb, var(--niblo-accent) 42%, var(--niblo-muted));
}

.niblo-vs-recap-seg.is-chosen {
    box-shadow: inset 0 0 0 3px var(--niblo-fg);
}

.niblo-vs-recap-names,
.niblo-vs-recap-total {
    color: var(--niblo-muted);
    font-size: 0.85rem;
    margin: 0.4rem 0 0;
}

/*
 * Everything above animates a width, a height or an opacity to report a result.
 * A reader who has asked for less motion still needs the result, so the values
 * are kept and only the travel is dropped.
 */
@media (prefers-reduced-motion: reduce) {
    .niblo-poll-fill,
    .niblo-vs-fill,
    .niblo-vs-pct,
    .niblo-poll-pct,
    .niblo-vs-media,
    .niblo .niblo-vs-side {
        transition-duration: 1ms !important;
    }

    .niblo .niblo-vs-side:hover:not(:disabled) {
        transform: none;
    }
}

/* ---- holding the controls against the theme -----------------------------
 *
 * Hello Elementor, the theme this plugin is built for, styles
 * `[type="button"]:hover` and `button:focus`. Those selectors are exactly as
 * specific as `.niblo .niblo-a-btn`, and the theme's stylesheet is enqueued
 * after this one - so the tie went to the theme, and every control in the
 * plugin turned the theme's accent colour the moment a reader hovered or
 * tapped it. A revealed answer went crimson straight over its own right-or-
 * wrong colour, and a voted poll row lost its bar behind a flat slab.
 *
 * Restating each background on the interactive states outranks that without
 * reaching for !important. The answer states are excluded rather than
 * overridden: correct, wrong and chosen own their colour, and hovering a
 * revealed answer must not take it away.
 *
 * This is the reason the file opens by claiming to be theme-proof. It was not.
 */

/*
 * The theme sets a text colour on those states as well as a background, so both
 * have to be restated. Fixing only the background left white-on-lavender text
 * across a voted poll row and every hovered answer - legible in the screenshot
 * only if you were looking for it, and invisible to any assertion about layout.
 */
.niblo .niblo-a-btn:hover:not(.is-correct):not(.is-wrong):not(.is-chosen),
.niblo .niblo-a-btn:focus:not(.is-correct):not(.is-wrong):not(.is-chosen),
.niblo .niblo-a-btn:active:not(.is-correct):not(.is-wrong):not(.is-chosen),
.niblo .niblo-a-btn:disabled:not(.is-correct):not(.is-wrong):not(.is-chosen),
.niblo .niblo-poll-btn:hover,
.niblo .niblo-poll-btn:focus,
.niblo .niblo-poll-btn:active,
.niblo .niblo-poll-btn:disabled,
.niblo .niblo-btn:hover:not(.niblo-btn-primary),
.niblo .niblo-btn:focus:not(.niblo-btn-primary),
.niblo .niblo-btn:active:not(.niblo-btn-primary) {
    background-color: var(--niblo-paper);
    color: var(--niblo-fg);
}

/*
 * And the hover fill on top of it.
 *
 * The block above exists to beat a theme's own :hover, so it has to be the
 * thing that states what hovering an answer looks like - restating the resting
 * colour there is what left the fill unreachable.
 */
@media (hover: hover) {
    .niblo .niblo-a-btn:hover:not(.is-correct):not(.is-wrong):not(.is-chosen) {
        background-color: var(--niblo-accent);
        color: #fffdf8;
    }
}

/* The panel colour is the floor a side with no picture rests on. */
/* A side's type is always over a picture or a scrim, so it stays white. */
.niblo .niblo-vs-side:hover,
.niblo .niblo-vs-side:focus,
.niblo .niblo-vs-side:active,
.niblo .niblo-vs-side:disabled {
    background-color: var(--niblo-line);
    color: #fff;
}

.niblo .niblo-btn-primary:hover,
.niblo .niblo-btn-primary:focus,
.niblo .niblo-btn-primary:active,
.niblo .niblo-next:hover,
.niblo .niblo-next:focus,
.niblo .niblo-next:active,
.niblo .niblo-again:hover,
.niblo .niblo-again:focus,
.niblo .niblo-again:active,
.niblo .niblo-cta:hover,
.niblo .niblo-cta:focus,
.niblo .niblo-cta:active,
.niblo-imm .niblo-cta:hover,
.niblo-imm .niblo-cta:focus,
.niblo-imm .niblo-cta:active {
    background-color: var(--niblo-accent);
    color: #fff;
}

/*
 * The answer states keep their own ink, which the exclusions above deliberately
 * leave alone - but the theme's rule still reaches them, so they are restated
 * at a specificity that outranks it.
 */
.niblo .niblo-a-btn.is-correct:hover,
.niblo .niblo-a-btn.is-correct:focus,
.niblo .niblo-a-btn.is-correct:disabled {
    background-color: var(--niblo-correct-fill);
    color: var(--niblo-correct-ink);
}

.niblo .niblo-a-btn.is-wrong:hover,
.niblo .niblo-a-btn.is-wrong:focus,
.niblo .niblo-a-btn.is-wrong:disabled {
    background-color: var(--niblo-wrong-fill);
    color: var(--niblo-wrong-ink);
}

.niblo .niblo-a-btn.is-chosen:hover,
.niblo .niblo-a-btn.is-chosen:focus,
.niblo .niblo-a-btn.is-chosen:disabled {
    background-color: var(--niblo-accent);
    color: #fffdf8;
}

/* ---- carrying on into the next run --------------------------------------
 *
 * There is no cover slide between two runs: the summary names what is coming,
 * shows a thumbnail of it, and is itself the control that goes there. A second
 * full slide repeating that title was one more swipe between the reader and the
 * thing they had already agreed to.
 */

.niblo-imm .niblo-cta:disabled {
    cursor: default;
    opacity: 0.55;
}

.niblo-end .niblo-summary-inner {
    text-align: center;
}

/* ---- a way past an ad ---- */

/*
 * The countdown moves the feed on by itself, but only where a duration is set.
 * With none, an ad slide was a wall the reader had to scroll around without
 * being told they could.
 */
.niblo-imm .niblo-ad-skip,
.niblo .niblo-ad-skip {
    align-items: center;
    -webkit-appearance: none;
    appearance: none;
    backdrop-filter: blur(8px);
    background: var(--niblo-panel, rgba(20, 20, 22, .62));
    border: 1px solid rgba(255, 255, 255, .22);
    border-radius: 999px;
    color: rgba(255, 255, 255, .92);
    cursor: pointer;
    display: inline-flex;
    font: inherit;
    font-size: .78rem;
    font-weight: 500;
    gap: 6px;
    letter-spacing: .01em;
    padding: 8px 14px 8px 16px;
    position: absolute;
    right: 14px;
    top: 68px;
    transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease;
    z-index: 6;
}

/* A chevron drawn in CSS: an arrow character would be rewritten to an image by
 * the same emoji filter the reactions have to dodge. */
.niblo-imm .niblo-ad-skip::after,
.niblo .niblo-ad-skip::after {
    border-right: 1.5px solid currentColor;
    border-top: 1.5px solid currentColor;
    content: "";
    height: 6px;
    transform: rotate(45deg);
    width: 6px;
}

.niblo-imm .niblo-ad-skip:hover,
.niblo .niblo-ad-skip:hover {
    background: var(--niblo-panel-hi, rgba(20, 20, 22, .82));
    border-color: rgba(255, 255, 255, .4);
    color: #fff;
}

/* ---- what is coming, on the summary -------------------------------------
 *
 * Every selector here is scoped under .niblo-imm, and that is the whole point.
 *
 * A bare class is one point of specificity. Themes built on Elementor style
 * their buttons with a compound selector - a class and an element - which is
 * worth more, so an unscoped rule quietly lost: the card took the theme's
 * button colour, its centred text and its full-width block layout, which is
 * why it arrived as a pink band with the headline running off both edges.
 *
 * The takeover is appended to the body, so nothing else in the plugin's own
 * sheet is an ancestor of it. .niblo-imm is.
 */

/*
 * Deliberately no blanket `.niblo-imm button` reset.
 *
 * It would be one class and one element, which outranks the single-class rules
 * the close button, the arrows and the skip control are written with - so the
 * reset would have stripped the overlay's own chrome while fixing the theme's.
 * Each control is raised to two classes instead.
 */

/*
 * The onward card: a thumbnail and a title, laid out like the desktop cover -
 * picture on one side, words on the other.
 */
.niblo-imm .niblo-summary-next {
    align-items: center;
    position: relative;
    backdrop-filter: var(--niblo-imm-blur, none);
    background: var(--niblo-imm-fill, color-mix(in srgb, var(--niblo-ink, #fff) 10%, transparent));
    border: var(--niblo-border, 1px) solid var(--niblo-imm-line, rgba(255, 255, 255, .18));
    border-radius: var(--niblo-radius, 12px);
    box-shadow: var(--niblo-imm-lift, none);
    color: var(--niblo-imm-text, #fff);
    cursor: pointer;
    display: flex;
    gap: 12px;
    margin: 20px 0 0;
    max-width: 100%;
    overflow: hidden;
    padding: 10px;
    text-align: left;
    transition: background-color 160ms ease, border-color 160ms ease;
    width: 100%;
}

.niblo-imm .niblo-summary-next:hover {
    background: rgba(255, 255, 255, .16);
    border-color: rgba(255, 255, 255, .34);
}

.niblo-imm .niblo-summary-next-thumb {
    background: center/cover no-repeat rgba(255, 255, 255, .08);
    border-radius: 8px;
    flex: 0 0 auto;
    height: 52px;
    width: 52px;
}

.niblo-imm .niblo-summary-next-text {
    flex: 1 1 auto;
    /*
     * A flex item will not go below its content's width on min-width alone in
     * every engine; a zero basis width with flex-grow is what actually lets the
     * headline wrap rather than run out under the thumbnail.
     */
    min-width: 0;
    text-align: left;
    width: 0;
}

.niblo-imm .niblo-summary-next .niblo-eyebrow {
    display: block;
    font-size: 10px;
    margin: 0 0 3px;
    text-align: left;
}

/* The whole headline, wrapped. */
.niblo-imm .niblo-summary-next-title {
    color: #fff;
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-size: .9rem;
    font-weight: var(--niblo-heading-weight, 500);
    line-height: 1.3;
    margin: 0;
    min-width: 0;
    overflow-wrap: anywhere;
    text-align: left;
    white-space: normal;
}

/* The countdown, traced around the card it belongs to. */
.niblo-imm .niblo-ring {
    height: 100%;
    inset: 0;
    overflow: visible;
    pointer-events: none;
    position: absolute;
    width: 100%;
}

.niblo-imm .niblo-ring rect {
    fill: none;
    opacity: .85;
    stroke: #fff;
    stroke-dasharray: 100;
    stroke-dashoffset: 100;
    stroke-width: 2;
}

.niblo-imm .niblo-ring.is-running rect {
    animation: niblo-ring-run linear forwards;
}

@keyframes niblo-ring-run {
    to { stroke-dashoffset: 0; }
}

/* The secondary action on a summary, where the primary is to carry on. */
.niblo-imm .niblo-cta-ghost {
    background: transparent;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .5);
    color: #fff;
}

.niblo-imm .niblo-cta-ghost:hover {
    background: rgba(255, 255, 255, .12);
}

/* ---- the opening card on a wide screen ----------------------------------
 *
 * The cover is a 4:5 portrait sized from its own max-height, which is right on
 * a phone and wrong in a desktop column: it came out a narrow card marooned in
 * the middle of the measure. From here it is a banner running the full width,
 * with the copy held to a readable line rather than stretched across all of it.
 */

@media (min-width: 900px) {
    .niblo .niblo-cover-card {
        aspect-ratio: 16 / 7;
        max-height: none;
        min-height: 400px;
        width: 100%;
    }

    .niblo .niblo-cover-inner {
        max-width: 640px;
        padding: 44px 48px;
    }

    /*
     * Wide, the darkening has to come from the side the words are on. A scrim
     * that only rises from the foot leaves the headline sitting on open picture.
     */
    .niblo .niblo-cover-scrim {
        background:
            linear-gradient(to right, rgba(0, 0, 0, .9) 0%, rgba(0, 0, 0, .6) 45%, rgba(0, 0, 0, .15) 78%),
            linear-gradient(to top, rgba(0, 0, 0, .72), rgba(0, 0, 0, 0) 60%);
    }

    /*
     * The takeover keeps its portrait shape at every width: inside it the frame
     * is a phone-shaped column, not a page column.
     */
    .niblo-imm .niblo-cover-card {
        aspect-ratio: 4 / 5;
        min-height: 0;
    }

    /* ---- the quiz start screen at the same width ---- */

    /*
     * Side by side rather than a narrow centred stack. The picture earns its
     * place at this width, and the text stops being a column of centred lines
     * floating in the middle of the page.
     */
    .niblo .niblo-start {
        align-items: center;
        display: grid;
        gap: 36px;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        text-align: left;
    }

    .niblo .niblo-start-media {
        margin: 0;
    }

    .niblo .niblo-start-media img {
        border-radius: var(--niblo-radius);
        display: block;
        height: 100%;
        max-height: 420px;
        object-fit: cover;
        width: 100%;
    }

    /* With no picture there is nothing to sit beside, so it centres again. */
    .niblo .niblo-start:not(:has(.niblo-start-media)) {
        display: block;
        text-align: center;
    }
}

/* ---- the small unit on the results card ---------------------------------
 *
 * Same width and shape as the card above it, so the two read as one block. The
 * summary is where a reader has just finished something and is deciding whether
 * to carry on, which is a better place for inventory than a slide of its own
 * interrupting the run.
 */

.niblo-imm .niblo-summary-ad {
    background: rgba(255, 255, 255, .06);
    border: 1px solid rgba(255, 255, 255, .14);
    border-radius: 12px;
    box-sizing: border-box;
    margin: 10px 0 0;
    overflow: hidden;
    padding: 10px;
    position: relative;
    width: 100%;
}

.niblo-imm .niblo-summary-ad-frame {
    display: block;
    min-height: 100px;
    position: relative;
    width: 100%;
}

.niblo-imm .niblo-summary-ad .niblo-ad-unit {
    display: block;
    min-height: 100px;
    width: 100%;
}

/*
 * The full-slide ad frame is absolutely positioned so a tall creative cannot
 * stretch a fixed-height slide. Here the card is sized by its contents, so an
 * out-of-flow frame would collapse it to nothing - the same trap the quiz ad
 * break fell into.
 */
.niblo-imm .niblo-summary-ad .niblo-ad-frame {
    display: block;
    inset: auto;
    position: static;
    width: 100%;
}

.niblo-imm .niblo-summary-ad .niblo-ad-media {
    display: block;
    height: auto;
    inset: auto;
    max-height: 160px;
    object-fit: contain;
    position: static;
    width: 100%;
}

.niblo-imm .niblo-summary-ad .niblo-ad-flag {
    display: block;
    margin: 0 0 6px;
    position: static;
}

/* On the card it sits in flow, not pinned to the corner of the viewport. */
.niblo-imm .niblo-ad-skip-inline {
    display: inline-flex;
    margin: 8px 0 0;
    position: static;
    right: auto;
    top: auto;
}

/* ---- a quiz playing as a story --------------------------------------------
 *
 * The same full-screen run the rating feed uses, with questions in place of
 * pictures to react to. The layout of the answers follows what they are: text
 * stacks, four pictures square up, more than four go wide with the label on the
 * picture so the question stays on screen.
 *
 * Structure for all of this also lives in the runtime's injected block, because
 * none of these selectors appear in the HTML the server sends and an optimiser
 * that decides what is "used" by reading that markup drops them.
 */

.niblo-imm .niblo-qslide {
    justify-content: flex-end;
}

.niblo-imm .niblo-qslide-media {
    inset: 0;
    overflow: hidden;
    position: absolute;
}

/*
 * Half height: the picture takes the top of the screen and the answers sit on
 * solid ground beneath it.
 *
 * The slide's own scrim is a bottom-up gradient built for a full-bleed picture.
 * Over a half-height one it darkens ground that is already solid and leaves the
 * photograph's lower edge as a straight line, so here the picture carries a
 * mask instead and the scrim is switched off.
 */
.niblo-imm .niblo-qslide.is-half {
    background: #0f1012;
}

.niblo-imm .niblo-qslide.is-half .niblo-qslide-media {
    bottom: auto;
    height: 50%;
}

.niblo-imm .niblo-qslide.is-half .niblo-slide-scrim {
    display: none;
}

.niblo-imm .niblo-qslide.is-half .niblo-qslide-media img {
    -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 74%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 0, #000 74%, transparent 100%);
}

.niblo-imm .niblo-qslide.is-half .niblo-qslide-foot {
    padding-top: 12px;
}

.niblo-imm .niblo-qslide-media img {
    display: block;
    height: 100%;
    object-fit: cover;
    width: 100%;
}

/*
 * A question with no picture of its own shows the quiz's featured image,
 * exactly as it would show its own: full-bleed, sharp, under the same scrim.
 *
 * It was blurred and dimmed for a while, on the reasoning that a borrowed
 * picture should sit further back. In practice that put a smear behind most of
 * the run and looked like a fault rather than a decision.
 */

/* ---- how far through ---- */

.niblo-imm .niblo-qrail {
    display: flex;
    gap: 4px;
    left: 16px;
    position: absolute;
    right: 16px;
    top: 56px;
    z-index: 5;
}

.niblo-imm .niblo-qrail-seg {
    background: var(--niblo-hairline, rgba(255, 255, 255, .28));
    border-radius: 2px;
    flex: 1 1 0;
    height: 2px;
}

.niblo-imm .niblo-qrail-seg.is-done {
    background: var(--niblo-ink, #fff);
}

.niblo-imm .niblo-qrail-seg {
    background: var(--niblo-hairline, rgba(255, 255, 255, .28));
    border-radius: 2px;
    flex: 1 1 0;
    height: 2px;
}

.niblo-imm .niblo-qrail-seg.is-done {
    background: var(--niblo-ink, #fff);
}

/* ---- the countdown ---------------------------------------------------------
 *
 * A ring that empties with the seconds left inside it, rather than a hairline
 * draining across the top of the screen. On a question, how long is left is the
 * one thing worth knowing, and a bar says only that something is happening.
 */

/* ---- the question ---- */

/*
 * The foot scrolls when it has to. A long question with six answers is taller
 * than the room under the picture, and clipping it hides the answers, which is
 * the one thing the slide exists to show.
 */
.niblo-imm .niblo-qslide-foot {
    max-height: 78%;
    overflow-y: auto;
    padding: 0 18px 26px;
    position: relative;
    -webkit-overflow-scrolling: touch;
    z-index: 4;
}

.niblo-imm .niblo-qslide.is-half .niblo-qslide-foot {
    max-height: 52%;
}

.niblo-imm .niblo-qslide-title {
    color: #fff;
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-heading-size, 1.2rem);
    font-weight: var(--niblo-heading-weight, 500);
    line-height: 1.25;
    margin: 0 0 12px;
    text-shadow: 0 1px 12px rgba(0, 0, 0, .6);
}

.niblo-imm .niblo-qanswers {
    display: grid;
    gap: 8px;
}

.niblo-imm .niblo-qanswers.is-grid,
.niblo-imm .niblo-qanswers.is-wide {
    grid-template-columns: 1fr 1fr;
}

.niblo-imm .niblo-qanswer {
    -webkit-appearance: none;
    align-items: center;
    appearance: none;
    /*
     * The same panel the page uses, unless the site asks for glass.
     *
     * These four tokens are how every control over a photograph is drawn, so
     * choosing a preset repaints all of them and a format added later needs no
     * rule of its own. See "The panel contract" at the top of this file.
     */
    backdrop-filter: var(--niblo-imm-blur, none);
    background: var(--niblo-imm-fill, #fffdf8);
    border: var(--niblo-border, 1px) solid var(--niblo-imm-line, #191515);
    border-radius: var(--niblo-radius, 12px);
    box-shadow: var(--niblo-imm-lift, none);
    box-sizing: border-box;
    color: var(--niblo-imm-text, #191515);
    cursor: pointer;
    display: flex;
    font: inherit;
    font-size: .95rem;
    gap: 10px;
    padding: 12px 14px;
    position: relative;
    text-align: left;
    transition: background-color 160ms ease, border-color 160ms ease;
    width: 100%;
}

.niblo-imm .niblo-qanswer:disabled {
    cursor: default;
}

/* A long answer wraps rather than being cut off mid-word. */
.niblo-imm .niblo-qanswer-text {
    min-width: 0;
    overflow-wrap: anywhere;
    white-space: normal;
}

/*
 * A picture answer is the picture.
 *
 * It fills its tile and the label sits on it, always - whether there are four
 * or fourteen. A caption in a band underneath wastes the height the picture
 * needs and makes the whole set taller than the screen, which is what pushed
 * the question off the top. Only the shape changes with the count: square up to
 * four, wide beyond that so more of them still fit.
 */
.niblo-imm .niblo-qanswers.is-grid .niblo-qanswer,
.niblo-imm .niblo-qanswers.is-wide .niblo-qanswer {
    display: block;
    overflow: hidden;
    padding: 0;
}

.niblo-imm .niblo-qanswers.is-grid .niblo-qanswer {
    aspect-ratio: 1 / 1;
}

.niblo-imm .niblo-qanswers.is-wide .niblo-qanswer {
    aspect-ratio: 16 / 9;
}

.niblo-imm .niblo-qanswers.is-grid .niblo-qanswer-img,
.niblo-imm .niblo-qanswers.is-wide .niblo-qanswer-img {
    background: center/cover no-repeat rgba(255, 255, 255, .06);
    inset: 0;
    position: absolute;
}

/* Enough of a floor under the label to hold it against any photograph. */
.niblo-imm .niblo-qanswers.is-grid .niblo-qanswer-text,
.niblo-imm .niblo-qanswers.is-wide .niblo-qanswer-text {
    background: linear-gradient(to top, rgba(0, 0, 0, .9), rgba(0, 0, 0, .55) 45%, rgba(0, 0, 0, 0));
    bottom: 0;
    font-size: .85rem;
    left: 0;
    line-height: 1.2;
    padding: 20px 10px 9px;
    position: absolute;
    right: 0;
    text-shadow: 0 1px 6px rgba(0, 0, 0, .8);
}

.niblo-imm .niblo-qanswer-mark {
    flex: 0 0 auto;
    height: 18px;
    margin-left: auto;
    position: relative;
    width: 18px;
}

.niblo-imm .niblo-qanswers.is-grid .niblo-qanswer-mark,
.niblo-imm .niblo-qanswers.is-wide .niblo-qanswer-mark {
    margin: 0;
    position: absolute;
    right: 8px;
    top: 8px;
}

/*
 * Right and wrong are drawn, not written: a tick or a cross in CSS rather than
 * a character, for the same reason the reactions are - WordPress rewrites emoji
 * text nodes into remote images.
 */
/*
 * The same colours the page uses, not a second pair.
 *
 * These were two hardcoded values, so changing "Correct answer" on the settings
 * screen repainted the quiz in the article and left the full-screen one green.
 * Mixed with the ground rather than used flat: the panel sits over a photograph
 * and a solid fill would lose the picture behind it.
 */
.niblo-imm .niblo-qanswer.is-correct {
    /* The colour itself, not a wash of it. A verdict is meant to land. */
    background-color: var(--niblo-correct-fill, #58c96b) !important;
    border-color: var(--niblo-correct-fill, #58c96b);
    color: var(--niblo-correct-ink, #191515);
}

.niblo-imm .niblo-qanswer.is-wrong {
    background-color: var(--niblo-wrong-fill, #f04444) !important;
    border-color: var(--niblo-wrong-fill, #f04444);
    color: var(--niblo-wrong-ink, #ffffff);
}

/*
 * The answer they picked, where there is no verdict to give.
 *
 * On a personality quiz, a poll or a trivia quiz holding its verdict back, this
 * is the only feedback there is - and it used to be a white ring and nothing
 * else, so the pick looked the same as the answers around it. The page has
 * filled it with the accent all along; this is that, on a phone.
 */
.niblo-imm .niblo-qanswer.is-chosen:not(.is-correct):not(.is-wrong) {
    background-color: var(--niblo-accent) !important;
    border-color: var(--niblo-accent);
    color: var(--niblo-accent-ink, #fff);
}

/*
 * And the same motion.
 *
 * A verdict that only changes colour reads as a repaint wherever it happens.
 * The keyframes are the page's own, so the two views answer the same way.
 */
.niblo-imm .niblo-qanswer.is-correct,
.niblo-imm .niblo-qanswer.is-chosen,
.niblo-imm .niblo-vsslide-side.is-chosen {
    animation: niblo-pop 240ms cubic-bezier(.34, 1.4, .64, 1);
}

.niblo-imm .niblo-qanswer.is-wrong {
    animation: niblo-nudge 260ms ease-in-out;
}

.niblo-imm .niblo-qanswer.is-correct .niblo-qanswer-mark,
.niblo-imm .niblo-qanswer.is-wrong .niblo-qanswer-mark {
    animation: niblo-mark 220ms 90ms cubic-bezier(.34, 1.5, .64, 1) backwards;
}

@media (prefers-reduced-motion: reduce) {
    .niblo-imm .niblo-qanswer.is-correct,
    .niblo-imm .niblo-qanswer.is-wrong,
    .niblo-imm .niblo-qanswer.is-chosen,
    .niblo-imm .niblo-vsslide-side.is-chosen,
    .niblo-imm .niblo-qanswer.is-correct .niblo-qanswer-mark,
    .niblo-imm .niblo-qanswer.is-wrong .niblo-qanswer-mark {
        animation: none;
    }
}

.niblo-imm .niblo-qanswer.is-correct .niblo-qanswer-mark::before,
.niblo-imm .niblo-qanswer.is-correct .niblo-qanswer-mark::after,
.niblo-imm .niblo-qanswer.is-wrong .niblo-qanswer-mark::before,
.niblo-imm .niblo-qanswer.is-wrong .niblo-qanswer-mark::after {
    background: #fff;
    border-radius: 2px;
    content: "";
    position: absolute;
}

.niblo-imm .niblo-qanswer.is-correct .niblo-qanswer-mark::before {
    height: 2px;
    left: 1px;
    top: 10px;
    transform: rotate(45deg);
    width: 7px;
}

.niblo-imm .niblo-qanswer.is-correct .niblo-qanswer-mark::after {
    height: 2px;
    left: 5px;
    top: 8px;
    transform: rotate(-45deg);
    width: 12px;
}

.niblo-imm .niblo-qanswer.is-wrong .niblo-qanswer-mark::before,
.niblo-imm .niblo-qanswer.is-wrong .niblo-qanswer-mark::after {
    height: 2px;
    left: 2px;
    top: 8px;
    width: 14px;
}

.niblo-imm .niblo-qanswer.is-wrong .niblo-qanswer-mark::before { transform: rotate(45deg); }
.niblo-imm .niblo-qanswer.is-wrong .niblo-qanswer-mark::after  { transform: rotate(-45deg); }

.niblo-imm .niblo-qslide.is-answered .niblo-qanswer:not(.is-chosen):not(.is-correct) {
    opacity: .55;
}

/* ---- the opening card ---- */

.niblo-imm .niblo-qintro {
    justify-content: flex-start;
}

.niblo-imm .niblo-qintro-media {
    height: 64%;
    left: 0;
    overflow: hidden;
    position: absolute;
    right: 0;
    top: 0;
}

.niblo-imm .niblo-qintro-media img {
    display: block;
    height: 100%;
    object-fit: cover;
    object-position: top;
    width: 100%;
}

/* The picture dissolves into solid ground, so a headline of any length is
 * readable rather than fighting the photograph behind it. */
/*
 * The picture dissolves into the copy rather than stopping above it.
 *
 * The fade begins well inside the photograph and reaches solid ground only
 * after the headline has started, so there is no visible edge where one ends
 * and the other begins - the image becomes the title's background.
 */
.niblo-imm .niblo-qintro-fade {
    background: linear-gradient(
        to bottom,
        rgba(15, 16, 18, 0) 0%,
        rgba(15, 16, 18, .35) 22%,
        rgba(15, 16, 18, .72) 42%,
        rgba(15, 16, 18, .93) 58%,
        #0f1012 74%,
        #0f1012 100%
    );
    bottom: 0;
    left: 0;
    position: absolute;
    right: 0;
    top: 22%;
}

.niblo-imm .niblo-qintro-inner {
    box-sizing: border-box;
    margin-top: auto;
    padding: 0 20px 30px;
    position: relative;
    width: 100%;
    z-index: 4;
}

.niblo-imm .niblo-pill {
    background: var(--niblo-accent);
    border-radius: 6px;
    color: #fff;
    display: inline-block;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .12em;
    padding: 4px 12px;
    text-transform: uppercase;
}

.niblo-imm .niblo-qintro-title {
    color: #fff;
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-heading-size, 1.7rem);
    font-weight: var(--niblo-heading-weight, 500);
    line-height: 1.1;
    margin: 12px 0 0;
}

.niblo-imm .niblo-qintro-text {
    color: rgba(255, 255, 255, .82);
    font-size: .95rem;
    line-height: 1.5;
    margin: 12px 0 0;
}

.niblo-imm .niblo-qintro-start {
    display: block;
    margin-top: 20px;
    text-align: center;
    width: 100%;
}

/* The masthead: logo left, the format named beside it. */
.niblo-imm .niblo-imm-brand.is-labelled {
    gap: 10px;
    justify-content: flex-start;
    padding: 0 16px;
}

/* ---- the closing card ---- */

/*
 * The picture is the point of a result, so it takes the top of the screen and
 * the copy sits beneath. Both crammed into a centred stack left a postage stamp
 * above four lines of text.
 */
/*
 * The picture and the copy are stacked, not layered.
 *
 * Positioned absolutely the picture took no room, so the copy had to be pushed
 * down by a padding of the same height - and being bottom-aligned it then sank
 * to the foot of the screen, leaving a band of black between the two. In normal
 * flow the copy starts where the picture stops.
 */
.niblo-imm .niblo-qresult-media {
    /*
     * The picture fills the slide and the words sit on it.
     *
     * It used to take a share of a column, which meant a hard edge where it
     * stopped and a band of flat colour under it. Behind everything, with a
     * gradient down it, there is no edge to see.
     */
    inset: 0;
    overflow: hidden;
    position: absolute;
    z-index: 0;
}

.niblo-imm .niblo-qresult-media::after {
    background: linear-gradient(
        to bottom,
        rgba(0, 0, 0, 0) 24%,
        rgba(0, 0, 0, .45) 46%,
        var(--niblo-surface,#191515) 78%
    );
    content: '';
    inset: 0;
    position: absolute;
}

.niblo-imm .niblo-qresult-media img {
    display: block;
    height: 100%;
    object-fit: cover;
    width: 100%;
}

/* A video cannot be a backdrop: it stays in the column, above the words. */
.niblo-imm .niblo-qresult-media.is-video {
    align-items: center;
    background: #000;
    display: flex;
    flex: 0 0 auto;
    inset: auto;
    position: relative;
    width: 100%;
}

.niblo-imm .niblo-qresult-media.is-video::after { content: none; }

.niblo-imm .niblo-qresult-media.is-video iframe {
    aspect-ratio: 16 / 9;
    border: 0;
    display: block;
    width: 100%;
}

/* The copy sits at the foot of the picture rather than under it. */
.niblo-imm .niblo-summary.has-art {
    justify-content: flex-end;
}

/*
 * A column, so that one part of it can be the part that gives way.
 *
 * Everything used to scroll together, which meant a long description pushed
 * what comes next off the bottom of the screen - the one thing on the card
 * that has to stay visible.
 */
.niblo-imm .niblo-summary.has-art .niblo-summary-inner {
    display: flex;
    flex: 0 1 auto;
    flex-direction: column;
    margin-top: 0;
    max-height: 100%;
    /* Without this the column refuses to shrink and the copy is clipped. */
    min-height: 0;
    overflow: visible;
    padding-bottom: 22px;
    padding-top: 16px;
}

/* Everything but the description holds its size. */
.niblo-imm .niblo-summary.has-art .niblo-summary-inner > * {
    flex: 0 0 auto;
}

.niblo-imm .niblo-qresult-title {
    color: #fff;
    font-family: var(--niblo-heading-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-heading-size, 1.15rem);
    font-weight: var(--niblo-heading-weight, 500);
    line-height: 1.2;
    margin: 4px 0;
}

.niblo-imm .niblo-qresult-desc {
    color: rgba(255, 255, 255, .82);
    /*
     * The one thing on the card that may be any length, so it is the one that
     * shrinks and scrolls. The actions and what comes next keep their place.
     */
    flex: 0 1 auto;
    font-size: .9rem;
    line-height: 1.45;
    margin: 0 0 10px;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/*
 * One row: the lead action, then the rest as glyphs.
 *
 * Stacked full-width buttons ran the card off the bottom of the screen and
 * took Play again with them. Here the lead takes what is left and the others
 * cost about fifty pixels each.
 */
.niblo-imm .niblo-qresult-actions {
    align-items: stretch;
    display: flex;
    gap: 8px;
    margin: 14px 0 0;
}

.niblo-imm .niblo-qresult-actions > * {
    flex: 0 0 auto;
}

.niblo-imm .niblo-qresult-actions > .is-lead {
    flex: 1 1 auto;
    min-width: 0;
}

.niblo-imm .niblo-qbtn {
    -webkit-appearance: none;
    align-items: center;
    appearance: none;
    border: 1px solid transparent;
    border-radius: 999px;
    box-sizing: border-box;
    cursor: pointer;
    display: flex;
    font: inherit;
    font-size: .95rem;
    font-weight: 600;
    gap: 8px;
    justify-content: center;
    padding: 13px 16px;
    text-decoration: none;
    width: 100%;
}

.niblo-imm .niblo-qbtn-ico {
    display: inline-flex;
    flex: 0 0 auto;
}

.niblo-imm .niblo-qbtn-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * A glyph and nothing else, until the screen is wide enough for the word.
 *
 * On a phone three labelled buttons cannot share a row, and the label is the
 * part a reader can do without: the glyphs are a share arrow and a replay
 * arrow, both of which say what they are.
 */
.niblo-imm .niblo-qbtn-icon {
    padding: 13px 15px;
    width: auto;
}

.niblo-imm .niblo-qbtn-icon .niblo-qbtn-label {
    display: none;
}

@media (min-width: 620px) {
    .niblo-imm .niblo-qbtn-icon {
        padding: 13px 20px;
    }

    .niblo-imm .niblo-qbtn-icon .niblo-qbtn-label {
        display: inline;
    }
}

.niblo-imm .niblo-qbtn-primary {
    background: var(--niblo-accent);
    color: #fff;
}

.niblo-imm .niblo-qbtn-ghost {
    background: transparent;
    border-color: rgba(255, 255, 255, .45);
    color: #fff;
}

/* Where there is no system share sheet, the same single button opens a menu -
 * so the two actions stay the same size whatever the platform offers. */
.niblo-imm .niblo-qshare-wrap.is-compact .niblo-qshare-menu {
    left: auto;
    min-width: 168px;
    right: 0;
}

.niblo-imm .niblo-qshare-wrap {
    position: relative;
}

.niblo-imm .niblo-qshare-menu {
    background: #1b1c20;
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: 12px;
    bottom: calc(100% + 8px);
    display: grid;
    gap: 6px;
    left: 0;
    padding: 8px;
    position: absolute;
    right: 0;
    z-index: 8;
}

.niblo-imm .niblo-qshare-item {
    border-radius: 8px;
    color: #fff;
    display: block;
    font-size: .9rem;
    padding: 9px 12px;
    text-decoration: none;
}

.niblo-imm .niblo-qshare-item:hover {
    background: rgba(255, 255, 255, .12);
}

/* ---- a floor under the header ---------------------------------------------
 *
 * The logo and the close button sit at the top of the screen with whatever the
 * slide is showing running underneath them. Over a dark picture that reads;
 * over a bright one the logo disappears and the X looks broken. The gradient
 * sits behind both and above everything else.
 */
.niblo-imm .niblo-imm-topfade {
    background: linear-gradient(to bottom, rgba(0, 0, 0, .72), rgba(0, 0, 0, 0));
    height: 110px;
    left: 0;
    pointer-events: none;
    position: absolute;
    right: 0;
    top: 0;
    z-index: 2;
}

/*
 * Sharing the outcome as a picture.
 *
 * Under the pair rather than beside it: taking a result to a story is a
 * different kind of action from replaying or moving on, and squeezing three
 * buttons into one row makes all of them too small to read.
 */
.niblo-imm .niblo-qbtn-story {
    background: color-mix(in srgb, var(--niblo-ink, #fff) 12%, transparent);
    border-color: var(--niblo-hairline, rgba(255, 255, 255, .28));
    color: #fff;
}

.niblo-imm .niblo-qbtn-story:hover:not(:disabled) {
    background: rgba(255, 255, 255, .2);
}

.niblo-imm .niblo-qbtn-story:disabled {
    cursor: default;
    opacity: .6;
}

/*
 * A gated quiz's slides, out of the scroll until its Start button is pressed.
 *
 * Out entirely rather than merely invisible: a slide with no box has no snap
 * point, so swiping past the opening card lands on whatever follows the quiz.
 */
.niblo-imm .niblo-feed > .niblo-locked {
    display: none;
}

/* ---- the roles the settings screen names ---------------------------------
 *
 * A question, an answer and a result are the three things a reader actually
 * looks at, and until now none of them had a control of their own: they
 * inherited whatever the page happened to use.
 */

.niblo .niblo-q-title,
.niblo-imm .niblo-qslide-title {
    font-family: var(--niblo-question-family, var(--niblo-site-family, inherit));
    font-weight: var(--niblo-question-weight, inherit);
    letter-spacing: var(--niblo-question-spacing, normal);
    text-transform: var(--niblo-question-transform, none);
}

.niblo-imm .niblo-qslide-title {
    font-size: var(--niblo-question-size, 1.35rem);
}

.niblo .niblo-a-btn,
.niblo-imm .niblo-qanswer {
    font-family: var(--niblo-answer-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-answer-size, inherit);
    font-weight: var(--niblo-answer-weight, inherit);
    letter-spacing: var(--niblo-answer-spacing, normal);
    text-transform: var(--niblo-answer-transform, none);
}

.niblo .niblo-result-title,
.niblo-imm .niblo-qresult-title {
    font-family: var(--niblo-result-family, var(--niblo-site-family, inherit));
    font-weight: var(--niblo-result-weight, inherit);
    letter-spacing: var(--niblo-result-spacing, normal);
    text-transform: var(--niblo-result-transform, none);
}

.niblo-imm .niblo-qresult-title {
    font-size: var(--niblo-result-size, 1.15rem);
}

/* ---- the slow push into a photograph ------------------------------------ */

/*
 * Running from the start rather than released when the slide is judged to be
 * on screen. Waiting put the whole effect behind an IntersectionObserver: a
 * threshold not met, a slide already marked as watched, a feed rebuilt under a
 * stale observer, and the picture simply never moved. It loops and reverses,
 * so there is nothing to hold it back for.
 */
.niblo-imm .niblo-kb {
    animation: niblo-kb 9s ease-in-out infinite alternate;
    transform-origin: 50% 40%;
    will-change: transform;
}

.niblo-imm .niblo-kb-soft {
    animation: niblo-kb-soft 12s ease-in-out infinite alternate;
    transform-origin: 50% 30%;
}

/* Every other slide pulls back instead, so a run is not one long push. */
.niblo-imm .niblo-kb-out .niblo-kb {
    animation-name: niblo-kb-rev;
}

@keyframes niblo-kb {
    from { transform: scale(1.06) translate3d(0, 0, 0); }
    to   { transform: scale(1.24) translate3d(-1.5%, -2.5%, 0); }
}

@keyframes niblo-kb-rev {
    from { transform: scale(1.24) translate3d(1.5%, 2%, 0); }
    to   { transform: scale(1.06) translate3d(0, 0, 0); }
}

@keyframes niblo-kb-soft {
    from { transform: scale(1.02); }
    to   { transform: scale(1.16); }
}

/*
 * A reader who has asked their phone for less motion gets less of it, unless
 * the site has overruled that under Niblo > Settings > Gameplay.
 */
@media (prefers-reduced-motion: reduce) {
    .niblo-imm:not(.niblo-motion) .niblo-kb,
    .niblo-imm:not(.niblo-motion) .niblo-kb-soft {
        animation: none;
    }
}


/* ---- a matchup, filling the screen --------------------------------------
 *
 * Two halves rather than two columns: a phone is tall, so the sides stack and
 * each gets the whole width to be tapped. The same shape as the in-page
 * versus, turned ninety degrees to fit the screen it is on.
 */

.niblo-imm .niblo-vsslide {
    display: flex;
    flex-direction: column;
    justify-content: stretch;
    padding: 0;
}

.niblo-imm .niblo-vsslide-title {
    color: #fff;
    font-family: var(--niblo-question-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-question-size, 1.05rem);
    font-weight: 600;
    left: 0;
    margin: 0;
    padding: 68px 24px 0;
    pointer-events: none;
    position: absolute;
    right: 0;
    text-align: center;
    text-shadow: 0 2px 12px rgba(0, 0, 0, .7);
    top: 0;
    z-index: 5;
}

.niblo-imm .niblo-vsslide-side {
    -webkit-appearance: none;
    appearance: none;
    background: #15161a;
    border: 0;
    cursor: pointer;
    display: block;
    flex: 1 1 50%;
    font: inherit;
    margin: 0;
    min-height: 0;
    overflow: hidden;
    padding: 0;
    position: relative;
    width: 100%;
}

.niblo-imm .niblo-vsslide-media {
    background: center / cover no-repeat;
    inset: 0;
    position: absolute;
}

.niblo-imm .niblo-vsslide-a .niblo-vsslide-scrim {
    background: linear-gradient(to bottom, rgba(0, 0, 0, .5), rgba(0, 0, 0, .1) 55%, rgba(0, 0, 0, .6));
}

.niblo-imm .niblo-vsslide-b .niblo-vsslide-scrim {
    background: linear-gradient(to top, rgba(0, 0, 0, .5), rgba(0, 0, 0, .1) 55%, rgba(0, 0, 0, .6));
}

.niblo-imm .niblo-vsslide-scrim {
    inset: 0;
    position: absolute;
}

.niblo-imm .niblo-vsslide-body {
    align-items: center;
    display: flex;
    flex-direction: column;
    gap: 6px;
    inset: 0;
    justify-content: center;
    padding: 24px;
    position: absolute;
    z-index: 3;
}

/*
 * A chip, drawn from the same five tokens as a quiz answer, so the panel
 * treatment chosen under Design > Colours reaches a matchup too. It used to be
 * white type with a drop shadow, which is what you reach for when the words
 * have nothing behind them - and it made a matchup look like a different
 * product from the quiz beside it.
 */
.niblo-imm .niblo-vsslide-label {
    backdrop-filter: var(--niblo-imm-blur, none);
    background: var(--niblo-imm-fill, rgba(20, 20, 22, .62));
    border: var(--niblo-border, 1px) solid var(--niblo-imm-line, rgba(255, 255, 255, .3));
    border-radius: var(--niblo-radius, 12px);
    box-shadow: var(--niblo-imm-lift, none);
    color: var(--niblo-imm-text, #fff);
    padding: 10px 18px;
    font-family: var(--niblo-answer-family, var(--niblo-site-family, inherit));
    font-size: var(--niblo-answer-size, 1.35rem);
    font-weight: 700;
    line-height: 1.15;
    text-align: center;
}

/* Only once there is a split to show. */
.niblo-imm .niblo-vsslide-pct {
    color: #fff;
    font-size: 2.4rem;
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    line-height: 1;
    opacity: 0;
    text-shadow: 0 2px 14px rgba(0, 0, 0, .75);
    transform: translateY(6px);
    transition: opacity 260ms ease, transform 260ms ease;
}

.niblo-imm .niblo-vsslide.is-voted .niblo-vsslide-pct {
    opacity: 1;
    transform: none;
}

/*
 * The bar is the half itself: its share of the screen, drawn as a wash from the
 * dividing line outward, so the two sides read as one measure rather than two.
 */
.niblo-imm .niblo-vsslide.is-voted .niblo-vsslide-side::after {
    background: var(--niblo-accent);
    content: '';
    height: 4px;
    left: 0;
    opacity: .9;
    position: absolute;
    transition: width 420ms ease;
    width: var(--niblo-vs-share, 0%);
    z-index: 4;
}

.niblo-imm .niblo-vsslide.is-voted .niblo-vsslide-a::after { bottom: 0; }
.niblo-imm .niblo-vsslide.is-voted .niblo-vsslide-b::after { top: 0; }

.niblo-imm .niblo-vsslide.is-voted .niblo-vsslide-side:not(.is-chosen) .niblo-vsslide-body {
    opacity: .72;
}

.niblo-imm .niblo-vsslide-badge {
    align-items: center;
    background: var(--niblo-accent);
    border-radius: 999px;
    color: #fff;
    display: flex;
    font-size: 13px;
    font-weight: 800;
    height: 44px;
    justify-content: center;
    left: 50%;
    letter-spacing: .04em;
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 44px;
    z-index: 6;
}

/*
 * A, B, C on a full-screen answer.
 *
 * The same lettering the page uses. It sits in the panel rather than on the
 * photograph, so it stays readable whatever the picture behind it is doing.
 */
.niblo-imm .niblo-qanswer-key {
    align-items: center;
    border: 1px solid currentColor;
    border-radius: 7px;
    display: flex;
    flex: 0 0 auto;
    font-size: .78rem;
    font-weight: 700;
    height: 24px;
    justify-content: center;
    opacity: .75;
    width: 24px;
}

/* What was picked, on a matchup run's closing card. */
.niblo-imm .niblo-vsrecap {
    display: flex;
    flex-direction: column;
    gap: 8px;
    list-style: none;
    margin: 14px 0 0;
    max-height: 40vh;
    overflow-y: auto;
    padding: 0;
    text-align: left;
}

.niblo-imm .niblo-vsrecap-row {
    align-items: center;
    backdrop-filter: var(--niblo-imm-blur, none);
    background: var(--niblo-imm-fill, color-mix(in srgb, var(--niblo-ink, #fff) 8%, transparent));
    border: var(--niblo-border, 1px) solid var(--niblo-imm-line, transparent);
    border-radius: var(--niblo-radius, 12px);
    box-shadow: var(--niblo-imm-lift, none);
    color: var(--niblo-imm-text, #fff);
    display: flex;
    gap: 10px;
    margin: 0;
    padding: 8px 12px 8px 8px;
}

.niblo-imm .niblo-vsrecap-thumb {
    background: rgba(255, 255, 255, .12) center / cover no-repeat;
    border-radius: 8px;
    flex: 0 0 auto;
    height: 38px;
    width: 38px;
}

.niblo-imm .niblo-vsrecap-text {
    color: inherit;
    font-size: .92rem;
    font-weight: 600;
    line-height: 1.25;
    min-width: 0;
}

/* ---- what an answer does when it lands ----------------------------------
 *
 * In the page, not only full screen. A desktop answer changed colour and
 * nothing else, which reads as a repaint rather than as a response - the
 * verdict arrived with no moment attached to it.
 *
 * Transform and opacity only, so nothing on the page moves while it plays.
 */

.niblo .niblo-a-btn.is-correct,
.niblo .niblo-a-btn.is-chosen {
    animation: niblo-pop 240ms cubic-bezier(.34, 1.4, .64, 1);
}

.niblo .niblo-a-btn.is-wrong {
    animation: niblo-nudge 260ms ease-in-out;
}

/* The mark arrives after the fill, so the two read as one gesture. */
.niblo .niblo-a-btn.is-correct .niblo-a-mark,
.niblo .niblo-a-btn.is-wrong .niblo-a-mark {
    animation: niblo-mark 220ms 90ms cubic-bezier(.34, 1.5, .64, 1) backwards;
}

@keyframes niblo-pop {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.025); }
    100% { transform: scale(1); }
}

@keyframes niblo-nudge {
    0%, 100% { transform: translateX(0); }
    20%      { transform: translateX(-5px); }
    50%      { transform: translateX(4px); }
    80%      { transform: translateX(-2px); }
}

@keyframes niblo-mark {
    from { opacity: 0; transform: scale(.5); }
    to   { opacity: 1; transform: scale(1); }
}

/* The result arrives rather than appearing. */
.niblo .niblo-result {
    animation: niblo-reveal 380ms cubic-bezier(.2, .7, .3, 1);
}

@keyframes niblo-reveal {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .niblo .niblo-poll-btn.is-chosen,
    .niblo .niblo-vs-side.is-chosen,
    .niblo .niblo-a-btn.is-correct,
    .niblo .niblo-a-btn.is-wrong,
    .niblo .niblo-a-btn.is-chosen,
    .niblo .niblo-a-btn.is-correct .niblo-a-mark,
    .niblo .niblo-a-btn.is-wrong .niblo-a-mark,
    .niblo .niblo-result {
        animation: none;
    }
}

/* ---- the takeover, defended ---------------------------------------------
 *
 * The page's controls have been restated against the theme for a long time;
 * these never were. A tapped answer keeps focus, and a theme that paints
 * button:focus - or :active, or :disabled, which every answer becomes once the
 * question is done - fills exactly the one the reader chose, in a colour that
 * is nowhere in this plugin. It looks like a bug in the quiz and it is not.
 *
 * The verdict states are excluded rather than overridden: right, wrong and the
 * chosen ring own their colour, and a theme must not take it away.
 *
 * These carry !important, which nothing else in this file does. A theme that
 * paints its buttons with !important beats any specificity a stylesheet can
 * reach, and the takeover is a full-screen view of this plugin's own making -
 * there is no argument for letting the article's button styling into it.
 */
.niblo-imm .niblo-qanswer:hover:not(.is-correct):not(.is-wrong):not(.is-chosen),
.niblo-imm .niblo-qanswer:focus:not(.is-correct):not(.is-wrong):not(.is-chosen),
.niblo-imm .niblo-qanswer:focus-visible:not(.is-correct):not(.is-wrong):not(.is-chosen),
.niblo-imm .niblo-qanswer:active:not(.is-correct):not(.is-wrong):not(.is-chosen),
.niblo-imm .niblo-qanswer:disabled:not(.is-correct):not(.is-wrong):not(.is-chosen) {
    background: var(--niblo-imm-fill, rgba(20, 20, 22, .62)) !important;
    border-color: var(--niblo-imm-line, rgba(255, 255, 255, .28)) !important;
    color: var(--niblo-imm-text, #fff) !important;
}

/* And the theme must not take that fill away either. */
.niblo-imm .niblo-qanswer.is-chosen:not(.is-correct):not(.is-wrong):hover,
.niblo-imm .niblo-qanswer.is-chosen:not(.is-correct):not(.is-wrong):focus,
.niblo-imm .niblo-qanswer.is-chosen:not(.is-correct):not(.is-wrong):active,
.niblo-imm .niblo-qanswer.is-chosen:not(.is-correct):not(.is-wrong):disabled {
    background-color: var(--niblo-accent) !important;
    border-color: var(--niblo-accent) !important;
    color: var(--niblo-accent-ink, #fff) !important;
}

.niblo-imm .niblo-qanswer.is-correct:hover,
.niblo-imm .niblo-qanswer.is-correct:focus,
.niblo-imm .niblo-qanswer.is-correct:active,
.niblo-imm .niblo-qanswer.is-correct:disabled {
    background-color: var(--niblo-correct-fill, #58c96b) !important;
    border-color: var(--niblo-correct-fill, #58c96b) !important;
    color: var(--niblo-correct-ink, #191515) !important;
}

.niblo-imm .niblo-qanswer.is-wrong:hover,
.niblo-imm .niblo-qanswer.is-wrong:focus,
.niblo-imm .niblo-qanswer.is-wrong:active,
.niblo-imm .niblo-qanswer.is-wrong:disabled {
    background-color: var(--niblo-wrong-fill, #f04444) !important;
    border-color: var(--niblo-wrong-fill, #f04444) !important;
    color: var(--niblo-wrong-ink, #ffffff) !important;
}

/* The same for the rating buttons and the matchup sides. */
.niblo-imm .niblo-vote:hover,
.niblo-imm .niblo-vote:focus,
.niblo-imm .niblo-vote:active,
.niblo-imm .niblo-vote:disabled {
    background: var(--niblo-raise) !important;
    color: var(--niblo-ink, #fff) !important;
}

.niblo-imm .niblo-vote.is-chosen:hover,
.niblo-imm .niblo-vote.is-chosen:focus,
.niblo-imm .niblo-vote.is-chosen:active,
.niblo-imm .niblo-vote.is-chosen:disabled {
    background-color: var(--niblo-accent) !important;
}

.niblo-imm .niblo-vsslide-side:hover,
.niblo-imm .niblo-vsslide-side:focus,
.niblo-imm .niblo-vsslide-side:active,
.niblo-imm .niblo-vsslide-side:disabled {
    background: #15161a !important;
}
