/* ==========================================================================
   SP PRIMITIVES
   ==========================================================================
   Added 2026-08-12 for the solution-pages feedback rework. See
   docs/superpowers/specs/2026-08-12-solution-pages-rework-design.md §3.

   THE HEADER THIS REPLACES WAS OUT OF DATE, and misleadingly so. It said
   "shared across the three Solutions pages" and described three agents working
   on them in parallel. Those pages were retired in the September restructure;
   the reason the file exists is history, not current architecture. Anyone
   reading the old note would have believed a change here reached three pages
   that no longer exist. Corrected 2026-09-16.

   WHO ACTUALLY READS THIS FILE, and what each one uses:
     /platform/modules/root-cause-analysis   sp-vcard, sp-tags, sp-figure
     /platform/modules/anomaly-detection     sp-figure
     /platform/modules/agents                sp-tags, sp-figure
     /platform/engine                        sp-figure

   So .sp-figure--framed is the only primitive here that is genuinely shared.
   .sp-tags has two readers. .sp-vcard has ONE — Root-Cause Analysis' "Who
   benefits" grid — so a change to it is a change to that section and nothing
   else, whatever the word "primitives" in the filename suggests. If a second
   page never takes it up, it belongs in css/page/root-cause-analysis.css.

   Load it after solution-page.css, before the page-scoped sheets.

   THREE PRIMITIVES, NOTHING ELSE.
     .sp-vcard         the value card — icon, question, one value line
     .sp-tags          keyword chips that support the visual above them
     .sp-figure--framed  the demos' gradient backdrop, for non-demo figures

   Do not add a fourth thing here without a spec entry for it. A shared file
   that accumulates one-offs stops being shared and starts being a dumping
   ground.
   ========================================================================== */


/* ==========================================================================
   § THE VALUE CARD
   ==========================================================================
   Icon in an outlined circle, the reader's own question as the headline, and
   one line saying what having that answer lets them do.

   IT DOES NOT FLIP. The System Intelligence page's old benefit-card flipped,
   and a header that needs a flip to be understood is a header that does not
   explain itself — which is the feedback that produced this card. Everything
   the card says is visible at rest.

   NO NUMBERS ON THESE CARDS. The value is a sentence. An invented metric is an
   unsourced claim wearing a card, and there is no sourced figure for any of
   these. See the spec, §2.4.
   -------------------------------------------------------------------------- */

.sp-vcard__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-4);
  margin: var(--sp-6) 0 0;
  padding: 0;
  list-style: none;
}

/* Four questions do not want a 3 + 1 orphan row. */
.sp-vcard__grid--4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

@media (max-width: 1080px) {
  .sp-vcard__grid,
  .sp-vcard__grid--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 640px) {
  .sp-vcard__grid,
  .sp-vcard__grid--4 {
    grid-template-columns: minmax(0, 1fr);
  }
}

.sp-vcard {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  min-width: 0;
  padding: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-card);
  /* The lift is the "website lives" feel: small, fast, and gone the moment the
     pointer leaves. Anything springier reads as a marketing template. */
  transition: transform 180ms ease, border-color 180ms ease, background-color 180ms ease;
}

.sp-vcard:hover,
.sp-vcard:focus-within {
  transform: translateY(-3px);
  border-color: var(--accent-soft);
}

@media (prefers-reduced-motion: reduce) {
  .sp-vcard {
    transition: border-color 180ms ease;
  }

  .sp-vcard:hover,
  .sp-vcard:focus-within {
    transform: none;
  }
}

/* The circle is drawn, not filled — an outline reads as an engineering mark,
   a filled tile reads as an app icon. */
.sp-vcard__icon {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 52px;
  height: 52px;
  border: 1px solid var(--accent-soft);
  border-radius: 50%;
  color: var(--accent);
}

.sp-vcard__icon svg,
.sp-vcard__icon img {
  width: 24px;
  height: 24px;
  display: block;
}

/* This element IS an <h3> in the markup, so it should carry the site's h3
   scale: 1.125rem, weight 600, -0.02em. It was 1rem with no tracking, which
   made the card's question — the most important line on the card — set smaller
   than an h3 anywhere else on the site. */
.sp-vcard__head {
  margin: var(--sp-2) 0 0;
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.02em;
  color: var(--text);
  text-wrap: balance;
}

