/* Streamlined Stays — depth layer.
 *
 * CSS-3D scenes ported from the design system's Hero3D, ServiceTile(depth),
 * CoverageMap3D, UnitViewer3D and ScrollScene components. No WebGL and no
 * build step, so this keeps working on locked-down machines.
 *
 * Progressive enhancement, always. Every scene renders a flat, readable
 * composition from the server. assets/js/depth.js adds `.ss-depth-on` to
 * <html> only when the browser supports preserve-3d AND the visitor has not
 * asked for reduced motion; every transform below is scoped behind that class.
 * With JS off, or motion reduced, the page is the flat version.
 */

/* ------------------------------------------------------------------ *
 * Hero3D
 * ------------------------------------------------------------------ */

/* Content stays bottom-aligned — that's the editorial signature shared with
   the article heroes on blog.php and the guides. The height is clamped rather
   than a bare vh: the design system's 86vh was sized for a hero carrying an
   intro, a CTA and three photo panels, and leaves the eyebrow-plus-headline
   pairing stranded at the foot of a mostly empty frame. */
.ss-hero {
    position: relative;
    display: flex;
    align-items: flex-end;
    min-height: clamp(400px, 56vh, 620px);
    overflow: hidden;
    isolation: isolate;
    background: var(--ss-navy);
    color: var(--ss-white);
}

.ss-hero__stage {
    position: absolute;
    inset: 0;
}

.ss-hero__world {
    position: absolute;
    inset: 0;
}

/* The photographic plate. Doubles as the flat hero background. */
.ss-hero__plate {
    position: absolute;
    inset: -6%;
    background-image: url("../../images/a1.jpg");
    background-position: center;
    background-size: cover;
    filter: saturate(.9) contrast(1.04) brightness(.72);
}

@media (max-width: 768px) {
    .ss-hero__plate {
        background-image: url("../../images/perf/a1-mobile.webp");
    }
}

.ss-hero__fill {
    position: absolute;
    inset: -6%;
    background: var(--ss-fill-light);
}

.ss-hero__key {
    position: absolute;
    inset: 0;
    background: var(--ss-key-light);
    pointer-events: none;
}

/* Darkens the left of the frame so the headline stays legible over the photo. */
.ss-hero__scrim {
    position: absolute;
    inset: 0;
    background: var(--ss-scrim-copy);
    pointer-events: none;
}

/* Top padding only has to clear the fixed navbar for the case where the box
   compresses to its floor; the bottom value is what actually sets the copy off
   the edge. --ss-hero-pad-top (170px) still serves the article heroes. */
.ss-hero__copy {
    position: relative;
    width: var(--ss-shell);
    margin: 0 auto;
    padding: calc(var(--ss-nav-height) + 44px) 0 64px;
}

.ss-hero__inner {
    max-width: 620px;
}

.ss-hero__eyebrow {
    display: block;
    margin-bottom: 16px;
    color: var(--ss-gold);
    font-family: var(--ss-font-sans);
    font-size: var(--ss-size-eyebrow);
    font-weight: 800;
    letter-spacing: var(--ss-track-label);
    text-transform: uppercase;
}

.ss-hero__copy h1 {
    margin: 0;
    color: var(--ss-white);
    font-family: var(--font-display);
    font-size: var(--ss-size-hero);
    font-weight: 700;
    line-height: var(--ss-lh-hero);
    text-shadow: 0 2px 24px rgba(11, 18, 46, .45);
    text-wrap: pretty;
}

/* --- Hero, enhanced --- */
.ss-depth-on .ss-hero__stage {
    perspective: var(--ss-perspective);
    perspective-origin: 38% 42%;
}

.ss-depth-on .ss-hero__world {
    transform-style: preserve-3d;
    transform:
        rotateX(calc(var(--tx, 0) * var(--ss-tilt-max)))
        rotateY(calc(var(--ty, 0) * var(--ss-tilt-max)))
        translateZ(calc(var(--p, 0) * 110px));
    transition: transform var(--ss-dur-tilt) var(--ss-ease-camera);
}

.ss-depth-on .ss-hero__plate {
    transform: translateZ(var(--ss-z-plate)) scale(1.18);
}

.ss-depth-on .ss-hero__fill {
    transform: translateZ(-140px) scale(1.1);
}

