/* Shared visual product pages (Sharpen / Lens dirt language).
   Theme via --pv-* on .pv-page */
.pv-page {
    --pv-bg: #101214;
    --pv-ink: #f3eee6;
    --pv-accent: #d4b45a;
    --pv-surface: #16181c;
    --pv-radius: 4px;
    background: var(--pv-bg);
}
.pv-page .page-bg {
    background:
        radial-gradient(ellipse 70% 45% at 0% 0%, color-mix(in srgb, var(--pv-accent) 12%, transparent), transparent 58%),
        radial-gradient(ellipse 50% 40% at 100% 100%, color-mix(in srgb, var(--pv-accent) 7%, transparent), transparent 55%);
}

.pv-shot { margin: 0; display: block; height: 100%; }
.pv-shot-box {
    position: relative;
    overflow: hidden;
    height: 100%;
    min-height: 12rem;
    aspect-ratio: var(--ar, 16 / 9);
    border-radius: var(--pv-radius);
    background-color: var(--pv-surface);
    background-image: radial-gradient(rgba(255, 255, 255, 0.07) 0.7px, transparent 0.8px);
    background-size: 11px 11px;
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pv-accent) 22%, transparent);
}
.pv-shot.is-filled .pv-shot-box {
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
    background-image: none;
}
.pv-shot img,
.pv-shot video,
.pv-shot iframe,
.pv-shot picture {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border: 0;
    z-index: 1;
}
/* Fail-open reveal.
   Images used to start at opacity:0 and were revealed only when JS added
   .is-filled on the load event. Anything that broke that one chain — a load
   event fired before the listener attached, a format the browser declined to
   decode, a script that didn't run — left a permanently black box with no way
   back. Images are now visible as soon as the browser has them, and the
   authoring placeholder is shown only when a load actually fails
   (.is-broken, set from the img error handler). */
.pv-shot picture { opacity: 1; }
.pv-shot img { opacity: 1; }
.pv-shot video { opacity: 0; }
.pv-shot.is-filled video.is-on { opacity: 1; }
.pv-shot iframe { opacity: 1; }
.pv-shot-fallback {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: none;
    flex-direction: column;
    justify-content: flex-end;
    gap: 0.3rem;
    padding: clamp(1rem, 3vw, 1.6rem);
    color: var(--text);
}
/* Only when the image genuinely failed to load. */
.pv-shot.is-broken .pv-shot-fallback { display: flex; }
/* Or when there is no media yet: an authoring slot for a clip still to be
   shot. The fallback text is the brief for it. Drop the class when the clip
   lands — the figure then behaves like any other. */
.pv-shot.is-placeholder .pv-shot-fallback { display: flex; }
.pv-shot-kicker {
    font-family: var(--font-display);
    font-size: 0.6875rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--pv-accent);
}
.pv-shot-file {
    font-family: var(--font-display);
    font-size: clamp(1rem, 2.2vw, 1.3rem);
    font-weight: 500;
    letter-spacing: -0.02em;
    color: #fff;
}
.pv-shot-size { font-size: 0.75rem; color: var(--text-muted); }
.pv-shot-what {
    margin: 0.35rem 0 0;
    max-width: 44ch;
    font-size: 0.875rem;
    line-height: 1.55;
    color: var(--text-soft);
}

