/* ONLYDROP v355 — Crossfades only (no transitional zoom) for work backgrounds.
   The old display:none/block toggles exposed a bright intermediate frame.
   Keep scene layers mounted; use ease-in-out on both fade directions.
   Image sizing, header masking and scroll positioning remain unchanged. */
html body #views > :is(.od-art2d-backdrop,.od-animation-backdrop,.od-projects-backdrop){
  display:block!important;
  visibility:visible!important;
  opacity:0!important;
  transition:opacity 540ms cubic-bezier(.42,0,.58,1)!important;
  will-change:opacity;
  pointer-events:none!important;
}
html body #views:has(> #work.active[data-cat="art2d"]) > .od-art2d-backdrop{
  opacity:1!important;
}
html body #views:has(> #work.active:is([data-cat="animation2d"],[data-cat="animation3d"],[data-cat="storyboard"]))
  > .od-animation-backdrop{
  opacity:1!important;
}
html body #views:has(> #work.active[data-cat="projects"]) > .od-projects-backdrop{
  opacity:1!important;
}

/* Render both animation scenes at all times, even before the route changes.
   A dark fallback avoids blending partially transparent scenes into a
   temporary solid-white canvas. */
html body #views > .od-animation-backdrop{
  background:#0b1015!important;
}
html body #views > .od-animation-backdrop > .od-animation-bg-image{
  display:block!important;
  visibility:visible!important;
  background-color:transparent!important;
  transition:opacity 540ms cubic-bezier(.42,0,.58,1)!important;
}
html body #views > .od-animation-backdrop > .od-animation-bg-2d{
  background-image:url("assets/animation2d/background/BG%20Animation.png?v=252")!important;
  opacity:0!important;
}
html body #views > .od-animation-backdrop > .od-animation-bg-3d{
  background-image:url("assets/animation3d/background/BG%203D%20ANIMATION.png")!important;
  opacity:0!important;
}
html body #views:has(> #work.active:is([data-cat="animation2d"],[data-cat="storyboard"]))
  > .od-animation-backdrop > .od-animation-bg-2d{
  opacity:1!important;
}
html body #views:has(> #work.active[data-cat="animation3d"])
  > .od-animation-backdrop > .od-animation-bg-3d{
  opacity:1!important;
}

/* The original strong white 2D fade and delicate 3D fade are preserved,
   but their gradient changes now crossfade instead of swapping instantly. */
html body #views > .od-animation-backdrop > .od-animation-bottom-fade,
html body #views:has(> #work.active[data-cat="animation3d"])
  > .od-animation-backdrop > .od-animation-bottom-fade{
  display:block!important;
  height:clamp(110px,23%,300px)!important;
  opacity:1!important;
  background:none!important;
}
html body #views > .od-animation-backdrop > .od-animation-bottom-fade::before,
html body #views > .od-animation-backdrop > .od-animation-bottom-fade::after{
  content:"";
  display:block;
  position:absolute;
  left:0;
  right:0;
  bottom:0;
  pointer-events:none;
  transition:opacity 540ms cubic-bezier(.42,0,.58,1)!important;
}
html body #views > .od-animation-backdrop > .od-animation-bottom-fade::before{
  inset:0;
  background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,255,255,.52) 66%,#fff)!important;
  opacity:0;
}
html body #views > .od-animation-backdrop > .od-animation-bottom-fade::after{
  height:clamp(65px,12dvh,150px);
  background:linear-gradient(to bottom,
    rgba(255,255,255,0) 0%,
    rgba(255,255,255,.07) 55%,
    rgba(255,255,255,.22) 100%)!important;
  opacity:0;
}
html body #views:has(> #work.active:is([data-cat="animation2d"],[data-cat="storyboard"]))
  > .od-animation-backdrop > .od-animation-bottom-fade::before{
  opacity:1;
}
html body #views:has(> #work.active[data-cat="animation3d"])
  > .od-animation-backdrop > .od-animation-bottom-fade::after{
  opacity:1;
}