.ss-depth-on .ss-hero__scrim {
    transform: translateZ(var(--ss-z-mid));
}

.ss-depth-on .ss-hero__copy {
    transform: translateZ(var(--ss-z-ui));
}

@media (max-width: 991px) {
    .ss-hero {
        min-height: clamp(320px, 46vh, 460px);
    }

    .ss-hero__copy {
        padding-top: calc(var(--ss-nav-height-mobile) + 32px);
        padding-bottom: 48px;
    }
}

@media (max-width: 620px) {
    .ss-hero__copy h1 {
        font-size: 2.6rem;
    }
}

/* ------------------------------------------------------------------ *
 * ServiceTile — the home service grid
 * ------------------------------------------------------------------ */

.ss-tile-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: minmax(250px, auto);
    gap: 15px;
    padding: 40px;
}

.ss-tile {
    position: relative;
    display: block;
    aspect-ratio: 4 / 3;
    cursor: pointer;
    text-decoration: none;
}

.ss-tile:focus-visible {
    outline: var(--ss-outline-focus);
    outline-offset: 4px;
}

.ss-tile__tilt {
    position: absolute;
    inset: 0;
    display: block;
    transition: transform .5s var(--ss-ease-zoom);
}

.ss-tile__clip {
    position: absolute;
    inset: 0;
    display: block;
    overflow: hidden;
    border-radius: var(--ss-radius-lg);
    transition: box-shadow .4s var(--ss-ease);
}

/* A real <img>, not a JS-assigned background: it needs no script, gets native
   lazy loading, and its src resolves against the document rather than against
   this stylesheet. */
.ss-tile__img {
    position: absolute;
    inset: -2%;
    width: 104%;
    height: 104%;
    object-fit: cover;
    transition: transform var(--ss-dur-zoom) var(--ss-ease-zoom);
}

.ss-tile:hover .ss-tile__img {
    transform: scale(var(--ss-zoom-hover));
}

.ss-tile__key {
    position: absolute;
    inset: 0;
    background: var(--ss-key-light);
    opacity: 0;
    pointer-events: none;
    transition: opacity .4s var(--ss-ease);
}

/* Sibling of the clip layer, not a child: an overflow:hidden ancestor would
   flatten the label's Z translation. */
.ss-tile__label {
    position: absolute;
    bottom: 20px;
    left: 50%;
    width: 80%;
    box-sizing: border-box;
    padding: 10px 20px;
    border-radius: var(--ss-radius-pill);
    background: var(--ss-pill-stone);
    color: var(--ss-paper);
    font-family: var(--ss-font-sans);
    font-size: 1rem;
    font-weight: 600;
    text-align: center;
    text-transform: uppercase;
    pointer-events: none;
    transform: translateX(-50%);
    transition: transform var(--ss-dur-slow) var(--ss-ease);
}

/* Visible by default so the label survives with JS off. The staggered reveal
   is opt-in: .ss-js is set inline in <head>, so there is no flash. */
.ss-js .ss-tile__label {
    opacity: 0;
}

.ss-js .ss-tile__label.is-shown {
    animation: ss-tile-fade-up .8s var(--ss-ease) forwards;
}

@keyframes ss-tile-fade-up {
    from {
        opacity: 0;
        transform: translate(-50%, 30px);
    }

    to {
        opacity: 1;
        transform: translate(-50%, 0);
    }
}

.ss-js .ss-tile-grid > .ss-tile:nth-child(1) .ss-tile__label.is-shown { animation-delay: .2s; }
.ss-js .ss-tile-grid > .ss-tile:nth-child(2) .ss-tile__label.is-shown { animation-delay: .4s; }
.ss-js .ss-tile-grid > .ss-tile:nth-child(3) .ss-tile__label.is-shown { animation-delay: .6s; }
.ss-js .ss-tile-grid > .ss-tile:nth-child(4) .ss-tile__label.is-shown { animation-delay: .8s; }
.ss-js .ss-tile-grid > .ss-tile:nth-child(5) .ss-tile__label.is-shown { animation-delay: 1s; }
.ss-js .ss-tile-grid > .ss-tile:nth-child(6) .ss-tile__label.is-shown { animation-delay: 1.2s; }

/* --- Tiles, enhanced --- */
.ss-depth-on .ss-tile {
    perspective: var(--ss-perspective-tile);
}

