/*
 * Nova baseline effects (nova/baseline-polish in the effects catalog): hover micro-interactions +
 * scroll-reveal + scroll-to-top button. Ships with every site and is auto-enqueued via
 * functions.php by default — no per-project generation needed. Unlike the rest of the effects
 * catalog, this one is NOT gated behind a marker attribute: it targets structural selectors present
 * on any real page, so Content's only lever is removing its functions.php enqueue block entirely
 * for a static/minimal/no-animation brief (see ContentContext.ts's Baseline effects section) —
 * never a per-page decision.
 */

/* Global box-sizing reset: a generated custom widget's CSS (e.g. a per-project effect file) that
 * sets width:100% plus its own padding, without ever declaring box-sizing itself, renders wider
 * than its container under the default content-box model — the padding adds on top of the 100%
 * instead of being carved out of it, which has been observed to overflow into and visually cover a
 * neighboring column. border-box makes width:100% + padding behave as most authors actually expect,
 * closing that failure mode at the root instead of requiring every generated CSS file to declare it. */
*,
*::before,
*::after {
    box-sizing: border-box;
}

/* Global responsive-image safety net: WordPress core's own "max-width:100%; height:auto" image
 * reset is scoped to specific selectors (.wp-block-image img, img[class*=wp-image-], etc.) that
 * only ever match a native image block — never a bare <img> a generated custom widget's own
 * markup/JS creates (a product-viewer, a gallery, a card component). Without an explicit
 * width/height/object-fit of its own, such an image renders at full natural resolution and
 * overflows its container by hundreds of pixels, bleeding into neighboring content — confirmed
 * live on a generated shop product-viewer widget. A bare `img` selector has the lowest possible
 * specificity, so any more specific sizing a widget's own CSS declares still wins over this — it
 * only catches images nobody ever sized. */
img {
    max-width: 100%;
    height: auto;
}

.wp-block-button__link,
.wp-block-group.has-background:not(.alignfull):not(.alignwide) {
    transition:
        transform 0.25s ease,
        box-shadow 0.25s ease;
}

/* Core ships word-break: break-word on button links, which breaks mid-character in narrow
 * containers (e.g. a Classic layout's 30%-width sidebar). Wrap at word boundaries instead;
 * overflow-wrap/hyphens still catch a genuinely too-long single word as a fallback ("Start-ed"
 * reads as intentional, unlike an arbitrary character cut) — but hyphenation alone won't save a
 * button that's cramped enough that even one hyphenated half doesn't fit (most engines refuse a
 * break leaving under ~3 characters on either side, so short words like "Started" don't hyphenate
 * at all). Let the font-size shrink with the container as a last resort instead: core's own button
 * padding is em-based, so it shrinks right along with it. */
.wp-block-buttons {
    container-type: inline-size;
}

/* Default vertical-align:baseline on this inline-block anchor aligns it to a "strut" based on the
 * wrapper's inherited font metrics, not the button's own — a fill button (no border, thicker
 * padding) and an outline button (border, thinner padding) land their text baselines at different
 * offsets from that strut, so their wrapping `.wp-block-button` boxes end up different heights and
 * visibly misaligned in a `wp:buttons` row. top removes the strut dependency entirely. */
.wp-block-button__link {
    word-break: normal;
    overflow-wrap: break-word;
    -webkit-hyphens: auto;
    hyphens: auto;
    font-size: clamp(0.75rem, 4cqw, 1.125rem);
    vertical-align: top;
}

.wp-block-button__link:hover,
.wp-block-group.has-background:not(.alignfull):not(.alignwide):hover {
    transform: translateY(-4px);
    box-shadow: var(--wp--preset--shadow--elevated, 0 8px 24px rgba(0, 0, 0, 0.16));
}

.scroll-reveal {
    opacity: 0;
    transform: translateY(24px);
    transition:
        opacity 0.6s ease,
        transform 0.6s ease;
}

.scroll-reveal.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* Scroll-to-top button: injected by baseline.js (no markup for this exists in any generated page),
 * hidden by default and only shown past a scroll threshold — see baseline.js for why opacity+
 * visibility rather than display is used to hide it (keeps the transition animatable). */
.nova-scroll-to-top {
    position: fixed;
    right: var(--wp--preset--spacing--30, 24px);
    bottom: var(--wp--preset--spacing--30, 24px);
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: none;
    border-radius: 9999px;
    background: var(--wp--preset--color--contrast, #111);
    color: var(--wp--preset--color--base, #fff);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition:
        opacity 0.25s ease,
        transform 0.25s ease,
        visibility 0s linear 0.25s;
}

.nova-scroll-to-top.is-visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition:
        opacity 0.25s ease,
        transform 0.25s ease,
        visibility 0s linear 0s;
}

.nova-scroll-to-top:hover {
    transform: translateY(-4px);
    box-shadow: var(--wp--preset--shadow--elevated, 0 8px 24px rgba(0, 0, 0, 0.16));
}

.nova-scroll-to-top svg {
    width: 20px;
    height: 20px;
    fill: currentColor;
}

.wp-block-cover__inner-container :where(h1, h2, h3, h4, h5, h6, p) {
    text-shadow:
        0 1px 3px rgba(0, 0, 0, 0.45),
        0 1px 12px rgba(0, 0, 0, 0.3);
}

/* Photo covers: diagonal shading for depth, layered on top of the block's own overlayColor/
 * dimRatio via background-image (a separate property, so it never fights the native dim the
 * model sets per block). Native cover attributes only produce a flat color overlay — a gradient
 * shape isn't something dimRatio/overlayColor can express, hence the CSS. */
:where(.wp-block-cover:has(> .wp-block-cover__image-background)) > .wp-block-cover__background {
    background-image: linear-gradient(135deg, rgba(0, 0, 0, 0.35) 0%, rgba(0, 0, 0, 0.1) 100%);
}

/* Card patterns (nova/card-row-centered, nova/info-row-centered): the shared card shape is an
 * accent-5-background group with an image as its first child, an alignItems:stretch layout so the
 * image fills the card's full width instead of shrinking to its own, and the row that holds them
 * stretching every card to the tallest one in its line. Per-generation content re-types this JSON
 * rather than reusing the pattern directly, so a generation can drop/flip alignItems/
 * verticalAlignment — the card still has the right classes/structure, just misaligned. Enforce both
 * structurally (matched on the classes the model reliably keeps — backgroundColor + a leading
 * image — not a bespoke className) so the layout is correct regardless of what the generated JSON
 * says. */
.wp-block-group:has(> .wp-block-group.has-accent-5-background-color:has(> .wp-block-image)) {
    align-items: stretch;
}

.wp-block-group.has-accent-5-background-color:has(> .wp-block-image) {
    align-items: stretch;
}

.wp-block-group.has-accent-5-background-color:has(> .wp-block-image) > .wp-block-image {
    align-self: stretch;
    width: 100%;
}

.wp-block-group.has-accent-5-background-color:has(> .wp-block-image) > .wp-block-image img {
    width: 100%;
}
