/* Sitekit V2 — glue only. Everything else is Elementor settings. */

/* Hello Elementor prints its own header/footer above canvas templates. */
body.page header.site-header,
body.page footer.site-footer { display: none !important; }

/* Sticky/fixed needs clip, never hidden. */
html, body { overflow-x: clip; }

/* ── WordPress admin bar ───────────────────────────────────────────────────
   Logged-in users get a fixed toolbar at z-index 99999, and the site header is
   itself `position: fixed`, so without an offset the logo slides underneath it.
   In-flow content is already handled by WP's own `html { margin-top }`; only
   fixed elements need this.

   The height is NOT hard-coded. WordPress publishes it as a custom property on
   <html> and flips it 32px → 46px at its own 782px breakpoint
   (wp-includes/css/admin-bar.css), so deriving from that variable tracks the
   switch for free and stays correct if core ever changes the numbers.

   Below 600px core switches the bar to `position: absolute` (admin-bar.css
   line 1112) — it scrolls away with the document rather than staying put.
   Offsetting there would pin the header 46px down and leave a permanent strip
   of page showing above it for the whole scroll, so the offset returns to 0 and
   the only cost is an overlap at the very top of the page. That is the better
   trade: it self-corrects the moment you scroll. */
:root { --sk-admin-offset: 0px; }
body.admin-bar { --sk-admin-offset: var(--wp-admin--admin-bar--height, 32px); }
@media screen and (max-width: 600px) {
  body.admin-bar { --sk-admin-offset: 0px; }
}

/* ── Header ────────────────────────────────────────────────────────────────
   position/offset/z-index are Elementor settings; only the backdrop blur is
   here, because the classic container has no backdrop-filter control (it
   exists solely in the v4 atomic-widget schema). */
.sk-header {
  background-color: rgba(255, 255, 255, 0.9) !important;
  -webkit-backdrop-filter: blur(32px);
  backdrop-filter: blur(32px);
}

/* The hero paints its photo under the bar; every other page starts below it. */
.sk-hero { position: relative; }

/* ── Mobile navigation ─────────────────────────────────────────────────────
   The panel drops out of the header as one white rounded card. There is ONE
   button: the header sits above the panel in z-order, so the toggle occupies
   identical pixels open or closed and simply morphs into an X. */
.sk-mnav-toggle {
  display: flex; flex-direction: column; align-items: flex-end; gap: 6px;
  width: 30px; height: 30px; justify-content: center;
  padding: 0; margin: 0; background: none; border: 0; cursor: pointer;
}
.sk-mnav-toggle:hover,
.sk-mnav-toggle:focus,
.sk-mnav-toggle:active { background: none; outline: none; }
.sk-mnav-toggle:focus-visible { outline: 2px solid #F06218; outline-offset: 4px; }
.sk-mnav-toggle span {
  display: block; height: 2px; width: 30px; background: #4A4A4A;
  transition: transform .3s ease, opacity .2s ease;
}

@media (max-width: 1024px) {
  body.sk-mnav-open .sk-mnav-toggle span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
  body.sk-mnav-open .sk-mnav-toggle span:nth-child(2) { opacity: 0; }
  body.sk-mnav-open .sk-mnav-toggle span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }
}

.sk-mnav {
  position: fixed !important;
  /* Must equal the mobile bar's real height, or the first menu item slides up
     under it. The bar is 14 + 32 (logo) + 14 = 60; the logo's mobile size is an
     Elementor setting, so changing it here means changing it there too. */
  top: calc(60px + var(--sk-admin-offset, 0px)); left: 0; right: 0;
  z-index: 9990;
  max-height: calc(100vh - 60px - var(--sk-admin-offset, 0px));
  overflow-y: auto; overscroll-behavior: contain;
  border-radius: 0 0 20px 20px;
  box-shadow: 0 8px 8px -4px rgba(0,0,0,.08), 0 4px 6px -4px rgba(0,0,0,.12);
  /* No `display:flex !important` — it would beat .elementor-hidden-desktop and
     leave the panel in the DOM on desktop. */
  flex-direction: column; flex-wrap: nowrap;
  transform: translateY(-8px);
  opacity: 0; visibility: hidden;
  transition: opacity .25s ease, transform .25s ease, visibility 0s linear .25s;
}
.sk-mnav.is-open {
  transform: none; opacity: 1; visibility: visible; transition-delay: 0s;
}
body.sk-mnav-open { overflow: hidden; }