/* Project backdrops are exclusive: no inactive artwork can remain
   layered over another project. The entire backdrop still crossfades in/out
   of the Projects route within the original 320ms transition. */
html body #views > .od-projects-backdrop > .od-projects-bg{
  display:none!important;
  visibility:hidden!important;
  opacity:0!important;
  transition:none!important;
}
html body #views:has(> #work.active[data-cat="projects"][data-projects-mode="groove"])
  > .od-projects-backdrop > .od-projects-bg-groove,
html body #views:has(> #work.active[data-cat="projects"][data-projects-mode="devotus"])
  > .od-projects-backdrop > .od-projects-bg-devotus,
html body #views:has(> #work.active[data-cat="projects"][data-projects-mode="personal"])
  > .od-projects-backdrop > .od-projects-bg-personal{
  display:block!important;
  visibility:visible!important;
  opacity:1!important;
}

/* Keep the project content exclusive too, even if older grid declarations
   try to display another subsection. */
html body #views #work[data-cat="projects"][data-projects-mode="groove"]
  .od-projects-showcase > .od-project-view:not([data-project-view="groove"]),
html body #views #work[data-cat="projects"][data-projects-mode="devotus"]
  .od-projects-showcase > .od-project-view:not([data-project-view="devotus"]),
html body #views #work[data-cat="projects"][data-projects-mode="personal"]
  .od-projects-showcase > .od-project-view:not([data-project-view="personal"]){
  display:none!important;
}

/* The scroll header duplicates the currently selected wallpaper only. */
html body #views #work[data-cat="projects"][data-projects-mode="groove"]
  > .work-section > .od-work-top-occluder > .od-cover-project-bg:not(.od-cover-project-groove),
html body #views #work[data-cat="projects"][data-projects-mode="devotus"]
  > .work-section > .od-work-top-occluder > .od-cover-project-bg:not(.od-cover-project-devotus),
html body #views #work[data-cat="projects"][data-projects-mode="personal"]
  > .work-section > .od-work-top-occluder > .od-cover-project-bg:not(.od-cover-project-personal){
  display:none!important;
}
/* The previous Art 2D scroll effect and the foreground sticky occluder are
   untouched; only the independent backdrop layers are blended. */
@media(prefers-reduced-motion:reduce){
  html body #views > :is(.od-art2d-backdrop,.od-animation-backdrop,.od-projects-backdrop),
  html body #views > .od-animation-backdrop > .od-animation-bg-image,
  html body #views > .od-animation-backdrop > .od-animation-bottom-fade::before,
  html body #views > .od-animation-backdrop > .od-animation-bottom-fade::after,
  html body #views > .od-projects-backdrop > .od-projects-bg{
    transition:none!important;
    will-change:auto!important;
  }
}
html.motion-paused body #views > :is(.od-art2d-backdrop,.od-animation-backdrop,.od-projects-backdrop),
html.motion-paused body #views > .od-animation-backdrop > .od-animation-bg-image,
html.motion-paused body #views > .od-animation-backdrop > .od-animation-bottom-fade::before,
html.motion-paused body #views > .od-animation-backdrop > .od-animation-bottom-fade::after,
html.motion-paused body #views > .od-projects-backdrop > .od-projects-bg{
  transition:none!important;
  will-change:auto!important;
}

/* v357 — Keep the scrolling header mask's duplicate image out of the
   540ms scene crossfade. It cannot blend in parallel with the real backdrop:
   its background-image switches instantly at the 215ms route handoff.
   Fade it out with the old content, hold transparent until the new scene
   finishes, then let it settle back without moving the fixed menus. */
