/*
Theme Name: Shanna Jones Photography
Theme URI: https://shannajonesphotography.com
Description: Custom child theme for shannajonesphotography.com. All site styles live in this file so they are version-controlled and deploy with the codebase, rather than sitting in the Customizer's Additional CSS (which is stored in the database).
Author: Multimedia Intelligence
Author URI: https://shannajonesphotography.com
Template: hello-elementor
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: sjp-child
*/

/* =================================
   GLOBAL STYLES
   ================================= */

html {
    scroll-behavior: smooth;
}

/* =================================
   COMMON LINK STYLES
   ================================= */

/* Remove underlines from navigation and special links */
.shana-jones-photography a,
.shanna-jones-photography-bottom a,
.header-menu-nav a,
.home-header-menu a,
.elementor-post-info__item--type-date a,
.back-to-top a,
.single-post .blog-title a,
.single-post .blog-date a {
    border-bottom: none !important;
}

/* Letter spacing adjustments */
.shana-jones-photography a {
    letter-spacing: 0.4px !important;
}

.shanna-jones-photography-bottom a {
    letter-spacing: 0.25px !important;
    position: relative;
    left: -1px;
}

/* =================================
   HEADER MENU
   ================================= */

.header-menu-close,
.header-menu-wrapper {
    display: none;
}

/* Header auto-hide.

   Elementor sets position:fixed on the header's outer container, so the
   wordmark and the MENU button sit over the page at every scroll position and
   land on top of the loop grid captions and the About block's quote.
   header-autohide.js watches scroll direction and toggles --hidden.

   Both classes are added by that script, so with JS off nothing here applies
   and the header stays exactly where Elementor put it.

   visibility, not transform alone: the MENU button's container is positioned
   absolutely 20px above the bar's own box, so translating by 100% of the bar
   leaves it poking over the top edge. It is delayed out and undelayed back in
   so the slide has time to finish before the bar stops being hit-testable.

   Deliberately no will-change: it would make the bar a containing block for
   fixed-position descendants, and .header-menu-wrapper inside is fixed. That
   is harmless while the panel is display:none, but it would quietly break a
   full-screen overlay if the menu is ever wired up. */
.sjp-header-autohide {
    transition: transform 0.35s ease, opacity 0.35s ease, visibility 0s linear 0s;
}

.sjp-header-autohide.sjp-header--hidden {
    transform: translateY(-100%);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform 0.35s ease, opacity 0.35s ease, visibility 0s linear 0.35s;
}

@media (prefers-reduced-motion: reduce) {
    .sjp-header-autohide,
    .sjp-header-autohide.sjp-header--hidden {
        transition: none;
    }
}

/* =================================
   PORTRAIT GALLERY
   ================================= */
.portrait-viewing {
    position: relative;
    overflow: hidden;
    object-fit: cover;
    cursor: pointer;
    user-select: none;
    transform: translate3d(0, 0, 0); /* Hardware acceleration */
}

.portrait-back {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 2;
    transform: scale(1);
    transition: transform 0.8s ease-in-out;
}

.portrait-front {
    position: relative;
    z-index: 3;
    display: block;
}

.portrait-title-hover {
    opacity: 0;
    transition: opacity 0.6s ease-in-out;
    pointer-events: none;
    position: absolute;
    z-index: 5;
}

.portrait-title-hover h4 {
    font-size: 16px !important;
}

/* Desktop hover effects */
@media (hover: hover) and (pointer: fine) {
    .portrait-viewing:hover .portrait-back {
        transform: scale(1.04);
    }
    
    .portrait-viewing:hover .portrait-title-hover {
        opacity: 1;
        pointer-events: auto;
    }
}

/* =================================
   RESPONSIVE LAYOUTS
   ================================= */

/* Tablet & Desktop (600px - 1800px) */
@media screen and (min-width: 600px) and (max-width: 1800px) {
    .portrait-viewing {
        max-height: 960px;
    }
    
    .home .type-post {
        max-height: 890px;
    }
}