.pv-hero {
    display: grid;
    min-height: 100vh;
    min-height: 100dvh;
}
.pv-hero-media { min-height: 52vh; min-height: 52dvh; }
.pv-hero-media .pv-shot-box {
    min-height: 52vh;
    min-height: 52dvh;
    height: 100%;
    aspect-ratio: auto;
    border-radius: 0;
    box-shadow: none;
}
.pv-hero-copy {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 5.5rem var(--gutter) 2rem;
}
@media (min-width: 900px) {
    .pv-hero {
        grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
        align-items: stretch;
    }
    .pv-hero--flip {
        grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
    }
    .pv-hero--flip .pv-hero-copy { order: 1; }
    .pv-hero--flip .pv-hero-media { order: 2; }
    .pv-hero-copy { padding: 6rem var(--gutter) 4rem; }
    .pv-hero-media { min-height: 100vh; min-height: 100dvh; }
    .pv-hero-media .pv-shot-box { min-height: 100vh; min-height: 100dvh; }
}
.pv-kicker {
    font-family: var(--font-display);
    font-size: 0.75rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--pv-accent);
    margin: 0 0 0.85rem;
}
.pv-hero h1 {
    font-family: var(--font-display);
    font-size: clamp(2.5rem, 7vw, 5.2rem);
    font-weight: 400;
    letter-spacing: -0.045em;
    line-height: 0.94;
    color: var(--pv-ink);
    margin: 0 0 0.85rem;
    max-width: 10ch;
}
.pv-hero-lead {
    margin: 0 0 1.1rem;
    max-width: 34ch;
    font-size: clamp(0.95rem, 1.5vw, 1.1rem);
    line-height: 1.5;
    color: rgba(237, 237, 237, 0.78);
}
.pv-price {
    font-family: var(--font-display);
    font-size: 1.35rem;
    letter-spacing: -0.03em;
    color: #fff;
    margin: 0 0 1.15rem;
}
.pv-price s {
    color: var(--text-muted);
    font-size: 0.9em;
    margin-left: 0.45rem;
}
.pv-actions { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.pv-btn-icon {
    display: inline-flex;
    margin-left: 0.35rem;
    transition: transform 0.2s ease;
}
.btn-primary:hover .pv-btn-icon { transform: translateX(2px); }
@media (prefers-reduced-motion: reduce) {
    .btn-primary:hover .pv-btn-icon { transform: none; }
}

/* ---- Full-bleed hero (VHS pattern) ----
   One full-screen image behind everything, copy pinned to the bottom edge
   and legible over a scrim rather than sat beside the shot in its own
   column. Opt in with `pv-hero pv-hero--full` — the compound selectors
   below beat the base .pv-hero rules regardless of source order. */
.pv-hero.pv-hero--full {
    position: relative;
    display: flex;
    align-items: flex-end;
    isolation: isolate;
}
.pv-hero--full .pv-hero-media {
    position: absolute;
    inset: 0;
    z-index: 0;
    min-height: 0;
}
.pv-hero--full .pv-hero-media .pv-shot-box {
    height: 100%;
    min-height: 100vh;
    min-height: 100dvh;
    aspect-ratio: auto;
    border-radius: 0;
    box-shadow: none;
}
/* The scrim ramp is measured in rem from the bottom edge, not in percentages
   of the hero. The hero is 100dvh, so percentage stops move with the viewport:
   on a 900px-tall desktop window the copy started halfway up, where the old
   32%-to-100% ramp was still only ~35% opaque, and the cyan kicker and muted
   terms line vanished into a bright frame of the video. A fixed ramp keeps the
   same cover over the copy block whatever the window height. */
.pv-hero-scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        linear-gradient(180deg,
            color-mix(in srgb, var(--pv-bg) 50%, transparent) 0%,
            transparent 20%),
        linear-gradient(0deg,
            color-mix(in srgb, var(--pv-bg) 88%, transparent) 0rem,
            color-mix(in srgb, var(--pv-bg) 58%, transparent) 26rem,
            transparent 46rem);
}
/* Desktop pins the copy to the bottom left of a full-width frame, so it also
   gets a left-edge wash. It buys the contrast the vertical ramp alone can't
   without flattening the whole shot, and it dies out well before the right
   half of the frame. Below 900px the copy is full width and this would just
   be a dark stripe, so it is off. */
.pv-hero-scrim::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--pv-bg) 50%, transparent) 0%,
        color-mix(in srgb, var(--pv-bg) 25%, transparent) 32%,
        transparent 60%);
}
@media (max-width: 899px) {
    .pv-hero-scrim::before { content: none; }
}
.pv-hero.pv-hero--full .pv-hero-copy {
    position: relative;
    z-index: 2;
    width: min(100%, 1400px);
    margin-inline: auto;
    padding: 0 var(--gutter) clamp(1.75rem, 5vw, 3rem);
    padding-bottom: calc(clamp(1.75rem, 5vw, 3rem) + env(safe-area-inset-bottom));
}
@media (max-width: 899px) {
    .pv-hero--full .pv-hero-copy { padding-bottom: calc(6.25rem + env(safe-area-inset-bottom)); }
    .pv-hero--full .pv-actions { flex-direction: column; align-items: stretch; max-width: 22rem; }
    .pv-hero--full .pv-actions .btn { width: 100%; }
}

.pv-section { padding-block: clamp(3.5rem, 9vw, 7rem); }
.pv-wrap {
    width: min(100%, 1400px);
    margin-inline: auto;
    padding-inline: var(--gutter);
}
.pv-h2 {
    font-family: var(--font-display);
    font-size: clamp(1.85rem, 4.4vw, 3.1rem);
    font-weight: 400;
    letter-spacing: -0.03em;
    line-height: 1.08;
    color: var(--pv-ink);
    margin: 0 0 0.75rem;
    max-width: 16ch;
}
.pv-body {
    margin: 0;
    max-width: 42ch;
    font-size: 1rem;
    line-height: 1.65;
    color: var(--text-soft);
}