html body #views #work > .work-section > .od-work-top-occluder{
  opacity:1!important;
  transition:opacity 180ms cubic-bezier(.42,0,.58,1)!important;
}
html:not(.motion-paused) body #views #work.od-work-switching-out
  > .work-section > .od-work-top-occluder{
  opacity:0!important;
  transition:opacity 215ms cubic-bezier(.42,0,.58,1)!important;
}
html:not(.motion-paused) body #views #work:is(.od-cover-awaiting,.od-cover-suspended)
  > .work-section > .od-work-top-occluder{
  opacity:0!important;
  transition:none!important;
}
/* The mask still clips scrolled media in the resting state. The temporary
   transparency affects only route handoffs, not position, clip-path, or scroll. */
@media(prefers-reduced-motion:reduce){
  html body #views #work > .work-section > .od-work-top-occluder{
    transition:none!important;
  }
}
html.motion-paused body #views #work > .work-section > .od-work-top-occluder{
  transition:none!important;
}

/* v367 — True crossfades. Two elements at 50% over a dark canvas leave
   25% of that dark canvas visible. Instead, retain the outgoing wallpaper
   at full opacity while the incoming wallpaper fades 0 -> 1 above it.
   This produces an actual 50/50 image mix at the halfway point. */

/* Always order the currently selected scene ABOVE the inactive scenes,
   without ever crossing in front of the work content (z-index:2). */
html body #views > :is(.od-art2d-backdrop,.od-animation-backdrop,.od-projects-backdrop){
  z-index:0!important;
}
html body #views:has(> #work.active[data-cat="art2d"]) > .od-art2d-backdrop,
html body #views:has(> #work.active:is([data-cat="animation2d"],[data-cat="animation3d"],[data-cat="storyboard"])) > .od-animation-backdrop,
html body #views:has(> #work.active[data-cat="projects"]) > .od-projects-backdrop{
  z-index:1!important;
}

/* Outgoing category keeps its opacity at 1 until arrival is complete.
   Selectors deliberately cover the exact state saved before setView(). */
html body #views[data-od-backdrop-from="art2d"] > .od-art2d-backdrop,
html body #views:is([data-od-backdrop-from="animation2d"],[data-od-backdrop-from="animation3d"],[data-od-backdrop-from="storyboard"]) > .od-animation-backdrop,
html body #views[data-od-backdrop-from="projects"] > .od-projects-backdrop{
  opacity:1!important;
}

/* The two animation images share one wallpaper layer: when crossing 2D
   (also Storyboard) and 3D, use the same opaque-under/translucent-over
   strategy for their individual image elements. */
html body #views > .od-animation-backdrop > :is(.od-animation-bg-2d,.od-animation-bg-3d){
  z-index:0!important;
}
html body #views:has(> #work.active:is([data-cat="animation2d"],[data-cat="storyboard"]))
  > .od-animation-backdrop > .od-animation-bg-2d,
html body #views:has(> #work.active[data-cat="animation3d"])
  > .od-animation-backdrop > .od-animation-bg-3d{
  z-index:1!important;
}
html body #views:is([data-od-backdrop-from="animation2d"],[data-od-backdrop-from="storyboard"])
  > .od-animation-backdrop > .od-animation-bg-2d,
html body #views[data-od-backdrop-from="animation3d"]
  > .od-animation-backdrop > .od-animation-bg-3d{
  opacity:1!important;
}
/* The entering animation image remains at its normal CSS-driven opacity
   transition, now on top of the preserved source image. */

/* v368 — Full route coverage: never fade BOTH a wallpaper container and its
   child image when entering Animation from a different category. That nested
   multiplication gives only 25% of the new art at the visual midpoint. */
html body #views:is(
  [data-od-backdrop-from="art2d"],
  [data-od-backdrop-from="projects"],
  [data-od-backdrop-from="home"],
  [data-od-backdrop-from="about"],
  [data-od-backdrop-from="contact"]
) > .od-animation-backdrop > .od-animation-bg-image,
html body #views:not([data-od-backdrop-from]) > .od-animation-backdrop > .od-animation-bg-image{
  transition:none!important;
}
/* When an animation scene is the destination of a cross-category handoff,
   the inner art is already fully visible underneath its fading outer layer. */