/* --dim (#8d99ae) on white is 2.88:1 — under WCAG AA for body text (4.5:1)
   and under even the large-text floor (3:1). This is card body copy at 14px,
   so it was the least readable text in the card carrying the most meaning.
   --muted (#5c677d) is 5.69:1 and passes; the half-step in size buys back the
   legibility the small measure costs. Same rule for every card on all four
   Solutions pages, which had the same failure. */
.sp-vcard__body {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--muted);
}


/* ==========================================================================
   § KEYWORD CHIPS
   ==========================================================================
   These replace the standalone chip sections. A chip set belongs directly
   beneath the visual it supports, so it reads as a label on that visual rather
   than as a section of its own.

   Quiet, small, dense — a Jira keyword label. They support a message. They
   never compete with it.

   TWO VARIANTS.
     .sp-tags__item   static label, not focusable, carries no behaviour
     .sp-tags__btn    pressable; pressing reveals one line in .sp-tags__value

   The pressable variant works by the mechanics bt-who established: every value
   line is in the DOM and one is shown at rest, so the whole set reads
   completely with JavaScript off and to assistive technology.

   BT-WHO ITSELF NO LONGER USES THESE. Its seven role chips became a tab strip
   (css/page/behavioral-twin.css) because that page shows a static .sp-tags__item
   row and a pressable .sp-tags__btn row within one scroll, and the two variants
   render identically — a visitor who has just learnt the first row is decoration
   has no reason to press the second. Worth weighing before putting a pressable
   set on a page that also carries a static one.
   -------------------------------------------------------------------------- */

.sp-tags {
  margin: var(--sp-4) 0 0;
}

.sp-tags__label {
  margin: 0 0 var(--sp-3);
}

.sp-tags__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.sp-tags__item,
.sp-tags__btn {
  display: inline-block;
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: var(--sp-micro);
  line-height: 1.4;
  letter-spacing: 0.01em;
  color: var(--muted);
  background: transparent;
}

.sp-tags__btn {
  cursor: pointer;
  transition: color 160ms ease, border-color 160ms ease;
}

.sp-tags__btn:hover {
  color: var(--text);
  border-color: var(--accent-soft);
}

.sp-tags__btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Pressed is the selection, so it may spend the accent. Only one chip in a set
   is ever pressed. */
.sp-tags__btn[aria-pressed="true"] {
  color: var(--accent);
  border-color: var(--accent);
}

.sp-tags__value {
  max-width: var(--sp-measure);
  margin: var(--sp-4) 0 0;
  font-size: var(--sp-body-sm);
  line-height: 1.6;
  color: var(--dim);
}


/* ==========================================================================
   § THE FRAMED FIGURE
   ==========================================================================
   The product demos sit inset on a gradient backdrop card, and that framing is
   most of why they read as a product being presented rather than a drawing on
   a page. A figure that is not a PulsarDemo flow — the Twin hero composite —
   needs the same treatment to belong.

   This deliberately restates .pd__frame's background rather than reusing the
   class. .pd__frame is shared with every demo on the site; the rework is
   additive-only, so it does not get edited, subclassed or depended on from
   outside the demo system.
   -------------------------------------------------------------------------- */

.sp-figure--framed {
  position: relative;
  padding: clamp(14px, 2.4vw, 34px);
  overflow: hidden;
  border-radius: calc(var(--radius) + 8px);
  background:
    radial-gradient(120% 140% at 8% 0%, rgba(78, 205, 196, 0.5) 0%, transparent 55%),
    radial-gradient(100% 120% at 100% 100%, rgba(91, 159, 212, 0.45) 0%, transparent 60%),
    linear-gradient(150deg, #14304a 0%, #0e2036 55%, #101b2e 100%);
}

/* The same faint engineering grid, masked away from the edges so it never
   competes with what sits on top of it. */
.sp-figure--framed::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
  background-size: 26px 26px;
  mask-image: radial-gradient(ellipse at 30% 10%, #000 20%, transparent 75%);
}

.sp-figure--framed > * {
  position: relative;
}

/* The caption inside a framed figure is hidden per spec §3.4 — the page uses
   .sr-only from main.css for that, not a variant here. */