/* Flex items shrink by default; on a short screen that squashes the panel. */
.sk-mnav > * { flex-shrink: 0; }
.sk-mnav__links .elementor-nav-menu a { padding-left: 0 !important; }

/* ── Decoration ────────────────────────────────────────────────────────────
   Both are deliberate overhangs: the hero confetti spills onto the white
   section below, the testimonial coil rides up into the section above. */
.sk-hero-decor, .sk-coil { pointer-events: none; }

/* ── Testimonial card ──────────────────────────────────────────────────────
   Avatar hangs above the card and the quote mark is pinned inside its corner;
   neither is in the flow, which Elementor's own controls cannot express for a
   widget inside a flex column. */
.sk-testimonial {
  position: relative; overflow: visible;
  /* Figma 1:4770 / 1:3492 — the row is 333 tall around a 260 card, i.e. 36.5
     clear top AND bottom. The avatar/badge hangs 34 up, so 36.5 leaves it 2.5
     to spare. Symmetric margin is what makes the row measure 333 rather than
     301 and keeps everything below it on the design's y. */
  margin: 36.5px 0;
  /* Figma 1:4772 carries TWO drop shadows and Elementor's box-shadow control is
     single-layer, so this cannot be expressed as a setting. Kept here in full
     rather than emitting a native shadow the glue would then have to override —
     Elementor's per-element CSS outranks a class, so the panel would show a
     value that does nothing. */
  box-shadow: -32px 36px 12px rgba(0,0,0,.04), 0 2px 8px rgba(0,0,0,.07);
}
.sk-testimonial__avatar { position: absolute; top: -34px; left: 50%; transform: translateX(-50%); }
.sk-testimonial__avatar img { border-radius: 50%; display: block; }
.sk-testimonial__mark { position: absolute; top: 31px; left: 25px; }

/* ── Adopt ─────────────────────────────────────────────────────────────────
   The numbered step badge hangs above its card exactly as the testimonial
   avatar does; the card shell itself reuses .sk-testimonial. */
.sk-step__badge { position: absolute; top: -34px; left: 50%; transform: translateX(-50%); }

/* ── Adoptable pets ────────────────────────────────────────────────────────
   Markup comes from the [sc_pets] shortcode in mu-plugins/sc-pets.php, so it
   cannot be laid out with Elementor settings — this is the one place on the site
   where a grid genuinely has to be CSS. Kept to the design's own tokens. */
