/* ==========================================================================
   Purple Party — component styles
   2026-09 visual direction · requires tokens.css

   Added to the output contract deliberately (see MANIFEST.md → Additions).
   The contract asked for annotated artboards; artboards that share one real
   stylesheet are worth more than eleven that each invent their own, because
   this file is the thing an engineer actually lifts.

   Every value here references a token. There are no literals below except
   0, 1, 50%, 100% and transparent.
   ========================================================================== */

/* == BASE ================================================================= */

.pp-page {
  margin: 0;
  background: var(--pp-ground);
  color: var(--pp-ink);
  font-family: var(--pp-sans);
  font-size: var(--pp-text-sm);
  line-height: var(--pp-lh-sm);
  -webkit-font-smoothing: antialiased;
}

.pp-prose {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-lg);
  line-height: var(--pp-lh-lg);
  color: var(--pp-ink);
  max-width: var(--pp-measure-prose);
  text-wrap: pretty;
}

.pp-label {
  font-family: var(--pp-sans);
  font-size: var(--pp-text-2xs);
  line-height: var(--pp-lh-2xs);
  letter-spacing: var(--pp-track-label);
  text-transform: uppercase;
  color: var(--pp-ink-4);
}

.pp-meta  { font-size: var(--pp-text-xs); color: var(--pp-ink-3); }
.pp-note  { font-size: var(--pp-text-xs); line-height: var(--pp-lh-xs);
            color: var(--pp-ink-3); max-width: var(--pp-measure-note); }

:where(a, button, [tabindex]):focus-visible {
  outline: var(--pp-focus);
  outline-offset: var(--pp-focus-offset);
}

/* == 1. POST CARD ========================================================= */

/* No card. The "card" is a band of the page separated by one hairline, with
   hierarchy carried entirely by type. Boxes-in-boxes is the dashboard idiom
   this product is trying not to be. */

.pp-post {
  border-bottom: var(--pp-hair) solid var(--pp-rule);
  padding: var(--pp-s6) 0;
  display: flex;
  gap: var(--pp-s4);
  align-items: flex-start;
}
.pp-post__portrait {
  flex: 0 0 auto;
  width: 44px; height: 44px;
  border-radius: var(--pp-r-pill);
  border: var(--pp-hair) solid var(--pp-rule-strong);
  background: var(--pp-sunken) center/cover no-repeat;
}
.pp-post__body { flex: 1 1 auto; min-width: 0; }

.pp-post__head {
  display: flex; flex-wrap: wrap;
  gap: var(--pp-s3);
  align-items: baseline; justify-content: space-between;
}
.pp-post__name {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-xl);
  color: var(--pp-ink);
  background: transparent; border: 0; padding: 0;
  border-bottom: var(--pp-hair) solid var(--pp-rule-strong);
  cursor: pointer;
}
.pp-post__name:hover { border-bottom-color: var(--pp-ink-3); }

/* The one dynamic relational fact. Not a badge, not a stat — a sentence, set
   in the interface sans so it reads as the system speaking, indented behind a
   rule so it is clearly not the author's words. */
.pp-post__relation {
  margin-top: var(--pp-s2);
  padding-left: var(--pp-s3);
  border-left: var(--pp-mark) solid var(--pp-rule-strong);
  font-size: var(--pp-text-xs);
  line-height: var(--pp-lh-xs);
  color: var(--pp-ink-3);
  max-width: var(--pp-measure-note);
}
/* Earned purple: this relation exists BECAUSE the two of them crossed the
   divide. The only relational fact that gets the accent. */
.pp-post__relation--converged {
  border-left-color: var(--pp-converge);
  color: var(--pp-converge-ink);
}
/* Empty state — the viewer has no assessment, so there is nothing true to say.
   It says that, rather than guessing or hiding. */
.pp-post__relation--empty {
  border-left-style: dashed;
  border-left-color: var(--pp-rule-dashed);
  color: var(--pp-ink-4);
}

.pp-post__text {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-lg);
  line-height: var(--pp-lh-lg);
  margin-top: var(--pp-s4);
  max-width: var(--pp-measure-prose);
  text-wrap: pretty;
}

.pp-post__actions {
  display: flex; flex-wrap: wrap;
  gap: var(--pp-s2);
  margin-top: var(--pp-s4);
}
.pp-act {
  font-family: var(--pp-sans);
  font-size: var(--pp-text-xs);
  color: var(--pp-ink-2);
  background: var(--pp-surface);
  border: var(--pp-hair) solid var(--pp-rule-strong);
  border-radius: var(--pp-r-hair);
  padding: var(--pp-s2) var(--pp-s3);
  cursor: pointer;
  transition: border-color var(--pp-dur-1) var(--pp-ease),
              color var(--pp-dur-1) var(--pp-ease);
}
.pp-act:hover { border-color: var(--pp-ink-4); color: var(--pp-ink); }
.pp-act[aria-pressed="true"] {
  border-color: var(--pp-ink); color: var(--pp-ink);
  background: var(--pp-sunken);
}

