/* Rosen support chat — the concept's design language, in a plugin.

   Restraint over decoration, one accent, type does the work. Same rules as
   website/concept/concept.css, which is where every token below comes from.

   ── Why every token has a fallback ──────────────────────────────────────
   R12 — converting the concept into the live theme — has not shipped. So this
   stylesheet runs today on a theme that defines none of --ink, --body, --line or
   --radius, and tomorrow on one that defines all of them. Reading them through
   var(--ink, #111517) means the widget inherits the design system the moment the
   theme carries it, and looks right in the meantime, with nothing to remember to
   change on the day. The literals are copied from concept.css, not chosen here.

   ── The colour that is not allowed ──────────────────────────────────────
   --green (#8cc054) is 2.15:1 on white. It is decorative — the launcher glow,
   a focus ring, a status dot on a dark ground — and it is NEVER text and never a
   border that has to be seen. Every green word and every green button uses
   --green-ink (#4a7324). The audit fails on this exact substitution, and it has
   failed on it before. */

/* The no-script launcher is a SIBLING of .rchat, not a child — it has to be, or
   the root's `hidden` would hide the one link that exists for the case where
   nothing can remove it. So it has to be named here too, or every token below
   resolves to nothing and it renders as unstyled text on a white corner. */
.rchat,
.rchat-launcher--noscript {
  /* One place for the tokens, so the panel, the sheet and the launcher cannot
     drift apart. */
  --rchat-ink:       var(--ink, #111517);
  --rchat-ink-2:     var(--ink-2, #1d2327);
  --rchat-body:      var(--body, #4f5a62);
  --rchat-muted:     var(--muted, #667079);
  --rchat-line:      var(--line, #e4e8ea);
  --rchat-wash:      var(--wash, #f5f7f8);
  --rchat-page:      var(--page, #ffffff);
  --rchat-accent:    var(--green-ink, #4a7324);   /* text and buttons */
  --rchat-glow:      var(--green, #8cc054);       /* decorative only */
  --rchat-soft:      var(--green-soft, #f2f8ea);
  --rchat-radius:    var(--radius, 16px);
  --rchat-shadow:    var(--shadow, 0 1px 2px rgba(17,21,23,.04), 0 12px 32px rgba(17,21,23,.06));
  --rchat-shadow-lg: var(--shadow-lg, 0 2px 4px rgba(17,21,23,.05), 0 24px 60px rgba(17,21,23,.10));
  --rchat-ease:      var(--ease, cubic-bezier(.16,.84,.44,1));
  --rchat-ease-out:  var(--ease-out, cubic-bezier(.16,1,.3,1));

  /* ONE source of truth for the breakpoint. chat.js reads this value off the
     element with getComputedStyle and builds its media query from it, the same
     trick concept.css uses for --dwell. Change it here and the sheet, the scroll
     lock, the drag-to-dismiss and the Enter-key behaviour all move together —
     they used to be a magic 640 in two files that could disagree. */
  --rchat-mobile-max: 640px;

  --rchat-gap-bottom: 20px;
  --rchat-gap-side:   20px;

  /* ── the two values chat.js measures rather than assumes ────────────────
     A launcher pinned to the bottom-right corner is only in the corner until
     something else claims that corner. On this store the demo toolbar does —
     `position:fixed; bottom:0; z-index:99999`, 88px tall on a desktop — and it
     covered the launcher completely: the whole button, not part of it. A
     customer could neither see the chat nor click it, which read as "there is
     no chat".

     The toolbar does reserve room, with `body{padding-bottom:74px}`. That
     reservation cannot work here and never could: a fixed element is positioned
     against the viewport, not against the body box, so body padding moves the
     page and leaves every fixed overlay exactly where it was. Any bottom-docked
     bar has the same shape — a cookie notice, a sticky add-to-cart, a
     "cart updated" strip — so the answer is not a selector for this one bar.

     `--rchat-obstruction` is how many pixels of the bottom edge are already
     taken, measured in the browser by chat.js and written back here.
     `--rchat-z` is one above whatever that bar stacks at, because being 68px
     higher than a bar you are still behind only moves the problem.

     Both keep working with the defaults below when nothing is measured and when
     JavaScript never runs, so the widget is never worse off than it was. */
  --rchat-obstruction: 0px;
  --rchat-z:           9999;

  /* ── and the third one: the page's own last line ────────────────────────
     A bar is not the only thing that can be under the launcher. At the very
     bottom of every page on this store the footer's legal row ends with
     "© 2026 Rosen Implant Solutions LLC", right-aligned — it finishes at
     x=1333 on a 1440 window and the pill spans 1280–1404, so the pill sat on
     the last four words of the copyright.

     That is not a stacking problem and adding z-index to it only decides which
     of the two is destroyed. Nor is it something --rchat-obstruction can see:
     the legal row is ordinary in-flow content, not a fixed bar, and it is only
     under the launcher when the visitor has scrolled to the end.

     `--rchat-floor` is how far the launcher has to rise to stand clear of the
     document's own last row, measured by chat.js when that row comes into
     view and back to 0px the moment it leaves. It applies to the LAUNCHER
     ONLY, unlike the two above: the panel is an overlay the visitor opened and
     is meant to cover the page, the launcher is one they did not ask for and
     may not cover anything. */
  --rchat-floor: 0px;

  font: 400 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;
  color: var(--rchat-body);
}

/* `hidden` is an attribute the theme's own reset can beat, and a launcher that
   appears before its script has loaded is a button that does nothing. */
.rchat[hidden] { display: none !important; }

.rchat-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── launcher ──────────────────────────────────────────────────────────── */

.rchat-launcher {
  position: fixed;
  right: var(--rchat-gap-side);
  /* env() keeps it off the iPhone home indicator. --rchat-obstruction keeps it
     off whatever the page has docked to the bottom edge — see the token block;
     env() alone never knew about those, which is how the demo toolbar came to
     swallow this button whole. --rchat-floor keeps it off the page's own last
     row, which is how it came to sit on the footer copyright. */
  bottom: calc(var(--rchat-gap-bottom) + var(--rchat-obstruction, 0px) + var(--rchat-floor, 0px) + env(safe-area-inset-bottom, 0px));
  z-index: 9999;
  z-index: var(--rchat-z, 9999);

  display: inline-flex; align-items: center; gap: 9px;
  margin: 0; padding: 13px 20px 13px 17px;
  border: 0; border-radius: 100px;
  background: var(--rchat-accent); color: #fff;
  font: inherit; font-size: 15px; font-weight: 600; line-height: 1;
  text-decoration: none; cursor: pointer;
  box-shadow: 0 8px 20px rgba(74,115,36,.24);
  transition: transform .25s var(--rchat-ease), box-shadow .25s var(--rchat-ease), opacity .2s var(--rchat-ease);
}
.rchat-launcher:hover { transform: translateY(-2px); box-shadow: 0 14px 30px rgba(74,115,36,.32); color: #fff; }
.rchat-launcher:active { transform: translateY(0) scale(.985); }
.rchat-launcher-icon { display: grid; place-items: center; }

/* Open: the launcher gets out of the way rather than sitting under the panel.
   visibility, not display, so the focus-return on Escape still has an element
   to land on. */
.rchat.is-open .rchat-launcher { opacity: 0; visibility: hidden; transform: scale(.85); }

/* Eclipsed: something else on the page owns the screen right now.
   On a phone the launcher is a 48px pill floating over the content, and when
   the theme's navigation drawer or its search sheet is open it floats over
   THOSE — it was sitting on a row of the category list, covering the link
   underneath it. The drawer is a modal: while it is open nothing outside it
   should be reachable, a chat button least of all. chat.js sets this class from
   the same scroll lock the drawer uses, so it costs no knowledge of the theme.
   Same treatment as is-open, for the same reason: visibility, not display, so
   focus has somewhere to return to. */
.rchat.is-eclipsed .rchat-launcher { opacity: 0; visibility: hidden; transform: scale(.85); pointer-events: none; }

/* ── scrim (mobile only) ───────────────────────────────────────────────── */

.rchat-scrim {
  position: fixed; inset: 0;
  z-index: 9998;
  z-index: calc(var(--rchat-z, 9999) - 1);
  background: rgba(11,14,16,.46);
  opacity: 0; visibility: hidden;
  transition: opacity .3s var(--rchat-ease), visibility 0s linear .3s;
}
.rchat-scrim.is-open { opacity: 1; visibility: visible; transition: opacity .34s var(--rchat-ease), visibility 0s; }
.rchat-scrim[hidden] { display: none; }

/* ── panel: desktop ────────────────────────────────────────────────────── */

.rchat-panel {
  position: fixed;
  right: var(--rchat-gap-side);
  bottom: calc(var(--rchat-gap-bottom) + var(--rchat-obstruction, 0px) + env(safe-area-inset-bottom, 0px));
  z-index: 10000;
  z-index: calc(var(--rchat-z, 9999) + 1);

  width: 380px;                        /* the figure in the specification */
  max-width: calc(100vw - 40px);
  /* The obstruction comes off the height as well as the offset. Lifting the
     panel without shortening it pushes its head off the top of the window
     instead — and the panel is 560px on a 950px screen, so there is not much
     spare. What must never end up under a bar is the composer: a chat you can
     read and cannot type into is not a chat. */
  height: min(560px, calc(100vh - 120px - var(--rchat-obstruction, 0px)));
  display: flex; flex-direction: column; overflow: hidden;

  background: var(--rchat-page);
  border: 1px solid var(--rchat-line);
  border-radius: 20px;
  box-shadow: var(--rchat-shadow-lg);

  opacity: 0; transform: translateY(12px) scale(.985); transform-origin: 100% 100%;
  transition: opacity .26s var(--rchat-ease), transform .3s var(--rchat-ease-out);
}
.rchat-panel[hidden] { display: none; }
.rchat.is-open .rchat-panel { opacity: 1; transform: none; }

/* ── head ──────────────────────────────────────────────────────────────── */

.rchat-head {
  position: relative; flex: none;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 16px 14px 14px 20px;
  border-bottom: 1px solid var(--rchat-line);
  background: var(--rchat-page);
}
.rchat-grip { display: none; }

.rchat-id { min-width: 0; flex: 1; }
.rchat-title {
  margin: 0; font-size: 15.5px; font-weight: 600; letter-spacing: -.01em;
  color: var(--rchat-ink); line-height: 1.25;
}
.rchat-sub {
  margin: 3px 0 0; font-size: 12.5px; line-height: 1.4; color: var(--rchat-muted);
  display: flex; align-items: center; flex-wrap: wrap; gap: 0 6px;
}
/* The dot is decoration; the words beside it carry the meaning, because a
   colour is not an answer to "are they open". */
.rchat-dot {
  width: 7px; height: 7px; flex: none; border-radius: 50%;
  background: var(--rchat-muted);
}
.rchat-sub[data-open="1"] .rchat-dot { background: var(--rchat-glow); }
/* The separator hangs off the SECOND span, not the first. CSS has no previous
   sibling, so "hide the separator when the hours are empty" only works if the
   separator belongs to the thing that can be empty. */
.rchat-sub-hours::before { content: "·"; margin-right: 6px; color: var(--rchat-muted); }
.rchat-sub-hours:empty { display: none; }

.rchat-close {
  flex: none; display: grid; place-items: center;
  width: 34px; height: 34px; padding: 0;
  border: 0; border-radius: 10px; background: transparent;
  color: var(--rchat-muted); cursor: pointer;
  transition: background .2s var(--rchat-ease), color .2s var(--rchat-ease);
}
.rchat-close:hover { background: var(--rchat-wash); color: var(--rchat-ink); }

/* ── transcript ────────────────────────────────────────────────────────── */

.rchat-log {
  flex: 1; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  padding: 18px 20px 6px;
  display: flex; flex-direction: column; gap: 12px;
}

.rchat-msg { display: flex; max-width: 100%; }
.rchat-msg--user { justify-content: flex-end; }

.rchat-bubble {
  max-width: 86%;
  padding: 11px 14px;
  border-radius: 16px;
  font-size: 14.5px; line-height: 1.55;
  /* A model reply can carry a SKU or a URL with no spaces in it. Without this a
     single long token pushes the bubble past the panel and the whole transcript
     scrolls sideways. */
  overflow-wrap: anywhere;
}
.rchat-msg--bot .rchat-bubble {
  background: var(--rchat-wash); color: var(--rchat-ink-2);
  border-bottom-left-radius: 6px;
}
.rchat-msg--user .rchat-bubble {
  background: var(--rchat-accent); color: #fff;
  border-bottom-right-radius: 6px;
}
.rchat-bubble p { margin: 0 0 8px; }
.rchat-bubble p:last-child { margin-bottom: 0; }
.rchat-bubble strong { font-weight: 600; color: inherit; }
.rchat-bubble ul { margin: 6px 0 0; padding-left: 18px; }
.rchat-bubble li { margin: 0 0 4px; }
.rchat-bubble li:last-child { margin-bottom: 0; }
.rchat-bubble .rchat-library-links { list-style: none; padding: 0; margin-top: 12px; }
.rchat-library-links a {
  display: inline-flex; align-items: center; min-height: 44px;
  max-width: 100%; color: var(--rchat-accent); font-weight: 600;
  text-decoration: underline; text-underline-offset: 3px;
}

.rchat-privacy {
  margin: 2px 0 0; padding: 0 2px;
  font-size: 11.5px; line-height: 1.45; color: var(--rchat-muted);
}

/* ── the handoff card ──────────────────────────────────────────────────────
   The most important thing in the panel, so it is a card and not a sentence
   with a link in it. Handing over is the default output, not the failure. */

.rchat-handoff {
  margin: 2px 0; padding: 14px;
  border: 1px solid var(--rchat-line); border-radius: var(--rchat-radius);
  background: var(--rchat-soft);
}
.rchat-handoff p { margin: 0 0 11px; font-size: 14px; color: var(--rchat-ink-2); }
.rchat-handoff-cta {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 18px; border-radius: 100px;
  background: var(--rchat-accent); color: #fff;
  font-size: 14px; font-weight: 600; text-decoration: none;
  box-shadow: 0 6px 16px rgba(74,115,36,.22);
  transition: transform .25s var(--rchat-ease), box-shadow .25s var(--rchat-ease);
}
.rchat-handoff-cta:hover { transform: translateY(-2px); box-shadow: 0 12px 24px rgba(74,115,36,.3); color: #fff; }
.rchat-handoff-note {
  margin: 10px 0 0 !important; font-size: 11.5px; color: var(--rchat-muted) !important;
}
.rchat-handoff-ref { font-variant-numeric: tabular-nums; letter-spacing: .02em; }

/* ── status line ───────────────────────────────────────────────────────── */

.rchat-status {
  flex: none; margin: 0; padding: 0 20px;
  font-size: 12px; color: var(--rchat-muted); min-height: 18px;
}
.rchat-status:empty { min-height: 0; }

/* ── composer ──────────────────────────────────────────────────────────── */

.rchat-composer {
  flex: none;
  display: flex; align-items: flex-end; gap: 8px;
  margin: 6px 12px 0; padding: 8px 8px 8px 14px;
  border: 1px solid var(--rchat-line); border-radius: 18px;
  background: var(--rchat-page);
  transition: border-color .2s var(--rchat-ease), box-shadow .2s var(--rchat-ease);
}
.rchat-composer:focus-within {
  border-color: var(--rchat-accent);
  box-shadow: 0 0 0 4px rgba(140,192,84,.18);
}
.rchat-input {
  flex: 1; min-width: 0;
  border: 0; outline: none; background: none; resize: none;
  font: inherit; font-size: 15px; line-height: 1.45; color: var(--rchat-ink);
  padding: 8px 0; max-height: 108px; overflow-y: auto;
}
.rchat-input::placeholder { color: var(--rchat-muted); }

.rchat-send {
  flex: none; display: grid; place-items: center;
  width: 38px; height: 38px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--rchat-accent); color: #fff; cursor: pointer;
  transition: opacity .2s var(--rchat-ease), transform .2s var(--rchat-ease);
}
.rchat-send:disabled { opacity: .32; cursor: default; }
.rchat-send:not(:disabled):hover { transform: scale(1.06); }

/* ── foot ──────────────────────────────────────────────────────────────── */

.rchat-foot {
  flex: none; padding: 10px 20px calc(14px + env(safe-area-inset-bottom, 0px));
  text-align: center;
}
.rchat-foot-wa {
  font-size: 12.5px; font-weight: 600;
  color: var(--rchat-accent);            /* --green would be 2.15:1 here */
  text-decoration: none; border-bottom: 1px solid rgba(74,115,36,.28);
}
.rchat-foot-wa:hover { border-bottom-color: var(--rchat-accent); color: var(--rchat-accent); }

/* ── focus ─────────────────────────────────────────────────────────────────
   concept.css found the site had no focus styles at all — every control was
   invisible to the keyboard. Not repeating that here. */

.rchat :focus-visible,
.rchat-launcher:focus-visible {
  outline: 2px solid var(--rchat-accent); outline-offset: 3px; border-radius: 10px;
  box-shadow: 0 0 0 5px rgba(140,192,84,.3);
}
/* The panel takes focus on open so a screen reader announces the dialog. That
   is a programmatic focus, not a keyboard journey, so it must not draw a ring. */
.rchat-panel:focus { outline: none; }

/* ── typing indicator ──────────────────────────────────────────────────── */

.rchat-typing { display: inline-flex; align-items: center; gap: 4px; }
.rchat-typing i {
  width: 5px; height: 5px; border-radius: 50%; background: var(--rchat-muted);
  animation: rchat-bounce 1.2s var(--rchat-ease) infinite;
}
.rchat-typing i:nth-child(2) { animation-delay: .15s; }
.rchat-typing i:nth-child(3) { animation-delay: .3s; }
@keyframes rchat-bounce { 0%,60%,100% { opacity: .3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }

/* ══════════════════════════════════════════════════════════════════════════
   MOBILE — a sheet from the bottom.

   Not a squeezed desktop panel. The client rejected a squeezed layout once
   already and asked for native-app standard, which is what the account area was
   rebuilt to: full width, off the bottom edge, rounded top corners, a grab
   handle you can actually drag, and the composer sitting above the home
   indicator rather than under it.

   The breakpoint below MUST match --rchat-mobile-max, which chat.js reads to
   decide about the scroll lock, the drag and the Enter key. Media queries
   cannot read a custom property, so this is the one place the number is
   repeated — and the variable is what the JavaScript trusts.
   ══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 640px) {

  /* A circle, not a pill, and the word goes.
     At 390px the "Support" pill is 126px wide and floats over whatever the page
     has in its bottom-right corner — it was cutting the home page's "Direct
     line / to our clinical team" line down to "to …". The icon alone is the
     pattern every visitor already knows, it halves the footprint, and the label
     is not lost: it stays on the button as aria-label, which is what a screen
     reader was reading anyway.

     Scoped inside .rchat on purpose: the <noscript> link is a SIBLING of the
     root and carries the text and no icon, so hiding its label would leave an
     empty green circle as the only route to a human on a browser with
     JavaScript off. It keeps the pill. */
  .rchat .rchat-launcher {
    width: 52px; height: 52px; padding: 0;
    justify-content: center; gap: 0;
  }
  .rchat-launcher--noscript { padding: 13px 18px; }
  .rchat .rchat-launcher-text {
    position: absolute; width: 1px; height: 1px; margin: -1px;
    padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }

  .rchat-panel {
    right: 0; left: 0;
    /* Off the bottom edge — unless the bottom edge is already spoken for, in
       which case the sheet stops above it rather than sliding its composer
       underneath it. */
    bottom: 0;
    bottom: var(--rchat-obstruction, 0px);
    width: auto; max-width: none;
    /* dvh, because 100vh on iOS Safari is the height WITHOUT the browser chrome
       — a sheet sized to it puts its own composer under the address bar. The vh
       line stays as the fallback for browsers that predate dvh. */
    height: 86vh;
    height: min(86dvh, 720px, calc(100dvh - 40px - var(--rchat-obstruction, 0px)));
    border: 0; border-bottom: 0;
    border-radius: 22px 22px 0 0;
    box-shadow: 0 -18px 50px rgba(17,21,23,.22);

    transform: translateY(100%); opacity: 1;
    transition: transform .34s var(--rchat-ease-out);
  }
  .rchat.is-open .rchat-panel { transform: translateY(0); }

  /* While a finger is on the handle the sheet follows it, so no transition can
     be fighting the per-frame writes. Same reasoning as the concept's tilt. */
  .rchat.is-dragging .rchat-panel { transition: none; }

  /* The whole header is the drag target — a 4px bar is not a touch target, and
     touch-action:none is what stops the browser claiming the gesture as a page
     scroll before the sheet ever sees it. */
  .rchat-head { padding-top: 22px; touch-action: none; }
  .rchat-grip {
    display: block; position: absolute; top: 9px; left: 50%;
    width: 38px; height: 4px; margin-left: -19px;
    border-radius: 100px; background: var(--rchat-line);
  }
  .rchat-close { touch-action: manipulation; }

  .rchat-log { padding: 16px 16px 6px; }
  .rchat-bubble { max-width: 90%; }
  .rchat-composer { margin: 6px 10px 0; }
  /* 16px stops iOS zooming the whole page in the moment the field is focused,
     which on a sheet leaves the customer looking at a magnified corner of it. */
  .rchat-input { font-size: 16px; }
  .rchat-foot { padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
}

/* Short landscape phones: the sheet would otherwise be taller than the screen
   and the composer would sit off it. */
@media (max-width: 640px) and (max-height: 480px) {
  .rchat-panel {
    height: 94vh;
    height: min(94dvh, calc(100dvh - 16px - var(--rchat-obstruction, 0px)));
  }
}

/* ── reduced motion ────────────────────────────────────────────────────────
   The sheet still travels — an overlay that materialises with no movement reads
   as a page break rather than a panel — but everything decorative stops. */

@media (prefers-reduced-motion: reduce) {
  .rchat-launcher,
  .rchat-panel,
  .rchat-scrim,
  .rchat-send,
  .rchat-handoff-cta { transition-duration: .01ms !important; }
  .rchat-typing i { animation: none; opacity: .55; }
  .rchat-launcher:hover,
  .rchat-handoff-cta:hover { transform: none; }
}

/* ── forced colours ───────────────────────────────────────────────────────
   In Windows high-contrast the bubbles lose their backgrounds, and a transcript
   where the customer's words and the assistant's words look identical is not a
   transcript. Borders survive forced-colors; backgrounds do not. */

@media (forced-colors: active) {
  .rchat-panel { border: 1px solid CanvasText; }
  .rchat-bubble { border: 1px solid CanvasText; }
  .rchat-msg--user .rchat-bubble { border-style: double; border-width: 3px; }
  .rchat-dot { outline: 1px solid CanvasText; }
}

/* Attachments remain outside the message transcript. */
.rchat-media { padding: 8px 16px 0; border-top: 1px solid #e1e8e2; }
.rchat-media[hidden], .rchat-media [hidden] { display: none !important; }
.rchat-media-tools { display: flex; flex-wrap: wrap; gap: 6px; }
.rchat-media-tools button { border: 1px solid #b9cabb; border-radius: 8px; background: #f2f6f2; color: #24412b; padding: 8px 10px; min-height: 40px; font: inherit; font-size: 12px; cursor: pointer; }
.rchat-media-tools button:focus-visible { outline: 2px solid #416b43; outline-offset: 2px; }
.rchat-media-tools button:disabled { opacity: .55; cursor: default; }
.rchat-media-notice, #rosen-chat-media-status { font-size: 11px; line-height: 1.4; margin: 6px 0; color: #52645a; }