.sc-pets {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 25px;
  list-style: none; margin: 0; padding: 0;
}
@media (max-width: 1024px) { .sc-pets { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 767px)  { .sc-pets { grid-template-columns: 1fr; } }

.sc-pets__card {
  background: #F6F8FB; border-radius: 20px; overflow: hidden; height: 100%;
  display: flex; flex-direction: column;
}
.sc-pets__photo {
  display: block; width: 100%; height: 240px; object-fit: cover;
  border-radius: 8px 8px 0 0; background: #E9E9E9;
}
.sc-pets__name { margin: 20px 24px 12px; font-size: 20px; line-height: 1.2; color: #000; }
.sc-pets__meta { margin: 0 24px 24px; }
.sc-pets__row { display: flex; gap: 8px; padding: 2px 0; }
.sc-pets__row dt { font-weight: 700; color: #343434; min-width: 68px; }
.sc-pets__row dd { margin: 0; color: #4A4A4A; }
.sc-pets__empty { text-align: center; color: #6C6C6C; padding: 48px 0; }

/* The card's own button. `margin-top: auto` pins it to the bottom of the flex
   column so a card with a longer breed name does not sit its button higher than
   its neighbours'. Matches the site button: orange, 10px radius, white label. */
.sc-pets__button {
  margin: auto 24px 24px; align-self: flex-start;
  display: inline-block; padding: 12px 24px;
  background: #F06218; color: #FFFFFF; border-radius: 10px;
  font-weight: 600; line-height: 1.2; text-decoration: none;
  transition: background-color .15s ease;
}
.sc-pets__button:hover,
.sc-pets__button:focus { background: #D2530F; color: #FFFFFF; }
.sc-pets__button:focus-visible { outline: 3px solid #000; outline-offset: 2px; }

/* Defined here rather than trusted to the theme, since the pet buttons depend on
   it to carry "(opens in a new tab)" to screen readers without showing it. */
.sc-pets .screen-reader-text {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(1px, 1px, 1px, 1px); clip-path: inset(50%); white-space: nowrap;
}

/* ── Contact ───────────────────────────────────────────────────────────────
   A 113px rule between the three detail blocks (Figma 1:4553). Drawn as a
   pseudo-element in the 25px gutter because it is shorter than its row and so
   cannot be a border, and Elementor has no control for it. Dropped once the
   blocks stack. */
.sk-contact__block { position: relative; }
.sk-contact__block + .sk-contact__block::before {
  content: ""; position: absolute; left: -13px; top: 50%;
  transform: translateY(-50%);
  width: 1px; height: 113px; background: #F06218;
}
@media (max-width: 767px) {
  .sk-contact__block + .sk-contact__block::before { display: none; }
}
.sk-contact__block a { color: inherit; }
/* The disc must not squash when the label beside it wraps. */
.sk-contact__disc { flex: 0 0 auto; }

/* ── Resources ─────────────────────────────────────────────────────────────
   The FAQ rows are a plain title + toggle closing on a 1px rule; Elementor's
   accordion draws a full box by default. */
.sk-faq .elementor-accordion .elementor-accordion-item {
  border: 0; border-bottom: 1px solid #E9E9EA;
}
.sk-faq .elementor-tab-title { padding: 16px 0; }
.sk-faq .elementor-tab-content { border: 0; padding: 0 0 16px; }
.sk-back-link a { color: inherit; text-decoration: none; }
.sk-back-link a:hover { color: #F06218; }
.sk-contact-form .elementor-field-textual { height: 50px; }
.sk-contact-form textarea.elementor-field-textual { height: 196px; }

/* ── Footer ────────────────────────────────────────────────────────────────
   Link lists are text widgets so the client can edit them; the anchors need to
   stack. Note the <p> trap: a text-editor only wraps content in <p> when it has
   no markup, so both selectors are needed. */
.sk-foot-links, .sk-foot-links p { margin: 0; }
.sk-foot-links a { display: block; color: inherit; text-decoration: none; }
.sk-foot-links a:hover { color: #F06218; }
.sk-foot-address a { color: inherit; text-decoration: underline; }
.sk-foot-legal a { color: inherit; text-decoration: none; }
.sk-foot-legal a:hover { text-decoration: underline; }

@media (prefers-reduced-motion: reduce) {
  .sk-mnav, .sk-mnav-toggle span { transition: none; }
}

/* ── Entrance animations ───────────────────────────────────────────────────
   Ported from the published Figma Sites build. Figma drives these by writing
   inline styles frame by frame; here they are CSS transitions flipped by one
   IntersectionObserver (see ANIM_JS), which is cheaper and interruptible.

   The three offsets are Figma's own, measured off the live build:
     nav             translateY(-60)   drops in from above, once, on load
     section heading translateY(+50)   short rise
     content block   translateY(+150)  long rise
   One duration across two distances is what makes the heading land before the
   content under it — that is the whole effect, and it comes for free.

   EVERY rule is scoped to html.sk-anim, which only JS adds. No JS, no
   IntersectionObserver, or reduced motion -> nothing here applies and the page
   is simply finished. That is the point: an entrance animation must never be
   able to leave content invisible. */
html.sk-anim .sk-rise,
html.sk-anim .sk-rise-sm {
  opacity: 0;
  will-change: opacity, transform;
  transition: opacity .8s cubic-bezier(.22, .61, .36, 1),
              transform .8s cubic-bezier(.22, .61, .36, 1);
}

/* The pre-roll blanket — and the fix for two bugs that were really one bug.
   ANIM_JS runs at the END of the body, so it can only add `sk-rise` to things
   that have already been parsed and, on a warm cache, already PAINTED. That
   produced exactly what it sounds like: the first screen appeared finished,
   then snapped down and rose back into place (the "wiggle"), and the h1 — the
   one block whose delay is 0 — was flipped hidden and revealed inside a single
   style resolution, so its computed style never changed and no transition ever
   started (it just "was there").

   Hiding whole SECTIONS is something CSS can do from the top of the body,
   before a single one of them exists in the DOM, which is the only place early
   enough to matter. ANIM_JS drops `sk-pre` the moment it has tagged the real
   targets, so the blanket hands straight over to the per-block hidden state
   with nothing visible in between.

   The excluded classes are the ones ANIM_JS skips anyway — blanketing those
   would hide them and then pop them in, which is worse than not animating them.
   And the whole thing is doubly conditional: `sk-anim` AND `sk-pre`, both added
   by script, either one removed by a failsafe, and the page is simply finished. */
html.sk-anim.sk-pre .elementor > .e-con:not(.sk-header):not(.sk-mnav):not(.sk-photo-band):not(.sk-adopt-banner) {
  opacity: 0;
}

/* And the other half of `sk-pre`: ARMING MUST NOT ANIMATE.
   `.sk-rise` carries both the hidden state and the transition, so the moment
   the class lands the browser generates a transition INTO hiding — from the
   painted `opacity: 1` toward 0, over the full 800ms, delays and all. Every
   block was drifting down and fading OUT, and the observer then reversed it two
   frames later. That was the wiggle. And it is why the h1 read as "already
   visible": with a 0ms delay it got about 4% into the fade-out before turning
   round, so it never looked hidden and never looked like it faded in.
   It was never a missing animation. It was one animation too many.
   `sk-pre` is on for the whole tagging phase, so nothing can transition until
   the hidden state has been resolved once with transitions off. */
html.sk-anim.sk-pre .sk-rise,
html.sk-anim.sk-pre .sk-rise-sm {
  transition: none;
}
/* The header, as a keyframe rather than a JS-toggled class. Declarative means
   it cannot end up half-applied; `both` holds the finished state; and if the
   arming class is ever removed (the ARM script's own failsafe) the animation is
   simply cancelled and the bar is visible, which is the right failure. */
@keyframes sk-header-drop {
  from { opacity: 0; transform: translateY(-60px); }
  to   { opacity: 1; transform: none; }
}
html.sk-anim .sk-header {
  /* .5s delay: the h1 lands first, then the bar drops in over it. */
  animation: sk-header-drop .8s cubic-bezier(.22, .61, .36, 1) .5s both;
}

/* The long distance is what nearly every block on the site uses, so it is the
   one that sets the overall feel — 200px read as too much once the arming bug
   was out of the way and you could actually see the movement. The short one is
   only on headings and was never the problem, so it comes back a little rather
   than proportionally; keeping the two distances clearly apart is what makes a
   heading land before the content under it. */
html.sk-anim .sk-rise    { transform: translateY(130px); }
html.sk-anim .sk-rise-sm { transform: translateY(65px); }

/* Wins over all three above: same specificity, declared later. */
html.sk-anim .sk-in {
  opacity: 1;
  transform: none;
}

/* Belt and braces — the JS already bails, but if the media query flips mid-session
   (a reader changing the OS setting) the page must settle, not stay hidden. */
@media (prefers-reduced-motion: reduce) {
  html.sk-anim .sk-rise,
  html.sk-anim .sk-rise-sm {
    opacity: 1;
    transform: none;
    transition: none;
  }
  html.sk-anim .sk-header { animation: none; }
  html.sk-anim.sk-pre .elementor > .e-con { opacity: 1; }
}
