/* ============================================================
   SHARP DESIGN BUILD -- additive aliveness layer
   Loaded after sections.css. Owns motion-only presentation.
   ============================================================ */

/* Custom cursor removed per David (Jun 19) — native cursor restored. */

/* Tile-stone — Beanro grow. The card enters small, the section pins at center,
   and over the pinned scrub the card grows small->large while the chisel
   scrubs on the same beat (motion.js initTileStoneExpand). The frames paint to
   the <canvas>; here we just swap it in over the blank-slab card background once
   motion is live. Width-grow + canvas sizing live in sections.css / motion.js. (David, Jun 19) */
.motion-ready #tile-stone .tilestone__canvas { display: block; }

/* Design & Planning 3D card-swap primitives. */
.motion-ready .design-planning__stage {
  perspective: 1150px;            /* tighter = stronger foreshortening for the front/back read */
  perspective-origin: 50% 45%;
  transform-style: preserve-3d;
}

.motion-ready .design-planning__photo,
.motion-ready .design-planning__sketch {
  backface-visibility: hidden;
  transform-style: preserve-3d;
}

/* GPU hint (Jun 20, REVISED Jun 22): promote the two card layers as soon as motion
   is ready — i.e. at page load, NOT at swap-start.

   FIRST-SWAP POP ROOT CAUSE (David Jun 22): this used to be gated behind `.is-live`,
   which initDesignPlanningCardSwap adds in the SAME tick it calls tl.play(). So the
   very first swap ran while the browser was still *creating* these compositor layers
   — the photo rendered on the not-yet-promoted layer, stayed visually behind through
   the whole first trade, then "cut to front" the instant promotion finished. Every
   later swap was flawless because the layers were already warm. Pre-promoting at
   motion-ready makes the layers exist long before the first play, so the first swap
   renders identically to all the rest. (The earlier `.is-live`-gated demotion was a
   VRAM micro-opt; for two small cards the saving is negligible and not worth a
   visible first-play pop.) `is-live` is still toggled in JS as a lifecycle marker. */
.motion-ready .design-planning__photo,
.motion-ready .design-planning__sketch {
  will-change: transform, filter;
}

/* NO z-index on either card — front/back is decided purely by translateZ inside the
   preserve-3d stage, so the depth swap is continuous (no discrete stacking flip = no
   pop). Rest depths are seeded in the var defaults (sketch forward, photo back). */
.motion-ready .design-planning__photo {
  transform:
    translate3d(var(--dp-photo-x, 0), var(--dp-photo-y, 0), var(--dp-photo-z, -70px))
    rotate(var(--dp-photo-r, 0deg))
    scale(var(--dp-photo-s, 1));
}

.motion-ready .design-planning__sketch {
  /* clip-path removed (David Jun 21): the sketch now shows FULL in its native 4:3
     ratio — no rest-crop. The swap is a pure depth/position trade of two whole cards. */
  transform:
    translate3d(var(--dp-sketch-x, 0), var(--dp-sketch-y, 0), var(--dp-sketch-z, 70px))
    rotate(var(--dp-sketch-r, -4deg))
    scale(var(--dp-sketch-s, 1));
}

/* (is-swapped z-index toggle removed Jun 21 — it caused a one-frame pop mid-swap.
   The sketch now stays the top layer through the whole quick trade; see motion.js
   initDesignPlanningCardSwap.) */

/* Before/after tease. */
.motion-ready .ba__handle,
.motion-ready .ba__grip {
  transition:
    background 220ms var(--ease-out),
    color 220ms var(--ease-out),
    box-shadow 220ms var(--ease-out);
}

.motion-ready .ba__slider.is-teasing .ba__handle,
.motion-ready .ba__slider.is-dragging .ba__handle {
  background: transparent;
}

.motion-ready .ba__slider.is-teasing .ba__handle::before,
.motion-ready .ba__slider.is-dragging .ba__handle::before {
  background: var(--terracotta);
}

.motion-ready .ba__slider.is-teasing .ba__grip,
.motion-ready .ba__slider.is-dragging .ba__grip {
  background: var(--terracotta);
  color: #fffaf3;
  box-shadow: 0 10px 30px rgba(192, 97, 61, 0.42);
}

.motion-ready .ba__slider.has-user-touched .ba__grip {
  background: rgba(245, 242, 236, 0.96);
  color: #121419;
}

.motion-ready .ba__slider.has-user-touched.is-dragging .ba__handle {
  background: transparent;
}

.motion-ready .ba__slider.has-user-touched.is-dragging .ba__handle::before {
  background: var(--terracotta);
}

