/* ─────────────────────────────────────────────────────────────────────────────
   stance-tree.css — 🌳 the topic tree of stances
   ─────────────────────────────────────────────────────────────────────────────
   Companion to stance-tree.js. Two rules govern everything below:

   1. NO PER-ISSUE SELECTORS. Every colour on a branch or a leaf comes from the
      four custom properties PDXIssueColors.styleFor() writes inline
      (--pdx-ic / -soft / -wash / -ink). This file never names an issue, so adding
      a core issue needs no edit here and an issue is the same colour on this
      surface as on every other one.
   2. A PATTERN-ONLY ROW MUST NOT BE ABLE TO LOOK LIKE A STANCE. Its rail is
      dashed rather than solid, it takes no topic fill, its name is not bolded to
      stance weight, and it carries a visible tag. Three signals, because one is a
      thing a reader can miss.
   ───────────────────────────────────────────────────────────────────────────── */

.pdxtree-sec { margin-bottom: 1.25rem; }
.pdxtree-h {
  margin: 0 0 .25rem; font-size: 1.05rem; font-weight: 800; letter-spacing: .01em;
  color: #eaf2ff;
}
.pdxtree-sub {
  margin: 0 0 .7rem; font-size: .82rem; line-height: 1.45; color: #9fb4d4;
}
.pdxtree-sub b { color: #cfe0f8; font-weight: 700; }

.pdxtree { display: flex; flex-direction: column; gap: .4rem; }

/* ── the broad node ─────────────────────────────────────────────────────────
   Navigation furniture. The count is the only number allowed on this face; see
   wall 2 in stance-tree.js. */
.pdxtree-branch {
  border: 1px solid rgba(148, 163, 184, 0.18);
  border-left: 3px solid var(--pdx-ic, #94A3B8);
  border-radius: 10px;
  background: rgba(10, 15, 30, 0.36);
  overflow: hidden;
}
.pdxtree-branch.pdxtree-ic { background: linear-gradient(90deg, var(--pdx-ic-soft, transparent), rgba(10, 15, 30, 0.36) 70%); }
/* STEP ONE OF THE FUNNEL IS A CONTROL, AND IT IS SIZED LIKE ONE. The whole row is
   the button, it is never shorter than the 44px a thumb needs, and
   touch-action: manipulation drops the double-tap-zoom wait that makes a phone tap
   feel like it was ignored. */
.pdxtree-bface {
  display: flex; align-items: center; gap: .5rem; width: 100%;
  min-height: 44px; touch-action: manipulation;
  padding: .55rem .7rem; background: none; border: 0; cursor: pointer;
  text-align: left; font: inherit; color: #eaf2ff;
}
.pdxtree-bface:hover { background: rgba(255, 255, 255, 0.04); }
.pdxtree-bface:focus-visible { outline: 2px solid var(--pdx-ic, #7dd3fc); outline-offset: -2px; }
.pdxtree-caret {
  flex: 0 0 auto; font-size: .8rem; color: var(--pdx-ic-ink, #9fb4d4);
  transition: transform .16s ease;
}
.pdxtree-branch[data-pdxtree-open="1"] .pdxtree-caret { transform: rotate(90deg); }
.pdxtree-btitle { flex: 1 1 auto; font-size: .92rem; font-weight: 750; }
.pdxtree-bn {
  flex: 0 0 auto; font-size: .7rem; font-weight: 700; color: #9fb4d4;
  padding: .1rem .42rem; border-radius: 999px;
  background: rgba(148, 163, 184, 0.14);
  border: 1px solid rgba(148, 163, 184, 0.2);
}
.pdxtree-panel { padding: .1rem .45rem .5rem; display: flex; flex-direction: column; gap: .22rem; }
.pdxtree-panel[hidden] { display: none; }

/* ── the branch's state summary ─────────────────────────────────────────────
   Counts of rows, in the bands' own words, so a CLOSED header still says what is
   underneath it. Quieter than the topic name and quieter than the count: it is a
   description of the panel, not a headline. Worst tension first, and on a phone
   only that first bit survives — the count and the sharpest signal are what fit,
   and the whole sentence is on the face's title either way. No percentage and no
   ratio can appear here; see wall 2 in stance-tree.js. */
.pdxtree-bsum {
  flex: 0 0 auto; display: inline-flex; flex-wrap: wrap; align-items: baseline;
  gap: .1rem .34rem; font-size: .66rem; line-height: 1.3; color: #8fa6c6;
  font-variant-numeric: tabular-nums;
}
.pdxtree-bsumbit + .pdxtree-bsumbit::before { content: "·"; opacity: .55; margin-right: .3rem; }
.pdxtree-bsumbit.b-cuts_against { color: #fca5a5; font-weight: 700; }
.pdxtree-bsumbit.b-mixed        { color: #fbe08a; }
.pdxtree-bsumbit.b-aligns       { color: #86efac; }

/* ── the optional mid node ──────────────────────────────────────────────────
   Only rendered where a branch failed the flat-scan test (see MID in the JS).
   A heading, not a control: nothing collapses at this level, because a second
   collapsible tier is a second thing to fight with on a phone. */
.pdxtree-mid { display: flex; flex-direction: column; gap: .22rem; }
.pdxtree-mid + .pdxtree-mid { margin-top: .3rem; }
.pdxtree-midhd {
  font-size: .68rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: #8fa6c6; padding: .3rem .35rem .1rem;
}

/* ── the leaf ───────────────────────────────────────────────────────────────
   One scannable line: name, Said, Record, cue. It wraps rather than truncates,
   because a truncated stance label is a stance a reader cannot read. */
.pdxtree-leaf {
  border-left: 3px solid var(--pdx-ic, #94A3B8);
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.022);
}
.pdxtree-leaf.pdxtree-ic { background: var(--pdx-ic-soft, rgba(255, 255, 255, 0.022)); }
/* THE LEAF'S PRIMARY CONTROL — the whole-width tap, so it carries the same 44px
   floor and the same tap latency fix as the branch face above it. It opens the
   dossier for THIS PERSON on this issue, and it is the only thing on the leaf
   that does; the quiet link under it (.pdxtree-file) is a different destination,
   sized and coloured so it cannot be mistaken for this one. */
.pdxtree-face {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .3rem .5rem;
  width: 100%; min-height: 44px; touch-action: manipulation;
  padding: .42rem .5rem; background: none; border: 0; cursor: pointer;
  text-align: left; font: inherit; color: #dce8f8;
}
.pdxtree-face:hover { background: rgba(255, 255, 255, 0.045); border-radius: 6px; }
.pdxtree-face:focus-visible { outline: 2px solid var(--pdx-ic, #7dd3fc); outline-offset: -2px; }
.pdxtree-dot {
  flex: 0 0 auto; width: .5rem; height: .5rem; border-radius: 50%;
  background: var(--pdx-ic, #94A3B8); align-self: center;
}
.pdxtree-name { flex: 1 1 12rem; font-size: .855rem; font-weight: 700; color: #eaf2ff; }
.pdxtree-slots {
  flex: 1 1 100%; display: flex; align-items: center; flex-wrap: wrap; gap: .26rem .45rem;
  font-size: .73rem; line-height: 1.3;
}
.pdxtree-go { flex: 0 0 auto; color: #8fa6c6; font-size: .95rem; align-self: center; }

/* THE ISSUE FILE'S DOOR — a second destination on the same row, and the styling
   is the whole argument for why that is safe to add. It sits BELOW the face
   rather than inside it, so it cannot disturb the face's wrapping and cannot be
   hit by a thumb aiming at the name. It is small, uppercase and dim, which reads
   as a footnote next to a bold 0.855rem name; and it is right-aligned, away from
   the rail where every leaf's meaning starts. A reader scanning the person's
   record never has to look at it. A reader who wants "everyone on this issue"
   finds it exactly where they are already looking. */
/* THE LEAF'S FOOTER LINE. The leaf became a wrapping flex row when the scope
   control (ⓘ) joined the issue-file link: the face still takes the full width
   and keeps its own line, and the two quiet controls share the line under it —
   ⓘ pinned left, the file link filling the rest and staying right-aligned. Both
   are siblings of the face, never children of it, which is what keeps a tap on
   either from reaching the row's dossier door. */
.pdxtree-leaf { display: flex; flex-wrap: wrap; align-items: center; }
.pdxtree-face { flex: 1 1 100%; }
.pdxtree-leaf > .pdxis-key { margin: 0 0 .3rem .35rem; }
.pdxtree-file {
  display: block; flex: 1 1 auto; min-width: 0; box-sizing: border-box;
  padding: 0 .5rem .38rem; text-align: right;
  font-size: .64rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: #7f96b6; text-decoration: none; touch-action: manipulation;
}
.pdxtree-file:hover, .pdxtree-file:focus-visible {
  color: var(--pdx-ic, #7dd3fc); text-decoration: underline;
}
.pdxtree-file:focus-visible { outline: 2px solid var(--pdx-ic, #7dd3fc); outline-offset: -2px; border-radius: 5px; }
.pdxtree-filego { font-weight: 700; }

/* Said — theirs. */
.pdxtree-said { color: #b9cbe6; }
.pdxtree-said b { font-weight: 700; color: #8fa6c6; }
.pdxtree-said.s-support { color: #86efac; }
.pdxtree-said.s-oppose  { color: #fca5a5; }
.pdxtree-said.s-mixed   { color: #fbe08a; }
.pdxtree-said.s-none    { color: #8fa6c6; font-style: italic; }
/* THE BASELINE IN THE SAID SLOT. Tinted by the side the record read, but dashed
   and trailed by "· from the record" so it is never scanned as a quote. The
   leaf still carries the "Not in Direction Match" tag beside it. */
.pdxtree-said.is-baseline {
  border-bottom: 1px dashed rgba(148,163,184,0.45); font-style: normal;
}
.pdxtree-said.is-baseline b { color: #8fa6c6; }
.pdxtree-basefrom { color: #8fa6c6; font-style: italic; opacity: 0.9; }

/* Record — the formal record's, never theirs. The lane marker (🏛) is part of
   the label in the markup for exactly that reason. */
.pdxtree-pat { color: #b9cbe6; }
.pdxtree-pat b { font-weight: 700; color: #8fa6c6; }
.pdxtree-pat.tone-support { color: #86efac; }
.pdxtree-pat.tone-oppose  { color: #fca5a5; }
.pdxtree-pat.tone-mixed   { color: #fbe08a; }
.pdxtree-pat.tone-muted   { color: #8fa6c6; }
/* Thin and no-clear-pattern are marked, not muffled. They used to be dialled to
   .72 opacity and a smaller face, which put a true statement about a real record
   behind the same veil a browser uses for a disabled control — and a reader who
   cannot comfortably read a row cannot audit it. The border already carries the
   distinction: dashed for thin, dotted for flat, in the pattern engine's own
   weight classes. That is the honest signal; the fade was only volume. */
.pdxtree-pat.w-thin, .pdxtree-pat.w-flat { opacity: 1; }
/* A SCORED SLOT PAINTS FROM THE VERDICT, not from the record's lean. The word in
   the slot is Direction Match's ("Backed up", "Contradicted"), so its colour is
   Direction Match's too — taken from the verdict the row already resolved and
   passed in as a custom property, never restated as a hex in this file. */
.pdxtree-pat.tone-verdict { color: var(--pdx-rc, #b9cbe6); }
.pdxtree-pat.st-scored b { color: var(--pdx-rc, #8fa6c6); opacity: .8; }
/* Depth is the smaller half of the same sentence: how much is behind the label.
   It never outweighs the label and it is never coloured on its own. */
.pdxtree-depth { font-style: normal; opacity: .8; }
/* ONE DOCUMENT UNDER A DEPTH THAT READS LIKE SEVERAL. Printed at full opacity in
   the amber this product uses for limits on a finding, beside the item count it
   qualifies — the leaves that carry it are the ones the count makes look deepest,
   so it is the one thing on the line that must not be dimmed. */
.pdxtree-one { font-style: normal; font-weight: 700; color: #d8bd85; }
/* The one-item horizon. Printed, not hidden — including on a phone, where it is
   the row most likely to be misread as a settled finding. */
.pdxtree-early { font-style: italic; font-size: .68rem; color: #9fb4d4; opacity: .95; }
/* On file with no direction read, still warming, nothing on file: three true
   states, none of them absent and none of them faded. The muted slate and the
   italic say "this is inventory, not a finding" while keeping the row as legible
   as a scored one — the opacity that used to sit here said "this control is
   broken" instead, which is the one thing none of the three means. */
.pdxtree-pat.st-onfile, .pdxtree-pat.st-pending, .pdxtree-pat.st-none {
  color: #8fa6c6; font-style: italic;
}

/* THE ONE PERCENTAGE A LEAF MAY CARRY. It belongs to the Record slot it sits
   beside — one issue's Direction Match result — and it is emitted only for the
   scored state (see pctHtml). No branch has one; no pattern-only row has one. */
.pdxtree-pct {
  font-size: .7rem; font-weight: 800; font-variant-numeric: tabular-nums;
  padding: .04rem .3rem; border-radius: 4px;
  color: var(--pdx-rc, #cfe0f5); background: rgba(148, 163, 184, 0.12);
  border: 1px solid rgba(148, 163, 184, 0.22);
}

/* The cue — a relation between the two slots beside it, printed only when both
   exist (pattern_only being the one that says the opposite out loud). */
.pdxtree-cue {
  font-size: .66rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  padding: .06rem .38rem; border-radius: 999px;
  border: 1px solid rgba(148, 163, 184, 0.28); color: #9fb4d4;
}
.pdxtree-cue.c-aligns       { color: #86efac; border-color: rgba(134, 239, 172, 0.4); background: rgba(74, 222, 128, 0.1); }
.pdxtree-cue.c-cuts_against { color: #fca5a5; border-color: rgba(252, 165, 165, 0.45); background: rgba(248, 113, 113, 0.12); }
.pdxtree-cue.c-split        { color: #fbe08a; border-color: rgba(245, 200, 66, 0.4); background: rgba(245, 200, 66, 0.1); }
.pdxtree-cue.c-pattern_only { color: #9fb4d4; border-style: dashed; background: none; }

/* The disclosure tag. Same pill on the row and in the footer note, so the two
   read as one statement rather than two coincidences. */
.pdxtree-tag {
  font-size: .63rem; font-weight: 800; letter-spacing: .03em;
  padding: .06rem .36rem; border-radius: 4px; white-space: nowrap;
  color: #cbd5e1; background: rgba(148, 163, 184, 0.14);
  border: 1px dashed rgba(148, 163, 184, 0.5);
}

/* The vehicle tag: same pill shape as the disclosure tag above so the two read as
   one family, in the warm tone the package-vs-provision copy uses everywhere else.
   Absence is meaningful here — a leaf with no tag is a leaf whose formal record is
   ordinary votes — so it is deliberately the only warm thing in the slot row. */
.pdxtree-veh {
  font-size: .63rem; font-weight: 800; letter-spacing: .03em;
  padding: .06rem .36rem; border-radius: 4px; white-space: nowrap;
  color: #d0ab6e; background: rgba(208, 171, 110, 0.12);
  border: 1px dashed rgba(208, 171, 110, 0.5);
}

/* ── A DOOR THAT COULD NOT OPEN ────────────────────────────────────────────
   Printed on the row itself rather than as a toast, because the row is where the
   reader's attention and thumb already are, and because a message that floats away
   after three seconds is a message a reader on a bus does not get. It is a live
   region in the markup, so a screen reader hears it without moving focus. */
.pdxtree-fail {
  margin: 0 .5rem .4rem; padding: .38rem .5rem; border-radius: 6px;
  font-size: .72rem; line-height: 1.45; color: #fecaca;
  background: rgba(248, 113, 113, 0.1);
  border: 1px dashed rgba(252, 165, 165, 0.5);
}
.pdxtree-leaf[data-pdxtree-failed="1"] { border-left-color: #fca5a5; }

/* ── pattern-only: visibly not a stance ────────────────────────────────────── */
.pdxtree-leaf.is-patternonly {
  border-left-style: dashed;
  background: rgba(10, 15, 30, 0.3);
}
.pdxtree-leaf.is-patternonly.pdxtree-ic { background: rgba(10, 15, 30, 0.3); }
.pdxtree-leaf.is-patternonly .pdxtree-dot {
  background: none; border: 1px dashed var(--pdx-ic, #94A3B8);
}
.pdxtree-leaf.is-patternonly .pdxtree-name { font-weight: 600; color: #cfdcf0; }
/* Quiet = a pattern-only row whose read is thin. Admitted, and no longer dressed
   DOWN: it used to be the smallest, dimmest thing in the panel, which made a real
   record on file read as a greyed-out dead control rather than as inventory. The
   class is still emitted and still filterable; what it no longer does is take
   contrast away. Everything that distinguishes the row is earned copy the reader
   can act on — the "Pattern only" cue, the "Not in Direction Match" tag, the item
   counts, and the dashed border and dot .is-patternonly already draws. */
.pdxtree-leaf.is-quiet { opacity: 1; }
.pdxtree-leaf.is-quiet .pdxtree-name { font-weight: 600; }

/* ── THE HEADER TALLY ──────────────────────────────────────────────────────
   Four figures, each one a field of the shared counts object, each carrying the
   denominator it means in its own title. Middot-separated rather than boxed: it
   is a caption on the tree below it, not a scoreboard of its own. */
.pdxtree-tally {
  margin: 0 .1rem .5rem; display: flex; flex-wrap: wrap; align-items: baseline;
  gap: .18rem .5rem; font-size: .7rem; line-height: 1.45; color: #9fb4d4;
}
.pdxtree-tallybit { display: inline-flex; align-items: baseline; gap: .3rem; }
.pdxtree-tallybit + .pdxtree-tallybit::before { content: "·"; opacity: .6; }
.pdxtree-tallybit[title] { cursor: help; }

/* ── THE FILTER CHIPS ──────────────────────────────────────────────────────
   One row of view switches, one of them active. They are controls, so they are
   sized for a thumb rather than for the caption they sit under, and the active one
   is marked by more than colour (weight and border as well as fill) because the
   pressed state is the only thing telling a reader why rows are missing. Nothing
   here carries a number: a chip is a view, not a count. */
.pdxtree-filters {
  margin: 0 .1rem .5rem; display: flex; flex-wrap: wrap; gap: .3rem;
}
.pdxtree-fchip {
  font: inherit; font-size: .7rem; font-weight: 700; line-height: 1;
  padding: .34rem .6rem; border-radius: 999px; cursor: pointer;
  color: #b9cbe6; background: rgba(148, 163, 184, 0.12);
  border: 1px solid rgba(148, 163, 184, 0.26);
}
.pdxtree-fchip:hover { background: rgba(148, 163, 184, 0.2); color: #eaf2ff; }
.pdxtree-fchip:focus-visible { outline: 2px solid #7dd3fc; outline-offset: 1px; }
.pdxtree-fchip.is-on {
  color: #0b1220; font-weight: 800;
  background: #cfe0f5; border-color: #cfe0f5;
}

/* ── THE ORDER CONTROL ─────────────────────────────────────────────────────
   Topic or sharpest-first, as a pair of chips beside the filters. Deliberately
   quieter than a filter chip and labelled with the word "Order", because the two
   controls do different things and a reader must never read this one as hiding
   rows: the filters change WHICH issues are on screen, this changes only the
   arrangement. It replaces a whole second, tension-ranked issue section that used
   to sit below this tree — see the note over SORTS in stance-tree.js. */
.pdxtree-sort {
  margin: -.2rem .1rem .5rem; display: flex; flex-wrap: wrap;
  align-items: center; gap: .3rem;
}
.pdxtree-sort-k {
  font-size: .62rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: #7e93b3;
}
.pdxtree-schip {
  font: inherit; font-size: .68rem; font-weight: 700; line-height: 1;
  padding: .3rem .55rem; border-radius: 999px; cursor: pointer;
  color: #9fb4d4; background: transparent;
  border: 1px solid rgba(148, 163, 184, 0.24);
}
.pdxtree-schip:hover { color: #eaf2ff; border-color: rgba(148, 163, 184, 0.42); }
.pdxtree-schip:focus-visible { outline: 2px solid #7dd3fc; outline-offset: 1px; }
.pdxtree-schip.is-on {
  color: #eaf2ff; background: rgba(148, 163, 184, 0.16);
  border-color: rgba(148, 163, 184, 0.44);
}
/* The one line tension order owes a reader: what "sharpest" means, and that
   nothing has been removed or re-scored to produce it. Above the rows, not below
   them, because it explains the arrangement they are about to read. */
.pdxtree-ordernote { margin: 0 .1rem .45rem; }

/* The honest empty view. It states the filter, the answer and the way back. */
.pdxtree-empty {
  margin: .2rem .1rem .1rem; padding: .6rem .7rem; border-radius: 10px;
  border: 1px dashed rgba(148, 163, 184, 0.3); background: rgba(10, 15, 30, 0.34);
  font-size: .78rem; line-height: 1.5; color: #b9cbe6;
}
.pdxtree-empty b { color: #eaf2ff; }
.pdxtree-reset { margin-left: .3rem; }

/* ── FLAT MODE ─────────────────────────────────────────────────────────────
   At or under the threshold in stance-tree.js there are no branches to style: the
   same leaves, in tension order, in one list. Identical leaf chrome by design —
   a row must not look like a different kind of row because the profile is small. */
.pdxtree-flat { display: flex; flex-direction: column; gap: .22rem; }

.pdxtree-note {
  margin: .55rem .1rem 0; font-size: .7rem; line-height: 1.5; color: #8fa6c6;
}
.pdxtree-note-only { display: flex; align-items: baseline; gap: .35rem; flex-wrap: wrap; }

@media (max-width: 639px) {
  .pdxtree-name { flex: 1 1 100%; }
  .pdxtree-face { padding: .5rem .45rem; }
  /* The two controls a reader drives this surface with keep their full tap target
     on the screen where taps are least precise. */
  .pdxtree-face, .pdxtree-bface { min-height: 44px; }
  .pdxtree-slots { font-size: .7rem; }
  .pdxtree-bface { padding: .62rem .6rem; flex-wrap: wrap; }
  /* NARROW: THE COUNT AND THE WORST SIGNAL FIRST. Only the leading summary bit is
     kept — it is the highest-tension band present, because the bits are emitted in
     band order — and the rest of the sentence stays on the face's title. */
  .pdxtree-bsumbit.is-extra { display: none; }
  .pdxtree-bsum { flex: 1 1 100%; }
  .pdxtree-fchip { padding: .4rem .62rem; }
  .pdxtree-schip { padding: .38rem .58rem; }
}
@media (prefers-reduced-motion: reduce) {
  .pdxtree-caret { transition: none; }
}