/* == 2. DISTRIBUTION MARKER =============================================== */

/* The signature element. One shape, six jobs: calibration, cue sensitivity,
   poll response, forecast record, assessment band, community spread.
   Minimum legible width 120px; the strip stays 1px-crisp at any width because
   everything inside it is drawn in percentage terms. */

.pp-dist {
  display: inline-block;
  width: 120px;                 /* the floor; callers may widen             */
  vertical-align: middle;
}
.pp-dist--wide  { width: 220px; }
.pp-dist--full  { width: 100%; max-width: 320px; }

.pp-dist__plot {
  position: relative;
  height: 26px;
  background: var(--pp-dist-track);
  border-radius: var(--pp-r-hair);
  overflow: hidden;
}
.pp-dist--wide .pp-dist__plot,
.pp-dist--full .pp-dist__plot { height: 34px; }

/* the spread itself, as thin columns */
.pp-dist__bars { position: absolute; inset: 0; display: flex; align-items: flex-end; }
.pp-dist__bar  { flex: 1 1 0; background: var(--pp-dist-bar); }
.pp-dist__bar--a { background: var(--pp-pole-a); }
.pp-dist__bar--b { background: var(--pp-pole-b); background-image: var(--pp-pole-b-texture); }

/* middle half */
.pp-dist__iqr {
  position: absolute; top: 0; bottom: 0;
  background: var(--pp-dist-iqr);
  mix-blend-mode: multiply;
  opacity: .55;
}

/* where the two clusters actually overlap — the one purple in the marker */
.pp-dist__overlap {
  position: absolute; top: 0; bottom: 0;
  background: var(--pp-converge-wash-2);
  border-left: var(--pp-hair) solid var(--pp-converge-line);
  border-right: var(--pp-hair) solid var(--pp-converge-line);
}

.pp-dist__median {
  position: absolute; top: 0; bottom: 0;
  width: var(--pp-hair);
  background: var(--pp-dist-median);
}

/* You: always a filled dot. Them: always a hollow ring. Never colour alone. */
.pp-dist__you, .pp-dist__them {
  position: absolute; top: 50%;
  width: 9px; height: 9px;
  border-radius: var(--pp-r-pill);
  transform: translate(-50%, -50%);
}
.pp-dist__you  { background: var(--pp-dist-you);
                 box-shadow: 0 0 0 var(--pp-mark) var(--pp-dist-track); }
.pp-dist__them { background: transparent;
                 border: var(--pp-mark) solid var(--pp-dist-them);
                 box-shadow: 0 0 0 var(--pp-hair) var(--pp-dist-track); }

/* A range answer is a capsule, not a point — the product never asks anyone to
   be more precise than they are. */
.pp-dist__band {
  position: absolute; top: 50%;
  height: 11px;
  transform: translateY(-50%);
  border: var(--pp-mark) solid var(--pp-dist-you);
  border-radius: var(--pp-r-pill);
  background: transparent;
}
.pp-dist__truth {                 /* calibration only: the actual answer     */
  position: absolute; top: 0; bottom: 0;
  width: var(--pp-mark);
  background: var(--pp-ink);
}

.pp-dist__scale {
  display: flex; justify-content: space-between;
  margin-top: var(--pp-s1);
  font-size: var(--pp-text-2xs);
  color: var(--pp-ink-4);
}
.pp-dist__caption {
  margin-top: var(--pp-s1);
  font-size: var(--pp-text-2xs);
  line-height: var(--pp-lh-2xs);
  color: var(--pp-ink-3);
}

/* Interactive variant: arrow keys move the band, home/end jump to the ends. */
.pp-dist[tabindex]:focus-visible .pp-dist__plot {
  outline: var(--pp-focus); outline-offset: var(--pp-focus-offset);
}

/* == 3. APPARATUS — AI OUTPUT ============================================= */

/* A readout, not a speaker. Cool paper, monospace header, panel composition
   always stated. There is no avatar and no name because there is no person. */

.pp-apparatus {
  background: var(--pp-apparatus);
  border: var(--pp-hair) solid var(--pp-apparatus-rule);
  border-radius: var(--pp-r-soft);
  color: var(--pp-apparatus-ink);
  padding: var(--pp-s5) var(--pp-s5) var(--pp-s4);
  max-width: var(--pp-measure-prose);
}
.pp-apparatus__head {
  font-family: var(--pp-mono);
  font-size: var(--pp-text-2xs);
  letter-spacing: var(--pp-track-label);
  text-transform: uppercase;
  color: var(--pp-apparatus-ink-2);
  display: flex; flex-wrap: wrap;
  gap: var(--pp-s2) var(--pp-s3);
  align-items: center;
  padding-bottom: var(--pp-s3);
  border-bottom: var(--pp-hair) solid var(--pp-apparatus-rule);
}
/* "7 of 10 models" is the honest unit. Never "the AI says". The tally is drawn
   as ticks so the split is visible before the number is read. */
