/**
 * Salesy storefront chat — the docked sidebar shell (0.18.0, ADR 0027).
 *
 * A tall panel down one side of the page, opened by the same floating launcher
 * the panel shell uses (whose look lives in widget-core.css, because more than
 * one shell has one). Everything INSIDE the dock is widget-core.css.
 *
 * This file satisfies core's one contract: `.salesy-sidebar` declares
 * `container-type: inline-size`, which is what makes core's `@container`
 * queries match at all. It matters more here than anywhere else — a dock is
 * narrow by definition, so the opening screen stays in its ONE-column layout
 * and the collage fan is suppressed below the width it needs. That suppression
 * is at the bottom of this file and is the sidebar's own decision, not core's.
 *
 * The 768px breakpoint is stated here AND in `wideEnoughToReopen()` in
 * widget-shell-sidebar.js, coupled on purpose: below it the dock IS the screen,
 * so a boot-time reopen would cover the page the shopper just navigated to.
 * Moving one without the other is the bug that pairing guards against.
 */

/* The dock. `position: fixed` against the viewport, so it is unaffected by
   whatever the theme does with its own stacking and scrolling. */
#salesy-root .salesy-sidebar {
  position: fixed;
  top: 0;
  bottom: 0;
  width: var(--salesy-dock-width, 420px);
  max-width: 100vw;
  z-index: 99998;
  display: flex;
  flex-direction: column;
  background: var(--salesy-surface);
  box-shadow: 0 0 40px -12px rgba(17, 24, 39, 0.35);
  /* Core's opening screen and collage are @container queries. See the header. */
  container-type: inline-size;
}

/* Which edge, as one of two fixed class names — never the merchant's own
   string written into a declaration. The border sits on the inner edge, so it
   reads as a seam against the page rather than an outline around a box. */
#salesy-root.salesy-dock-right .salesy-sidebar {
  right: 0;
  border-left: 1px solid var(--salesy-border);
}

#salesy-root.salesy-dock-left .salesy-sidebar {
  left: 0;
  border-right: 1px solid var(--salesy-border);
}

/* The minimised launcher needs no rules of its own here any more (ADR 0034):
   it sits exactly where the chat button sits, on core's own root positioning
   (`bottom: var(--salesy-offset-bottom)` plus `salesy-pos-left`/`-right`),
   from the same Placement settings a merchant already uses for that button.
   The four-corner `salesy-corner-*` pair this file used to carry is gone with
   the setting that fed it. */

/* The launcher IS the minimised state, so it is not on screen while the dock
   is open — the dock carries its own minimise control, and a button that
   toggles something already filling the edge beside it is one affordance too
   many. This also removes any question of the two overlapping, whichever
   corner the merchant put the button in. */
#salesy-root.salesy-shell-sidebar.salesy-open .salesy-toggle {
  display: none;
}

/* The head: sign-in on the left, the two round controls on the right. No
   title — the store's name is already the dock's aria-label and the
   launcher's, and a narrow column cannot spare a row to repeat it. */
#salesy-root .salesy-sidebar-head {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  padding: calc(14px + env(safe-area-inset-top)) 16px 4px;
}

/* A dash rather than a cross, like the panel's and for the same reason: this
   minimises back to the launcher and the conversation survives it. Sized here
   rather than in core because each shell picks its own glyph. */
#salesy-root .salesy-sidebar .salesy-close {
  font-size: 20px !important;
}

/* -- The one rule outside our own root -------------------------------------

   `push` mode narrows the page so the dock covers nothing, and there is no way
   to do that from inside `#salesy-root`: the thing that has to move is the
   host document. So this is the single deliberate exception to the scoping
   rule that the rest of this widget is built on (widget-core.css, mechanism 1),
   and `WidgetAssetTest::test_the_stylesheet_is_scoped_to_the_root_id` carries
   a named allowlist entry for exactly these selectors and no others.

   Three things keep the exception small:

   - It is OPT-IN. The default mode floats above the page and touches nothing,
     so a merchant who never chooses `push` never gets any of this.
   - It is one property on one element, scoped to a class this widget adds and
     removes itself. Nothing here restyles the theme; it moves one edge.
   - The width is read from a custom property the script already validated and
     clamped, so no value is composed into a declaration here either.

   THE PAGE SNAPS RATHER THAN SLIDES, and that is not a style preference. A
   `transition` on this margin leaves the declaration stuck at its start value
   — the page never moves at all, in any form of the transition: the `margin`
   shorthand, and the logical longhands named explicitly, both measured at 0px
   on a live storefront where `transition: none` measured the full 420px. The
   property arrives with `!important` and a `var()` in the same style change
   that first applies the rule, and it does not survive being animated out of
   that. A page that moves instantly is worth more than one that animates
   never, so there is no transition here and no reduced-motion block to pair
   with one.

   `scroll-padding` is not adjusted and `position: fixed` elements in the theme
   (a sticky header, a cookie bar) will NOT move — a fixed element is
   positioned against the viewport, and nothing short of restyling the theme
   can change that. It is the accepted residual of this mode, and the reason
   floating is the default. */
html.salesy-push body {
  margin-inline-end: var(--salesy-dock-width, 420px) !important;
}

html.salesy-push:has(#salesy-root.salesy-dock-left) body {
  margin-inline-end: 0 !important;
  margin-inline-start: var(--salesy-dock-width, 420px) !important;
}

/* -- Narrow ---------------------------------------------------------------- */

/* Below the tablet breakpoint the dock IS the screen: a 420px column beside a
   390px phone viewport is not a sidebar, it is a covered page. The launcher
   goes with it, exactly as the panel's does, because it would otherwise float
   on top of its own dock. Push mode stops pushing here too — there is nothing
   left to push the page into. */
@media (max-width: 767px) {
  #salesy-root .salesy-sidebar {
    width: auto;
    left: 0;
    right: 0;
    border: 0;
  }

  #salesy-root .salesy-sidebar-head {
    padding: calc(10px + env(safe-area-inset-top)) 12px 4px;
  }

  html.salesy-push body,
  html.salesy-push:has(#salesy-root.salesy-dock-left) body {
    margin-inline-start: 0 !important;
    margin-inline-end: 0 !important;
  }
}

/* The collage fan is tuned for a landscape panel: three overlapping cards
   beside a two-column intro. A dock is portrait by definition, so below the
   width the fan needs it is hidden and the opening screen is the copy alone —
   which is the same treatment a restored conversation already gets. Hiding it
   in CSS rather than not rendering it keeps the decision here, where the width
   is known; the script cannot see how wide the shell made itself. */
@container (max-width: 479px) {
  #salesy-root .salesy-collage {
    display: none;
  }
}
