@layer layout {

  html:has(.viewer),
  html:has(.viewer) body {
    height: 100%;
    overflow: hidden;
    overscroll-behavior: none;
    touch-action: manipulation;
    /* Solid colour first: Safari tints its toolbar / bottom inset from it (white without one). */
    background: var(--color-canvas) radial-gradient(ellipse at 45% 40%, var(--color-canvas-glow), var(--color-canvas)) no-repeat;
  }

  /* Large-viewport height (+ the iOS home-screen shortfall) so the scene also paints
     behind Safari's bottom toolbar area, which a fixed inset: 0 box stops short of. */
  .viewer__stage,
  .viewer__labels {
    position: fixed;
    top: 0;
    left: 0;
    right: var(--panel-width);
    height: 100vh;
    height: 100lvh;
  }

  .viewer__stage canvas {
    display: block;
  }

  .viewer__labels {
    pointer-events: none;

    /* Each label its own compositor layer, sealed off from the rest: three moves every one each frame
       (CSS2DRenderer), which otherwise repaints the lot — on a big house it halved the frame rate. */
    &>* {
      will-change: transform;
      contain: layout style paint;
    }
  }

  /* Over the 3D view (left of the panel), three columns: the side (HUD, tools, rooms) | workspace
     tabs | gizmo. It lets clicks through to the scene; only its controls take them. */
  .viewer__top {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: var(--panel-width);
    z-index: 5;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: start;
    gap: 12px;
    padding: calc(12px + env(safe-area-inset-top)) 12px calc(12px + env(safe-area-inset-bottom)) calc(14px + env(safe-area-inset-left));
    pointer-events: none;

    & button {
      pointer-events: auto;
    }
  }

  /* The left column, top to bottom of the view: HUD, the drawing tools, then (pushed down) the rooms
     and the floor layout. The room list gives way when the screen is short. */
  .viewer__side {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    min-height: 0;
  }

  .viewer__side-end {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    min-height: 0;
    margin-top: auto;

    &>* {
      pointer-events: auto;
    }
  }

  /* Navigation gizmo (and, on phones, the panel button), in the row's right column. */
  .viewer__corner {
    grid-column: 3;
    justify-self: end;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
  }

  /* The walls' look, left of the gizmo, level with its top. */
  .viewer__corner-top {
    display: flex;
    align-items: flex-start;
    gap: 8px;
  }

  .viewer__hud {
    text-shadow: 0 1px 2px color-mix(in oklch, var(--black) 60%, transparent);
  }

  .viewer__view-name {
    font-size: 14px;
  }

  /* Which room is focused; a click (or / or Esc) goes back to the whole floor. */
  .focus-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
    padding: calc(3px + var(--hairline-gap)) calc(10px + var(--hairline-gap));
    font-size: 12px;
    color: var(--color-ink);
    text-shadow: none;
    background: var(--color-primary-surface);
    border: var(--hairline) solid var(--color-primary);
    border-radius: 999px;
    cursor: pointer;
  }

  .focus-chip__exit {
    color: var(--color-ink-muted);
  }

  .viewer__hint {
    margin-top: 2px;
    color: var(--color-ink-muted);
    font-size: 12px;
  }

  /* An assistant at work on the house through the MCP tools (houses/_assistant): a pulse and its name. */
  .assistant-status {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-top: 6px;
    font-size: 12px;
    color: var(--color-ink);
  }

  .assistant-status__pulse {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-accent);
    animation: assistant-pulse 1.2s ease-in-out infinite;
  }

  @keyframes assistant-pulse {
    0%, 100% { opacity: 0.35; scale: 0.8; box-shadow: 0 0 0 0 color-mix(in oklch, var(--color-accent) 50%, transparent); }
    50% { opacity: 1; scale: 1; box-shadow: 0 0 0 5px color-mix(in oklch, var(--color-accent) 0%, transparent); }
  }

  @media (prefers-reduced-motion: reduce) {
    .assistant-status__pulse {
      animation: none;
    }
  }

  @media (max-width: 760px) {
    .viewer__hint {
      display: none;
    }

    .viewer__top {
      right: 0;
      padding: calc(10px + env(safe-area-inset-top)) calc(10px + env(safe-area-inset-right)) 0 calc(14px + env(safe-area-inset-left));
    }

    /* The panel opens full screen over the scene here, so the scene takes the whole width. */
    .viewer__stage,
    .viewer__labels {
      right: 0;
    }
  }
}