.pp-apparatus__tally { display: flex; gap: 3px; align-items: center; }
.pp-apparatus__tick {
  width: 3px; height: 12px;
  background: var(--pp-apparatus-tick);
  border-radius: var(--pp-hair);
}
.pp-apparatus__tick--off { background: transparent;
  box-shadow: inset 0 0 0 var(--pp-hair) var(--pp-apparatus-tick); }

.pp-apparatus__finding {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-md);
  line-height: var(--pp-lh-md);
  color: var(--pp-apparatus-ink);
  margin-top: var(--pp-s4);
  max-width: var(--pp-measure-note);
}
.pp-apparatus__rows { margin-top: var(--pp-s4); }
.pp-apparatus__row {
  display: flex; flex-wrap: wrap;
  gap: var(--pp-s2) var(--pp-s4);
  padding: var(--pp-s2) 0;
  border-top: var(--pp-hair) solid var(--pp-apparatus-rule);
  font-size: var(--pp-text-xs);
  line-height: var(--pp-lh-xs);
}
.pp-apparatus__key {
  font-family: var(--pp-mono);
  font-size: var(--pp-text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--pp-track-label);
  color: var(--pp-apparatus-ink-2);
  flex: 0 0 122px;
}
.pp-apparatus__val { flex: 1 1 220px; min-width: 0; color: var(--pp-apparatus-ink); }
.pp-apparatus__foot {
  margin-top: var(--pp-s4);
  padding-top: var(--pp-s3);
  border-top: var(--pp-hair) solid var(--pp-apparatus-rule);
  font-family: var(--pp-mono);
  font-size: var(--pp-text-2xs);
  line-height: var(--pp-lh-2xs);
  color: var(--pp-apparatus-ink-2);
}

/* Split panels are informative. The split state is drawn AT LEAST as
   prominently as agreement: two stacked columns, both fully legible. */
.pp-apparatus__split {
  display: flex; flex-wrap: wrap;
  gap: var(--pp-s5);
  margin-top: var(--pp-s4);
}
.pp-apparatus__side { flex: 1 1 240px; min-width: 0; }
.pp-apparatus__side-head {
  font-family: var(--pp-mono);
  font-size: var(--pp-text-2xs);
  text-transform: uppercase;
  letter-spacing: var(--pp-track-label);
  color: var(--pp-apparatus-ink-2);
  padding-bottom: var(--pp-s2);
  margin-bottom: var(--pp-s3);
  border-bottom: var(--pp-mark) solid var(--pp-apparatus-tick);
}

/* Not adjudicable is an ANSWER. It gets the same weight as any other, and no
   warning colour, no icon, nothing that reads as breakage. */
.pp-apparatus--notadj .pp-apparatus__finding { font-style: normal; }
.pp-apparatus--notadj .pp-apparatus__head { color: var(--pp-apparatus-ink); }

/* == 4. CLAIM STATUS CHIP ================================================ */

/* Six states. Each is distinguishable without colour: the border style and the
   leading mark differ. None of them is red; none of them is a warning. */

.pp-claim {
  display: inline-flex; align-items: center;
  gap: var(--pp-s2);
  font-family: var(--pp-sans);
  font-size: var(--pp-text-xs);
  border-radius: var(--pp-r-hair);
  padding: var(--pp-s1) var(--pp-s3);
  border: var(--pp-hair) solid var(--pp-rule-strong);
  background: transparent;
  color: var(--pp-ink-2);
}
.pp-claim__mark {
  font-family: var(--pp-mono);
  font-size: var(--pp-text-2xs);
  line-height: 1;
  opacity: .9;
}

/* nobody has looked at this — absence of review, not approval */
.pp-claim--unexamined {
  border-style: dashed; border-color: var(--pp-rule-dashed);
  color: var(--pp-ink-4);
}
/* challenged, and it survived */
.pp-claim--held {
  border-color: var(--pp-converge-line);
  background: var(--pp-converge-wash);
  color: var(--pp-converge-ink);
}
/* the panel disagreed with itself — a real finding */
.pp-claim--contested {
  border-color: var(--pp-converge-line);
  color: var(--pp-converge-ink);
}
/* not an empirical question */
.pp-claim--notadj { border-color: var(--pp-rule-strong); color: var(--pp-ink-2); }
/* evidence went the other way and the author let it stand */
.pp-claim--against { border-color: var(--pp-ink); color: var(--pp-ink); }
/* the author fixed it themselves — the highest-status state on the platform */
.pp-claim--corrected {
  border-color: var(--pp-earned-line);
  background: var(--pp-earned-wash);
  color: var(--pp-earned-ink);
}

.pp-claim-aside {
  font-size: var(--pp-text-xs);
  line-height: var(--pp-lh-xs);
  color: var(--pp-ink-3);
  max-width: var(--pp-measure-note);
}

/* == 5. ASSESSMENT SENTENCE + BAND ======================================= */

