/* ──────────────────────────────────────────────────────────────────────────
 * pepita support chat — brand skin (SHARED, standalone, reusable)
 *
 * Styles the widget's own .pepita-* elements from the shared pepita design
 * tokens (--bg / --ink / --ink-soft / --ink-faint / --rule / --accent /
 * --error / --on-accent / --font). Every surface that embeds the widget defines
 * those, so this one file matches whichever host loads it with no edits — Rosé
 * Pine on both surfaces today. Fallbacks keep it correct if a token is missing.
 * This fully replaces the barebone widget.css (load this instead).
 *
 * SHARED VERBATIM between two places — keep them byte-identical:
 *   • the marketing site — pepita-d800, served at /pepita-chat.css
 *   • the app            — apps/app/static/pepita-chat.css
 * Anything true of only ONE surface does NOT belong here. Today that is the
 * app's own launchers and its anchored / popover window: those live in
 * `pepita-chat-app.css`, loaded AFTER this file, in the app only.
 *
 * What IS here: the widget's DEFAULT presentation — the floating trigger and
 * window it builds for itself when the embed passes no parent containers — plus
 * all the chrome that looks the same on every host. The floating rules are
 * inert on a surface that supplies its own containers, because there the
 * widget's .pepita-root is never inserted into the document at all.
 *
 * Drift check: the deploy pipeline MINIFIES served CSS, so never diff
 * https://pepita.dev/pepita-chat.css against this source — read the site's
 * working copy through the pepita MCP instead. The working-copy `sha` is the
 * content sha256, so `shasum -a 256` on this file must equal it.
 * ────────────────────────────────────────────────────────────────────────── */

/* Tokens are defined on all three top-level widget elements, not just
   .pepita-root: when the host supplies a parent anchor the window is appended
   straight into it (NOT inside .pepita-root), so it must carry the tokens
   itself. In floating mode the window/trigger sit inside .pepita-root and
   simply re-declare the same values — harmless. */
.pepita-root,
.pepita-window,
.pepita-trigger {
  /* Read the HOST's shadcn tokens, with the shadcn defaults as fallbacks. The
     fallbacks are what make this sheet safe to ship ahead of a host: a surface
     that has not adopted the tokens yet still gets the right neutral palette,
     rather than the retired terracotta these used to fall back to. */
  --pc-bg: var(--background, oklch(1 0 0));
  --pc-ink: var(--foreground, oklch(0.148 0.004 228.8));
  --pc-soft: var(--muted-foreground, oklch(0.56 0.021 213.5));
  --pc-faint: color-mix(in oklch, var(--muted-foreground, oklch(0.56 0.021 213.5)) 65%, var(--background, oklch(1 0 0)));
  --pc-rule: var(--border, oklch(0.925 0.005 214.3));
  --pc-accent: var(--primary, oklch(0.218 0.008 223.9));
  --pc-error: var(--destructive, oklch(0.577 0.245 27.325));
  --pc-on-accent: var(--primary-foreground, oklch(0.987 0.002 197.1));
  --pc-font: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
  --pc-surface: var(--muted, oklch(0.963 0.002 197.1));
  --pc-radius: 6px;
  /* A drop shadow models occluded light — it must read dark in BOTH themes,
     so base it on black, NOT --ink (which flips light in dark mode and made
     the shadow pale). Matches the uikit overlays' rgba(0,0,0,…) convention. */
  --pc-shadow:
    0 18px 48px -16px rgba(0, 0, 0, 0.42),
    0 4px 14px -8px rgba(0, 0, 0, 0.3);

  font-family: var(--pc-font);
}

/* ---- floating placement: the widget's own bottom-right mount, used whenever
   the embed passes no data-parent-chat / data-parent-trigger ---- */
.pepita--floating {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 2147483000;
}
.pepita--floating .pepita-window {
  position: fixed;
  right: 22px;
  bottom: 90px;
}