/* Mobile (< 600px) */
@media screen and (max-width: 599px) {
    .portrait-front img {
        height: 660px !important;
        width: auto !important;
    }
    
    .portrait-title-hover {
        opacity: 1 !important;
        z-index: 10 !important;
    }
    
    .portrait-title-hover--about-sj-mobile {
        height: 650px !important;
        position: relative !important;
    }
    
    .portrait-viewing .portrait-back {
        width: auto;
        height: auto;
        position: relative !important;
        z-index: 50 !important;
        display: block !important;
        opacity: 1 !important;
        visibility: visible !important;
    }
    
    /* Footer alignment */
    .footer-special-right-text-button,
    .footer-special-right-text-button .elementor-button {
        text-align: left;
    }
}

/* Mobile/Touch devices - Simplified */
@media (hover: none) and (pointer: coarse) {
    .portrait-viewing .portrait-back {
        display: none;
        opacity: 0;
        visibility: hidden;
    }
    
    .portrait-viewing .portrait-front {
        position: relative;
        z-index: 10;
        display: block;
        opacity: 1;
    }
    
    /* The caption is a hover reveal on desktop, and a touch device never
       hovers, so on touch it simply stays on.

       It used to be hidden on any tile that had a back image. Combined with
       the rule above hiding the back, that left every photo on a touch screen
       with no title and no location, and nothing that could ever reveal them.
       Below 600px the mobile block force-shows captions, which is why phones
       looked right and only tablets, phones in landscape and desktop-site
       mode were affected.

       This also retires the :has() test and its @supports fallback: both
       existed only to pick which tiles kept a caption, and now every tile
       does. */
    .portrait-viewing .portrait-title-hover {
        opacity: 1;
        pointer-events: auto;
    }
    
    /* Optimize touch interactions */
    .portrait-viewing a {
        position: relative;
        z-index: 100;
        display: block;
        transform: translateZ(0);
    }
}

/* =================================
   HOME PAGE & GRID
   ================================= */
/* !important because Elementor generates its own gap rule for the widget
   (.elementor-NN .elementor-element-XXX .elementor-grid), which outranks a
   plain class selector and reinstates the row gap between tiles. */
.elementor-widget-loop-grid .elementor-grid {
    grid-column-gap: 0 !important;
    grid-row-gap: 0 !important;
    gap: 0 !important;
}

/* Hairline seams between tiles.
   Two separate causes, both visible on wide screens:
   1. Images are inline by default, so they sit on the text baseline and
      leave a few pixels of background below each one — the horizontal lines.
   2. Column tracks rarely divide evenly (1990 / 3 = 663.33), so the browser
      rounds each image's width down and the background shows through the
      remainder — the vertical lines. Letting the image run a pixel past its
      cell, with the cell clipping the overflow, closes the seam without
      shifting the composition. */
.elementor-loop-container.elementor-grid > .e-loop-item {
    overflow: hidden;
    /* Same rounding on the vertical axis: image heights are auto and round
       down, so rows are pulled up a pixel to overlap the remainder. */
    margin-bottom: -1px;
}

.elementor-loop-container.elementor-grid .portrait-front img,
.elementor-loop-container.elementor-grid .portrait-back img {
    display: block;
    width: calc(100% + 1px);
    max-width: none;
}

/* Blocking the image alone is not enough: these images are links, and Elementor
   wraps them in an <a> that is inline-block. That anchor then sits on the text
   baseline itself and reserves descender space under it — the same few pixels,
   moved one element up. At the 28px line-height inherited here that is a 6px
   white band under every tile, which is the visible gap between grid rows
   rather than a hairline.

   The mobile block already blocks these anchors as part of the two-up layout,
   which is why the gap only showed from 600px up. */
.elementor-loop-container.elementor-grid .portrait-front a,
.elementor-loop-container.elementor-grid .portrait-back a {
    display: block;
}

/* =================================
   BLOG
   ================================= */

.blog-header-bg {
    background-position: center !important;
    background-size: cover !important;
}

.single-post .blog-title a,
.single-post .blog-date a {
    color: #000 !important;
    font-weight: 700;
}