html body #views:has(> #work.active:is([data-cat="animation2d"],[data-cat="storyboard"]))
  > .od-animation-backdrop > .od-animation-bg-2d,
html body #views:has(> #work.active[data-cat="animation3d"])
  > .od-animation-backdrop > .od-animation-bg-3d{
  opacity:1!important;
}

/* Project subpages: persistent wallpapers crossfade using the same rule as
   category backgrounds. The outgoing project remains fully visible BELOW
   the new project, instead of disappearing at the 200ms handoff. */
html body #views > .od-projects-backdrop > .od-projects-bg{
  display:block!important;
  visibility:visible!important;
  opacity:0!important;
  transition:opacity 340ms cubic-bezier(.42,0,.58,1)!important;
  z-index:0!important;
}
html body #views:has(> #work.active[data-cat="projects"][data-projects-mode="groove"])
  > .od-projects-backdrop > .od-projects-bg-groove,
html body #views:has(> #work.active[data-cat="projects"][data-projects-mode="devotus"])
  > .od-projects-backdrop > .od-projects-bg-devotus,
html body #views:has(> #work.active[data-cat="projects"][data-projects-mode="personal"])
  > .od-projects-backdrop > .od-projects-bg-personal{
  display:block!important;
  visibility:visible!important;
  opacity:1!important;
  z-index:1!important;
}
html body #views:has(> #work.active[data-od-project-from="groove"])
  > .od-projects-backdrop > .od-projects-bg-groove,
html body #views:has(> #work.active[data-od-project-from="devotus"])
  > .od-projects-backdrop > .od-projects-bg-devotus,
html body #views:has(> #work.active[data-od-project-from="personal"])
  > .od-projects-backdrop > .od-projects-bg-personal{
  opacity:1!important;
}
/* Remove the previous dark-cover flash; keep the designed overlay steady. */
html body #views:has(> #work.active.od-projects-changing)
  > .od-projects-backdrop::after,
html body #views #work.active[data-cat="projects"].od-projects-changing
  > .work-section > .od-work-top-occluder::after{
  background-color:rgba(4,7,12,.43)!important;
}
/* Prevent the header's duplicate project image from snapping mid-transition. */
html:not(.motion-paused) body #views #work.active.od-projects-changing
  > .work-section > .od-work-top-occluder{
  opacity:0!important;
  transition:opacity 180ms cubic-bezier(.42,0,.58,1)!important;
}
@media(prefers-reduced-motion:reduce){
  html body #views > .od-projects-backdrop > .od-projects-bg{
    transition:none!important;
  }
}
html.motion-paused body #views > .od-projects-backdrop > .od-projects-bg{
  transition:none!important;
}

/* v369 — Home -> every section must crossfade over the actual Home scene.
   setView() deactivates #home immediately, otherwise exposing the dark
   #views canvas beneath the incoming background during its first 540ms. */
html body #views[data-od-home-hold] > #home.view-panel:not(.active){
  opacity:1!important;
  visibility:visible!important;
  transform:none!important;
  translate:none!important;
  filter:none!important;
  z-index:0!important;
  pointer-events:none!important;
  animation:none!important;
  transition:none!important;
}
/* The work background layers are already at z-index:1 (above Home at 0)
   and the content remains at z-index:2. No change to menu positions,
   image crops, scroll dimensions or foreground animations is needed. */

/* About and Contact do not use a separate wallpaper layer; their full
   destination panel performs the same 540ms overlay fade over Home. */
@keyframes odHomeToInfo369{
  from{opacity:0}
  to{opacity:1}
}
html:not(.motion-paused) body #views[data-od-home-hold] > :is(#about,#contact).active{
  animation:odHomeToInfo369 540ms cubic-bezier(.42,0,.58,1) both!important;
}
@media(prefers-reduced-motion:reduce){
  html body #views[data-od-home-hold] > :is(#about,#contact).active{
    animation:none!important;
  }
}