.ss-depth-on .ss-tile__tilt {
    transform-style: preserve-3d;
}

.ss-depth-on .ss-tile.is-tilting .ss-tile__tilt {
    transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateZ(var(--ss-z-lift));
    transition: transform var(--ss-dur-fast) ease-out;
}

.ss-depth-on .ss-tile.is-tilting .ss-tile__clip {
    box-shadow: var(--ss-tile-lift-shadow);
}

.ss-depth-on .ss-tile.is-tilting .ss-tile__key {
    opacity: 1;
}

.ss-depth-on .ss-tile.is-tilting .ss-tile__label {
    transform: translateX(-50%) translateZ(var(--ss-z-label));
}

.ss-depth-on .ss-tile.is-tilting .ss-tile__label.is-shown {
    animation: none;
    opacity: 1;
}

@media (max-width: 991px) {
    .ss-tile-grid {
        grid-template-columns: repeat(2, 1fr);
        padding: 20px;
    }

    /* Touch screens never get a hover, so the label has to stand on its own.
       Matched on .ss-js too, otherwise the opt-in hide above would win. */
    .ss-tile__label,
    .ss-js .ss-tile__label {
        bottom: 5px;
        width: 250px;
        max-width: 90%;
        padding: 6px 12px;
        background: #24324f;
        color: var(--ss-white);
        opacity: 1;
        animation: none !important;
        transform: translateX(-50%) !important;
    }
}

@media (max-width: 576px) {
    .ss-tile-grid {
        grid-template-columns: 1fr;
        gap: 20px;
    }
}

/* ------------------------------------------------------------------ *
 * CoverageMap3D
 * ------------------------------------------------------------------ */

.ss-coverage {
    padding: var(--ss-band-y) 40px;
    background: var(--ss-white);
    font-family: var(--ss-font-sans);
}

.ss-coverage__inner {
    width: min(1180px, 100%);
    margin: 0 auto;
}

/* The design system's CoverageMap3D puts a gold eyebrow here, which works on
   the dark hero but only reaches 2.25:1 on this white band. --text-eyebrow-on-light
   is the token the system provides for exactly this case, and it matches the
   eyebrows already used on the resources and impact bands. */
.ss-coverage__eyebrow {
    display: block;
    margin-bottom: 12px;
    color: var(--text-eyebrow-on-light);
    font-size: var(--ss-size-eyebrow);
    font-weight: 800;
    letter-spacing: var(--ss-track-label);
    text-transform: uppercase;
}

.ss-coverage__inner h2 {
    margin: 0 0 14px;
    color: var(--ss-navy);
    font-family: var(--ss-font-serif);
    font-size: var(--ss-size-h2);
    line-height: var(--ss-lh-h2);
}

.ss-coverage__note {
    max-width: 62ch;
    margin: 0 0 26px;
    color: var(--ss-muted);
    font-size: var(--ss-size-body);
    line-height: var(--ss-lh-body);
}

.ss-coverage__foot {
    margin: 22px 0 0;
    color: var(--ss-muted);
    font-size: .86rem;
    line-height: 1.6;
}

/* Flat composition: the plate as a plain picture, metros as chips. */
.ss-coverage__flat {
    padding: 22px;
    border: 1px solid var(--ss-border);
    border-radius: var(--ss-radius-lg);
    background: var(--ss-white);
}

.ss-coverage__flat img {
    display: block;
    width: 100%;
    height: auto;
}

.ss-coverage__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 20px 0 0;
    padding: 0;
    list-style: none;
}

.ss-coverage__chips li {
    padding: 7px 13px;
    border: 1px solid var(--ss-border);
    border-radius: var(--ss-radius-pill);
    background: var(--ss-white);
    color: var(--ss-navy);
    font-size: .84rem;
    font-weight: 700;
}

/* The 3D stage only exists once the camera does. */
.ss-coverage__stage {
    display: none;
}

.ss-depth-on .ss-coverage__stage {
    display: block;
    position: relative;
    height: clamp(320px, 44vw, 560px);
    overflow: hidden;
    border-radius: var(--ss-radius-lg);
    background: var(--ss-orbit-floor);
    perspective: var(--ss-perspective);
    perspective-origin: 50% 34%;
}

