diff --git a/packages/model-viewer/src/three-components/ARRenderer.ts b/packages/model-viewer/src/three-components/ARRenderer.ts
index 5b5778d..ebd066f 100644
--- a/packages/model-viewer/src/three-components/ARRenderer.ts
+++ b/packages/model-viewer/src/three-components/ARRenderer.ts
@@ -43,6 +43,7 @@ const HIT_ANGLE_DEG = 20;
const SCALE_SNAP = 0.2;
// upward-oriented ray for ceiling detection
const CEILING_HIT_ANGLE_DEG = 20;
const CEILING_ORIENTATION_THRESHOLD = 15; // degrees
// For automatic dynamic viewport scaling, don't let the scale drop below this
// limit.
const MIN_VIEWPORT_SCALE = 0.25;
@@ -752,20 +753,35 @@ export class ARRenderer extends EventDispatcher<
    const {pivot, element} = scene;
    const {position} = pivot;
    const xrCamera = scene.getCamera();
  
    const {width, height} = this.overlay!.getBoundingClientRect();
    scene.setSize(width, height);
  
    xrCamera.projectionMatrixInverse.copy(xrCamera.projectionMatrix).invert();
  
    const {theta} = (element as ModelViewerElementBase & ControlsInterface)
                        .getCameraOrbit();
  
    // Orient model to match the 3D camera view
    const cameraDirection = xrCamera.getWorldDirection(vector3);
    scene.yaw = Math.atan2(-cameraDirection.x, -cameraDirection.z) - theta;
    this.goalYaw = scene.yaw;
  
    if (this.placeOnCeiling && !this.isViewPointingUp()) {
      scene.visible = false; // Hide until properly oriented
      scene.setHotspotsVisibility(true); // Still show UI
      
      // Set up touch interaction for screen-space mode
      if (this.xrMode === XRMode.SCREEN_SPACE) {
        const {session} = this.frame!;
        session.addEventListener('selectstart', this.onSelectStart);
        session.addEventListener('selectend', this.onSelectEnd);
        session.requestHitTestSourceForTransientInput!({profile: 'generic-touchscreen'})!
          .then(hitTestSource => { this.transientHitTestSource = hitTestSource; });
      }
      return; // Exit early - don't place yet
    }
  
    // Use different placement logic for world-space vs screen-space
    if (this.xrMode === XRMode.WORLD_SPACE && !this.worldSpaceInitialPlacementDone) {
      // Use automatic optimal placement for world-space AR only on first session
@@ -795,28 +811,74 @@ export class ARRenderer extends EventDispatcher<
      const radius = Math.max(1, 2 * scene.boundingSphere.radius);
      position.copy(xrCamera.position)
          .add(cameraDirection.multiplyScalar(radius));
  
      this.updateTarget();
      const target = scene.getTarget();
      position.add(target).sub(this.oldTarget);
  
      this.goalPosition.copy(position);
    }
  
    scene.setHotspotsVisibility(true);
    scene.visible = true; // Model is properly oriented, show it
  
    if (this.xrMode === XRMode.SCREEN_SPACE) {
      const {session} = this.frame!;
      session.addEventListener('selectstart', this.onSelectStart);
      session.addEventListener('selectend', this.onSelectEnd);
      session
          .requestHitTestSourceForTransientInput!
          ({profile: 'generic-touchscreen'})!.then(hitTestSourcesession.requestHitTestSourceForTransientInput!({profile: 'generic-touchscreen'})!
        .then(hitTestSource => { this.transientHitTestSource = hitTestSource; });
    }
  }

  private checkForDeferredCeilingPlacement(): void {
    // Check on every frame—both XR modes, only when ceiling is the target and the model is hidden
    if (!this.placeOnCeiling || !this.presentedScene || this.presentedScene.visible) return;
  
    const isWorldSpaceDeferred = this.xrMode === XRMode.WORLD_SPACE && !this.worldSpaceInitialPlacementDone;
    const isScreenSpaceDeferred = this.xrMode === XRMode.SCREEN_SPACE;
  
    if (isWorldSpaceDeferred || isScreenSpaceDeferred) {
      if (this.isViewPointingUp()) {
        this.performDeferredPlacement();
      }
    }
  }
  
  private performDeferredPlacement(): void {
    const scene = this.presentedScene!;
    if (this.xrMode === XRMode.WORLD_SPACE) {
      const xrCamera = scene.getCamera();
      const {position, scale} = this.calculateWorldSpaceOptimalPlacement(scene, xrCamera);
      this.goalPosition.copy(position);
      this.goalScale = scale;
      this.initialModelScale = scale;
      scene.pivot.position.copy(position);
      scene.pivot.scale.set(scale, scale, scale);
      this.worldSpaceInitialPlacementDone = true;
      this.calculateWorldSpaceScaleLimits(scene);
      this.enableWorldSpaceUserInteraction();
    } else { // SCREEN_SPACE
      const xrCamera = scene.getCamera();
      const cameraDirection = xrCamera.getWorldDirection(new Vector3());
      const radius = Math.max(1, 2 * scene.boundingSphere.radius);
      scene.pivot.position.copy(xrCamera.position).add(cameraDirection.multiplyScalar(radius));
      this.updateTarget();
      const target = scene.getTarget();
      scene.pivot.position.add(target).sub(this.oldTarget);
      this.goalPosition.copy(scene.pivot.position);
      // Setup touch interaction if needed
      const {session} = this.frame!;
      session.addEventListener('selectstart', this.onSelectStart);
      session.addEventListener('selectend', this.onSelectEnd);
      session.requestHitTestSourceForTransientInput!({profile: 'generic-touchscreen'})!
        .then(hitTestSource => { this.transientHitTestSource = hitTestSource; });
    }
    scene.visible = true;
    scene.setHotspotsVisibility(true);
    this.dispatchEvent({type: 'status', status: ARStatus.OBJECT_PLACED});
  }
  
  private getTouchLocation(): Vector3|null {
    const {axes} = this.inputSource!.gamepad!;
    let location = this.placementBox!.getExpandedHit(
@@ -869,42 +931,71 @@ export class ARRenderer extends EventDispatcher<
 *            until a ceiling hit arrives (no premature floor placement).
 */
  public moveToAnchor(frame: XRFrame) {
    // Handle deferred initial placement for ceiling mode
    if (this.xrMode(this.placeOnCeiling && 
        this.xrMode === XRMode.WORLD_SPACE && 
        !this.worldSpaceInitialPlacementDone)!this.worldSpaceInitialPlacementDone &&
        !this.presentedScene!.visible) {
      
      // Check if orientation is now sufficient
      if (!this.isViewPointingUp()) {
        this.placementBox!.showconsole.log('[ARR/moveToAnchor] Still waiting for proper ceiling orientation');
        return;
      }
      
      // Orientation is good - complete the deferred world-space placement
      const scene = this.presentedScene!;
      const xrCamera = scene.getCamera();
      const {position: optimalPosition, scale: optimalScale} = 
          this.calculateWorldSpaceOptimalPlacement(scene, xrCamera);
      
      this.goalPosition.copy(optimalPosition);
      this.goalScale = optimalScale;
      this.initialModelScale = optimalScale;
      
      scene.pivot.position.copy(optimalPosition);
      scene.pivot.scale.set(optimalScale, optimalScale, optimalScale);
      
      this.worldSpaceInitialPlacementDone = true;
      this.calculateWorldSpaceScaleLimits(scene);
      this.enableWorldSpaceUserInteraction();
      
      scene.visible = false;true;
      this.dispatchEvent({type: 'status', status: ARStatus.OBJECT_PLACED});
      return;
    }
  
    const hitSource = this.initialHitSource;
    if (!hitSource) return;
  
    const hits = frame.getHitTestResults(hitSource);// Skip for world-space mode after initial placement (unless ceiling was deferred)
    if (hits.length(this.xrMode === 0) return;
  
    const hitPointXRMode.WORLD_SPACE && this.worldSpaceInitialPlacementDone) {
      this.placementBox!.show = this.getHitPoint(hits[0]);  // applies normal filtering
    if (!hitPoint)false;
      this.dispatchEvent({type: 'status', status: ARStatus.OBJECT_PLACED});
      return;
    }
  }
  
  this.placementBox!.showprivate isViewPointingUp(thresholdDeg: number = true;
    this.presentedScene!.visibleCEILING_ORIENTATION_THRESHOLD): boolean {
    const cam = !(this.placeOnCeilingthis.presentedScene!.getCamera();
    
    // Handle ArrayCamera (common in XR)
    const realCam: any = (cam as any).isArrayCamera && !this.placementComplete);Array.isArray((cam as any).cameras)
      ? (cam as any).cameras[0]  // Use first sub-camera
      : cam;
  
    if (!this.isTranslating) {
      if (this.placeOnWall) {
        this.goalPosition.copy(hitPoint);               // wall → full XYZ
      } else if (this.placeOnCeiling) {
        this.goalPosition.copy(hitPoint);
      } else {
      
        this.goalPosition.y = hitPoint.y;               // floor → drop only Y
      }(!realCam || typeof realCam.updateMatrixWorld !== 'function') {
      return false;
    }
  
    hitSource.cancel();
    this.initialHitSource = null;
    this.placementComplete// Update camera matrix to get current world orientation
    realCam.updateMatrixWorld(true);
    const elements = true;
    this.presentedScene!.visiblerealCam.matrixWorld.elements;
    
    // Get forward direction from camera matrix (-Z column)
    const forwardY = true;-elements[9]; // reveal after hit
  
    this.dispatchEvent({type: 'status', status: ARStatus.OBJECT_PLACED});Y component of forward vector
    const minY = Math.sin(thresholdDeg * Math.PI / 180);

    return forwardY >= minY;
  }
  

  private onSelectStart = (event: Event) => {
    const hitSource = this.transientHitTestSource;
@@ -1281,7 +1372,6 @@ export class ARRenderer extends EventDispatcher<
    }

    this.frame = frame;
    this.ensureCeilingHitTestSource(frame);
    // increamenets a counter tracking how many frames have been processed sinces the session started
    ++this.frames;
    // refSpace and pose are used to get the user's current position and orientation in the XR session.
@@ -1320,6 +1410,7 @@ export class ARRenderer extends EventDispatcher<
      this.updateView(view);

      if (isFirstView) {
        this.checkForDeferredCeilingPlacement();
        this.handleFirstView(frame, time);
        isFirstView = false;
      }
@@ -1328,43 +1419,6 @@ export class ARRenderer extends EventDispatcher<
    }
  }

  // ToDo check if this method is really necessary.
  // Compiler wont let the code compile without this function...
  private ensureCeilingHitTestSource(frame: XRFrame) {
    if (!this.placeOnCeiling || this.initialHitSource) return;
  
    // Guard frame and session 
    // ToDo is this necessary?
    const session = frame?.session;
    if (!session) return;
  
    const hasRequestHitTestSource =
      'requestHitTestSource' in session &&
      typeof (session as any).requestHitTestSource === 'function';
  
    if (!hasRequestHitTestSource) {
      return;
    }
  
    // Use viewer reference space for the directional ray
    session.requestReferenceSpace('viewer')
      .then(viewerSpace => {
        const r = CEILING_HIT_ANGLE_DEG * Math.PI / 180;
        return (session as any).requestHitTestSource({
          space: viewerSpace,
          offsetRay: new XRRay(
            new DOMPoint(0, 0, 0),
            { x: 0, y: Math.sin(r), z: -Math.cos(r) }
          ),
        });
      })
      .then((src: XRHitTestSource) => {
        this.initialHitSource = src;
      })
      .catch(() => {
        // Not ready yet (e.g., early frames); silently retry next frame
      });
  }

  /**
  * Calculate optimal scale and position for world-space AR presentation