/* ---------------------------------------------------------------------------
   Home page styles.
   Moved out of the inline <style> block in Views/Home/Index.cshtml. Linked via
   the "Styles" section so it loads on the home page ONLY -- it contains a
   global .d-flex override that would affect every other page, including the
   shared header, if it were linked in _Layout directly.
   Razor required @@ to emit a literal @; in a plain stylesheet these are
   single @ again (9 were converted).
   --------------------------------------------------------------------------- */
/* Brand palette and the shared .services__one card treatment moved to
   wwwroot/css/brand.css, which is linked site-wide -- both were needed on
   /Covers and /Interiors too and could not stay in this home-only file. */
/* ---------------- Hero: featured book gallery ----------------
   A bookstore-style showcase: one large centre title flanked by two
   medium and two small covers, all standing on a shared baseline.
   Widths are custom properties so the tiers scale together per
   breakpoint without repeating the size rules. */
.bp-hero {
    /* Sequencing: covers, then headline word by word, then subtitle.
       The last cover starts at 0.57s and has finished travelling in from
       the right by 1.52s (70% of its 1.35s run); only the short downward
       settle remains after that. Starting the text at 1.4s overlaps that
       tail, so the hero reads as one continuous motion instead of two
       movements separated by a pause. */
    --bp-text-start: 1.4s;
    --bp-word-step: 90ms;
    /* headline finishes: text-start + 5 steps of stagger + one 0.7s word */
    --bp-title-end: calc(var(--bp-text-start) + 1.15s);
    background: #ffffff;
    padding: 70px 0 90px;
    /* Covers start off-screen right; clip so no horizontal scrollbar. */
    overflow: hidden;
}
/* Both are <span>, so display and type scale must be set explicitly -- an
   inline element would otherwise inherit body size. Colours follow the
   brand brief: Navy #1B2A4A for headings, Slate #6C7A94 for secondary. */
.bp-hero__title {
    display: block;
    font-family: var(--bp-display-font);
    color: var(--bp-navy);
    /* Arno Pro Display ships Regular only -- anything heavier would be a
       synthesised fake bold, which looks coarse on a display serif. Size and
       the navy carry the hierarchy instead. */
    font-weight: 400;
    /* Stepped up from clamp(2rem, 4.6vw, 3.4rem). Two reasons: the headline
       was asked to be bigger, and Cormorant's small x-height makes a given
       font-size read smaller than the sans it replaced, so part of this is
       simply holding the previous apparent size. */
    font-size: clamp(2.6rem, 6vw, 4.75rem);
    line-height: 1.08;
    /* A large Garamond needs its tracking pulled in slightly or the words
       drift apart at display size. */
    letter-spacing: -0.015em;
    margin: 0 0 18px;
}
.bp-hero__word {
    /* inline-block so each word can be transformed independently */
    display: inline-block;
    animation: bp-hero-word-in 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
    animation-delay: calc(var(--bp-text-start) + var(--bp-word-index) * var(--bp-word-step));
}
/* Subtitle comes last, once the headline has finished. Moved off AOS so
   the whole hero runs on one timeline: AOS fires on scroll position, which
   cannot be sequenced against these animations. */