/* The sentence is the result. The band is the evidence for it, and it is
   secondary — smaller, quieter, below. A number alone would be a score, and
   this product does not score people. */

.pp-assess { padding-bottom: var(--pp-s6); border-bottom: var(--pp-hair) solid var(--pp-rule); }
.pp-assess__dim {
  font-family: var(--pp-sans);
  font-size: var(--pp-text-2xs);
  letter-spacing: var(--pp-track-label);
  text-transform: uppercase;
  color: var(--pp-ink-4);
}
.pp-assess__sentence {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-xl);
  line-height: var(--pp-lh-xl);
  color: var(--pp-ink);
  max-width: var(--pp-measure-lede);
  margin-top: var(--pp-s3);
  text-wrap: pretty;
}
.pp-assess__marker { margin-top: var(--pp-s5); }
.pp-assess__note {
  margin-top: var(--pp-s4);
  padding-left: var(--pp-s3);
  border-left: var(--pp-mark) solid var(--pp-rule);
  font-size: var(--pp-text-xs);
  line-height: var(--pp-lh-xs);
  color: var(--pp-ink-3);
  max-width: var(--pp-measure-note);
}
/* withheld is a choice, and it looks like one */
.pp-assess--withheld .pp-assess__sentence { color: var(--pp-ink-4); }
.pp-assess__withheld-slot {
  margin-top: var(--pp-s5);
  height: 26px;
  border: var(--pp-hair) dashed var(--pp-rule-dashed);
  border-radius: var(--pp-r-hair);
}

/* == 6. ESSAY SECTION WITH THREAD ======================================== */

.pp-section { padding: var(--pp-s6) 0; border-bottom: var(--pp-hair) solid var(--pp-rule); }
.pp-section__head {
  display: flex; flex-wrap: wrap; gap: var(--pp-s3);
  align-items: baseline; justify-content: space-between;
  margin-bottom: var(--pp-s4);
}
.pp-section__body { font-family: var(--pp-serif);
  font-size: var(--pp-text-lg); line-height: var(--pp-lh-lg);
  max-width: var(--pp-measure-prose); text-wrap: pretty; }

/* "revised since the objection" — warm, never an alert */
.pp-section__revised {
  margin-top: var(--pp-s4);
  padding: var(--pp-s3) var(--pp-s4);
  background: var(--pp-earned-wash);
  border-left: var(--pp-mark) solid var(--pp-earned-line);
  font-size: var(--pp-text-xs);
  line-height: var(--pp-lh-xs);
  color: var(--pp-earned-ink);
  max-width: var(--pp-measure-note);
}

.pp-thread-anchor {
  margin-top: var(--pp-s5);
  padding-left: var(--pp-s4);
  border-left: var(--pp-hair) solid var(--pp-rule);
}

/* == 7. VERSION / DIFF =================================================== */

/* The inversion that is the whole product: a revised essay must LOOK more
   trustworthy than a pristine one. Revision is set in the earned palette and
   given more room, not less. Removed text is legible and struck with a
   hairline — never red, never hidden, never shamed. */

.pp-diff { border: var(--pp-hair) solid var(--pp-rule); border-radius: var(--pp-r-soft); overflow: hidden; }
.pp-diff__head {
  display: flex; flex-wrap: wrap; gap: var(--pp-s3);
  align-items: baseline; justify-content: space-between;
  padding: var(--pp-s3) var(--pp-s4);
  background: var(--pp-earned-wash);
  border-bottom: var(--pp-hair) solid var(--pp-earned-line);
  color: var(--pp-earned-ink);
  font-size: var(--pp-text-xs);
}
.pp-diff__body { padding: var(--pp-s4); background: var(--pp-surface); }
.pp-diff__was, .pp-diff__now {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-md);
  line-height: var(--pp-lh-md);
  max-width: var(--pp-measure-prose);
  padding: var(--pp-s3) 0;
}
.pp-diff__was {
  color: var(--pp-ink-3);
  text-decoration: line-through;
  text-decoration-thickness: var(--pp-hair);
  text-decoration-color: var(--pp-ink-4);
}
.pp-diff__now { color: var(--pp-ink); border-left: var(--pp-mark) solid var(--pp-earned-line);
                padding-left: var(--pp-s3); }
.pp-diff__because {
  margin-top: var(--pp-s3); padding-top: var(--pp-s3);
  border-top: var(--pp-hair) solid var(--pp-rule);
  font-size: var(--pp-text-xs); line-height: var(--pp-lh-xs);
  color: var(--pp-ink-3); max-width: var(--pp-measure-note);
}

.pp-version {
  font-family: var(--pp-sans);
  font-size: var(--pp-text-2xs);
  letter-spacing: var(--pp-track-label);
  text-transform: uppercase;
  color: var(--pp-earned-ink);
  border: var(--pp-hair) solid var(--pp-earned-line);
  background: var(--pp-earned-wash);
  border-radius: var(--pp-r-hair);
  padding: var(--pp-s1) var(--pp-s2);
}
.pp-version--v1 {           /* never revised — quieter, not cleaner */
  color: var(--pp-ink-4);
  border-style: dashed; border-color: var(--pp-rule-dashed);
  background: transparent;
}