/* Blog post links */
[data-widget_type="text-editor.default"] a,
[data-elementor-type="single-post"] .elementor-widget-text-editor a {
    color: #000 !important;
    border-bottom: 1px solid #000;
    font-weight: 700;
    text-decoration: none;
}

/* =================================
   PORTFOLIO / LIGHTBOX
   ================================= */

.elementor-slideshow__title {
    display: none !important;
}

.elementor-lightbox .elementor-lightbox-item {
    padding: 20px !important;
}

/* =================================
   CONTACT FORM
   ================================= */

.contact-us-wp-form label {
    margin-bottom: 0 !important;
    color: #000 !important;
}

.contact-us-wp-form input {
    color: #000 !important;
    border: none !important;
    border-bottom: 1px solid #000 !important;
    border-radius: 0 !important;
    font-family: "Lato", sans-serif !important;
    font-size: 16px !important;
    padding: 0 !important;
}

.contact-us-wp-form textarea {
    border: 1px solid #000 !important;
    border-radius: 0 !important;
    margin-top: 15px !important;
    resize: none;
}

.contact-us-wp-form input:focus {
    border: 0 !important;
    border-bottom: 1px solid #000 !important;
    outline: none !important;
    box-shadow: none !important;
}

.contact-us-wp-form .wpforms-field-description {
    color: #000 !important;
    border-radius: 0 !important;
    margin-top: 10px;
}

/* Submit button */
.contact-us-wp-form-submit {
    background: none !important;
    box-shadow: none !important;
    color: #000 !important;
    padding: 0 !important;
    border-bottom: 2px solid #000 !important;
    border-radius: 0 !important;
    transition: all 0.25s ease;
}

.contact-us-wp-form-submit:hover {
    background: #000 !important;
    color: #fff !important;
    padding: 10px 16px !important;
}

/* =================================
   FOOTER
   ================================= */

.back-to-top {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
}

.back-to-top.show {
    opacity: 1;
    visibility: visible;
}

.footer-special-right-text-button,
.footer-special-right-text-button .elementor-button {
    text-align: right;
}

@media screen and (max-width: 599px) {
    /* Footer alignment */
    .footer-special-right-text-button,
    .footer-special-right-text-button .elementor-button {
        text-align: left;
    }
}

/* =================================
   LATEST STORIES GRID
   ================================= */

/* Three flex columns inside an Elementor grid container. Column 1 is a single
   700px feature image; columns 2 and 3 stack two loop grids each, with a title
   and location caption between them. Because that caption wraps to a variable
   number of lines, the stacked columns run past the feature image by however
   tall it happens to be.

   story-grid.js measures the caption and rescales each stacked column's images
   — keeping their authored 430:210 proportion — so the last image's bottom
   edge lands on the feature image's. It writes inline heights, which is what
   it takes to outrank the fixed height in Elementor's generated
   `.elementor-NNNN .elementor-element-XXXX img` rule.

   Scoped to the container's Elementor ID. Add `sjp-story-grid` under
   Advanced -> CSS Classes on that container to make the hook survive a
   rebuild, then the ID half of the selector can go.

   Images are inline by default, so they sit on the text baseline and leave a
   few pixels of descender space below each one. That space sits between the
   image the script sized and the caption below it, so the column lands short
   of the feature image by a few pixels per row. */
.sjp-story-grid .elementor-widget-theme-post-featured-image img,
.elementor-element-173ead4 .elementor-widget-theme-post-featured-image img {
    display: block;
}

/* =================================
   MOBILE TWO-COLUMN LOOP GRID
   ================================= */

/* Restored from commit 8f058cc, which "Update Repo" (033cf29) dropped.
   One deliberate change from the original: the About-block selector below
   used to be "a loop grid holding exactly one item". The Latest Stories grid
   added since is built from five single-item loop grids, so that selector now
   catches them too and would dissolve their tiles with display:contents.
   Keying off the panel's own class instead names the block it was written
   for. */