/* ---- launcher: round primary button with a lucide chat glyph ---- */
.pepita-trigger {
  width: 56px;
  height: 56px;
  border: none;
  border-radius: 50%;
  background: var(--pc-accent);
  color: transparent; /* hides the "Chat" label visually; kept for a11y */
  font-size: 0;
  cursor: pointer;
  position: relative;
  box-shadow: var(--pc-shadow);
  transition: transform 0.15s ease, filter 0.15s ease;
}
.pepita-trigger:hover {
  transform: translateY(-2px);
  filter: brightness(1.05);
}
.pepita-trigger:active {
  transform: translateY(0);
}
.pepita-trigger::before {
  /* lucide "message-circle-more", inlined as an SVG mask so the glyph needs no
     icon font and stays token-coloured through `background-color`. lucide draws
     with STROKES rather than fills, so the mask carries the stroke attributes —
     without them the paths have no area and the mask comes out empty. */
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 26px;
  height: 26px;
  background-color: var(--pc-on-accent);
  --pc-chat-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719'/%3E%3Cpath d='M8 12h.01'/%3E%3Cpath d='M12 12h.01'/%3E%3Cpath d='M16 12h.01'/%3E%3C/svg%3E");
  -webkit-mask: var(--pc-chat-icon) center / contain no-repeat;
  mask: var(--pc-chat-icon) center / contain no-repeat;
}

/* ---- unread badge on the widget's OWN trigger --------------------------------
 * Widget contract (https://widget.pepita.support): the widget sets
 * `data-pending` on its trigger while there are unread replies. A host that
 * hides that trigger and uses a launcher of its own has to mirror the signal
 * itself — see pepita-chat-app.css for how the app does it. --- */
.pepita-trigger[data-pending]::after {
  content: "";
  /* Pin the box model — the host's reset may or may not reach ::after
     (Tailwind's does → border-box, and the border eats inward → a smaller dot;
     a plain `*` reset doesn't → content-box), which otherwise makes this one
     rule render at different sizes per surface. */
  box-sizing: content-box;
  position: absolute;
  top: -1px;
  right: -1px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--pc-error);
  border: 2.5px solid var(--pc-bg);
}