/* == 8. POLL RESULT ====================================================== */

.pp-poll__q {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-2xl);
  line-height: var(--pp-lh-2xl);
  max-width: var(--pp-measure-lede);
  letter-spacing: var(--pp-track-tight);
  text-wrap: pretty;
}
.pp-poll__rows { margin-top: var(--pp-s5); }
.pp-poll__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--pp-s2) var(--pp-s4);
  align-items: center;
  padding: var(--pp-s3) 0;
  border-top: var(--pp-hair) solid var(--pp-rule);
}
.pp-poll__answer { font-family: var(--pp-serif); font-size: var(--pp-text-md); }
.pp-poll__row--yours .pp-poll__answer { color: var(--pp-ink); }
.pp-poll__row--yours { position: relative; }
.pp-poll__row--yours::before {
  content: ""; position: absolute; left: calc(var(--pp-s4) * -1); top: 0; bottom: 0;
  width: var(--pp-mark); background: var(--pp-ink);
}
.pp-poll__share { font-family: var(--pp-mono); font-size: var(--pp-text-xs); color: var(--pp-ink-3); }
.pp-poll__bar { grid-column: 1 / -1; height: 6px; background: var(--pp-dist-track); border-radius: var(--pp-r-hair); }
.pp-poll__bar > i { display: block; height: 100%; background: var(--pp-dist-bar); border-radius: var(--pp-r-hair); }
/* an answer both clusters chose at similar rates — genuine common ground */
.pp-poll__row--converged .pp-poll__bar > i { background: var(--pp-converge); }
.pp-poll__row--converged .pp-poll__answer { color: var(--pp-converge-ink); }

/* The doorway out of your own group. Not a button — a sentence you can walk
   through, because the point is curiosity rather than conversion. */
.pp-poll__doorway {
  margin-top: var(--pp-s5);
  display: flex; flex-wrap: wrap; gap: var(--pp-s3);
}
.pp-doorway {
  font-family: var(--pp-sans);
  font-size: var(--pp-text-xs);
  color: var(--pp-ink-2);
  background: transparent;
  border: var(--pp-hair) solid var(--pp-rule-strong);
  border-radius: var(--pp-r-pill);
  padding: var(--pp-s2) var(--pp-s3);
  cursor: pointer;
  transition: border-color var(--pp-dur-1) var(--pp-ease), color var(--pp-dur-1) var(--pp-ease);
}
.pp-doorway:hover { border-color: var(--pp-ink-4); color: var(--pp-ink); }
.pp-doorway--across { border-color: var(--pp-converge-line); color: var(--pp-converge-ink); }

/* == 9. THREAD =========================================================== */

.pp-thread { display: flex; flex-direction: column; }
.pp-turn {
  padding: var(--pp-s5) 0;
  border-top: var(--pp-hair) solid var(--pp-rule);
}
.pp-turn__who {
  display: flex; flex-wrap: wrap; gap: var(--pp-s3);
  align-items: baseline;
  font-size: var(--pp-text-xs); color: var(--pp-ink-3);
}
.pp-turn__body {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-md); line-height: var(--pp-lh-md);
  color: var(--pp-ink); margin-top: var(--pp-s3);
  max-width: var(--pp-measure-prose);
}
/* a turn that reached across — the ranking reason, stated */
.pp-turn--bridged { border-left: var(--pp-mark) solid var(--pp-converge); padding-left: var(--pp-s4); }
.pp-turn__why {
  margin-top: var(--pp-s3);
  font-size: var(--pp-text-2xs); line-height: var(--pp-lh-2xs);
  color: var(--pp-converge-ink);
}
/* duplicate objections are merged rather than repeated — the count is honest
   about how many people raised it, without staging a pile-on */
.pp-turn__merged {
  margin-top: var(--pp-s3);
  padding: var(--pp-s2) var(--pp-s3);
  background: var(--pp-sunken);
  border-radius: var(--pp-r-hair);
  font-size: var(--pp-text-2xs); color: var(--pp-ink-3);
}

/* == 10. EARNED CREDENTIAL ROW =========================================== */

