/* Cross-Impact Instrument — functional stylesheet.
   Scope deliberately: legible structure, real interactive states (hover,
   active/pressed, disabled, "this is the current step"), and enough visual
   grouping that a cold respondent isn't reading a wall of plain text. Not
   a visual identity pass — colours are a small neutral-plus-one-accent
   system, not a brand system. */

:root {
  --sticky-offset: 0px;
  --bg: #faf9f5;
  --ink: #141413;
  --ink-soft: #5b5952;
  --border: #e4e1d8;
  --card: #ffffff;
  --accent: #3f6b52;
  --accent-ink: #ffffff;
  --danger: #a13f2b;
  --radius: 8px;
  color-scheme: light;
}

* { box-sizing: border-box; }
html { scroll-padding-top: 12px; }
body {
  margin: 0;
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  background: var(--bg);
  color: var(--ink);
}
img { max-width: 100%; display: block; }
[hidden] { display: none !important; }

.wrap {
  max-width: 720px;
  margin: 0 auto;
  padding: 24px 18px 80px;
}

.eyebrow {
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 6px;
}
h1 { font-size: 1.4rem; margin: 0 0 12px; line-height: 1.25; }
h3 { font-size: 1rem; margin: 0 0 8px; }
p { margin: 0 0 12px; }
.muted { color: var(--ink-soft); font-size: 0.85rem; }

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 14px;
}

