/**
 * Salesy storefront chat — the search-bar popup shell (0.17.0, ADR 0027;
 * ADR 0028 for the move from full screen to an anchored popup; ADR 0033 for
 * the shell's own floating launcher and its panel-matching layout).
 *
 * A conversation panel that COVERS the store's own search bar, at one fixed
 * size. The store's search bar is what opens it; the floating chat button on
 * the same page belongs to the panel shell, mounted alongside this one
 * (ADR 0034), and the single rule below that touches `.salesy-toggle` is
 * about getting that button out of the way at phone widths, not about owning
 * it.
 *
 * Everything INSIDE the popup is widget-core.css. This file frames it.
 *
 * The same three isolation mechanisms bind here as in core — every rule scoped
 * `#salesy-root …`, `!important` on any forced property the reset would
 * otherwise zero, and a priority-9999 enqueue. See widget-core.css's header.
 *
 * This file satisfies core's one contract: `.salesy-popup-frame` declares
 * `container-type: inline-size`, which is what makes core's `@container`
 * queries — the intro's two-column switch and the collage fan — match at all.
 * Without it the opening screen stays in its narrow layout at every width, and
 * nothing anywhere reports a problem.
 */

/* ── The box (ADR 0028) ────────────────────────────────────────────────────
   One fixed size, borrowed from the panel's own "expanded" preset — the
   popup is never resized or toggled, so there is exactly one width/height
   pair and no size-class mechanism to swap it. `top`/`left` come from
   `positionPopup()` in widget-shell-overlay.js, which measures the search bar
   and writes them as validated custom properties, the same discipline the
   old clip-path reveal's geometry answered to (0.15.0). */
#salesy-root.salesy-shell-overlay {
  --salesy-popup-width: 1040px;
  --salesy-popup-height: 720px;
}

#salesy-root .salesy-popup {
  position: fixed;
  top: var(--salesy-popup-top, 20px);
  left: var(--salesy-popup-left, 20px);
  width: var(--salesy-popup-width);
  height: var(--salesy-popup-height);
  max-width: calc(100vw - 2 * var(--salesy-offset-side));
  max-height: calc(100vh - 2 * var(--salesy-offset-bottom));
  max-height: calc(100dvh - 2 * var(--salesy-offset-bottom));
  z-index: 2147483000;
  display: flex;
  flex-direction: column;
  background: var(--salesy-surface);
  border: 1px solid rgba(17, 24, 39, 0.06);
  border-radius: var(--salesy-radius-panel);
  box-shadow: var(--salesy-shadow-panel);
  overflow: hidden;
  /* The intro's one/two-column switch keys off the FRAME's width — see
     `.salesy-popup-frame` below — not the popup's; container-type belongs on
     the frame for that reason, this box only needs its own visual treatment.
     The fallback value on every `var(...)` above is what applies before the
     popup has ever been positioned, or if a synthesized event left it
     unmeasurable — a static corner near the bar's usual position beats no
     box at all. */

  /* Shut: out of the accessibility tree and out of the way of clicks, the
     same convention core's `salesy-hidden` uses elsewhere — except this class
     transitions, which `display: none` cannot (see OPEN_STATE_CLASS in the
     JS file for why `visibility` carries that instead). The slight scale is a
     SETTLE, not an unfold — there is no shape to grow from once the popup
     covers the bar rather than opening beside it, just a short arrival
     exactly where the bar already was. No `translateY`: there is no more
     above/below distinction to signal a direction for. */
  visibility: hidden;
  pointer-events: none;
  opacity: 0;
  transform: scale(0.98);
  transition:
    opacity 180ms cubic-bezier(0.3, 0, 0.8, 0.15),
    transform 180ms cubic-bezier(0.3, 0, 0.8, 0.15),
    visibility 0s linear 180ms;
}

#salesy-root .salesy-popup--open {
  visibility: visible;
  pointer-events: auto;
  opacity: 1;
  transform: none;
  transition:
    opacity 160ms cubic-bezier(0.05, 0.7, 0.1, 1),
    transform 160ms cubic-bezier(0.05, 0.7, 0.1, 1),
    visibility 0s;
}