.pp-earned {
  background: var(--pp-earned-wash);
  border: var(--pp-hair) solid var(--pp-earned-line);
  border-radius: var(--pp-r-soft);
  padding: var(--pp-s6) var(--pp-s5);
}
.pp-earned__title {
  font-family: var(--pp-serif);
  font-weight: 400;
  font-size: var(--pp-text-xl);
  margin: 0 0 var(--pp-s1);
  color: var(--pp-ink);
}
.pp-earned__group { margin-top: var(--pp-s6); }
.pp-earned__group-label {
  font-family: var(--pp-sans);
  font-size: var(--pp-text-2xs);
  letter-spacing: var(--pp-track-label);
  text-transform: uppercase;
  color: var(--pp-earned-ink);
  margin-bottom: var(--pp-s3);
}
.pp-earned__row {
  display: flex; flex-wrap: wrap; gap: var(--pp-s3);
  align-items: baseline; justify-content: space-between;
  padding: var(--pp-s3) 0;
  border-bottom: var(--pp-hair) solid var(--pp-earned-rule);
}
.pp-earned__row:last-child { border-bottom: 0; }
.pp-earned__what { font-family: var(--pp-serif); font-size: var(--pp-text-md); color: var(--pp-ink); }
.pp-earned__how  { font-size: var(--pp-text-2xs); color: var(--pp-earned-ink); text-align: right; }

/* == 11. EMPTY AND LOW-DATA STATES ======================================= */

/* Frequent, and therefore designed. Each says what is missing and why, in the
   product's own voice. None of them uses an icon, an exclamation mark, or a
   colour that implies something went wrong. */

.pp-empty {
  border: var(--pp-hair) dashed var(--pp-rule-dashed);
  border-radius: var(--pp-r-soft);
  padding: var(--pp-s6) var(--pp-s5);
  max-width: var(--pp-measure-note);
}
.pp-empty__head {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-lg);
  line-height: var(--pp-lh-lg);
  color: var(--pp-ink-2);
}
.pp-empty__why {
  margin-top: var(--pp-s3);
  font-size: var(--pp-text-xs); line-height: var(--pp-lh-xs);
  color: var(--pp-ink-3);
}
/* a cell suppressed because it would identify someone */
.pp-empty--suppressed { border-style: solid; border-color: var(--pp-rule-strong); }
.pp-empty--suppressed .pp-empty__head { font-family: var(--pp-mono);
  font-size: var(--pp-text-xs); letter-spacing: var(--pp-track-label);
  text-transform: uppercase; color: var(--pp-ink-3); }

/* == RESPONSIVE ========================================================== */

@media (max-width: 720px) {
  .pp-apparatus__key { flex-basis: 100%; }
  .pp-post { gap: var(--pp-s3); }
  .pp-poll__q { font-size: var(--pp-text-xl); }
}

/* == PAGE SHELL ========================================================== */

/* Not in the component list, but the compositions need it and it is product
   code, not artboard chrome. Typography-led: a serif wordmark, sans navigation,
   one hairline, no bar, no shadow, no background of its own. */

.pp-shell { padding: var(--pp-s7) var(--pp-s5) var(--pp-s9); max-width: 1240px; margin: 0 auto; }

.pp-topbar {
  display: flex; flex-wrap: wrap;
  gap: var(--pp-s3) var(--pp-s6);
  align-items: baseline; justify-content: space-between;
  border-bottom: var(--pp-hair) solid var(--pp-rule);
  padding-bottom: var(--pp-s3);
  margin-bottom: var(--pp-s7);
}
.pp-wordmark {
  font-family: var(--pp-serif);
  font-size: var(--pp-text-sm);
  letter-spacing: var(--pp-track-mark);
  text-transform: uppercase;
  color: var(--pp-converge);          /* wayfinding purple — see RATIONALE §3 */
  text-decoration: none;
}
.pp-nav { display: flex; flex-wrap: wrap; gap: var(--pp-s5); align-items: baseline; flex: 1 1 auto; }
.pp-nav a {
  font-size: var(--pp-text-sm);
  color: var(--pp-ink-3);
  text-decoration: none;
  border-bottom: var(--pp-hair) solid transparent;
  padding-bottom: 3px;
  transition: color var(--pp-dur-1) var(--pp-ease), border-color var(--pp-dur-1) var(--pp-ease);
}
.pp-nav a:hover { color: var(--pp-ink); border-bottom-color: var(--pp-rule); }
.pp-nav a[aria-current="page"] { color: var(--pp-converge-ink); border-bottom-color: var(--pp-converge); }
.pp-viewer { display: flex; gap: var(--pp-s2); align-items: baseline;
  font-size: var(--pp-text-xs); color: var(--pp-ink-3); }
.pp-viewer b { font-weight: 400; color: var(--pp-ink); }

.pp-cols { display: flex; flex-wrap: wrap; gap: var(--pp-s7); align-items: flex-start; }
.pp-rail { flex: 1 1 220px; min-width: 0; }
.pp-main { flex: 3 1 520px; min-width: 0; }
.pp-aside { flex: 1 1 280px; min-width: 0; }

.pp-rail__group { margin-bottom: var(--pp-s6); }
.pp-rail__items { display: flex; flex-direction: column; }
.pp-rail__item {
  text-align: left;
  font-family: var(--pp-sans);
  font-size: var(--pp-text-sm);
  color: var(--pp-ink);
  background: transparent;
  border: none;
  border-left: var(--pp-mark) solid var(--pp-rule);
  padding: var(--pp-s2) var(--pp-s3);
  cursor: pointer;
}
.pp-rail__item span { display: block; font-size: var(--pp-text-2xs);
  color: var(--pp-ink-4); margin-top: 3px; }