/* ---- buttons ---- */
button {
  font: inherit;
  cursor: pointer;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--ink);
  padding: 9px 16px;
  transition: background 0.12s ease, border-color 0.12s ease, transform 0.05s ease;
}
button:hover:not(:disabled) { border-color: #c9c4b6; background: #f4f2ec; }
button:active:not(:disabled) { transform: translateY(1px); }
button:disabled { opacity: 0.45; cursor: not-allowed; }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  padding: 11px 20px;
}
.btn-primary:hover:not(:disabled) { background: #345a44; border-color: #345a44; }
.btn-ghost { background: transparent; border-color: transparent; color: var(--ink-soft); }
.btn-ghost:hover:not(:disabled) { background: #f0efe8; color: var(--ink); }

/* toggle/chip controls (relevant?, direction, strength) */
.chiprow { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  border: 1px solid #d8d4c6;
  background: #e6e3da;
  color: var(--ink-soft);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 0.86rem;
  min-width: 34px;
}
.chip:hover:not(.chip-on):not(:disabled) { background: #dbd7c9; }
.chip.chip-on {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
  font-weight: 600;
}
/* Without this, the generic button:hover rule above (higher specificity than
   a plain .chip.chip-on due to the :hover pseudo-class + :not()) would win
   and wash a validated chip out to a light grey while the mouse sits over it. */
.chip.chip-on:hover { background: var(--ink); border-color: var(--ink); }
/* Round 2 only: this is the answer carried over from Round 1, not yet
   reviewed this round. Distinct mid-grey, halfway between the plain
   unselected chip and a validated (clicked-this-round) black one. */
.chip.chip-pending {
  background: #9c9686;
  border-color: #9c9686;
  color: #fff;
  font-weight: 500;
}
.chip.chip-pending:hover { background: #8b8574; border-color: #8b8574; }
.ctrl-group { margin-bottom: 8px; }
.ctrl-group.is-sub { opacity: 0.72; }
.ctrl-label { display: block; font-size: 0.78rem; color: var(--ink-soft); margin-bottom: 4px; }
.ctrl-label-needed { color: var(--danger); font-weight: 600; }
.ctrl-label-editable::after { content: " — still editable"; font-weight: 400; }
.ctrl-inactive-note { display: block; font-size: 0.74rem; color: var(--ink-soft); margin-top: 2px; }

/* ---- pass tabs ---- */
.passtabs { display: flex; gap: 6px; margin: 14px 0; flex-wrap: wrap; }
.passtab { font-size: 0.84rem; padding: 7px 14px; }
.passtab-active { background: var(--ink); border-color: var(--ink); color: #fff; font-weight: 600; }

/* ---- sticky pass-tabs + progress bar while scrolling the matrix ---- */
.vote-sticky-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  padding-top: 10px;
  margin: 0 -18px;
  padding-left: 18px;
  padding-right: 18px;
  border-bottom: 1px solid var(--border);
  box-shadow: 0 4px 10px -6px rgba(20, 20, 19, 0.15);
}
.vote-sticky-bar .progress-row { margin-bottom: 12px; }
.sticky-title-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-bottom: 10px;
}
.sticky-title { font-size: 1rem; font-weight: 700; line-height: 1.3; }

/* ---- progress ---- */
.progress-row { display: flex; gap: 18px; margin: 10px 0 16px; flex-wrap: wrap; }
.progress-item { flex: 1 1 160px; min-width: 140px; }
.progress-item .label { font-size: 0.76rem; color: var(--ink-soft); margin-bottom: 4px; display: flex; justify-content: space-between; }
.progress-track { height: 8px; border-radius: 4px; background: var(--border); overflow: hidden; }
.progress-fill { height: 100%; background: var(--accent); border-radius: 4px; transition: width 0.2s ease; }
.progress-note { font-size: 0.84rem; color: var(--ink-soft); margin: 6px 0 14px; }

/* ---- Round 2 completion tracker: how much has actually been confirmed
   with a click this round, distinct from the Relevance/Direction/Strength
   bars above which also count values simply carried over from Round 1. ---- */
.r2-completion { margin-top: 2px; padding-top: 12px; border-top: 1px dashed var(--border); }
.r2-completion-label { display: flex; justify-content: space-between; font-size: 0.78rem; font-weight: 600; color: var(--ink); margin-bottom: 4px; }
.r2-completion-fill { background: #9c9686; }
.r2-completion-done .r2-completion-fill { background: var(--accent); }
.r2-completion-note { font-size: 0.76rem; color: var(--ink-soft); margin-top: 5px; }
.r2-completion-done .r2-completion-note { color: var(--accent); font-weight: 600; }

/* ---- issue / matrix rows ---- */
/* Each issue is boxed so it reads as one distinct unit on the page,
   separate from the issue above/below it. */
.issue-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0 16px 16px;
  margin-top: 20px;
  background: #ece9dc;
  box-shadow: 0 1px 4px rgba(20, 20, 19, 0.09);
}
.issue-card:first-of-type { margin-top: 0; }

/* Frozen per-issue header: stays pinned just under the global sticky bar
   while you work through that issue's rows, then the next issue's own
   header takes its place once you scroll past this one. Background
   matches .issue-card so it masks rows scrolling underneath without a
   visible seam, and it sits inset from the card's border via the card's
   own left/right padding so the sticky header never overruns the
   rounded corners. */
.issue-sticky-header {
  position: sticky;
  top: var(--sticky-offset, 0px);
  background: #ece9dc;
  z-index: 15;
  padding: 14px 0 10px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 10px;
}
.issue-title { font-size: 1.05rem; font-weight: 700; margin-bottom: 4px; }
.issue-summary { color: var(--ink-soft); font-size: 0.92rem; }
.issue-media { margin: 10px 0; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--border); }
.issue-details { background: #f6f4ee; border-radius: 6px; padding: 12px; font-size: 0.88rem; color: var(--ink-soft); margin: 8px 0 4px; }

.passrow {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 12px;
  margin-top: 10px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  background: var(--card);
}
/* Round 1 rows: passrow-label/passrow-controls sit directly in .passrow.
   Round 2 rows: they're wrapped in .passrow-main instead, so a third item
   (.passrow-hist) can sit beside them on the same row rather than stacking
   underneath. */
.passrow-main { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; flex: 1 1 auto; min-width: 0; }
/* Round 2 rows with a histogram: a real 3-column grid (label / controls /
   hist) instead of nested flex-wrap. Nested flex-wrap let the label+controls
   pair collapse onto their own stacked lines under width pressure, which
   both dropped the histogram below them and made rows inconsistent with
   each other depending on how much their label text wrapped. Grid columns
   hold their position regardless, and only their own contents (e.g. a tight
   row of strength chips) wrap internally when short on room. */
.passrow.passrow-with-hist {
  display: grid;
  /* Label capped so it can't hog space; controls given a floor wide enough
     to hold a full 5-chip strength row without wrapping; histogram fixed
     and thin so its width never varies row to row (that variance was what
     made rows drift out of line with each other). These three minimums
     plus the two column gaps must add up to comfortably less than the
     app's own 720px content cap (.wrap) minus its and the card's padding
     — about 628px in practice — or the grid overflows its row and the
     columns visibly run into each other. Keep a real margin here, not
     just enough to scrape by. */
  grid-template-columns: minmax(130px, 190px) minmax(270px, 1fr) 166px;
  column-gap: 10px;
  align-items: start;
}
/* .passrow-label/.passrow-controls also carry a min-width from the plain
   flex layout used elsewhere (Round 1's rows, and this same class without
   a histogram). That min-width still applies to a grid item and silently
   overrides the grid column's own max above once it's larger — which is
   exactly what blew the width budget and ran this column into the next.
   The grid's own minmax already sets the real floor, so let the item
   itself go down to 0. */
.passrow.passrow-with-hist .passrow-label,
.passrow.passrow-with-hist .passrow-controls { min-width: 0; }
.passrow.passrow-with-hist .passrow-main { display: contents; }
.passrow-label { flex: 1 1 220px; min-width: 200px; }
.passrow-dim { display: flex; align-items: center; gap: 6px; font-weight: 600; margin-top: 2px; }

/* ---- dimension navigation icons (nav-icons-sketch) ----
   Same ink colour as surrounding text, one fixed glyph per dimension.
   No colour/direction/verdict encoded — purely "which row is this." */
.dim-icon {
  width: 16px; height: 16px; flex: none;
  stroke: currentColor; stroke-width: 1.6; fill: none;
  stroke-linecap: round; stroke-linejoin: round;
}
.dim-label-icon { display: inline-flex; align-items: center; gap: 5px; }
.dim-info-btn {
  width: 18px; height: 18px; border-radius: 50%;
  padding: 0; font-size: 0.7rem; line-height: 1;
  border: 1px solid var(--border); color: var(--ink-soft); background: var(--bg);
}
.dim-explain { margin-top: 6px; font-size: 0.82rem; color: var(--ink-soft); background: #f6f4ee; border-radius: 6px; padding: 8px 10px; }
.passrow-controls { flex: 1 1 260px; min-width: 220px; }
.chip-subrow { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.chip-subrow-label { font-size: 0.76rem; color: var(--ink-soft); min-width: 54px; flex: none; }

.my-r1-answer {
  margin-top: 6px; font-size: 0.78rem; font-weight: 600; color: var(--ink);
  background: #eef2fb; border-radius: 6px; padding: 4px 8px; display: inline-block;
}

/* ---- R1 histogram toggle ---- */
.r1hist-btn {
  font-size: 0.72rem; border-radius: 12px; padding: 3px 10px;
  background: transparent; border-color: var(--border); color: var(--ink-soft); margin-top: 6px;
}
.r1hist-btn:hover { background: #f0efe8; }

/* ---- read-aloud (browser text-to-speech) button ---- */
.read-aloud-btn {
  font-size: 0.72rem; font-weight: 400; border-radius: 12px; padding: 3px 10px;
  background: transparent; border-color: var(--border); color: var(--ink-soft);
  vertical-align: middle; margin-left: 4px;
}
.read-aloud-btn:hover { background: #f0efe8; color: var(--ink); }
/* Sits as its own column at the right of the row, alongside the dimension
   text and the vote chips, instead of stacking underneath them. */
.passrow-hist { width: 166px; padding-left: 2px; }
/* Ten bars (signed strength -5..-1, 1..5) plus a separate not-relevant bar,
   all fixed-width so the strip is always the same size and lines up the
   same way on every row regardless of vote counts or column length. A
   count only appears above a bar that actually got votes (an empty grey
   track already reads as zero), stacked directly on top of its own bar —
   not in a shared row underneath all eleven — so two counts never have to
   fit side by side in the same cramped space. Every bar also gets its
   scale value underneath (bare digit on the positive side, colour and
   position already say "positive"). Hover any bar for the exact value
   and count spelled out. */
.hist10 { display: flex; justify-content: flex-end; }
.hist10-bars { display: flex; align-items: flex-start; gap: 3px; }
.hist10-item { width: 9px; cursor: default; display: flex; flex-direction: column; align-items: center; }
.hist10-item:first-child { width: 12px; }
.hist10-track {
  width: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center;
  background: #f0efe8; border: 1px solid var(--border); border-radius: 2px;
}
.hist10-fill { width: 100%; min-height: 0; border-radius: 1px 1px 0 0; }
.hist10-fill.hist10-nr { background: #b7b2a2; }
.hist10-fill.hist10-neg { background: var(--danger); }
.hist10-fill.hist10-pos { background: var(--accent); }
.hist10-num { font-size: 0.62rem; font-weight: 700; color: var(--ink); line-height: 1.4; white-space: nowrap; }
.hist10-tag { font-size: 0.56rem; letter-spacing: -0.2px; color: var(--ink-soft); line-height: 1.3; white-space: nowrap; }
.hist10-divider { align-self: stretch; width: 1px; background: var(--border); margin: 0 1px; }

/* ---- rank / accord rows (results, insights) ---- */
.rank-row { display: flex; align-items: center; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.rank-row:last-child { border-bottom: none; }
.rank-row .rr-label { flex: 1 1 40%; font-size: 0.92rem; }
.rank-bar-track { flex: 1 1 40%; height: 9px; background: var(--border); border-radius: 5px; overflow: hidden; }
.rank-bar-fill { height: 100%; background: var(--accent); }
.rr-value { flex: 0 0 auto; min-width: 90px; text-align: right; font-size: 0.82rem; color: var(--ink-soft); }
.lean-tag { font-size: 0.78rem; padding: 2px 8px; border-radius: 10px; background: #f0efe8; color: var(--ink-soft); }

/* Aspect sensitivity table: a fixed grid (not the flexible .rank-row)
   so the rank/digital/signed/lean/accord columns stay aligned instead of
   wrapping. Wrapped in a horizontally-scrolling container for narrow
   screens rather than letting columns collapse into each other. */
.sensitivity-table { overflow-x: auto; }
.sensitivity-row {
  display: grid;
  grid-template-columns: 26px minmax(120px, 1fr) 52px 52px 92px 58px;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  min-width: 460px;
  font-size: 0.92rem;
}
.sensitivity-row:last-child { border-bottom: none; }
.sensitivity-head { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ink-soft); }
.sr-rank { font-size: 0.82rem; font-weight: 600; color: var(--ink-soft); }
.sr-num { text-align: right; font-size: 0.82rem; color: var(--ink-soft); white-space: nowrap; }
.sr-signed { font-weight: 600; color: var(--ink); }
.sr-lean { font-size: 0.78rem; padding: 2px 8px; border-radius: 10px; background: #f0efe8; color: var(--ink-soft); text-align: center; white-space: nowrap; }
.sensitivity-head .sr-lean { background: none; }

/* ---- moderator ---- */
.modbar { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
.modtab { font-size: 0.86rem; }
.modtab-active { background: var(--ink); border-color: var(--ink); color: #fff; }
.modrow { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 8px 0; }
input[type="text"], input[type="datetime-local"], input[type="password"] {
  font: inherit; padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--card); color: var(--ink);
}
label { font-size: 0.84rem; color: var(--ink-soft); }
.status-pill { display: inline-block; font-size: 0.78rem; padding: 3px 10px; border-radius: 12px; background: #f0efe8; color: var(--ink-soft); }
.status-pill.is-live { background: #e6efe9; color: var(--accent); font-weight: 600; }
.status-pill.is-closed { background: #fbeae5; color: var(--danger); font-weight: 600; }

/* Language toggle (EN/FR) - small, top-right, present on every
   participant-facing screen; never shown in the moderator panel. */
.lang-toggle { display: flex; justify-content: flex-end; gap: 4px; margin-bottom: 6px; }
.lang-btn {
  font-size: 0.78rem; font-weight: 600; padding: 3px 10px; border-radius: 12px;
  background: transparent; border: 1px solid var(--border); color: var(--ink-soft); cursor: pointer;
}
.lang-btn:hover { background: #f0efe8; color: var(--ink); }
.lang-btn.lang-btn-active { background: var(--ink); border-color: var(--ink); color: var(--card); }

/* Moderator exercise list: the ID needs to be impossible to miss, since
   duplicated/renamed exercises often share the same title verbatim and
   only the ID tells them apart (mistaking one exercise for another here
   means managing, duplicating, or deleting the wrong one). */
.ex-id-badge {
  display: inline-block; font-family: ui-monospace, "SF Mono", Consolas, monospace;
  font-size: 0.82rem; font-weight: 700; letter-spacing: 0.02em;
  padding: 2px 8px; border-radius: 5px; background: var(--ink); color: var(--card);
  margin-right: 4px; vertical-align: middle;
}

.error-banner { background: #fbeae5; border: 1px solid #eec3b6; color: var(--danger); border-radius: 6px; padding: 10px 12px; margin-bottom: 14px; font-size: 0.88rem; }
.nudge-banner { background: #f0efe8; border-radius: 6px; padding: 10px 12px; margin-bottom: 14px; font-size: 0.9rem; }

a.modlink { display: inline-block; margin-top: 18px; font-size: 0.82rem; color: var(--ink-soft); }

@media (max-width: 480px) {
  .rank-row { flex-wrap: wrap; }
  .rr-value { text-align: left; }
}