/* ---- conversation window ---- */
.pepita-window {
  display: none;
  flex-direction: column;
  width: 360px;
  max-width: calc(100vw - 44px);
  height: 460px;
  max-height: calc(100vh - 130px);
  background: var(--pc-bg);
  color: var(--pc-ink);
  font-family: var(--pc-font);
  border: 1px solid var(--pc-rule);
  border-radius: var(--pc-radius);
  box-shadow: var(--pc-shadow);
  overflow: hidden;
}
.pepita-window--open {
  display: flex;
  animation: pc-pop 0.18s ease-out;
}
@keyframes pc-pop {
  from {
    opacity: 0;
    transform: translateY(10px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* ---- header: window-coloured, split from the body by a hairline rule ---- */
.pepita-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 12px;
  background: var(--pc-bg);
  color: var(--pc-ink);
  border-bottom: 1px solid var(--pc-rule);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.pepita-minimize {
  background: none;
  border: none;
  cursor: pointer;
  font: inherit;
  font-size: 15px;
  line-height: 1;
  color: var(--pc-soft);
  padding: 0 2px;
}
.pepita-minimize:hover {
  color: var(--pc-ink);
}

/* ---- messages ---- */
.pepita-messages {
  flex: 1;
  overscroll-behavior: contain;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
  background: var(--pc-bg);
}

/* ---- "New messages" pill -----------------------------------------------------
 * Shown over the list when a reply arrives while the reader is scrolled up.
 * APPEARANCE ONLY belongs here: the widget owns `position`, `left`, `bottom`,
 * `transform` and `display` as INLINE styles (inline beats a stylesheet, and
 * toggling `display` is how it shows/hides the pill), and sets `data-visible`
 * as the state hook.
 * Do NOT reuse the pc-pop keyframe for the entrance — it animates `transform`,
 * and an animation overrides inline styles for the properties it touches, so it
 * would fight the inline translateX(-50%) centering and make the pill jump
 * sideways. Animate opacity only. --- */
.pepita-newmsg {
  border: none;
  border-radius: 999px;
  background: var(--pc-accent);
  color: var(--pc-on-accent);
  font: inherit;
  font-family: var(--pc-font);
  font-size: 12px;
  font-weight: 600;
  padding: 5px 12px;
  cursor: pointer;
  box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.45);
  transition: filter 0.15s ease;
}
.pepita-newmsg::before {
  /* Phosphor "arrow-down" (BOLD, not regular): at the pill's 12px the regular
     weight's stem is ~0.4px and washes out — bold is also the app's icon weight.
     Inlined as an SVG mask like the trigger glyph, so no icon font is needed on
     either surface, and `currentColor` keeps it locked to the label colour.
     An inline-block pseudo, NOT flex + gap: the widget sets `display` INLINE
     (block/none) to show and hide the pill, so a stylesheet `display: flex`
     would be overridden and the gap would never apply. */
  content: "";
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  margin-right: 0.35em;
  vertical-align: -0.13em;
  background-color: currentColor;
  --pc-arrow-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M208.49,152.49l-72,72a12,12,0,0,1-17,0l-72-72a12,12,0,0,1,17-17L116,187V40a12,12,0,0,1,24,0V187l51.51-51.52a12,12,0,0,1,17,17Z'/%3E%3C/svg%3E");
  -webkit-mask: var(--pc-arrow-icon) center / contain no-repeat;
  mask: var(--pc-arrow-icon) center / contain no-repeat;
}
.pepita-newmsg:hover {
  filter: brightness(1.06);
}
.pepita-newmsg[data-visible] {
  animation: pc-fade-in 0.16s ease-out;
}
@keyframes pc-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.pepita-message {
  font-size: 13.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
/* you (whoever is chatting) — right, an accent-TINTED bubble, mirroring the
   editor's AI-chat user bubble (not a solid fill). */
.pepita-message--visitor {
  align-self: flex-end;
  max-width: 85%;
  padding: 0.4rem 0.6rem;
  border-radius: 3px;
  background: color-mix(in oklch, var(--pc-accent) 10%, transparent);
  border: 1px solid color-mix(in oklch, var(--pc-accent) 35%, transparent);
  color: var(--pc-ink);
}

/* ---- operator prose ----------------------------------------------------------
 * TWO widget elements are the same KIND of thing — free-standing text from
 * pepita's side, arriving as markdown rendered to sanitized HTML:
 *   • .pepita-message--admin — an actual reply from the operator
 *   • .pepita-empty          — the greeting shown while the thread is empty
 * So they share every rule below, grouped with :is() rather than duplicated.
 * (:is() takes the highest specificity of its arguments; both are single
 * classes, so these selectors weigh exactly what they did before.)
 *
 * Presentation is deliberately the AI-assistant shape: NO bubble, no border,
 * full width, left. The element rules mirror the editor's `.md-body`, so text
 * reads the same whether it arrives as plain text or as markdown HTML.
 * .pepita-empty needs `font-size`/`line-height` of its own because it is not a
 * .pepita-message and so inherits none of that block's typography. --- */
:is(.pepita-message--admin, .pepita-empty) {
  align-self: stretch;
  max-width: 100%;
  padding: 0;
  background: none;
  border: 0;
  color: var(--pc-ink);
  font-size: 13.5px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}
:is(.pepita-message--admin, .pepita-empty) p {
  margin: 0 0 0.6em;
}
:is(.pepita-message--admin, .pepita-empty) p:last-child {
  margin-bottom: 0;
}
:is(.pepita-message--admin, .pepita-empty) ul,
:is(.pepita-message--admin, .pepita-empty) ol {
  margin: 0 0 0.6em;
  padding-left: 1.2em;
}
:is(.pepita-message--admin, .pepita-empty) li {
  margin: 0.1em 0;
}
:is(.pepita-message--admin, .pepita-empty) a {
  color: var(--pc-accent);
  text-decoration: underline;
}
:is(.pepita-message--admin, .pepita-empty) code {
  font-family: var(--pc-font);
  font-size: 0.9em;
  background: var(--pc-surface);
  border: 1px solid var(--pc-rule);
  border-radius: 3px;
  padding: 0.05em 0.3em;
}
:is(.pepita-message--admin, .pepita-empty) pre {
  margin: 0 0 0.6em;
  padding: 8px 10px;
  background: var(--pc-surface);
  border: 1px solid var(--pc-rule);
  border-radius: 5px;
  overflow-x: auto;
}
:is(.pepita-message--admin, .pepita-empty) pre code {
  border: 0;
  padding: 0;
  background: none;
}
:is(.pepita-message--admin, .pepita-empty) h1,
:is(.pepita-message--admin, .pepita-empty) h2,
:is(.pepita-message--admin, .pepita-empty) h3 {
  font-size: 1em;
  font-weight: 600;
  margin: 0 0 0.4em;
}

/* ---- away notice (outside opening hours) -------------------------------------
 * One persistent <div class="pepita-away">, a direct child of .pepita-window
 * between the transcript and the composer, holding plain text the widget
 * rewrites in place.
 *
 * It is CHROME, not a message: quiet, centred, a size below the transcript, and
 * cut off from it by a hairline — the operator's reply is also full-width
 * unbubbled prose, so without that separation this would read as the last thing
 * a person said.
 *
 * DELIBERATELY NOT TINTED. .pepita-inputrow below is already --pc-surface with a
 * top rule; tinting this too would make one block with a hairline stranded
 * through its middle. Leaving the notice on --pc-bg keeps the composer's tint as
 * the thing that marks the input, and needs no sibling rule reaching into
 * .pepita-inputrow — which would be wrong anyway, since `+` still matches a
 * notice the widget has set to `display: none`, so the composer would lose its
 * rule exactly when there is no notice to merge with.
 *
 * Three things the widget owns — don't fight them:
 *   • `display` is an INLINE style (none/block): never set it here, and never
 *     rely on flex layout inside this box;
 *   • `[data-visible]` is a bare presence attribute set alongside that flip —
 *     entrance only, never visibility;
 *   • `flex: 0 0 auto` is required. This is a flex item of a fixed-height column;
 *     without it a two-line notice gets squeezed instead of taking its space
 *     from the transcript.
 *
 * `font-size` is absolute, not `em`: .pepita-window sets no font-size, so `0.9em`
 * would resolve against the browser default and come out LARGER than a message. */
.pepita-away {
  flex: 0 0 auto;
  padding: 9px 14px;
  border-top: 1px solid var(--pc-rule);
  background: var(--pc-bg);
  color: var(--pc-soft);
  font-size: 12.5px;
  line-height: 1.45;
  text-align: center;
  text-wrap: balance;
}
.pepita-away[data-visible] {
  animation: pc-fade-in 0.16s ease-out;
}

/* ---- input row (composer) ----
   Modelled on the editor's AI-chat composer: the whole tinted region IS the
   text-entry surface, and Send sits INSIDE it rather than beside a separate
   boxed field. Achieved on the existing widget markup
   (.pepita-inputrow > textarea.pepita-input + button.pepita-send) with CSS
   alone — the row becomes a column, the textarea goes borderless/transparent,
   and Send drops to the bottom-right. Deliberately no border and no focus
   ring (the flush AI style); the surface tint alone marks the widget. */
.pepita-inputrow {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  padding: 12px;
  border-top: 1px solid var(--pc-rule);
  background: var(--pc-surface);
}
.pepita-input {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-family: var(--pc-font);
  font-size: 13.5px;
  line-height: 20px;
  color: var(--pc-ink);
  resize: none;
}
.pepita-input::placeholder {
  color: var(--pc-faint);
}
.pepita-input:focus {
  outline: none;
}
.pepita-send {
  /* A shadcn ICON BUTTON: `size="icon"` geometry (a 36px square, the `rounded-md`
     radius, the primary fill) with a lucide "corner-down-left" glyph. The widget
     renders its own text label inside this button, so the label is hidden the
     same way `.pepita-trigger` hides its own — `font-size: 0` plus a transparent
     colour, which keeps it readable to a screen reader while the glyph carries
     the meaning on screen.

     The glyph is a MASK rather than a background image so it takes its colour
     from `background-color`, and therefore follows the token in both themes.
     lucide draws with strokes, so the mask carries the stroke attributes —
     without them the path encloses no area and the mask comes out empty. */
  align-self: flex-end;
  flex: 0 0 auto;
  position: relative;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 6px;
  background: var(--pc-accent);
  color: transparent;
  font-size: 0;
  cursor: pointer;
  transition: filter 0.15s ease;
}
.pepita-send::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 16px;
  background-color: var(--pc-on-accent);
  --pc-send-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3Cpath d='m9 10-5 5 5 5'/%3E%3C/svg%3E");
  -webkit-mask: var(--pc-send-icon) center / contain no-repeat;
  mask: var(--pc-send-icon) center / contain no-repeat;
}
.pepita-send:hover {
  filter: brightness(1.06);
}

/* ---- small screens: near-full-width sheet ---- */
@media (max-width: 460px) {
  .pepita--floating .pepita-window {
    right: 12px;
    left: 12px;
    bottom: 84px;
    width: auto;
    max-width: none;
  }
}

/* ---- respect reduced-motion ---- */
@media (prefers-reduced-motion: reduce) {
  .pepita-window--open {
    animation: none;
  }
  .pepita-trigger {
    transition: none;
  }
  .pepita-newmsg {
    animation: none;
    transition: none;
  }
  .pepita-away {
    animation: none;
  }
}
