/**
 * Newsletter capture — inline unit, desktop modal, mobile bottom sheet.
 *
 * The popup is `position: fixed` and ships `[hidden]`, so it never occupies
 * space in normal flow and cannot contribute to Cumulative Layout Shift. CLS is
 * measured on real users and feeds page experience, which makes it the most
 * concrete ranking risk in this file.
 *
 * Google's intrusive-interstitial guidance prohibits obscuring *the entire
 * page*, and blocking content *on arrival from search*. The mobile sheet stays
 * outside that on three counts, each pinned by a test in
 * newsletter/tests/test_seo_safety.py:
 *
 *   - it opens only after deep engagement, never on arrival;
 *   - it is capped in height and anchored to the bottom, so it never covers
 *     what is being read;
 *   - the backdrop is removed below 768px, so nothing is dimmed and the article
 *     behind the sheet stays scrollable and tappable.
 *
 * No z-index literals here — see z-index.css for the scale.
 */

/* ===================================================================
 * Shared
 * =================================================================== */

.nl-h {
    font-size: var(--font-size-xl);
    margin: 0 0 var(--spacing-2);
    color: var(--color-gray-900);
}

.nl-sub {
    margin: 0 0 var(--spacing-4);
    color: var(--color-gray-600);
    font-size: var(--font-size-sm);
}

.nl-label {
    /* Present for screen readers; the placeholder carries the visual cue. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.nl-row {
    display: flex;
    gap: var(--spacing-2);
    flex-wrap: wrap;
}

.nl-input {
    flex: 1 1 14rem;
    min-width: 0;
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--color-gray-300);
    border-radius: var(--radius-md);
    font-size: var(--font-size-base);
}

.nl-input:focus-visible,
.nl-btn:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

.nl-btn {
    padding: 0.625rem 1.25rem;
    background: var(--color-primary);
    color: #fff;
    border: 1px solid var(--color-primary);
    border-radius: var(--radius-md);
    font-weight: 600;
    cursor: pointer;
}

.nl-btn:hover {
    background: var(--color-primary-dark);
}

.nl-btn:disabled {
    opacity: 0.6;
    cursor: default;
}

/* The honeypot must be unreachable to people but present to a bot parsing the
 * DOM, so it is moved off-screen rather than display:none — some bots skip
 * hidden fields, which would defeat the point. */
.nl-hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.nl-msg {
    margin: var(--spacing-2) 0 0;
    font-size: var(--font-size-sm);
    min-height: 1.25rem; /* reserved, so a message never shifts the form */
}

.nl-msg.is-ok {
    color: var(--color-primary);
}

.nl-msg.is-err {
    color: var(--color-error);
}

/* ===================================================================
 * Inline unit — the primary capture on every viewport
 * =================================================================== */

.nl-inline {
    margin: var(--spacing-8) 0;
    padding: var(--spacing-6);
    background: var(--color-gray-50);
    border: 1px solid var(--color-gray-200);
    border-radius: var(--radius-lg);
}

/* ===================================================================
 * Popup — centered modal on desktop, bottom sheet on mobile.
 * Both open only after engagement; see the mobile section below.
 * =================================================================== */

.nl-pop[hidden] {
    display: none;
}

.nl-pop-backdrop {
    position: fixed;
    inset: 0;
    background: rgb(0 0 0 / 45%);
    z-index: var(--z-index-modal-backdrop);
}

.nl-pop-card {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: min(28rem, calc(100vw - 2rem));
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
    padding: var(--spacing-6);
    background: #fff;
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-xl);
    z-index: var(--z-index-modal);
    animation: nl-rise 0.18s ease-out;
}

.nl-pop-x {
    position: absolute;
    top: 0.25rem;
    right: 0.25rem;
    /* A 44px box around a small glyph. The hit area was ~19x28px, which on a
     * phone is what turns a dismissable sheet into an intrusive one — the
     * guidance cares that people can actually get rid of it. Applied to the
     * base rule, not the mobile block: it was too small on desktop too. */
    display: grid;
    place-items: center;
    min-width: 44px;
    min-height: 44px;
    background: none;
    border: 0;
    font-size: 1.75rem;
    line-height: 1;
    color: var(--color-gray-500);
    cursor: pointer;
}

.nl-pop-x:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

/* Keep the heading out from under the close button's 44px box. */
.nl-pop-card .nl-h {
    padding-right: 2.5rem;
}

@keyframes nl-rise {
    from {
        opacity: 0;
        transform: translate(-50%, calc(-50% + 8px));
    }
}

/* The centered card animates from its own translate(-50%, -50%), so nl-rise
 * cannot be reused by a sheet that sits at translate: none. */
@keyframes nl-slide-up {
    from {
        transform: translateY(100%);
    }
}

/* ===================================================================
 * Mobile sheet — the same dialog, anchored to the bottom, dimming nothing.
 *
 * 768px exactly, not the 767.98px used elsewhere in this project:
 * newsletter.js compares `window.innerWidth <= MOBILE_MAX` inclusively, and a
 * fractional breakpoint would leave one pixel of width where the script opens
 * a sheet that is still painted as a centered modal.
 * =================================================================== */

@media (max-width: 768px) {
    /* The most important line in this file. Dimming the whole viewport is the
     * pattern Google's guidance actually names, and a full-screen backdrop
     * also swallows touch-scroll, which blocks the article behind the sheet.
     * Removing it leaves the page readable and scrollable while the sheet is
     * open; the 44px close button is what dismisses it. */
    .nl-pop-backdrop {
        display: none;
    }

    .nl-pop-card {
        top: auto;
        right: 0;
        bottom: 0;
        left: 0;
        width: auto;
        /* A cap, not a height — the card already scrolls its own overflow.
         * 45vh clears the heading, the wrapped input/button row and the ~65px
         * Turnstile widget on a 667px-tall phone without pushing the submit
         * button out of view. */
        max-height: 45vh;
        transform: none;
        border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
        /* Clear of the home indicator. */
        padding-bottom: calc(var(--spacing-6) + env(safe-area-inset-bottom));
        /* --shadow-xl casts 20px downward, which is invisible under a sheet. */
        box-shadow: 0 -6px 24px rgb(0 0 0 / 25%);
        overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
        animation: nl-slide-up 0.18s ease-out;
    }
}

/* Last on purpose: this has the same specificity as the sheet rule above, so
 * source order is the only thing that lets it cancel both animations. */
@media (prefers-reduced-motion: reduce) {
    .nl-pop-card {
        animation: none;
    }
}