.ss-depth-on .ss-coverage__flat,
.ss-depth-on .ss-coverage__chips {
    display: none;
}

.ss-coverage__plate {
    position: absolute;
    top: 50%;
    left: 50%;
    width: min(88%, 900px);
    aspect-ratio: 1449 / 736;
    border-radius: var(--ss-radius-xs);
    /* Crop matches the design system's default: x .2275 y .181 w .5125 h .523 */
    background: var(--ss-white) url("../../images/state-by-state-map.jpg") no-repeat;
    background-position: 46.67% 37.95%;
    background-size: 195.12% 191.2%;
    box-shadow: 0 34px 44px rgba(23, 32, 51, .30), 0 2px 0 rgba(23, 32, 51, .10);
    transform-style: preserve-3d;
    transform: translate(-50%, -50%) rotateX(calc(52deg + var(--tx, 0deg))) rotateZ(var(--tz, 0deg));
    transition: transform .5s cubic-bezier(.22, 1, .36, 1);
}

.ss-coverage__marker {
    position: absolute;
    left: var(--x);
    top: var(--y);
    width: 0;
    height: 0;
    transform-style: preserve-3d;
}

.ss-coverage__marker::before {
    content: "";
    position: absolute;
    left: -7px;
    top: -4px;
    width: 14px;
    height: 8px;
    border-radius: 50%;
    background: rgba(23, 32, 51, .35);
    filter: blur(2px);
}

.ss-coverage__stand {
    position: absolute;
    left: 0;
    bottom: 0;
    transform-style: preserve-3d;
    transform: rotateX(calc(-52deg - var(--tx, 0deg)));
    transform-origin: bottom center;
}

.ss-coverage__stand::before {
    content: "";
    position: absolute;
    left: -1px;
    bottom: 0;
    width: 2px;
    height: var(--h);
    background: linear-gradient(to top, rgba(43, 55, 106, .15), var(--ss-blue));
}

.ss-coverage__pin {
    position: absolute;
    left: 50%;
    bottom: calc(var(--h) - 3px);
    padding: 5px 11px;
    border-radius: var(--ss-radius-pill);
    background: var(--ss-navy);
    color: var(--ss-paper);
    font-size: .7rem;
    font-weight: 800;
    letter-spacing: .02em;
    text-transform: uppercase;
    white-space: nowrap;
    box-shadow: 0 8px 18px rgba(23, 32, 51, .28);
    transform: translateX(-50%);
}

.ss-coverage__marker--emphasis .ss-coverage__pin {
    background: var(--ss-gold);
    color: var(--ss-navy);
}

@media (max-width: 620px) {
    .ss-coverage {
        padding: var(--ss-band-y-sm) 20px;
    }

    .ss-coverage__inner h2 {
        font-size: var(--ss-size-h2-sm);
    }
}

/* ------------------------------------------------------------------ *
 * UnitViewer3D — the midterm-rentals photo viewer
 *
 * Flat and orbit share ONE set of <figure>s. Flat lays them out as a plain
 * responsive grid; the depth layer lifts the same elements onto an orbit ring.
 * No duplicated markup, so no duplicated image downloads.
 * ------------------------------------------------------------------ */

.ss-unit {
    font-family: var(--ss-font-sans);
}

.ss-unit__eyebrow {
    display: block;
    margin-bottom: 14px;
    color: var(--ss-blue-deeper);
    font-size: var(--ss-size-eyebrow);
    font-weight: 800;
    letter-spacing: var(--ss-track-label);
    text-transform: uppercase;
}

.ss-unit__group[hidden] {
    display: none;
}

/* --- Flat: an honest responsive photo row. --- */
.ss-unit__stage {
    position: relative;
}

.ss-unit__ring {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--ss-grid-gap);
}

.ss-unit__panel {
    margin: 0;
}

.ss-unit__panel img {
    display: block;
    width: 100%;
    height: 200px;
    object-fit: cover;
    border-radius: var(--ss-radius-lg);
}

.ss-unit__panel figcaption {
    margin-top: 10px;
    color: var(--ss-navy);
    font-size: var(--ss-size-body-sm);
    font-weight: 600;
}

.ss-unit__panel figcaption span {
    display: block;
    margin-top: 4px;
    color: var(--ss-gray);
    font-weight: 500;
}