.pp-rail__item[aria-current="true"] {
  border-left-color: var(--pp-ink);
  background: var(--pp-sunken);
}

.pp-viewhead {
  display: flex; flex-wrap: wrap; gap: var(--pp-s3);
  align-items: baseline; justify-content: space-between;
  border-bottom: var(--pp-hair) solid var(--pp-rule);
  padding-bottom: var(--pp-s3);
}
.pp-viewhead h1 { font-family: var(--pp-serif); font-weight: 400;
  font-size: var(--pp-text-2xl); margin: 0; letter-spacing: var(--pp-track-tight); }

@media (max-width: 900px) {
  .pp-rail { order: 2; flex-basis: 100%; }
  .pp-main { order: 1; }
  .pp-aside { order: 3; flex-basis: 100%; }
  .pp-nav { order: 3; flex-basis: 100%; gap: var(--pp-s4); }
}

/* == PROPS AND TIPS ======================================================= */

/* Props are free and typed; the type is the information. There is no total —
   a single number is a scoreboard and four typed numbers are a description.
   Tips are rare, require a note, and never touch ranking. See
   docs/08-props-and-tips-demo.md §1 for the four load-bearing rules. */

.pp-props { display: flex; flex-wrap: wrap; gap: var(--pp-s2); }
.pp-prop {
  display: inline-flex; align-items: baseline; gap: var(--pp-s2);
  font-family: var(--pp-sans); font-size: var(--pp-text-xs);
  color: var(--pp-ink-2); background: var(--pp-surface);
  border: var(--pp-hair) solid var(--pp-rule-strong);
  border-radius: var(--pp-r-hair); padding: var(--pp-s2) var(--pp-s3);
  cursor: pointer;
  transition: border-color var(--pp-dur-1) var(--pp-ease), color var(--pp-dur-1) var(--pp-ease);
}
.pp-prop:hover:not(:disabled) { border-color: var(--pp-ink-4); color: var(--pp-ink); }
.pp-prop__d { font-family: var(--pp-mono); font-size: .8em; opacity: .55; }
.pp-prop__n { font-family: var(--pp-mono); font-size: var(--pp-text-2xs); color: var(--pp-ink-3); }
.pp-prop[aria-pressed="true"] {
  border-color: var(--pp-ink); color: var(--pp-ink); background: var(--pp-sunken);
}
.pp-prop:disabled { opacity: .5; cursor: not-allowed; }

/* "Fair to the other side" can only be given by someone who disagrees with the
   author, which makes it unfakeable by your own side. The one prop that earns
   purple. */
.pp-prop--fair { border-color: var(--pp-converge-line); color: var(--pp-converge-ink); }
.pp-prop--fair .pp-prop__n { color: var(--pp-converge-ink); }
.pp-prop--fair[aria-pressed="true"] {
  border-color: var(--pp-converge); background: var(--pp-converge-wash);
  color: var(--pp-converge-ink);
}

/* Composition first, amount second and small. Never a per-member total. */
.pp-support { margin-top: var(--pp-s4); }
.pp-support__line { font-size: var(--pp-text-xs); color: var(--pp-ink-3); }
.pp-support__line b { font-weight: 400; color: var(--pp-ink);
  font-family: var(--pp-serif); font-size: var(--pp-text-sm); }
.pp-support__amt { font-family: var(--pp-mono); font-size: var(--pp-text-2xs);
  color: var(--pp-ink-4); }
.pp-support__split { display: inline-flex; align-items: center; gap: var(--pp-s2);
  font-family: var(--pp-sans); font-size: var(--pp-text-2xs);
  letter-spacing: var(--pp-track-label); text-transform: uppercase;
  color: var(--pp-converge-ink); border: var(--pp-hair) solid var(--pp-converge-line);
  background: var(--pp-converge-wash); border-radius: var(--pp-r-hair);
  padding: var(--pp-s1) var(--pp-s2); margin-left: var(--pp-s2); }

/* The line readers need, wherever the mechanic first appears. */
.pp-support__rule { margin-top: var(--pp-s3); font-size: var(--pp-text-xs);
  line-height: var(--pp-lh-xs); color: var(--pp-ink-2);
  border-left: var(--pp-mark) solid var(--pp-rule-strong);
  padding-left: var(--pp-s3); max-width: var(--pp-measure-note); }
.pp-support__rule b { font-weight: 400; color: var(--pp-ink); }

/* Notes are the gift; the money is the underline. */
.pp-notes { margin-top: var(--pp-s5); }
.pp-note-row { padding: var(--pp-s4) 0; border-top: var(--pp-hair) solid var(--pp-rule);
  max-width: var(--pp-measure-note); }
.pp-note-row__who { display: flex; flex-wrap: wrap; gap: var(--pp-s2) var(--pp-s3);
  align-items: baseline; font-size: var(--pp-text-xs); color: var(--pp-ink-3); }
