/* ==========================================================================
   Status Banner
   --------------------------------------------------------------------------
   Self-contained styling for the stats row and the urgency banner.

   The source used an in-house SCSS mixin DSL (perch/spring/when/media) and a
   global `html { font-size: 62.5% }`, so every `rem` there was 10px-based.
   Those mixins are expanded to plain CSS below and the rem values are
   converted to absolute px at that 10px base, so this file drops into any
   page regardless of its root font size.

     2.35rem -> 23.5px      1.25rem -> 12.5px
     1.8rem  -> 18px        1rem    -> 10px
     1.5rem  -> 15px        0.5rem  -> 5px
   ========================================================================== */

.sb {
  /* ---- design tokens ---------------------------------------------------- */
  /* Swap --sb-font for your site's face to match screenshots exactly. */
  --sb-font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;

  --sb-text: #1f1f1f;
  --sb-rule: #ebebeb;        /* stat separators */
  --sb-tray-bg: #f6f6f6;     /* stats row tray */
  --sb-banner-bg: #fde7ba;   /* banner */
  --sb-beacon: #f5a66c;      /* beacon dot */

  --sb-radius: 5px;
  --sb-body-size: 18px;
  --sb-icon-size: 23.5px;
  --sb-icon-opacity: 0.65;

  /* The source pulled the tray and banner up over the rule above them. */
  --sb-overlap: -15px;

  width: 100%;
  max-width: 100%;
  font-family: var(--sb-font);
  color: var(--sb-text);
  text-align: left;
}

.sb *,
.sb *::before,
.sb *::after {
  box-sizing: border-box;
}

/* When every rule suppresses both pieces (a direct posting, for instance) the
   wrapper renders with no children — take it out of the layout entirely. */
.sb:empty {
  display: none;
}

/* Shared icon treatment for both the stats row and the banner. */
.sb__icon {
  height: var(--sb-icon-size);
  width: var(--sb-icon-size);
  flex: 0 0 auto;
  opacity: var(--sb-icon-opacity);
}

/* ==========================================================================
   Stats row
   ========================================================================== */

.sb__stats {
  width: 100%;
  max-width: 100%;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px 20px;
  margin-top: 12.5px;
  padding: 10px;
  background: var(--sb-tray-bg);
  border-radius: var(--sb-radius);
}

/* The tuck-under-the-rule-above offset belongs to whichever element is
   actually first inside .sb, not to .sb__stats/.sb__banner individually.
   Baking it into each of them independently was fine while stats and
   banner were always .sb's only two children; it stops being fine once a
   banner sits inside its own wrapper (see .banner-version below) with a
   label above it, something per-element -15px shifts would then throw out
   of alignment against. */
.sb > *:first-child {
  position: relative;
  top: var(--sb-overlap);
}

@media (max-width: 1100px) {
  .sb__stats {
    grid-template-columns: repeat(auto-fit, minmax(310px, 1fr));
  }
}

@media (max-width: 768px) {
  .sb__stats {
    grid-template-columns: 1fr;
    gap: 20px;
  }
}

.sb__stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
  color: var(--sb-text);
  border-right: 1px solid var(--sb-rule);
  /* Wraps rather than overflowing the grid cell. At typical widths each stat
     fits on one line anyway; this only kicks in once the column is too
     narrow for its content (e.g. "Last response: a few seconds ago"
     alongside other stats), instead of spilling past the tray's edge. */
  white-space: normal;
  overflow-wrap: break-word;
}

.sb__stat:last-child {
  border-right-color: transparent;
}

/* Below this width the columns start wrapping, so the rules read as noise. */
@media (max-width: 910px) {
  .sb__stat {
    border-right: 0 solid transparent;
  }
}

@media (max-width: 768px) {
  .sb__stat {
    border-right: 0;
    border-bottom: 1px solid var(--sb-rule);
    padding-bottom: 10px;
  }

  .sb__stat:last-child {
    border-bottom-color: transparent;
    padding-bottom: 0;
  }
}

.sb__stat__value {
  display: flex;
  align-items: center;
  gap: 5px;
  width: 100%;
  min-width: 0;
  font-size: var(--sb-body-size);
  font-weight: 400;
  line-height: 1.35;
}