@media screen and (max-width: 599px) {

    /* ── About block ──────────────────────────────────────────
       Its own loop grid holding a single item, so a second column would
       always be empty. Instead of leaving a hole, the item's two faces —
       the photo and the black text panel that reveals on hover elsewhere —
       are split into the two cells.

       display:contents dissolves the loop item and its container so their
       children become grid cells directly. The panel keeps position:relative
       so Elementor's ::before background overlay still anchors to it. */
    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) {
        display: grid !important;
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        grid-column-gap: 0 !important;
        grid-row-gap: 0 !important;
    }

    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) > .e-loop-item,
    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) > .e-loop-item > .portrait-viewing {
        display: contents !important;
    }

    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) .portrait-front {
        aspect-ratio: 2 / 3;
        overflow: hidden;
        min-width: 0;
    }

    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) .portrait-front .elementor-widget-container,
    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) .portrait-front a {
        display: block;
        height: 100%;
    }

    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) .portrait-front img {
        width: 100% !important;
        height: 100% !important;
        object-fit: cover !important;
    }

    /* Overrides the fixed 650px height that stacked this panel under the
       photo when the layout was single-column. */
    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) .portrait-title-hover--about-sj-mobile {
        position: relative !important;
        height: auto !important;
        aspect-ratio: 2 / 3;
        min-width: 0;
        max-width: 100%;
        overflow: hidden;
        /* Set explicitly: as a grid cell this no longer sits over the photo,
           so it can't rely on Elementor's ::before overlay for its fill. */
        background-color: #000 !important;
        padding: 12px !important;
    }

    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) .portrait-title-hover--about-sj-mobile .e-con-inner {
        width: 100% !important;
        max-width: 100% !important;
    }

    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) .portrait-title-hover--about-sj-mobile .elementor-widget-theme-post-content,
    .home .elementor-loop-container.elementor-grid:has(.portrait-title-hover--about-sj-mobile) .portrait-title-hover--about-sj-mobile .elementor-widget-theme-post-content p {
        font-size: 9px !important;
        line-height: 13px !important;
        margin: 0 !important;
        overflow-wrap: anywhere;
    }

    /* Everything below is scoped to loop grids holding more than one item,
       so the About block above keeps its own treatment. */

    /* Give the widget a definite width before anything below measures itself.

       Elementor lays the top of the home page out as a wrapping row flex
       container, so this widget is a row flex item and its base size comes from
       its own content. That content is the grid below, which is sized entirely
       in fractions and ratios — minmax(0,1fr) tracks, percentage-width images,
       aspect-ratio boxes — none of which contribute anything to an intrinsic
       width measurement. The honest answer to "how wide is your content?" is
       therefore zero.

       Chromium papers over that and hands the item the container width anyway.
       WebKit takes the zero at its word, so on iOS the widget collapses to 0px,
       its tracks resolve to "0px 0px", and the entire first row of photographs
       vanishes while still occupying its space in the flow. Only this widget is
       affected: the About block is rescued by the intrinsic width of its quote
       text, and the main grid below sits in a column flex container, where
       items stretch across instead of being measured.

       A definite width takes intrinsic sizing out of the picture. Kept as
       width rather than flex-basis on purpose: width is the cross axis in a
       column container and the main axis in a row one, so it is correct in
       both, whereas flex-basis:100% would set a height in the column case.

       Scoped by :has() to the multi-item grids this section restyles, so the
       single-item Latest Stories grids keep their own sizing. */
    .home .elementor-widget-loop-grid:has(.elementor-loop-container.elementor-grid > .e-loop-item ~ .e-loop-item) {
        width: 100% !important;
        min-width: 0;
    }

    /* Two-up. minmax(0,1fr) rather than 1fr: a plain 1fr is minmax(auto,1fr),
       and the long location captions push the tracks wider than the screen. */
    .home .elementor-widget-loop-grid .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) {
        display: grid !important;
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        grid-column-gap: 0 !important;
        grid-row-gap: 0 !important;
        width: 100% !important;
        max-width: 100% !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
    }

    /* Each item claims a whole row and splits into the two cells itself, rather
       than one item per cell. Letting items flow one-per-cell would break the
       pairing: an item landing in the right column puts its second face on the
       next row. Claiming the row keeps every pair together whatever the item's
       position, and without leaving an empty cell behind. */
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item {
        grid-column: 1 / -1 !important;
        min-width: 0;
        max-width: 100%;
    }

    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item > .portrait-viewing {
        display: grid !important;
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        gap: 0 !important;
        aspect-ratio: auto !important;
        max-height: none !important;
        width: 100%;
    }

    /* The two faces of a tile — the photo and the one that reveals on hover on
       desktop — become the left and right cells. Both carry the 2:3 ratio the
       layout is built on, so a row is exactly as tall as any other.

       width/height are reset from the auto the mobile block above sets on
       .portrait-back, which was sized for the old stacked layout. */
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-front,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-back {
        position: relative !important;
        aspect-ratio: 2 / 3;
        overflow: hidden;
        min-width: 0;
        width: auto !important;
        height: auto !important;
    }

    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-front .elementor-widget-container,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-front a,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-back .elementor-widget-container,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-back a {
        display: block;
        height: 100%;
    }

    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-front img,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-back img {
        width: 100% !important;
        height: 100% !important;
        object-fit: cover !important;
    }

    /* The caption stays an overlay, pinned to the bottom of the left cell only
       rather than spanning the pair — right:50% is exactly the column boundary,
       the two tracks being equal with no gap between them.

       On the no-back tiles below the panel is a grid cell in the flow, not an
       overlay; `right` is ignored on a relatively-positioned box that already
       has `left`, so this leaves them alone.

       z-index clears the 50 the mobile block gives .portrait-back, which would
       otherwise paint over it. */
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-title-hover {
        left: 0 !important;
        right: 50% !important;
        width: auto !important;
        max-width: 100% !important;
        padding: 10px !important;
        z-index: 60 !important;
    }

    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-title-hover .e-con-inner {
        width: 100% !important;
        max-width: 100% !important;
    }

    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-title-hover .elementor-heading-title {
        font-size: 11px !important;
        line-height: 14px !important;
        white-space: normal !important;
        overflow-wrap: anywhere;
    }

    /* Testimonial and "as featured in" tiles are overlaid text, not photos,
       so they need scaling down to survive a half-width tile. */
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-title-hover .elementor-widget-theme-post-content,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-title-hover .elementor-widget-theme-post-content p,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item .portrait-title-hover .elementor-widget-theme-post-content h4 {
        font-size: 9px !important;
        line-height: 13px !important;
        margin: 0 0 3px !important;
    }

    /* ── Tiles with no second photo ───────────────────────────
       Testimonials and the special block have only one image, so there is no
       back face to fill the right cell. Their text panel takes it instead:
       photo left, black panel right. Keyed off the missing .portrait-back
       rather than the category, so the special block is covered too and no
       tile is ever left with a blank cell.

       Elementor positions this panel absolutely over the photo with top:0 and
       --min-height:100%. As a grid cell it has to sit in the flow instead. */
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item:not(:has(.portrait-back)) .portrait-title-hover {
        position: relative !important;
        top: auto !important;
        height: auto !important;
        min-height: 0 !important;
        aspect-ratio: 2 / 3;
        min-width: 0;
        max-width: 100%;
        overflow: hidden;
        /* Set explicitly: no longer sitting over the photo, so it can't rely on
           Elementor's ::before overlay for its fill. */
        background-color: #000 !important;
    }

    /* The longest quote runs past the cell at 13px leading on a 360px phone.
       Tightening it a notch lands it; the 9px body size is unchanged. */
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item:not(:has(.portrait-back)) .portrait-title-hover .elementor-widget-theme-post-content,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item:not(:has(.portrait-back)) .portrait-title-hover .elementor-widget-theme-post-content p,
    .home .elementor-loop-container.elementor-grid:has(> .e-loop-item ~ .e-loop-item) > .e-loop-item:not(:has(.portrait-back)) .portrait-title-hover .elementor-widget-theme-post-content h4 {
        line-height: 11px !important;
    }
}

/* =================================
   END OF STYLESHEET
   ================================= */