/* --- Orbit --- */
.ss-depth-on .ss-unit__stage {
    height: clamp(320px, 40vw, 460px);
    overflow: hidden;
    border-radius: var(--ss-radius-lg);
    background: var(--ss-orbit-floor);
    perspective: var(--ss-perspective);
    perspective-origin: 50% 42%;
}

/* The ring is pushed back by exactly one radius, so the front panel lands on
   the stage plane instead of in the camera's lap. */
.ss-depth-on .ss-unit__ring {
    display: block;
    position: absolute;
    inset: 0;
    gap: 0;
    transform-style: preserve-3d;
    transform: translateZ(calc(var(--radius, 0px) * -1)) rotateY(var(--ry, 0deg));
    transition: transform .72s cubic-bezier(.22, 1, .36, 1);
}

/* --panel-w, --panel-h and --radius are measured from the stage in depth.js. */
.ss-depth-on .ss-unit__panel {
    position: absolute;
    top: 50%;
    left: 50%;
    width: var(--panel-w, 320px);
    height: var(--panel-h, 210px);
    margin-top: calc(var(--panel-h, 210px) / -2);
    margin-left: calc(var(--panel-w, 320px) / -2);
    transform: rotateY(var(--angle, 0deg)) translateZ(var(--radius, 0px));
    transform-style: preserve-3d;
}

.ss-depth-on .ss-unit__panel img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border-radius: var(--ss-radius-lg);
    box-shadow: var(--ss-orbit-shadow-side);
    filter: brightness(.82) saturate(.9);
    transition: filter .6s var(--ss-ease), box-shadow .6s var(--ss-ease);
}

.ss-depth-on .ss-unit__panel.is-front img {
    box-shadow: var(--ss-orbit-shadow-front);
    filter: none;
}

/* Caption rides inside the panel, over a scrim, so the fixed-height panel box
   contains everything it needs. */
.ss-depth-on .ss-unit__panel figcaption {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    margin: 0;
    padding: 34px 18px 16px;
    border-radius: 0 0 var(--ss-radius-lg) var(--ss-radius-lg);
    background: linear-gradient(to top, rgba(17, 24, 39, .82) 0%, rgba(17, 24, 39, 0) 100%);
    color: var(--ss-white);
    font-weight: 700;
    text-align: center;
}

.ss-depth-on .ss-unit__panel figcaption span {
    color: #dfe4ee;
}

/* Orbit controls only mean something once the ring exists. */
.ss-unit__controls {
    display: none;
    justify-content: center;
    gap: 12px;
    margin-top: 18px;
}

.ss-depth-on .ss-unit__controls {
    display: flex;
}

.ss-unit__controls button {
    min-width: var(--ss-tap-min);
    min-height: var(--ss-tap-min);
    padding: 0 18px;
    border: 1px solid var(--ss-border);
    border-radius: var(--ss-radius-pill);
    background: var(--ss-white);
    color: var(--ss-navy);
    cursor: pointer;
    font-family: inherit;
    font-size: var(--ss-size-body-sm);
    font-weight: 700;
}

.ss-unit__controls button:hover {
    background: var(--ss-mist);
}

.ss-unit__controls button:focus-visible {
    outline: var(--ss-outline-focus);
    outline-offset: 2px;
}

@media (max-width: 900px) {
    .ss-unit__ring {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 560px) {
    .ss-unit__ring {
        grid-template-columns: 1fr;
    }
}

/* ------------------------------------------------------------------ *
 * ScrollScene — sections as planes in one perspective volume
 * ------------------------------------------------------------------ */

.ss-depth-on .ss-scene {
    display: block;
    perspective: var(--ss-perspective);
    perspective-origin: 50% 50%;
}

/* The design system's ScrollScene also fades the plane out as it leaves the
   middle of the viewport (fade: .35). Deliberately dropped here: at 65% opacity
   the service-tile labels measure 3.78:1 against the photos behind them, which
   fails WCAG AA. Depth and tilt carry the effect on their own; contrast stays
   at the value the design specifies. */
.ss-depth-on .ss-scene > .ss-scene__plane {
    transform-style: preserve-3d;
    will-change: transform;
    transform: translateZ(calc(var(--away, 0) * var(--scene-depth, 140) * -1px)) rotateX(calc(var(--p, 0) * var(--scene-tilt, 5) * 1deg));
}