/* v370 — Home navigation is a two-stage sequence:
   (1) images crossfade for 540ms with zero destination interface;
   (2) the stationary interface fades in after the image is settled.
   Target only section chrome and content, NOT the backdrop layer nor
   the pinned occluder that handles scrolling. */
html:not(.motion-paused) body #views.od-home-ui-pending > #work.active > .work-section > :not(.od-work-top-occluder){
  opacity:0!important;
  animation:none!important;
  transition:none!important;
}
/* The separate global discipline rail also belongs to the new interface. */
html:not(.motion-paused).od-home-ui-pending body .od-rail{
  opacity:0!important;
  animation:none!important;
  transition:none!important;
}
@keyframes odHomeInterfaceReveal370{
  from{opacity:0}
  to{opacity:1}
}
html:not(.motion-paused) body #views.od-home-ui-revealing > #work.active > .work-section > :not(.od-work-top-occluder),
html:not(.motion-paused).od-home-ui-revealing body .od-rail{
  animation:odHomeInterfaceReveal370 320ms cubic-bezier(.42,0,.58,1) both!important;
}
/* No transforms, width, position or alignment changes: only visibility. */
@media(prefers-reduced-motion:reduce){
  html body #views.od-home-ui-pending > #work.active > .work-section > :not(.od-work-top-occluder){
    opacity:1!important;
  }
}

/* v381 — Original Work backdrops are restored as the permanent visual
   source. Two of the five already-mounted image scenes are displayed only
   during Work-to-Work navigation, translated edge-to-edge at 100vh. */
html body #views > .od-vertical-stage{
  position:absolute!important;inset:0!important;
  width:100%!important;height:100%!important;
  z-index:1!important;overflow:hidden!important;
  background:transparent!important;
  isolation:isolate!important;pointer-events:none!important;
  display:block!important;opacity:0!important;
  visibility:hidden!important;
  transition:none!important;
}
html body #views > .od-vertical-stage.od-vertical-stage-live{
  visibility:visible!important;opacity:1!important;
}
html body #views > .od-vertical-stage > .od-vertical-strip{
  position:absolute!important;inset:0!important;
  width:100%!important;height:100%!important;
  display:block!important;transform:none!important;
  filter:none!important;will-change:auto!important;
}
html body #views .od-vertical-scene{
  position:absolute!important;inset:0!important;
  width:100%!important;height:100%!important;
  display:block!important;
  overflow:hidden!important;isolation:isolate!important;
  opacity:1!important;
  background:transparent;
  transform:translate3d(0,130%,0);
  pointer-events:none!important;
  visibility:hidden!important;
}
html body #views .od-vertical-scene:is(.od-vertical-scene-current,.od-vertical-scene-next){
  visibility:visible!important;
}
html body #views .od-vertical-scene[data-scene="art2d"]{
  background:#fff!important;
}
html body #views .od-vertical-scene[data-scene="projects"]{
  background:#090a0f!important;
}
html body #views .od-vertical-animation-art{
  display:block!important;position:absolute!important;inset:0!important;
  width:100%!important;height:100%!important;
  object-fit:cover!important;object-position:center!important;
  background:none!important;
}
html body #views .od-vertical-animation-fade{
  position:absolute;left:0;right:0;bottom:0;
  height:clamp(110px,23%,300px);
  background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,255,255,.52) 66%,#fff);
}
html body #views .od-vertical-scene[data-scene="animation3d"] .od-vertical-animation-fade{
  height:clamp(65px,12%,150px);
  background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,255,255,.07) 55%,rgba(255,255,255,.22));
}
html body #views .od-vertical-scene[data-scene="storyboard"]::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:rgba(5,8,14,.055);
}
html body #views .od-vertical-art{
  display:block!important;position:absolute!important;
  inset:0 auto auto 0!important;width:100%!important;
  max-width:none!important;height:auto!important;
  transform:translate3d(0,var(--od-art-bg-translate,0px),0);
}
html body #views .od-vertical-art-fade{
  position:absolute;left:0;right:0;bottom:0;
  height:clamp(160px,35%,420px);
  background:linear-gradient(to bottom,rgba(255,255,255,0) 0%,rgba(255,255,255,.12) 25%,rgba(255,255,255,.58) 67%,#fff);
}
html body #views .od-vertical-project-art{
  display:block!important;position:absolute!important;
  inset:-8%!important;width:116%!important;height:116%!important;
  object-fit:cover!important;object-position:center!important;
  transform:scale(1.06)!important;
  filter:blur(38px) brightness(.95) saturate(.85)!important;
  background:none!important;
}
html body #views .od-vertical-scene[data-scene="projects"]::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:rgba(4,7,12,.43);
}
/* The original three CSS backdrops are NOT hidden here. They are always
   visible for Work routes. The sliding scenes simply paint above them. */