/* Asked for less motion: the popup still arrives, just without the fade or
   the settle — visibility alone is what makes it appear and disappear. */
@media (prefers-reduced-motion: reduce) {
  #salesy-root .salesy-popup,
  #salesy-root .salesy-popup--open {
    transform: none;
    transition: visibility 0s;
  }
}

/* The control strip. No title and no store name: the shopper just came from
   this store's own search bar and knows where they are — the row exists for
   the two controls and for the space above the conversation. */
#salesy-root .salesy-popup-bar {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  padding: 14px 20px 4px;
}

/* The conversation's frame — log first, delivery/cart panels, then the
   composer cluster last (ADR 0033; the same order the panel's and sidebar's
   frames use — see the JS file's `attachSurface()`).
   `min-height: 0` is load-bearing for the same reason it is on the log: a
   flex item defaults to min-height auto, so without it the log refuses to
   shrink and is pushed past the bottom of the box instead of scrolling.
   `container-type` lives here rather than on `.salesy-popup` because core's
   `@container` queries key off the conversation's own rendered width. */
#salesy-root .salesy-popup-frame {
  display: flex;
  flex: 1;
  min-height: 0;
  flex-direction: column;
  container-type: inline-size;
}

/* The close glyph is a dash now, not a cross (ADR 0033) — the same size the
   panel's and sidebar's own `.salesy-close` rules use, for the same reason:
   this minimises the popup rather than ending anything, and the conversation
   survives it. */
#salesy-root .salesy-close {
  font-size: 20px !important;
}

/* Below the tablet breakpoint the popup becomes the screen — an anchored
   1040×720 box has nowhere sensible to sit on a phone, so it takes over
   exactly the way the panel already does below this width (both files state
   the number independently; see widget-shell-panel.css's header for why).
   `inset: 0` alone pins all four sides — the JS-computed `top`/`left` custom
   properties no longer describe anything meaningful once it does, but they
   need no separate override: an explicit `top: auto; left: auto` here was
   tried once and is exactly the bug this comment now warns against — inset's
   shorthand already sets `top`/`left` to `0`, and two more literal
   declarations for the same properties, later in the same rule, would win
   over it and undo two of the four sides. Without them the box anchored only
   by `right: 0; bottom: 0`, with `width`/`height: auto` shrinking it to its
   own content instead of filling the viewport — a corner-docked sliver of
   character-wrapped text, not a full screen. */
@media (max-width: 767px) {
  #salesy-root .salesy-popup {
    position: fixed;
    inset: 0;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    border: 0;
    border-radius: 0;
  }

  #salesy-root .salesy-popup-bar {
    padding: calc(10px + env(safe-area-inset-top)) 14px 4px;
  }

  /* The floating chat button belongs to the PANEL shell, which since ADR
     0042 is not even mounted while this one is (the two are mutually
     exclusive again) — so in the common case this rule has nothing to hide.
     It stays for the one moment it briefly could: right before
     `disableSearchAi()` unmounts this shell and the panel takes over, the
     same rule, for the same reason, that widget-shell-panel.css applies to
     its own launcher at this width, so neither shell floats a button on top
     of the very conversation it is in the middle of handing off.
     `.salesy-open` is set by `open()` and cleared by `close()`/`conceal()` in
     widget-shell-overlay.js, and the rule is stated HERE rather than
     borrowed from the panel's stylesheet because a shell must load rules for
     every class its own script writes
     (WidgetAssetTest::test_a_shell_only_uses_classes_whose_rules_it_loads). */
  #salesy-root.salesy-shell-overlay.salesy-open .salesy-toggle {
    display: none;
  }

  /* The composer is the bottom-most element again (ADR 0033) — the same
     safe-area override the panel's own mobile block carries, for the same
     reason: whichever element is actually flush with the screen's bottom
     edge is the one that needs it. */
  #salesy-root .salesy-form {
    margin: 2px 12px calc(12px + env(safe-area-inset-bottom)) !important;
  }
}