.sb__stat__value b {
  font-weight: 600;
}

/* The relative timestamp, with the absolute date on hover. */
.sb__date {
  position: relative;
  cursor: default;
  font-weight: 600;
  border-bottom: 1px dotted transparent;
}

.sb__date:hover {
  border-bottom-color: currentColor;
}

.sb__date__tooltip {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  padding: 6px 9px;
  border-radius: 4px;
  background: #1f1f1f;
  color: #fff;
  font-size: 13px;
  font-weight: 400;
  line-height: 1.2;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  transition: opacity 150ms ease;
}

.sb__date:hover .sb__date__tooltip {
  opacity: 1;
  visibility: visible;
}

/* ==========================================================================
   Banner
   ========================================================================== */

.sb__banner {
  width: 100%;
  max-width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 10px;
  margin: 10px 0 20px;
  background: var(--sb-banner-bg);
  border-radius: var(--sb-radius);
}

.sb__banner__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

/* v2 only (--summary covers both streaming and done): once the matter line
   starts typing, streaming is two lines too, not just done, so the default
   align-items: center above (fine for every single-line banner, v1
   included) would center the Beacon against the whole block, reading as
   too low. Align it with the first line instead. 7.65px is half of
   (24.3px line-height, body-size 18px * 1.35) minus the Beacon's own 9px. */
.sb__banner--summary {
  align-items: flex-start;
}
.sb__banner--summary .sb__banner__icon {
  margin-top: 7.65px;
}

.sb__banner__text {
  margin-left: 5px;
  font-size: var(--sb-body-size);
  line-height: 1.35;
}

/* The lead sentence. `text-transform: unset` is inherited-style defence from
   the source, where an ancestor could uppercase this text. */
.sb__banner__text span {
  text-transform: unset;
  font-weight: 600;
}

/* v2's matter line (SummaryBanner.tsx, done state): a plain second line
   under the bold activity lead, not a bullet. A <div>, not a <span>, so it
   doesn't pick up the bold rule above. */
.sb__banner__text__matter {
  margin-top: 2px;
  font-weight: 400;
}

/* ==========================================================================
   Beacon  (replaces the react-status-beacon dependency)
   ========================================================================== */

.sb__beacon {
  position: relative;
  display: inline-block;
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  margin-right: 7px;
}

.sb__beacon__dot,
.sb__beacon__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--sb-beacon);
}

.sb__beacon__ring {
  animation: sb-pulse 1.8s ease-out infinite;
}

@keyframes sb-pulse {
  0% {
    transform: scale(1);
    opacity: 0.7;
  }
  100% {
    transform: scale(2.6);
    opacity: 0;
  }
}

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

/* ==========================================================================
   v2: SummaryBanner states (loading / streaming / done / error)
   ========================================================================== */

.sb__banner--error {
  background: #fbeaea;
  color: #7a2e2e;
}

/* Loading: a shimmering placeholder bar standing in for the not-yet-arrived
   summary text. */
.sb__skeleton {
  display: inline-block;
  width: 220px;
  height: 14px;
  border-radius: 4px;
  background: linear-gradient(90deg, #f0dba8 25%, #f7e6bc 37%, #f0dba8 63%);
  background-size: 400% 100%;
  animation: sb-skeleton 1.4s ease-in-out infinite;
}

@keyframes sb-skeleton {
  0% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0 50%;
  }
}

/* Streaming: a blinking caret after whichever line is actively typing
   (SummaryBanner.tsx puts this class on the activity span while it's
   growing, then moves it to the matter line once that starts), visual
   only. The aria-live wiring that keeps this from being announced per
   token lands in Phase 3. */
.sb__banner__caret::after {
  content: "";
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 2px;
  vertical-align: -0.15em;
  background: currentColor;
  animation: sb-cursor 1s step-end infinite;
}

@keyframes sb-cursor {
  0%,
  50% {
    opacity: 1;
  }
  50.01%,
  100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sb__skeleton,
  .sb__banner__caret::after {
    animation: none;
  }
}