.pv-compare {
    position: relative;
    margin-top: clamp(1.5rem, 4vw, 2.4rem);
    --split: 48%;
    overflow: hidden;
    border-radius: var(--pv-radius);
    touch-action: pan-y;
    user-select: none;
    -webkit-user-select: none;
    cursor: ew-resize;
}
.pv-compare-base .pv-shot-box,
.pv-compare-over .pv-shot-box {
    width: 100%;
    min-height: clamp(16rem, 52vw, 38rem);
    aspect-ratio: 16 / 9;
    pointer-events: none;
}
.pv-compare-over {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 2;
    clip-path: inset(0 calc(100% - var(--split)) 0 0);
}
.pv-compare-rule {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--split);
    width: 2px;
    margin-left: -1px;
    background: #fff;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--pv-accent) 45%, transparent);
    pointer-events: none;
    z-index: 3;
}
.pv-compare-knob {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 2.75rem;
    height: 2.75rem;
    margin: -1.375rem 0 0 -1.375rem;
    border-radius: 999px;
    border: 1.5px solid #fff;
    background: color-mix(in srgb, var(--pv-bg) 78%, transparent);
}
.pv-compare-knob::before,
.pv-compare-knob::after {
    content: "";
    position: absolute;
    top: 50%;
    width: 7px;
    height: 7px;
    border-top: 1.5px solid #fff;
    border-right: 1.5px solid #fff;
    margin-top: -4px;
}
.pv-compare-knob::before { left: 0.7rem; transform: rotate(-135deg); }
.pv-compare-knob::after { right: 0.7rem; transform: rotate(45deg); }
.pv-compare input[type="range"] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.pv-compare-caption {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 0.85rem;
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.pv-pair {
    display: grid;
    gap: 0.75rem;
    margin-top: clamp(1.5rem, 4vw, 2.4rem);
}
@media (min-width: 800px) {
    .pv-pair { grid-template-columns: 1fr 1fr; }
}
.pv-pair-label {
    margin: 0.7rem 0 0;
    font-family: var(--font-display);
    font-size: 0.8125rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.pv-hits {
    display: grid;
    gap: 0.75rem;
    grid-template-columns: 1fr;
}
@media (min-width: 860px) {
    .pv-hits {
        grid-template-columns: 1.15fr 0.85fr;
        grid-template-rows: auto auto;
    }
    .pv-hits > :nth-child(1) { grid-column: 1; grid-row: 1 / 3; }
    .pv-hits > :nth-child(1) .pv-shot-box { --ar: 3 / 4; min-height: 100%; }
    .pv-hits > :nth-child(4) { grid-column: 1 / -1; }
}
.pv-hits--even {
    grid-template-columns: 1fr;
}
@media (min-width: 860px) {
    .pv-hits--even {
        grid-template-columns: 1fr 1fr;
        grid-template-rows: none;
    }
    .pv-hits--even > :nth-child(1) { grid-column: auto; grid-row: auto; }
    .pv-hits--even > :nth-child(1) .pv-shot-box { --ar: 16 / 9; }
    .pv-hits--even > :nth-child(4) { grid-column: auto; }
}

.pv-spec-row {
    display: grid;
    gap: 1.5rem;
}
@media (min-width: 900px) {
    .pv-spec-row {
        grid-template-columns: 1.15fr 0.9fr;
        gap: 3rem;
        align-items: end;
    }
}
.pv-spec-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.25rem 1.5rem;
    margin-top: 1.75rem;
}
.pv-spec dt {
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    font-family: var(--font-display);
    margin: 0 0 0.25rem;
}
.pv-spec dd { margin: 0; color: #fff; font-size: 1rem; }

.pv-job {
    position: relative;
    min-height: clamp(22rem, 56vw, 32rem);
    display: flex;
    align-items: flex-end;
}
.pv-job .pv-shot,
.pv-job .pv-shot-box {
    position: absolute;
    inset: 0;
    height: 100%;
    aspect-ratio: auto;
    min-height: 100%;
    border-radius: 0;
}
.pv-job-copy {
    position: relative;
    z-index: 2;
    width: 100%;
    max-width: 1400px;
    margin: 0 auto;
    padding: 4.5rem var(--gutter) 2.25rem;
    background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--pv-bg) 92%, transparent) 55%);
}
.pv-job h3 {
    font-family: var(--font-display);
    font-size: clamp(1.6rem, 3.4vw, 2.4rem);
    font-weight: 400;
    letter-spacing: -0.03em;
    margin: 0 0 0.5rem;
    color: #fff;
}
@media (min-width: 900px) {
    .pv-job--side {
        display: grid;
        grid-template-columns: 1.15fr 0.85fr;
        min-height: clamp(24rem, 46vw, 32rem);
    }
    .pv-job--side .pv-shot,
    .pv-job--side .pv-shot-box {
        position: relative;
        inset: auto;
        order: 1;
    }
    .pv-job--side .pv-job-copy {
        order: 2;
        background: transparent;
        display: flex;
        flex-direction: column;
        justify-content: center;
        padding: 3rem var(--gutter);
    }
}

.pv-close {
    text-align: left;
    padding-block: clamp(4rem, 12vw, 8rem);
}
.pv-close h2 {
    font-family: var(--font-display);
    font-size: clamp(2.2rem, 6vw, 4.4rem);
    font-weight: 400;
    letter-spacing: -0.04em;
    line-height: 1.05;
    margin: 0 0 1.4rem;
    max-width: 12ch;
    color: var(--pv-ink);
}
.pv-close h2 em {
    font-style: italic;
    font-weight: 400;
    display: inline-block;
    padding-bottom: 0.15em;
    line-height: 1.12;
}

@media (max-width: 767px) {
    .pv-spec-grid { grid-template-columns: 1fr; }
}
