body{font-family: "Kumbh Sans", sans-serif;}
/*--------- Common Css ----------- */
.blog-img img,.medevents .medevents-img , .casestudies .casestudies-img, .gallery .presscard,.doccard .doccard-img img, .vm .vmimg img{
    transition: transform 0.4s ease-in-out;
}
.limit-text{
  display: inline-block;
  width: 14ch;             /* ch = character units */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle; 
}
.blog-img:hover img ,.medevents:hover .medevents-img, .casestudies:hover .casestudies-img, .gallery:hover .presscard,.doccard:hover .doccard-img img, .vm .vmimg:hover img {
    transform: scale(1.03); /* Adjust scale as needed */
}
.list-none li{    list-style: none;}
.points ul{
    padding-left: 0px;
}
.spec-body p{
    padding-left:20px;
}
.breadcrumb{
        background: linear-gradient(90deg, #FFF9ED 0%, #FFEFCB 50%, #FFF9ED 100%) !important;
}

.text-96{color:#969696 !important;}
.obj-cover{object-fit: cover !important;}
.obj-fill{object-fit: fill !important;}
.navbar-light .navbar-nav .nav-link {color: black;font-size:16px;font-weight:500;}
a.text-hover:hover{text-decoration:underline !important;}
a.text-hover-color:hover{color:#F7B32B !important;}
.text-ul{text-decoration:underline !important;}
.faq-hover:hover{background: #B8B8B8 !important;}
.ofh{overflow: hidden;}
.bg-white{background: #000;}
.bg-app {background: #F7B32B;}
.text-main {color: #F7B32B !important;}
.bg-lapp{background: #F7B32B;}
.text-appp {color: #F48C12 !important;}
.text-app2 {color: #F7B32B !important;}
.bg-darkk{background-color: #000000 !important;}
.bg-news{background: #F6F6F6;}
.bg-light1 {background: rgba(0, 0, 0, 0.04);}
.bg-greyy{background: #B8B8B8 !important;}
.text-darkk{color: #000000;}
.text-darkkk{color: #000000 !important;}
.text-grey{color: #969696;}
.text-lblue{color: #0F4DED !important;}
.text-nblue{color: #0A0CF4 !important;}
.text-app {color: #F48C12;}
.text-lightt , .text-lightt p{color:#555555 !important;}
.brs-10 {border-radius: 10px;}
.brs-15{border-radius: 15px;}
.brs-top-15{border-top-left-radius: 15px;border-top-right-radius: 15px;}
.brs-bot-15{border-bottom-left-radius: 15px;border-bottom-right-radius: 15px;box-shadow: rgba(139, 150, 153, .2) 0 5px 18px;}
.brs-bot-30{border-bottom-left-radius: 30px;border-bottom-right-radius: 30px;}
.brs-20 {border-radius: 20px;}
.brs-30 {border-radius: 30px;}
.brs-40 {border-radius: 40px;}
.brs-50{border-radius:50%;}
.pad5-7{padding: 3px 5px;}  
.lh-60{line-height: 75px;}
.fs-65{font-size: 65px;}
.sideimg {position: absolute;top: 0px;left: 0;width: 350px;}
.bg-under{background: #545454;}
.mtn-48{margin-top: -48px;}
.wid-20{width: 20px;}
.fw-100{font-weight:100;}
.fw-200{font-weight:200;}
.fw-300{font-weight:300;}
.fw-400{font-weight:400;}
.fw-500{font-weight:500;}
.fw-600{font-weight:600;}
.fw-700{font-weight:700;}
.fw-800{font-weight:800;}
.fw-900{font-weight:900;}
.btnsecondary {padding: 8px 30px;border-radius:30px !important;}
.btnprimary {padding: 12px 30px !important;border-radius:30px !important;}

/*--------- Text overflow Control Css --------- */
.overelipsis1 {display: -webkit-box;-webkit-line-clamp: 1;-webkit-box-orient: vertical;overflow: hidden;}
.overelipsis2 {display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;overflow: hidden;}
.overelipsis3 {display: -webkit-box;-webkit-line-clamp: 3;-webkit-box-orient: vertical;overflow: hidden;}
.overelipsis {display: -webkit-box;-webkit-line-clamp: 5;-webkit-box-orient: vertical;overflow: hidden;}

/*Navbar Styles*/
.navbar-nav .nav-link.active {
  color: #F7B32B !important;
}
.navbar-nav .nav-link:hover {
  color: #F7B32B !important;
}
.navbar-nav .dropdown .nav-link:hover {
    color: #F7B32B !important;
}

.navbar-nav .dropdown .nav-link.active {
    color: #F7B32B !important;
}

.top-navbar-head.activescroll {
    background: #fff;
    padding: 12px 15px !important;
    box-shadow: rgba(139, 150, 153, .2) 0 5px 18px;
}
  nav.breadcrumb{
        position: relative;
        justify-content: flex-end;
    } 
    ol.breadcrumb {
        justify-content: flex-end;
        margin: 0px;
        padding: 0px;
    }
    .bred_flex {
        display: flex;
        justify-content: space-between;
    }
    .bred_flex h1 {
        font-size: 18px;
        margin-bottom: 0px;
    }
    
/*--------- Top Menu Css ---------*/
.top_menu .float-right a i{font-size: 15px;background: #000000;border-radius: 50%;color: #F7B32B;padding: initial;width: 25px;height: 25px;text-align: center;padding-top: 5px;}

/*services*/
.service .testimoimg{width: 75px;height: 75px;border-radius: 50%;}

.service-card:hover .text-hover-color{
    color:#F7B32B !important
}
.wid-30 {
    width: 30px;
}
/*vision-mission*/
.vision-mission-card:hover .text-hover-color{
    color:#F7B32B !important
}
/*Doctors*/
.doctor-card:hover .text-hover-color{
    color:#F7B32B !important
}
.doctoricons{
    background: #000;
    margin: 0px 5px;
    color: #fff;
    width: 23px;
    height: 23px;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 13px;
}
/*Banner Section STYLES*/
.carousel-indicators li{
    border-radius: 50%;
    width: 12px;
    height: 12px;
}
.banner_txt {
    position: absolute;
    top: 505;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: #fff;
    text-align: center;
    width: 80%;
}
.banner_txt h3{
    font-size: 40px;
    font-weight: bold;
}

.banner_txt p{
    font-size: 20px;
}

a._banner_href {
    color: #fff;
    width: 100%;
    display: block;
}
  
.banner_txt h1{font-size:50px;font-size: 60px;width: 75%;font-weight: 900;}
.banner_txt p{width:75%;}


/*About Styles*/
.docimgabout{
    width: 350px;
    object-fit: cover;
    position: absolute;
    height: 400px;
    left: 40px;
    top: 35px;
}
.docimgabouthome{
     width: 350px !important;
     height: 350px !important;
}
.about_homepage div.text-lightt p{
    font-size:14px !important;
    font-weight:500 !important;
}
.whytochoosehome .choosetickbefore li{
    font-size: 18px;
    font-weight: 600;
}
.whytochoosehome .choosetickbefore p{
    font-size: 15px;
    font-weight: 300;
    line-height: 20px;
}
/*Awards Styles*/
.awards-card .card-text{
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    height: 320px;
}
.awards_homepage .post:hover p.awardtitle{
    color:#F7B32B !important;
}
/*Press Styles*/
.presscard{
    border: 3px solid #A1A0A0 !important;
    padding: 1px;
}
.presscontent{
    overflow-y: auto;
    height: 65px;
    }
/*News Styles*/
.news .post:hover .newstitle{
    color:#F7B32B ;
}
.news-information h1.font-weight-bold.mb-0 {
    font-size: 30px;
}
/*Treatments Styles*/
.treatments .treatments-card:hover h3.treattitle{
    color:#F7B32B ;
}
/*FAQ STyles*/
.faq-hover.active {
    background-color: #B8B8B8 !important; 
}
.faqsection .card-body p{
    color: #4D4D4D;
    font-size: 14px;
    font-weight: 400;
}
/*#accordion .hdng a:after {font-family:Fontawesome;content:'\f078';float:right;font-size:15px;}*/
/*#accordion .hdng a.collapsed:after {font-family:Fontawesome;content:'\f077';}*/

#accordion .hdng a:after {
    font-family: FontAwesome;
    content: '\f077'; /* up arrow — shown when expanded */
    float: right;
    font-size: 15px;
}

#accordion .hdng a.collapsed:after {
    content: '\f078'; /* down arrow — shown when collapsed */
}

#democ .carousel-indicators .active {background: #F7B32B;border: 1px solid #F7B32B;margin-top: 9px;}

.whychoosevideo{position:absolute;}
.choosetickbefore *{color:#ffffff;}
.w-250{width:250px;}
.bg-hgrey{background: #F4F4F4;}
.maskimg{position: absolute;right: 0;width: 200px;top: 0;}




/*--------- Blog Area input Css ---------*/
.blogcategory ul li.yearnum:hover p{
    color:#F7B32B !important;
}
.blogcategory ul li{border:1px solid #e9e9e9;padding:4px;}
.blogcategory ul li a:hover{color: #F7B32B;}
.blogarea h2, .blogarea h3, .blogarea h4, .blogarea h5, .blogarea h6{font-weight:bold;margin:20px 0px;}
.blogarea p{font-size:18px;}
.blogarea span{color: #000000;font-size:16px !important;}
.blogarea ul li, .blogarea ol li{font-size:18px;
/*padding: 8px 0px;line-height: 30px;*/
    
}
.blogarea img{width:100%;margin:20px 0px;border: 1px solid #dee2e6;}

/*---------Events Css --------- */
.medeventsdiv a:hover{text-decoration: none;}
.medevents{background: rgba(0, 0, 0, 0.04);cursor:pointer;height: 320px;}
.medevents:hover{background: #000000;}
.medevents p{color:#000000;}
.medevents:hover p{color:#ffffff;}
.medevents p.text-app{color:#000000;}
.medevents:hover p.text-app{color:#F7B32B;}
.venuedetails{height:45px;overflow-y:scroll;}
.medevents:hover span , .medevents:hover .title{color: #F7B32B !important;}

/*--------- Tesimonial Css --------- */
.testimoimg{width: 75px;height: 75px;border-radius: 50%;}
.paginationcss .page-link {position: relative;display: block;padding: 15px 20px;line-height: 1.25;color: #121212;background-color: #fff;border: 1px solid #dee2e6;border-radius: 50%;margin-right: 16px;}
.page-item:first-child .page-link {border-radius: 50%;}
.paginationcss  .page-item:last-child .page-link {border-radius: 50%;}
.paginationcss .page-item.active .page-link {color: #000000;background-color: #F7B32B;border-color: #dee2e6;}


/*--------- Faq's Css --------- */
.faqsection a, .faqsection .text-link {color: #3a3a3a;}
.faqsection a:hover, .faqsection .text-link:hover {text-decoration: none;}

/*--------- video Gallery Css --------- */
.video_gallery_homepage .videogallery:hover span.vidtitle{
    color:#F7B32B !important;
}
.vedioimg{position:relative;}
.videogallery{position: absolute;top: 0;bottom: 0;left: 0;right: 0;padding:15px;background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000000 100%);}
.vgallery .btnandtitle{position:absolute;bottom: 20px;}
.playbtnimg{position:absolute;left: 40%;top: 36%;width:130px;}
.playbtnimgvideo1{left: 75px;}

/*--------- Owl-Carousel Css --------- */
.owl-item a:hover{text-decoration: none;}
.owl-theme .owl-controls .owl-page span {background: #F7B32B;}
.owl-buttons{position: absolute;right: 74px;top: -70px;}
.owl-controls .owl-page, .owl-controls .owl-buttons div {cursor: pointer;background: #000000!important;width: 50px;}
.owl-controls .owl-page{background: transparent !important;width: 20px !important;}

/*--------- Contact Us and Write a Review Css ---------*/
.contactusform ::placeholder {color: #000000;font-size:18px;}
.contactusform{background: #F8FCFF;}
.contactusform .form-control{background: rgba(0, 0, 254, 0.04) !important;padding:25px 15px;border:1px solid #0A0CF4 !important;    border-radius: 7px;}
.writereview .form-control{background: transparent;padding: 25px 15px;}
.writereviewtestimonial .form-control{border: 1px solid #000000;}
.writereview .form-control::placeholder {color: #000000;}
.wreviewp{padding: 10px 10px !important;height: 52px;}
.wreviewpeople{background: rgba(0, 0, 0, 0.04);height: 240px;}
.wrpeopleimg{width: 50px;height: 50px;}
.peoplereview{height: 125px;overflow-y: auto;}
.mobilecon{width: 60px;position: absolute;left: 0px;top: -12px;}

/*--------- Social media icons Css ---------*/
.bg-fb{background: #3b5998;}
.bg-twit{background: #00acee;}
.bg-link{background: #0072b1;}
.bg-whats{background: #25D366;}

/*--------- Book Appointgment Css ---------*/
.bookappointment-text:hover .bookapptxt{
    color:#F48C12 !important;
}
.bookapmt .form-control{border: none !important;border-bottom: 1px solid #808080 !important;border-radius: 0;box-shadow: none;}
.bookapmt .form-control::placeholder{font-size:14px !important;}
.bookapmt .form-control{padding-left:0px !important;}
.appointmentimg{position: absolute;right: -100px;}
.appointmentslotscontainer label{background: #eee;border-radius: 4px;padding: 2px 8px;float: left;color: #000000;border: 1px solid #727272;}
.appointmentslotscontainer label:hover{background:#0A0CF4;color:#FFFFFF;}
.appointmentslotscontainer div{width:178px;text-align:center;position:relative;font-size: 16px;}

/*--------- Speciality's Css ---------*/
.specialtick ul{padding-left: 0px;}

/* The tick used to be `position: absolute; left: -10px`, which is what cropped
   it: pulled out of flow it had nothing to align its height against, and the
   negative offset put it outside its container's box, where any ancestor with
   `overflow: hidden` clips it. It is now an ordinary flex item in `.spec-line`
   (see about_us.php), so it sits in the flow, level with the first line of the
   text, and cannot leave its container.

   NOTE: `.spec-line` is a NEW class rather than reusing `.specialtick` for the
   wrapper — which is what the commented-out `display: flex; align-items: center`
   just above was originally reaching for. `.specialtick ul` rules exist in this
   file (here and in the `list-style: none` rule further down) and have never
   matched anything, because `.specialtick` is the <img>. Moving that class onto
   the wrapper would suddenly activate them and strip the list bullets, changing
   the current appearance. A separate class keeps this fix to alignment only. */
.spec-line{
    display: flex;
    align-items: flex-start;   /* icon stays level with the FIRST line */
    gap: 1rem;                 /* consistent icon-to-text spacing */
}
.spec-line .specialtick{
    flex: 0 0 auto;            /* never shrink — a shrunk flex item is the other
                                  way this icon gets squeezed on narrow screens */
    align-self: flex-start;
}
.spec-line .spec-body{
    flex: 1 1 auto;
    min-width: 0;              /* lets long words wrap instead of forcing overflow */
}
/* the value is admin HTML — text, or a <ul>. Collapsing the outer margins keeps
   its first line level with the icon whichever it is. */
.spec-line .spec-body > *:first-child{ margin-top: 0; }
.spec-line .spec-body > *:last-child{ margin-bottom: 0; }
.artdate{right: 0px;position: absolute;bottom: 22px;background: #F7B32B;padding: 10px 15px;}

/*--------- Gallery Css ---------*/
.albumcss{height: 100%;overflow: hidden;}
.allimgnums {position: absolute;bottom: 90px;right: 0;left: 0;color: white;font-size: 18px;font-weight: 600;background: #14131394;text-align: center;}
.albumcss:hover .allimgnums{
    display:block !important;
}
/*--------- iframe Css ---------*/
.mapvenue iframe{width:100%;}

/*--------- Submit btn Searchbar Css ---------*/
.subbtnsearch{position: absolute;right: 8px;top: 8px;border:none !important;background:transparent;z-index:1;padding:0px 12px;color:transparent;}


/*--------- Custotm style ScrollBar Css ---------*/
.cusscroll ::-webkit-scrollbar {width: 2px;}
.cusscroll ::-webkit-scrollbar-track {box-shadow: inset 0 0 5px grey; }
.cusscroll ::-webkit-scrollbar-thumb {background: #F7B32B;  border-radius: 10px;}
.cusscroll ::-webkit-scrollbar-thumb:hover {background: #b30000; }


/*--------- Contact Us Css ---------*/
.c_row {display: flex;align-items: center;}
.workhrs.c_row{display: flex;align-items: normal;}
.c_row .c_icon {min-width:50px;height: 50px;vertical-align: middle;text-align: center;background: #F7B32B;border-radius: 50%;display: flex;justify-content: center; margin-right: 0.7em;}
.c_row .c_icon i {color: #000000;font-size: 24px;}
.contdetails .c_row .c_icon{align-items: center;}

.bookappfooter .c_row{align-items: start !important;}
.bookappfooter .c_row .c_icon {min-width:0px !important;height: 0px !important;}



.choosetickbefore ul , .specialtick ul{list-style:none !important;}
.choosetickbefore ul li{color:#ffffff;position:relative;margin-top:20px;}
.choosetickbefore ul li::before {content: url('https://wellvgo.com/assets/img/tickmark.png');margin-right:15px;position:absolute;left: -40px;}
/*--------- Footer Css ---------*/
footer p.footba::before{content: "";position: absolute;width: 420px;left: 0;height: 1px;background: #575757;top: 31px;}
footer p.footba::after{content: "";position: absolute;width: 420px;right: 0;height: 1px;background: #575757;top: 31px;}
.breadcrumb {border-radius: 0px;}

/*--------- Video Popup Css ---------*/
.video-block button.close {position: absolute;z-index: 999;background: #023047;color: #fff;padding: 10px;opacity: 1;right: 0;top: 0px;}

.text-red {color: red;}
.h-280{height:310px;object-fit:cover;}
.h-250{height:250px;object-fit:cover;}

/*--------- Responsive Css ---------*/
@media (max-width: 1200px) {
footer p.footba::before{display:none;}
footer p.footba::after{display:none;}
}  

@media (max-width: 1024px) {
.top_menu{display:none;}
.appointmentimg {display: none;}
.navbar{padding:20px;box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;}
}  

@media (max-width: 768px) {
.appointmentslotscontainer div {width: 250px;} 
.bookappempire{-ms-flex: 0 0 100%;flex: 0 0 100%;max-width: 100%;}
}

@media (max-width: 767px) {
/*COMMON CODE*/
.mob-d-flex{display:flex !important;}
.mob-flex-col{flex-direction:column !important;}
.mob-border-none{border:none !important;}
.mob-text-center{text-align:center !important;}
.height-auto{height:auto !important;}
.mobpx-0{padding-left: 0px !important;padding-right: 0px !important;}
.mobd-none{display:none !important;}
.mobp-static{position: static !important;}
.mobpl-15{padding-left: 15px !important;}
.mobpl-0{padding-left: 0px !important;}
.mobpr-15{padding-right: 15px !important;}
.mobpx-15{padding-left: 15px !important;padding-right: 15px !important;}
.mobpx-0{padding-left: 0px !important;padding-right: 0px !important;}
.mobmx-0{margin-left: 0px !important;margin-right: 0px !important;}
.mobmr-15{margin-right: 15px !important;}
.mobtext-center{text-align: center !important;}
.mobw-100{width: 100% !important;}
.mobmy-5px{margin: 5px 0px !important;}   
.mobfs-24{font-size: 24px !important;}
.moblh-3{line-height: 3;}
.mobtext-right{text-align:right !important;}
.mobjustify-right{justify-content:end !important;}
.file-upload-input {
    width: 200px !important;
}
.btnprimary {
    padding: 8px 22px !important;
    font-size: 14px;
}
.bred_flex {flex-direction: column;}
.banner_txt h1 {
    font-size: 24px;
    width: 100%;
}
.docimgabouthome{
    position: static;
}
.medevents{height: auto;}
.whychoosevideo{position:relative !important;}
/*casestudies*/
.casestudies_homepage  .owl-buttons{
    display:none;
}


} 


@media (max-width: 450px) {
.fs-65{font-size:40px !important;}
.fs-40{font-size:35px !important;}
.w-75{width:100% !important;}
.playbtnimg {width: 80px;}
.sideimg {display:none;}
.centext{text-align:center;}
.py-5{padding-top:10px !important; padding-bottom:10px !important;}
.pt-5{padding-top:10px !important;}
.owl-buttons {right: -4px;top: -38px;}
#testimonials_slider .owl-buttons {top: 0px;position: relative;}
.pt-3{padding-top: 0.5rem!important;}
.lh-60 {line-height: 52px;}
.mr-20{margin-right:0px !important;}
.w-250{width:200px;}
.navbar-brand.fs-30{font-size:26px !important;}
}  

@media (max-width: 375px) {
.navbar-brand.fs-30{font-size:20px !important;}
.fs-50 {font-size: 35px !important;}
.fs-40 {font-size: 28px !important;}
}  

@media (max-width: 325px) {
.docimgabout {width: 285px;height: 285px;}
.navbar-brand.fs-30{font-size:16px !important;}
}

/* ===========================================================================
   Header entrance animations + hover effects (animation-only, additive).
   Elegant fade + slide-down for the top bar and navbar on page load, with a
   subtle staggered reveal of the brand, menu items and contact/social items,
   plus motion-based hover effects. No colors, layout, structure or
   functionality are changed — only animation and hover motion is added.
   =========================================================================== */
@keyframes hdrDrop{
    from{ opacity: 0; transform: translateY(-34px); }
    to{   opacity: 1; transform: translateY(0); }
}
@keyframes hdrItemIn{
    from{ opacity: 0; transform: translateY(-12px); }
    to{   opacity: 1; transform: translateY(0); }
}

/* entrance: top bar drops in first, navbar follows with a slight delay */
.top_menu{ animation: hdrDrop .7s cubic-bezier(.22,.61,.36,1) backwards; }
nav.top-navbar-head{ animation: hdrDrop .85s cubic-bezier(.22,.61,.36,1) .1s backwards; }

/* entrance: brand + menu items + top-bar items cascade in (subtle stagger) */
.top-navbar-head .navbar-brand{ animation: hdrItemIn .6s ease .3s backwards; }
.top-navbar-head .navbar-nav > .nav-item{ animation: hdrItemIn .55s ease backwards; }
.top-navbar-head .navbar-nav > .nav-item:nth-child(1){ animation-delay: .38s; }
.top-navbar-head .navbar-nav > .nav-item:nth-child(2){ animation-delay: .45s; }
.top-navbar-head .navbar-nav > .nav-item:nth-child(3){ animation-delay: .52s; }
.top-navbar-head .navbar-nav > .nav-item:nth-child(4){ animation-delay: .59s; }
.top-navbar-head .navbar-nav > .nav-item:nth-child(5){ animation-delay: .66s; }
.top-navbar-head .navbar-nav > .nav-item:nth-child(6){ animation-delay: .73s; }
.top-navbar-head .navbar-nav > .nav-item:nth-child(7){ animation-delay: .80s; }
.top-navbar-head .navbar-nav > .nav-item:nth-child(n+8){ animation-delay: .87s; }
.top_menu .top_left li{ animation: hdrItemIn .5s ease .35s backwards; }
.top_menu .top_right li{ animation: hdrItemIn .5s ease .45s backwards; }

/* hover effects — motion only (existing colors kept exactly as they are) */
.top-navbar-head .navbar-nav > .nav-item > .nav-link{ transition: color .3s ease, transform .3s ease; }
.top-navbar-head .navbar-nav > .nav-item > .nav-link:hover{ transform: translateY(-2px); }
.top-navbar-head .navbar-brand{ transition: transform .35s ease; }
.top-navbar-head .navbar-brand:hover{ transform: scale(1.03); }
.top_menu .top_left a{ transition: opacity .3s ease; }
.top_menu .top_left a:hover{ opacity: .8; }
.top_menu .top_left a i{ transition: transform .3s ease; }
.top_menu .top_left a:hover i{ transform: translateY(-1px) scale(1.1); }
.top_menu .top_right a i{ transition: transform .35s cubic-bezier(.34,1.56,.64,1); }
.top_menu .top_right a:hover i{ transform: translateY(-2px) scale(1.1); }

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .top_menu, nav.top-navbar-head, .top-navbar-head .navbar-brand,
    .top-navbar-head .navbar-nav > .nav-item,
    .top_menu .top_left li, .top_menu .top_right li{ animation: none !important; }
}

/* ===========================================================================
   Hero / banner (animation-only, additive).

   The headline is revealed as ONE element, by a left-to-right wipe (clip-path)
   with a short fade. It is deliberately NOT split into words or characters:
   per-letter spans disable kerning between glyphs — which changes the effective
   letter-spacing — and they were the cause of the overlapping-headline
   regression. Left whole, the font, size, weight, line-height, letter-spacing,
   wrapping and final position are all exactly what the design specifies; the
   wipe only controls how much of it is painted, so the text is readable and
   stable from the first frame to the last.

   Around it: the photograph drifts the whole time its slide is up (alternate
   slides push in and pull out), the subheading resolves out of a soft blur, the
   buttons rise as a group and light up one after the other, and once the copy
   has arrived the whole block settles into a slow drift that returns to its
   exact original position every cycle. The sequence replays on every slide
   change, and the incoming slide starts while it is still travelling so the
   copy builds as the picture lands.

   No colors, typography, spacing, layout, content or functionality change.
   Every delay is a fixed value in CSS — nothing is measured and no text is
   touched — so there is nothing that can fall out of step. With JS off or
   reduced-motion on, every slide renders exactly as designed.
   =========================================================================== */
/* alternate slides push in / pull out, so a long rotation never feels repetitive */
@keyframes bnrKenA{
    from{ transform: scale(1)    translate3d(0,0,0); }
    to  { transform: scale(1.12) translate3d(-1.8%,-1.2%,0); }
}
@keyframes bnrKenB{
    from{ transform: scale(1.12) translate3d(1.8%,1.2%,0); }
    to  { transform: scale(1)    translate3d(0,0,0); }
}
/* The headline is uncovered left to right — the same progressive feel as typing,
   but the text itself is never touched, so it cannot reflow or overlap. The
   insets end NEGATIVE, so at rest the clip region sits outside the element and
   nothing can ever be shaved off a glyph. */
@keyframes bnrHeadIn{
    from{ opacity: 0; clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { opacity: 1; clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* Once the copy has arrived the whole text block settles into a slow drift, so
   the hero keeps breathing instead of freezing. The -50%/-50% is .banner_txt's
   own existing centring transform, carried through every keyframe so the block
   sits exactly where the design puts it and returns there each cycle. */
@keyframes bnrDrift{
    0%,100%{ transform: translate(-50%, -50%); }
    50%    { transform: translate(-50%, calc(-50% - 6px)); }
}
/* the subheading resolves out of a soft blur rather than just sliding up */
@keyframes bnrTextUp{
    from{ opacity: 0; transform: translateY(26px); filter: blur(9px); }
    to  { opacity: 1; transform: translateY(0);    filter: blur(0); }
}
/* the group carries the movement and each button carries its own fade, so the
   buttons' own `transform` stays free for the hover lift */
@keyframes bnrBtnGroup{ from{ transform: translateY(16px) scale(.94); } to{ transform: translateY(0) scale(1); } }
@keyframes bnrBtnFade{  from{ opacity: 0; } to{ opacity: 1; } }
/* the indicator that just became active pops once and settles back — it ends
   where it started, so the dots look exactly as designed at rest */
@keyframes bnrDot{ 0%{ transform: scale(1); } 45%{ transform: scale(1.45); } 100%{ transform: scale(1); } }

/* --- LAYERING. The copy must sit above the photograph on every slide. The
       picture's Ken Burns transform makes it a stacking context of its own, so
       rather than trusting that to land below the copy by accident, the two are
       ordered explicitly. `position: relative` with no offsets moves nothing.

       The overlay tint (`.overlay_N::before`, built per slide in index.php) is
       deliberately left alone: it is generated as the carousel item's first child
       with `z-index: auto`, so it already paints behind the picture today. Giving
       the picture `z-index: 1` keeps that exactly as it is — raising the overlay
       instead would make a coloured wash appear over every banner, which is a
       design change nobody asked for. */
#demo .carousel-item{ position: relative; }
#demo .banner_slider{ position: relative; z-index: 1; }
#demo .banner_txt{ position: absolute; z-index: 3; }

/* --- NO PRE-HIDE. This is the fix for "the copy is missing on every slide but
       the first".

       There used to be a standing `opacity: 0` here on the headline, subheading
       and buttons, applied to EVERY slide the moment `.bnr-js` went on. Only the
       slide carrying `.bnr-live` was ever given an animation to undo it, and
       `.bnr-live` is added by JS off Bootstrap's carousel events. So visibility
       depended entirely on that wiring succeeding: any slide that did not receive
       the class — because the events had not bound, or because the slide was
       still `display: none` when the event fired and so never ran its animation —
       kept `opacity: 0` for good. The copy was not behind the image; it was
       transparent.

       So the hidden starting state now comes ONLY from each reveal's own
       `from` keyframe via `animation-fill-mode: both`, which holds it through the
       animation's delay. Every keyframe involved starts at `opacity: 0`
       (bnrHeadIn, bnrTextUp, bnrBtnFade), so the entrance looks identical — but a
       slide with no animation running is now simply VISIBLE, which is the safe
       default. There is no longer any state in which the copy can be stranded
       invisible, and no hover, class or event is needed to make it appear. */

/* --- the live slide plays. Every delay is a fixed value, so a long or a short
       headline can never put the sequence out of step.

       TIMING, tightened: this sequence used to run to 2.10s (headline landing at
       1.40s, subheading 2.00s, buttons 2.10s). On a first load that is long
       enough that the hero still looked like it was assembling after the nav and
       the next section were already up — the banner read as arriving late even
       once its picture was there. The same choreography, in the same order, now
       finishes at 1.15s, with the headline — the part that matters — essentially
       there by 0.76s. Nothing about the gestures themselves changed. */
#demo.bnr-js .carousel-item.bnr-live .banner_txt h1{ animation: bnrHeadIn .70s cubic-bezier(.22,.61,.36,1) .06s both; }
#demo.bnr-js .carousel-item.bnr-live .banner_txt p{ animation: bnrTextUp .50s cubic-bezier(.22,.61,.36,1) .40s both; }
#demo.bnr-js .carousel-item.bnr-live .banner_txt .buttons{ animation: bnrBtnGroup .55s cubic-bezier(.34,1.56,.64,1) .60s both; }
#demo.bnr-js .carousel-item.bnr-live .banner_txt .buttons .btn{ animation: bnrBtnFade .40s ease .60s both; }
#demo.bnr-js .carousel-item.bnr-live .banner_txt .buttons .btn:nth-child(2){ animation-delay: .70s; }
/* the slow drift takes over once everything has landed */
#demo.bnr-js .carousel-item.bnr-live .banner_txt{ animation: bnrDrift 5.5s ease-in-out 1.25s infinite; }
/* 6.5s against Bootstrap's 5s interval, so the slide always changes before the
   drift can reach its end and freeze */
#demo.bnr-js .carousel-item.bnr-live .banner_slider img{ animation: bnrKenA 6.5s ease-out both; }
#demo.bnr-js .carousel-item:nth-child(even).bnr-live .banner_slider img{ animation-name: bnrKenB; }
#demo.bnr-js .carousel-indicators li.active{ animation: bnrDot .55s cubic-bezier(.34,1.56,.64,1); }

/* --- controls + indicators: motion only, existing colours untouched */
#demo .carousel-indicators li{ transition: transform .35s cubic-bezier(.34,1.56,.64,1); }
#demo .carousel-indicators li:hover{ transform: scale(1.25); }
#demo .carousel-control-prev-icon,
#demo .carousel-control-next-icon{ transition: transform .3s cubic-bezier(.34,1.56,.64,1); }
#demo .carousel-control-prev:hover .carousel-control-prev-icon{ transform: translateX(-4px) scale(1.12); }
#demo .carousel-control-next:hover .carousel-control-next-icon{ transform: translateX(4px) scale(1.12); }

/* gentle hover on the hero buttons — motion only (existing colors kept) */
#demo .banner_txt .buttons .btn{ transition: transform .3s ease, box-shadow .3s ease; }
#demo .banner_txt .buttons .btn:hover{ transform: translateY(-3px); }

@media (prefers-reduced-motion: reduce){
    #demo.bnr-js .banner_txt h1,
    #demo.bnr-js .banner_txt p,
    #demo.bnr-js .banner_txt .buttons,
    #demo.bnr-js .banner_txt .buttons .btn{ opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; animation: none !important; }
    #demo.bnr-js .carousel-item.bnr-live .banner_txt{ animation: none !important; }
    #demo.bnr-js .carousel-item.bnr-live .banner_slider img{ animation: none !important; }
    #demo.bnr-js .carousel-indicators li.active{ animation: none !important; }
    #demo .carousel-indicators li,
    #demo .carousel-control-prev-icon,
    #demo .carousel-control-next-icon{ transition: none !important; transform: none !important; }
}

/* ===========================================================================
   About Us section — scroll-reveal entrance, statistics count-up + hover.
   Animation-only, additive; classes are toggled by a small self-contained
   script (with graceful fallback). No colors, spacing, typography, layout,
   content or functionality are changed.
   =========================================================================== */
@keyframes abFadeUp{ from{ opacity: 0; transform: translateY(28px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes abZoomIn{ from{ opacity: 0; transform: scale(.95); } to{ opacity: 1; transform: scale(1); } }

/* pre-hide (only while the script drives the reveal — shows normally if JS is off).
   NOTE: the statistics block — h3.centext and .row.centext .col-md-4 — is
   deliberately absent from this animation layer. It carries no opacity, no
   transform, no transition and no hover from here, so its alignment, spacing and
   responsive behaviour are exactly as designed. Its only animation is the
   count-up, which is pure text and touches no layout. */
.about_homepage.about-js .docimgabouthome,
.about_homepage.about-js h3.text-app2,
.about_homepage.about-js h2,
.about_homepage.about-js .text-lightt,
.about_homepage.about-js .mb-30.fs-18,
.about_homepage.about-js .mb-30.fs-18 ul li,
.about_homepage.about-js .col-md-7 .mobtext-center{ opacity: 0; }

/* staggered reveal when the section scrolls into view */
.about_homepage.about-inview .docimgabouthome{ animation: abZoomIn .9s cubic-bezier(.22,.61,.36,1) forwards; }
.about_homepage.about-inview h3.text-app2{ animation: abFadeUp .7s ease .15s forwards; }
.about_homepage.about-inview h2{ animation: abFadeUp .75s cubic-bezier(.22,.61,.36,1) .28s forwards; }
.about_homepage.about-inview .text-lightt{ animation: abFadeUp .75s ease .42s forwards; }
.about_homepage.about-inview .mb-30.fs-18{ animation: abFadeUp .75s ease .52s forwards; }
.about_homepage.about-inview .mb-30.fs-18 ul li{ animation: abFadeUp .55s ease forwards; }
.about_homepage.about-inview .mb-30.fs-18 ul li:nth-child(1){ animation-delay: .64s; }
.about_homepage.about-inview .mb-30.fs-18 ul li:nth-child(2){ animation-delay: .74s; }
.about_homepage.about-inview .mb-30.fs-18 ul li:nth-child(3){ animation-delay: .84s; }
.about_homepage.about-inview .mb-30.fs-18 ul li:nth-child(4){ animation-delay: .94s; }
.about_homepage.about-inview .mb-30.fs-18 ul li:nth-child(n+5){ animation-delay: 1.04s; }
.about_homepage.about-inview .col-md-7 .mobtext-center{ animation: abFadeUp .6s ease 1.0s forwards; }

/* hover effects — motion only (existing colors/design untouched) */
.about_homepage .docimgabouthome{ transition: transform .5s ease; }
.about_homepage .docimgabouthome:hover{ transform: scale(1.04); }
.about_homepage .mb-30.fs-18 ul li{ transition: transform .3s ease; }
.about_homepage .mb-30.fs-18 ul li:hover{ transform: translateX(6px); }

/* ===========================================================================
   Why to Choose section — premium entrance sequence + hover interactions.

   Animation-only and additive. Every reveal class is toggled by a
   self-contained script, so with JS off (or reduced-motion on) the section
   renders exactly as designed. No colors, spacing, typography, layout,
   content or functionality are changed — the aurora glow, light sweep, icon
   ripple and hover bloom are all neutral white at very low alpha, so they add
   light rather than hue and leave the finalised palette intact.

   Sequence (~2.5s): the two halves open like a shutter — the artwork uncovered
   from its left edge, the panel from its right edge, the two fronts meeting in
   the middle (.85s) -> a light sweep crosses the artwork -> the label rises ->
   the heading is uncovered left-to-right AS ONE ELEMENT -> description blocks
   rise -> feature rows slide in from the left, each tick popping with a ring
   pulsing out behind it -> the artwork and the corner graphic begin to drift.
   Per-element delays are assigned by the script, so any number of paragraphs or
   feature rows stays in step.

   Both columns are clipped, never transformed, for the entrance. A transform on
   the media column would make it the containing block for the video lightbox
   inside it — a fixed-position element that must stay anchored to the viewport.

   The heading is deliberately not split into words or letters: per-word and
   per-letter spans change line-breaking and disable kerning, which alters the
   effective letter-spacing. Left whole, its typography and wrapping are
   untouched and only the amount painted is animated.
   =========================================================================== */

/* registered so the hover scale can still transition smoothly while the
   floating keyframes own `transform` (degrades to an instant scale change
   where @property is unsupported) */
@property --wc-sc{ syntax: '<number>'; initial-value: 1; inherits: false; }
@property --wc-px{ syntax: '<length>'; initial-value: 0px; inherits: false; }
@property --wc-py{ syntax: '<length>'; initial-value: 0px; inherits: false; }

@keyframes wcFadeUp{ from{ opacity: 0; transform: translateY(24px); } to{ opacity: 1; transform: translateY(0); } }
/* The two halves open like a shutter: the artwork is uncovered from its left
   edge while the panel is uncovered from its right edge, so the two reveal
   fronts travel toward each other and meet in the middle. Clip only — no
   transform on either column, which keeps the video lightbox (a fixed-position
   child of the media column) anchored to the viewport as it should be. The
   insets end NEGATIVE so nothing is clipped at rest. */
@keyframes wcRevealL{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
@keyframes wcRevealR{
    from{ clip-path: inset(-.2em -.2em -.2em 100%); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the heading is uncovered left to right, as one element */
@keyframes wcHeadIn{
    from{ opacity: 0; clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { opacity: 1; clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* feature rows arrive from the left, in the direction their tick points */
@keyframes wcSlideIn{
    from{ opacity: 0; transform: translateX(-20px); }
    to  { opacity: 1; transform: translateX(0); }
}
/* each tick lands with a ring pulsing out behind it. The ring is box-shadow, so
   it costs no layout, and it ends fully transparent leaving nothing behind. */
@keyframes wcPop{
    0%  { opacity: 0; transform: scale(0)    rotate(-30deg); box-shadow: 0 0 0 0    rgba(255,255,255,.45); }
    60% { opacity: 1; transform: scale(1.18) rotate(6deg);   box-shadow: 0 0 0 9px  rgba(255,255,255,.16); }
    100%{ opacity: 1; transform: scale(1)    rotate(0deg);   box-shadow: 0 0 0 18px rgba(255,255,255,0); }
}
/* the decorative corner graphic drifts, so the panel is never completely still */
@keyframes wcMask{
    0%,100%{ transform: translate3d(0,0,0); }
    50%    { transform: translate3d(-9px,7px,0); }
}
@keyframes wcSweep{
    0%  { opacity: 0; transform: translateX(-130%) skewX(-18deg); }
    15% { opacity: 1; }
    85% { opacity: 1; }
    100%{ opacity: 0; transform: translateX(240%) skewX(-18deg); }
}
@keyframes wcGlowDrift{ from{ background-position: 16% 22%; } to{ background-position: 76% 72%; } }
@keyframes wcFloat{
    0%,100%{ transform: translate3d(var(--wc-px,0px), calc(var(--wc-py,0px) - 5px), 0) scale(var(--wc-sc,1)); }
    50%    { transform: translate3d(var(--wc-px,0px), calc(var(--wc-py,0px) + 5px), 0) scale(var(--wc-sc,1)); }
}
@keyframes wcRipple{ from{ opacity: .5; transform: scale(.5); } to{ opacity: 0; transform: scale(2.6); } }

/* --- aurora glow: a slow white bloom drifting behind the copy. Layered as a
       background-IMAGE so the panel's background-COLOR stays exactly as set. */
.whytochoosehome.wc-glow .col-md-6.bg-darkk{
    background-image: radial-gradient(42% 48% at 30% 32%, rgba(255,255,255,.11), rgba(255,255,255,0) 70%);
    background-repeat: no-repeat;
    background-size: 165% 165%;
    animation: wcGlowDrift 12s ease-in-out infinite alternate;
}

/* --- pre-hide, only while the script drives the reveal.
       The two columns are pre-CLIPPED rather than faded, so the copy inside them
       is never dimmed by a parent's opacity as it reveals. The .choosetickbefore
       wrapper and its <ul> are deliberately NOT hidden either: fading a parent
       would group its children and cancel their individual stagger.
       Note: while .wc-inview is on, the reveal below wins the `animation`
       property on the panel over the glow rule above (same specificity, later in
       source), so the bloom is present but still until the shutter has finished
       and the class is dropped. That ordering is intentional. */
.whytochoosehome.wc-js .col-md-6.p-0{ clip-path: inset(-.2em 100% -.2em -.2em); }
.whytochoosehome.wc-js .col-md-6.bg-darkk{ clip-path: inset(-.2em -.2em -.2em 100%); }
.whytochoosehome.wc-js .bg-darkk h3,
.whytochoosehome.wc-js .bg-darkk p.text-app,
.whytochoosehome.wc-js .choosetickbefore > p,
.whytochoosehome.wc-js .choosetickbefore ul li{ opacity: 0; }
.whytochoosehome.wc-js .choosetickbefore ul li::before{ opacity: 0; transform: scale(0); }

/* --- staggered reveal (per-element delays are set by the script) */
.whytochoosehome.wc-inview .col-md-6.p-0{ animation: wcRevealL .85s cubic-bezier(.65,0,.35,1) forwards; }
.whytochoosehome.wc-inview .col-md-6.bg-darkk{ animation: wcRevealR .85s cubic-bezier(.65,0,.35,1) forwards; }
.whytochoosehome.wc-inview .bg-darkk h3{ animation: wcFadeUp .7s ease .55s forwards; }
.whytochoosehome.wc-inview .bg-darkk p.text-app{ animation: wcHeadIn .9s cubic-bezier(.22,.61,.36,1) .7s forwards; }
.whytochoosehome.wc-inview .choosetickbefore > p{ animation: wcFadeUp .65s ease forwards; }
.whytochoosehome.wc-inview .choosetickbefore ul li{ animation: wcSlideIn .55s cubic-bezier(.22,.61,.36,1) forwards; }
.whytochoosehome.wc-inview .choosetickbefore ul li::before{ animation: wcPop .55s cubic-bezier(.34,1.56,.64,1) var(--wc-icon-d, 0s) forwards; }
/* the corner graphic drifts once the section has settled */
.whytochoosehome.wc-float .maskimg{ animation: wcMask 14s ease-in-out infinite; }

/* --- media column: one-time light sweep, hover bloom, hover zoom, float */
.whytochoosehome .col-md-6.p-0{ overflow: hidden; }
/* ::after = the sweep, ::before = the hover bloom. Both sit above the image and
   ignore pointer events, so the video play link keeps working untouched. */
.whytochoosehome .col-md-6.p-0::after{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 40%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.30), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
/* the sweep waits for the shutter to finish, otherwise it would be crossing a
   column that is still being uncovered */
.whytochoosehome.wc-inview .col-md-6.p-0::after{ animation: wcSweep 1.5s cubic-bezier(.4,0,.2,1) .95s forwards; }
.whytochoosehome .col-md-6.p-0::before{
    content: '';
    position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 3;
    box-shadow: inset 0 0 70px rgba(255,255,255,.16);
    opacity: 0; pointer-events: none; transition: opacity .45s ease;
}
.whytochoosehome .col-md-6.p-0:hover::before{ opacity: 1; }
.whytochoosehome .col-md-6.p-0 > img,
.whytochoosehome .col-md-6.p-0 .whychoosevideo{
    transform: translate3d(var(--wc-px,0px), var(--wc-py,0px), 0) scale(var(--wc-sc,1));
    transition: transform .35s ease, --wc-sc .45s ease;
    will-change: transform;
}
.whytochoosehome.wc-float .col-md-6.p-0 > img,
.whytochoosehome.wc-float .col-md-6.p-0 .whychoosevideo{ animation: wcFloat 6.5s ease-in-out infinite; }
.whytochoosehome .col-md-6.p-0:hover > img,
.whytochoosehome .col-md-6.p-0:hover .whychoosevideo{ --wc-sc: 1.05; }
/* video variant: the play button swells slightly with the artwork */
.whytochoosehome .col-md-6.p-0 .playbtnimg{ transition: transform .4s cubic-bezier(.34,1.56,.64,1); }
.whytochoosehome .col-md-6.p-0:hover .playbtnimg{ transform: scale(1.12); }

/* --- feature rows: hover slide with a micro-bounce, icon tilt, soft ripple */
.whytochoosehome .choosetickbefore ul li{ transition: transform .38s cubic-bezier(.34,1.56,.64,1); }
.whytochoosehome .choosetickbefore ul li:hover{ transform: translateX(8px); }
/* border-radius shapes the entrance ring pulse into a circle. The pseudo-element
   has no background or border of its own, only the tick image, so this changes
   nothing that is visible at rest. */
.whytochoosehome .choosetickbefore ul li::before{
    z-index: 1; border-radius: 50%;
    transition: transform .35s cubic-bezier(.34,1.56,.64,1);
}
.whytochoosehome .choosetickbefore ul li:hover::before{ transform: scale(1.15) rotate(8deg); }
.whytochoosehome .choosetickbefore ul li::after{
    content: '';
    position: absolute; left: -40px; top: 0; z-index: 0;
    width: 30px; height: 30px; margin: -3px 0 0 -3px;
    border-radius: 50%; opacity: 0; pointer-events: none;
    background: radial-gradient(circle, rgba(255,255,255,.5), rgba(255,255,255,0) 70%);
}
.whytochoosehome .choosetickbefore ul li:hover::after{ animation: wcRipple .9s ease-out; }

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .whytochoosehome .col-md-6.p-0,
    .whytochoosehome .col-md-6.bg-darkk,
    .whytochoosehome .bg-darkk h3,
    .whytochoosehome .bg-darkk p.text-app,
    .whytochoosehome .choosetickbefore > p,
    .whytochoosehome .choosetickbefore ul li{ opacity: 1 !important; transform: none !important; clip-path: none !important; animation: none !important; }
    .whytochoosehome .choosetickbefore ul li::before{ opacity: 1 !important; transform: none !important; box-shadow: none !important; animation: none !important; }
    .whytochoosehome .choosetickbefore ul li::after,
    .whytochoosehome .col-md-6.p-0::after,
    .whytochoosehome .col-md-6.p-0::before{ opacity: 0 !important; animation: none !important; }
    .whytochoosehome.wc-glow .col-md-6.bg-darkk{ animation: none !important; }
    .whytochoosehome .maskimg,
    .whytochoosehome .col-md-6.p-0 .playbtnimg,
    .whytochoosehome .col-md-6.p-0 > img,
    .whytochoosehome .col-md-6.p-0 .whychoosevideo{ transform: none !important; animation: none !important; transition: none !important; }
}

/* ===========================================================================
   Blogs section (home) — premium entrance sequence + hover interactions.

   Animation-only and additive. The reveal classes are toggled by a small
   self-contained script placed right after the section (same pattern as the
   About / Why to Choose sections), and both classes are dropped once the
   sequence finishes so the hover transforms take over cleanly. With JS off or
   reduced-motion on, the section renders exactly as designed.

   Nothing here changes colors, typography, spacing, layout, card sizes,
   markup or behaviour: the light sweep and the reflection are neutral white at
   low alpha, and only transform / opacity / clip-path / filter are animated.

   Entrance: section fades up -> the heading is uncovered left-to-right ->
   "View All" slides in from the right -> cards reveal one by one (120ms
   apart), and each card then assembles itself like an article opening: the
   artwork is drawn in from the left, the headline is typeset after it, then
   the body copy and the Read more button settle in underneath.
   Idle: one on-screen card's artwork breathes 2px every 8-10s.

   Hover is deliberately limited to the artwork. Hovering .blog-img lifts and
   lights the image and drifts a soft reflection across it; the title,
   description and Read more button underneath never react, and the card
   itself does not lift. Moving the cursor over the copy does nothing at all.
   =========================================================================== */
@keyframes blSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes blViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes blCardUp{    from{ opacity: 0; transform: translateY(35px); } to{ opacity: 1; transform: translateY(0); } }
/* The heading is uncovered left-to-right. Letter-spacing is deliberately NOT
   animated — that would both alter the typography and force a reflow. The insets
   end negative, so at rest the clip sits outside the element and no glyph can be
   shaved. */
@keyframes blHeadReveal{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
@keyframes blShine{
    0%  { opacity: 0; transform: translateX(-140%) skewX(-18deg); }
    12% { opacity: 1; }
    88% { opacity: 1; }
    100%{ opacity: 0; transform: translateX(260%)  skewX(-18deg); }
}
/* the artwork is drawn in from the left, like a page being opened */
@keyframes blPlate{
    from{ clip-path: inset(0 100% 0 0); transform: scale(1.05); }
    to  { clip-path: inset(0 0 0 0);    transform: scale(1); }
}
/* the headline is typeset left-to-right, echoing the section heading above it.
   Negative end insets, so a line-clamped title can never have a glyph shaved. */
@keyframes blTypeset{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* body copy and the Read more button settle in underneath it */
@keyframes blBodyIn{ from{ opacity: 0; transform: translateY(10px); } to{ opacity: 1; transform: translateY(0); } }
/* idle heartbeat — one random card breathes once every 8-10s */
@keyframes blIdlePulse{ 0%,100%{ transform: translateY(0); } 50%{ transform: translateY(-2px); } }

/* --- pre-hide (only while the script drives the reveal). The h3 itself is not
       hidden: its title text is masked and its "View All" slides in, each on
       its own timing. */
.blog_homepage.bl-js,
.blog_homepage.bl-js h3 span.float-right,
.blog_homepage.bl-js .blog{ opacity: 0; }
/* the script wraps the heading's own text node so it can be masked without
   catching "View All"; `color: inherit` keeps the global `span` colour rule
   from repainting the heading */
.blog_homepage .bl-head{ display: inline-block; color: inherit; }
.blog_homepage.bl-js .bl-head{ clip-path: inset(0 100% 0 0); }
.blog_homepage.bl-js .blog-img img{ clip-path: inset(0 100% 0 0); }
.blog_homepage.bl-js .blog p.overelipsis1{ clip-path: inset(0 100% 0 0); }
.blog_homepage.bl-js .blog p.overelipsis2,
.blog_homepage.bl-js .blog .btn.btnthird{ opacity: 0; }

/* --- staggered reveal. Card delays are assigned by the script, and each card
       also carries a --bl-d custom property that its artwork, headline, body
       copy and button offset from — so every card assembles itself in the same
       order: picture, then headline, then the text underneath. */
.blog_homepage.bl-js.bl-in{ animation: blSectionUp .8s ease-out both; }
.blog_homepage.bl-js.bl-in .bl-head{ animation: blHeadReveal .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.blog_homepage.bl-js.bl-in h3 span.float-right{ animation: blViewIn .5s ease-out .45s both; }
.blog_homepage.bl-js.bl-in .blog{ animation: blCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.blog_homepage.bl-js.bl-in .blog-img img{ animation: blPlate .85s cubic-bezier(.22,.61,.36,1) calc(var(--bl-d, 0s) + .10s) both; }
.blog_homepage.bl-js.bl-in .blog p.overelipsis1{ animation: blTypeset .6s cubic-bezier(.22,.61,.36,1) calc(var(--bl-d, 0s) + .32s) both; }
.blog_homepage.bl-js.bl-in .blog p.overelipsis2{ animation: blBodyIn .55s ease calc(var(--bl-d, 0s) + .48s) both; }
.blog_homepage.bl-js.bl-in .blog .btn.btnthird{ animation: blBodyIn .5s cubic-bezier(.34,1.56,.64,1) calc(var(--bl-d, 0s) + .62s) both; }
/* the heartbeat breathes the artwork only — the copy below never moves */
.blog_homepage .blog.bl-idle .blog-img img{ animation: blIdlePulse 1.2s ease-in-out; }
/* hovering mid-pulse drops the animation instantly so the hover lift still reads */
.blog_homepage .blog.bl-idle .blog-img:hover img{ animation: none; }

/* --- "View All": underline grows from the left, text lifts. The rule stands in
       for the theme's default hover underline so the growth is what reads. */
.blog_homepage h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.blog_homepage h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.blog_homepage h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.blog_homepage h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- card: no hover reaction at all. The title, description and Read more
       button below the artwork stay completely still — only the image
       responds. `position: relative` stays because the reveal and the idle
       heartbeat are scoped through the card. */
.blog_homepage .blog{ position: relative; }
/* the Blogs carousel gutter lives in the CAROUSEL GUTTERS block at the end of
   this file, with every other section's, so the whole set can be read at once */

/* --- image: a restrained lift rather than a zoom, and it is the artwork that
       carries the hover — moving the cursor over the copy triggers nothing.
       Light and contrast lift by 3%, enough to read as "lit", with no overlay
       and no blur. The lift stays inside .blog-img's own overflow, so nothing
       spills over the text or out of the carousel. */
.blog_homepage .blog-img{ position: relative; overflow: hidden; cursor: pointer; }
.blog_homepage .blog-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.blog_homepage .blog-img:hover img{
    transform: translateY(-5px) scale(1.03);
    filter: brightness(1.03) contrast(1.03);
}

/* --- soft reflection drifting across the image once on hover. Held under 10%
       so it reads as a change of light, not a shine. */
.blog_homepage .blog-img::after{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 45%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.08), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.blog_homepage .blog-img:hover::after{ animation: blShine 1.4s cubic-bezier(.4,0,.2,1); }

/* --- touch / small screens: drop the lift and the sweep, keep the fade-in and
       the staggered reveal so scrolling stays smooth */
@media (max-width: 767px), (hover: none){
    .blog_homepage .blog-img:hover img{ transform: none; filter: none; }
    .blog_homepage .blog-img:hover::after{ animation: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .blog_homepage,
    .blog_homepage h3,
    .blog_homepage h3 span.float-right,
    .blog_homepage .blog{ opacity: 1 !important; transform: none !important; animation: none !important; }
    .blog_homepage .bl-head{ clip-path: none !important; animation: none !important; }
    .blog_homepage .blog p.overelipsis2,
    .blog_homepage .blog .btn.btnthird{ opacity: 1 !important; transform: none !important; animation: none !important; }
    .blog_homepage .blog-img img,
    .blog_homepage .blog p.overelipsis1,
    .blog_homepage h3 span.float-right a{ clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .blog_homepage h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
    .blog_homepage .blog-img::after{ opacity: 0 !important; animation: none !important; }
}

/* ===========================================================================
   News section — entrance sequence + artwork-only hover.

   Animation-only and additive, same pattern as the Blogs section: a small
   self-contained script right after the section toggles the reveal classes and
   drops them once the sequence finishes, so hover takes over cleanly. With JS
   off or reduced-motion on, the section renders exactly as designed.

   The entrance leans into what makes this section news: each photograph is set
   into its frame from below and "develops" to its exact designed rendering,
   then the dateline is stamped across left-to-right, then the headline and the
   Read more button are already in place beneath. Nothing changes colors,
   typography, spacing, layout or markup — the develop filter lands on `none`
   and the reflection is neutral white under 10% alpha.

   Hover is limited to the artwork, matching the Blogs section: the copy block
   underneath never moves. The one exception is the section's own pre-existing
   `.news .post:hover .newstitle` colour rule, which is part of the finished
   design and is left untouched.
   =========================================================================== */
@keyframes nwSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes nwViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes nwCardUp{    from{ opacity: 0; transform: translateY(35px); } to{ opacity: 1; transform: translateY(0); } }
/* letter-spacing is deliberately not animated — it would alter the typography
   and force a reflow. Negative end insets keep every glyph intact at rest. */
@keyframes nwHeadReveal{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* photo settles into its frame from below and develops to the designed look */
@keyframes nwPlate{
    from{ clip-path: inset(100% 0 0 0); transform: scale(1.06); filter: contrast(.92) brightness(1.06); }
    to  { clip-path: inset(0 0 0 0);    transform: scale(1);    filter: none; }
}
/* dateline is stamped across, left to right */
@keyframes nwStamp{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
@keyframes nwShine{
    0%  { opacity: 0; transform: translateX(-140%) skewX(-18deg); }
    12% { opacity: 1; }
    88% { opacity: 1; }
    100%{ opacity: 0; transform: translateX(260%)  skewX(-18deg); }
}
@keyframes nwIdlePulse{ 0%,100%{ transform: translateY(0); } 50%{ transform: translateY(-2px); } }

/* --- pre-hide (only while the script drives the reveal) */
.news_homepage.nw-js,
.news_homepage.nw-js h3 span.float-right,
.news_homepage.nw-js .post{ opacity: 0; }
/* the script wraps the heading's own text node so the mask misses "View All";
   `color: inherit` stops the global `span` colour rule repainting the heading */
.news_homepage .nw-head{ display: inline-block; color: inherit; }
.news_homepage.nw-js .nw-head{ clip-path: inset(0 100% 0 0); }
.news_homepage.nw-js .post-img img{ clip-path: inset(100% 0 0 0); }
.news_homepage.nw-js .post p.fw-600{ clip-path: inset(0 100% 0 0); }

/* --- staggered reveal. Card delays are assigned by the script, and each card
       also carries a --nw-d custom property that its photo and dateline offset
       from, so every card tells the same little story in sequence. */
.news_homepage.nw-js.nw-in{ animation: nwSectionUp .8s ease-out both; }
.news_homepage.nw-js.nw-in .nw-head{ animation: nwHeadReveal .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.news_homepage.nw-js.nw-in h3 span.float-right{ animation: nwViewIn .5s ease-out .45s both; }
.news_homepage.nw-js.nw-in .post{ animation: nwCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.news_homepage.nw-js.nw-in .post-img img{ animation: nwPlate .9s cubic-bezier(.22,.61,.36,1) calc(var(--nw-d, 0s) + .10s) both; }
.news_homepage.nw-js.nw-in .post p.fw-600{ animation: nwStamp .55s cubic-bezier(.22,.61,.36,1) calc(var(--nw-d, 0s) + .38s) both; }

/* the heartbeat breathes the artwork only — the copy below never moves */
.news_homepage .post.nw-idle .post-img img{ animation: nwIdlePulse 1.2s ease-in-out; }
.news_homepage .post.nw-idle .post-img:hover img{ animation: none; }

/* --- "View All": underline grows from the left, text lifts. Stands in for the
       theme's default hover underline so the growth is what reads. */
.news_homepage h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.news_homepage h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.news_homepage h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.news_homepage h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- card: no hover reaction. Dateline, headline and Read more stay still. */
.news_homepage .post{ position: relative; }

/* --- image: hover is carried by the artwork, so moving the cursor over the
       copy triggers nothing. The lift stays inside .post-img's own overflow,
       so it never spills over the text or out of the carousel. */
.news_homepage .post-img{ position: relative; overflow: hidden; cursor: pointer; }
.news_homepage .post-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.news_homepage .post-img:hover img{
    transform: translateY(-5px) scale(1.03);
    filter: brightness(1.03) contrast(1.03);
}

/* --- soft reflection drifting across the photo once on hover, under 10% so it
       reads as a change of light rather than a shine */
.news_homepage .post-img::after{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 45%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.08), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.news_homepage .post-img:hover::after{ animation: nwShine 1.4s cubic-bezier(.4,0,.2,1); }

/* --- touch / small screens: drop the lift and the sweep, keep the entrance */
@media (max-width: 767px), (hover: none){
    .news_homepage .post-img:hover img{ transform: none; filter: none; }
    .news_homepage .post-img:hover::after{ animation: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .news_homepage,
    .news_homepage h3,
    .news_homepage h3 span.float-right,
    .news_homepage .post{ opacity: 1 !important; transform: none !important; animation: none !important; }
    .news_homepage .nw-head{ clip-path: none !important; animation: none !important; }
    .news_homepage .post-img img,
    .news_homepage .post p.fw-600,
    .news_homepage h3 span.float-right a{ clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .news_homepage h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
    .news_homepage .post-img::after{ opacity: 0 !important; animation: none !important; }
}

/* ===========================================================================
   Press Release section (home) — entrance sequence + artwork-only hover.

   Animation-only and additive, same pattern as Blogs and News: a small
   self-contained script right after the section toggles the reveal classes and
   drops them once the sequence finishes, so hover takes over cleanly. With JS
   off or reduced-motion on, the section renders exactly as designed.

   These cards are press clippings, so the entrance plays to that: each clipping
   is laid down onto the page with a slight rotation that settles square, then
   its masthead is stamped across, then the headline, excerpt and date rise
   underneath. On hover a clipping lifts and tilts a little off the page with a
   soft drop shadow, as though being picked up — the caption never moves.

   Everything is scoped to .pressrelease_homepage because `.gallery` and
   `.presscard` are shared with the photo gallery and the press listing page,
   and `.gallery` is also what baguetteBox binds its lightbox to.
   =========================================================================== */
@keyframes prSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes prViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes prCardUp{    from{ opacity: 0; transform: translateY(35px); } to{ opacity: 1; transform: translateY(0); } }
/* headline + masthead reveals. Negative end insets, so no glyph is ever shaved. */
@keyframes prWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the clipping is laid down onto the page and settles square */
@keyframes prLayDown{
    from{ opacity: 0; transform: rotate(-3deg)  scale(.94); }
    60% { opacity: 1; transform: rotate(.8deg)  scale(1.01); }
    to  { opacity: 1; transform: rotate(0deg)   scale(1); }
}
@keyframes prTextUp{ from{ opacity: 0; transform: translateY(12px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes prIdlePulse{ 0%,100%{ transform: translateY(0); } 50%{ transform: translateY(-2px); } }

/* --- pre-hide (only while the script drives the reveal) */
.pressrelease_homepage.pr-js,
.pressrelease_homepage.pr-js h3 span.float-right,
.pressrelease_homepage.pr-js .gallery{ opacity: 0; }
/* the script wraps the heading's own text node so the wipe misses "View All";
   `color: inherit` stops the global `span` colour rule repainting the heading */
.pressrelease_homepage .pr-head{ display: inline-block; color: inherit; }
.pressrelease_homepage.pr-js .pr-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.pressrelease_homepage.pr-js .gallery .presscard{ opacity: 0; }
.pressrelease_homepage.pr-js .gallery p.text-lblue{ clip-path: inset(-.2em 100% -.2em -.2em); }
.pressrelease_homepage.pr-js .gallery p.overelipsis1,
.pressrelease_homepage.pr-js .gallery p.overelipsis2,
.pressrelease_homepage.pr-js .gallery p.text-96{ opacity: 0; }

/* --- staggered reveal. Card delays are assigned by the script, and each card
       carries a --pr-d custom property that its clipping, masthead, headline,
       excerpt and date all offset from. */
.pressrelease_homepage.pr-js.pr-in{ animation: prSectionUp .8s ease-out both; }
.pressrelease_homepage.pr-js.pr-in .pr-head{ animation: prWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.pressrelease_homepage.pr-js.pr-in h3 span.float-right{ animation: prViewIn .5s ease-out .45s both; }
.pressrelease_homepage.pr-js.pr-in .gallery{ animation: prCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.pressrelease_homepage.pr-js.pr-in .gallery .presscard{ animation: prLayDown .8s cubic-bezier(.22,.61,.36,1) calc(var(--pr-d, 0s) + .10s) both; }
.pressrelease_homepage.pr-js.pr-in .gallery p.text-lblue{ animation: prWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--pr-d, 0s) + .34s) both; }
.pressrelease_homepage.pr-js.pr-in .gallery p.overelipsis1{ animation: prTextUp .5s ease calc(var(--pr-d, 0s) + .48s) both; }
.pressrelease_homepage.pr-js.pr-in .gallery p.overelipsis2{ animation: prTextUp .5s ease calc(var(--pr-d, 0s) + .60s) both; }
.pressrelease_homepage.pr-js.pr-in .gallery p.text-96{ animation: prTextUp .5s ease calc(var(--pr-d, 0s) + .72s) both; }

/* the heartbeat breathes the clipping only — the caption below never moves */
.pressrelease_homepage .gallery.pr-idle .presscard{ animation: prIdlePulse 1.2s ease-in-out; }
.pressrelease_homepage .gallery.pr-idle a.item:hover .presscard{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.pressrelease_homepage h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.pressrelease_homepage h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.pressrelease_homepage h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.pressrelease_homepage h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- the clipping carries the hover. The shared `.gallery:hover .presscard`
       zoom (which the photo gallery also uses) is neutralised inside this
       section only, so moving the cursor over the caption does nothing. */
.pressrelease_homepage .gallery .presscard{
    transition: transform .5s cubic-bezier(.22,.61,.36,1), box-shadow .5s ease, filter .5s ease;
    will-change: transform;
}
.pressrelease_homepage .gallery:hover .presscard{ transform: none; }
.pressrelease_homepage .gallery a.item{ cursor: pointer; }
.pressrelease_homepage .gallery a.item:hover .presscard{
    transform: translateY(-6px) rotate(-1.2deg) scale(1.04);
    box-shadow: 0 16px 30px rgba(0,0,0,.22);
    filter: brightness(1.03) contrast(1.03);
}

/* In slider mode the owl wrapper clips at its padding edge, which would slice
   the lift and the drop shadow off. The breathing room is cancelled out by an
   equal negative margin, so the cards, the controls and everything after the
   carousel render in exactly the same place — only the clip region grows.
   Horizontal clipping, which the carousel relies on, is untouched. */
.pressrelease_homepage .owl-carousel .owl-wrapper-outer{ padding: 26px 0; margin: -26px 0; }
/* that negative top margin collapses out to .owl-carousel, so absolutely
   positioned nav arrows would otherwise ride 26px up with it */
.pressrelease_homepage .owl-carousel .owl-buttons{ margin-top: 26px; }

/* --- touch / small screens: drop the lift, keep the entrance */
@media (max-width: 767px), (hover: none){
    .pressrelease_homepage .gallery a.item:hover .presscard{ transform: none; box-shadow: none; filter: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .pressrelease_homepage,
    .pressrelease_homepage h3,
    .pressrelease_homepage h3 span.float-right,
    .pressrelease_homepage .gallery{ opacity: 1 !important; transform: none !important; animation: none !important; }
    .pressrelease_homepage .pr-head{ clip-path: none !important; animation: none !important; }
    .pressrelease_homepage .gallery .presscard,
    .pressrelease_homepage .gallery p.text-lblue,
    .pressrelease_homepage .gallery p.overelipsis1,
    .pressrelease_homepage .gallery p.overelipsis2,
    .pressrelease_homepage .gallery p.text-96,
    .pressrelease_homepage h3 span.float-right a{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .pressrelease_homepage h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Events section (home) — entrance sequence + card hover.

   Animation-only and additive, same pattern as the other card sections: a small
   self-contained script right after the section toggles the reveal classes and
   drops them once the sequence finishes. With JS off or reduced-motion on, the
   section renders exactly as designed.

   These cards are dates, not pictures — there is no artwork at all — so the
   entrance plays to the calendar: the day number hinges down into place like a
   calendar page being turned, the month follows it, then the title, time and
   venue rise underneath.

   Hover is at CARD level here, unlike Blogs / News / Press Release. That is
   deliberate: the whole card is wrapped in a single <a>, so the entire surface
   is genuinely clickable, and the finished design already flips the card to
   black with white copy and amber accents on hover. Those colours are NOT
   touched — the only change is that they now ease instead of snapping, plus a
   small lift and shadow.
   =========================================================================== */
@keyframes evSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes evViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes evCardUp{    from{ opacity: 0; transform: translateY(35px); } to{ opacity: 1; transform: translateY(0); } }
/* heading wipe. Negative end insets, so no glyph is ever shaved. */
@keyframes evWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the date hinges down from its top edge, like a calendar page turning. The
   perspective lives inside the transform, so no ancestor needs a `perspective`
   property and nothing becomes a containing block for positioned children. */
@keyframes evFlipIn{
    from{ opacity: 0; transform: perspective(600px) rotateX(-78deg); }
    to  { opacity: 1; transform: perspective(600px) rotateX(0deg); }
}
@keyframes evTextUp{ from{ opacity: 0; transform: translateY(12px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes evIdlePulse{ 0%,100%{ transform: translateY(0); } 50%{ transform: translateY(-2px); } }

/* --- pre-hide (only while the script drives the reveal) */
.events_homepage.ev-js,
.events_homepage.ev-js h3 span.float-right,
.events_homepage.ev-js .medevents{ opacity: 0; }
/* the script wraps the heading's own text node so the wipe misses "View All";
   `color: inherit` stops the global `span` colour rule repainting the heading */
.events_homepage .ev-head{ display: inline-block; color: inherit; }
.events_homepage.ev-js .ev-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
/* The title also carries .fs-20 and .fw-600, so the month and time rules below
   exclude it explicitly — otherwise it would pick up two animations at once.
   The hidden .d-none duplicate date block is a <div>, so the child combinator
   already keeps its paragraphs out of all of this. */
.events_homepage .medevents > p.fs-50,
.events_homepage .medevents > p.fs-20:not(.title){ transform-origin: top center; }
.events_homepage.ev-js .medevents > p{ opacity: 0; }

/* --- staggered reveal. Card delays are assigned by the script, and each card
       carries an --ev-d custom property that its date, title, time and venue
       all offset from. */
.events_homepage.ev-js.ev-in{ animation: evSectionUp .8s ease-out both; }
.events_homepage.ev-js.ev-in .ev-head{ animation: evWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.events_homepage.ev-js.ev-in h3 span.float-right{ animation: evViewIn .5s ease-out .45s both; }
.events_homepage.ev-js.ev-in .medevents{ animation: evCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.events_homepage.ev-js.ev-in .medevents > p.fs-50{ animation: evFlipIn .65s cubic-bezier(.22,.61,.36,1) calc(var(--ev-d, 0s) + .10s) both; }
.events_homepage.ev-js.ev-in .medevents > p.fs-20:not(.title){ animation: evFlipIn .6s cubic-bezier(.22,.61,.36,1) calc(var(--ev-d, 0s) + .28s) both; }
.events_homepage.ev-js.ev-in .medevents > p.title{ animation: evTextUp .5s ease calc(var(--ev-d, 0s) + .46s) both; }
.events_homepage.ev-js.ev-in .medevents > p.fw-600:not(.title){ animation: evTextUp .5s ease calc(var(--ev-d, 0s) + .58s) both; }
.events_homepage.ev-js.ev-in .medevents > p.fs-12,
.events_homepage.ev-js.ev-in .medevents > p.overelipsis2{ animation: evTextUp .5s ease calc(var(--ev-d, 0s) + .70s) both; }

/* the heartbeat breathes a whole card, since a card is what the user clicks */
.events_homepage .medevents.ev-idle{ animation: evIdlePulse 1.2s ease-in-out; }
.events_homepage .medevents.ev-idle:hover{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.events_homepage h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.events_homepage h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.events_homepage h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.events_homepage h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- card hover. The designed colour flip is untouched; it simply eases now
       instead of snapping, and the card lifts a little off the page. */
.events_homepage .medevents{
    transition: background-color .4s ease,
                transform .4s cubic-bezier(.22,.61,.36,1),
                box-shadow .4s ease;
}
.events_homepage .medevents p,
.events_homepage .medevents span,
.events_homepage .medevents .title{ transition: color .35s ease; }
.events_homepage .medevents:hover{
    transform: translateY(-6px);
    box-shadow: 0 16px 30px rgba(0,0,0,.20);
}
/* The card links carry the theme's default hover underline, which draws a line
   under every line of copy in the card. The events LISTING page already
   suppresses this via `.medeventsdiv a:hover`; the home page had no equivalent.
   The heading's "View All" sits outside .col-md-12, so it is unaffected. */
.events_homepage .col-md-12 a:hover{ text-decoration: none; }

/* In slider mode the owl wrapper clips at its padding edge, which would slice
   the lift and the shadow off. The breathing room is cancelled out by an equal
   negative margin, so everything renders in exactly the same place — only the
   clip region grows. Horizontal clipping, which the carousel relies on, is
   untouched. */
.events_homepage .owl-carousel .owl-wrapper-outer{ padding: 26px 0; margin: -26px 0; }
.events_homepage .owl-carousel .owl-buttons{ margin-top: 26px; }

/* --- touch / small screens: drop the lift, keep the entrance */
@media (max-width: 767px), (hover: none){
    .events_homepage .medevents:hover{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .events_homepage,
    .events_homepage h3,
    .events_homepage h3 span.float-right,
    .events_homepage .medevents,
    .events_homepage .medevents > p{ opacity: 1 !important; transform: none !important; animation: none !important; }
    .events_homepage .ev-head{ clip-path: none !important; animation: none !important; }
    .events_homepage .medevents,
    .events_homepage .medevents p,
    .events_homepage .medevents span,
    .events_homepage h3 span.float-right a{ transition: none !important; }
    .events_homepage .medevents:hover{ box-shadow: none !important; }
    .events_homepage h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Testimonials section (home) — entrance sequence + hover.

   Animation-only and additive, same pattern as the other card sections: a small
   self-contained script right after the section toggles the reveal classes and
   drops them once the sequence finishes. With JS off or reduced-motion on, the
   section renders exactly as designed.

   Two things shape this one. It sits on a black panel, so the accents are
   neutral white at low alpha — light, not hue, exactly as in Why to Choose. And
   nothing inside a testimonial is a link, so the hover is deliberately quiet
   and adds NO cursor change: it must not imply the card can be clicked.

   Each testimonial's outer handle is its .col-md-12 — one per quote, and the
   section heading sits outside it. `.testimoimg` and `.peoplereview` are shared
   with services, departments and the write-a-review block, so everything is
   scoped to .testimonials_homepage.
   =========================================================================== */
@keyframes tsSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes tsViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes tsCardUp{    from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
/* heading + nameplate wipes. Negative end insets, so no glyph is ever shaved. */
@keyframes tsWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the portrait arrives with a ring pulsing out from it. The avatar is already a
   circle, so the box-shadow ring is naturally round, and it ends fully
   transparent leaving nothing behind. */
@keyframes tsAvatarIn{
    0%  { opacity: 0; transform: scale(.4); box-shadow: 0 0 0 0    rgba(255,255,255,.40); }
    60% { opacity: 1; transform: scale(1.1); box-shadow: 0 0 0 12px rgba(255,255,255,.12); }
    100%{ opacity: 1; transform: scale(1);  box-shadow: 0 0 0 24px rgba(255,255,255,0); }
}
@keyframes tsTextUp{ from{ opacity: 0; transform: translateY(14px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes tsIdlePulse{ 0%,100%{ transform: scale(1); } 50%{ transform: scale(1.05); } }

/* --- pre-hide (only while the script drives the reveal) */
.testimonials_homepage.ts-js,
.testimonials_homepage.ts-js h3 span.float-right,
.testimonials_homepage.ts-js .col-md-12{ opacity: 0; }
/* the script wraps the heading's own text node so the wipe misses "View All";
   `color: inherit` stops the global `span` colour rule repainting the heading */
.testimonials_homepage .ts-head{ display: inline-block; color: inherit; }
.testimonials_homepage.ts-js .ts-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.testimonials_homepage.ts-js .testimoimg{ opacity: 0; }
.testimonials_homepage.ts-js .position-relative > p{ clip-path: inset(-.2em 100% -.2em -.2em); }
.testimonials_homepage.ts-js p.peoplereview{ opacity: 0; }

/* --- staggered reveal. Card delays are assigned by the script, and each card
       carries a --ts-d custom property that the portrait, the nameplate and the
       quote all offset from. */
.testimonials_homepage.ts-js.ts-in{ animation: tsSectionUp .8s ease-out both; }
.testimonials_homepage.ts-js.ts-in .ts-head{ animation: tsWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.testimonials_homepage.ts-js.ts-in h3 span.float-right{ animation: tsViewIn .5s ease-out .45s both; }
.testimonials_homepage.ts-js.ts-in .col-md-12{ animation: tsCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.testimonials_homepage.ts-js.ts-in .testimoimg{ animation: tsAvatarIn .7s cubic-bezier(.34,1.56,.64,1) calc(var(--ts-d, 0s) + .10s) both; }
.testimonials_homepage.ts-js.ts-in .position-relative > p{ animation: tsWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--ts-d, 0s) + .30s) both; }
.testimonials_homepage.ts-js.ts-in p.peoplereview{ animation: tsTextUp .55s ease calc(var(--ts-d, 0s) + .48s) both; }

/* the heartbeat breathes the portrait only — the quote never moves */
.testimonials_homepage .col-md-12.ts-idle .testimoimg{ animation: tsIdlePulse 1.3s ease-in-out; }
.testimonials_homepage .col-md-12.ts-idle:hover .testimoimg{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.testimonials_homepage h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.testimonials_homepage h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.testimonials_homepage h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.testimonials_homepage h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- hover: the quote lifts a touch and the portrait gains a soft white ring.
       No cursor change and no shadow on the card — there is nothing to click,
       and a drop shadow would be invisible against the black panel anyway. */
.testimonials_homepage .col-md-12{ transition: transform .4s cubic-bezier(.22,.61,.36,1); }
.testimonials_homepage .col-md-12:hover{ transform: translateY(-4px); }
.testimonials_homepage .testimoimg{ transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease; }
.testimonials_homepage .col-md-12:hover .testimoimg{
    transform: scale(1.08);
    box-shadow: 0 0 0 6px rgba(255,255,255,.10);
}

/* In slider mode the owl wrapper clips at its padding edge, which would slice
   the lift and the portrait's ring off. The breathing room is cancelled out by
   an equal negative margin, so everything renders in exactly the same place —
   only the clip region grows. Horizontal clipping is untouched. */
.testimonials_homepage .owl-carousel .owl-wrapper-outer{ padding: 22px 0; margin: -22px 0; }
.testimonials_homepage .owl-carousel .owl-buttons{ margin-top: 22px; }

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .testimonials_homepage .col-md-12:hover{ transform: none; }
    .testimonials_homepage .col-md-12:hover .testimoimg{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .testimonials_homepage,
    .testimonials_homepage h3,
    .testimonials_homepage h3 span.float-right,
    .testimonials_homepage .col-md-12,
    .testimonials_homepage .position-relative > p,
    .testimonials_homepage p.peoplereview{ opacity: 1 !important; transform: none !important; clip-path: none !important; animation: none !important; transition: none !important; }
    .testimonials_homepage .ts-head{ clip-path: none !important; animation: none !important; }
    .testimonials_homepage .testimoimg,
    .testimonials_homepage h3 span.float-right a{ opacity: 1 !important; transform: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .testimonials_homepage h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   FAQ section (home) — entrance sequence + hover.

   Animation-only and additive. A small self-contained script right after the
   section toggles the reveal classes and drops them once the sequence
   finishes. With JS off or reduced-motion on, the section renders exactly as
   designed.

   IMPORTANT: this is a Bootstrap collapse accordion. The `.collapse` element
   itself is never touched — Bootstrap owns its height, and adding an opacity,
   transform or animation to it would fight the open/close. Everything here
   animates the card, the header, the chevron or the card-BODY instead, so the
   accordion, its data-parent behaviour and the existing .active toggling in
   js.php all keep working untouched.

   The entrance rules key off .fq-js/.fq-in, added by each page's own script, so
   the home section and the standalone FAQ page never trigger each other. The
   hover/chevron rules originally targeted only the home section's
   `.primary_section.faqsection`, since `.faqsection`, `#accordion`, `.faq-hover`
   and `.hdng` are all shared with the standalone page too; that standalone page
   now opts in with its own `.fq-hover-page` marker instead of widening the
   original selector, so nothing about the home section's scoping changed.
   =========================================================================== */
@keyframes fqSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes fqViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes fqTextUp{    from{ opacity: 0; transform: translateY(14px); } to{ opacity: 1; transform: translateY(0); } }
/* Each question is drawn onto the page left-to-right while it slides in, the
   way a list gets written down. The insets end NEGATIVE, so the clip sits
   outside the card and can never trim an answer opened mid-entrance. */
@keyframes fqCardIn{
    from{ opacity: 0; transform: translateX(-26px); clip-path: inset(-.3em 100% -.3em -.3em); }
    to  { opacity: 1; transform: translateX(0);     clip-path: inset(-.3em -.3em -.3em -.3em); }
}
/* heading wipe. Negative end insets, so no glyph is ever shaved. */
@keyframes fqWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the chevron spins into place, landing on whichever angle its own state wants */
@keyframes fqChev{
    from{ opacity: 0; transform: rotate(calc(var(--fq-rot, 0deg) - 120deg)) scale(.3); }
    to  { opacity: 1; transform: rotate(var(--fq-rot, 0deg))                scale(1); }
}
/* an answer drops in and pulls into focus as its panel finishes opening */
@keyframes fqAnswerIn{
    from{ opacity: 0; transform: translateY(-10px); filter: blur(5px); }
    to  { opacity: 1; transform: translateY(0);     filter: blur(0); }
}

/* --- pre-hide (only while the script drives the reveal) */
.faqsection.fq-js,
.faqsection.fq-js h3 span.float-right,
.faqsection.fq-js .col-md-12 > p,
.faqsection.fq-js .card{ opacity: 0; }
/* the standalone FAQ page has no "View All" to protect and no h3 — its h1 can be
   clipped directly, with no need for the fq-head text-node-wrapping trick */
.faqsection.fq-js h1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.faqsection.fq-js.fq-in h1{ animation: fqWipe .8s cubic-bezier(.22,.61,.36,1) .1s both; }
/* the script wraps the heading's own text node so the wipe misses "View All";
   `color: inherit` stops the global `span` colour rule repainting the heading */
.faqsection .fq-head{ display: inline-block; color: inherit; }
.faqsection.fq-js .fq-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.faqsection.fq-js .hdng a::after{ opacity: 0; }

/* --- staggered reveal. Card delays are assigned by the script, and each card
       carries a --fq-d custom property that its chevron offsets from. */
.faqsection.fq-js.fq-in{ animation: fqSectionUp .8s ease-out both; }
.faqsection.fq-js.fq-in .fq-head{ animation: fqWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.faqsection.fq-js.fq-in h3 span.float-right{ animation: fqViewIn .5s ease-out .45s both; }
.faqsection.fq-js.fq-in .col-md-12 > p{ animation: fqTextUp .6s ease .5s both; }
.faqsection.fq-js.fq-in .card{ animation: fqCardIn .6s cubic-bezier(.22,.61,.36,1) both; }
.faqsection.fq-js.fq-in .hdng a::after{ animation: fqChev .45s cubic-bezier(.34,1.56,.64,1) calc(var(--fq-d, 0s) + .18s) both; }

/* --- opening an answer: the copy drops in once the panel has finished
       expanding. Bootstrap adds .show at the end of its height transition, so
       this reads as the answer settling into the space just made for it.
       Targets the card-BODY, never the .collapse wrapper Bootstrap animates. */
:is(.primary_section.faqsection, .faqsection.fq-hover-page) .collapse.show > .card-body{ animation: fqAnswerIn .45s ease both; }

/* --- "View All": underline grows from the left, text lifts */
.faqsection h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.faqsection h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.faqsection h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.faqsection h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- the chevron TURNS instead of swapping glyphs.
       The theme uses two different FontAwesome characters for the two states —
       \f077 pointing up when open, \f078 pointing down when closed — and a
       content swap cannot animate, so the accordion's main moment had no motion
       at all. Both states now use the down chevron and the open one is rotated
       180deg: each rest position looks exactly as it did before, but the change
       between them is a smooth turn. The angle lives on a custom property so the
       entrance spin can land on whichever one its own row needs. */
:is(.primary_section.faqsection, .faqsection.fq-hover-page) #accordion .hdng a{ --fq-rot: -180deg; }          /* open   */
:is(.primary_section.faqsection, .faqsection.fq-hover-page) #accordion .hdng a.collapsed{ --fq-rot: 0deg; }   /* closed */
:is(.primary_section.faqsection, .faqsection.fq-hover-page) #accordion .hdng a::after,
:is(.primary_section.faqsection, .faqsection.fq-hover-page) #accordion .hdng a.collapsed::after{
    content: '\f078';
    transform: rotate(var(--fq-rot, 0deg));
    transition: transform .4s cubic-bezier(.34,1.56,.64,1);
}

/* --- header hover. The designed grey is untouched; it simply eases in now
       instead of snapping. The question slides to meet the cursor and the
       chevron swells, hinting that the row is about to move. */
:is(.primary_section.faqsection, .faqsection.fq-hover-page) .card-header.faq-hover{ transition: background-color .3s ease; }
:is(.primary_section.faqsection, .faqsection.fq-hover-page) .hdng{ transition: transform .35s cubic-bezier(.22,.61,.36,1); }
:is(.primary_section.faqsection, .faqsection.fq-hover-page) .card-header:hover .hdng{ transform: translateX(6px); }
/* #accordion is carried through here so this outranks the ID-bearing base rule */
:is(.primary_section.faqsection, .faqsection.fq-hover-page) #accordion .card-header:hover .hdng a::after{
    transform: rotate(var(--fq-rot, 0deg)) scale(1.25);
}
/* hovering a CLOSED question tips its chevron part-way round, previewing the
   turn it is about to make — the row tells you what clicking will do */
:is(.primary_section.faqsection, .faqsection.fq-hover-page) #accordion .card-header:hover .hdng a.collapsed::after{
    transform: rotate(-32deg) scale(1.25);
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .faqsection,
    .faqsection h3,
    .faqsection h3 span.float-right,
    .faqsection .col-md-12 > p,
    .faqsection .card,
    .faqsection .hdng{ opacity: 1 !important; transform: none !important; animation: none !important; transition: none !important; }
    .faqsection .fq-head,
    .faqsection h1{ clip-path: none !important; opacity: 1 !important; animation: none !important; }
    .faqsection .card{ clip-path: none !important; }
    /* the original two-glyph chevron is restored, so with motion off the open and
       closed states still read correctly without relying on a rotation */
    :is(.primary_section.faqsection, .faqsection.fq-hover-page) #accordion .hdng a::after{ content: '\f077' !important; }
    :is(.primary_section.faqsection, .faqsection.fq-hover-page) #accordion .hdng a.collapsed::after{ content: '\f078' !important; }
    .faqsection .hdng a::after{ opacity: 1 !important; transform: none !important; animation: none !important; transition: none !important; }
    :is(.primary_section.faqsection, .faqsection.fq-hover-page) .collapse.show > .card-body{ animation: none !important; filter: none !important; }
    :is(.primary_section.faqsection, .faqsection.fq-hover-page) .card-header.faq-hover{ transition: none !important; }
    .faqsection h3 span.float-right a{ transform: none !important; transition: none !important; }
    .faqsection h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Awards section (home) — entrance sequence + artwork hover.

   Animation-only and additive, same pattern as the other card sections. With
   JS off or reduced-motion on, the section renders exactly as designed.

   The gesture here is a SPOTLIGHT: each award opens out of a circle, the way a
   light widens onto a trophy. Nothing else on the page uses a circular clip, so
   the section reads as its own thing. The hover gleam is narrower, brighter and
   faster than the soft reflections on Blogs / News / Press Release, so it reads
   as light catching metal rather than a passing sheen.

   Scoped to .awards_homepage throughout: `.post` and `.post-img` are shared
   with News, and this section even carries the `news` class itself.
   =========================================================================== */
@keyframes awSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes awViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes awCardUp{    from{ opacity: 0; transform: translateY(35px); } to{ opacity: 1; transform: translateY(0); } }
/* heading + date wipes. Negative end insets, so no glyph is ever shaved. */
@keyframes awWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* The spotlight opens. 85% is past the 70.7% a circle needs to clear the corners
   of ANY rectangle, so whatever the image's aspect ratio nothing is clipped at
   rest — and unlike the `farthest-corner` keyword, a percentage interpolates. */
@keyframes awIris{
    from{ opacity: 0; clip-path: circle(0%  at 50% 50%); transform: scale(1.08); }
    to  { opacity: 1; clip-path: circle(85% at 50% 50%); transform: scale(1); }
}
@keyframes awTextUp{ from{ opacity: 0; transform: translateY(12px); } to{ opacity: 1; transform: translateY(0); } }
/* a narrow, quick glint rather than a soft reflection */
@keyframes awGleam{
    0%  { opacity: 0; transform: translateX(-140%) skewX(-22deg); }
    10% { opacity: 1; }
    90% { opacity: 1; }
    100%{ opacity: 0; transform: translateX(340%)  skewX(-22deg); }
}
@keyframes awIdlePulse{ 0%,100%{ transform: translateY(0); } 50%{ transform: translateY(-2px); } }

/* --- pre-hide (only while the script drives the reveal) */
.awards_homepage.aw-js,
.awards_homepage.aw-js h3 span.float-right,
.awards_homepage.aw-js .post{ opacity: 0; }
.awards_homepage .aw-head{ display: inline-block; color: inherit; }
.awards_homepage.aw-js .aw-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.awards_homepage.aw-js .post-img img{ clip-path: circle(0% at 50% 50%); }
.awards_homepage.aw-js .post p.fw-600{ clip-path: inset(-.2em 100% -.2em -.2em); }
.awards_homepage.aw-js .post p.awardtitle,
.awards_homepage.aw-js .post .btn.btnthird{ opacity: 0; }

/* --- staggered reveal; each card carries an --aw-d the inner beats offset from */
.awards_homepage.aw-js.aw-in{ animation: awSectionUp .8s ease-out both; }
.awards_homepage.aw-js.aw-in .aw-head{ animation: awWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.awards_homepage.aw-js.aw-in h3 span.float-right{ animation: awViewIn .5s ease-out .45s both; }
.awards_homepage.aw-js.aw-in .post{ animation: awCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.awards_homepage.aw-js.aw-in .post-img img{ animation: awIris .85s cubic-bezier(.22,.61,.36,1) calc(var(--aw-d, 0s) + .10s) both; }
.awards_homepage.aw-js.aw-in .post p.fw-600{ animation: awWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--aw-d, 0s) + .34s) both; }
.awards_homepage.aw-js.aw-in .post p.awardtitle{ animation: awTextUp .5s ease calc(var(--aw-d, 0s) + .48s) both; }
.awards_homepage.aw-js.aw-in .post .btn.btnthird{ animation: awTextUp .5s ease calc(var(--aw-d, 0s) + .62s) both; }

/* the heartbeat breathes the artwork only — the caption below never moves */
.awards_homepage .post.aw-idle .post-img img{ animation: awIdlePulse 1.2s ease-in-out; }
.awards_homepage .post.aw-idle .post-img:hover img{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.awards_homepage h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.awards_homepage h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.awards_homepage h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.awards_homepage h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- the artwork carries the motion hover; the glint crosses it once */
.awards_homepage .post-img{ position: relative; overflow: hidden; cursor: pointer; }
.awards_homepage .post-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.awards_homepage .post-img:hover img{
    transform: translateY(-5px) scale(1.04);
    filter: brightness(1.05) contrast(1.03);
}
.awards_homepage .post-img::after{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 22%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.35), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.awards_homepage .post-img:hover::after{ animation: awGleam .8s cubic-bezier(.4,0,.2,1); }
/* the section's own designed title-colour hover is untouched — it just eases now */
.awards_homepage .post p.awardtitle{ transition: color .3s ease; }

/* --- touch / small screens: drop the lift and the glint, keep the entrance */
@media (max-width: 767px), (hover: none){
    .awards_homepage .post-img:hover img{ transform: none; filter: none; }
    .awards_homepage .post-img:hover::after{ animation: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .awards_homepage,
    .awards_homepage h3,
    .awards_homepage h3 span.float-right,
    .awards_homepage .post{ opacity: 1 !important; transform: none !important; animation: none !important; }
    .awards_homepage .aw-head{ clip-path: none !important; animation: none !important; }
    .awards_homepage .post-img img,
    .awards_homepage .post p.fw-600,
    .awards_homepage .post p.awardtitle,
    .awards_homepage .post .btn.btnthird,
    .awards_homepage h3 span.float-right a{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .awards_homepage .post-img::after{ opacity: 0 !important; animation: none !important; }
    .awards_homepage h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Vision / Mission section (home) — entrance sequence + hover.

   Animation-only and additive. With JS off or reduced-motion on, the section
   renders exactly as designed.

   The gesture is literal: the picture COMES INTO FOCUS, resolving out of a
   blur as its heading is uncovered and the copy rises beside it. For a section
   headed "Vision" that felt like the one idea worth building the whole thing on.

   Two structural notes. This section has no heading row and no "View All", so
   there is nothing to wipe at section level — it is card choreography only. And
   the picture is `position: sticky`: a transform on ANY ancestor, or an
   `overflow: hidden` on one, would break that. So the card wrapper is never
   transformed and .vmimg never gets an overflow — only the image itself and the
   text column are animated.

   Scoped to `.vm`, which appears nowhere else in the theme.
   =========================================================================== */
@keyframes vmSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
/* the picture resolves out of a blur — the section's whole idea in one keyframe */
@keyframes vmFocus{
    from{ opacity: 0; filter: blur(12px); transform: scale(1.06); }
    to  { opacity: 1; filter: blur(0);    transform: scale(1); }
}
@keyframes vmWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
@keyframes vmTextUp{ from{ opacity: 0; transform: translateY(16px); } to{ opacity: 1; transform: translateY(0); } }

/* --- pre-hide. Note the card wrapper (.col-md-12) is deliberately absent: a
       transform on it would become the containing block for the sticky picture
       inside and stop it sticking. */
.vm.vm-js{ opacity: 0; }
.vm.vm-js .vmimg img{ opacity: 0; }
.vm.vm-js .vision-mission-card h3{ clip-path: inset(-.2em 100% -.2em -.2em); }
.vm.vm-js .vision-mission-card > *:not(h3){ opacity: 0; }

/* --- staggered reveal; each card carries a --vm-d the inner beats offset from */
.vm.vm-js.vm-in{ animation: vmSectionUp .8s ease-out both; }
.vm.vm-js.vm-in .vmimg img{ animation: vmFocus .95s cubic-bezier(.22,.61,.36,1) calc(var(--vm-d, 0s) + .10s) both; }
.vm.vm-js.vm-in .vision-mission-card h3{ animation: vmWipe .7s cubic-bezier(.22,.61,.36,1) calc(var(--vm-d, 0s) + .30s) both; }
/* the copy is editor HTML, so whatever elements it produces are staggered */
.vm.vm-js.vm-in .vision-mission-card > *:not(h3){ animation: vmTextUp .55s ease calc(var(--vm-d, 0s) + .45s) both; }
.vm.vm-js.vm-in .vision-mission-card > *:nth-child(3){ animation-delay: calc(var(--vm-d, 0s) + .56s); }
.vm.vm-js.vm-in .vision-mission-card > *:nth-child(4){ animation-delay: calc(var(--vm-d, 0s) + .67s); }
.vm.vm-js.vm-in .vision-mission-card > *:nth-child(n+5){ animation-delay: calc(var(--vm-d, 0s) + .78s); }

/* --- hover. The shared `.vm .vmimg:hover img` zoom is kept and enriched; this
       rule has identical specificity and simply sits later in the file. */
.vm .vmimg img{ transition: transform .5s cubic-bezier(.22,.61,.36,1), filter .5s ease; }
.vm .vmimg:hover img{ transform: scale(1.05); filter: brightness(1.04) contrast(1.03); }
.vm .vision-mission-card h3{ transition: transform .35s cubic-bezier(.22,.61,.36,1); }
.vm .vision-mission-card:hover h3{ transform: translateX(5px); }

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .vm .vmimg:hover img{ transform: none; filter: none; }
    .vm .vision-mission-card:hover h3{ transform: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .vm,
    .vm .vmimg img,
    .vm .vision-mission-card h3,
    .vm .vision-mission-card > *{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
}

/* ===========================================================================
   Services section (home) — entrance sequence + hover.

   Animation-only and additive. With JS off or reduced-motion on, the section
   renders exactly as designed.

   SCOPING NOTE: this section is `<section class="cusscroll bg-darkk pt-50
   pb-50">` — and the Departments section below it is byte-identical, right down
   to sharing `.service-card`, `.testimoimg` and `.position-relative`. There is
   no class or id that separates them, so the script tags this one with .sv-sec
   and every rule here hangs off that. Without it these styles would land on
   Departments too.

   The gesture is the ICON: it turns to face you on its vertical axis, like a
   badge being shown. The panel is black, so the accents are neutral white at
   low alpha.
   =========================================================================== */
@keyframes svSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes svViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes svCardUp{    from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes svWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the icon turns to face you. The perspective lives inside the transform, so no
   ancestor needs a `perspective` property and nothing becomes a containing
   block for the absolutely positioned icon. */
@keyframes svIconIn{
    from{ opacity: 0; transform: perspective(700px) rotateY(-95deg) scale(.85); }
    to  { opacity: 1; transform: perspective(700px) rotateY(0deg)   scale(1); }
}
@keyframes svTextUp{ from{ opacity: 0; transform: translateY(14px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes svIdlePulse{ 0%,100%{ transform: scale(1); } 50%{ transform: scale(1.06); } }

/* --- pre-hide (only while the script drives the reveal) */
.sv-sec.sv-js,
.sv-sec.sv-js h3 span.float-right,
.sv-sec.sv-js .service-card{ opacity: 0; }
.sv-sec .sv-head{ display: inline-block; color: inherit; }
.sv-sec.sv-js .sv-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.sv-sec.sv-js .service-card .testimoimg{ opacity: 0; }
.sv-sec.sv-js .service-card .position-relative > p{ clip-path: inset(-.2em 100% -.2em -.2em); }
.sv-sec.sv-js .service-card p.overelipsis3{ opacity: 0; }

/* --- staggered reveal; each card carries a --sv-d the inner beats offset from */
.sv-sec.sv-js.sv-in{ animation: svSectionUp .8s ease-out both; }
.sv-sec.sv-js.sv-in .sv-head{ animation: svWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.sv-sec.sv-js.sv-in h3 span.float-right{ animation: svViewIn .5s ease-out .45s both; }
.sv-sec.sv-js.sv-in .service-card{ animation: svCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.sv-sec.sv-js.sv-in .service-card .testimoimg{ animation: svIconIn .75s cubic-bezier(.22,.61,.36,1) calc(var(--sv-d, 0s) + .10s) both; }
.sv-sec.sv-js.sv-in .service-card .position-relative > p{ animation: svWipe .6s cubic-bezier(.22,.61,.36,1) calc(var(--sv-d, 0s) + .32s) both; }
.sv-sec.sv-js.sv-in .service-card p.overelipsis3{ animation: svTextUp .55s ease calc(var(--sv-d, 0s) + .48s) both; }

/* the heartbeat breathes the icon only — the copy never moves */
.sv-sec .service-card.sv-idle .testimoimg{ animation: svIdlePulse 1.3s ease-in-out; }
.sv-sec .service-card.sv-idle:hover .testimoimg{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.sv-sec h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.sv-sec h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.sv-sec h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.sv-sec h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- hover: the row leans toward the cursor and the icon gains a soft ring.
       The theme's own `.service-card:hover .text-hover-color` amber is
       untouched — it just eases now instead of snapping. */
.sv-sec .service-card{ transition: transform .4s cubic-bezier(.22,.61,.36,1); }
.sv-sec .service-card:hover{ transform: translateX(6px); }
.sv-sec .service-card .text-hover-color{ transition: color .3s ease; }
.sv-sec .service-card .testimoimg{ transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease; }
.sv-sec .service-card:hover .testimoimg{
    transform: scale(1.08);
    box-shadow: 0 0 0 6px rgba(255,255,255,.10);
}

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .sv-sec .service-card:hover{ transform: none; }
    .sv-sec .service-card:hover .testimoimg{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .sv-sec,
    .sv-sec h3,
    .sv-sec h3 span.float-right,
    .sv-sec .service-card,
    .sv-sec .service-card .position-relative > p,
    .sv-sec .service-card p.overelipsis3{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; transition: none !important; }
    .sv-sec .sv-head{ clip-path: none !important; animation: none !important; }
    .sv-sec .service-card .testimoimg,
    .sv-sec h3 span.float-right a{ opacity: 1 !important; transform: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .sv-sec h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Treatments section (home) — entrance sequence + hover.

   Animation-only and additive. With JS off or reduced-motion on, the section
   renders exactly as designed.

   The gesture is a LETTERBOX: each picture opens out of a thin horizontal band,
   the frame widening above and below until the whole image is there. Nothing
   else on the page opens on that axis.

   Scoped with .primary_section.treatments, which is this section and the
   treatments listing page — both are the same card grid, so the hover polish
   reading identically on each is intentional. `.treatments` alone would also
   have caught the sidebars on the department and treatment detail pages.
   =========================================================================== */
@keyframes trSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes trViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes trCardUp{    from{ opacity: 0; transform: translateY(35px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes trWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the frame opens out from a thin band. Negative end insets, so the picture is
   never trimmed at rest. */
@keyframes trBand{
    from{ opacity: 0; clip-path: inset(46% 0 46% 0);        transform: scale(1.06); }
    to  { opacity: 1; clip-path: inset(-.2em -.2em -.2em -.2em); transform: scale(1); }
}
@keyframes trTextUp{ from{ opacity: 0; transform: translateY(14px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes trIdlePulse{ 0%,100%{ transform: translateY(0); } 50%{ transform: translateY(-2px); } }

/* --- pre-hide (only while the script drives the reveal) */
.treatments.tr-js,
.treatments.tr-js h3 span.float-right,
.treatments.tr-js .treatments-card{ opacity: 0; }
.treatments .tr-head{ display: inline-block; color: inherit; }
.treatments.tr-js .tr-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.treatments.tr-js .treatments-card .card-img img{ opacity: 0; clip-path: inset(46% 0 46% 0); }
.treatments.tr-js .treatments-card h3.treattitle,
.treatments.tr-js .treatments-card p.overelipsis2{ opacity: 0; }

/* --- staggered reveal; each card carries a --tr-d the inner beats offset from */
.treatments.tr-js.tr-in{ animation: trSectionUp .8s ease-out both; }
.treatments.tr-js.tr-in .tr-head{ animation: trWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.treatments.tr-js.tr-in h3 span.float-right{ animation: trViewIn .5s ease-out .45s both; }
.treatments.tr-js.tr-in .treatments-card{ animation: trCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.treatments.tr-js.tr-in .treatments-card .card-img img{ animation: trBand .85s cubic-bezier(.22,.61,.36,1) calc(var(--tr-d, 0s) + .10s) both; }
.treatments.tr-js.tr-in .treatments-card h3.treattitle{ animation: trTextUp .5s ease calc(var(--tr-d, 0s) + .34s) both; }
.treatments.tr-js.tr-in .treatments-card p.overelipsis2{ animation: trTextUp .5s ease calc(var(--tr-d, 0s) + .48s) both; }

/* the heartbeat breathes the picture only — the copy below never moves */
.treatments .treatments-card.tr-idle .card-img img{ animation: trIdlePulse 1.2s ease-in-out; }
.treatments .treatments-card.tr-idle .card-img:hover img{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.primary_section.treatments h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.primary_section.treatments h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.primary_section.treatments h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.primary_section.treatments h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- hover, on the PICTURE only. Three things happen together: the shot pushes
       in, a gleam crosses it once, and a brand-coloured edge draws along the
       bottom of the frame. The copy underneath never reacts. */
@keyframes trGleam{
    0%  { opacity: 0; transform: translateX(-130%) skewX(-20deg); }
    12% { opacity: 1; }
    88% { opacity: 1; }
    100%{ opacity: 0; transform: translateX(330%)  skewX(-20deg); }
}
.primary_section.treatments .treatments-card .card-img{ position: relative; overflow: hidden; cursor: pointer; }
.primary_section.treatments .treatments-card .card-img img{
    transition: transform .6s cubic-bezier(.22,.61,.36,1), filter .6s ease;
    will-change: transform;
}
/* triggered by the picture itself, not the card, so moving the cursor over the
   name or the copy underneath does nothing at all */
.primary_section.treatments .treatments-card .card-img:hover img{
    transform: scale(1.09);
    filter: brightness(1.05) contrast(1.04);
}
/* the gleam */
.primary_section.treatments .treatments-card .card-img::before{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 38%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.30), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.primary_section.treatments .treatments-card .card-img:hover::before{ animation: trGleam .9s cubic-bezier(.4,0,.2,1); }
/* the edge, drawing left to right along the bottom of the frame */
.primary_section.treatments .treatments-card .card-img::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
    height: 3px; background: #F7B32B;
    transform: scaleX(0); transform-origin: left center;
    transition: transform .5s cubic-bezier(.22,.61,.36,1);
    pointer-events: none;
}
.primary_section.treatments .treatments-card .card-img:hover::after{ transform: scaleX(1); }
.primary_section.treatments .treatments-card h3.treattitle{ transition: color .3s ease; }

/* --- touch / small screens: drop the lift, keep the entrance */
@media (max-width: 767px), (hover: none){
    .primary_section.treatments .treatments-card .card-img:hover img{ transform: none; filter: none; }
    .primary_section.treatments .treatments-card .card-img:hover::before{ animation: none; }
    .primary_section.treatments .treatments-card .card-img:hover::after{ transform: scaleX(0); }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .treatments,
    .treatments h3,
    .treatments h3 span.float-right,
    .treatments .treatments-card,
    .treatments .treatments-card h3.treattitle,
    .treatments .treatments-card p.overelipsis2{ opacity: 1 !important; clip-path: none !important; transform: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .treatments .tr-head{ clip-path: none !important; animation: none !important; }
    .treatments .treatments-card .card-img img,
    .primary_section.treatments h3 span.float-right a{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .primary_section.treatments .treatments-card .card-img::before{ opacity: 0 !important; animation: none !important; }
    .primary_section.treatments .treatments-card .card-img::after{ transform: scaleX(0) !important; transition: none !important; }
    .primary_section.treatments h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Doctors section (home) — entrance sequence + card hover.

   Animation-only and additive. With JS off or reduced-motion on, the section
   renders exactly as designed.

   The gesture is a pair of DOORS: each portrait opens from a line down its
   centre, the frame widening left and right. Treatments opens on the other
   axis, so the two sit either side of the same idea without repeating it.

   Scoped with #doctors. The plain `.doctors` class is no good here — the
   Vision / Mission section on this very page also carries it, as do the doctor,
   department and treatment detail pages.
   =========================================================================== */
@keyframes drSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes drViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes drCardUp{    from{ opacity: 0; transform: translateY(35px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes drWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the portrait opens from its centre line outwards. Negative end insets, so the
   picture is never trimmed at rest. */
@keyframes drDoors{
    from{ opacity: 0; clip-path: inset(0 50% 0 50%);            transform: scale(1.05); }
    to  { opacity: 1; clip-path: inset(-.2em -.2em -.2em -.2em); transform: scale(1); }
}
@keyframes drTextUp{ from{ opacity: 0; transform: translateY(13px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes drIdlePulse{ 0%,100%{ transform: translateY(0); } 50%{ transform: translateY(-2px); } }

/* --- pre-hide (only while the script drives the reveal) */
#doctors.dr-js,
#doctors.dr-js h3 span.float-right,
#doctors.dr-js .doccard{ opacity: 0; }
#doctors .dr-head{ display: inline-block; color: inherit; }
#doctors.dr-js .dr-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
#doctors.dr-js .doccard-img img{ opacity: 0; clip-path: inset(0 50% 0 50%); }
#doctors.dr-js .doccard p.fw-600{ clip-path: inset(-.2em 100% -.2em -.2em); }
#doctors.dr-js .doccard h3.doctitle,
#doctors.dr-js .doccard p.overelipsis2,
#doctors.dr-js .doccard .btn.btnthird{ opacity: 0; }

/* --- staggered reveal; each card carries a --dr-d the inner beats offset from */
#doctors.dr-js.dr-in{ animation: drSectionUp .8s ease-out both; }
#doctors.dr-js.dr-in .dr-head{ animation: drWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
#doctors.dr-js.dr-in h3 span.float-right{ animation: drViewIn .5s ease-out .45s both; }
#doctors.dr-js.dr-in .doccard{ animation: drCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
#doctors.dr-js.dr-in .doccard-img img{ animation: drDoors .85s cubic-bezier(.22,.61,.36,1) calc(var(--dr-d, 0s) + .10s) both; }
#doctors.dr-js.dr-in .doccard p.fw-600{ animation: drWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--dr-d, 0s) + .32s) both; }
#doctors.dr-js.dr-in .doccard h3.doctitle{ animation: drTextUp .5s ease calc(var(--dr-d, 0s) + .46s) both; }
#doctors.dr-js.dr-in .doccard p.overelipsis2{ animation: drTextUp .5s ease calc(var(--dr-d, 0s) + .58s) both; }
#doctors.dr-js.dr-in .doccard .btn.btnthird{ animation: drTextUp .5s ease calc(var(--dr-d, 0s) + .70s) both; }

/* the heartbeat breathes the portrait only — the copy below never moves */
#doctors .doccard.dr-idle .doccard-img img{ animation: drIdlePulse 1.2s ease-in-out; }
#doctors .doccard.dr-idle:hover .doccard-img img{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
#doctors h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
#doctors h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
#doctors h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
#doctors h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- hover. The shared `.doccard:hover .doccard-img img` zoom is kept and
       enriched; this rule is more specific, so it simply takes over. */
#doctors .doccard-img{ position: relative; overflow: hidden; }
#doctors .doccard-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
#doctors .doccard:hover .doccard-img img{
    transform: translateY(-5px) scale(1.05);
    filter: brightness(1.03) contrast(1.03);
}
#doctors .doccard{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
#doctors .doccard:hover{ transform: translateY(-6px); box-shadow: 0 16px 30px rgba(0,0,0,.16); }

/* the owl wrapper would slice the card lift and its shadow off; the breathing
   room is cancelled by an equal negative margin, so nothing moves */
#doctors .owl-carousel .owl-wrapper-outer{ padding: 26px 0; margin: -26px 0; }
#doctors .owl-carousel .owl-buttons{ margin-top: 26px; }

/* --- touch / small screens: drop the lift, keep the entrance */
@media (max-width: 767px), (hover: none){
    #doctors .doccard:hover{ transform: none; box-shadow: none; }
    #doctors .doccard:hover .doccard-img img{ transform: none; filter: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    #doctors,
    #doctors h3,
    #doctors h3 span.float-right,
    #doctors .doccard,
    #doctors .doccard p.fw-600,
    #doctors .doccard h3.doctitle,
    #doctors .doccard p.overelipsis2,
    #doctors .doccard .btn.btnthird{ opacity: 1 !important; clip-path: none !important; transform: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    #doctors .dr-head{ clip-path: none !important; animation: none !important; }
    #doctors .doccard-img img,
    #doctors h3 span.float-right a{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    #doctors h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Departments section (home) — entrance sequence + hover.

   Animation-only and additive. With JS off or reduced-motion on, the section
   renders exactly as designed.

   SCOPING NOTE: exactly the same trap as Services — this section carries only
   "cusscroll bg-darkk pt-50 pb-50", identical to Services, and the two share
   .service-card, .testimoimg and .position-relative. The script tags this one
   .dp-sec and Services .sv-sec, so the two sets of rules stay disjoint.

   Departments is deliberately built as the MIRROR of Services: its cards enter
   from the right where Services rises, its icon drops and bounces where the
   Services icon turns, and it leans left on hover where Services leans right.
   Same family, read as a pair, never the same move twice.
   =========================================================================== */
@keyframes dpSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes dpViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
/* cards arrive from the right — the mirror of the Services rise */
@keyframes dpCardIn{    from{ opacity: 0; transform: translateX(34px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes dpWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the icon drops in and settles with a bounce */
@keyframes dpIconIn{
    0%  { opacity: 0; transform: translateY(-20px) scale(.55); }
    60% { opacity: 1; transform: translateY(3px)   scale(1.08); }
    100%{ opacity: 1; transform: translateY(0)     scale(1); }
}
@keyframes dpTextUp{ from{ opacity: 0; transform: translateY(14px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes dpIdlePulse{ 0%,100%{ transform: scale(1); } 50%{ transform: scale(1.06); } }

/* --- pre-hide (only while the script drives the reveal) */
.dp-sec.dp-js,
.dp-sec.dp-js h3 span.float-right,
.dp-sec.dp-js .service-card{ opacity: 0; }
.dp-sec .dp-head{ display: inline-block; color: inherit; }
.dp-sec.dp-js .dp-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.dp-sec.dp-js .service-card .testimoimg{ opacity: 0; }
.dp-sec.dp-js .service-card .position-relative h3{ clip-path: inset(-.2em 100% -.2em -.2em); }
.dp-sec.dp-js .service-card p.peoplereview{ opacity: 0; }

/* --- staggered reveal; each card carries a --dp-d the inner beats offset from */
.dp-sec.dp-js.dp-in{ animation: dpSectionUp .8s ease-out both; }
.dp-sec.dp-js.dp-in .dp-head{ animation: dpWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.dp-sec.dp-js.dp-in h3 span.float-right{ animation: dpViewIn .5s ease-out .45s both; }
.dp-sec.dp-js.dp-in .service-card{ animation: dpCardIn .7s cubic-bezier(.22,.61,.36,1) both; }
.dp-sec.dp-js.dp-in .service-card .testimoimg{ animation: dpIconIn .75s cubic-bezier(.34,1.56,.64,1) calc(var(--dp-d, 0s) + .10s) both; }
.dp-sec.dp-js.dp-in .service-card .position-relative h3{ animation: dpWipe .6s cubic-bezier(.22,.61,.36,1) calc(var(--dp-d, 0s) + .32s) both; }
.dp-sec.dp-js.dp-in .service-card p.peoplereview{ animation: dpTextUp .55s ease calc(var(--dp-d, 0s) + .48s) both; }

/* the heartbeat breathes the icon only — the copy never moves */
.dp-sec .service-card.dp-idle .testimoimg{ animation: dpIdlePulse 1.3s ease-in-out; }
.dp-sec .service-card.dp-idle:hover .testimoimg{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.dp-sec h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.dp-sec h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.dp-sec h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.dp-sec h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- hover: the row leans LEFT, mirroring the way Services leans right, and the
       icon gains a soft ring. The theme's own `.service-card:hover
       .text-hover-color` amber is untouched — it just eases now. */
.dp-sec .service-card{ transition: transform .4s cubic-bezier(.22,.61,.36,1); }
.dp-sec .service-card:hover{ transform: translateX(-6px); }
.dp-sec .service-card .text-hover-color{ transition: color .3s ease; }
.dp-sec .service-card .testimoimg{ transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease; }
.dp-sec .service-card:hover .testimoimg{
    transform: scale(1.08);
    box-shadow: 0 0 0 6px rgba(255,255,255,.10);
}

/* the icon drops in from above its resting spot, so the owl wrapper needs the
   headroom; cancelled by an equal negative margin, so nothing moves */
.dp-sec .owl-carousel .owl-wrapper-outer{ padding: 24px 0; margin: -24px 0; }
.dp-sec .owl-carousel .owl-buttons{ margin-top: 24px; }

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .dp-sec .service-card:hover{ transform: none; }
    .dp-sec .service-card:hover .testimoimg{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .dp-sec,
    .dp-sec h3,
    .dp-sec h3 span.float-right,
    .dp-sec .service-card,
    .dp-sec .service-card .position-relative h3,
    .dp-sec .service-card p.peoplereview{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; transition: none !important; }
    .dp-sec .dp-head{ clip-path: none !important; animation: none !important; }
    .dp-sec .service-card .testimoimg,
    .dp-sec h3 span.float-right a{ opacity: 1 !important; transform: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .dp-sec h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Photo Gallery section (home) — entrance sequence + hover.

   Animation-only and additive. With JS off or reduced-motion on, the section
   renders exactly as designed.

   The gesture is a CAMERA PULLING BACK: each album photo starts heavily zoomed
   and eases out to frame the shot, then the album name is uncovered under it.
   `.albumcss` already carries overflow:hidden, so the whole move is contained
   inside the existing frame with no layout change at all.

   The album name is matched as `.albumcss + h3` rather than by class, because
   the section's own heading is an h3 too.
   =========================================================================== */
@keyframes pgSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes pgViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes pgWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the shot is framed: a heavy zoom easing back to rest */
@keyframes pgPullBack{
    from{ opacity: 0; transform: scale(1.32); }
    to  { opacity: 1; transform: scale(1); }
}
/* the "More Photos" banner already appears on hover via a display toggle, which
   cannot transition — this gives it a slide instead of a pop */
@keyframes pgBanner{ from{ opacity: 0; transform: translateY(14px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes pgIdlePulse{ 0%,100%{ transform: scale(1); } 50%{ transform: scale(1.03); } }

/* --- pre-hide (only while the script drives the reveal) */
.photo_gallery_homepage.pg-js,
.photo_gallery_homepage.pg-js h3 span.float-right{ opacity: 0; }
.photo_gallery_homepage .pg-head{ display: inline-block; color: inherit; }
.photo_gallery_homepage.pg-js .pg-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.photo_gallery_homepage.pg-js .albumcss img{ opacity: 0; }
.photo_gallery_homepage.pg-js .albumcss + h3{ clip-path: inset(-.2em 100% -.2em -.2em); }

/* --- staggered reveal; each album carries a --pg-d the inner beats offset from */
.photo_gallery_homepage.pg-js.pg-in{ animation: pgSectionUp .8s ease-out both; }
.photo_gallery_homepage.pg-js.pg-in .pg-head{ animation: pgWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.photo_gallery_homepage.pg-js.pg-in h3 span.float-right{ animation: pgViewIn .5s ease-out .45s both; }
.photo_gallery_homepage.pg-js.pg-in .albumcss img{ animation: pgPullBack .95s cubic-bezier(.22,.61,.36,1) calc(var(--pg-d, 0s) + .10s) both; }
.photo_gallery_homepage.pg-js.pg-in .albumcss + h3{ animation: pgWipe .6s cubic-bezier(.22,.61,.36,1) calc(var(--pg-d, 0s) + .40s) both; }

/* the heartbeat breathes the photograph only — the album name never moves */
.photo_gallery_homepage .albumcss.pg-idle img{ animation: pgIdlePulse 1.3s ease-in-out; }
.photo_gallery_homepage .albumcss.pg-idle:hover img{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.photo_gallery_homepage h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.photo_gallery_homepage h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.photo_gallery_homepage h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.photo_gallery_homepage h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- hover: the shot pushes back IN, the opposite of the way it arrived, and
       the existing "More Photos" banner now slides up rather than popping. */
.photo_gallery_homepage .albumcss img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.photo_gallery_homepage .albumcss:hover img{
    transform: scale(1.07);
    filter: brightness(1.03) contrast(1.03);
}
.photo_gallery_homepage .albumcss:hover .allimgnums{ animation: pgBanner .35s cubic-bezier(.22,.61,.36,1); }
.photo_gallery_homepage .albumcss + h3{ transition: transform .35s cubic-bezier(.22,.61,.36,1); }
.photo_gallery_homepage a:hover .albumcss + h3{ transform: translateY(-2px); }

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .photo_gallery_homepage .albumcss:hover img{ transform: none; filter: none; }
    .photo_gallery_homepage a:hover .albumcss + h3{ transform: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .photo_gallery_homepage,
    .photo_gallery_homepage h3,
    .photo_gallery_homepage h3 span.float-right,
    .photo_gallery_homepage .albumcss + h3{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; transition: none !important; }
    .photo_gallery_homepage .pg-head{ clip-path: none !important; animation: none !important; }
    .photo_gallery_homepage .albumcss img,
    .photo_gallery_homepage h3 span.float-right a{ opacity: 1 !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .photo_gallery_homepage .albumcss:hover .allimgnums{ animation: none !important; }
    .photo_gallery_homepage h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Video Gallery section (home) — entrance sequence + hover.

   Animation-only and additive. With JS off or reduced-motion on, the section
   renders exactly as designed.

   The gesture belongs to the PLAY BUTTON: the thumbnail settles, then the play
   control pops in with a ring pulsing out of it, then the title is uncovered
   beside it. The idle heartbeat pulses that same button rather than the
   picture — on a video card the play control is the thing that should look
   alive.

   This section is always a slider; there is no row fallback in the markup.
   =========================================================================== */
@keyframes vgSectionUp{ from{ opacity: 0; transform: translateY(30px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes vgViewIn{    from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes vgCardUp{    from{ opacity: 0; transform: translateY(32px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes vgWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
@keyframes vgThumbIn{ from{ opacity: 0; transform: scale(1.1); } to{ opacity: 1; transform: scale(1); } }
/* the play control arrives with a ring pushing out of it and ending clear */
@keyframes vgPlayIn{
    0%  { opacity: 0; transform: scale(.3);  box-shadow: 0 0 0 0    rgba(255,255,255,.45); }
    60% { opacity: 1; transform: scale(1.15); box-shadow: 0 0 0 14px rgba(255,255,255,.14); }
    100%{ opacity: 1; transform: scale(1);   box-shadow: 0 0 0 26px rgba(255,255,255,0); }
}
/* the idle beacon: the play control breathes, not the picture */
@keyframes vgPlayPulse{
    0%,100%{ transform: scale(1);    box-shadow: 0 0 0 0    rgba(255,255,255,0); }
    50%    { transform: scale(1.12); box-shadow: 0 0 0 12px rgba(255,255,255,.12); }
}

/* --- pre-hide (only while the script drives the reveal) */
.video_gallery_homepage.vg-js,
.video_gallery_homepage.vg-js h3 span.float-right,
.video_gallery_homepage.vg-js .vedioimg{ opacity: 0; }
.video_gallery_homepage .vg-head{ display: inline-block; color: inherit; }
.video_gallery_homepage.vg-js .vg-head{ clip-path: inset(-.2em 100% -.2em -.2em); }
.video_gallery_homepage.vg-js .vedioimg .videoimg{ opacity: 0; }
.video_gallery_homepage.vg-js .vedioimg .playbtnimgvideo{ opacity: 0; }
.video_gallery_homepage.vg-js .vedioimg span.vidtitle{ clip-path: inset(-.2em 100% -.2em -.2em); }

/* --- staggered reveal; each card carries a --vg-d the inner beats offset from */
.video_gallery_homepage.vg-js.vg-in{ animation: vgSectionUp .8s ease-out both; }
.video_gallery_homepage.vg-js.vg-in .vg-head{ animation: vgWipe .8s cubic-bezier(.22,.61,.36,1) .2s both; }
.video_gallery_homepage.vg-js.vg-in h3 span.float-right{ animation: vgViewIn .5s ease-out .45s both; }
.video_gallery_homepage.vg-js.vg-in .vedioimg{ animation: vgCardUp .7s cubic-bezier(.22,.61,.36,1) both; }
.video_gallery_homepage.vg-js.vg-in .vedioimg .videoimg{ animation: vgThumbIn .8s cubic-bezier(.22,.61,.36,1) calc(var(--vg-d, 0s) + .10s) both; }
.video_gallery_homepage.vg-js.vg-in .vedioimg .playbtnimgvideo{ animation: vgPlayIn .7s cubic-bezier(.34,1.56,.64,1) calc(var(--vg-d, 0s) + .32s) both; }
.video_gallery_homepage.vg-js.vg-in .vedioimg span.vidtitle{ animation: vgWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--vg-d, 0s) + .50s) both; }

/* the heartbeat pulses the play control — the picture and title never move */
.video_gallery_homepage .vedioimg.vg-idle .playbtnimgvideo{ animation: vgPlayPulse 1.5s ease-in-out; }
.video_gallery_homepage .vedioimg.vg-idle:hover .playbtnimgvideo{ animation: none; }

/* --- "View All": underline grows from the left, text lifts */
.video_gallery_homepage h3 span.float-right a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.video_gallery_homepage h3 span.float-right a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
    background: currentColor;                  /* takes the link's own colour */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.video_gallery_homepage h3 span.float-right a:hover{ transform: translateY(-2px); text-decoration: none; }
.video_gallery_homepage h3 span.float-right a:hover::after{ transform: scaleX(1); }

/* --- hover: the picture pushes in behind its gradient and the play control
       swells with a ring. The theme's own amber on span.vidtitle is untouched —
       it just eases now instead of snapping. */
.video_gallery_homepage .vedioimg{ overflow: hidden; }
.video_gallery_homepage .vedioimg .videoimg{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.video_gallery_homepage .vedioimg:hover .videoimg{
    transform: scale(1.06);
    filter: brightness(1.04) contrast(1.03);
}
.video_gallery_homepage .playbtnimgvideo{ transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease; border-radius: 50%; }
.video_gallery_homepage .vedioimg:hover .playbtnimgvideo{
    transform: scale(1.15);
    box-shadow: 0 0 0 10px rgba(255,255,255,.12);
}
.video_gallery_homepage .videogallery span.vidtitle{ transition: color .3s ease; }

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .video_gallery_homepage .vedioimg:hover .videoimg{ transform: none; filter: none; }
    .video_gallery_homepage .vedioimg:hover .playbtnimgvideo{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .video_gallery_homepage,
    .video_gallery_homepage h3,
    .video_gallery_homepage h3 span.float-right,
    .video_gallery_homepage .vedioimg,
    .video_gallery_homepage .vedioimg span.vidtitle{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; transition: none !important; }
    .video_gallery_homepage .vg-head{ clip-path: none !important; animation: none !important; }
    .video_gallery_homepage .vedioimg .videoimg,
    .video_gallery_homepage .vedioimg .playbtnimgvideo,
    .video_gallery_homepage h3 span.float-right a{ opacity: 1 !important; transform: none !important; filter: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .video_gallery_homepage h3 span.float-right a::after{ transform: scaleX(0) !important; transition: none !important; }
}

/* ===========================================================================
   Book Appointment strip + Footer — entrance sequences and hover.

   These live in layout/footer.php, so unlike the home-page sections everything
   here runs on EVERY page. One script at the end of that file drives both.

   Animation-only and additive. With JS off or reduced-motion on, both render
   exactly as designed.

   The strip is the site's primary call to action, so it gets the most
   deliberate treatment: the headline rises out of nothing, the contact rows
   arrive from the right where they sit, and the button lands last with a little
   overshoot. After that the button carries a slow recurring sheen — the one
   piece of looping motion on the page, because this is the one element that
   should keep asking to be clicked.

   The footer's signature is its own existing ornament: the 420px rules either
   side of "Menu" and "Follow me" now DRAW OUTWARD from their label instead of
   simply being there.
   =========================================================================== */

/* ---------- Book Appointment strip ---------- */
@keyframes bkSectionUp{ from{ opacity: 0; transform: translateY(26px); } to{ opacity: 1; transform: translateY(0); } }
/* the headline rises out of nothing — appropriate for "book an appointment",
   where the whole gesture of the section is forward and upward. Negative end
   insets, so no glyph is ever shaved. */
@keyframes bkHeadUp{
    from{ opacity: 0; transform: perspective(1100px) rotateX(-48deg) translateY(34px); filter: blur(9px); }
    to  { opacity: 1; transform: perspective(1100px) rotateX(0deg)   translateY(0);    filter: blur(0); }
}
/* the contact rows arrive from the right, the side they sit on */
@keyframes bkRowIn{ from{ opacity: 0; transform: translateX(38px); } to{ opacity: 1; transform: translateX(0); } }
/* the glyphs spin in rather than merely appearing */
@keyframes bkIconIn{
    0%  { opacity: 0; transform: scale(.15) rotate(-160deg); }
    65% { opacity: 1; transform: scale(1.3) rotate(12deg); }
    100%{ opacity: 1; transform: scale(1)   rotate(0deg); }
}
@keyframes bkBtnIn{
    0%  { opacity: 0; transform: translateY(20px) scale(.82); }
    62% { opacity: 1; transform: translateY(0)    scale(1.1); }
    100%{ opacity: 1; transform: translateY(0)    scale(1); }
}
/* Two warm light fields drift across the amber panel at different speeds, which
   is what stops a flat block of colour reading as flat. Pure white at low alpha
   — light over the existing colour, never a new hue. */
@keyframes bkDriftA{
    0%,100%{ transform: translate3d(-4%, -3%, 0) scale(1); }
    50%    { transform: translate3d( 5%,  4%, 0) scale(1.14); }
}
@keyframes bkDriftB{
    0%,100%{ transform: translate3d( 6%,  4%, 0) scale(1.1); }
    50%    { transform: translate3d(-5%, -4%, 0) scale(1); }
}
/* The call to action breathes for as long as the strip is on screen. The lift is
   read from a custom property so hovering can raise the button WHILE it breathes
   — two animations cannot both own `transform`, but one can read the other's
   value. */
@keyframes bkBreathe{
    0%,100%{ transform: translateY(var(--bk-lift, 0px)) scale(1); }
    50%    { transform: translateY(var(--bk-lift, 0px)) scale(1.04); }
}
/* A sheen that crosses the button, then waits. The sweep occupies the first
   fifth of the cycle and the rest is deliberately idle, which is how a "every
   few seconds" rhythm is expressed in pure CSS. */
@keyframes bkSheenLoop{
    0%   { opacity: 0; transform: translateX(-150%) skewX(-20deg); }
    3%   { opacity: 1; }
    17%  { opacity: 1; }
    20%  { opacity: 0; transform: translateX(350%)  skewX(-20deg); }
    100% { opacity: 0; transform: translateX(350%)  skewX(-20deg); }
}

/* registered so the hover lift can ease in and out while the breathe animation
   owns `transform` (falls back to an instant lift without @property support) */
@property --bk-lift{ syntax: '<length>'; initial-value: 0px; inherits: false; }

/* --- the living panel. Two drifting light fields sit behind the content; the
       container is lifted above them so nothing overlays the copy. Only
       position/overflow/z-index are involved, so nothing moves. */
.bookappfooter{ position: relative; overflow: hidden; }
.bookappfooter > .container,
.bookappfooter > .container-fluid{ position: relative; z-index: 1; }
.bookappfooter::before,
.bookappfooter::after{
    content: '';
    position: absolute; top: -25%; left: -25%;
    width: 150%; height: 150%;
    pointer-events: none;
    opacity: 0;
    transition: opacity 1.2s ease;
}
.bookappfooter::before{
    background:
        radial-gradient(38% 44% at 22% 30%, rgba(255,255,255,.42), rgba(255,255,255,0) 68%),
        radial-gradient(30% 34% at 74% 66%, rgba(255,255,255,.28), rgba(255,255,255,0) 70%);
}
.bookappfooter::after{
    background:
        radial-gradient(26% 30% at 62% 22%, rgba(255,255,255,.30), rgba(255,255,255,0) 70%),
        radial-gradient(34% 38% at 34% 80%, rgba(255,255,255,.22), rgba(255,255,255,0) 72%);
}
/* they only come alive once the strip has finished arriving */
.bookappfooter.bk-glow::before{ opacity: 1; animation: bkDriftA 17s ease-in-out infinite; }
.bookappfooter.bk-glow::after{  opacity: 1; animation: bkDriftB 23s ease-in-out infinite; }

/* --- pre-hide (only while the script drives the reveal) */
.bookappfooter.bk-js{ opacity: 0; }
/* the headline hinges up from its own baseline rather than its middle */
.bookappfooter .col-md-8 > p{ transform-origin: bottom center; }
.bookappfooter.bk-js .col-md-8 > p{ opacity: 0; }
.bookappfooter.bk-js .c_row{ opacity: 0; }
/* .c_icon is forced to 0x0 in this strip, so it is the glyph inside that is
   actually visible and therefore the thing worth animating */
.bookappfooter.bk-js .c_row .c_icon i{ opacity: 0; }
.bookappfooter.bk-js .btnsecondary{ opacity: 0; }

/* --- reveal; per-element delays are assigned by the script */
.bookappfooter.bk-js.bk-in{ animation: bkSectionUp .8s ease-out both; }
.bookappfooter.bk-js.bk-in .col-md-8 > p{ animation: bkHeadUp .95s cubic-bezier(.22,.61,.36,1) .15s both; }
.bookappfooter.bk-js.bk-in .c_row{ animation: bkRowIn .6s cubic-bezier(.22,.61,.36,1) both; }
.bookappfooter.bk-js.bk-in .c_row .c_icon i{ animation: bkIconIn .55s cubic-bezier(.34,1.56,.64,1) var(--bk-icon-d, 0s) both; }
.bookappfooter.bk-js.bk-in .btnsecondary{ animation: bkBtnIn .7s cubic-bezier(.34,1.56,.64,1) both; }

/* --- the sheen, once the strip has finished arriving */
.bookappfooter .btnsecondary{ position: relative; overflow: hidden; }
.bookappfooter .btnsecondary::before{
    content: '';
    position: absolute; top: 0; left: 0;
    width: 26%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.22), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.bookappfooter.bk-glow .btnsecondary::before{ animation: bkSheenLoop 4.5s linear infinite; }
/* ...and the button breathes the whole time it is on screen */
.bookappfooter.bk-glow .btnsecondary{ animation: bkBreathe 3.4s ease-in-out infinite; }

/* --- hover on the call to action.
       The theme flips this button from its secondary colours to its primary ones
       on hover and adds `border: 1px solid` — but the button carries `border-0`,
       so that border makes the box 2px bigger and the whole button jumps. That
       jitter is much more obvious once the colours ease rather than snap, so the
       border is suppressed here and drawn as a 1px INSET SHADOW instead:
       identical 1px line, `currentColor` so it is the exact same colour the
       theme asked for, and no reflow. Nothing about the look changes. */
.bookappfooter .btnsecondary{
    transition: background-color .35s ease, color .35s ease,
                box-shadow .4s ease, --bk-lift .4s cubic-bezier(.22,.61,.36,1),
                transform .4s cubic-bezier(.22,.61,.36,1);
}
.bookappfooter .btnsecondary:hover{
    border: 0 !important;
    /* the designed 1px line, a tight ring of light, and a deep drop — an outer
       box-shadow is not clipped by the button's own overflow, so all three read */
    box-shadow: inset 0 0 0 1px currentColor,
                0 0 0 7px rgba(255,255,255,.22),
                0 20px 40px rgba(0,0,0,.30);
    --bk-lift: -5px;                /* consumed by the breathe keyframes above */
    transform: translateY(-5px);    /* fallback for when the breathe is not running */
}
/* the phone and email rows lean toward the cursor, their glyph leading */
.bookappfooter .c_row a{ display: inline-block; transition: transform .3s cubic-bezier(.22,.61,.36,1); }
.bookappfooter .c_row a:hover{ transform: translateX(6px); text-decoration: none; }
.bookappfooter .c_row .c_icon i{ transition: transform .4s cubic-bezier(.34,1.56,.64,1); }
.bookappfooter .c_row:hover .c_icon i{ transform: scale(1.3) rotate(-10deg); }

/* ---------- Footer ---------- */
/* the heading arrives out of focus and sharpens, which gives a flat dark panel
   an actual sense of depth */
@keyframes ftUp{
    from{ opacity: 0; transform: translateY(22px); filter: blur(6px); }
    to  { opacity: 1; transform: translateY(0);    filter: blur(0); }
}
@keyframes ftPop{
    0%  { opacity: 0; transform: scale(.25) rotate(-140deg); }
    65% { opacity: 1; transform: scale(1.28) rotate(10deg); }
    100%{ opacity: 1; transform: scale(1)   rotate(0deg); }
}
/* the two rules either side of a label draw outward from it */
@keyframes ftLine{ from{ transform: scaleX(0); } to{ transform: scaleX(1); } }
/* ...and then a spark keeps running out along each of them. The travel occupies
   the first 45% of the cycle and the rest is idle, which is how a recurring
   rhythm is written in pure CSS. */
@keyframes ftSparkL{
    0%   { background-position: 430px 0; }
    45%  { background-position: -100px 0; }
    100% { background-position: -100px 0; }
}
@keyframes ftSparkR{
    0%   { background-position: -100px 0; }
    45%  { background-position: 430px 0; }
    100% { background-position: 430px 0; }
}
/* Two fields of light motes drift across the dark panel at different speeds and
   in opposite directions, which reads as depth rather than as a pattern. Pure
   white at low alpha — light over the existing colour, never a new hue. */
@keyframes ftMotesA{
    0%,100%{ transform: translate3d(-3%,  3%, 0); }
    50%    { transform: translate3d( 3%, -3%, 0); }
}
@keyframes ftMotesB{
    0%,100%{ transform: translate3d( 4%, -2%, 0) scale(1.05); }
    50%    { transform: translate3d(-4%,  2%, 0) scale(1); }
}
/* the dot fields double as a starfield: each layer's background-position is
   walked down by exactly one background-size tile, so the loop point is
   invisible and the dots read as continuously falling rather than looping.
   Runs alongside the drift above — different property, same element, no
   conflict — so the field still sways gently while the stars stream through
   it. .after's second (spotlight) layer is repeated unchanged each keyframe
   so only its star layer moves. */
@keyframes ftStarsFallA{
    0%   { background-position: 0 0; }
    100% { background-position: 0 132px; }
}
@keyframes ftStarsFallB{
    0%   { background-position: 70px 90px,  0 0; }
    100% { background-position: 70px 316px, 0 0; }
}

/* --- the living panel. Two mote fields sit behind the content, oversized so the
       drift never exposes an edge, and the container is lifted above them.
       Only position/overflow/z-index are involved, so nothing moves. */
footer{ position: relative; overflow: hidden; }
footer > .container,
footer > .container-fluid{ position: relative; z-index: 1; }
footer::before,
footer::after{
    content: '';
    position: absolute; top: -25%; left: -25%;
    width: 150%; height: 150%;
    pointer-events: none;
    opacity: 0;
    transition: opacity 1.6s ease;
}
footer::before{
    background-image: radial-gradient(circle, rgba(255,255,255,.55) 1.1px, rgba(255,255,255,0) 1.7px);
    background-size: 132px 132px;
}
footer::after{
    background-image:
        radial-gradient(circle, rgba(255,255,255,.34) 1.4px, rgba(255,255,255,0) 2.1px),
        radial-gradient(46% 40% at 50% 8%, rgba(255,255,255,.07), rgba(255,255,255,0) 70%);
    background-size: 226px 226px, 100% 100%;
    background-position: 70px 90px, 0 0;
}
/* they only come alive once the footer has finished arriving */
footer.ft-glow::before{ opacity: .55; animation: ftMotesA 26s ease-in-out infinite, ftStarsFallA 7s linear infinite; }
footer.ft-glow::after{  opacity: .70; animation: ftMotesB 34s ease-in-out infinite, ftStarsFallB 9s linear infinite; }

/* --- occasional meteors. Three of them fall right ACROSS the whole panel,
       entering above the top edge and burning out near the bottom, each idle
       for the great majority of its own cycle.

       On path length, which is the thing that was wrong before: for a given
       vertical drop H the path is H / sin(θ), so a STEEPER angle gives a
       SHORTER streak. At 58° a 300px path was only 159px across and 254px
       down — a stub in one corner. Easing the angle back to 42°-50° and
       pushing travel to 720-900px roughly quadruples the visible sweep while
       staying unambiguously a fall (at 46° the motion is still 72% vertical).
       The end distances are set so each meteor's fade completes just as it
       reaches the bottom edge: it burns out in view instead of being clipped
       mid-flight, which is both prettier and what real ones do.

       The rest of what makes it read as a meteor rather than a sliding streak:

       a) The tail TRAILS the head. Each span is a zero-size point; the head dot
          is centred on it and the tail is pinned `right:0`, so the tail body
          occupies local x from -len to 0 — i.e. entirely BEHIND the point.
          Travel is then `rotate(θ) translateX(+d)`, which moves along the
          element's own local +x, so the head always leads and the tail always
          drags back along the flight path, at every angle, for free.
       b) The trail is a tapered WEDGE, not a bar — clip-path narrows it to a
          point at the far end, and the gradient holds nearly all its light in
          the last third behind the head, so the far end is a faint wisp. On a
          300px trail a flat linear fade looks like a painted stick.
       c) The brightness is asymmetric: it snaps to peak in ~12% of the streak,
          then burns out over the rest. Real meteors never fade in.
       d) It slows slightly as it dies, via a per-keyframe timing function on
          the burn-out segments only (the idle stretch stays linear). Kept
          gentle on purpose — a strong ease-out reads as braking, not burning.
       e) All three fall near-parallel (42°-50°). Criss-crossing directions read
          as chaos; parallel reads as sky.
       f) Speed follows distance: the near one covers 960px at ~565px/s, the far
          one 780px at ~390px/s. Nearer = faster is the parallax cue, and it
          runs the same way as the tail-length and brightness cues below.
       g) Trail length, thickness, head size and peak brightness all step down
          together, so the short dim ones sit visibly further away.

       Timing: periods 11s / 17s / 23s are pairwise coprime, so the three only
       realign every 11x17x23 = 4301s (~72 min). Combined they average one
       meteor every ~5s. There is no random number here and none is needed —
       the flashes never settle into a readable rhythm.

       Markup is three empty aria-hidden spans first inside <footer>. They share
       .container's z-index and precede it in document order, so they paint
       above both dust fields but below every piece of real content. Gated on
       .ft-glow, so nothing loops until the entrance has finished, exactly like
       the dust above. */
footer .ft-shoot{
    position: absolute;
    width: 0; height: 0;          /* a point: both parts are placed relative to it */
    z-index: 1;
    pointer-events: none;
    opacity: 0;
}
/* the trail — pinned to the point's right edge so it extends BACKWARDS only.
   Nearly all the light sits in the last third, behind the head; the far 40% is
   a faint wisp, which is what stops a 300px trail looking like a painted bar. */
footer .ft-shoot::before{
    content: '';
    position: absolute;
    right: 0;
    top: calc(var(--ft-thick, 3px) / -2);
    width: var(--ft-len, 240px); height: var(--ft-thick, 3px);
    background: linear-gradient(90deg,
        rgba(255,255,255,0)    0%,
        rgba(255,255,255,.10) 40%,
        rgba(255,255,255,.38) 72%,
        rgba(255,255,255,.92) 100%);
    clip-path: polygon(0 50%, 100% 0, 100% 100%);   /* apex at the far end */
}
/* the burning head, centred exactly on the point */
footer .ft-shoot::after{
    content: '';
    position: absolute;
    right: calc(var(--ft-head, 4px) / -2);
    top:   calc(var(--ft-head, 4px) / -2);
    width: var(--ft-head, 4px); height: var(--ft-head, 4px);
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 7px 1px rgba(255,255,255,.8);
}

/* all three start above the top edge, so each falls INTO frame rather than
   materialising inside it, and they are spread left-to-right so their paths
   together sweep the whole panel instead of stacking in one corner */
footer .ft-shoot-1{ top: -18%; left:  2%; --ft-len: 320px; --ft-thick: 4px;   --ft-head: 5px; }
footer .ft-shoot-2{ top: -12%; left: 30%; --ft-len: 240px; --ft-thick: 3px;   --ft-head: 4px; }
footer .ft-shoot-3{ top: -24%; left: 56%; --ft-len: 175px; --ft-thick: 2.5px; --ft-head: 3px; }

/* the NEAR one — 11s cycle, falling 62%->77.5% (1.7s) over 960px at ~565px/s:
   longest trail, full brightness, fastest */
@keyframes ftMeteor1{
    0%, 62%{ opacity: 0;   transform: rotate(46deg) translateX(-60px) scaleX(.22);
             animation-timing-function: linear; }
    63.9%  { opacity: 1;   transform: rotate(46deg) translateX(200px) scaleX(1);
             animation-timing-function: cubic-bezier(.32,.5,.55,1); }   /* burn-out */
    70.6%  { opacity: .72;
             animation-timing-function: cubic-bezier(.32,.5,.55,1); }
    77.5%  { opacity: 0;   transform: rotate(46deg) translateX(900px) scaleX(1); }
    100%   { opacity: 0; }
}
/* the MID one — 17s cycle, falling 16%->27.2% (1.9s) over 880px at ~463px/s */
@keyframes ftMeteor2{
    0%, 16%{ opacity: 0;   transform: rotate(50deg) translateX(-60px) scaleX(.22);
             animation-timing-function: linear; }
    17.3%  { opacity: .78; transform: rotate(50deg) translateX(180px) scaleX(1);
             animation-timing-function: cubic-bezier(.32,.5,.55,1); }
    22.2%  { opacity: .55;
             animation-timing-function: cubic-bezier(.32,.5,.55,1); }
    27.2%  { opacity: 0;   transform: rotate(50deg) translateX(820px) scaleX(1); }
    100%   { opacity: 0; }
}
/* the FAR one — 23s cycle, falling 22%->30.7% (2.0s) over 780px at ~390px/s:
   shortest trail, dimmest, slowest — the parallax runs with the other cues */
@keyframes ftMeteor3{
    0%, 22%{ opacity: 0;   transform: rotate(42deg) translateX(-60px) scaleX(.22);
             animation-timing-function: linear; }
    23%    { opacity: .58; transform: rotate(42deg) translateX(210px) scaleX(1);
             animation-timing-function: cubic-bezier(.32,.5,.55,1); }
    26.8%  { opacity: .4;
             animation-timing-function: cubic-bezier(.32,.5,.55,1); }
    30.7%  { opacity: 0;   transform: rotate(42deg) translateX(720px) scaleX(1); }
    100%   { opacity: 0; }
}
footer.ft-glow .ft-shoot-1{ animation: ftMeteor1 11s linear infinite; }
footer.ft-glow .ft-shoot-2{ animation: ftMeteor2 17s linear infinite; }
footer.ft-glow .ft-shoot-3{ animation: ftMeteor3 23s linear infinite; }

/* --- pre-hide. `ul` is excluded and its list items handled instead: fading the
       list as well would group its children and mute their own stagger. */
footer.ft-js .col-md-12 > *:not(ul){ opacity: 0; }
footer.ft-js .col-md-12 > ul > li{ opacity: 0; }
/* each rule starts collapsed against its label — ::before reaches in from the
   left so it grows from its right end, and ::after the other way round */
footer.ft-js p.footba::before{ transform: scaleX(0); transform-origin: right center; }
footer.ft-js p.footba::after{  transform: scaleX(0); transform-origin: left center; }

/* --- reveal; the script walks the footer in document order and assigns the
       delays, so any combination of optional blocks still cascades correctly */
footer.ft-js.ft-in .col-md-12 > *:not(ul){ animation: ftUp .6s cubic-bezier(.22,.61,.36,1) both; }
footer.ft-js.ft-in .col-md-12 > ul > li.list-inline-item{ animation: ftUp .5s ease both; }
footer.ft-js.ft-in .col-md-12 > ul > li.nav-item{ animation: ftPop .55s cubic-bezier(.34,1.56,.64,1) both; }
footer.ft-js.ft-in p.footba::before,
footer.ft-js.ft-in p.footba::after{ animation: ftLine .85s cubic-bezier(.22,.61,.36,1) var(--ft-line-d, .6s) both; }

/* --- a spark then keeps travelling outward along each rule. The highlight is a
       background-IMAGE layered over the rule's existing background-COLOR, parked
       off the end so it is invisible until it runs. This lives on .ft-glow, which
       is added after the reveal classes are dropped, so the two never collide. */
footer p.footba::before,
footer p.footba::after{
    background-image: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.9) 50%, rgba(255,255,255,0) 100%);
    background-repeat: no-repeat;
    background-size: 100px 100%;
}
footer p.footba::before{ background-position: -100px 0; }   /* parked past the left end  */
footer p.footba::after{  background-position: 430px 0; }    /* parked past the right end */
footer.ft-glow p.footba::before{ animation: ftSparkL 4.2s linear 1.2s infinite; }
footer.ft-glow p.footba::after{  animation: ftSparkR 4.2s linear 1.2s infinite; }

/* --- menu links: a rule grows under them instead of the browser's underline,
       matching the "View All" links throughout the site. */
footer .col-md-12 > ul > li.list-inline-item > a{
    position: relative; display: inline-block;
    transition: transform .35s cubic-bezier(.22,.61,.36,1);
}
footer .col-md-12 > ul > li.list-inline-item > a::after{
    content: '';
    /* insets match the anchor's own px-4 / pb-4 padding, so the rule sits under
       the text rather than out at the edge of the padding box */
    position: absolute; left: 1.5rem; right: 1.5rem; bottom: 1.35rem; height: 2px;
    background: #F7B32B;                       /* brand amber, per the brief */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
footer .col-md-12 > ul > li.list-inline-item > a:hover{ transform: translateY(-2px); text-decoration: none; }
footer .col-md-12 > ul > li.list-inline-item > a:hover::after{ transform: scaleX(1); }

/* --- social icons: a simple lift and a soft amber halo that fades in behind the
       glyph. Two things, both easing at the same speed, nothing that spins or
       tracks the cursor. */
footer .col-md-12 > ul > li.nav-item > a{ transition: transform .3s ease; }
footer .col-md-12 > ul > li.nav-item > a i{
    /* inline-block + a radius so the halo below renders as a circle. The glyph
       has no background, so neither changes anything visible at rest. */
    position: relative; display: inline-block; border-radius: 50%;
    transition: transform .3s ease;
}
footer .col-md-12 > ul > li.nav-item > a:hover{ transform: translateY(-4px); text-decoration: none; }
footer .col-md-12 > ul > li.nav-item > a:hover i{ transform: scale(1.15); }
/* the halo. Uses ::after, never ::before — Font Awesome's own glyph is rendered
   on ::before, and a second ::before would silently replace the icon itself. */
footer .col-md-12 > ul > li.nav-item > a i::after{
    content: '';
    position: absolute; inset: -9px;
    border-radius: 50%;
    background: rgba(247,179,43,.16);
    opacity: 0; pointer-events: none;
    transition: opacity .3s ease;
}
footer .col-md-12 > ul > li.nav-item > a:hover i::after{ opacity: 1; }

/* --- the credit link in the copyright line gets the same growing rule */
footer p span a{ position: relative; display: inline-block; }
footer p span a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
    background: #F7B32B;                       /* brand amber, matching the menu links */
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
footer p span a:hover{ text-decoration: none; }
footer p span a:hover::after{ transform: scaleX(1); }

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .bookappfooter .btnsecondary:hover{ transform: none; box-shadow: inset 0 0 0 1px currentColor; }
    .bookappfooter .c_row a:hover{ transform: none; }
    .bookappfooter .c_row:hover .c_icon i{ transform: none; }
    footer .col-md-12 > ul > li.list-inline-item > a:hover{ transform: none; }
    footer .col-md-12 > ul > li.nav-item > a:hover{ transform: none; }
    footer .col-md-12 > ul > li.nav-item > a:hover i{ transform: none; }
    footer .col-md-12 > ul > li.nav-item > a:hover i::after{ opacity: 0; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .bookappfooter,
    .bookappfooter .col-md-8 > p,
    .bookappfooter .c_row,
    .bookappfooter .c_row .c_icon i,
    .bookappfooter .btnsecondary{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .bookappfooter .btnsecondary::before,
    .bookappfooter::before,
    .bookappfooter::after{ opacity: 0 !important; animation: none !important; }
    .bookappfooter .btnsecondary:hover{ box-shadow: inset 0 0 0 1px currentColor !important; }
    footer .col-md-12 > *,
    footer .col-md-12 > ul > li{ opacity: 1 !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    footer::before,
    footer::after{ opacity: 0 !important; animation: none !important; }
    footer .ft-shoot{ display: none !important; }
    footer p.footba::before,
    footer p.footba::after{ transform: none !important; animation: none !important; background-image: none !important; }
    footer .col-md-12 > ul > li.nav-item > a i::after{ opacity: 0 !important; }
    /* NOTE: the icon itself is deliberately not grouped into the rule below. It
       used to share `transform: scaleX(0)` with the underline pseudo-elements,
       which squashed every social icon to zero width whenever reduced-motion was
       on — scaleX(0) is only correct for hiding a 1px underline, not an icon. */
    footer .col-md-12 > ul > li.nav-item > a i{ transform: none !important; transition: none !important; }
    footer .col-md-12 > ul > li.list-inline-item > a::after,
    footer p span a::after{ transform: scaleX(0) !important; text-shadow: none !important; transition: none !important; }
}

/* ===========================================================================
   Navbar scroll progress — a lit filament across the top of the header.

   Two layers, both driven by a single --nav-p (0 to 1) that a small script in
   footer.php updates. Neither is a plain bar:

   · the FILL is a gradient that brightens toward its leading end, scaled on the
     X axis, so it is composited and costs nothing to move;
   · the HEAD is a full-width layer carrying a fixed-size bloom pinned to its
     right edge, translated by (p - 1) * 100%. That places its right edge exactly
     at p of the header's width WITHOUT ever scaling the layer, so the glow keeps
     its shape at every position — a scaled glow would smear at low progress.

   The script eases the value toward the scroll position rather than snapping to
   it each frame, which is what separates this from a stock progress bar: the
   filament flows and settles instead of twitching. It stays invisible until you
   actually begin scrolling.

   nav.top-navbar-head is `sticky-top`, so it is already a containing block and
   the filament travels with the header. Nothing here changes layout.
   =========================================================================== */
/* Three hairlines, all exactly 2px and all flush to the header's top edge, so the
   indicator reads as part of the chrome rather than as something sitting on top
   of it. Nothing spills below the line.

   · TRACK — a barely-there groove the fill runs along. This is what makes the
     line look designed rather than accidental: without it a short fill is just a
     stray mark floating in the corner.
   · FILL — the progress itself.
   · TIP — a 34px gradient that lifts to a lighter amber right at the leading
     edge. It is only ever TRANSLATED, never scaled, so it keeps its shape at
     every position; a highlight attached to the scaling fill would smear.

   The fill and tip are real elements (appended by the script) rather than
   pseudo-elements, because a pseudo cannot take an inline style — which would
   have forced the progress value through a custom property and a calc(), and
   that chain fails silently if any link does not resolve. */
nav.top-navbar-head::before{
    content: '';
    position: absolute; top: 0; left: 0;
    width: 100%; height: 2px;
    background: rgba(0,0,0,.07);
    z-index: 5;
    pointer-events: none;
    opacity: 0;
    transition: opacity .4s ease;
}
.nav-prog-bar,
.nav-prog-head{
    position: absolute; top: 0; left: 0;
    width: 100%; height: 2px;
    pointer-events: none;
    opacity: 0;
    transition: opacity .4s ease;
}
.nav-prog-bar{
    z-index: 6;
    background: linear-gradient(90deg, rgba(247,179,43,.55) 0%, #F7B32B 100%);
    transform: scaleX(0);
    transform-origin: left center;
}
.nav-prog-head{
    z-index: 7;
    background-image: linear-gradient(90deg, rgba(247,179,43,0) 0%, #FFE0A6 100%);
    background-repeat: no-repeat;
    background-position: right center;
    background-size: 34px 2px;
    transform: translateX(-100%);
}
/* the script adds this to the header once there is any progress to show */
nav.top-navbar-head.nav-prog::before{ opacity: 1; }
nav.top-navbar-head.nav-prog .nav-prog-bar{ opacity: 1; }
nav.top-navbar-head.nav-prog .nav-prog-head{ opacity: 1; }

/* ===========================================================================
   Global micro-interactions — the polish pass.

   Motion and light only: nothing here changes a colour that was already set, a
   size, a spacing or a layout. Every value is either the brand amber that is
   already used throughout this file, or white at low alpha.
   =========================================================================== */

/* --- header links: a brand rule grows under the label, matching the footer and
       the "View All" links. Hover only — the active page is left exactly as
       designed, so nothing changes at rest. */
.top-navbar-head .navbar-nav > .nav-item > .nav-link{ position: relative; }
.top-navbar-head .navbar-nav > .nav-item > .nav-link::after{
    content: '';
    /* insets match Bootstrap's own .nav-link padding, so the rule sits under the
       label rather than out at the edge of its box */
    position: absolute; left: 1rem; right: 1rem; bottom: .3rem; height: 2px;
    background: #F7B32B;
    transform: scaleX(0); transform-origin: left center;
    transition: transform .35s cubic-bezier(.22,.61,.36,1);
}
.top-navbar-head .navbar-nav > .nav-item > .nav-link:hover::after{ transform: scaleX(1); }

/* --- dropdowns open with a settle instead of appearing. Bootstrap adds .show,
       so this replays every time one is opened. */
@keyframes navDrop{
    from{ opacity: 0; transform: translateY(-9px) scale(.985); }
    to  { opacity: 1; transform: translateY(0)    scale(1); }
}
.top-navbar-head .dropdown-menu.show{ animation: navDrop .28s cubic-bezier(.22,.61,.36,1) both; }
.top-navbar-head .dropdown-item{ transition: transform .25s cubic-bezier(.22,.61,.36,1), background-color .25s ease; }
.top-navbar-head .dropdown-item:hover{ transform: translateX(5px); }

/* --- every button gets a press. This is the single most valuable interaction on
       the site: it makes the whole page feel like it is made of real controls.
       Two buttons carry their own hover transform and so need the press restated
       at matching weight, or their hover rule would keep winning. */
/* background-color/color/border-color are included here because .btnprimary and
   .btnsecondary (theme_css.php) flip both on hover with no transition of their
   own, so every primary/secondary button on the site — including the two
   Submit buttons on Contact Us and Book Appointment — used to snap instead of
   ease. No colour value changes here, only how a change in colour is played. */
.btn{
    transition: transform .18s cubic-bezier(.22,.61,.36,1), box-shadow .25s ease,
                background-color .3s ease, color .3s ease, border-color .3s ease;
}
.btn:active{ transform: scale(.97); }
#demo .banner_txt .buttons .btn:active{ transform: translateY(-3px) scale(.97); }
.bookappfooter .btnsecondary:active{ transform: translateY(-5px) scale(.97); }

/* --- form fields answer the cursor. A ring rather than the browser outline, and
       the outline is only removed because the ring replaces it. */
input, select, textarea{ transition: box-shadow .25s ease, border-color .25s ease; }
/* a lighter preview ring on hover, so a field answers the cursor before it is
   even focused — :not(:focus) so it can never outrank the real focus ring
   above if the field happens to be both hovered and focused at once */
input:hover:not(:focus), select:hover:not(:focus), textarea:hover:not(:focus){
    box-shadow: 0 0 0 3px rgba(247,179,43,.12);
}
input:focus, select:focus, textarea:focus{
    outline: none;
    box-shadow: 0 0 0 3px rgba(247,179,43,.28);
}

/* --- keyboard users get a visible, deliberate focus ring rather than whatever
       the browser would have drawn */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
[role="button"]:focus-visible{
    outline: 2px solid #F7B32B;
    outline-offset: 3px;
    border-radius: 2px;
}

/* --- selected text picks up the brand rather than the browser's default blue */
::selection{ background: #F7B32B; color: #000; }

/* --- in-page links glide instead of jumping, and land clear of the sticky
       header rather than underneath it */
html{ scroll-behavior: smooth; scroll-padding-top: 96px; }

@media (prefers-reduced-motion: reduce){
    html{ scroll-behavior: auto; }
    .nav-prog-head{ display: none !important; }
    nav.top-navbar-head::before,
    .nav-prog-bar{ transition: none !important; }
    .top-navbar-head .navbar-nav > .nav-item > .nav-link::after{ transform: scaleX(0) !important; transition: none !important; }
    .top-navbar-head .dropdown-menu.show{ animation: none !important; }
    .top-navbar-head .dropdown-item,
    .btn,
    input, select, textarea{ transition: none !important; }
    .top-navbar-head .dropdown-item:hover,
    .btn:active,
    #demo .banner_txt .buttons .btn:active,
    .bookappfooter .btnsecondary:active{ transform: none !important; }
}

/* ===========================================================================
   About Us page — entrance sequences + hover.

   Animation-only and additive. A script at the end of about_us.php tags the two
   blocks and drives the reveals; with JS off or reduced-motion on the page
   renders exactly as designed.

   SCOPING: this page has no body class, no section id and no unique wrapper, and
   the stylesheet is shared by every page. So the script tags <body> with
   .ab-page and the two blocks with .ab-intro / .ab-spec, found by walking up
   from elements that only exist here (.docimgabout and .specialtick) rather than
   by guessing at utility classes.

   TWO CONSTRAINTS drove the design:
   · The portrait column is `position: sticky`. A transform on that wrapper — or
     an overflow on it — would stop it sticking, so only the two images inside it
     are ever animated, never the column or the .sticky-top div.
   · The statistics block here is the same markup as the home page's. It
     deliberately carries NO opacity, transform or transition, exactly as agreed
     there; its only animation is the number counting, which is pure text.
   =========================================================================== */
@keyframes abWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
@keyframes abUp{ from{ opacity: 0; transform: translateY(20px); } to{ opacity: 1; transform: translateY(0); } }
/* the big heading resolves out of a blur as it rises */
@keyframes abRise{
    from{ opacity: 0; transform: translateY(26px); filter: blur(7px); }
    to  { opacity: 1; transform: translateY(0);    filter: blur(0); }
}
/* the decorative shape behind the portrait settles square first... */
@keyframes abShape{
    from{ opacity: 0; transform: scale(.82) rotate(-7deg); }
    to  { opacity: 1; transform: scale(1)   rotate(0deg); }
}
/* ...then the portrait itself is uncovered upward inside it, so the two layers
   read as one composition being assembled rather than two images appearing */
@keyframes abPortrait{
    from{ opacity: 0; clip-path: inset(100% -.2em -.2em -.2em); transform: translateY(26px); }
    to  { opacity: 1; clip-path: inset(-.2em -.2em -.2em -.2em); transform: translateY(0); }
}
@keyframes abBtn{
    0%  { opacity: 0; transform: translateY(16px) scale(.9); }
    62% { opacity: 1; transform: translateY(0)    scale(1.06); }
    100%{ opacity: 1; transform: translateY(0)    scale(1); }
}
/* a specialty's label arrives at the right margin it is aligned to */
@keyframes abLabelIn{ from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes abTick{
    0%  { opacity: 0; transform: scale(0)    rotate(-140deg); }
    65% { opacity: 1; transform: scale(1.28) rotate(10deg); }
    100%{ opacity: 1; transform: scale(1)    rotate(0deg); }
}

/* ---------- the intro block ---------- */
/* --- pre-hide. The stats row and the sticky wrapper are both deliberately
       absent from every list below. */
.ab-page .ab-intro.ab-js .sticky-top > img{ opacity: 0; }
/* NOTE the `.text-lightt` qualifier on the short-content block. The statistics
   row is ALSO a direct child of this column and also carries .mb-20, so a plain
   `.col-md-6 > .mb-20` would hide and transform the statistics — the exact thing
   that must not happen to them. */
.ab-page .ab-intro.ab-js h2,
.ab-page .ab-intro.ab-js .col-md-6 > .mb-20.text-lightt,
.ab-page .ab-intro.ab-js .col-md-6 > .mb-30,
.ab-page .ab-intro.ab-js p.centext,
.ab-page .ab-intro.ab-js .mobtext-center > a{ opacity: 0; }
.ab-page .ab-intro.ab-js h1{ opacity: 0; }

/* --- reveal */
.ab-page .ab-intro.ab-js.ab-in .sticky-top > img:not(.docimgabout){ animation: abShape .9s cubic-bezier(.22,.61,.36,1) .1s both; }
.ab-page .ab-intro.ab-js.ab-in .docimgabout{ animation: abPortrait 1s cubic-bezier(.22,.61,.36,1) .34s both; }
.ab-page .ab-intro.ab-js.ab-in h2{ animation: abUp .65s ease .2s both; }
.ab-page .ab-intro.ab-js.ab-in h1{ animation: abRise .9s cubic-bezier(.22,.61,.36,1) .36s both; }
.ab-page .ab-intro.ab-js.ab-in .col-md-6 > .mb-20.text-lightt{ animation: abUp .7s ease .54s both; }
.ab-page .ab-intro.ab-js.ab-in .col-md-6 > .mb-30{ animation: abUp .7s ease .66s both; }
.ab-page .ab-intro.ab-js.ab-in p.centext{ animation: abUp .6s ease .8s both; }
.ab-page .ab-intro.ab-js.ab-in .mobtext-center > a{ animation: abBtn .7s cubic-bezier(.34,1.56,.64,1) .95s both; }

/* the trailing long-form block reveals on its own as it comes into view */
.ab-page .ab-more.ab-js{ opacity: 0; }
.ab-page .ab-more.ab-js.ab-in{ animation: abUp .8s cubic-bezier(.22,.61,.36,1) both; }

/* --- hover: the portrait warms and eases forward a touch */
.ab-page .docimgabout{ transition: transform .6s cubic-bezier(.22,.61,.36,1), filter .6s ease; will-change: transform; }
.ab-page .sticky-top:hover .docimgabout{ transform: scale(1.03); filter: brightness(1.04) contrast(1.03); }

/* ---------- the specialties block ---------- */
/* --- pre-hide */
.ab-page .ab-spec.ab-js h2{ clip-path: inset(-.2em 100% -.2em -.2em); }
.ab-page .ab-spec.ab-js .row > .col-md-4 > p{ opacity: 0; }
/* THE TEXT ONLY — never an ancestor of the tick. `clip-path` clips an element's
   absolutely-positioned descendants as well as its in-flow ones, and `onView()`
   in about_us.php never removes `ab-js`/`ab-in`, so with `both` fill this clip
   stays applied permanently. While the tick lived INSIDE this element (as
   `position: absolute; left: -10px`) that meant its left ~7px sat outside the
   clip region, which only reaches -.2em, and was sliced off for good — the
   cropped icon that was reported. The tick is now a flex SIBLING of `.spec-body`
   rather than a child of the wiped element, so no clip can reach it. */
.ab-page .ab-spec.ab-js .spec-body{ clip-path: inset(-.2em 100% -.2em -.2em); }
.ab-page .ab-spec.ab-js .specialtick{ opacity: 0; }

/* --- reveal; each row carries an --ab-d its three parts offset from */
.ab-page .ab-spec.ab-js.ab-in h2{ animation: abWipe .8s cubic-bezier(.22,.61,.36,1) .1s both; }
.ab-page .ab-spec.ab-js.ab-in .row > .col-md-4 > p{ animation: abLabelIn .6s cubic-bezier(.22,.61,.36,1) var(--ab-d, 0s) both; }
.ab-page .ab-spec.ab-js.ab-in .specialtick{ animation: abTick .6s cubic-bezier(.34,1.56,.64,1) calc(var(--ab-d, 0s) + .12s) both; }
.ab-page .ab-spec.ab-js.ab-in .spec-body{ animation: abWipe .6s cubic-bezier(.22,.61,.36,1) calc(var(--ab-d, 0s) + .2s) both; }

/* --- hover: the row is picked out, its tick turns, and the label leans in.
       The tint is neutral black at 3% — a shade, not a colour. */
.ab-page .ab-spec .row{
    border-radius: 10px;
    transition: background-color .3s ease;
}
.ab-page .ab-spec .row:hover{ background-color: rgba(0,0,0,.03); }
.ab-page .ab-spec .row > .col-md-4 > p,
.ab-page .ab-spec .specialtick{ transition: transform .35s cubic-bezier(.34,1.56,.64,1); }
.ab-page .ab-spec .row:hover > .col-md-4 > p{ transform: translateX(-5px); }
.ab-page .ab-spec .row:hover .specialtick{ transform: scale(1.22) rotate(-8deg); }

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .ab-page .sticky-top:hover .docimgabout{ transform: none; filter: none; }
    .ab-page .ab-spec .row:hover{ background-color: transparent; }
    .ab-page .ab-spec .row:hover > .col-md-4 > p,
    .ab-page .ab-spec .row:hover .specialtick{ transform: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .ab-page .ab-intro .sticky-top > img,
    .ab-page .ab-intro h1,
    .ab-page .ab-intro h2,
    .ab-page .ab-intro .col-md-6 > .mb-20.text-lightt,
    .ab-page .ab-intro .col-md-6 > .mb-30,
    .ab-page .ab-intro p.centext,
    .ab-page .ab-intro .mobtext-center > a,
    .ab-page .ab-more,
    .ab-page .ab-spec h2,
    .ab-page .ab-spec .row > .col-md-4 > p,
    .ab-page .ab-spec .spec-body,
    .ab-page .ab-spec .specialtick{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .ab-page .ab-spec .row{ transition: none !important; }
    .ab-page .ab-spec .row:hover{ background-color: transparent !important; }
}

/* ===========================================================================
   Services and Departments listing pages — entrance + hover.

   Animation-only and additive. With JS off or reduced-motion on, both pages
   render exactly as designed.

   ONE BLOCK SERVES BOTH PAGES, deliberately. They are the same design — a grid
   of icon-led cards — and both carry the identical `section.primary_section
   .service.cusscroll`, so treating them as one component is correct rather than
   a shortcut. A script on each page tags <body> with .sd-page; nothing here can
   reach the home page, whose own Services and Departments sections are
   namespaced to .sv-sec and .dp-sec.

   Their markup differs in two small ways, handled by matching both forms:
   the name is a <p> on Services and an <h3> on Departments (so `.text-hover-color`
   is matched instead), and the description is `p.overelipsis3` there but
   `p.peoplereview` here.

   The card handle is `.col-md-4.my-4`, which is the grid cell on BOTH pages.
   `.service-card` itself is the cell on Services but an inner `.row` on
   Departments — and a row carries Bootstrap's negative margins, so a shadow on
   it would sit 15px wider than the card it belongs to.

   The reveal is a DIAGONAL CASCADE rather than a straight stagger: the delay is
   (row + column), so the grid fills in a wave from the top-left corner. Every
   other list on the site runs left-to-right in source order; a grid earns
   something that reads in two dimensions.
   =========================================================================== */
@keyframes sdWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
@keyframes sdUp{ from{ opacity: 0; transform: translateY(16px); } to{ opacity: 1; transform: translateY(0); } }
@keyframes sdCardIn{ from{ opacity: 0; transform: translateY(32px); } to{ opacity: 1; transform: translateY(0); } }
/* the icon arrives with an amber ring pushing out of it. These pages sit on the
   light section background, so the ring is brand amber rather than the white
   used on the home page's dark panels. */
@keyframes sdIconIn{
    0%  { opacity: 0; transform: scale(.3);   box-shadow: 0 0 0 0    rgba(247,179,43,.55); }
    60% { opacity: 1; transform: scale(1.18); box-shadow: 0 0 0 13px rgba(247,179,43,.18); }
    100%{ opacity: 1; transform: scale(1);    box-shadow: 0 0 0 26px rgba(247,179,43,0); }
}

/* --- pre-hide (only while the script drives the reveal) */
.sd-page .sd-js h1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.sd-page .sd-js .col-md-4.my-4{ opacity: 0; }
.sd-page .sd-js .service-card .testimoimg{ opacity: 0; }
.sd-page .sd-js .service-card .text-hover-color{ clip-path: inset(-.2em 100% -.2em -.2em); }
.sd-page .sd-js .service-card p.overelipsis3,
.sd-page .sd-js .service-card p.peoplereview{ opacity: 0; }

/* --- reveal; each cell carries a --sd-d holding its diagonal position, and the
       three beats inside it offset from that */
.sd-page .sd-js.sd-in h1{ animation: sdWipe .8s cubic-bezier(.22,.61,.36,1) .1s both; }
.sd-page .sd-js.sd-in .col-md-4.my-4{ animation: sdCardIn .7s cubic-bezier(.22,.61,.36,1) var(--sd-d, 0s) both; }
.sd-page .sd-js.sd-in .service-card .testimoimg{ animation: sdIconIn .7s cubic-bezier(.34,1.56,.64,1) calc(var(--sd-d, 0s) + .10s) both; }
.sd-page .sd-js.sd-in .service-card .text-hover-color{ animation: sdWipe .6s cubic-bezier(.22,.61,.36,1) calc(var(--sd-d, 0s) + .28s) both; }
.sd-page .sd-js.sd-in .service-card p.overelipsis3,
.sd-page .sd-js.sd-in .service-card p.peoplereview{ animation: sdUp .55s ease calc(var(--sd-d, 0s) + .42s) both; }

/* --- hover: the cell lifts off the page and the icon takes an amber ring. The
       theme's own `.service-card:hover .text-hover-color` amber is untouched —
       it just eases now instead of snapping. */
.sd-page .col-md-4.my-4{
    border-radius: 12px;   /* shapes the shadow; nothing is visible at rest */
    transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease;
}
.sd-page .col-md-4.my-4:hover{
    transform: translateY(-7px);
    box-shadow: 0 18px 34px rgba(0,0,0,.10);
}
.sd-page .service-card .text-hover-color{ transition: color .3s ease; }
.sd-page .service-card .testimoimg{ transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease; }
.sd-page .col-md-4.my-4:hover .testimoimg{
    transform: scale(1.1);
    box-shadow: 0 0 0 7px rgba(247,179,43,.22);
}
/* the View More control answers the cursor like the rest of the site */
.sd-page #load_more .btn{ transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.sd-page #load_more .btn:hover{ transform: translateY(-3px); box-shadow: 0 12px 24px rgba(0,0,0,.16); }

/* ---------------------------------------------------------------------------
   The Doctors and Awards listing pages are the same pattern again — a grid of
   cards under a centred heading, with the same cell as the handle — so they run
   on everything above and only add the beats specific to their own card.

   The inner gestures are borrowed on purpose: a doctor's portrait opens from its
   centre line exactly as it does on the home page, and an award still opens out
   of a circle like a spotlight. A card should behave the same way wherever it
   appears. Those keyframes (drDoors, awIris, awGleam) are declared with the home
   page sections and reused here rather than duplicated.
   --------------------------------------------------------------------------- */

/* --- Doctors: portrait, then specialisation, name, bio, button */
.sd-page .sd-js .doccard-img img{ opacity: 0; clip-path: inset(0 50% 0 50%); }
.sd-page .sd-js .doccard p.fw-600{ clip-path: inset(-.2em 100% -.2em -.2em); }
/* the name is an h3 that ALSO carries .overelipsis2, so the bio is matched as a
   p to keep the two apart */
.sd-page .sd-js .doccard h3.doctitle,
.sd-page .sd-js .doccard p.overelipsis2,
.sd-page .sd-js .doccard .btn.btnthird{ opacity: 0; }

.sd-page .sd-js.sd-in .doccard-img img{ animation: drDoors .85s cubic-bezier(.22,.61,.36,1) calc(var(--sd-d, 0s) + .10s) both; }
.sd-page .sd-js.sd-in .doccard p.fw-600{ animation: sdWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--sd-d, 0s) + .30s) both; }
.sd-page .sd-js.sd-in .doccard h3.doctitle{ animation: sdUp .5s ease calc(var(--sd-d, 0s) + .42s) both; }
.sd-page .sd-js.sd-in .doccard p.overelipsis2{ animation: sdUp .5s ease calc(var(--sd-d, 0s) + .52s) both; }
.sd-page .sd-js.sd-in .doccard .btn.btnthird{ animation: sdUp .5s ease calc(var(--sd-d, 0s) + .62s) both; }

.sd-page .doccard-img{ position: relative; overflow: hidden; }
.sd-page .doccard-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.sd-page .col-md-4.my-4:hover .doccard-img img{
    transform: translateY(-5px) scale(1.05);
    filter: brightness(1.03) contrast(1.03);
}

/* --- Awards: the spotlight, then the citation lines in turn */
.sd-page .sd-js .awards-card .post-img img{ opacity: 0; clip-path: circle(0% at 50% 50%); }
.sd-page .sd-js .awards-card .card-text > h3{ opacity: 0; }
.sd-page .sd-js .awards-card .card-text > p{ clip-path: inset(-.2em 100% -.2em -.2em); }
.sd-page .sd-js .awards-card .peoplereview{ opacity: 0; }

.sd-page .sd-js.sd-in .awards-card .post-img img{ animation: awIris .85s cubic-bezier(.22,.61,.36,1) calc(var(--sd-d, 0s) + .10s) both; }
.sd-page .sd-js.sd-in .awards-card .card-text > h3{ animation: sdUp .5s ease calc(var(--sd-d, 0s) + .30s) both; }
.sd-page .sd-js.sd-in .awards-card .card-text > p{ animation: sdWipe .5s cubic-bezier(.22,.61,.36,1) both; }
.sd-page .sd-js.sd-in .awards-card .card-text > p:nth-of-type(1){ animation-delay: calc(var(--sd-d, 0s) + .42s); }
.sd-page .sd-js.sd-in .awards-card .card-text > p:nth-of-type(2){ animation-delay: calc(var(--sd-d, 0s) + .50s); }
.sd-page .sd-js.sd-in .awards-card .card-text > p:nth-of-type(3){ animation-delay: calc(var(--sd-d, 0s) + .58s); }
.sd-page .sd-js.sd-in .awards-card .peoplereview{ animation: sdUp .55s ease calc(var(--sd-d, 0s) + .68s) both; }

.sd-page .awards-card .post-img{ position: relative; overflow: hidden; }
.sd-page .awards-card .post-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.sd-page .col-md-4.my-4:hover .awards-card .post-img img{
    transform: translateY(-5px) scale(1.04);
    filter: brightness(1.05) contrast(1.03);
}
/* the same narrow glint the home page awards use, so light still catches metal */
.sd-page .awards-card .post-img::after{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 22%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.35), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.sd-page .col-md-4.my-4:hover .awards-card .post-img::after{ animation: awGleam .8s cubic-bezier(.4,0,.2,1); }

/* --- News listing: the photograph settles into frame and develops, then the
        dateline is stamped across, then the title and button rise — the same
        gestures the home page news cards use.

        `.post.p-10` is what separates these from the awards cards above: those
        are `.awards-card.post`, which shares `.post` and `.post-img` but never
        carries `p-10`. Without that qualifier the two would animate each other. */
/* clip-path ONLY, no opacity: nwPlate below animates clip-path/transform/filter
   and never touches opacity. An opacity:0 here would never be reversed by that
   keyframe, so the image would stay invisible until the script strips this class
   at the very end of the sequence — which is exactly what made it look "late". */
.sd-page .sd-js .post.p-10 .post-img img{ clip-path: inset(100% 0 0 0); }
.sd-page .sd-js .post.p-10 p.fw-600{ clip-path: inset(-.2em 100% -.2em -.2em); }
.sd-page .sd-js .post.p-10 p.newstitle,
.sd-page .sd-js .post.p-10 .btn.btnthird{ opacity: 0; }

/* The photograph starts at the SAME moment as its card, not after it. Previously
   it was offset +.10s and ran for .9s, so the card frame was already on screen
   while the picture inside was still arriving — which reads as the image being
   late. Now the two land together and the picture is the quickest thing in the
   card, so it leads the copy instead of trailing it. */
.sd-page .sd-js.sd-in .post.p-10 .post-img img{ animation: nwPlate .55s cubic-bezier(.22,.61,.36,1) var(--sd-d, 0s) both; }
.sd-page .sd-js.sd-in .post.p-10 p.fw-600{ animation: nwStamp .45s cubic-bezier(.22,.61,.36,1) calc(var(--sd-d, 0s) + .14s) both; }
.sd-page .sd-js.sd-in .post.p-10 p.newstitle{ animation: sdUp .45s ease calc(var(--sd-d, 0s) + .24s) both; }
.sd-page .sd-js.sd-in .post.p-10 .btn.btnthird{ animation: sdUp .45s ease calc(var(--sd-d, 0s) + .32s) both; }

/* Hover is carried by the photograph ALONE here, matching the home page news
   cards — the dateline, title and button never move. That was an explicit
   preference for these cards, so the shared cell lift is cancelled for this page
   via the .nw-list class the script puts on the section. */
.sd-page .nw-list .col-md-4.my-4:hover{ transform: none; box-shadow: none; }
.sd-page .post.p-10 .post-img{ position: relative; overflow: hidden; cursor: pointer; }
.sd-page .post.p-10 .post-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.sd-page .post.p-10 .post-img:hover img{
    transform: translateY(-5px) scale(1.03);
    filter: brightness(1.03) contrast(1.03);
}

/* --- Press Release listing: reuses the home page's "clipping laid down"
        gesture (prLayDown/prWipe/prTextUp) so the idea reads the same wherever
        it appears. The clipping and the card land together, not one after the
        other — the same fix applied to the Blog and News listing pages. */
.sd-page .sd-js .gallery .presscard{ opacity: 0; }
.sd-page .sd-js .gallery p.text-lblue{ clip-path: inset(-.2em 100% -.2em -.2em); }
.sd-page .sd-js .gallery p.overelipsis1,
.sd-page .sd-js .gallery p.presscontent,
.sd-page .sd-js .gallery p.text-96,
.sd-page .sd-js .gallery .d-flex > a{ opacity: 0; }

.sd-page .sd-js.sd-in .gallery .presscard{ animation: prLayDown .6s cubic-bezier(.22,.61,.36,1) var(--sd-d, 0s) both; }
.sd-page .sd-js.sd-in .gallery p.text-lblue{ animation: prWipe .45s cubic-bezier(.22,.61,.36,1) calc(var(--sd-d, 0s) + .16s) both; }
.sd-page .sd-js.sd-in .gallery p.overelipsis1{ animation: prTextUp .45s ease calc(var(--sd-d, 0s) + .26s) both; }
.sd-page .sd-js.sd-in .gallery p.presscontent{ animation: prTextUp .45s ease calc(var(--sd-d, 0s) + .36s) both; }
.sd-page .sd-js.sd-in .gallery p.text-96,
.sd-page .sd-js.sd-in .gallery .d-flex > a{ animation: prTextUp .4s ease calc(var(--sd-d, 0s) + .46s) both; }

/* the clipping carries the hover, exactly as it does on the home page: the
   shared `.gallery:hover .presscard` zoom (also used by the photo gallery) is
   neutralised inside this page only, so the caption never reacts. */
.sd-page .gallery .presscard{
    transition: transform .5s cubic-bezier(.22,.61,.36,1), box-shadow .5s ease, filter .5s ease;
    will-change: transform;
}
.sd-page .gallery:hover .presscard{ transform: none; }
.sd-page .gallery a.item{ cursor: pointer; }
.sd-page .gallery a.item:hover .presscard{
    transform: translateY(-6px) rotate(-1.2deg) scale(1.04);
    box-shadow: 0 16px 30px rgba(0,0,0,.22);
    filter: brightness(1.03) contrast(1.03);
}
/* the Read more link gets the site's growing amber underline */
.sd-page .gallery .d-flex > a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.sd-page .gallery .d-flex > a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
    background: #F7B32B;
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.sd-page .gallery .d-flex > a:hover{ transform: translateY(-2px); text-decoration: none; }
.sd-page .gallery .d-flex > a:hover::after{ transform: scaleX(1); }

/* --- touch / small screens: drop the hovers, keep the entrance */
@media (max-width: 767px), (hover: none){
    .sd-page .col-md-4.my-4:hover{ transform: none; box-shadow: none; }
    .sd-page .col-md-4.my-4:hover .testimoimg{ transform: none; box-shadow: none; }
    .sd-page .col-md-4.my-4:hover .doccard-img img,
    .sd-page .col-md-4.my-4:hover .awards-card .post-img img{ transform: none; filter: none; }
    .sd-page .col-md-4.my-4:hover .awards-card .post-img::after{ animation: none; }
    .sd-page .gallery a.item:hover .presscard{ transform: none; box-shadow: none; filter: none; }
    .sd-page .gallery .d-flex > a:hover{ transform: none; }
    .sd-page #load_more .btn:hover{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .sd-page h1,
    .sd-page .col-md-4.my-4,
    .sd-page .service-card .text-hover-color,
    .sd-page .service-card p.overelipsis3,
    .sd-page .service-card p.peoplereview,
    .sd-page .doccard p.fw-600,
    .sd-page .doccard h3.doctitle,
    .sd-page .doccard p.overelipsis2,
    .sd-page .doccard .btn.btnthird,
    .sd-page .awards-card .card-text > h3,
    .sd-page .awards-card .card-text > p,
    .sd-page .awards-card .peoplereview{ opacity: 1 !important; clip-path: none !important; transform: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .sd-page .service-card .testimoimg,
    .sd-page .doccard-img img,
    .sd-page .awards-card .post-img img{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .sd-page .awards-card .post-img::after{ opacity: 0 !important; animation: none !important; }
    /* News and Press Release listing — belt-and-braces alongside the above: .sd-js
       is only ever added once the script has already checked reduced-motion and
       chosen not to animate, so these mostly guard the HOVER effects, which run
       from plain :hover and are not gated by that check. */
    .sd-page .post.p-10 p.fw-600,
    .sd-page .post.p-10 p.newstitle,
    .sd-page .post.p-10 .btn.btnthird,
    .sd-page .gallery p.text-lblue,
    .sd-page .gallery p.overelipsis1,
    .sd-page .gallery p.presscontent,
    .sd-page .gallery p.text-96{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; transition: none !important; }
    .sd-page .post.p-10 .post-img img,
    .sd-page .gallery .presscard{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .sd-page .gallery .d-flex > a{ transform: none !important; transition: none !important; }
    .sd-page .gallery .d-flex > a::after{ transform: scaleX(0) !important; transition: none !important; }
    .sd-page #load_more .btn{ transition: none !important; }
    .sd-page #load_more .btn:hover{ transform: none !important; box-shadow: none !important; }
}

/* ---------------------------------------------------------------------------
   Photo Gallery listing page — same grid handle (.col-md-4.my-4), so it also
   runs on everything in the shared .sd-page block above. Reuses the exact
   "camera pulling back" gesture already established for this same album card
   on the home page (pgPullBack/pgWipe/pgBanner) — the markup is identical
   there down to the class names, so the same keyframes apply unmodified.
   --------------------------------------------------------------------------- */
/* opacity ONLY, no clip-path: pgPullBack below animates opacity/transform and
   never touches clip-path. A clip-path here would never be reversed by that
   keyframe, so the image would stay invisible until the script strips this
   class at the very end of the sequence — which is exactly what made it look
   "late". (Awards uses a real circle-reveal keyframe and needs its clip-path
   pre-hide; this one does not — copying that pattern here was the mistake.) */
.sd-page .sd-js .albumcss img{ opacity: 0; }
.sd-page .sd-js .albumcss + h3{ clip-path: inset(-.2em 100% -.2em -.2em); }

.sd-page .sd-js.sd-in .albumcss img{ animation: pgPullBack .8s cubic-bezier(.22,.61,.36,1) var(--sd-d, 0s) both; }
.sd-page .sd-js.sd-in .albumcss + h3{ animation: pgWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--sd-d, 0s) + .30s) both; }

/* --- hover: the shot pushes further in, and the "More Photos" banner (a plain
       display:none/block toggle, which cannot itself transition) slides up
       into view instead of popping. */
.sd-page .albumcss{ overflow: hidden; }
.sd-page .albumcss img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.sd-page .albumcss:hover img{ transform: scale(1.07); filter: brightness(1.03) contrast(1.03); }
.sd-page .albumcss:hover .allimgnums{ animation: pgBanner .35s cubic-bezier(.22,.61,.36,1); }
.sd-page .albumcss + h3{ transition: transform .35s cubic-bezier(.22,.61,.36,1); }
.sd-page a:hover .albumcss + h3{ transform: translateY(-2px); }

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .sd-page .albumcss:hover img{ transform: none; filter: none; }
    .sd-page a:hover .albumcss + h3{ transform: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .sd-page .albumcss + h3{ opacity: 1 !important; clip-path: none !important; transform: none !important; transition: none !important; }
    .sd-page .albumcss img{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .sd-page .albumcss:hover .allimgnums{ animation: none !important; }
}

/* ===========================================================================
   Blog listing page — entrance + hover.

   Animation-only and additive. With JS off or reduced-motion on, the page
   renders exactly as designed.

   This one gets its own block rather than joining the four listing pages above,
   for two reasons: its grid is TWO across (.col-md-6, so the diagonal maths uses
   a different column count and a different cell selector), and it has a sticky
   sidebar carrying a nested collapse accordion that none of the others have.

   The card gestures are borrowed from the home page blogs: the artwork is drawn
   in from the left, the headline typeset after it, then the copy and button.
   Those keyframes (blPlate, blTypeset, blBodyIn) are declared there and reused.

   Hover is on the ARTWORK ONLY — no cell lift — matching the explicit preference
   set for the home page blog cards, where the copy underneath must stay still.

   The sidebar column is `position: sticky`, so neither it nor the .sticky-top
   wrapper is ever transformed; only their children are animated.
   =========================================================================== */
/* --- pre-hide (only while the script drives the reveal) */
.bp-page .bp-js h1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.bp-page .bp-js .col-md-6.my-4{ opacity: 0; }
/* clip-path ONLY, no opacity: blPlate below animates clip-path/transform and
   never touches opacity. An opacity:0 here would never be reversed by that
   keyframe, so the image would stay invisible until the script strips this class
   at the very end of the sequence — which is exactly what made it look "late". */
.bp-page .bp-js .blog-img img{ clip-path: inset(0 100% 0 0); }
.bp-page .bp-js .blog p.overelipsis1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.bp-page .bp-js .blog p.overelipsis2,
.bp-page .bp-js .blog .btn.btnthird{ opacity: 0; }
.bp-page .bp-js .sticky-top > form,
.bp-page .bp-js .sticky-top > .blogcategory{ opacity: 0; }

/* --- reveal; each cell carries a --bp-d holding its diagonal position */
.bp-page .bp-js.bp-in h1{ animation: sdWipe .7s cubic-bezier(.22,.61,.36,1) .08s both; }
.bp-page .bp-js.bp-in .sticky-top > form{ animation: sdUp .5s ease .1s both; }
.bp-page .bp-js.bp-in .sticky-top > .blogcategory{ animation: sdUp .5s ease .2s both; }
/* The artwork starts at the SAME moment as its card, not after it. Previously it
   was offset +.10s and ran for .85s, so the card frame was already on screen
   while the picture inside was still arriving — which reads as the image being
   late. Now the two land together and the picture is the quickest thing in the
   card, so it leads the copy instead of trailing it. */
.bp-page .bp-js.bp-in .col-md-6.my-4{ animation: sdCardIn .6s cubic-bezier(.22,.61,.36,1) var(--bp-d, 0s) both; }
.bp-page .bp-js.bp-in .blog-img img{ animation: blPlate .55s cubic-bezier(.22,.61,.36,1) var(--bp-d, 0s) both; }
.bp-page .bp-js.bp-in .blog p.overelipsis1{ animation: blTypeset .45s cubic-bezier(.22,.61,.36,1) calc(var(--bp-d, 0s) + .14s) both; }
.bp-page .bp-js.bp-in .blog p.overelipsis2{ animation: blBodyIn .45s ease calc(var(--bp-d, 0s) + .24s) both; }
.bp-page .bp-js.bp-in .blog .btn.btnthird{ animation: blBodyIn .45s cubic-bezier(.34,1.56,.64,1) calc(var(--bp-d, 0s) + .32s) both; }

/* --- hover: the artwork alone. More specific than the shared
       `.blog-img:hover img` zoom, so it takes over cleanly. */
.bp-page .blog-img{ position: relative; overflow: hidden; cursor: pointer; }
.bp-page .blog-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.bp-page .blog-img:hover img{
    transform: translateY(-5px) scale(1.05);
    filter: brightness(1.03) contrast(1.03);
}

/* --- the sidebar archive. The arrow turns down only once its panel is genuinely
       open: Bootstrap sets aria-expanded on the toggle, whereas .collapsed is
       absent from the markup on load and so cannot be relied on for the initial
       state. The angle rides on a custom property so a hover nudge can compose
       with it instead of replacing it. */
.bp-page .yearnum > p{
    --bp-rot: 0deg;
    border-radius: 6px;
    transition: background-color .25s ease;
}
.bp-page .yearnum > p[aria-expanded="true"]{ --bp-rot: 90deg; }
.bp-page .yearnum > p:hover{ background-color: rgba(0,0,0,.045); }
.bp-page .yearnum > p i{
    transform: rotate(var(--bp-rot, 0deg));
    transition: transform .35s cubic-bezier(.34,1.56,.64,1);
}
.bp-page .yearnum > p:hover i{ transform: rotate(var(--bp-rot, 0deg)) translateX(3px); }
/* the month rows inside a year */
.bp-page .yearnum .collapse p.border{ transition: background-color .25s ease; }
.bp-page .yearnum .collapse p.border:hover{ background-color: rgba(0,0,0,.045); }
/* and the individual posts under a month get the site's growing amber rule */
.bp-page .yearnum li.border > a{
    position: relative; display: inline-block;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.bp-page .yearnum li.border > a::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
    background: #F7B32B;
    transform: scaleX(0); transform-origin: left center;
    transition: transform .3s cubic-bezier(.22,.61,.36,1);
}
.bp-page .yearnum li.border > a:hover{ transform: translateX(4px); text-decoration: none; }
.bp-page .yearnum li.border > a:hover::after{ transform: scaleX(1); }

/* the View More control answers the cursor like the rest of the site */
.bp-page #load_more .btn{ transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.bp-page #load_more .btn:hover{ transform: translateY(-3px); box-shadow: 0 12px 24px rgba(0,0,0,.16); }

/* --- touch / small screens: drop the hovers, keep the entrance */
@media (max-width: 767px), (hover: none){
    .bp-page .blog-img:hover img{ transform: none; filter: none; }
    .bp-page .yearnum > p:hover{ background-color: transparent; }
    .bp-page .yearnum > p:hover i{ transform: rotate(var(--bp-rot, 0deg)); }
    .bp-page .yearnum .collapse p.border:hover{ background-color: transparent; }
    .bp-page .yearnum li.border > a:hover{ transform: none; }
    .bp-page #load_more .btn:hover{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .bp-page h1,
    .bp-page .col-md-6.my-4,
    .bp-page .blog p.overelipsis1,
    .bp-page .blog p.overelipsis2,
    .bp-page .blog .btn.btnthird,
    .bp-page .sticky-top > form,
    .bp-page .sticky-top > .blogcategory{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; transition: none !important; }
    .bp-page .blog-img img{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .bp-page .yearnum > p,
    .bp-page .yearnum > p i,
    .bp-page .yearnum .collapse p.border,
    .bp-page .yearnum li.border > a{ transition: none !important; }
    .bp-page .yearnum li.border > a{ transform: none !important; }
    .bp-page .yearnum li.border > a::after{ transform: scaleX(0) !important; transition: none !important; }
    .bp-page #load_more .btn{ transition: none !important; }
    .bp-page #load_more .btn:hover{ transform: none !important; box-shadow: none !important; }
}

/* ===========================================================================
   Vision & Mission page — entrance + hover.

   Animation-only and additive. With JS off or reduced-motion on, the page
   renders exactly as designed.

   Reuses the exact "coming into focus" gesture (vmFocus/vmWipe/vmTextUp)
   already established for this same topic on the home page's Vision/Mission
   section, so the idea reads the same wherever it appears.

   Each entry (Vision, Mission, and any others the admin adds) is a large
   stacked block, not a grid cell, so it is revealed independently as it
   scrolls into view rather than cascading with a shared delay.

   STICKY SAFETY: the picture sits inside a `.sticky-top` div. Only the picture
   itself is ever animated. `.sticky-top` and everything above it — .col-md-4,
   .row, .col-md-12.mb-5 — are only ever given a marker class here, never a
   transform or filter: either one on an ANCESTOR of a sticky element creates a
   new containing block and breaks its stickiness. Transforming the picture
   itself is unaffected by this, since it is a descendant of the sticky div, not
   an ancestor of it.
   =========================================================================== */
.vmp-page .vme-js h3{ clip-path: inset(-.2em 100% -.2em -.2em); }
.vmp-page .vme-js .col-md-8 > p.fs-14,
.vmp-page .vme-js .col-md-8 > *:not(p.fs-14){ opacity: 0; }
.vmp-page .vme-js .sticky-top img.docimg{ opacity: 0; }

.vmp-page .vme-js.vme-in h3{ animation: vmWipe .75s cubic-bezier(.22,.61,.36,1) .05s both; }
.vmp-page .vme-js.vme-in .col-md-8 > p.fs-14{ animation: vmTextUp .6s ease .2s both; }
.vmp-page .vme-js.vme-in .col-md-8 > *:not(p.fs-14){ animation: vmTextUp .6s ease .32s both; }
.vmp-page .vme-js.vme-in .sticky-top img.docimg{ animation: vmFocus .9s cubic-bezier(.22,.61,.36,1) .15s both; }

/* --- hover: the picture alone comes further into focus */
.vmp-page .sticky-top img.docimg{ transition: transform .5s cubic-bezier(.22,.61,.36,1), filter .5s ease; }
.vmp-page .sticky-top:hover img.docimg{ transform: scale(1.03); filter: brightness(1.04) contrast(1.03); }

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .vmp-page .sticky-top:hover img.docimg{ transform: none; filter: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .vmp-page h3,
    .vmp-page .col-md-8 > p.fs-14,
    .vmp-page .col-md-8 > *:not(p.fs-14),
    .vmp-page .sticky-top img.docimg{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
}

/* ===========================================================================
   Events listing page — entrance + hover.

   Animation-only and additive. With JS off or reduced-motion on, the page
   renders exactly as designed.

   Reuses the exact keyframes already established for this same card on the
   home page (evWipe/evFlipIn/evTextUp/evCardUp), so the calendar-page-turning
   gesture reads the same wherever it appears. The colour flip itself
   (`.medevents:hover` → black background, amber accents) is a GLOBAL rule
   already shared by both pages; only the easing, lift, shadow and entrance are
   added here.

   This page's time paragraph carries only `.mb-0` — the home section's carries
   `.fw-600` too — so its selector is exclusion-based (mb-0, but not the day,
   title or venue-label paragraphs, which also carry mb-0) rather than relying
   on a class this page's markup doesn't have.

   Grid cascade: cards are `.col-md-3.medeventsdiv.my-4` (four across). The
   diagonal-wave delay is written by the script straight onto each `.medevents`
   element as --ev-d; being an ordinary (inheriting) custom property, its own
   child paragraphs pick it up automatically, with no extra wrapper needed.
   =========================================================================== */
.ev-page .ev-js h1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.ev-page .ev-js .medevents{ opacity: 0; }
.ev-page .ev-js .medevents > p.fs-50,
.ev-page .ev-js .medevents > p.fs-20:not(.title){ transform-origin: top center; }
.ev-page .ev-js .medevents > p{ opacity: 0; }

.ev-page .ev-js.ev-in h1{ animation: evWipe .8s cubic-bezier(.22,.61,.36,1) .1s both; }
.ev-page .ev-js.ev-in .medevents{ animation: evCardUp .7s cubic-bezier(.22,.61,.36,1) var(--ev-d, 0s) both; }
.ev-page .ev-js.ev-in .medevents > p.fs-50{ animation: evFlipIn .65s cubic-bezier(.22,.61,.36,1) calc(var(--ev-d, 0s) + .10s) both; }
.ev-page .ev-js.ev-in .medevents > p.fs-20:not(.title){ animation: evFlipIn .6s cubic-bezier(.22,.61,.36,1) calc(var(--ev-d, 0s) + .24s) both; }
.ev-page .ev-js.ev-in .medevents > p.title{ animation: evTextUp .5s ease calc(var(--ev-d, 0s) + .38s) both; }
.ev-page .ev-js.ev-in .medevents > p.mb-0:not(.title):not(.fs-50):not(.fs-12){ animation: evTextUp .5s ease calc(var(--ev-d, 0s) + .48s) both; }
.ev-page .ev-js.ev-in .medevents > p.fs-12,
.ev-page .ev-js.ev-in .medevents > p.overelipsis2{ animation: evTextUp .5s ease calc(var(--ev-d, 0s) + .58s) both; }

/* --- hover: same colour flip as the home section, now eased plus a lift */
.ev-page .medevents{
    transition: background-color .4s ease, transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease;
}
.ev-page .medevents p,
.ev-page .medevents span,
.ev-page .medevents .title{ transition: color .35s ease; }
.ev-page .medevents:hover{ transform: translateY(-6px); box-shadow: 0 16px 30px rgba(0,0,0,.20); }

/* --- touch / small screens: drop the lift, keep the entrance */
@media (max-width: 767px), (hover: none){
    .ev-page .medevents:hover{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .ev-page h1,
    .ev-page .medevents,
    .ev-page .medevents > p{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; }
    .ev-page .medevents,
    .ev-page .medevents p,
    .ev-page .medevents span{ transition: none !important; }
    .ev-page .medevents:hover{ box-shadow: none !important; }
}

/* ===========================================================================
   Testimonials listing page — entrance + hover.

   Animation-only and additive. With JS off or reduced-motion on, the page
   renders exactly as designed.

   Reuses the card-level and text keyframes already established on the home
   page's Testimonials section (tsCardUp/tsTextUp), so the two read as the same
   idea. The avatar ring is NOT reused as-is, though: the home section sits on a
   black panel, so its ring is white; this page's section is `bg-white`, where a
   white ring would be invisible, so it gets its own amber-toned version
   (tsAvatarInLight) — same gesture, adapted to the page it is on.

   This page covers several markup shapes sharing one outer `.wreviewpeople`
   class — a text quote, a local video, and a YouTube/Instagram poster-link (the
   fourth variant, an external YouTube link, is rendered `d-none` and so is
   never visible to animate) — so the entrance targets that shared wrapper plus
   a small set of variant-agnostic inner selectors, rather than choreographing
   every variant individually. The poster image in the YouTube/Insta variant is
   nested inside its own `<a>`, one level deeper than the video tag in the local
   variant, so it is matched as a descendant, not a direct child.
   =========================================================================== */
@keyframes tsAvatarInLight{
    0%  { opacity: 0; transform: scale(.4); box-shadow: 0 0 0 0    rgba(247,179,43,.45); }
    60% { opacity: 1; transform: scale(1.1); box-shadow: 0 0 0 12px rgba(247,179,43,.16); }
    100%{ opacity: 1; transform: scale(1);  box-shadow: 0 0 0 24px rgba(247,179,43,0); }
}

.ts-page .ts-js h1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.ts-page .ts-js .writereviewtestimonial h3{ opacity: 0; }
.ts-page .ts-js .wreviewpeople{ opacity: 0; }
.ts-page .ts-js .wreviewpeople .wrpeopleimg{ opacity: 0; }
.ts-page .ts-js .wreviewpeople img.image-fluid,
.ts-page .ts-js .wreviewpeople video{ opacity: 0; }
.ts-page .ts-js .wreviewpeople p.peoplereview,
.ts-page .ts-js .wreviewpeople p.overelipsis3,
.ts-page .ts-js .wreviewpeople .testimonial-stars{ opacity: 0; }

.ts-page .ts-js.ts-in h1{ animation: tsWipe .8s cubic-bezier(.22,.61,.36,1) .1s both; }
.ts-page .ts-js.ts-in .writereviewtestimonial h3{ animation: tsTextUp .6s ease .1s both; }
.ts-page .ts-js.ts-in .wreviewpeople{ animation: tsCardUp .7s cubic-bezier(.22,.61,.36,1) var(--ts-d, 0s) both; }
.ts-page .ts-js.ts-in .wreviewpeople .wrpeopleimg{ animation: tsAvatarInLight .7s cubic-bezier(.34,1.56,.64,1) calc(var(--ts-d, 0s) + .12s) both; }
.ts-page .ts-js.ts-in .wreviewpeople img.image-fluid,
.ts-page .ts-js.ts-in .wreviewpeople video{ animation: tsTextUp .6s ease calc(var(--ts-d, 0s) + .10s) both; }
.ts-page .ts-js.ts-in .wreviewpeople p.peoplereview{ animation: tsTextUp .55s ease calc(var(--ts-d, 0s) + .30s) both; }
.ts-page .ts-js.ts-in .wreviewpeople p.overelipsis3{ animation: tsTextUp .55s ease calc(var(--ts-d, 0s) + .26s) both; }
.ts-page .ts-js.ts-in .wreviewpeople .testimonial-stars{ animation: tsTextUp .5s ease calc(var(--ts-d, 0s) + .42s) both; }

/* --- hover: the card lifts, its picture/video eases forward, an avatar or a
       play control gets a touch more light. The local video's own play/pause
       behaviour, bound separately in js.php, is left completely untouched. */
.ts-page .wreviewpeople{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.ts-page .wreviewpeople:hover{ transform: translateY(-5px); box-shadow: 0 16px 30px rgba(0,0,0,.10); }
.ts-page .wreviewpeople img.image-fluid,
.ts-page .wreviewpeople video{ transition: transform .55s cubic-bezier(.22,.61,.36,1); }
.ts-page .wreviewpeople:hover img.image-fluid,
.ts-page .wreviewpeople:hover video{ transform: scale(1.03); }
.ts-page .wreviewpeople .wrpeopleimg{ transition: transform .4s cubic-bezier(.34,1.56,.64,1); }
.ts-page .wreviewpeople:hover .wrpeopleimg{ transform: scale(1.08); }
.ts-page .wreviewpeople .playButton,
.ts-page .wreviewpeople .playbtnimgvideo{ transition: transform .4s cubic-bezier(.34,1.56,.64,1); }
.ts-page .wreviewpeople:hover .playButton,
.ts-page .wreviewpeople:hover .playbtnimgvideo{ transform: scale(1.12); }

/* --- touch / small screens: drop the hovers, keep the entrance */
@media (max-width: 767px), (hover: none){
    .ts-page .wreviewpeople:hover{ transform: none; box-shadow: none; }
    .ts-page .wreviewpeople:hover img.image-fluid,
    .ts-page .wreviewpeople:hover video{ transform: none; }
    .ts-page .wreviewpeople:hover .wrpeopleimg{ transform: none; }
    .ts-page .wreviewpeople:hover .playButton,
    .ts-page .wreviewpeople:hover .playbtnimgvideo{ transform: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .ts-page h1,
    .ts-page .writereviewtestimonial h3,
    .ts-page .wreviewpeople,
    .ts-page .wreviewpeople .wrpeopleimg,
    .ts-page .wreviewpeople img.image-fluid,
    .ts-page .wreviewpeople video,
    .ts-page .wreviewpeople p.peoplereview,
    .ts-page .wreviewpeople p.overelipsis3,
    .ts-page .wreviewpeople .testimonial-stars{ opacity: 1 !important; clip-path: none !important; transform: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
}

/* ===========================================================================
   Video Gallery listing page — entrance + hover.

   Animation-only and additive. With JS off or reduced-motion on, the page
   renders exactly as designed.

   This page's markup is the same shape as the home page's video gallery right
   down to the class names (`.vedioimg`, `.videogallery`, `.playbtnimgvideo`),
   so it reuses those exact keyframes (vgWipe/vgThumbIn/vgPlayIn) unmodified.
   The play control's ring is white, which is correct here too: `.videogallery`
   carries its own dark gradient overlay regardless of which page it is on, so
   a white ring always sits on a dark patch, unlike the Testimonials avatar
   which needed an amber version for a plain white section background.

   Grid: cards are `.col-md-6.my-4` (two across, the same count as the Blog
   listing page), so this gets its own diagonal-cascade script rather than
   joining the three-or-four-across `.sd-page` system above.
   =========================================================================== */
.vg-page .vg-js h1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.vg-page .vg-js .col-md-6.my-4{ opacity: 0; }
.vg-page .vg-js .vedioimg img{ opacity: 0; transform: scale(1.1); }
.vg-page .vg-js .vedioimg .playbtnimgvideo{ opacity: 0; }
.vg-page .vg-js .vedioimg span.fs-16{ clip-path: inset(-.2em 100% -.2em -.2em); }

.vg-page .vg-js.vg-in h1{ animation: vgWipe .8s cubic-bezier(.22,.61,.36,1) .1s both; }
.vg-page .vg-js.vg-in .col-md-6.my-4{ animation: sdCardIn .7s cubic-bezier(.22,.61,.36,1) var(--vg-d, 0s) both; }
.vg-page .vg-js.vg-in .vedioimg img{ animation: vgThumbIn .75s cubic-bezier(.22,.61,.36,1) var(--vg-d, 0s) both; }
.vg-page .vg-js.vg-in .vedioimg .playbtnimgvideo{ animation: vgPlayIn .7s cubic-bezier(.34,1.56,.64,1) calc(var(--vg-d, 0s) + .28s) both; }
.vg-page .vg-js.vg-in .vedioimg span.fs-16{ animation: vgWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--vg-d, 0s) + .42s) both; }

/* --- hover: the thumbnail eases in behind its existing dark gradient and the
       play control swells with a ring. */
.vg-page .vedioimg{ overflow: hidden; }
.vg-page .vedioimg img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
    will-change: transform;
}
.vg-page .vedioimg:hover img{ transform: scale(1.06); filter: brightness(1.04) contrast(1.03); }
.vg-page .playbtnimgvideo{ transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease; border-radius: 50%; }
.vg-page .vedioimg:hover .playbtnimgvideo{ transform: scale(1.15); box-shadow: 0 0 0 10px rgba(255,255,255,.12); }

/* --- touch / small screens: drop the hover, keep the entrance */
@media (max-width: 767px), (hover: none){
    .vg-page .vedioimg:hover img{ transform: none; filter: none; }
    .vg-page .vedioimg:hover .playbtnimgvideo{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .vg-page h1,
    .vg-page .col-md-6.my-4,
    .vg-page .vedioimg span.fs-16{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; transition: none !important; }
    .vg-page .vedioimg img,
    .vg-page .vedioimg .playbtnimgvideo{ opacity: 1 !important; transform: none !important; filter: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
}

/* ===========================================================================
   Contact Us page — entrance + hover.

   One of the two "main" pages, so this gets the fullest treatment on the site:
   the enquiry form fields cascade in and the Submit button arrives last with a
   pop; the map cards fade up; each contact-info row slides in from the right
   with its icon popping an amber ring, then answers hover with a rotate and a
   ring of its own — the same idea already used for the footer's Book
   Appointment strip, built fresh here since that one is scoped to
   `.bookappfooter` specifically and this page's `.c_row`/`.c_icon` are a
   separate, page-local instance of the same shared base classes.

   STICKY SAFETY: the map column sits in a `.sticky-top` div (`.col-md-7 >
   .sticky-top`). Only ITS DESCENDANTS — the map cards inside — are ever
   animated; `.sticky-top` and its ancestors are left alone, since a transform
   or filter on either would create a new containing block and break the
   stickiness of everything below it.

   Animation-only and additive. With JS off or reduced-motion on, the page
   renders exactly as designed.
   =========================================================================== */
@keyframes cuWipe{
    from{ clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { clip-path: inset(-.2em -.2em -.2em -.2em); }
}
@keyframes cuFieldIn{ from{ opacity: 0; transform: translateY(12px); } to{ opacity: 1; transform: translateY(0); } }
/* the field lifts a hair as it is invalidated, in the SAME indigo the page
   already uses — no red is introduced, only motion and a stronger version of a
   colour this field already carries */
@keyframes cuShake{
    10%,90%{ transform: translateX(-1px); }
    20%,80%{ transform: translateX(2px); }
    30%,50%,70%{ transform: translateX(-4px); }
    40%,60%{ transform: translateX(4px); }
}
@keyframes cuBtnIn{
    0%  { opacity: 0; transform: translateY(16px) scale(.9); }
    60% { opacity: 1; transform: translateY(0)    scale(1.05); }
    100%{ opacity: 1; transform: translateY(0)    scale(1); }
}
@keyframes cuCardIn{ from{ opacity: 0; transform: scale(.96); } to{ opacity: 1; transform: scale(1); } }
@keyframes cuRowIn{ from{ opacity: 0; transform: translateX(26px); } to{ opacity: 1; transform: translateX(0); } }
@keyframes cuIconPop{
    0%  { opacity: 0; transform: scale(.3);   box-shadow: 0 0 0 0    rgba(247,179,43,.5); }
    60% { opacity: 1; transform: scale(1.15); box-shadow: 0 0 0 12px rgba(247,179,43,.18); }
    100%{ opacity: 1; transform: scale(1);    box-shadow: 0 0 0 24px rgba(247,179,43,0); }
}

/* --- the enquiry form: the signature entrance, converge-from-the-sides.
       Each label and its input arrive from OPPOSITE edges and dock together,
       rather than the form simply fading up — it assembles itself.

       DIRECTION: the script classifies each field by its actual rendered
       column position (odd = left, even = right) among the col-md-6 fields
       that are actually switched on, not by field NAME. Full Name/Email/
       Phone/Subject can each be toggled independently in the admin, which
       shifts who ends up in the visual left or right slot — keying off name
       instead of position would send a field the wrong direction the moment
       one of its neighbours is turned off. Message (col-md-12) always gets
       the left-column treatment, as specified, and closes the sequence;
       Submit follows as its own final step.

       OVERSHOOT: cubic-bezier(.16,1,.3,1) already overshoots slightly on its
       own — both interior control points sit at y=1 — but that native amount
       is small and distance-dependent. The keyframes below add an explicit
       70% stop instead, so every field overshoots by exactly the same
       6px/1.04-scale regardless of distance, matching every other overshoot
       already built this way elsewhere in this file (icon pops, card
       lay-downs, and so on) rather than leaving it to curve-math chance.

       OPACITY: only ever reaches 1 by the 40% mark of each element's own
       animation, then holds — so it is already solid while still travelling,
       never a fade dragged out over the full distance.

       GUARD RAILS: only transform and opacity move (position/margin are never
       touched, so layout cannot shift by a pixel), and `.form-group` gets
       `overflow:hidden` ONLY while `.cu-form-js` is present, so a field's ±60px
       travel can never spill into its neighbour — and the moment the sequence
       ends the clipping is lifted, before it can ever cut off the focus/hover
       glows added above, which extend a few px past the input's own edges. */
@keyframes cuArriveL{
    0%  { opacity: 0; transform: translateX(-60px); }
    40% { opacity: 1; }
    70% { transform: translateX(6px); }
    100%{ transform: translateX(0); }
}
@keyframes cuArriveR{
    0%  { opacity: 0; transform: translateX(60px); }
    40% { opacity: 1; }
    70% { transform: translateX(-6px); }
    100%{ transform: translateX(0); }
}
@keyframes cuSubmitConverge{
    0%  { opacity: 0; transform: scale(.85); }
    40% { opacity: 1; }
    70% { transform: scale(1.04); }
    100%{ transform: scale(1); }
}
/* the "docking" flash: a ring of the field's own indigo blooms as it lands and
   settles, timed to its own arrival rather than a fixed clock. box-shadow,
   never the real border, so the field's actual 1px border and box size are
   never touched — this is the one place transform/opacity alone couldn't
   deliver the effect asked for, so it is layered on as a second property. */
@keyframes cuDock{
    0%,75%{ box-shadow: 0 0 0 0 rgba(10,12,244,0); }
    88%   { box-shadow: 0 0 0 3px rgba(10,12,244,.65); }
    100%  { box-shadow: 0 0 0 0 rgba(10,12,244,0); }
}
/* reduced motion collapses the whole choreography to one plain fade */
@keyframes cuReducedFade{ from{ opacity: 0; } to{ opacity: 1; } }

.cu-page .cu-form-js .contactusform h1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.cu-page .cu-form-js.cu-form-in .contactusform h1{ animation: cuWipe .8s cubic-bezier(.22,.61,.36,1) .1s both; }

.cu-page .cu-form-js .contactusform .form-group{ overflow: hidden; }
.cu-page .cu-form-js .contactusform .form-group label,
.cu-page .cu-form-js .contactusform .form-group .form-control,
.cu-page .cu-form-js .contactusform #submit{ opacity: 0; }

.cu-page .cu-form-js.cu-form-in .contactusform .form-group.cu-left > label{
    animation: cuArriveL .55s cubic-bezier(.16,1,.3,1) var(--cu-row-d, 0s) both;
}
.cu-page .cu-form-js.cu-form-in .contactusform .form-group.cu-left > .form-control{
    animation: cuArriveR .55s cubic-bezier(.16,1,.3,1) var(--cu-input-d, .08s) both,
               cuDock .55s ease var(--cu-input-d, .08s) both;
}
.cu-page .cu-form-js.cu-form-in .contactusform .form-group.cu-right > label{
    animation: cuArriveR .55s cubic-bezier(.16,1,.3,1) var(--cu-row-d, 0s) both;
}
.cu-page .cu-form-js.cu-form-in .contactusform .form-group.cu-right > .form-control{
    animation: cuArriveL .55s cubic-bezier(.16,1,.3,1) var(--cu-input-d, .08s) both,
               cuDock .55s ease var(--cu-input-d, .08s) both;
}
.cu-page .cu-form-js.cu-form-in .contactusform #submit{
    animation: cuSubmitConverge .55s cubic-bezier(.16,1,.3,1) var(--cu-row-d, 0s) both;
}

/* reduced motion: a plain 200ms fade, no travel, no stagger */
@media (prefers-reduced-motion: reduce){
    .cu-page .cu-form-js .contactusform .form-group{ overflow: visible !important; }
    .cu-page .cu-form-js.cu-form-in .contactusform .form-group label,
    .cu-page .cu-form-js.cu-form-in .contactusform .form-group .form-control,
    .cu-page .cu-form-js.cu-form-in .contactusform #submit{
        animation: cuReducedFade .2s ease both !important;
    }
}

/* --- inputs & labels: decisive hover/focus feedback, not just the faint
       sitewide ring. This page's own fields are already a bold blue-bordered
       box (#0A0CF4, set above and never touched here), so the very low-alpha
       amber ring added globally for the rest of the site reads as almost
       nothing against it. Everything below is tinted with that SAME existing
       blue rather than a new colour — light layered on the page's own hue,
       the same principle used everywhere else on the site.

       Hover and focus are kept deliberately distinct: hover is an invitation
       (a small lift, a soft glow), focus is a commitment (no lift — the field
       is already where it needs to be — just a stronger glow, an accent border
       drawing in, and the resting tint easing toward the page's own white).
       `:hover:not(:focus)` on the shared box-shadow/transform properties keeps
       the two from fighting if a click lands on a field while the pointer is
       still over it. */
.cu-page .contactusform .form-group label{
    display: inline-block;
    transition: transform .25s cubic-bezier(.4,0,.2,1), color .25s cubic-bezier(.4,0,.2,1);
}
.cu-page .contactusform .form-group:hover label{ transform: translateY(-2px); }
.cu-page .contactusform .form-group:focus-within label{ color: #0A0CF4; transform: translateY(-2px); }

.cu-page .contactusform .form-group{ position: relative; }
.cu-page .contactusform .form-control{
    position: relative;   /* stacks above the accent border below, which shares its box */
    transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease, background-color .2s ease;
}
.cu-page .contactusform .form-control:hover:not(:focus){
    transform: translateY(-2px);
    box-shadow: 0 4px 14px rgba(10,12,244,.12);
}
.cu-page .contactusform .form-control:focus{
    box-shadow: 0 4px 18px rgba(10,12,244,.24);
    /* the existing pale tint eases toward the page's own white so typed text
       stands out — the same rgba(0,0,254) already set above, only fading */
    background-color: rgba(0, 0, 254, .01) !important;
}
/* the accent border draws in from the left on focus, layered over the resting
   one. A pseudo-element sized 2px beyond the input's own box (inset(-2px) —
   not a guess at where the label ends, which would be fragile) rather than
   the input's own border, so the field's actual 1px border and radius are
   never touched. `pointer-events:none` and sitting behind the input's own
   text/background keeps it purely decorative. */
.cu-page .contactusform .form-control::after{
    content: '';
    position: absolute; inset: -2px;
    border: 2px solid #0A0CF4;
    border-radius: 9px;
    clip-path: inset(0 100% 0 0);
    opacity: 0;
    pointer-events: none;
    z-index: -1;
}
.cu-page .contactusform .form-control:focus::after{
    opacity: 1;
    clip-path: inset(0 0 0 0);
    transition: clip-path .25s cubic-bezier(.4,0,.2,1), opacity .2s ease;
}

/* --- the whole enquiry form lifts a little further off the page while any one
       of its fields is focused, so the active form feels raised rather than
       just the single field inside it */
.cu-page .contactusform .row.w-75{ transition: box-shadow .35s ease; border-radius: 10px; }
.cu-page .contactusform .row.w-75:focus-within{ box-shadow: 0 20px 46px rgba(10,12,244,.10); }

/* --- invalid fields: jQuery Validate's OWN existing logic adds this .error
       class — nothing about that plugin or its rules is touched here, this
       only reacts to a class it already applies. Shake plus a stronger
       version of the field's own indigo; no red is introduced, since it is
       not used anywhere else in this design. */
.cu-page .contactusform .form-control.error{
    animation: cuShake .4s cubic-bezier(.36,.07,.19,.97) both;
    box-shadow: 0 0 0 3px rgba(10,12,244,.3);
}

/* --- touch / small screens: drop the field hovers, keep everything else */
@media (max-width: 767px), (hover: none){
    .cu-page .contactusform .form-group:hover label{ transform: none; }
    .cu-page .contactusform .form-control:hover:not(:focus){ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .cu-page .contactusform .form-group label,
    .cu-page .contactusform .form-control,
    .cu-page .contactusform .form-control::after,
    .cu-page .contactusform .row.w-75{ transition: none !important; }
    .cu-page .contactusform .form-group:hover label,
    .cu-page .contactusform .form-group:focus-within label{ transform: none !important; }
    /* background-color is deliberately left alone here: reduced-motion means no
       TRANSITION, not that the focus state can't change colour at all, and
       resetting it to `initial` would make the field transparent rather than
       restoring its actual resting tint (set with !important above). */
    .cu-page .contactusform .form-control:hover:not(:focus),
    .cu-page .contactusform .form-control:focus{ transform: none !important; box-shadow: none !important; }
    .cu-page .contactusform .form-control::after{ opacity: 0 !important; }
    .cu-page .contactusform .row.w-75:focus-within{ box-shadow: none !important; }
    .cu-page .contactusform .form-control.error{ animation: none !important; box-shadow: none !important; }
}

/* --- the map column + contact-info column --- */
.cu-page .cu-info-js .contdetails h2{ clip-path: inset(-.2em 100% -.2em -.2em); }
.cu-page .cu-info-js .contdetails h3{ opacity: 0; }
.cu-page .cu-info-js .mapouter{ opacity: 0; }
.cu-page .cu-info-js .contdetails .c_row{ opacity: 0; }
.cu-page .cu-info-js .contdetails .c_row .c_icon i{ opacity: 0; }

.cu-page .cu-info-js.cu-info-in .contdetails h2{ animation: cuWipe .75s cubic-bezier(.22,.61,.36,1) .1s both; }
.cu-page .cu-info-js.cu-info-in .mapouter{ animation: cuCardIn .6s cubic-bezier(.22,.61,.36,1) both; }
.cu-page .cu-info-js.cu-info-in .contdetails .c_row{ animation: cuRowIn .55s cubic-bezier(.22,.61,.36,1) both; }
.cu-page .cu-info-js.cu-info-in .contdetails .c_row .c_icon i{ animation: cuIconPop .55s cubic-bezier(.34,1.56,.64,1) var(--cu-icon-d, 0s) both; }
.cu-page .cu-info-js.cu-info-in .contdetails h3{ animation: cuFieldIn .5s ease both; }

/* --- hover: map cards lift, contact-icon rows answer the cursor exactly like
       the footer's own version of this same idea (rotate + amber ring) */
.cu-page .mapouter{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; border-radius: 6px; overflow: hidden; }
.cu-page .mapouter:hover{ transform: translateY(-4px); box-shadow: 0 16px 30px rgba(0,0,0,.14); }
.cu-page .contdetails .c_row a{ display: inline-block; transition: transform .3s cubic-bezier(.22,.61,.36,1); }
.cu-page .contdetails .c_row a:hover{ transform: translateX(4px); text-decoration: none; }
.cu-page .contdetails .c_row .c_icon i{ transition: transform .4s cubic-bezier(.34,1.56,.64,1); }
.cu-page .contdetails .c_row:hover .c_icon i{ transform: scale(1.2) rotate(-10deg); }
/* the standalone CTA button (dw_ci_value_type "btn") gets a lift, matching the
   rest of the site's buttons rather than only the colour-swap it has today */
.cu-page .contact_btn > a.btnprimary{ display: inline-block; transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.cu-page .contact_btn > a.btnprimary:hover{ transform: translateY(-3px); box-shadow: 0 10px 22px rgba(0,0,0,.16); }

/* --- Submit button: a lift plus a glow tinted with the button's OWN amber
       (#F7B32B), on top of the sitewide colour-ease/press already added
       globally to .btn. The press itself (:active) is that same global rule.

       NOTE ON SCOPE: a sweep/shine streak (à la the Blogs or Treatments cards)
       was considered here too, but this control is `<input type="submit">` —
       generated content (::before/::after) never renders on replaced form
       elements in any browser, so that technique has no element to attach to.
       A background-image sweep was the other option, but the button's colour
       is set via `background: ... !important` from a PHP variable the admin
       can change; layering a second background would mean hardcoding an
       assumed hex that could silently stop matching the real one. Skipped
       rather than shipped as something that looks right today and quietly
       breaks the first time the button colour is changed. */
.cu-page #lead_form #submit{ transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.cu-page #lead_form #submit:hover{ transform: translateY(-3px); box-shadow: 0 10px 22px rgba(247,179,43,.45); }

/* --- touch / small screens: drop the hovers, keep the entrance */
@media (max-width: 767px), (hover: none){
    .cu-page .mapouter:hover{ transform: none; box-shadow: none; }
    .cu-page .contdetails .c_row a:hover{ transform: none; }
    .cu-page .contdetails .c_row:hover .c_icon i{ transform: none; }
    .cu-page .contact_btn > a.btnprimary:hover{ transform: none; box-shadow: none; }
    .cu-page #lead_form #submit:hover{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .cu-page .contactusform h1,
    .cu-page .contactusform .row.w-75 > div,
    .cu-page .contdetails h2,
    .cu-page .contdetails h3,
    .cu-page .mapouter,
    .cu-page .contdetails .c_row{ opacity: 1 !important; clip-path: none !important; transform: none !important; animation: none !important; transition: none !important; }
    .cu-page .contdetails .c_row .c_icon i{ opacity: 1 !important; transform: none !important; box-shadow: none !important; animation: none !important; transition: none !important; }
    .cu-page .mapouter:hover,
    .cu-page .contact_btn > a.btnprimary:hover,
    .cu-page #lead_form #submit:hover{ transform: none !important; box-shadow: none !important; }
}

/* ===========================================================================
   Book Appointment page — entrance + hover.

   The other of the two "main" pages. This now has its OWN signature entrance —
   entirely bap-prefixed, no longer reusing Contact Us's generic keyframes — so
   the two main pages each have a distinct identity instead of one feeling like
   a copy of the other. Two things carry it: the big fs-40 headline resolves
   into focus (blur clearing as it rises) rather than a flat fade, and the
   portrait arrives from the right with a single light sweep crossing it once
   it lands, echoing the "premium portrait reveal" already used for doctor
   images elsewhere on the site. The eyebrow label above the headline, the form
   fields and the Submit button stay comparatively restrained — this is a form
   people need to read and fill in quickly, so the flourish belongs to the two
   hero elements (headline, portrait), not to every field.

   BUG FIXED HERE: the previous version paired `opacity:0` in the pre-hide with
   `cuWipe`, a keyframe that only ever animates clip-path — never opacity. That
   meant the h2 headline stayed fully invisible for the ENTIRE sequence and
   only snapped into view once the script stripped the reveal classes at the
   very end, which is exactly what read as "the title comes too late". Every
   keyframe below animates the same properties its own pre-hide rule sets, so
   that mismatch can't recur.

   Also adds one thing unique to this page: the appointment time-slot pills,
   injected by AJAX after the date/location handlers elsewhere in this file
   run. Their animation is a plain, always-on CSS rule rather than anything
   gated behind a reveal class, so it plays automatically whenever the existing
   script inserts new slots — nothing about that script is touched.

   Animation-only and additive. With JS off or reduced-motion on, the page
   renders exactly as designed.
   =========================================================================== */
@keyframes bapSlotIn{ from{ opacity: 0; transform: translateY(8px) scale(.92); } to{ opacity: 1; transform: translateY(0) scale(1); } }
/* the pill pops once when it becomes the selected slot */
@keyframes bapSlotPick{ 0%{ transform: scale(1); } 45%{ transform: scale(1.08); } 100%{ transform: scale(1); } }

/* the eyebrow label: a clean, quick wipe — opacity paired with clip-path, so
   it can never fall into the trap described above */
@keyframes bapHeadReveal{
    from{ opacity: 0; clip-path: inset(-.2em 100% -.2em -.2em); }
    to  { opacity: 1; clip-path: inset(-.2em -.2em -.2em -.2em); }
}
/* the big title: heavier and more deliberate than the eyebrow above it —
   resolves out of a blur as it rises, the same "coming into focus" idea used
   for Vision & Mission, carried here as this page's own version of it */
@keyframes bapTitleFocus{
    from{ opacity: 0; transform: translateY(20px); filter: blur(8px); }
    to  { opacity: 1; transform: translateY(0);    filter: blur(0); }
}
@keyframes bapFieldIn{
    from{ opacity: 0; transform: translateY(16px) scale(.98); }
    to  { opacity: 1; transform: translateY(0)    scale(1); }
}
/* the portrait arrives from the right and settles */
@keyframes bapPortraitIn{
    from{ opacity: 0; transform: translateX(50px) scale(1.04); }
    to  { opacity: 1; transform: translateX(0)    scale(1); }
}
/* a single light sweep crosses the portrait once it has landed */
@keyframes bapGleam{
    0%  { opacity: 0; transform: translateX(-140%) skewX(-20deg); }
    12% { opacity: 1; }
    88% { opacity: 1; }
    100%{ opacity: 0; transform: translateX(340%) skewX(-20deg); }
}

/* --- the form: eyebrow, then the big title resolving into focus, fields
       cascading (overlapping the title rather than waiting for it, so the
       whole thing reads as one continuous assembly instead of two separate
       waits), Submit arriving last with a pop */
.bap-page .bap-js .bookappempire h1,
.bap-page .bap-js .bookappempire h2{ opacity: 0; }
.bap-page .bap-js #appointment_form > .row > div{ opacity: 0; }
.bap-page .bap-js .contactdocimg{ opacity: 0; }

.bap-page .bap-js.bap-in .bookappempire h1{ animation: bapHeadReveal .55s cubic-bezier(.22,.61,.36,1) .05s both; }
.bap-page .bap-js.bap-in .bookappempire h2{ animation: bapTitleFocus .8s cubic-bezier(.22,.61,.36,1) .15s both; }
.bap-page .bap-js.bap-in #appointment_form > .row > div.bap-field{ animation: bapFieldIn .5s cubic-bezier(.22,.61,.36,1) both; }
.bap-page .bap-js.bap-in #appointment_form > .row > div.bap-submit{ animation: cuSubmitConverge .6s cubic-bezier(.34,1.56,.64,1) both; }
.bap-page .bap-js.bap-in .contactdocimg{ animation: bapPortraitIn .7s cubic-bezier(.22,.61,.36,1) .2s both; }

/* --- hover: the side portrait eases forward, matching the treatment already
       used for every other doctor/side image on the site. No overflow/position
       needed here — the wrapping .bap-img-col below already contains both the
       hover zoom and the gleam. */
.bap-page .contactdocimg{ transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease; }
.bap-page .contactdocimg:hover{ transform: scale(1.02); filter: brightness(1.03) contrast(1.02); }
/* the entrance gleam sits on the wrapping column (marked `.bap-img-col` in the
   markup, rather than matched via :has() — plain class support is universal,
   :has() only shipped in every evergreen browser as of late 2023), not the img
   itself, so it can sweep across without being scaled/moved by the portrait's
   own hover zoom */
.bap-page .bap-img-col{ position: relative; overflow: hidden; }
.bap-page .bap-img-col::after{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 45%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.25), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.bap-page .bap-js.bap-in .bap-img-col::after{
    animation: bapGleam 1s cubic-bezier(.4,0,.2,1) .75s both;
}

/* --- Submit button: a lift on top of the sitewide colour-ease/press already
       added globally to .btn */
.bap-page #appointment_form #submit{ transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.bap-page #appointment_form #submit:hover{ transform: translateY(-3px); box-shadow: 0 12px 24px rgba(0,0,0,.18); }

/* --- the appointment slot pills: fade+scale in as the existing AJAX handler
       inserts each one, a lift on hover, and a small pop the instant a pill
       becomes the selected slot. The colours themselves (amber when :checked,
       from this page's own inline <style>) are untouched — this only adds the
       transition and the entrance/pick motion around them. */
.bap-page .rd_button{ animation: bapSlotIn .4s cubic-bezier(.22,.61,.36,1) both; }
.bap-page .rd_button:nth-child(1){ animation-delay: 0s; }
.bap-page .rd_button:nth-child(2){ animation-delay: .05s; }
.bap-page .rd_button:nth-child(3){ animation-delay: .10s; }
.bap-page .rd_button:nth-child(4){ animation-delay: .15s; }
.bap-page .rd_button:nth-child(5){ animation-delay: .20s; }
.bap-page .rd_button:nth-child(n+6){ animation-delay: .25s; }
.bap-page .rd_button label{
    transition: background-color .3s ease, color .3s ease,
                transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease;
}
.bap-page .rd_button label:hover{ transform: translateY(-2px); box-shadow: 0 6px 14px rgba(0,0,0,.12); }
.bap-page .rd_button input[type="radio"]:checked + label{ animation: bapSlotPick .4s cubic-bezier(.34,1.56,.64,1); }

/* --- touch / small screens: drop the hovers, keep the entrance */
@media (max-width: 767px), (hover: none){
    .bap-page .contactdocimg:hover{ transform: none; filter: none; }
    .bap-page #appointment_form #submit:hover{ transform: none; box-shadow: none; }
    .bap-page .rd_button label:hover{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce){
    .bap-page .bookappempire h1,
    .bap-page .bookappempire h2,
    .bap-page #appointment_form > .row > div,
    .bap-page .contactdocimg{ opacity: 1 !important; clip-path: none !important; transform: none !important; filter: none !important; animation: none !important; transition: none !important; }
    .bap-page .contactdocimg:hover{ transform: none !important; filter: none !important; }
    .bap-page .bap-img-col::after{ opacity: 0 !important; animation: none !important; }
    .bap-page #appointment_form #submit:hover{ transform: none !important; box-shadow: none !important; }
    .bap-page .rd_button{ animation: none !important; }
    .bap-page .rd_button label{ transition: none !important; }
    .bap-page .rd_button label:hover{ transform: none !important; box-shadow: none !important; }
    .bap-page .rd_button input[type="radio"]:checked + label{ animation: none !important; }
}


/* ==========================================================================
   Service detail page — servicesinfo.php  (.si-page)
   ==========================================================================
   This page is an ARTICLE, not a grid, so it gets two different reveal
   strategies rather than one:

     1. The hero — title, photo, short description — is a one-shot
        choreographed entrance that plays straight away, because it is above
        the fold by definition.
     2. Everything after it reveals per block AS IT SCROLLS IN. That part of
        the page is `dw_sr_long_description_1`, free-form HTML from the admin
        of completely unknown length. A single staggered one-shot would either
        take ten seconds on a long article or would have finished playing long
        before the reader scrolled down to it.

   SCOPING: the script marks the article column `.si-body` and the trailing
   section `.si-more`, so no rule here depends on a Bootstrap class position.
   That matters because `.col-md-4.my-4`, `.service-card`, `.testimoimg`,
   `.text-hover-color` and `p.overelipsis3` on this page are the SAME markup as
   the Services/Departments listing cards (`.sd-page`) and the two home-page
   sections (`.sv-sec`, `.dp-sec`). All four are scoped on <body> or on the
   section, so none of them can reach in here.

   PRE-HIDE DISCIPLINE: every pre-hide below sets `opacity` and nothing else.
   The clip-path/transform starting states come from each keyframe's own `from`
   via `animation-fill-mode: both`. Pre-hiding a property that the paired
   keyframe never animates is what strands an element invisible for its whole
   sequence — the bug this file has had to fix four times (blPlate, nwPlate,
   pgPullBack, cuWipe-on-h2). Opacity is animated by every keyframe below, so
   it cannot happen here.
   ========================================================================== */

/* the title rises out of its own baseline behind a mask. Every other reveal on
   the site wipes HORIZONTALLY (inset(0 100% 0 0)); this is the vertical form,
   so the detail page reads as its own thing. The -.2em bleed top and bottom
   keeps ascenders and descenders from being shaved by the mask. */
@keyframes siMaskRise{
    from{ opacity: 0; clip-path: inset(100% 0 -.2em 0); transform: translateY(.4em); }
    to  { opacity: 1; clip-path: inset(-.2em 0 -.2em 0); transform: translateY(0); }
}
/* the hero photo unrolls top-to-bottom and settles down into place. Deliberately
   NO scale: it is a w-100 image with no clipping wrapper anywhere above it, so
   scaling it up would spill over the copy below and can trip a transient
   horizontal scrollbar. translateY is safe — it moves the image up, so it
   cannot add page height either. */
@keyframes siUnfurl{
    from{ opacity: 0; clip-path: inset(0 0 100% 0); transform: translateY(-10px); }
    35% { opacity: 1; }
    to  { opacity: 1; clip-path: inset(0 0 0 0);   transform: translateY(0); }
}
/* the workhorse: every article body block, and the fallback for any hero member
   that turns out to be neither the h1 nor the photo */
@keyframes siRise{
    from{ opacity: 0; transform: translateY(18px); }
    to  { opacity: 1; transform: translateY(0); }
}
/* More Services */
@keyframes siCardUp{
    from{ opacity: 0; transform: translateY(26px) scale(.97); }
    to  { opacity: 1; transform: translateY(0)    scale(1); }
}
@keyframes siIconIn{
    0%  { opacity: 0; transform: scale(.4)   rotate(-25deg); }
    60% { opacity: 1; transform: scale(1.12) rotate(6deg); }
    100%{ opacity: 1; transform: scale(1)    rotate(0deg); }
}
/* the card title slides in from the RIGHT on purpose — it carries .pl-90 to
   clear the absolutely-positioned 75px icon, and coming from the left would
   walk the text across that icon on the way in */
@keyframes siTitleIn{
    from{ opacity: 0; transform: translateX(10px); }
    to  { opacity: 1; transform: translateX(0); }
}
@keyframes siTextUp{
    from{ opacity: 0; transform: translateY(12px); }
    to  { opacity: 1; transform: translateY(0); }
}

/* --- pre-hide (opacity only — see the discipline note above) */
.si-page .si-h,
.si-page .si-r{ opacity: 0; }

/* --- hero reveal. The GENERIC rule is listed first so that any element which
       ends up promoted into the hero group still gets an opacity-animating
       reveal; the h1 and the photo then override it with their own gesture.
       This is what makes the group safe when the h1, photo or description is
       switched off in the admin and something else takes its slot. */
.si-page .si-body.si-in .si-h{ animation: siRise .65s cubic-bezier(.22,.61,.36,1) both; }
.si-page .si-body.si-in h1.si-h{ animation: siMaskRise .85s cubic-bezier(.22,.61,.36,1) both; }
.si-page .si-body.si-in img.si-h{ animation: siUnfurl 1s cubic-bezier(.22,.61,.36,1) both; }

/* --- article body: one block at a time, as it arrives */
.si-page .si-r.si-seen{ animation: siRise .6s cubic-bezier(.22,.61,.36,1) both; }

/* --- hover: the hero photo gets a light grade and a lifted shadow only. See
       the siUnfurl note for why it must not be scaled. */
.si-page .si-body > img.docimg{ transition: filter .5s ease, box-shadow .5s ease; }
.si-page .si-body > img.docimg:hover{
    filter: brightness(1.04) contrast(1.02) saturate(1.03);
    box-shadow: 0 14px 34px rgba(0,0,0,.14);
}

/* --- any LINKED image in the article lifts. This covers the optional CTA
       banner and any image the admin has linked inside the long description.
       Keyed on the anchor rather than a JS-added marker, so a CTA with no
       dw_sr_cta_link correctly gets no clickable affordance. */
.si-page .si-body a > img{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.si-page .si-body a:hover > img{ transform: translateY(-5px); box-shadow: 0 16px 32px rgba(0,0,0,.16); }

/* --- More Services: entrance, diagonal stagger via --si-d set per cell */
.si-page .si-more.si-mjs h2{ opacity: 0; }
.si-page .si-more.si-mjs .service-card{ opacity: 0; }
.si-page .si-more.si-mjs .service-card .testimoimg{ opacity: 0; }
.si-page .si-more.si-mjs .service-card .position-relative > p{ opacity: 0; }
.si-page .si-more.si-mjs .service-card p.overelipsis3{ opacity: 0; }

.si-page .si-more.si-mjs.si-min h2{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.si-page .si-more.si-mjs.si-min .service-card{ animation: siCardUp .7s cubic-bezier(.22,.61,.36,1) var(--si-d, 0s) both; }
.si-page .si-more.si-mjs.si-min .service-card .testimoimg{ animation: siIconIn .7s cubic-bezier(.34,1.56,.64,1) calc(var(--si-d, 0s) + .14s) both; }
.si-page .si-more.si-mjs.si-min .service-card .position-relative > p{ animation: siTitleIn .55s cubic-bezier(.22,.61,.36,1) calc(var(--si-d, 0s) + .3s) both; }
.si-page .si-more.si-mjs.si-min .service-card p.overelipsis3{ animation: siTextUp .55s ease calc(var(--si-d, 0s) + .44s) both; }

/* --- More Services: hover. The theme's own `.service-card:hover
       .text-hover-color` amber is left exactly as it is — this only gives it a
       transition to ease over, and adds the lift and the icon ring around it.
       The ring reuses that same amber (#F7B32B), so no new hue is introduced.

       There is deliberately NO underline sweep on the card title: it carries
       .overelipsis1, which is `display:-webkit-box` + `overflow:hidden` for the
       line clamp, so an absolutely positioned ::after would be clipped by that
       overflow or counted by the clamp — and placing one under the text would
       mean guessing the .pl-90 offset that clears the icon. */
.si-page .si-more .service-card{ transition: transform .4s cubic-bezier(.22,.61,.36,1); }
.si-page .si-more .service-card:hover{ transform: translateY(-8px); }
.si-page .si-more .service-card .text-hover-color{ transition: color .3s ease; }
.si-page .si-more .service-card .testimoimg{
    transition: transform .45s cubic-bezier(.34,1.56,.64,1), box-shadow .45s ease;
}
.si-page .si-more .service-card:hover .testimoimg{
    transform: scale(1.1) rotate(-6deg);
    box-shadow: 0 0 0 6px rgba(247,179,43,.18), 0 10px 20px rgba(0,0,0,.14);
}

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .si-page .si-body > img.docimg:hover{ filter: none; box-shadow: none; }
    .si-page .si-body a:hover > img{ transform: none; box-shadow: none; }
    .si-page .si-more .service-card:hover{ transform: none; }
    .si-page .si-more .service-card:hover .testimoimg{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion. The script already bails before it
   adds .si-h/.si-r/.si-mjs, so this is belt-and-braces — it also covers the
   case where the OS setting is flipped after the page has loaded. */
@media (prefers-reduced-motion: reduce){
    .si-page .si-h,
    .si-page .si-r,
    .si-page .si-more h2,
    .si-page .si-more .service-card,
    .si-page .si-more .service-card .testimoimg,
    .si-page .si-more .service-card .position-relative > p,
    .si-page .si-more .service-card p.overelipsis3{
        opacity: 1 !important; clip-path: none !important; transform: none !important;
        animation: none !important; transition: none !important;
    }
    .si-page .si-body > img.docimg{ transition: none !important; }
    .si-page .si-body > img.docimg:hover{ filter: none !important; box-shadow: none !important; }
    .si-page .si-body a > img{ transition: none !important; }
    .si-page .si-body a:hover > img{ transform: none !important; box-shadow: none !important; }
    .si-page .si-more .service-card .text-hover-color{ transition: none !important; }
    .si-page .si-more .service-card:hover{ transform: none !important; }
    .si-page .si-more .service-card .testimoimg{ transition: none !important; }
    .si-page .si-more .service-card:hover .testimoimg{ transform: none !important; box-shadow: none !important; }
}


/* ==========================================================================
   Doctor detail page — doctorsinfo.php  (.di-page)
   ==========================================================================
   Four zones, each with its own strategy:

     A. HERO — portrait + name + copy + Book Appointment. One-shot, plays at
        once: it is above the fold.
     B. `.points` — the long spec table, the second photo, the social row and
        the CTA. Reveals PER BLOCK AS IT SCROLLS IN, because how many rows the
        admin has filled in is unknowable and several of the fields are
        free-form HTML.
     C. Treatments sidebar — staggered down the column.
     D. "More Doctors" — diagonal wave.

   COMPONENT REUSE, deliberately: `.treatments-card` here is the same component
   as the home page's treatments section, and `.doccard` is the same component
   as the home section (`#doctors`) and the doctors listing page (`.sd-page`).
   Those already have entrance keyframes and a hover language, so this page
   REUSES trCardUp/trBand/trTextUp/trGleam and drCardUp/drDoors/drWipe/drTextUp
   rather than inventing a second way for the same card to move. Only the
   scoping is new. (Reusing another block's keyframes is already the convention
   here — `.sd-page` reuses drDoors, `.bp-page` reuses blTypeset, `.bap-page`
   reuses cuSubmitConverge.)

   Two things this page needed that the shared scopes provide but it did not:

     * `.doccard-img` and `.card-img` get `position: relative; overflow: hidden`
       here. The GLOBAL rule at the top of this file already zooms
       `.doccard:hover .doccard-img img` to 1.03 on every page — on this page
       there was nothing clipping it, so that pre-existing zoom was spilling
       out of the frame. The containment also clips trBand's and drDoors'
       scale(1.05/1.06), exactly as it does in the other two scopes.
     * `.treatments-card:hover h3.treattitle` amber. The theme's own rule for
       that (line ~240) is scoped `.treatments .treatments-card:hover`, and this
       page's sidebar has no `.treatments` ancestor, so the component was
       missing its established hover colour here. Re-added with the SAME
       #F7B32B. Flagging it because it is the one place in this block that
       introduces a colour where none was rendering before — say the word and
       it comes straight out.

   PRE-HIDE DISCIPLINE: as in the .si-page block, a pre-hide may only set
   properties its paired keyframe actually animates. Note `p.fw-600` below is
   pre-hidden with CLIP-PATH, not opacity — drWipe animates clip-path only, so
   pre-hiding it with opacity would strand it invisible for the whole sequence.
   That is the trap; the other two scopes get it right and so does this one.
   ========================================================================== */

/* the portrait rises INTO its frame: the mask opens bottom-up while the picture
   settles upward. Deliberately no scale — the portrait sits in a `.sticky-top`,
   and giving that overflow:hidden is what turns a sticky element into a scroll
   container and kills the stickiness, so there is nothing available to clip a
   zoom against. translateY is safe: transforms do not affect layout. */
@keyframes diPortraitIn{
    from{ opacity: 0; clip-path: inset(100% 0 0 0); transform: translateY(14px); }
    35% { opacity: 1; }
    to  { opacity: 1; clip-path: inset(0 0 0 0);    transform: translateY(0); }
}
/* a spec row opens: the label eases in from the left, the value follows from
   the right a beat behind it */
@keyframes diLabelIn{
    from{ opacity: 0; transform: translateX(-14px); }
    to  { opacity: 1; transform: translateX(0); }
}
@keyframes diValueIn{
    from{ opacity: 0; transform: translateX(14px); }
    to  { opacity: 1; transform: translateX(0); }
}
@keyframes diIconPop{
    0%  { opacity: 0; transform: scale(.3)  rotate(-30deg); }
    62% { opacity: 1; transform: scale(1.18) rotate(8deg); }
    100%{ opacity: 1; transform: scale(1)    rotate(0deg); }
}
@keyframes diBtnIn{
    0%  { opacity: 0; transform: translateY(16px) scale(.9); }
    65% { opacity: 1; transform: translateY(0)    scale(1.05); }
    100%{ opacity: 1; transform: translateY(0)    scale(1); }
}

/* --- A. HERO -------------------------------------------------------------- */
.di-page .di-h{ opacity: 0; }
/* generic first, so anything that ends up in the group still has an
   opacity-animating reveal; the specific gestures then override it */
.di-page .di-hero.di-in .di-h{ animation: siRise .6s cubic-bezier(.22,.61,.36,1) both; }
.di-page .di-hero.di-in h1.di-h{ animation: siMaskRise .85s cubic-bezier(.22,.61,.36,1) both; }
.di-page .di-hero.di-in img.docimg.di-h{ animation: diPortraitIn 1s cubic-bezier(.22,.61,.36,1) both; }
.di-page .di-hero.di-in .bookappointment-text.di-h{ animation: diBtnIn .7s cubic-bezier(.22,.61,.36,1) both; }

/* --- B. `.points`: one block at a time, as it arrives --------------------- */
.di-page .di-r{ opacity: 0; }
.di-page .di-r > .col-md-4,
.di-page .di-r > .col-md-8{ opacity: 0; }

.di-page .di-r.di-seen{ animation: siRise .6s cubic-bezier(.22,.61,.36,1) both; }
.di-page .di-r.di-seen > .col-md-4{ animation: diLabelIn .55s cubic-bezier(.22,.61,.36,1) .10s both; }
.di-page .di-r.di-seen > .col-md-8{ animation: diValueIn .55s cubic-bezier(.22,.61,.36,1) .20s both; }
/* the second, full-width photo unrolls rather than just rising */
.di-page img.docimg.di-r.di-seen{ animation: siUnfurl .95s cubic-bezier(.22,.61,.36,1) both; }
/* and the section heading gets the masked rise */
.di-page h2.text-app2.di-r.di-seen{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }

/* the social icons pop in one after another once their row arrives. Staggered
   in CSS rather than JS: only <a> elements are ever emitted in here, so
   nth-child counts them exactly, whichever networks the admin has filled in. */
.di-page .socialmedia.di-r .doctoricons{ opacity: 0; }
.di-page .socialmedia.di-r.di-seen .doctoricons{
    animation: diIconPop .55s cubic-bezier(.34,1.56,.64,1) var(--di-i, .3s) both;
}
.di-page .socialmedia .col-md-8 > a:nth-child(1) .doctoricons{ --di-i: .30s; }
.di-page .socialmedia .col-md-8 > a:nth-child(2) .doctoricons{ --di-i: .36s; }
.di-page .socialmedia .col-md-8 > a:nth-child(3) .doctoricons{ --di-i: .42s; }
.di-page .socialmedia .col-md-8 > a:nth-child(4) .doctoricons{ --di-i: .48s; }
.di-page .socialmedia .col-md-8 > a:nth-child(5) .doctoricons{ --di-i: .54s; }
.di-page .socialmedia .col-md-8 > a:nth-child(6) .doctoricons{ --di-i: .60s; }
.di-page .socialmedia .col-md-8 > a:nth-child(7) .doctoricons{ --di-i: .66s; }
.di-page .socialmedia .col-md-8 > a:nth-child(8) .doctoricons{ --di-i: .72s; }
.di-page .socialmedia .col-md-8 > a:nth-child(n+9) .doctoricons{ --di-i: .78s; }

/* --- C. Treatments sidebar: entrance ------------------------------------- */
.di-page .di-side.di-sjs h2{ opacity: 0; }
.di-page .di-side.di-sjs .treatments-card{ opacity: 0; }
.di-page .di-side.di-sjs .treatments-card .card-img img{ opacity: 0; }
.di-page .di-side.di-sjs .treatments-card h3.treattitle,
.di-page .di-side.di-sjs .treatments-card p.overelipsis2{ opacity: 0; }

.di-page .di-side.di-sjs.di-sin h2{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.di-page .di-side.di-sjs.di-sin .treatments-card{ animation: trCardUp .7s cubic-bezier(.22,.61,.36,1) var(--di-d, 0s) both; }
.di-page .di-side.di-sjs.di-sin .treatments-card .card-img img{ animation: trBand .85s cubic-bezier(.22,.61,.36,1) calc(var(--di-d, 0s) + .10s) both; }
.di-page .di-side.di-sjs.di-sin .treatments-card h3.treattitle{ animation: trTextUp .5s ease calc(var(--di-d, 0s) + .34s) both; }
.di-page .di-side.di-sjs.di-sin .treatments-card p.overelipsis2{ animation: trTextUp .5s ease calc(var(--di-d, 0s) + .46s) both; }

/* --- C. Treatments sidebar: hover. Same language as the home page's
       treatments cards — picture zooms, a gleam crosses it, an amber edge draws
       along the bottom. Triggered by the PICTURE, not the card, so moving the
       cursor over the name or the copy underneath does nothing. */
.di-page .di-side .treatments-card .card-img{ position: relative; overflow: hidden; cursor: pointer; }
.di-page .di-side .treatments-card .card-img img{
    transition: transform .6s cubic-bezier(.22,.61,.36,1), filter .6s ease;
}
.di-page .di-side .treatments-card .card-img:hover img{
    transform: scale(1.09);
    filter: brightness(1.05) contrast(1.04);
}
.di-page .di-side .treatments-card .card-img::before{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 38%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.30), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.di-page .di-side .treatments-card .card-img:hover::before{ animation: trGleam .9s cubic-bezier(.4,0,.2,1); }
.di-page .di-side .treatments-card .card-img::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
    height: 3px; background: #F7B32B;
    transform: scaleX(0); transform-origin: left center;
    transition: transform .5s cubic-bezier(.22,.61,.36,1);
    pointer-events: none;
}
.di-page .di-side .treatments-card .card-img:hover::after{ transform: scaleX(1); }
/* see the header note — restoring the colour the theme's own rule cannot reach
   on this page, using its exact value */
.di-page .di-side .treatments-card h3.treattitle{ transition: color .3s ease; }
.di-page .di-side .treatments-card:hover h3.treattitle{ color: #F7B32B; }

/* --- D. "More Doctors": entrance ---------------------------------------- */
.di-page .di-more.di-mjs h3.fw-800{ opacity: 0; }
.di-page .di-more.di-mjs .doccard{ opacity: 0; }
.di-page .di-more.di-mjs .doccard-img img{ opacity: 0; }
/* clip-path, NOT opacity — drWipe animates clip-path only (see header note) */
.di-page .di-more.di-mjs .doccard p.fw-600{ clip-path: inset(-.2em 100% -.2em -.2em); }
.di-page .di-more.di-mjs .doccard h3.doctitle,
.di-page .di-more.di-mjs .doccard p.overelipsis2,
.di-page .di-more.di-mjs .doccard .btn.btnthird{ opacity: 0; }

.di-page .di-more.di-mjs.di-min h3.fw-800{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.di-page .di-more.di-mjs.di-min .doccard{ animation: drCardUp .7s cubic-bezier(.22,.61,.36,1) var(--di-d, 0s) both; }
.di-page .di-more.di-mjs.di-min .doccard-img img{ animation: drDoors .85s cubic-bezier(.22,.61,.36,1) calc(var(--di-d, 0s) + .10s) both; }
.di-page .di-more.di-mjs.di-min .doccard p.fw-600{ animation: drWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--di-d, 0s) + .30s) both; }
.di-page .di-more.di-mjs.di-min .doccard h3.doctitle{ animation: drTextUp .5s ease calc(var(--di-d, 0s) + .42s) both; }
.di-page .di-more.di-mjs.di-min .doccard p.overelipsis2{ animation: drTextUp .5s ease calc(var(--di-d, 0s) + .52s) both; }
.di-page .di-more.di-mjs.di-min .doccard .btn.btnthird{ animation: drTextUp .5s ease calc(var(--di-d, 0s) + .62s) both; }

/* --- D. "More Doctors": hover. Same as the home section and the listing page.
       The containment here is also what finally clips the global
       `.doccard:hover .doccard-img img` zoom (see header note). */
.di-page .di-more .doccard-img{ position: relative; overflow: hidden; }
.di-page .di-more .doccard-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
}
.di-page .di-more .doccard:hover .doccard-img img{
    transform: translateY(-5px) scale(1.05);
    filter: brightness(1.03) contrast(1.03);
}
.di-page .di-more .doccard{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.di-page .di-more .doccard:hover{ transform: translateY(-6px); box-shadow: 0 16px 30px rgba(0,0,0,.16); }

/* --- hero hovers --------------------------------------------------------- */
/* the portrait gets a light grade and a lifted shadow only — no zoom, for the
   same sticky/no-clipping reason given on diPortraitIn */
.di-page .di-hero img.docimg{ transition: filter .5s ease, box-shadow .5s ease; }
.di-page .di-hero img.docimg:hover{
    filter: brightness(1.04) contrast(1.02) saturate(1.03);
    box-shadow: 0 14px 34px rgba(0,0,0,.14);
}
/* Book Appointment: a lift on top of the sitewide colour-ease/press already
   added globally to .btn */
.di-page .bookappointment-text .btn{ transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.di-page .bookappointment-text .btn:hover{ transform: translateY(-3px); box-shadow: 0 12px 24px rgba(0,0,0,.18); }

/* the social icons: a lift and a ring in the theme amber. Their own black
   background and white glyph are left exactly as they are. */
.di-page .doctoricons{ transition: transform .35s cubic-bezier(.34,1.56,.64,1), box-shadow .35s ease; }
.di-page a:hover .doctoricons{
    transform: translateY(-3px) scale(1.15);
    box-shadow: 0 0 0 4px rgba(247,179,43,.22);
}

/* the CTA banner, when the admin has given it a link. Scoped to a direct child
   of `.points` so it cannot catch the sidebar or "More Doctors" pictures, which
   are also `a > img`. */
.di-page .points > a > img{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.di-page .points > a:hover > img{ transform: translateY(-5px); box-shadow: 0 16px 32px rgba(0,0,0,.16); }

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .di-page .di-hero img.docimg:hover{ filter: none; box-shadow: none; }
    .di-page .bookappointment-text .btn:hover{ transform: none; box-shadow: none; }
    .di-page a:hover .doctoricons{ transform: none; box-shadow: none; }
    .di-page .points > a:hover > img{ transform: none; box-shadow: none; }
    .di-page .di-side .treatments-card .card-img:hover img{ transform: none; filter: none; }
    .di-page .di-side .treatments-card .card-img:hover::before{ animation: none; }
    .di-page .di-side .treatments-card .card-img:hover::after{ transform: scaleX(0); }
    .di-page .di-more .doccard:hover{ transform: none; box-shadow: none; }
    .di-page .di-more .doccard:hover .doccard-img img{ transform: none; filter: none; }
}

/* respect users who prefer reduced motion. The script already bails before it
   adds any of the driver classes, so this is belt-and-braces — it also covers
   the OS setting being flipped after the page has loaded. */
@media (prefers-reduced-motion: reduce){
    .di-page .di-h,
    .di-page .di-r,
    .di-page .di-r > .col-md-4,
    .di-page .di-r > .col-md-8,
    .di-page .socialmedia .doctoricons,
    .di-page .di-side h2,
    .di-page .di-side .treatments-card,
    .di-page .di-side .treatments-card .card-img img,
    .di-page .di-side .treatments-card h3.treattitle,
    .di-page .di-side .treatments-card p.overelipsis2,
    .di-page .di-more h3.fw-800,
    .di-page .di-more .doccard,
    .di-page .di-more .doccard-img img,
    .di-page .di-more .doccard p.fw-600,
    .di-page .di-more .doccard h3.doctitle,
    .di-page .di-more .doccard p.overelipsis2,
    .di-page .di-more .doccard .btn.btnthird{
        opacity: 1 !important; clip-path: none !important; transform: none !important;
        animation: none !important; transition: none !important;
    }
    .di-page .di-hero img.docimg{ transition: none !important; }
    .di-page .di-hero img.docimg:hover{ filter: none !important; box-shadow: none !important; }
    .di-page .bookappointment-text .btn{ transition: none !important; }
    .di-page .bookappointment-text .btn:hover{ transform: none !important; box-shadow: none !important; }
    .di-page a:hover .doctoricons{ transform: none !important; box-shadow: none !important; }
    .di-page .points > a > img{ transition: none !important; }
    .di-page .points > a:hover > img{ transform: none !important; box-shadow: none !important; }
    .di-page .di-side .treatments-card .card-img:hover img{ transform: none !important; filter: none !important; }
    .di-page .di-side .treatments-card .card-img::before{ opacity: 0 !important; animation: none !important; }
    .di-page .di-side .treatments-card .card-img::after{ transform: scaleX(0) !important; transition: none !important; }
    .di-page .di-more .doccard:hover{ transform: none !important; box-shadow: none !important; }
    .di-page .di-more .doccard:hover .doccard-img img{ transform: none !important; filter: none !important; }
}


/* ==========================================================================
   Department detail page — departmentsinfo.php  (.dpi-page)
   ==========================================================================
   NO new keyframes. Every component on this page already exists elsewhere on
   the site and already has a motion, so this block is entirely scoping and
   timing:

     A. ARTICLE column — same shape as the service detail page: masked title,
        unrolling photo, then the body revealing per block on scroll.
        (siMaskRise / siUnfurl / siRise)
     B. "Doctors Under X" — `.doccard`, the same card as the home section, the
        doctors listing and the doctor detail page. (drCardUp / drDoors /
        drWipe / drTextUp). TWO across here (col-md-6), not three.
     C. Treatments sidebar — same card as the home treatments section.
        (trCardUp / trBand / trTextUp / trGleam)
     D. "More Departments" — the same `.service-card` as the departments listing
        and the "More Services" strip on the service detail page, so it reuses
        that strip's motion. (siCardUp / siIconIn / siTitleIn / siTextUp)

   THREE THINGS THIS PAGE'S MARKUP DOES THAT THE OTHERS DO NOT:

   1. The sidebar wrapper is `class="sticky-top treatments"` — it carries
      `.treatments`. So the theme's own `.treatments .treatments-card:hover
      h3.treattitle` amber (line ~240) ALREADY fires here, unlike on the doctor
      detail page where that rule could not reach. It is therefore NOT re-added
      below; only a transition is added so it eases. For the same reason the
      existing reduced-motion block (line ~2162) already neutralises the
      sidebar cards — but its pseudo-element rules are scoped
      `.primary_section.treatments`, which this page is not, so the gleam and
      the amber edge DO have to be guarded here.

   2. `.service-card` is the inner `.row`, not the cell — as on the departments
      listing page. The stagger is therefore set on `.service-card` itself.

   3. Lines ~105-107 emit NESTED <a> tags around the card title. That is invalid
      HTML and every parser auto-closes the outer anchor, so the rendered DOM
      does not match the source and the h3 ends up inside the SECOND anchor.
      Every selector for that title is a DESCENDANT selector for this reason —
      `.position-relative > h3` would silently match nothing.

   PRE-HIDE DISCIPLINE, as in the two blocks above: a pre-hide may only set what
   its paired keyframe animates. Two live examples here — `p.fw-600` is
   pre-hidden with CLIP-PATH because drWipe animates clip-path only; and the
   "More Departments" title uses siTitleIn (opacity + translateX) rather than
   the sdWipe the listing page uses, precisely so it can be pre-hidden with
   opacity like everything around it.
   ========================================================================== */

/* --- A. ARTICLE column: hero plays at once, body reveals on scroll -------- */
.dpi-page .dpi-h,
.dpi-page .dpi-r{ opacity: 0; }

/* generic first, so anything promoted into the hero group still has an
   opacity-animating reveal; the title and photo then override it */
.dpi-page .dpi-body.dpi-in .dpi-h{ animation: siRise .65s cubic-bezier(.22,.61,.36,1) both; }
.dpi-page .dpi-body.dpi-in h1.dpi-h{ animation: siMaskRise .85s cubic-bezier(.22,.61,.36,1) both; }
.dpi-page .dpi-body.dpi-in img.docimg.dpi-h{ animation: siUnfurl 1s cubic-bezier(.22,.61,.36,1) both; }

.dpi-page .dpi-r.dpi-seen{ animation: siRise .6s cubic-bezier(.22,.61,.36,1) both; }
/* the two sub-headings ("Doctors Under X", the appointment strip's h5) rise
   behind a mask rather than just fading */
.dpi-page .dpi-r.dpi-seen > h5,
.dpi-page h3.dpi-r.dpi-seen{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }

/* --- A. hover: the department photo gets a light grade only. It is a w-100
       image with nothing clipping it, so a zoom would spill over the copy
       below — same reasoning as the service detail page's hero. */
.dpi-page .dpi-body > img.docimg{ transition: filter .5s ease, box-shadow .5s ease; }
.dpi-page .dpi-body > img.docimg:hover{
    filter: brightness(1.04) contrast(1.02) saturate(1.03);
    box-shadow: 0 14px 34px rgba(0,0,0,.14);
}
/* the CTA banner, when the admin has given it a link. Direct child of the
   column, so it cannot catch the doctor or treatment pictures further down. */
.dpi-page .dpi-body > a > img{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.dpi-page .dpi-body > a:hover > img{ transform: translateY(-5px); box-shadow: 0 16px 32px rgba(0,0,0,.16); }

/* --- A. the Book Appointment strip. Its amber `.bookapptxt` hover already
       exists in the theme (line ~352); this only gives it something to ease
       over, plus a nudge on the link itself. */
.dpi-page .bookappointment-text .bookapptxt{
    display: inline-block;
    transition: color .3s ease, transform .3s cubic-bezier(.22,.61,.36,1);
}
.dpi-page .bookappointment-text:hover .bookapptxt{ transform: translateX(4px); }

/* --- B. "Doctors Under X": entrance, TWO across ------------------------- */
.dpi-page .dpi-docs.dpi-djs .doccard{ opacity: 0; }
.dpi-page .dpi-docs.dpi-djs .doccard-img img{ opacity: 0; }
/* clip-path, NOT opacity — drWipe animates clip-path only */
.dpi-page .dpi-docs.dpi-djs .doccard p.fw-600{ clip-path: inset(-.2em 100% -.2em -.2em); }
.dpi-page .dpi-docs.dpi-djs .doccard h3.doctitle,
.dpi-page .dpi-docs.dpi-djs .doccard p.overelipsis2,
.dpi-page .dpi-docs.dpi-djs .doccard .btn.btnthird{ opacity: 0; }

.dpi-page .dpi-docs.dpi-djs.dpi-din .doccard{ animation: drCardUp .7s cubic-bezier(.22,.61,.36,1) var(--dpi-d, 0s) both; }
.dpi-page .dpi-docs.dpi-djs.dpi-din .doccard-img img{ animation: drDoors .85s cubic-bezier(.22,.61,.36,1) calc(var(--dpi-d, 0s) + .10s) both; }
.dpi-page .dpi-docs.dpi-djs.dpi-din .doccard p.fw-600{ animation: drWipe .55s cubic-bezier(.22,.61,.36,1) calc(var(--dpi-d, 0s) + .30s) both; }
.dpi-page .dpi-docs.dpi-djs.dpi-din .doccard h3.doctitle{ animation: drTextUp .5s ease calc(var(--dpi-d, 0s) + .42s) both; }
.dpi-page .dpi-docs.dpi-djs.dpi-din .doccard p.overelipsis2{ animation: drTextUp .5s ease calc(var(--dpi-d, 0s) + .52s) both; }
.dpi-page .dpi-docs.dpi-djs.dpi-din .doccard .btn.btnthird{ animation: drTextUp .5s ease calc(var(--dpi-d, 0s) + .62s) both; }

/* --- B. hover. Identical to the other three places this card appears. The
       containment is also what clips the GLOBAL `.doccard:hover .doccard-img
       img` zoom, which had nothing to clip it on this page, and drDoors'
       scale(1.05). */
.dpi-page .dpi-docs .doccard-img{ position: relative; overflow: hidden; }
.dpi-page .dpi-docs .doccard-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
}
.dpi-page .dpi-docs .doccard:hover .doccard-img img{
    transform: translateY(-5px) scale(1.05);
    filter: brightness(1.03) contrast(1.03);
}
.dpi-page .dpi-docs .doccard{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.dpi-page .dpi-docs .doccard:hover{ transform: translateY(-6px); box-shadow: 0 16px 30px rgba(0,0,0,.16); }

/* --- C. Treatments sidebar: entrance ------------------------------------ */
.dpi-page .dpi-side.dpi-sjs h2{ opacity: 0; }
.dpi-page .dpi-side.dpi-sjs .treatments-card{ opacity: 0; }
.dpi-page .dpi-side.dpi-sjs .treatments-card .card-img img{ opacity: 0; }
.dpi-page .dpi-side.dpi-sjs .treatments-card h3.treattitle,
.dpi-page .dpi-side.dpi-sjs .treatments-card p.overelipsis2{ opacity: 0; }

.dpi-page .dpi-side.dpi-sjs.dpi-sin h2{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.dpi-page .dpi-side.dpi-sjs.dpi-sin .treatments-card{ animation: trCardUp .7s cubic-bezier(.22,.61,.36,1) var(--dpi-d, 0s) both; }
.dpi-page .dpi-side.dpi-sjs.dpi-sin .treatments-card .card-img img{ animation: trBand .85s cubic-bezier(.22,.61,.36,1) calc(var(--dpi-d, 0s) + .10s) both; }
.dpi-page .dpi-side.dpi-sjs.dpi-sin .treatments-card h3.treattitle{ animation: trTextUp .5s ease calc(var(--dpi-d, 0s) + .34s) both; }
.dpi-page .dpi-side.dpi-sjs.dpi-sin .treatments-card p.overelipsis2{ animation: trTextUp .5s ease calc(var(--dpi-d, 0s) + .46s) both; }

/* --- C. hover: picture zooms, a gleam crosses it, an amber edge draws along
       the bottom. Triggered by the PICTURE, not the card, so the name and copy
       underneath are inert. The title's amber is the theme's own rule (see the
       header note) — only the transition is added here. */
.dpi-page .dpi-side .treatments-card .card-img{ position: relative; overflow: hidden; cursor: pointer; }
.dpi-page .dpi-side .treatments-card .card-img img{
    transition: transform .6s cubic-bezier(.22,.61,.36,1), filter .6s ease;
}
.dpi-page .dpi-side .treatments-card .card-img:hover img{
    transform: scale(1.09);
    filter: brightness(1.05) contrast(1.04);
}
.dpi-page .dpi-side .treatments-card .card-img::before{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 38%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.30), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.dpi-page .dpi-side .treatments-card .card-img:hover::before{ animation: trGleam .9s cubic-bezier(.4,0,.2,1); }
.dpi-page .dpi-side .treatments-card .card-img::after{
    content: '';
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
    height: 3px; background: #F7B32B;
    transform: scaleX(0); transform-origin: left center;
    transition: transform .5s cubic-bezier(.22,.61,.36,1);
    pointer-events: none;
}
.dpi-page .dpi-side .treatments-card .card-img:hover::after{ transform: scaleX(1); }
.dpi-page .dpi-side .treatments-card h3.treattitle{ transition: color .3s ease; }

/* --- D. "More Departments": entrance ------------------------------------ */
.dpi-page .dpi-more.dpi-mjs h2{ opacity: 0; }
.dpi-page .dpi-more.dpi-mjs .service-card{ opacity: 0; }
.dpi-page .dpi-more.dpi-mjs .service-card .testimoimg{ opacity: 0; }
/* descendant, not child — see the nested-anchor note in the header */
.dpi-page .dpi-more.dpi-mjs .service-card .text-hover-color{ opacity: 0; }
.dpi-page .dpi-more.dpi-mjs .service-card p.peoplereview{ opacity: 0; }

.dpi-page .dpi-more.dpi-mjs.dpi-min h2{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.dpi-page .dpi-more.dpi-mjs.dpi-min .service-card{ animation: siCardUp .7s cubic-bezier(.22,.61,.36,1) var(--dpi-d, 0s) both; }
.dpi-page .dpi-more.dpi-mjs.dpi-min .service-card .testimoimg{ animation: siIconIn .7s cubic-bezier(.34,1.56,.64,1) calc(var(--dpi-d, 0s) + .14s) both; }
.dpi-page .dpi-more.dpi-mjs.dpi-min .service-card .text-hover-color{ animation: siTitleIn .55s cubic-bezier(.22,.61,.36,1) calc(var(--dpi-d, 0s) + .3s) both; }
.dpi-page .dpi-more.dpi-mjs.dpi-min .service-card p.peoplereview{ animation: siTextUp .55s ease calc(var(--dpi-d, 0s) + .44s) both; }

/* --- D. hover. The theme's own `.service-card:hover .text-hover-color` amber
       is left as it is — this adds the lift and the icon ring around it, and
       the ring reuses that same amber so no new hue appears. */
.dpi-page .dpi-more .service-card{ transition: transform .4s cubic-bezier(.22,.61,.36,1); }
.dpi-page .dpi-more .col-md-4.my-4:hover .service-card{ transform: translateY(-8px); }
.dpi-page .dpi-more .service-card .text-hover-color{ transition: color .3s ease; }
.dpi-page .dpi-more .service-card .testimoimg{
    transition: transform .45s cubic-bezier(.34,1.56,.64,1), box-shadow .45s ease;
}
.dpi-page .dpi-more .col-md-4.my-4:hover .testimoimg{
    transform: scale(1.1) rotate(-6deg);
    box-shadow: 0 0 0 6px rgba(247,179,43,.18), 0 10px 20px rgba(0,0,0,.14);
}

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .dpi-page .dpi-body > img.docimg:hover{ filter: none; box-shadow: none; }
    .dpi-page .dpi-body > a:hover > img{ transform: none; box-shadow: none; }
    .dpi-page .bookappointment-text:hover .bookapptxt{ transform: none; }
    .dpi-page .dpi-docs .doccard:hover{ transform: none; box-shadow: none; }
    .dpi-page .dpi-docs .doccard:hover .doccard-img img{ transform: none; filter: none; }
    .dpi-page .dpi-side .treatments-card .card-img:hover img{ transform: none; filter: none; }
    .dpi-page .dpi-side .treatments-card .card-img:hover::before{ animation: none; }
    .dpi-page .dpi-side .treatments-card .card-img:hover::after{ transform: scaleX(0); }
    .dpi-page .dpi-more .col-md-4.my-4:hover .service-card{ transform: none; }
    .dpi-page .dpi-more .col-md-4.my-4:hover .testimoimg{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion. The script bails before adding any
   driver class, so this is belt-and-braces. The sidebar cards are partly
   covered already by the theme's own `.treatments`-scoped reduce block, but its
   pseudo-element rules need `.primary_section` and so miss this page — hence
   the ::before/::after entries below, which are the ones that matter. */
@media (prefers-reduced-motion: reduce){
    .dpi-page .dpi-h,
    .dpi-page .dpi-r,
    .dpi-page .dpi-docs .doccard,
    .dpi-page .dpi-docs .doccard-img img,
    .dpi-page .dpi-docs .doccard p.fw-600,
    .dpi-page .dpi-docs .doccard h3.doctitle,
    .dpi-page .dpi-docs .doccard p.overelipsis2,
    .dpi-page .dpi-docs .doccard .btn.btnthird,
    .dpi-page .dpi-side h2,
    .dpi-page .dpi-side .treatments-card,
    .dpi-page .dpi-side .treatments-card .card-img img,
    .dpi-page .dpi-side .treatments-card h3.treattitle,
    .dpi-page .dpi-side .treatments-card p.overelipsis2,
    .dpi-page .dpi-more h2,
    .dpi-page .dpi-more .service-card,
    .dpi-page .dpi-more .service-card .testimoimg,
    .dpi-page .dpi-more .service-card .text-hover-color,
    .dpi-page .dpi-more .service-card p.peoplereview{
        opacity: 1 !important; clip-path: none !important; transform: none !important;
        animation: none !important; transition: none !important;
    }
    .dpi-page .dpi-body > img.docimg{ transition: none !important; }
    .dpi-page .dpi-body > img.docimg:hover{ filter: none !important; box-shadow: none !important; }
    .dpi-page .dpi-body > a > img{ transition: none !important; }
    .dpi-page .dpi-body > a:hover > img{ transform: none !important; box-shadow: none !important; }
    .dpi-page .bookappointment-text .bookapptxt{ transition: none !important; }
    .dpi-page .bookappointment-text:hover .bookapptxt{ transform: none !important; }
    .dpi-page .dpi-docs .doccard:hover{ transform: none !important; box-shadow: none !important; }
    .dpi-page .dpi-docs .doccard:hover .doccard-img img{ transform: none !important; filter: none !important; }
    .dpi-page .dpi-side .treatments-card .card-img:hover img{ transform: none !important; filter: none !important; }
    .dpi-page .dpi-side .treatments-card .card-img::before{ opacity: 0 !important; animation: none !important; }
    .dpi-page .dpi-side .treatments-card .card-img::after{ transform: scaleX(0) !important; transition: none !important; }
    .dpi-page .dpi-more .col-md-4.my-4:hover .service-card{ transform: none !important; }
    .dpi-page .dpi-more .col-md-4.my-4:hover .testimoimg{ transform: none !important; box-shadow: none !important; }
}


/* ==========================================================================
   Blog detail page — bloginfo.php  (.bi-page)
   ==========================================================================
   Five zones:

     A. ARTICLE  (.blogarea) — masthead plays at once, body reveals on scroll
     B. "More from Blog" — `.blog` cards, TWO across
     C. Comment form (section.writereview)
     D. Comments (.wreviewpeople cards), TWO across

   COMPONENT REUSE: `.blog` here is the same card as the home blog section and
   the blog listing page, so it reuses blPlate / blTypeset / blBodyIn / blShine.
   `.wreviewpeople` is the same card as the testimonials page, so it reuses
   tsCardUp / tsTextUp. Only `biPlate` is new, and only because of the problem
   described immediately below.

   FOUR THINGS THIS PAGE'S MARKUP FORCES:

   1. blPlate CANNOT be used on the article's own hero image. It animates
      clip-path AND scale(1.05) but NOT opacity, and it relies on a clipping
      ancestor — `.blog-img{overflow:hidden}` in the two scopes that use it. The
      article hero is a bare <img> straight inside `.col-md-11` with nothing to
      clip it, so that scale would spill 5% over the copy. Hence `biPlate`: the
      same left-to-right editorial plate wipe, no scale (so it needs no
      containment) and WITH opacity (so it pairs with an ordinary pre-hide).
      blPlate is still used, unchanged, for the "More from Blog" cards, which do
      sit inside `.blog-img`.

   2. `.blog-img` gets `position: relative; overflow: hidden` here. The GLOBAL
      rule at the top of this file already zooms `.blog-img:hover img` to 1.03 on
      every page; on this page nothing was clipping it, so that pre-existing
      zoom was spilling out of the frame. It also clips blPlate's scale.

   3. The article's images and the WYSIWYG blocks cannot be selected by class —
      the hero <img> has NO class at all, and the long-description wrappers carry
      a class built from the row id (`<dwcode>_<id>_1`). Everything in zone A is
      therefore found by walking the column's children in document order.

   4. Line ~150 has a malformed `</div` (no closing bracket), so the parser
      produces ONE end tag where two were intended and the comment form's DOM
      nesting does not match the source. Zone C therefore never relies on that
      structure: it finds the form by `#lead_form` and its fields by
      `.form-group` descendants, which is correct however the divs end up
      nested. The markup itself is left alone — fixing it is a structural change.

   PRE-HIDE DISCIPLINE: a pre-hide may only set what its paired keyframe
   animates. This page has the two worst offenders in the file, and both are
   handled: `.blog-img img` is pre-hidden with CLIP-PATH (blPlate has no
   opacity — this exact pairing was one of the four historical bugs), and
   `p.overelipsis1` likewise (blTypeset is clip-path only).
   ========================================================================== */

/* the article hero: a left-to-right plate wipe. See note 1 above for why this
   is not blPlate. */
@keyframes biPlate{
    from{ opacity: 0; clip-path: inset(0 100% 0 0); }
    to  { opacity: 1; clip-path: inset(0 0 0 0); }
}

/* --- A. ARTICLE: masthead at once, body on scroll ------------------------- */
.bi-page .bi-h,
.bi-page .bi-r{ opacity: 0; }

/* generic first, so anything promoted into the masthead group still has an
   opacity-animating reveal; the title and hero photo then override it */
.bi-page .bi-body.bi-in .bi-h{ animation: siRise .6s cubic-bezier(.22,.61,.36,1) both; }
.bi-page .bi-body.bi-in h1.bi-h{ animation: siMaskRise .9s cubic-bezier(.22,.61,.36,1) both; }
.bi-page .bi-body.bi-in img.bi-h{ animation: biPlate .95s cubic-bezier(.22,.61,.36,1) both; }

.bi-page .bi-r.bi-seen{ animation: siRise .6s cubic-bezier(.22,.61,.36,1) both; }
/* the second photo sits in a col inside the alignment row — matching it via
   `> div > img` covers the Left, Right and stacked variants without the
   stylesheet needing to know which one the admin picked, and cannot catch the
   CTA banner, which is a direct child of the column */
.bi-page .bi-r.bi-seen > div > img{ animation: biPlate .9s cubic-bezier(.22,.61,.36,1) .12s both; }

/* --- A. hover. Every image in here is width:100% with a border (`.blogarea
       img`) and nothing clips it, so these get a light grade and a shadow
       rather than a zoom. */
.bi-page .bi-body img{ transition: filter .5s ease, box-shadow .5s ease; }
.bi-page .bi-body img:hover{
    filter: brightness(1.03) contrast(1.02) saturate(1.02);
    box-shadow: 0 14px 34px rgba(0,0,0,.13);
}
/* a linked image (the CTA banner, or anything the admin linked in the copy)
   lifts instead, since it is actually clickable */
.bi-page .bi-body a > img{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.bi-page .bi-body a:hover > img{ transform: translateY(-5px); box-shadow: 0 16px 32px rgba(0,0,0,.16); }

/* --- A. the Share row: the four buttons rise in turn, then lift on hover.
       Their brand background colours are untouched. */
.bi-page .bi-share.bi-r .bg-fb,
.bi-page .bi-share.bi-r .bg-twit,
.bi-page .bi-share.bi-r .bg-link,
.bi-page .bi-share.bi-r .bg-whats{ opacity: 0; }
.bi-page .bi-share.bi-r.bi-seen span > a{ animation: blBodyIn .5s cubic-bezier(.22,.61,.36,1) var(--bi-s, .2s) both; }
.bi-page .bi-share span > a:nth-child(1){ --bi-s: .20s; }
.bi-page .bi-share span > a:nth-child(2){ --bi-s: .28s; }
.bi-page .bi-share span > a:nth-child(3){ --bi-s: .36s; }
.bi-page .bi-share span > a:nth-child(4){ --bi-s: .44s; }
.bi-page .bi-share span > a{
    display: inline-block;
    transition: transform .3s cubic-bezier(.34,1.56,.64,1), box-shadow .3s ease;
}
.bi-page .bi-share span > a:hover{ transform: translateY(-4px); box-shadow: 0 8px 18px rgba(0,0,0,.22); }

/* --- B. "More from Blog": entrance, TWO across --------------------------- */
.bi-page .bi-more.bi-mjs h2{ opacity: 0; }
.bi-page .bi-more.bi-mjs .blog{ opacity: 0; }
/* clip-path, NOT opacity — blPlate animates clip-path + scale only */
.bi-page .bi-more.bi-mjs .blog-img img{ clip-path: inset(0 100% 0 0); }
/* likewise blTypeset */
.bi-page .bi-more.bi-mjs .blog p.overelipsis1{ clip-path: inset(-.2em 100% -.2em -.2em); }
.bi-page .bi-more.bi-mjs .blog p.overelipsis2,
.bi-page .bi-more.bi-mjs .blog .btn.btnthird{ opacity: 0; }

.bi-page .bi-more.bi-mjs.bi-min h2{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.bi-page .bi-more.bi-mjs.bi-min .blog{ animation: blBodyIn .6s cubic-bezier(.22,.61,.36,1) var(--bi-d, 0s) both; }
.bi-page .bi-more.bi-mjs.bi-min .blog-img img{ animation: blPlate .8s cubic-bezier(.22,.61,.36,1) calc(var(--bi-d, 0s) + .10s) both; }
.bi-page .bi-more.bi-mjs.bi-min .blog p.overelipsis1{ animation: blTypeset .6s cubic-bezier(.22,.61,.36,1) calc(var(--bi-d, 0s) + .34s) both; }
.bi-page .bi-more.bi-mjs.bi-min .blog p.overelipsis2{ animation: blBodyIn .5s ease calc(var(--bi-d, 0s) + .48s) both; }
.bi-page .bi-more.bi-mjs.bi-min .blog .btn.btnthird{ animation: blBodyIn .5s cubic-bezier(.34,1.56,.64,1) calc(var(--bi-d, 0s) + .60s) both; }

/* --- B. hover: the artwork only, same as the listing page. The containment is
       also what clips the global `.blog-img:hover img` zoom (see note 2). */
.bi-page .bi-more .blog-img{ position: relative; overflow: hidden; cursor: pointer; }
.bi-page .bi-more .blog-img img{
    transition: transform .55s cubic-bezier(.22,.61,.36,1), filter .55s ease;
}
.bi-page .bi-more .blog-img:hover img{
    transform: scale(1.06);
    filter: brightness(1.04) contrast(1.03);
}
.bi-page .bi-more .blog-img::after{
    content: '';
    position: absolute; top: 0; left: 0; z-index: 2;
    width: 40%; height: 100%;
    background: linear-gradient(100deg, rgba(255,255,255,0), rgba(255,255,255,.28), rgba(255,255,255,0));
    opacity: 0; pointer-events: none;
}
.bi-page .bi-more .blog-img:hover::after{ animation: blShine 1.4s cubic-bezier(.4,0,.2,1); }

/* --- C. comment form ----------------------------------------------------- */
.bi-page .bi-form.bi-fjs h3{ opacity: 0; }
.bi-page .bi-form.bi-fjs h3 + p{ opacity: 0; }
.bi-page .bi-form.bi-fjs .bi-fld,
.bi-page .bi-form.bi-fjs .bi-fsub{ opacity: 0; }

.bi-page .bi-form.bi-fjs.bi-fin h3{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.bi-page .bi-form.bi-fjs.bi-fin h3 + p{ animation: siRise .55s ease .14s both; }
.bi-page .bi-form.bi-fjs.bi-fin .bi-fld{ animation: siRise .55s cubic-bezier(.22,.61,.36,1) both; }
.bi-page .bi-form.bi-fjs.bi-fin .bi-fsub{ animation: diBtnIn .7s cubic-bezier(.22,.61,.36,1) both; }

/* the field hover/focus ring is already handled by the sitewide
   input/select/textarea rules; this only adds the lift on the button */
.bi-page .writereview #submit{ transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.bi-page .writereview #submit:hover{ transform: translateY(-3px); box-shadow: 0 12px 24px rgba(0,0,0,.18); }

/* --- D. comments: entrance, TWO across ---------------------------------- */
.bi-page .bi-cmt.bi-cjs h3{ opacity: 0; }
.bi-page .bi-cmt.bi-cjs h3 + p{ opacity: 0; }
.bi-page .bi-cmt.bi-cjs .wreviewpeople{ opacity: 0; }
.bi-page .bi-cmt.bi-cjs .wreviewpeople p.peoplereview,
.bi-page .bi-cmt.bi-cjs .wreviewpeople p.position-relative{ opacity: 0; }

.bi-page .bi-cmt.bi-cjs.bi-cin h3{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.bi-page .bi-cmt.bi-cjs.bi-cin h3 + p{ animation: siRise .55s ease .14s both; }
.bi-page .bi-cmt.bi-cjs.bi-cin .wreviewpeople{ animation: tsCardUp .7s cubic-bezier(.22,.61,.36,1) var(--bi-d, 0s) both; }
.bi-page .bi-cmt.bi-cjs.bi-cin .wreviewpeople p.peoplereview{ animation: tsTextUp .55s ease calc(var(--bi-d, 0s) + .18s) both; }
.bi-page .bi-cmt.bi-cjs.bi-cin .wreviewpeople p.position-relative{ animation: tsTextUp .55s ease calc(var(--bi-d, 0s) + .32s) both; }

/* --- D. hover: the same card lift the testimonials page gives it */
.bi-page .bi-cmt .wreviewpeople{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.bi-page .bi-cmt .wreviewpeople:hover{ transform: translateY(-5px); box-shadow: 0 16px 30px rgba(0,0,0,.10); }
.bi-page .bi-cmt input[name="load_more"]{ transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.bi-page .bi-cmt input[name="load_more"]:hover{ transform: translateY(-3px); box-shadow: 0 12px 24px rgba(0,0,0,.18); }

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .bi-page .bi-body img:hover{ filter: none; box-shadow: none; }
    .bi-page .bi-body a:hover > img{ transform: none; box-shadow: none; }
    .bi-page .bi-share span > a:hover{ transform: none; box-shadow: none; }
    .bi-page .bi-more .blog-img:hover img{ transform: none; filter: none; }
    .bi-page .bi-more .blog-img:hover::after{ animation: none; }
    .bi-page .writereview #submit:hover{ transform: none; box-shadow: none; }
    .bi-page .bi-cmt .wreviewpeople:hover{ transform: none; box-shadow: none; }
    .bi-page .bi-cmt input[name="load_more"]:hover{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion. The script bails before adding any
   driver class, so this is belt-and-braces — it also covers the OS setting
   being flipped after the page has loaded. */
@media (prefers-reduced-motion: reduce){
    .bi-page .bi-h,
    .bi-page .bi-r,
    .bi-page .bi-r > div > img,
    .bi-page .bi-share span > a,
    .bi-page .bi-more h2,
    .bi-page .bi-more .blog,
    .bi-page .bi-more .blog-img img,
    .bi-page .bi-more .blog p.overelipsis1,
    .bi-page .bi-more .blog p.overelipsis2,
    .bi-page .bi-more .blog .btn.btnthird,
    .bi-page .bi-form h3,
    .bi-page .bi-form h3 + p,
    .bi-page .bi-form .bi-fld,
    .bi-page .bi-form .bi-fsub,
    .bi-page .bi-cmt h3,
    .bi-page .bi-cmt h3 + p,
    .bi-page .bi-cmt .wreviewpeople,
    .bi-page .bi-cmt .wreviewpeople p.peoplereview,
    .bi-page .bi-cmt .wreviewpeople p.position-relative{
        opacity: 1 !important; clip-path: none !important; transform: none !important;
        animation: none !important; transition: none !important;
    }
    .bi-page .bi-body img{ transition: none !important; }
    .bi-page .bi-body img:hover{ filter: none !important; box-shadow: none !important; }
    .bi-page .bi-body a:hover > img{ transform: none !important; box-shadow: none !important; }
    .bi-page .bi-share span > a:hover{ transform: none !important; box-shadow: none !important; }
    .bi-page .bi-more .blog-img:hover img{ transform: none !important; filter: none !important; }
    .bi-page .bi-more .blog-img::after{ opacity: 0 !important; animation: none !important; }
    .bi-page .writereview #submit{ transition: none !important; }
    .bi-page .writereview #submit:hover{ transform: none !important; box-shadow: none !important; }
    .bi-page .bi-cmt .wreviewpeople:hover{ transform: none !important; box-shadow: none !important; }
    .bi-page .bi-cmt input[name="load_more"]{ transition: none !important; }
    .bi-page .bi-cmt input[name="load_more"]:hover{ transform: none !important; box-shadow: none !important; }
}


/* ==========================================================================
   News detail page — newsinfo.php  (.ni-page)
   ==========================================================================
   DELIBERATELY ALL-NEW. Every other page in this file was built by reusing the
   shared vocabulary (fade-rise, axis-aligned clip wipes, centre-out doors, iris,
   gleam sweeps, blur-focus, scale pops). This page uses none of it. Five
   techniques that appear NOWHERE else in this stylesheet:

     1. SPLIT TEXT — headings animated a word at a time. Every other text reveal
        on the site treats the element as one block.
     2. AN UNCOVERING CURTAIN — a solid panel slides off the photo. The existing
        gleams sweep a highlight OVER artwork; nothing else moves an object out
        of the way to expose what is behind it.
     3. COUNTER-PARALLAX — the photo drifts one way while the curtain leaves the
        other, two layers at two speeds inside one mask.
     4. CURSOR-TRACKING 3D TILT — thumbnails rotate to follow the pointer. The
        existing `--wc-*` magnetic hover translates and scales; nothing rotates
        in 3D from pointer position.
     5. SKEW AS A CONTENT ENTRANCE — skew currently exists only inside the gleam
        keyframes, never on content.

   Plus split-flap `rotateX` hinges (from a TOP edge for the dateline, a BOTTOM
   edge for the thumbnails and share chips), which is a different axis and origin
   from the existing evFlipIn / svIconIn flips.

   Two zones:
     A. ARTICLE (.col-md-8)
     B. "More On News" sidebar (.col-md-4.news)

   ON THE WORD SPLITTER: it wraps each word in `span.ni-w`, then puts the
   element's ORIGINAL innerHTML back once the run finishes, so the DOM ends up
   byte-identical to how it was served. It also refuses to touch any heading that
   contains element children, so admin-entered markup inside a title can never be
   flattened. `display: inline-block` on the words is what makes them
   transformable; the spaces between them stay real text nodes, so wrapping and
   line-breaking behave exactly as before.

   FOUR MARKUP FACTS THIS BLOCK RESPECTS:

   1. `.news .post:hover .newstitle` (line ~233) is GLOBALLY scoped — no page
      prefix — so that amber is ALREADY live on this page's sidebar. It is not
      re-added here; only a transition is added so it eases. Same situation as
      the department page's `.treatments` sidebar.

   2. baguetteBox is bound to `.gallery:not(.mr-20)` in layout/js.php, so this
      page's thumbnails are a live lightbox. It only binds click handlers and
      appends its overlay to <body>, so animating the thumbs is safe — but every
      rule below stays scoped under `.ni-body` / `.ni-side` so nothing can reach
      into that overlay.

   3. NOTHING IS SCALED WITHOUT A FRAME TO CLIP IT. The hero photo may be scaled
      freely, on hover and on entry, because `.post-img` is a plain full-bleed
      div that this block gives `overflow: hidden` — the picture fills it edge to
      edge, so the crop is exact. The gallery thumbs and the sidebar thumbs may
      NOT: their containers are padded Bootstrap columns, so a scaled picture
      grows into the 15px gutter and is still inside the column box when it gets
      there — `overflow: hidden` on the column would not clip it, it would just
      bleed over the gutter. `overflow` cannot go on the `a` instead: `a.item` is
      an inline box and overflow does not apply to those (nor, for that matter,
      does `transform` — which is why the tilt below sits on the img). Those
      thumbs therefore get rotation, grade and shadow, none of which need a crop.

   4. `<br>` elements are skipped by the driver (there is one after the CTA), so
      they cannot silently consume a slot in the reveal cascade.

   PRE-HIDE DISCIPLINE: this design sidesteps the trap rather than managing it.
   The hero photo has NO pre-hide at all — the curtain is what conceals it, so
   `niReveal` is free to animate transform only, and there is no opacity or clip
   to fall out of sync with. Everything that IS pre-hidden is pre-hidden on
   opacity alone, and every keyframe paired with it animates opacity.
   ========================================================================== */

/* ---------- the five new techniques ---------- */

/* 1. WORD-BY-WORD. The driver wraps each word of a heading in `span.ni-w`, then
      puts the original innerHTML back once the run finishes, so the DOM ends up
      byte-identical to before. Words rise while un-skewing and un-blurring, so
      the line assembles itself rather than appearing. */
@keyframes niWordUp{
    from{ opacity: 0; transform: translateY(.8em) skewY(7deg); filter: blur(6px); }
    60% { opacity: 1; }
    to  { opacity: 1; transform: translateY(0)    skewY(0deg); filter: blur(0); }
}
/* 2. CURTAIN. A panel sitting over the photo slides off, growing a slanted
      trailing edge as it goes, so the picture is UNCOVERED. Every other reveal
      on this site either fades, clips itself, or sweeps a highlight OVER the
      artwork; nothing else moves a solid object out of the way. */
@keyframes niCurtain{
    from{ transform: translateX(0)     skewX(0deg); }
    to  { transform: translateX(118%)  skewX(-14deg); }
}
/* 3. COUNTER-PARALLAX. While the curtain leaves to the right, the photo drifts
      left out of an oversize crop and settles — two layers moving in opposite
      directions inside one mask. No opacity here, and none is needed: the
      curtain is what hides it, so there is nothing to pre-hide and the
      pre-hide/keyframe trap cannot arise at all. */
@keyframes niReveal{
    from{ transform: scale(1.16) translateX(-3.5%); }
    to  { transform: scale(1)    translateX(0); }
}
/* 4. FLAP. The dateline drops in from its top edge like a split-flap board. */
@keyframes niFlapDown{
    from{ opacity: 0; transform: perspective(700px) rotateX(-88deg); }
    to  { opacity: 1; transform: perspective(700px) rotateX(0deg); }
}
/* 5. STAND-UP. Thumbnails hinge up off the page from their bottom edge. */
@keyframes niStandUp{
    from{ opacity: 0; transform: perspective(900px) rotateX(-72deg) translateY(18px); }
    to  { opacity: 1; transform: perspective(900px) rotateX(0deg)   translateY(0); }
}
/* skew as a CONTENT entrance — until now it only ever appeared inside the gleam
   sweeps. Gives the body copy a hint of motion blur as it arrives. */
@keyframes niSkewUp{
    from{ opacity: 0; transform: translateY(26px) skewY(2.5deg); }
    to  { opacity: 1; transform: translateY(0)    skewY(0deg); }
}
@keyframes niSlideSkew{
    from{ opacity: 0; transform: translateX(38px) skewX(-7deg); }
    to  { opacity: 1; transform: translateX(0)    skewX(0deg); }
}
@keyframes niChipIn{
    0%  { opacity: 0; transform: perspective(600px) rotateX(-90deg); }
    62% { opacity: 1; transform: perspective(600px) rotateX(14deg); }
    100%{ opacity: 1; transform: perspective(600px) rotateX(0deg); }
}

/* the two tilt angles are registered so they can be TRANSITIONED. Without
   @property a custom property is an unanimatable token, so the tilt would snap;
   with it, the tracking is damped and the release eases back. Unsupported
   browsers still get the tilt, just un-smoothed — the same graceful fallback the
   `--wc-*` magnetic hover above relies on. */
@property --ni-rx{ syntax: '<angle>'; initial-value: 0deg; inherits: false; }
@property --ni-ry{ syntax: '<angle>'; initial-value: 0deg; inherits: false; }

/* --- A. ARTICLE --------------------------------------------------------- */
.ni-page .ni-h,
.ni-page .ni-r{ opacity: 0; }

/* the split headings are NOT pre-hidden: their words are driven individually and
   each word's `both` fill holds it back until its turn, so the heading needs no
   opacity of its own. Keeping it out of the pre-hide is also what stops an
   un-split heading (one containing markup, which the driver skips) from being
   left invisible with nothing to reveal it. */
.ni-page .ni-w{ display: inline-block; }
.ni-page .ni-in .ni-split .ni-w,
.ni-page .ni-sin .ni-split .ni-w,
.ni-page .ni-seen.ni-split .ni-w{
    animation: niWordUp .75s cubic-bezier(.22,.61,.36,1) var(--ni-wd, 0s) both;
}

.ni-page .ni-body.ni-in .ni-h{ animation: niFlapDown .7s cubic-bezier(.22,.61,.36,1) both; }
.ni-page .ni-r.ni-seen{ animation: niSkewUp .65s cubic-bezier(.22,.61,.36,1) both; }

/* --- A. the hero: curtain off, photo counter-drifts in behind it --------- */
.ni-page .ni-body .post-img{ position: relative; overflow: hidden; }
.ni-page .ni-body .post-img::after{
    content: '';
    position: absolute; inset: 0; z-index: 2;
    background: #F7B32B;
    pointer-events: none;
    transform: translateX(118%);      /* parked off-frame at rest */
}
.ni-page .ni-body.ni-in .ni-hero::after{ animation: niCurtain .85s cubic-bezier(.65,0,.35,1) .12s both; }
.ni-page .ni-body.ni-in .ni-hero img{ animation: niReveal 1.25s cubic-bezier(.22,.61,.36,1) .12s both; }

/* hover: the photo breathes inside its own crop. Safe to scale now — the frame
   above is what clips it. */
.ni-page .ni-body .post-img img{ transition: transform .8s cubic-bezier(.22,.61,.36,1), filter .6s ease; }
.ni-page .ni-body .post-img:hover img{ transform: scale(1.04); filter: brightness(1.03) contrast(1.02); }

/* --- A. gallery: thumbnails hinge up, then follow the cursor in 3D ------- */
.ni-page .ni-body .gallery.ni-r .col-sm-4{ opacity: 0; }
.ni-page .ni-body .gallery.ni-r.ni-seen .col-sm-4{
    transform-origin: 50% 100%;
    animation: niStandUp .8s cubic-bezier(.22,.61,.36,1) var(--ni-g, .15s) both;
}
.ni-page .ni-body .gallery .col-sm-4:nth-child(1){ --ni-g: .15s; }
.ni-page .ni-body .gallery .col-sm-4:nth-child(2){ --ni-g: .24s; }
.ni-page .ni-body .gallery .col-sm-4:nth-child(3){ --ni-g: .33s; }
.ni-page .ni-body .gallery .col-sm-4:nth-child(4){ --ni-g: .42s; }
.ni-page .ni-body .gallery .col-sm-4:nth-child(5){ --ni-g: .51s; }
.ni-page .ni-body .gallery .col-sm-4:nth-child(6){ --ni-g: .60s; }
.ni-page .ni-body .gallery .col-sm-4:nth-child(7){ --ni-g: .69s; }
.ni-page .ni-body .gallery .col-sm-4:nth-child(n+8){ --ni-g: .78s; }

.ni-page .ni-body .gallery a.item{ cursor: pointer; }
/* the tilt lives on the IMG, not the anchor: `a.item` is an inline element and
   transforms do not apply to non-replaced inline boxes, so putting it on the
   anchor would silently do nothing unless its `display` were changed — and that
   would be a layout change. */
.ni-page .ni-tilt{
    transform: perspective(700px) rotateX(var(--ni-rx, 0deg)) rotateY(var(--ni-ry, 0deg));
    transition: --ni-rx .18s ease-out, --ni-ry .18s ease-out,
                box-shadow .3s ease, filter .3s ease;
}
.ni-page .ni-body .gallery a.item:hover img{
    box-shadow: 0 18px 34px rgba(0,0,0,.22);
    filter: brightness(1.04);
}

/* --- A. a linked image (the CTA banner) lifts, since it is actually clickable */
.ni-page .ni-body > a > img{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.ni-page .ni-body > a:hover > img{ transform: translateY(-5px); box-shadow: 0 16px 32px rgba(0,0,0,.16); }

/* --- A. the Share row: the chips flap up, then tip toward you on hover. Their
       brand background colours are untouched. */
.ni-page .ni-share.ni-r span > a{ opacity: 0; }
.ni-page .ni-share.ni-r.ni-seen span > a{ animation: niChipIn .6s cubic-bezier(.22,.61,.36,1) var(--ni-s, .2s) both; }
.ni-page .ni-share span > a:nth-child(1){ --ni-s: .22s; }
.ni-page .ni-share span > a:nth-child(2){ --ni-s: .32s; }
.ni-page .ni-share span > a:nth-child(3){ --ni-s: .42s; }
.ni-page .ni-share span > a:nth-child(4){ --ni-s: .52s; }
.ni-page .ni-share span > a{
    display: inline-block;
    transform-origin: 50% 100%;
    transition: transform .35s cubic-bezier(.34,1.56,.64,1), box-shadow .35s ease;
}
.ni-page .ni-share span > a:hover{
    transform: perspective(600px) rotateX(-16deg) translateY(-5px);
    box-shadow: 0 12px 22px rgba(0,0,0,.26);
}

/* --- B. "More On News" sidebar ------------------------------------------ */
.ni-page .ni-side.ni-sjs .post{ opacity: 0; }
.ni-page .ni-side.ni-sjs.ni-sin .post{
    animation: niSlideSkew .75s cubic-bezier(.22,.61,.36,1) var(--ni-d, 0s) both;
}
/* The thumbnail deliberately arrives WITH its row rather than counter-drifting
   like the hero does. niReveal scales to 1.16, and per note 3 there is no frame
   here that can crop that — the picture would swell into the gutter. The row's
   own 3D page-turn on hover is this sidebar's gesture instead. */

/* --- B. hover: the row turns a few degrees toward the reader, hinged on its
       left edge. The amber on `.newstitle` is the theme's own global rule — only
       the transition is added here. */
.ni-page .ni-side .post{
    transform-origin: left center;
    transition: transform .45s cubic-bezier(.22,.61,.36,1);
}
.ni-page .ni-side .post:hover{ transform: perspective(900px) rotateY(-5deg) translateX(4px); }
.ni-page .ni-side .post .newstitle{ transition: color .3s ease; }
/* grade and shadow only, no scale — see note 3. `overflow: hidden` on the column
   is pointless here (the picture bleeds into the padding long before it reaches
   the column edge) so it is not set. */
.ni-page .ni-side .post .col-md-6 > a > img{ transition: filter .4s ease, box-shadow .4s ease; }
.ni-page .ni-side .post:hover .col-md-6 > a > img{
    filter: brightness(1.05) contrast(1.02);
    box-shadow: 0 8px 18px rgba(0,0,0,.16);
}
.ni-page .ni-side .post a.text-app2{ display: inline-block; transition: transform .3s cubic-bezier(.22,.61,.36,1); }
.ni-page .ni-side .post:hover a.text-app2{ transform: translateX(4px); }

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .ni-page .ni-body .post-img:hover img{ transform: none; filter: none; }
    .ni-page .ni-body .gallery a.item:hover img{ box-shadow: none; filter: none; }
    .ni-page .ni-body > a:hover > img{ transform: none; box-shadow: none; }
    .ni-page .ni-share span > a:hover{ transform: none; box-shadow: none; }
    .ni-page .ni-side .post:hover{ transform: none; }
    .ni-page .ni-side .post:hover .col-md-6 > a > img{ transform: none; filter: none; }
    .ni-page .ni-side .post:hover a.text-app2{ transform: none; }
}

/* respect users who prefer reduced motion. The driver bails before it splits any
   heading or binds any tilt, so this is belt-and-braces — it also covers the OS
   setting being flipped after the page has loaded. */
@media (prefers-reduced-motion: reduce){
    .ni-page .ni-h,
    .ni-page .ni-r,
    .ni-page .ni-w,
    .ni-page .ni-body .post-img img,
    .ni-page .ni-body .gallery .col-sm-4,
    .ni-page .ni-share span > a,
    .ni-page .ni-side h3,
    .ni-page .ni-side .post,
    .ni-page .ni-side .post .col-md-6 > a > img,
    .ni-page .ni-side .post span.fs-12,
    .ni-page .ni-side .post p.newstitle,
    .ni-page .ni-side .post p.mb-0{
        opacity: 1 !important; clip-path: none !important; transform: none !important;
        filter: none !important; animation: none !important; transition: none !important;
    }
    /* the curtain must be parked OFF-frame, not merely un-animated: leaving it
       at its resting transform is correct, but killing the animation without
       this would be fine too — it is stated explicitly so a future edit to the
       base rule cannot accidentally leave a solid panel over the photo. */
    .ni-page .ni-body .post-img::after{ transform: translateX(118%) !important; animation: none !important; }
    .ni-page .ni-body .post-img:hover img{ transform: none !important; filter: none !important; }
    .ni-page .ni-tilt{ transform: none !important; transition: none !important; }
    .ni-page .ni-body .gallery a.item:hover img{ box-shadow: none !important; filter: none !important; }
    .ni-page .ni-body > a > img{ transition: none !important; }
    .ni-page .ni-body > a:hover > img{ transform: none !important; box-shadow: none !important; }
    .ni-page .ni-share span > a:hover{ transform: none !important; box-shadow: none !important; }
    .ni-page .ni-side .post:hover{ transform: none !important; }
    .ni-page .ni-side .post .newstitle{ transition: none !important; }
    .ni-page .ni-side .post:hover .col-md-6 > a > img{ transform: none !important; filter: none !important; }
    .ni-page .ni-side .post a.text-app2{ transition: none !important; }
    .ni-page .ni-side .post:hover a.text-app2{ transform: none !important; }
}

/* --- "More On News" stays with the reader ------------------------------
   The markup wrapper alone was not enough. The controller hands this column
   up to TEN items (Home.php, the recentnews query), so the block is taller
   than the viewport and usually about as tall as the article beside it — and
   a sticky element that tall has nowhere to travel, which is why it read as
   "not working" rather than as a broken rule.

   So the height is capped to the viewport and the block scrolls inside
   itself. `overflow-y` is on the STICKY ELEMENT, never on an ancestor: a
   clipping ANCESTOR is what silently turns a sticky element back into a
   static one, which is also why the column and section are pinned to
   `overflow: visible` here.

   The column must keep `align-self: stretch` (the flex default). It is the
   full-height column that gives the sticky child its travel — shrink it to
   its content and the effect dies, so it is stated rather than assumed. That
   also keeps the `border-left` running the full height of the row.

   `!important` throughout as requested, and it costs nothing: no other rule
   in this stylesheet targets these boxes. */
.news-information,
.news-information > .container,
.news-information > .container-fluid,
.news-information .row{ overflow: visible !important; }
.news-information .col-md-4.news{
    align-self: stretch !important;
    overflow: visible !important;
}
.news-information .col-md-4.news > .sticky-top{
    position: -webkit-sticky !important;
    position: sticky !important;
    top: 120px !important;
    z-index: 9 !important;
    /* 120px offset + a little breathing room at the bottom */
    max-height: calc(100vh - 140px) !important;
    overflow-y: auto !important;

    /* Clipping starts at the PADDING EDGE, and the `.post` rows are Bootstrap
       `.row`s — 15px wider than this wrapper on each side via their negative
       margins. Left as-is, `overflow-y` would shave the right-hand text column
       (it carries `pr-0`, so its copy runs right out to the row's edge). So the
       box is widened by the same amount and the padding puts every child back
       on the exact x it was on before: net layout unchanged, nothing cut.
       The extra 5px on the right is a gutter for the thin scrollbar, so the bar
       sits clear of the text rather than over it. */
    margin: 0 -20px 0 -15px !important;
    padding: 0 20px 0 15px !important;

    /* a thin, unobtrusive scrollbar — the list is the content, not the bar */
    scrollbar-width: thin;
}
.news-information .col-md-4.news > .sticky-top::-webkit-scrollbar{ width: 4px; }
.news-information .col-md-4.news > .sticky-top::-webkit-scrollbar-thumb{ border-radius: 4px; }

/* Below md every column is full width and stacked, so the sidebar follows the
   article instead of sitting beside it. Sticking it there would pin a tall
   block over the content the reader scrolled to, so it is released. */
@media (max-width: 767.98px){
    .news-information .col-md-4.news > .sticky-top{
        position: static !important;
        max-height: none !important;
        overflow: visible !important;
        margin: 0 !important;
        padding: 0 !important;
    }
}


/* ==========================================================================
   Treatment detail page — treatmentsinfo.php  (.tri-page)
   ==========================================================================
   ANOTHER all-new set, sharing nothing with the news detail page's five and
   nothing with the shared vocabulary the rest of the site uses. The idea is
   clinical — SCAN, FOCUS, DEAL — which suits a treatments page:

     1. MASK-GRADIENT DEVELOP — the hero photo is revealed by a soft-edged
        gradient sweeping down it, like a scan resolving. `mask-image` appears
        NOWHERE else in this stylesheet. It also needs no wrapper, which matters
        here: the hero is a bare <img> and replaced elements cannot have
        ::before/::after, so a pseudo-element scan line was not an option.
     2. DIAGONAL POLYGON WIPE — every heading and card photo is uncovered by a
        SLANTED edge. `clip-path: polygon()` exists in this file only as the
        static meteor-tail wedge; nothing animates one, and every animated clip
        elsewhere is an axis-aligned inset or a circle.
     3. Z-AXIS ARRIVAL — body copy comes toward the reader out of depth
        (`translateZ`), not up from below. A different axis from every existing
        entrance, including the news page's rotateX hinges.
     4. DEAL-FROM-A-DECK — the doctor cards are dealt in, each sliding from a
        shared offset with its rotation unwinding.
     5. CURSOR-TRACKED SPOTLIGHT — a soft highlight follows the pointer across a
        doctor card. Distinct from the news page's 3D tilt (which rotates the
        element) and from the `--wc-*` magnetic hover (which moves it): this
        moves LIGHT across a stationary card.
     6. SLOW KEN BURNS — the sidebar portraits drift and swell over 3.5s while
        hovered, rather than snapping to a zoom in 0.5s.

   Those five apply to the ARTICLE and the DOCTOR SIDEBAR only. The "More
   treatments" grid is explicitly NOT part of the set: it is the same card grid
   as the home page's treatments section, so it reuses that section's block
   verbatim rather than being given a second personality. See zone C below.

   MARKUP FACTS THIS BLOCK RESPECTS:

   1. `section.mt-5.treatments` carries `.treatments`, so the theme's own
      `.treatments .treatments-card:hover h3.treattitle` amber is ALREADY live
      there. The driver also adds `primary_section`, which brings in the rest of
      the home treatments polish — including its reduced-motion guards, which is
      why zone C needs no guarding of its own further down.

   2. `.card-img` has no containment on this page for the SIDEBAR (nothing
      reaches it), so this block adds `overflow: hidden` there before asking
      anything to scale inside it — that is what makes the Ken Burns drift safe.
      The "More treatments" `.card-img` gets its containment from the home block
      instead, via the `primary_section` the driver adds.

   3. Bootstrap's `.card` is already `position: relative`; the spotlight overlay
      takes `border-radius: inherit` so it cannot square off the card's rounded
      corners.

   4. PRE-EXISTING, NOT FIXED: the `div.blogpage.container` opened on line ~25 is
      never closed — count the `</div>`s and the "More treatments" <section> ends
      up INSIDE it, so `.blogpage img{width:100%;margin:20px 0;border:...}` is
      currently painting borders and margins onto those card photos. That is how
      the page renders today; correcting it is a structural change. Nothing below
      depends on that nesting either way — every zone is found through a marker
      the driver adds.

   PRE-HIDE DISCIPLINE: the hero photo has NO opacity pre-hide, because the mask
   conceals it and the mask's own starting position comes from the keyframe's
   backwards fill. If `mask-image` is unsupported the base rule is simply
   ignored, the animation moves nothing, and the picture is visible from the
   start — the failure mode is "no effect", never "invisible".
   ========================================================================== */

/* 1. the scan.

      The mask is THREE times the element's height, not two, and that matters.
      `mask-position` works like `background-position`, so the element only ever
      looks at a window one element-height tall: at `0% 0%` that window is the
      mask's top third, at `0% 100%` it is the bottom third. Sized at 200% the two
      windows are each half the mask and butt together in the middle, so the soft
      ramp is unavoidably inside one of them and the photo starts partly visible.
      At 300% there is a spare middle third to park the ramp in, so both end
      states are clean: top third fully opaque (shown), bottom third fully
      transparent (hidden), ramp only ever crossing the window in between.

      Animating 100% -> 0% slides the window up the mask, which brings the opaque
      region in from the top — so the edge sweeps DOWN the picture.

      Both the prefixed and unprefixed properties are animated: Safari only took
      `mask-*` unprefixed in 15.4, and `-webkit-mask-*` still has wider reach. */
@keyframes triDevelop{
    from{ -webkit-mask-position: 0% 100%; mask-position: 0% 100%; }
    to  { -webkit-mask-position: 0% 0%;   mask-position: 0% 0%; }
}
/* 2. the slanted edge. Both states are 4-point parallelograms so they
      interpolate; the leading pair simply starts collapsed onto the trailing
      pair, which is what gives it zero area. All bounds overshoot 100% at the
      end, so nothing can clip a descender at rest. */
@keyframes triDiagWipe{
    from{ opacity: 0; clip-path: polygon(-30% -20%, -30% -20%, -65% 120%, -65% 120%); }
    to  { opacity: 1; clip-path: polygon(-30% -20%, 145% -20%, 110% 120%, -65% 120%); }
}
/* 3. out of depth. translateZ is NEGATIVE at the start, so the block arrives
      smaller than its final size and can never overflow on the way in. */
@keyframes triDepthIn{
    from{ opacity: 0; transform: perspective(900px) translateZ(-170px) translateY(12px); }
    to  { opacity: 1; transform: perspective(900px) translateZ(0)      translateY(0); }
}
/* 4. dealt from a deck: off the top-right, rotation unwinding as it lands */
@keyframes triDeal{
    from{ opacity: 0; transform: translate(40px, -28px) rotate(7deg) scale(.94); }
    to  { opacity: 1; transform: translate(0, 0)        rotate(0deg) scale(1); }
}
/* (a squash-and-stretch keyframe lived here for the "More treatments" grid; it
   was removed when that grid was switched to reuse the home page's letterbox
   block instead, so nothing is left defined-but-unused.) */

/* the spotlight's position is registered so it can be TRANSITIONED — an
   unregistered custom property is an unanimatable token and the highlight would
   jump between pointer samples. Unsupported browsers still get the spotlight,
   just undamped. */
@property --tri-mx{ syntax: '<percentage>'; initial-value: 50%; inherits: true; }
@property --tri-my{ syntax: '<percentage>'; initial-value: 50%; inherits: true; }

/* --- A. ARTICLE --------------------------------------------------------- */
.tri-page .tri-h,
.tri-page .tri-r{ opacity: 0; }

.tri-page .tri-body.tri-in .tri-h{ animation: triDepthIn .75s cubic-bezier(.22,.61,.36,1) both; }
.tri-page .tri-body.tri-in h1.tri-h{ animation: triDiagWipe .85s cubic-bezier(.65,0,.35,1) both; }
.tri-page .tri-r.tri-seen{ animation: triDepthIn .7s cubic-bezier(.22,.61,.36,1) both; }
/* the second photo and the CTA banner are wiped rather than pushed out of depth,
   so the diagonal reads as this page's motif at every scale */
.tri-page img.tri-r.tri-seen,
.tri-page .tri-r.tri-seen > img{ animation: triDiagWipe .8s cubic-bezier(.65,0,.35,1) both; }

/* --- A. the hero: the scan. Mask lives only while the reveal is driving, so
       nothing is left permanently composited; it ends fully opaque and the
       unmasked state is identical, so dropping it cannot flash. */
.tri-page .tri-body.tri-in .tri-hero{
    /* opaque 0-40%, ramp 40-55%, transparent 55-100% — the ramp sits in the
       middle third, clear of both end windows. See the note above. */
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 40%, rgba(0,0,0,0) 55%, rgba(0,0,0,0) 100%);
            mask-image: linear-gradient(to bottom, #000 0%, #000 40%, rgba(0,0,0,0) 55%, rgba(0,0,0,0) 100%);
    -webkit-mask-size: 100% 300%;
            mask-size: 100% 300%;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    animation: triDevelop 1.15s cubic-bezier(.4,0,.25,1) .1s both;
}

/* --- A. hover on the article photos. They are `w-100` with nothing to crop
       them, so a grade and a shadow only — no scale. */
.tri-page .tri-body img.docimg{ transition: filter .5s ease, box-shadow .5s ease; }
.tri-page .tri-body img.docimg:hover{
    filter: brightness(1.04) contrast(1.02) saturate(1.03);
    box-shadow: 0 14px 34px rgba(0,0,0,.14);
}
.tri-page .tri-body a > img{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.tri-page .tri-body a:hover > img{ transform: translateY(-5px); box-shadow: 0 16px 32px rgba(0,0,0,.16); }

/* --- B. doctor sidebar: dealt in ---------------------------------------- */
.tri-page .tri-side.tri-sjs h2{ opacity: 0; }
.tri-page .tri-side.tri-sjs .card{ opacity: 0; }

.tri-page .tri-side.tri-sjs.tri-sin h2{ animation: triDiagWipe .8s cubic-bezier(.65,0,.35,1) both; }
.tri-page .tri-side.tri-sjs.tri-sin .card{
    animation: triDeal .7s cubic-bezier(.22,.61,.36,1) var(--tri-d, 0s) both;
}

/* --- B. the spotlight. White at low alpha — light laid over the card's own
       colours, never a new hue. `border-radius: inherit` so it cannot square off
       the card corners, and `pointer-events: none` so it cannot eat the click. */
.tri-page .tri-side .card{
    position: relative;              /* Bootstrap already sets this; explicit for safety */
    transition: --tri-mx .12s linear, --tri-my .12s linear,
                transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease;
}
.tri-page .tri-side .card:hover{ transform: translateY(-5px); box-shadow: 0 16px 30px rgba(0,0,0,.16); }
.tri-page .tri-side .card::after{
    content: '';
    position: absolute; inset: 0; z-index: 3;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0;
    transition: opacity .35s ease;
    background: radial-gradient(170px circle at var(--tri-mx, 50%) var(--tri-my, 50%),
                rgba(255,255,255,.32), rgba(255,255,255,0) 70%);
}
.tri-page .tri-side .card:hover::after{ opacity: 1; }
.tri-page .tri-side .card-img{ position: relative; overflow: hidden; }
.tri-page .tri-side .card-img img{ transition: transform 3.5s cubic-bezier(.25,.1,.25,1); }
.tri-page .tri-side .card:hover .card-img img{ transform: scale(1.08) translate(-1.5%, -1.5%); }

/* --- C. "More treatments" -------------------------------------------------
       Deliberately EMPTY. This section is the same card grid as the home page's
       treatments section, so rather than give it a second personality it reuses
       that section's block verbatim: the driver adds `primary_section` alongside
       the `.treatments` the markup already carries, which is the exact pair the
       home rules at the top of this file are scoped to, and then drives the same
       `tr-js` / `tr-in` / `--tr-d` / `.tr-head` / `tr-idle` contract.

       So "More treatments" gets the LETTERBOX entrance (each picture opening out
       of a thin horizontal band), the same card stagger, the same picture-only
       hover with its gleam and amber bottom edge, and the same idle heartbeat —
       identical to the home page, from one definition, with nothing duplicated
       here to drift out of step later.

       `.primary_section` is safe to add: it never appears as a standalone rule
       in either stylesheet, only ever compounded (`.primary_section.treatments`,
       `.primary_section.faqsection`), so it carries no styling of its own and
       adding it can activate nothing except the treatments polish intended. */

/* --- touch / small screens: drop the hovers, keep the entrances.
       The "More treatments" grid is not listed — the home block's own touch
       guard at the top of this file already covers it, for the same reason. */
@media (max-width: 767px), (hover: none){
    .tri-page .tri-body img.docimg:hover{ filter: none; box-shadow: none; }
    .tri-page .tri-body a:hover > img{ transform: none; box-shadow: none; }
    .tri-page .tri-side .card:hover{ transform: none; box-shadow: none; }
    .tri-page .tri-side .card:hover::after{ opacity: 0; }
    .tri-page .tri-side .card:hover .card-img img{ transform: none; }
}

/* respect users who prefer reduced motion. The driver bails before adding any
   driver class or binding the spotlight, so this is belt-and-braces — and note 1
   explains why the mask and the ::after still need naming explicitly. */
@media (prefers-reduced-motion: reduce){
    .tri-page .tri-h,
    .tri-page .tri-r,
    .tri-page .tri-side h2,
    .tri-page .tri-side .card,
    .tri-page .tri-hero{
        -webkit-mask-image: none !important; mask-image: none !important;
        animation: none !important;
    }
    .tri-page .tri-body img.docimg{ transition: none !important; }
    .tri-page .tri-body img.docimg:hover{ filter: none !important; box-shadow: none !important; }
    .tri-page .tri-body a > img{ transition: none !important; }
    .tri-page .tri-body a:hover > img{ transform: none !important; box-shadow: none !important; }
    .tri-page .tri-side .card::after{ opacity: 0 !important; transition: none !important; }
    .tri-page .tri-side .card:hover{ transform: none !important; box-shadow: none !important; }
    .tri-page .tri-side .card-img img{ transition: none !important; }
    .tri-page .tri-side .card:hover .card-img img{ transform: none !important; }
    /* "More treatments" is not listed: the home block's `.treatments`-scoped
       reduce rules already neutralise those cards, and its
       `.primary_section.treatments` pseudo-element rules now reach them too,
       because the driver adds `primary_section`. That is the same reuse that
       makes the entrance and hover identical — it covers reduced motion for
       free, where the department page had to guard the pseudo-elements itself. */
}


/* ==========================================================================
   Photo album + video detail — galleryinfo.php (.gi-page), videoinfo.php (.vi-page)
   ==========================================================================
   These two are treated as ONE family on purpose: they are the detail pages of
   the photo and video galleries, so they share a photographic vocabulary — a
   SHUTTER for the titles and a CROP SETTLE for the pictures — while each keeps
   what only it needs.

   THE NEW IDEA: `object-position`. It appears nowhere else in this stylesheet,
   and it is the right tool for exactly this markup. Both pages' pictures are
   `object-fit: cover` in a fixed-height box, which means the image is already
   cropped and there is slack outside the visible window. Animating
   `object-position` PANS that crop inside the box without the element ever
   changing size — so it needs no clipping ancestor and cannot overflow.

   That matters because the usual trick is unavailable here: on the album page
   `a.item` is an inline anchor (transforms do not apply to non-replaced inline
   boxes) and `.col-md-4` is a padded Bootstrap column, so a hover zoom could
   only be contained by changing `display` or letting the picture bleed into the
   gutter. Panning the crop sidesteps all of it — and for a photo gallery it is
   also the better interaction: you move the pointer and explore the photograph
   behind a fixed frame, rather than the frame growing at you.

   VIDEO-PLAYER SAFETY (videoinfo): the player is a <video> or a YouTube/Instagram
   <iframe>. It gets opacity and translateY ONLY — no clip-path, no filter, no
   mask, all of which are unreliable on replaced/embedded content and would blur
   or clip a playing video. It gets NO hover state at all, so nothing competes
   with its own controls.

   PRE-HIDE DISCIPLINE: every pre-hide below sets opacity, and every keyframe
   paired with one animates opacity.
   ========================================================================== */

/* the title opens from its centre line, like a shutter */
@keyframes giShutter{
    from{ opacity: 0; clip-path: inset(50% 0 50% 0); }
    to  { opacity: 1; clip-path: inset(-.25em 0 -.25em 0); }
}
/* the picture arrives and its CROP settles: the framing slides down into place
   while the frame itself never moves. See the note above on object-position. */
@keyframes giFrameIn{
    from{ opacity: 0; transform: translateY(22px); object-position: 50% 24%; }
    to  { opacity: 1; transform: translateY(0);    object-position: 50% 50%; }
}
/* the play control, with an AMBER ring rather than the white one vgPlayIn uses —
   that keyframe is for play buttons sitting on dark artwork; this one sits on the
   white sidebar, where white rings would be invisible. #F7B32B is the icon's own
   colour and `.text-app2`'s, so no new hue is introduced. */
@keyframes viPlayPop{
    0%  { opacity: 0; transform: scale(.3);   box-shadow: 0 0 0 0    rgba(247,179,43,.50); }
    60% { opacity: 1; transform: scale(1.18); box-shadow: 0 0 0 12px rgba(247,179,43,.16); }
    100%{ opacity: 1; transform: scale(1);    box-shadow: 0 0 0 22px rgba(247,179,43,0); }
}

/* ---------- galleryinfo: the album grid ---------- */
.gi-page .gi-grid.gi-js h1{ opacity: 0; }
.gi-page .gi-grid.gi-js .col-md-4 img{ opacity: 0; }

.gi-page .gi-grid.gi-js.gi-in h1{ animation: giShutter .85s cubic-bezier(.65,0,.35,1) .05s both; }
.gi-page .gi-grid.gi-js.gi-in .col-md-4 img{
    animation: giFrameIn .85s cubic-bezier(.22,.61,.36,1) var(--gi-d, 0s) both;
}

/* hover: the crop PANS toward the pointer, driven by the script. No scale, so
   nothing has to clip it — see the header note. The transition is what damps the
   pan between pointer samples and eases it back to centre on leave. */
.gi-page .gi-grid a.item{ cursor: pointer; }
.gi-page .gi-grid a.item img{
    object-position: 50% 50%;
    transition: object-position .25s ease-out, box-shadow .35s ease, filter .35s ease;
}
.gi-page .gi-grid a.item:hover img{
    box-shadow: 0 18px 36px rgba(0,0,0,.22);
    filter: brightness(1.04) contrast(1.02);
}

/* ---------- videoinfo ---------- */
.vi-page .vi-h,
.vi-page .vi-r{ opacity: 0; }

.vi-page .vi-body.vi-in .vi-h{ animation: siRise .65s cubic-bezier(.22,.61,.36,1) both; }
.vi-page .vi-body.vi-in h1.vi-h{ animation: giShutter .85s cubic-bezier(.65,0,.35,1) both; }
/* the player: opacity + translateY only. See VIDEO-PLAYER SAFETY above. */
.vi-page .vi-body.vi-in .vi-player{ animation: siRise .8s cubic-bezier(.22,.61,.36,1) both; }
.vi-page .vi-r.vi-seen{ animation: siRise .6s cubic-bezier(.22,.61,.36,1) both; }

/* --- comments. Same `.wreviewpeople` card as the testimonials and blog pages,
       so it reuses their motion and their hover rather than inventing a third. */
.vi-page .vi-cmt.vi-cjs .wreviewpeople{ opacity: 0; }
.vi-page .vi-cmt.vi-cjs .wreviewpeople p.peoplereview,
.vi-page .vi-cmt.vi-cjs .wreviewpeople p.position-relative{ opacity: 0; }

.vi-page .vi-cmt.vi-cjs.vi-cin .wreviewpeople{ animation: tsCardUp .7s cubic-bezier(.22,.61,.36,1) var(--vi-d, 0s) both; }
.vi-page .vi-cmt.vi-cjs.vi-cin .wreviewpeople p.peoplereview{ animation: tsTextUp .55s ease calc(var(--vi-d, 0s) + .18s) both; }
.vi-page .vi-cmt.vi-cjs.vi-cin .wreviewpeople p.position-relative{ animation: tsTextUp .55s ease calc(var(--vi-d, 0s) + .32s) both; }

.vi-page .vi-cmt .wreviewpeople{ transition: transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease; }
.vi-page .vi-cmt .wreviewpeople:hover{ transform: translateY(-5px); box-shadow: 0 16px 30px rgba(0,0,0,.10); }

/* --- the comment form, matching the blog page's treatment of the same markup */
.vi-page .vi-form.vi-fjs h4{ opacity: 0; }
.vi-page .vi-form.vi-fjs h4 + p{ opacity: 0; }
.vi-page .vi-form.vi-fjs .vi-fld,
.vi-page .vi-form.vi-fjs .vi-fsub{ opacity: 0; }

.vi-page .vi-form.vi-fjs.vi-fin h4{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }
.vi-page .vi-form.vi-fjs.vi-fin h4 + p{ animation: siRise .55s ease .14s both; }
.vi-page .vi-form.vi-fjs.vi-fin .vi-fld{ animation: siRise .55s cubic-bezier(.22,.61,.36,1) both; }
.vi-page .vi-form.vi-fjs.vi-fin .vi-fsub{ animation: diBtnIn .7s cubic-bezier(.22,.61,.36,1) both; }

/* the field focus ring is already handled by the sitewide input/textarea rules */
.vi-page #submit,
.vi-page input[name="load_more"],
.vi-page .btn.btnprimary{ transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease; }
.vi-page #submit:hover,
.vi-page input[name="load_more"]:hover,
.vi-page .btn.btnprimary:hover{ transform: translateY(-3px); box-shadow: 0 12px 24px rgba(0,0,0,.18); }

/* --- "More from Video Gallery": the rows arrive and each thumbnail's crop
       settles, the same gesture the album grid uses — these are sibling pages
       and the shared motif is deliberate. */
.vi-page .vi-side.vi-sjs h2{ opacity: 0; }
.vi-page .vi-side.vi-sjs .row{ opacity: 0; }
.vi-page .vi-side.vi-sjs .row img.obj-cover{ opacity: 0; }
.vi-page .vi-side.vi-sjs .row .playbtnimgvideo{ opacity: 0; }

.vi-page .vi-side.vi-sjs.vi-sin h2{ animation: giShutter .8s cubic-bezier(.65,0,.35,1) both; }
.vi-page .vi-side.vi-sjs.vi-sin .row{ animation: siRise .65s cubic-bezier(.22,.61,.36,1) var(--vi-d, 0s) both; }
.vi-page .vi-side.vi-sjs.vi-sin .row img.obj-cover{
    animation: giFrameIn .8s cubic-bezier(.22,.61,.36,1) calc(var(--vi-d, 0s) + .08s) both;
}
.vi-page .vi-side.vi-sjs.vi-sin .row .playbtnimgvideo{
    animation: viPlayPop .7s cubic-bezier(.34,1.56,.64,1) calc(var(--vi-d, 0s) + .3s) both;
}

/* --- sidebar hover: the thumbnail's crop pans and brightens, the play control
       swells inside an amber ring, and "Start Watching" nudges across. */
.vi-page .vi-side .row img.obj-cover{
    object-position: 50% 50%;
    transition: object-position .5s ease-out, filter .4s ease, box-shadow .4s ease;
}
.vi-page .vi-side .row:hover img.obj-cover{
    object-position: 50% 38%;
    filter: brightness(1.05) contrast(1.02);
    box-shadow: 0 10px 22px rgba(0,0,0,.16);
}
.vi-page .vi-side .playbtnimgvideo{
    border-radius: 50%;
    transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease;
}
.vi-page .vi-side .row:hover .playbtnimgvideo{
    transform: scale(1.18);
    box-shadow: 0 0 0 8px rgba(247,179,43,.20);
}
.vi-page .vi-side .row .text-app2{ display: inline-block; transition: transform .35s cubic-bezier(.22,.61,.36,1); }
.vi-page .vi-side .row:hover .text-app2{ transform: translateX(4px); }

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .gi-page .gi-grid a.item:hover img{ box-shadow: none; filter: none; }
    .vi-page .vi-cmt .wreviewpeople:hover{ transform: none; box-shadow: none; }
    .vi-page #submit:hover,
    .vi-page input[name="load_more"]:hover,
    .vi-page .btn.btnprimary:hover{ transform: none; box-shadow: none; }
    .vi-page .vi-side .row:hover img.obj-cover{ object-position: 50% 50%; filter: none; box-shadow: none; }
    .vi-page .vi-side .row:hover .playbtnimgvideo{ transform: none; box-shadow: none; }
    .vi-page .vi-side .row:hover .text-app2{ transform: none; }
}

/* respect users who prefer reduced motion. Both drivers bail before adding any
   class or binding the pan, so this is belt-and-braces. */
@media (prefers-reduced-motion: reduce){
    .gi-page .gi-grid h1,
    .gi-page .gi-grid .col-md-4 img,
    .vi-page .vi-h,
    .vi-page .vi-r,
    .vi-page .vi-player,
    .vi-page .vi-cmt .wreviewpeople,
    .vi-page .vi-cmt .wreviewpeople p.peoplereview,
    .vi-page .vi-cmt .wreviewpeople p.position-relative,
    .vi-page .vi-form h4,
    .vi-page .vi-form h4 + p,
    .vi-page .vi-form .vi-fld,
    .vi-page .vi-form .vi-fsub,
    .vi-page .vi-side h2,
    .vi-page .vi-side .row,
    .vi-page .vi-side .row img.obj-cover,
    .vi-page .vi-side .row .playbtnimgvideo{
        opacity: 1 !important; clip-path: none !important; transform: none !important;
        filter: none !important; box-shadow: none !important;
        object-position: 50% 50% !important;
        animation: none !important; transition: none !important;
    }
    .gi-page .gi-grid a.item img{ transition: none !important; object-position: 50% 50% !important; }
    .gi-page .gi-grid a.item:hover img{ box-shadow: none !important; filter: none !important; }
    .vi-page .vi-cmt .wreviewpeople:hover{ transform: none !important; box-shadow: none !important; }
    .vi-page #submit,
    .vi-page input[name="load_more"],
    .vi-page .btn.btnprimary{ transition: none !important; }
    .vi-page #submit:hover,
    .vi-page input[name="load_more"]:hover,
    .vi-page .btn.btnprimary:hover{ transform: none !important; box-shadow: none !important; }
    .vi-page .vi-side .row:hover img.obj-cover{ object-position: 50% 50% !important; filter: none !important; }
    .vi-page .vi-side .row:hover .playbtnimgvideo{ transform: none !important; box-shadow: none !important; }
    .vi-page .vi-side .row .text-app2{ transition: none !important; }
    .vi-page .vi-side .row:hover .text-app2{ transform: none !important; }
}


/* ==========================================================================
   Event detail page — eventinfo.php  (.ei-page)
   ==========================================================================
   THE MOTIF IS THE CALENDAR FLIP. The events component already owns one gesture
   that nothing else on the site uses — `evFlipIn`, which hinges an element down
   from its TOP edge like a calendar page turning — and the home section and the
   events listing both use it on the big day-number on each card. This page
   extends that gesture onto the detail page itself: the event's OWN date line
   flips down the same way, every section heading is wiped in with the events
   `evWipe`, and the "More Events" grid at the foot reuses the listing page's
   treatment wholesale. So the whole page speaks one vocabulary, and it is the
   events vocabulary rather than a seventh invented one.

   Only `eiPoster` is new: the two banner images hinge down from slightly above
   and settle, like a poster being pinned up. Same rotateX family as the calendar
   flip, but shallow and with a settle, so it reads as a poster going up rather
   than a page turning.

   MARKUP FACTS THIS BLOCK RESPECTS:

   1. `.medevents` already has a GLOBAL, unscoped hover — `background: #000`,
      `p` to white, `span`/`.title` to amber (lines ~294-301). That dramatic
      inversion is ALREADY live on this page's "More Events" cards. It is not
      re-added here; only the transitions are, so it eases instead of snapping —
      exactly what `.ev-page` and `.events_homepage` do with the same rule.

   2. eiPoster carries NO scale, on purpose. The hero sits in `.post-img`, which
      this block can give `overflow: hidden` — but the SECOND image is a bare
      <img> straight inside `.col-md-12` with nothing to crop it. One keyframe
      that is safe unwrapped beats two that differ only in containment. (At
      rotateX(-5deg) with a 1400px perspective the near edge projects under 1%
      wider, which stays inside the column's own 15px padding and shrinks to
      zero as it lands.) The hero still gets a contained zoom on HOVER, where
      `.post-img` is doing the cropping.

   3. The Venue map is raw admin HTML — `.mapvenue iframe{width:100%}` at line
      ~380 confirms it is an iframe. The WRAPPER div is animated, never the
      iframe: clip-path, filter and mask are all unreliable on embedded content.

   4. The external event link is emitted as a bare inline <a> with a loose text
      label beside it, not wrapped in any block. Transforms do not apply to
      non-replaced inline boxes, so it is given opacity only and will fade
      without moving — correct rather than silently broken.

   5. `.sticky-top` holds the date/venue panel, so it is never given
      `overflow: hidden` — that is what turns a sticky element into a scroll
      container and kills the stickiness.

   PRE-HIDE DISCIPLINE: note the split below. `evWipe` animates clip-path and NOT
   opacity, so the headings that use it are pre-hidden with CLIP-PATH and carry
   their own marker (`.ei-hw`); everything else is pre-hidden on opacity, and
   every keyframe paired with those animates opacity.
   ========================================================================== */

/* the poster goes up: hinged down from above and settling. See note 2 for why
   there is no scale. */
@keyframes eiPoster{
    from{ opacity: 0; transform: perspective(1400px) rotateX(-5deg) translateY(-22px); }
    to  { opacity: 1; transform: perspective(1400px) rotateX(0deg)  translateY(0); }
}

/* --- the top of the page: hero + both columns, built together ------------- */
.ei-page .ei-h{ opacity: 0; }
/* clip-path only — evWipe never touches opacity */
.ei-page .ei-hw{ clip-path: inset(-.2em 100% -.2em -.2em); }

.ei-page .ei-top.ei-in .ei-h{ animation: evTextUp .6s cubic-bezier(.22,.61,.36,1) both; }
.ei-page .ei-top.ei-in .ei-hw{ animation: evWipe .7s cubic-bezier(.22,.61,.36,1) both; }
.ei-page .ei-top.ei-in img.ei-h{ animation: eiPoster .9s cubic-bezier(.22,.61,.36,1) both; }
/* the event's own date line, hinged from its top edge — the motif */
.ei-page .ei-date{ transform-origin: top center; }
.ei-page .ei-top.ei-in p.ei-date{ animation: evFlipIn .7s cubic-bezier(.22,.61,.36,1) both; }

/* --- the lower block reveals on scroll ---------------------------------- */
.ei-page .ei-r{ opacity: 0; }
.ei-page .ei-r.ei-seen{ animation: evTextUp .6s cubic-bezier(.22,.61,.36,1) both; }
.ei-page img.ei-r.ei-seen{ animation: eiPoster .85s cubic-bezier(.22,.61,.36,1) both; }

/* --- hover: the hero breathes inside its own crop. Safe to scale because this
       rule is what supplies the crop; the second image has no wrapper and so
       gets a grade and a shadow only (note 2). */
.ei-page .post-img{ position: relative; overflow: hidden; }
.ei-page .post-img img{ transition: transform .7s cubic-bezier(.22,.61,.36,1), filter .5s ease; }
.ei-page .post-img:hover img{ transform: scale(1.04); filter: brightness(1.03) contrast(1.02); }

.ei-page .col-md-12 > img{ transition: filter .5s ease, box-shadow .5s ease; }
.ei-page .col-md-12 > img:hover{
    filter: brightness(1.03) contrast(1.02) saturate(1.02);
    box-shadow: 0 14px 34px rgba(0,0,0,.14);
}

/* the map: a soft lift on its wrapper to signal it is interactive. The iframe
   inside is never touched — see note 3. */
.ei-page .mapvenue .border{ transition: box-shadow .4s ease; }
.ei-page .mapvenue .border:hover{ box-shadow: 0 12px 26px rgba(0,0,0,.14); }

/* --- "More Events": the events listing page's treatment, reused ---------- */
.ei-page .ei-more.ei-mjs h3{ clip-path: inset(-.2em 100% -.2em -.2em); }
.ei-page .ei-more.ei-mjs .medevents{ opacity: 0; }
.ei-page .ei-more.ei-mjs .medevents > p{ opacity: 0; }
/* the two date lines hinge from their top edge, as on the cards elsewhere */
.ei-page .ei-more .medevents > p.fs-50,
.ei-page .ei-more .medevents > p.fs-20:not(.title){ transform-origin: top center; }

.ei-page .ei-more.ei-mjs.ei-min h3{ animation: evWipe .8s cubic-bezier(.22,.61,.36,1) .1s both; }
.ei-page .ei-more.ei-mjs.ei-min .medevents{ animation: evCardUp .7s cubic-bezier(.22,.61,.36,1) var(--ei-d, 0s) both; }
.ei-page .ei-more.ei-mjs.ei-min .medevents > p.fs-50{ animation: evFlipIn .65s cubic-bezier(.22,.61,.36,1) calc(var(--ei-d, 0s) + .10s) both; }
.ei-page .ei-more.ei-mjs.ei-min .medevents > p.fs-20:not(.title){ animation: evFlipIn .6s cubic-bezier(.22,.61,.36,1) calc(var(--ei-d, 0s) + .24s) both; }
.ei-page .ei-more.ei-mjs.ei-min .medevents > p.title{ animation: evTextUp .5s ease calc(var(--ei-d, 0s) + .38s) both; }
.ei-page .ei-more.ei-mjs.ei-min .medevents > p.mb-0:not(.title):not(.fs-50):not(.fs-12){ animation: evTextUp .5s ease calc(var(--ei-d, 0s) + .48s) both; }
.ei-page .ei-more.ei-mjs.ei-min .medevents > p.fs-12,
.ei-page .ei-more.ei-mjs.ei-min .medevents > p.overelipsis2{ animation: evTextUp .5s ease calc(var(--ei-d, 0s) + .58s) both; }

/* --- "More Events" hover. The black-background inversion is the theme's own
       global rule (note 1) — these lines only give it something to ease over,
       and add the lift around it. */
.ei-page .ei-more .medevents{
    transition: background-color .35s ease, transform .4s cubic-bezier(.22,.61,.36,1), box-shadow .4s ease;
}
.ei-page .ei-more .medevents p,
.ei-page .ei-more .medevents span,
.ei-page .ei-more .medevents .title{ transition: color .35s ease; }
.ei-page .ei-more .medevents:hover{ transform: translateY(-6px); box-shadow: 0 16px 30px rgba(0,0,0,.20); }

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .ei-page .post-img:hover img{ transform: none; filter: none; }
    .ei-page .col-md-12 > img:hover{ filter: none; box-shadow: none; }
    .ei-page .mapvenue .border:hover{ box-shadow: none; }
    .ei-page .ei-more .medevents:hover{ transform: none; box-shadow: none; }
}

/* respect users who prefer reduced motion. The driver bails before adding any
   class, so this is belt-and-braces. */
@media (prefers-reduced-motion: reduce){
    .ei-page .ei-h,
    .ei-page .ei-hw,
    .ei-page .ei-r,
    .ei-page .ei-date,
    .ei-page .ei-more h3,
    .ei-page .ei-more .medevents,
    .ei-page .ei-more .medevents > p{
        opacity: 1 !important; clip-path: none !important; transform: none !important;
        filter: none !important; animation: none !important; transition: none !important;
    }
    .ei-page .post-img img{ transition: none !important; }
    .ei-page .post-img:hover img{ transform: none !important; filter: none !important; }
    .ei-page .col-md-12 > img{ transition: none !important; }
    .ei-page .col-md-12 > img:hover{ filter: none !important; box-shadow: none !important; }
    .ei-page .mapvenue .border{ transition: none !important; }
    .ei-page .mapvenue .border:hover{ box-shadow: none !important; }
    .ei-page .ei-more .medevents,
    .ei-page .ei-more .medevents p,
    .ei-page .ei-more .medevents span{ transition: none !important; }
    .ei-page .ei-more .medevents:hover{ transform: none !important; box-shadow: none !important; }
}


/* ==========================================================================
   Testimonial video detail — testimonials_videoinfo.php  (.tvi-page)
   ==========================================================================
   This page is the video-detail sibling of videoinfo.php, and its sidebar is
   the SAME markup down to the class names (`img.obj-cover`, `.playbtnimgvideo`,
   `.text-app2` wrapping "Start Watching"). So it deliberately reuses that
   page's vocabulary rather than inventing a second one: the shutter for the
   headings, the crop-settle for the thumbnails, the amber ring for the play
   control. NO new keyframes are defined here — every animation below is one
   already established elsewhere in this stylesheet, which is what makes the
   page feel like the rest of the site instead of merely animated.

   VIDEO-PLAYER SAFETY, same rule as videoinfo: the player is a <video> or a
   YouTube/Instagram <iframe>. It gets opacity and translateY ONLY — no
   clip-path, no filter, no mask, none of which are reliable on replaced or
   embedded content — and NO hover state whatsoever, so nothing on the page
   competes with the player's own controls.

   Nothing here changes layout, colour or behaviour. The two amber values are
   `#F7B32B` expressed as rgba, which is the play icon's own colour and
   `.text-app2`'s, so no new hue enters the theme.
   ========================================================================== */

/* ---------- A. the player column: plays at once, it is above the fold ---- */
.tvi-page .tvi-h,
.tvi-page .tvi-player{ opacity: 0; }

/* the player leads, then its meta line, then the subject and the comment */
.tvi-page .tvi-body.tvi-in .tvi-player{ animation: siRise .8s cubic-bezier(.22,.61,.36,1) both; }
.tvi-page .tvi-body.tvi-in .tvi-h{ animation: siRise .65s cubic-bezier(.22,.61,.36,1) both; }
/* the subject line is the page's real title, so it gets the typeset reveal
   rather than the plain rise the paragraphs use */
.tvi-page .tvi-body.tvi-in h4.tvi-h{ animation: siMaskRise .8s cubic-bezier(.22,.61,.36,1) both; }

/* ---------- B. "More testimonial videos" ---------- */
.tvi-page .tvi-side.tvi-sjs h2{ opacity: 0; }
.tvi-page .tvi-side.tvi-sjs .row{ opacity: 0; }
.tvi-page .tvi-side.tvi-sjs .row img.obj-cover{ opacity: 0; }
.tvi-page .tvi-side.tvi-sjs .row .playbtnimgvideo{ opacity: 0; }

.tvi-page .tvi-side.tvi-sjs.tvi-sin h2{ animation: giShutter .8s cubic-bezier(.65,0,.35,1) both; }
.tvi-page .tvi-side.tvi-sjs.tvi-sin .row{
    animation: siRise .65s cubic-bezier(.22,.61,.36,1) var(--tvi-d, 0s) both;
}
.tvi-page .tvi-side.tvi-sjs.tvi-sin .row img.obj-cover{
    animation: giFrameIn .8s cubic-bezier(.22,.61,.36,1) calc(var(--tvi-d, 0s) + .08s) both;
}
.tvi-page .tvi-side.tvi-sjs.tvi-sin .row .playbtnimgvideo{
    animation: viPlayPop .7s cubic-bezier(.34,1.56,.64,1) calc(var(--tvi-d, 0s) + .3s) both;
}

/* --- sidebar hover: the thumbnail's crop PANS and brightens, the play control
       swells inside an amber ring, and "Start Watching" nudges across.

       The pan is `object-position`, not a scale: the thumbnails are
       `object-fit: cover` in a fixed 120px box, so the crop already has slack
       outside the visible window and panning it explores the frame without the
       element ever changing size. That matters here because the row sits in a
       padded Bootstrap column with no clipping ancestor — a scale would bleed
       into the gutter. */
.tvi-page .tvi-side .row img.obj-cover{
    object-position: 50% 50%;
    transition: object-position .5s ease-out, filter .4s ease, box-shadow .4s ease;
}
.tvi-page .tvi-side .row:hover img.obj-cover{
    object-position: 50% 38%;
    filter: brightness(1.05) contrast(1.02);
    box-shadow: 0 10px 22px rgba(0,0,0,.16);
}
.tvi-page .tvi-side .playbtnimgvideo{
    border-radius: 50%;
    transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease;
}
.tvi-page .tvi-side .row:hover .playbtnimgvideo{
    transform: scale(1.18);
    box-shadow: 0 0 0 8px rgba(247,179,43,.20);
}
/* `.text-app2` is already a flex item of the `d-flex flex-column` cell, so it is
   blockified and this `display` is a no-op — it is stated only so the transform
   cannot be ignored if that wrapper ever stops being a flex child. */
.tvi-page .tvi-side .row .text-app2{ display: inline-block; transition: transform .35s cubic-bezier(.22,.61,.36,1); }
.tvi-page .tvi-side .row:hover .text-app2{ transform: translateX(4px); }

/* --- touch / small screens: drop the hovers, keep the entrances */
@media (max-width: 767px), (hover: none){
    .tvi-page .tvi-side .row:hover img.obj-cover{ object-position: 50% 50%; filter: none; box-shadow: none; }
    .tvi-page .tvi-side .row:hover .playbtnimgvideo{ transform: none; box-shadow: none; }
    .tvi-page .tvi-side .row:hover .text-app2{ transform: none; }
}

/* respect users who prefer reduced motion. The driver bails before adding any
   class, so this is belt-and-braces. */
@media (prefers-reduced-motion: reduce){
    .tvi-page .tvi-h,
    .tvi-page .tvi-player,
    .tvi-page .tvi-side h2,
    .tvi-page .tvi-side .row,
    .tvi-page .tvi-side .row img.obj-cover,
    .tvi-page .tvi-side .row .playbtnimgvideo{
        opacity: 1 !important; clip-path: none !important; transform: none !important;
        filter: none !important; box-shadow: none !important;
        object-position: 50% 50% !important;
        animation: none !important; transition: none !important;
    }
    .tvi-page .tvi-side .row:hover img.obj-cover{ object-position: 50% 50% !important; filter: none !important; box-shadow: none !important; }
    .tvi-page .tvi-side .row:hover .playbtnimgvideo{ transform: none !important; box-shadow: none !important; }
    .tvi-page .tvi-side .row .text-app2{ transition: none !important; }
    .tvi-page .tvi-side .row:hover .text-app2{ transform: none !important; }
}


/* ==========================================================================
   CAROUSEL GUTTERS (home page) — one gap for every section
   ==========================================================================
   Deliberately NOT split across the per-section blocks above. The whole point
   of this is that all fourteen sliders agree, and that is only checkable if
   they are listed together. Adding a new slider? Add its wrapper here.

   These are Owl Carousel 1.x (see the `items` / `navigation` / `singleItem`
   options in index.php). Owl 1 has NO `margin` option, so the gap between two
   items is nothing but the inset carried by each item's inner wrapper, and
   every section had picked its own utility class for that. Measured before:

       Video Gallery   .vedioimg.mx-2               8px   → 16px gap  REFERENCE
       Photo Gallery   .albumcss.mx-2               8px   → 16px gap  already ok
       Treatments      .treatments-card.m-2         2px   →  4px gap
       Press Release   .mr-20.gallery               0px   →  0px gap
       News            .post.p-10                  10px   → 20px gap
       Awards          .post.p-10                  10px   → 20px gap
       Doctors         .doccard.p-10               10px   → 20px gap
       Testimonials    .container > .row           15px   → 30px gap
       Services        .container > .row           15px   → 30px gap
       Departments     .container > .row           15px   → 30px gap
       Vision/Mission  .col-md-12 > .row           15px   → 30px gap
       Blogs           .blog.px-3                  16px   → 32px gap
       Case Studies    .casestudies.px-3           16px   → 32px gap
       Events          .medevents.mx-3             16px   → 32px gap

   Two of those numbers are traps worth recording, because reading the markup
   alone gives the wrong answer:
   · `.m-2` looks like Bootstrap's 0.5rem, but style.css REDEFINES it as 2px
     further down the file (line ~1891 beats line ~121), so Treatments was at
     4px, not 16px.
   · `.mr-20` is 20px in style.css but zeroed by `.mr-20{margin-right:0px
     !important}` earlier in THIS file, so Press Release had no gutter at all.

   Everything is now 8px a side — 16px between neighbours, matching the Video
   Gallery. Each section keeps its own MECHANISM (a padding stays a padding, a
   margin stays a margin): none of these wrappers has a background or a border,
   so at 8px the two are pixel-identical, and leaving the property alone keeps
   each diff down to the one number that was wrong.

   Scoped by slider id throughout. The view only prints those ids when sliding
   is enabled — with it switched off the same wrappers render inside `.col-sm-*`
   grid cells, where the larger inset is correct because it pairs with the
   column's own gutter. None of this may reach that case.

   `!important` on the utility-class rules is not a preference: Bootstrap's
   spacing utilities are themselves `!important`, so nothing without it wins.
   The `.container` / `.col-md-12` rules need none — those carry no
   `!important`, and these selectors are far more specific.
   ========================================================================== */

/* ---- padding-based wrappers ---------------------------------------------
   `p-10` is a shorthand for all four sides, so only left and right are
   restated here — the 10px top and bottom stay exactly as they were, and the
   vertical rhythm of those rows does not move. */
#blog_slider .blog.px-3,
#casestudies_slider .casestudies.px-3,
#news_slider .post.p-10,
#awards_slider .post.p-10,
#doctors_slider .doccard.p-10{
    padding-left: 8px !important;
    padding-right: 8px !important;
}

/* ---- margin-based wrappers ----------------------------------------------
   Events keeps its `p-20` inner padding untouched: that is the card's internal
   breathing room, not the gutter. Treatments GAINS 6px a side here (it was on
   the 2px `.m-2`), so its cards' hover shadow has more room than before, not
   less. */
#event_slider .medevents.mx-3,
#treatments_slider .treatments-card.m-2,
#press_release_slider .gallery.mr-20{
    margin-left: 8px !important;
    margin-right: 8px !important;
}

/* ---- Bootstrap container / column wrappers ------------------------------
   These four wrap their content in a `.container` (or a `.col-md-12`) holding
   a nested `.row`, so the inset a visitor actually sees is
   container 15 − row −15 + inner column 15 = 15px. Trimming the OUTER padding
   to 8px moves that visible edge to 8px while the row ↔ column pairing inside
   stays untouched, which is what keeps those cards laid out exactly as before.

   The nested row then hangs 7px outside its container. That is invisible and
   safe here, and it was checked rather than assumed: every one of these rows
   (`.service-card`, `.vision-mission-card`, and the plain `.row` in the
   testimonials item) is a bare layout row with no background, no border and no
   shadow of its own, and none of these four sections paints a card surface at
   all — the home-page testimonial is an avatar plus white copy straight on the
   section's dark panel, NOT the `.wreviewpeople` card that the testimonials
   LISTING page uses. So all that moves is the content, inward, as intended.
   If a background is ever added to one of those rows, this block has to change
   with it.

   The child combinator matters: these pages are full of nested `.container`
   and `.col-md-12` elements, and a descendant selector would reset their
   padding too. `> ` restricts this to the element Owl itself wraps. Both
   layout classes are listed because the view picks between them from
   `dw_ts_layout`. */
#testimonials_slider .owl-item > .container,
#testimonials_slider .owl-item > .container-fluid,
#services_slider .owl-item > .container,
#services_slider .owl-item > .container-fluid,
#departments_slider .owl-item > .container,
#departments_slider .owl-item > .container-fluid,
#visionmission_slider .owl-item > .col-md-12{
    padding-left: 8px;
    padding-right: 8px;
}


/* ==========================================================================
   INNER-PAGE CARD WRAPPERS — the three that carried a SECOND inset
   ==========================================================================
   Read together with the `.card-grid` block below: that one sets the gutter
   itself to 8px a side on every listing grid, and this one removes the extra
   inset that three pages stacked ON TOP of their column. Both are needed for
   those three to land on 16px — the gutter alone would leave news and doctors
   at 8+10 = 18px a side, so a 36px gap.

   The listing pages carry NO carousel (the only `owlCarousel()` calls outside
   index.php are five in about_us.php whose target ids do not exist in that
   file, so they match nothing and do nothing). They are plain Bootstrap grids,
   so the gap is the column gutter, and three pages doubled up on it:

       news.php        .col-md-4.my-4 > .post.p-10             col +10px
       doctors.php     .col-md-4.my-4 > .doccard.p-10          col +10px
       treatments.php  .col-md-4.my-4 > .treatments-card.m-2   col + 2px

   Every other listing page adds nothing beyond its column and so needs nothing
   here: blog, blog_category_details, awards (its wrapper is `.awards-card
   post`, with no `p-10`), services, departments, casestudies, photo_gallery,
   video_gallery, pressrelease, testimonials, events.

   THE DISTINCTION THAT DECIDES THIS, and it was checked per class rather than
   assumed: an inset only counts as a gutter when its element paints nothing.
   `.post`, `.doccard` and `.treatments-card` carry no background and no border
   — they are bare layout wrappers — so their inset is pure gutter and removing
   it moves nothing but the gap. Two listings look like the same case and are
   deliberately LEFT ALONE, because their wrapper does paint, which makes the
   inset the card's internal padding instead:
       · testimonials.php  `.wreviewpeople.px-3.py-4`  — background rgba(0,0,0,.04)
       · events.php        `.medevents.p-20`           — background rgba(0,0,0,.04)
   Stripping those would shove the copy flat against a visible card edge.

   Horizontal only. `p-10` and `m-2` are four-side shorthands, and their top and
   bottom values also feed the space between grid ROWS — which is staying as it
   is, so only the left and right are restated.

   Scoped on the section element, not on the `.xx-page` body classes the
   animation drivers add: those arrive from JavaScript, and spacing must not
   depend on JavaScript having run. The `.col-md-4.my-4 >` qualifier is what
   keeps each rule on its listing grid — the home page reuses `.post.p-10`,
   `.doccard.p-10` and `.primary_section.treatments`, but never inside a
   `.col-md-4.my-4` cell, so the carousel gutters set above stay in force. */
section.news .col-md-4.my-4 > .post.p-10,
section.primary_section.doctors .col-md-4.my-4 > .doccard.p-10{
    padding-left: 0 !important;
    padding-right: 0 !important;
}
section.primary_section.treatments .col-md-4.my-4 > .treatments-card.m-2{
    margin-left: 0 !important;
    margin-right: 0 !important;
}

/* --- `.card-grid`: every inner-page card grid on the home page's 16px -------
   The listing pages were on the plain 30px Bootstrap column gutter while the
   home carousels are now 16px, so the same cards read as two different designs
   depending on which page you were looking at. One class, one rule, applied to
   the card-grid `.row` of each listing:

       blog.php · blog_category_details.php · news.php · doctors.php
       services.php · departments.php · treatments.php · awards.php
       casestudies.php · photo_gallery.php · video_gallery.php
       pressrelease.php · testimonials.php · events.php

   BOTH halves of the gutter are restated, and that is the whole point of doing
   it this way. A Bootstrap gutter is a PAIR: the row pulls out by 15px and each
   column pads back in by 15px, which is what leaves the first and last card
   flush with the container. Changing only the column padding would give the
   16px gap but bleed every card 7px past the container, so the grid would stop
   lining up with the page heading and any sidebar beside it. Moving the two
   together keeps the outer edges exactly where they are and changes nothing but
   the space between neighbours. Mobile is unaffected for the same reason: at
   full width the −8/+8 still cancels, just as −15/+15 did.

   DIRECT children only. Several of these cards contain a nested `.row` of their
   own — `.row.service-card` on departments.php is the clearest case — and those
   keep their own −15/+15 pairing untouched, exactly as they do inside the home
   page's container-wrapped sliders. A descendant selector here would have
   reached inside the cards and pulled their internal layout apart.

   Both attribute forms are needed: `[class^="col-"]` catches `class="col-md-6
   my-4"`, while `[class*=" col-"]` catches the cells that list `col-*` second,
   such as events.php's `medeventsdiv`. Heading cells are picked up by the same
   selector on purpose — left out, the `<h1>` above each grid would keep the old
   15px inset and sit 7px off from the cards underneath it.

   A static class on an existing `.row`, not a structural selector and not the
   `.xx-page` body classes the animation drivers add: no PHP or dynamic output is
   touched, spacing never depends on JavaScript having run, and it avoids the
   trap that `.col-md-9 > .row` would also match the doctors grid inside
   departmentsinfo.php. No `!important` needed — Bootstrap declares neither
   `.row` nor `.col-*` padding important, and both selectors below outrank it.

   Two pages are deliberately NOT given the class. visionmission.php is a stack
   of single full-width `.col-md-12` cells, so it has no neighbour to sit beside
   and the only effect would be to pull its copy 7px wider than every other
   block on the page. faqs.php is an accordion, not a grid. */
.card-grid{
    margin-left: -8px;
    margin-right: -8px;
}
.card-grid > [class^="col-"],
.card-grid > [class*=" col-"]{
    padding-left: 8px;
    padding-right: 8px;
}