html body #views.od-vertical-transitioning > :is(.od-art2d-backdrop,.od-animation-backdrop,.od-projects-backdrop),
html body #views.od-vertical-transitioning > .od-animation-backdrop > .od-animation-bg-image{
  transition:opacity 540ms cubic-bezier(.42,0,.58,1)!important;
}
@media(prefers-reduced-motion:reduce){
  html body #views > .od-vertical-stage{display:none!important}
}

/* v382 — The upper clipping mask must remain visible at every frame.
   Its mirrored viewport duplicates the exact backdrop scene positions and
   animations rather than showing an unrelated static wallpaper. */
html body #views #work.active > .work-section > .od-work-top-occluder:has(.od-vertical-cover-mirror){
  opacity:1!important;
  transition:none!important;
}
html body #views #work .od-work-top-occluder > .od-vertical-cover-mirror{
  position:absolute!important;
  overflow:hidden!important;
  isolation:isolate!important;
  z-index:4!important;
  pointer-events:none!important;
  background:transparent!important;
}
html body #views .od-vertical-cover-mirror > .od-vertical-scene{
  position:absolute!important;
  inset:0!important;
  width:100%!important;
  height:100%!important;
  overflow:hidden!important;
}
/* White bottom gradients belong to the viewport, not to either sliding
   image. The same applies to Art 2D's stronger stationary fade. */
html body #views .od-vertical-stage .od-vertical-animation-fade,
html body #views .od-vertical-stage .od-vertical-art-fade,
html body #views .od-vertical-cover-mirror .od-vertical-animation-fade,
html body #views .od-vertical-cover-mirror .od-vertical-art-fade{
  display:none!important;
}
html body #views > .od-vertical-fixed-fade{
  position:absolute!important;inset:0!important;
  width:100%!important;height:100%!important;
  pointer-events:none!important;
  visibility:hidden!important;opacity:0!important;
  z-index:1!important;
  overflow:hidden!important;
}
html body #views.od-vertical-transitioning > .od-vertical-fixed-fade{
  visibility:visible!important;opacity:1!important;
}
html body #views .od-vertical-fixed-fade > div{
  position:absolute!important;left:0!important;
  right:0!important;bottom:0!important;
  width:100%!important;pointer-events:none!important;
}
html body #views .od-vertical-fixed-fade > [data-tone="strong"]{
  height:clamp(110px,23%,300px)!important;
  background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,255,255,.52) 66%,#fff)!important;
}
html body #views .od-vertical-fixed-fade > [data-tone="art"]{
  height:clamp(160px,35%,420px)!important;
  background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,255,255,.12) 25%,rgba(255,255,255,.58) 67%,#fff)!important;
}
html body #views .od-vertical-fixed-fade > [data-tone="soft"]{
  height:clamp(65px,12%,150px)!important;
  background:linear-gradient(to bottom,rgba(255,255,255,0),rgba(255,255,255,.07) 55%,rgba(255,255,255,.22))!important;
}
html body #views .od-vertical-fixed-fade > [data-tone="none"]{
  height:0!important;background:none!important;
}