.pp-note-row__who b { font-weight: 400; font-family: var(--pp-serif);
  font-size: var(--pp-text-sm); color: var(--pp-ink); }
.pp-note-row__amt { font-family: var(--pp-mono); font-size: var(--pp-text-2xs);
  color: var(--pp-ink-4); }
.pp-note-row__t { font-family: var(--pp-serif); font-size: var(--pp-text-md);
  line-height: var(--pp-lh-md); color: var(--pp-ink); margin-top: var(--pp-s2);
  text-wrap: pretty; }
.pp-note-row__x { font-size: var(--pp-text-2xs); color: var(--pp-ink-4);
  margin-top: var(--pp-s2); }

/* The flagship: an author paying the person who corrected her. */
.pp-note-row--flag { border-left: var(--pp-mark) solid var(--pp-earned-line);
  background: var(--pp-earned-wash); padding-left: var(--pp-s4);
  padding-right: var(--pp-s4); border-top-color: var(--pp-earned-line);
  border-radius: var(--pp-r-hair); }
.pp-note-row--flag .pp-note-row__x { color: var(--pp-earned-ink); }

.pp-props-only { font-size: var(--pp-text-2xs); line-height: var(--pp-lh-2xs);
  color: var(--pp-ink-4); margin-top: var(--pp-s3); max-width: var(--pp-measure-note); }

/* --- the tip panel: a form, done carefully. No web3 chrome. --------------- */
.pp-tip { margin-top: var(--pp-s4); border: var(--pp-hair) solid var(--pp-rule-strong);
  border-radius: var(--pp-r-soft); padding: var(--pp-s5);
  max-width: 480px; background: var(--pp-surface); }
.pp-tip[hidden] { display: none !important; }
.pp-tip__k { font-size: var(--pp-text-2xs); letter-spacing: var(--pp-track-label);
  text-transform: uppercase; color: var(--pp-ink-4); margin-bottom: var(--pp-s3); }
.pp-tip__amts { display: flex; flex-wrap: wrap; gap: var(--pp-s2); align-items: center; }
.pp-tip__amts input[type=number] { width: 84px; font-family: var(--pp-mono);
  font-size: var(--pp-text-xs); color: var(--pp-ink); background: var(--pp-ground);
  border: var(--pp-hair) solid var(--pp-rule-strong); border-radius: var(--pp-r-hair);
  padding: var(--pp-s2) var(--pp-s3); }
.pp-tip textarea { width: 100%; box-sizing: border-box; min-height: 84px; resize: vertical;
  font-family: var(--pp-serif); font-size: var(--pp-text-sm); line-height: var(--pp-lh-sm);
  color: var(--pp-ink); background: var(--pp-ground);
  border: var(--pp-hair) solid var(--pp-rule-strong); border-radius: var(--pp-r-hair);
  padding: var(--pp-s3); margin-top: var(--pp-s3); }
.pp-tip textarea:focus { outline: none; border-color: var(--pp-ink-4); }
.pp-tip__foot { display: flex; flex-wrap: wrap; gap: var(--pp-s3);
  align-items: center; justify-content: space-between; margin-top: var(--pp-s3); }
.pp-tip__count { font-family: var(--pp-mono); font-size: var(--pp-text-2xs); color: var(--pp-ink-4); }
.pp-tip__priv { font-size: var(--pp-text-2xs); line-height: var(--pp-lh-2xs);
  color: var(--pp-ink-3); margin-top: var(--pp-s3); }
.pp-tip__chain { font-family: var(--pp-mono); font-size: var(--pp-text-2xs);
  color: var(--pp-ink-4); margin-top: var(--pp-s3);
  padding-top: var(--pp-s3); border-top: var(--pp-hair) solid var(--pp-rule); }
.pp-tip__done { font-family: var(--pp-serif); font-size: var(--pp-text-md);
  line-height: var(--pp-lh-md); color: var(--pp-ink); }

/* --- profile: supported work -------------------------------------------- */
.pp-supported__row { display: flex; flex-wrap: wrap; gap: var(--pp-s2) var(--pp-s4);
  align-items: baseline; justify-content: space-between;
  padding: var(--pp-s3) 0; border-bottom: var(--pp-hair) solid var(--pp-rule); }
.pp-supported__w { flex: 1 1 240px; min-width: 0; font-size: var(--pp-text-sm);
  color: var(--pp-ink); }
.pp-supported__n { font-size: var(--pp-text-2xs); color: var(--pp-ink-3);
  text-align: right; flex: 0 0 auto; }

/* Four typed props is the design — a single total would be a scoreboard — but
   four labelled buttons is a lot of vertical on a phone, so tighten rather
   than truncate. Labels stay full; nothing is abbreviated away. */
@media (max-width: 620px) {
  .pp-prop { font-size: 11.5px; padding: 5px 8px; gap: 5px; }
  .pp-props { gap: 5px; }
  .pp-prop__d { display: none; }
}