.motion-ready .ba__slider.has-user-touched.is-dragging .ba__grip {
  background: var(--terracotta);
  color: #fffaf3;
}

/* Hover micro-interactions and depth without changing layout. */
.motion-ready .svc-tile,
.motion-ready .work-card,
.motion-ready .review-card,
.motion-ready .team-card,
.motion-ready .process__step,
.motion-ready .btn {
  transition:
    transform 360ms var(--ease-out),
    box-shadow 360ms var(--ease-out),
    border-color 360ms var(--ease-out),
    background 360ms var(--ease-out);
}

/* Pop-out hover (David, Jun 21 — REFINES Jun 20): the rise+scale "pop" falsely
   signals clickability, so it is now RESERVED for genuinely clickable cards.
   Removed from non-interactive surfaces -- team portraits (Elu/George),
   process steps, and the (currently non-clickable) service tiles. Kept ONLY on
   .work-card, which is now click-to-expand (dump §5/§16) -- the pop correctly
   previews that click affordance. (Transition block above left UNCHANGED so any
   other shadow/border hover on those surfaces still eases — only the transform
   pop is removed.) */
.motion-ready .work-card:hover {
  transform: translate3d(0, -0.28rem, 0) scale(1.025);
}
/* The featured "One home, every room" card (.work-card--feature) is a plain
   <article> with NO data-work-card -- it is excluded from the click-to-expand
   binding (motion.js initWorkExpand targets [data-work-card]). So it must NOT
   pop on hover, or it falsely signals clickability sitting amid 7 cards that ARE
   clickable (David R3 §10/§5: reserve the pop for genuinely interactive cards). */
.motion-ready .work-card--feature:hover {
  transform: none;
}

/* Reviews pop (David, Jun 20): the old translateY-only "felt weird — just
   shifting it up." Now a smooth scale grow + a soft drop-shadow that bleeds a
   touch toward the neighbours. Scale is kept modest (~1.04) so borders never
   collide with adjacent cards; z-index lift keeps the grown card + its shadow
   above its siblings. (Hover-to-pause of the rail itself is in sections.js.)

   PAINT FIX (Jun 20): the soft shadow used to animate a ~60px-blur `box-shadow`
   on hover -- a per-frame PAINT op (the most expensive hover on the page). The
   shadow now lives on a pre-rendered `::after` layer that's always painted but
   sits at opacity 0; the hover only transitions its OPACITY (compositor-cheap),
   so the look is identical (soft shadow bleeding toward neighbours) with no
   repaint per frame. The card needs a stacking context for the layer to sit
   behind its content. */
.motion-ready .review-card { position: relative; }
.motion-ready .review-card::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  box-shadow:
    0 30px 60px -34px rgba(0, 0, 0, 0.62),
    0 10px 26px -18px rgba(0, 0, 0, 0.45);
  transition: opacity 360ms var(--ease-out);
}
.motion-ready .review-card:hover {
  transform: translate3d(0, -0.16rem, 0) scale(1.04);
  z-index: 4;
  border-color: rgba(236, 233, 227, 0.42);
}
.motion-ready .review-card:hover::after { opacity: 1; }

.motion-ready [data-motion-depth] {
  will-change: transform;
}

/* Drop the reveal GPU hint once the element has revealed (Jun 20). base.css sets
   `will-change: opacity, transform` on every `.js [data-reveal]` so the reveal
   itself composites smoothly, but it never cleared the hint afterward -- leaving
   dozens of retained compositor layers (real VRAM) at rest on long pages. Once a
   reveal finishes it carries `.is-in`; clear the hint there. Loaded after
   base.css, so this wins on source order. (initSectionReveals mirrors this for
   transform via clearProps; this covers the persistent will-change.) */
.js [data-reveal].is-in {
  will-change: auto;
}

/* Hero scope rail — ZERO hover fx (David, Jun 20: "don't want any hover fx at
   all on it"). sections.css pauses .scope-rail__track on :hover/:focus-within;
   override it so the word rail keeps scrolling, untouched by the cursor. This is
   the hero word rail only (the services strip marquee was already removed). */
.scope-rail:hover .scope-rail__track,
.scope-rail:focus-within .scope-rail__track {
  animation-play-state: running;
}

/* Tile-stone side labels stay visible without motion (gsap never hides them). */
.motion-static #tile-stone .tilestone__side,
.is-solo #tile-stone .tilestone__side,
.is-reduced-motion #tile-stone .tilestone__side {
  opacity: 1;
  transform: none;
}