.bp-hero__subtitle {
    display: block;
    font-family: var(--bp-display-font);
    /* Headline colour and weight, deliberately: the subtitle reads as the
       second line of one statement rather than as supporting text, so it
       leaves the Slate secondary colour behind. */
    color: var(--bp-navy);
    font-weight: 400;
    /* A step below the headline's clamp(2.6rem, 6vw, 4.75rem) -- roughly 55%
       of it at every breakpoint, which is enough to keep the hierarchy while
       staying clearly in the same voice. Capped so the 47-character line
       still fits on one row inside the container at desktop widths. */
    font-size: clamp(1.6rem, 3.4vw, 2.6rem);
    /* matches the headline, which needs its tracking pulled in at display size */
    letter-spacing: -0.015em;
    line-height: 1.25;
    margin: 0;
    /* linear here on purpose: the easing is set per keyframe below so the
       fall accelerates and the rebound decelerates, which a single easing
       curve across the whole animation cannot do. */
    animation: bp-hero-subtitle-drop 0.85s linear backwards;
    /* a second ahead of the headline finishing, so the two overlap */
    animation-delay: calc(var(--bp-title-end) - .5s);
}
/* Drops in from above, lands, rebounds once, then settles. */
@keyframes bp-hero-subtitle-drop {
    0% {
        opacity: 0;
        transform: translateY(-80px);
        /* gathering speed on the way down */
        animation-timing-function: cubic-bezier(0.55, 0, 1, 0.45);
    }
    /* first impact */
    50% {
        opacity: 1;
        transform: translateY(0);
        animation-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
    }
    /* the single bounce */
    72% {
        transform: translateY(-16px);
        animation-timing-function: cubic-bezier(0.55, 0, 1, 0.45);
    }
    /* settled */
    100% {
        opacity: 1;
        transform: translateY(0);
    }
}
@keyframes bp-hero-word-in {
    from {
        opacity: 0;
        transform: translateY(26px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}
@media (prefers-reduced-motion: reduce) {
    .bp-hero__word,
    .bp-hero__subtitle {
        animation: none;
    }
}
/* Gallery layout follows the reference site: cells are a percentage of the
   row, spaced with space-around, vertically centred, and each capped at
   500px. Visibility is breakpoint-driven rather than size-driven, so the
   arrangement stays symmetrical at every width. */
.bp-hero__books {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    justify-content: space-around;
    width: 100%;
    margin: 54px auto 0;
}
.bp-hero__book {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    /* gutter lives on the cell, so percentage widths still add up.
       6px on phones: at three covers across ~366px, 16px a side ate 96px
       of the row and left the inner pair too narrow to read. */
    padding-inline: 6px;
    max-width: 500px;
    /* <figure> carries a UA default margin of 1em 40px. */
    margin: 0;
    /* backwards fill shows the 0% frame during the stagger delay, then
       releases the element so :hover transforms are not overridden. */
    animation: bp-hero-book-in 1.35s cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
}
/* These target the <a> and <img> by element rather than a wrapper class.
   The markup carries no class on the anchor, so the previous
   .bp-hero__book-inner rules matched nothing -- which also cost the images
   their width:100% and left them at their intrinsic attribute width. */
.bp-hero__book a {
    position: relative;
    display: block;
    width: 100%;
    /* Lifts from the baseline rather than the middle. */
    transform-origin: bottom center;
    transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}
    /* Edge shading: a bright highlight just inside the spine and a soft
       darkening at both edges, so a flat cover reads as a physical book.
       Lives on the anchor because an <img> cannot carry ::before. */
    .bp-hero__book a::before {
        content: "";
        position: absolute;
        inset: 0;
        z-index: 2;
        pointer-events: none;
        border-radius: 4px;
        box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.1);
        background-image: linear-gradient(to right,
                rgba(0, 0, 0, 0.38) 0%,
                rgba(255, 255, 255, 0.22) 3%,
                rgba(0, 0, 0, 0.10) 5%,
                rgba(0, 0, 0, 0) 50%,
                rgba(0, 0, 0, 0) 97%,
                rgba(0, 0, 0, 0.20) 100%);
    }

/* Drop shadow, matched to the one master bakes into its banner artwork.
   Measured off Web_Cover_Book cover_1.png: on a 1357x1898 book the shadow
   reaches 43px to the LEFT and 57px BELOW, and essentially nothing above or
   right -- about 3% of the book's size each way, cast down and to the left.
   Hence the negative x offset; the old rule here was a centred 0 25px 50px.

   Scaled per tier so the outer covers, which render at roughly half the
   centre's width, do not wear a shadow built for a cover twice their size.
   The shadow sits on the <img>, not the anchor: if .bp-hero__book-inner is
   ever restored it brings overflow:hidden with it, which would clip a shadow
   painted on an inner element. */
.bp-hero__book img {
    display: block;
    width: 100%;
    height: auto;   /* original aspect ratio preserved */
    border-radius: 4px;
    --bp-book-shadow: 0.6;
    box-shadow: calc(-8px * var(--bp-book-shadow))
                calc(12px * var(--bp-book-shadow))
                calc(18px * var(--bp-book-shadow))
                rgba(0, 0, 0, 0.35);
    transition: box-shadow 0.35s ease;
}
/* Same specificity as the rule above, so these must come after it. */
.bp-hero__book--inner img  { --bp-book-shadow: 0.8; }
.bp-hero__book--center img { --bp-book-shadow: 1; }

.bp-hero__book:hover a,
.bp-hero__book:focus-within a {
    transform: translateY(-10px) scale(1.05);
}
    .bp-hero__book:hover img,
    .bp-hero__book:focus-within img {
        box-shadow: calc(-12px * var(--bp-book-shadow))
                    calc(20px * var(--bp-book-shadow))
                    calc(28px * var(--bp-book-shadow))
                    rgba(0, 0, 0, 0.42);
    }
    .bp-hero__book a:focus-visible {
        outline: 3px solid var(--bp-navy);
        outline-offset: 4px;
    }
/* --- widths and visibility, mobile first ---------------------------- */
/* Phone: the feature cover plus the inner pair -- three covers.

   The centre alone left most of the row empty. Three rather than two
   because the arrangement is symmetrical at every other width and two
   would put the feature cover off-centre; three is also the same set the
   tablet tier shows, just narrower. The outer pair stays hidden until
   1280px, where there is room for five. */
.bp-hero__book--outer {
    display: none;
}
.bp-hero__book--inner {
    display: flex;
    width: 28%;
    z-index: 2;
}
.bp-hero__book--center {
    width: 44%;
    z-index: 3;
}
/* Tablet: same three covers, but the row can afford the full gutter and a
   wider feature cover. */
@media (min-width: 768px) {
    .bp-hero__book {
        padding-inline: 16px;
    }
    .bp-hero__book--inner {
        display: flex;
        width: 25%;
        z-index: 2;
    }
    .bp-hero__book--center {
        width: 50%;
    }
}
/* Desktop: all five, centre still the widest. */
@media (min-width: 1280px) {
    /* Measured off the reference: the outer covers sit at ~43% of the centre
       and the inner pair at ~64%, putting the feature cover about 237% of the
       outer ones -- the 200-250% the design called for. Even sixths/fifths
       flattened this to 150% and the tiering stopped reading. */
    .bp-hero__book--outer {
        display: flex;
        width: 14%;
        z-index: 1;
    }
    .bp-hero__book--inner {
        width: 20%;
    }
    .bp-hero__book--center {
        width: 30%;
    }
}
/* Staggered left to right, so the row fills in as the covers arrive. */
.bp-hero__book:nth-child(1) { animation-delay: 0.05s; }
.bp-hero__book:nth-child(2) { animation-delay: 0.18s; }
.bp-hero__book:nth-child(3) { animation-delay: 0.31s; }
.bp-hero__book:nth-child(4) { animation-delay: 0.44s; }
.bp-hero__book:nth-child(5) { animation-delay: 0.57s; }
/* Two phases. First the cover travels in from completely off-screen on
   the right while held above its resting line, then it settles downward
   into place. .bp-hero clips the overflow so the off-screen start never
   produces a horizontal scrollbar. */
@keyframes bp-hero-book-in {
    0% {
        opacity: 0;
        transform: translateX(115vw) translateY(-55px);
    }
    45% {
        opacity: 1;
    }
    /* Arrived from the right, still raised. */
    70% {
        opacity: 1;
        transform: translateX(0) translateY(-55px);
    }
    /* Then drops top to bottom onto the baseline. */
    100% {
        opacity: 1;
        transform: translateX(0) translateY(0);
    }
}
@media (prefers-reduced-motion: reduce) {
    .bp-hero__book {
        animation: none;
    }
    .bp-hero__book-inner {
        transition: none;
    }
}
/* ---------------- Interiors collage ----------------
   Master's 20x15 staggered arrangement, with the gutters removed so
   adjacent tiles butt together. The empty cells are kept -- they are
   what gives the block its scattered composition. */
.parent2 {
    display: grid;
    grid-template-columns: repeat(20, 1fr);
    grid-template-rows: repeat(15, 1fr);
    grid-column-gap: 0;
    grid-row-gap: 0;
    width: 100%;
    height: auto;
    aspect-ratio: 11 / 8;
    /* shared vanishing point so every tile recedes into the same space */
    perspective: 1400px;
}

    .parent2 div {
        display: flex;
        justify-content: center;
        align-items: center;
        overflow: hidden;
    }

    .parent2 img {
        width: 100%;
        height: 100%;
        object-fit: fill;
        border-radius: 0px;
    }

.div11 { grid-area: 5 / 1 / 9 / 7; }
.div22 { grid-area: 3 / 7 / 9 / 15; }
.div33 { grid-area: 5 / 15 / 9 / 21; }
.div44 { grid-area: 9 / 5 / 14 / 12; }
.div55 { grid-area: 9 / 12 / 15 / 20; }

/* Each tile flies in from the edge it sits nearest, and from a distance:
   translateZ sets it back in space, the x/y offset gives it a direction.
   AOS supplies the scroll trigger by toggling .aos-animate, so these are
   transitions rather than keyframes -- a keyframe would fire on page load,
   long before the section is scrolled into view. */
[data-aos^="bp-in-"] {
    opacity: 0;
    transition-property: opacity, transform;
    transition-timing-function: cubic-bezier(0.16, 0.84, 0.44, 1);
}

    /* start positions, by where the tile lives in the collage */
    [data-aos="bp-in-left"]         { transform: translate3d(-140px, 0, -800px) scale(0.85); }
    [data-aos="bp-in-right"]        { transform: translate3d(140px, 0, -800px) scale(0.85); }
    [data-aos="bp-in-top"]          { transform: translate3d(0, -140px, -800px) scale(0.85); }
    [data-aos="bp-in-bottom"]       { transform: translate3d(0, 140px, -800px) scale(0.85); }
    [data-aos="bp-in-bottom-right"] { transform: translate3d(140px, 140px, -800px) scale(0.85); }

    /* all settle to the same resting state */
    [data-aos^="bp-in-"].aos-animate {
        opacity: 1;
        transform: translate3d(0, 0, 0) scale(1);
    }

@media (prefers-reduced-motion: reduce) {
    [data-aos^="bp-in-"] {
        opacity: 1;
        transform: none;
        transition: none;
    }
}

/* ---------------- Testimonials: short bold pull-quote, full review on demand ---------------- */
.bp-testimonials {
    background: var(--bp-light);
}
.bp-testimonial {
    max-width: 860px;
    margin: 0 auto;
    text-align: center;
    padding: 0 8px 8px;
}
/* Set like the Why Choose Us body copy: normal weight, body grey, body size.
   It was a bold display pull-quote at up to 32px. */
.bp-testimonial__quote {
    color: var(--bp-body);
    font-weight: 400;
    font-size: clamp(0.95rem, 1.3vw, 2.05rem);
    line-height: 1.75;
    margin-bottom: 22px;
}
.bp-testimonial__person {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
}
.bp-testimonial__avatar {
    width: 68px;
    height: 68px;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
}
.bp-testimonial__meta {
    text-align: left;
}
.bp-testimonial__name {
    color: var(--bp-navy);
    /* 400 like everything else: the family has no heavier real weight. */
    font-weight: 400;
    margin: 0;
}
.bp-testimonial__role {
    color: var(--bp-slate);
    font-size: 0.9rem;
    margin: 0;
}
/* Carousel chrome, kept in brand navy. Positioning is left to Swiper. */
/* Arrows moved down beside the pagination dots. Positioned with CSS only --
   they stay inside .swiper where Swiper manages them, because relocating
   them in the DOM previously broke the carousel. */
.bp-testimonials .swiper-button-next,
.bp-testimonials .swiper-button-prev {
    top: auto;
    bottom: 0;
    width: 24px;
    height: 24px;
    margin: 0;
    color: var(--bp-navy);
}

    /* six 9px bullets with 4px margins are about 102px wide, so 80px from
       centre clears them with a little breathing room */
    .bp-testimonials .swiper-button-prev {
        left: calc(50% - 80px);
        right: auto;
    }

    .bp-testimonials .swiper-button-next {
        right: calc(50% - 80px);
        left: auto;
    }
    /* The theme sets .swiper-button-*::after { display:none }, so Swiper's
       own glyph never paints. The buttons carry Font Awesome classes
       instead (as master does) and FA draws through ::before. */
    .bp-testimonials .swiper-button-next,
    .bp-testimonials .swiper-button-prev {
        font-size: 13px;
    }
/*  Dots and arrows share one band.

    The arrows sit in a 24px box at bottom:0 (above). This container had no rule
    at all, so it kept Swiper's bottom:10px and -- having no line-height of its
    own -- inherited the theme's fixed body line-height of 26px. The bullets are
    inline-blocks, so that 26px strut set the box height and pushed the dots to
    roughly 22px above the slider bottom while the arrows centred at 12px.

    Matching the arrows' band and centring with flex puts both on one line, and
    keeps doing so if the bullet size changes. Horizontal spacing still comes
    from Swiper's own margin: 0 4px on each bullet. */
.bp-testimonials .swiper-pagination {
    bottom: 0;
    height: 24px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bp-testimonials .swiper-pagination-bullet {
    width: 9px;
    height: 9px;
    background: var(--bp-navy);
    opacity: 0.28;
}
.bp-testimonials .swiper-pagination-bullet-active {
    opacity: 1;
}
.bp-testimonials .swiper {
    /* Room for the absolutely positioned pagination dots. */
    padding-bottom: 48px;
}
/*  A bare .d-flex override used to sit here, adding flex-wrap:wrap and a 16px
    gap to every .d-flex on the page. Removed: Bootstrap's own utilities are
    !important, so its display:flex and justify-content:center never applied
    anywhere the markup already carried .justify-content-center -- which both
    users on this page do. Only the wrap and the gap took effect, and neither
    does anything for a wrapper holding one centred button.

    What it DID reach was the header's auth list in _Layout, which carries
    .d-flex -- so on this page alone the header gained 16px gaps and wrapped
    Sign in / Sign up onto a second line. That is why the header looked
    different here from every other page. */
/* ---------------- Ebook section: fit the cover to the viewport ----------------
   Scooled_by_Rock_2.png is 1364x2276 -- a height/width ratio of 1.67. The only
   sizing it had was Bootstrap's .img-fluid, which caps WIDTH (max-width:100%)
   and leaves height:auto. At the ~555px a col-xl-6 gives it on a 1140px
   container that computes to roughly 927px tall, taller than a typical laptop
   viewport once the sticky header is accounted for -- so the bottom third of
   the cover sat below the fold and had to be scrolled to.

   Capping the height is what actually bounds it. width:auto lets the browser
   scale the width down to match, preserving the aspect ratio, so the whole
   cover is visible at any viewport height.

   The trade-off is inherent to the artwork: a 1.67-ratio image cannot be both
   full-width in a half-width column AND fully visible in a 700px viewport.
   Height wins here, because seeing the whole cover is the point. */
.bp-ebook {
    /* Shrink-wrap the image. .phone is positioned in percentages of this
       wrapper (78% wide, right:-12%), so if the wrapper stayed full-column
       width while the height cap narrowed the book, the phone would be sized
       and offset against the wrong box. */
    width: -moz-fit-content;
    width: fit-content;
    margin-inline: auto;
}

    .bp-ebook .book {
        display: block;
        width: auto;
        max-width: 100%;
        max-height: 75vh;
    }

/* Below the two-column breakpoint the artwork gets the full row, so width is
   the binding constraint and the viewport cap can relax. */
@media (max-width: 991.98px) {
    .bp-ebook .book {
        max-height: 60vh;
    }
}

.phone {
    position: absolute;
    width: 78%;
    bottom: 0;
    right: -12%;
}
.parent {
    display: grid;
    grid-template-columns: repeat(11, 1fr);
    grid-template-rows: repeat(10, 1fr);
    /* Butted together, no gutter: the collage reads as one sheet of covers. */
    grid-column-gap: 0;
    grid-row-gap: 0;
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
}
.parent div {
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden;
}
.parent img {
    width: 100%;
    height: 100%;
    object-fit: fill;
    border-radius: 0px;
}
.div1 {
    grid-area: 1 / 3 / 5 / 6;
}
.div2 {
    grid-area: 5 / 4 / 8 / 6;
}
.div3 {
    grid-area: 8 / 4 / 11 / 6;
}
.div4 {
    grid-area: 2 / 6 / 6 / 9;
}
.div5 {
    grid-area: 6 / 6 / 9 / 8;
}
.div6 {
    grid-area: 6 / 8 / 10 / 11;
}
.div7 {
    grid-area: 5 / 1 / 9 / 4;
}
.div8 {
    grid-area: 2 / 1 / 5 / 3;
}

/* ---------------------------------------------------------------------------
   Collages on small screens.

   Both grids are fixed at a large column count with a locked aspect-ratio:
   .parent is 11x10 with 8 placed tiles, .parent2 is 20x15 with 5. Neither had
   a single media query, so on a 360px phone the tiles computed to roughly
   90-100px and the artwork became texture rather than a portfolio.

   Below 768px each collapses to a two-column grid with the placements cleared,
   so the remaining images render three to four times larger. Desktop geometry
   is untouched.
   --------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
    /* --- home covers collage: 4 of the 8 -------------------------------
       The container no longer forces a square. repeat(2, 1fr) rows inside
       aspect-ratio: 1/1 made every cell square, and the artwork is 400x600
       (2:3) -- so object-fit: cover below was cropping a third of every
       cover away. Rows now size to the tiles, and the tiles carry the
       artwork's own ratio. */
    .parent {
        grid-template-columns: repeat(2, 1fr);
        grid-template-rows: auto;
        /* Butted together on mobile too -- the collage reads as one sheet. */
        gap: 0;
        aspect-ratio: auto;
    }

        /* The placements were tuned for an 11x10 grid and mean nothing here.
           2/3 is the measured ratio of all eight home-N.webp files (400x600),
           so the tile is exactly the shape of its image: the whole cover
           shows, with no crop and no letterbox to break the flush grid. */
        .parent .div1,
        .parent .div2,
        .parent .div3,
        .parent .div4 {
            grid-area: auto;
            aspect-ratio: 2 / 3;
        }

        /* Four covers read as a portfolio; eight at this width read as noise. */
        .parent .div5,
        .parent .div6,
        .parent .div7,
        .parent .div8 {
            display: none;
        }

        /* With the tile at the image's own ratio, cover, contain and fill all
           render identically. cover is kept because it is the one that cannot
           leave a hairline gap if a tile rounds to a sub-pixel height. */
        .parent img {
            object-fit: cover;
        }

    /* --- interiors collage: all 5, the last spanning both columns ------- */
    .parent2 {
        grid-template-columns: repeat(2, 1fr);
        grid-template-rows: auto;
        /* Butted together on mobile too -- the collage reads as one sheet. */
        gap: 0;
        aspect-ratio: auto;
        /* The 3D recede reads as blur at this size; the tiles are too small
           for the effect to be legible. */
        perspective: none;
    }

        .parent2 .div11,
        .parent2 .div22,
        .parent2 .div33,
        .parent2 .div44,
        .parent2 .div55 {
            grid-area: auto;
            transform: none;
            /* 500/352 is the measured ratio of collage-2..5; 3/2 was cropping
               about 5% off each. collage-1 is 500x335 and loses ~5% of its
               width instead -- unavoidable while the five files disagree, and
               far less visible than a ragged, gappy grid. */
            aspect-ratio: 500 / 352;
        }

        /* odd one out gets the full width rather than a half-empty row */
        .parent2 .div55 {
            grid-column: 1 / -1;
        }

        .parent2 img {
            object-fit: cover;
        }
}
