/* ==========================================================================
   CO Climate Tracker
   climate/climate.css

   Section identity first, then the components unique to the tracker. This is
   the most data-dense section of the site, so it leans hardest on the mono
   voice: cold alpine accent, tabular figures, tight rules.

   The .stages component defined here is the one every bill page will reuse.
   ========================================================================== */

[data-section="climate"] {
  --brand: #3d7fa3;            /* alpine, cold high country */
  --brand-soft: #7fa8c4;
  --brand-text-light: #2a6d90; /* 5.1:1 on bone */
  --brand-text-dark: #a6cbe0;  /* 11:1 on ink */
}

/* Legislative numbers read as data, not as prose. */
[data-section="climate"] .mono,
[data-section="climate"] .stage__name {
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   SESSION BANNER
   Colorado climate policy runs in two channels at different times of year.
   This says which one is live, in the owner's own words, set by hand in
   climate/tracker.json. It sits directly under the subnav as a full-bleed
   ink band, so it reads as part of the chrome rather than as an alert box.
   -------------------------------------------------------------------------- */

.session {
  background: var(--c-ink-900);
  color: var(--c-bone);
  border-bottom: 1px solid rgba(246, 242, 233, 0.14);
}

.session .wrap {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  gap: var(--sp-3) var(--sp-5);
  padding-block: var(--sp-5);
}

.session__label {
  position: relative;
  padding-left: 1.1rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: var(--tracking-micro);
  text-transform: uppercase;
  color: var(--brand-soft);
  white-space: nowrap;
}

/* The sun from the monogram, doing duty as a status light. */
.session__label::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.42em;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--brand-soft);
}

/* In session, the light goes gold. Colour the text and the dot separately:
   one rule for both paints a gold block over the label. */
.session[data-status="in_session"] .session__label { color: var(--c-gold); }
.session[data-status="in_session"] .session__label::before { background: var(--c-gold); }

.session__note {
  font-size: var(--step--1);
  line-height: 1.6;
  color: rgba(246, 242, 233, 0.82);
  max-width: 68ch;
}

@media (max-width: 40rem) {
  .session .wrap { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   LANES
   One lane per channel. A lane with nothing in it is omitted by the builder;
   a lane holding only concluded items collapses into a <details> so it never
   reads as broken, while the record stays reachable.
   -------------------------------------------------------------------------- */

.lane + .lane,
.lane__archive { margin-top: clamp(2rem, 4.5vw, 3rem); }

.lane__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line-strong);
}

.lane__head .lane__title { font-size: var(--step-3); }

.lane__count {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: var(--tracking-micro);
  text-transform: uppercase;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

/* Collapsed lanes and archives share one summary row. */
.lane__summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-block: var(--sp-4);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  list-style: none;
}

.lane__summary::-webkit-details-marker { display: none; }

.lane__summary .lane__title {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.lane__summary::after {
  content: "Show";
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: var(--tracking-micro);
  text-transform: uppercase;
  color: var(--accent-text);
}

details[open] > .lane__summary::after { content: "Hide"; }

.lane__summary:hover .lane__title { color: var(--text); }

/* --------------------------------------------------------------------------
   MEASURE
   One tracked thing, bill or ballot measure. "Measure" covers both: in
   legislative usage a bill is a measure too.
   -------------------------------------------------------------------------- */

.measure {
  position: relative;
  padding-block: clamp(1.5rem, 3vw, 2rem);
  border-bottom: 1px solid var(--line);
  scroll-margin-top: calc(var(--header-h) + 2rem);
}

.measure:last-child { border-bottom: 0; }

.measure__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-5);
}

.measure__number {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}

.measure__title {
  margin-top: var(--sp-3);
  font-size: var(--step-2);
  max-width: 28ch;
}

.measure__summary {
  display: grid;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
  max-width: 64ch;
  color: var(--text);
  font-size: var(--step-0);
  line-height: 1.62;
}

.measure .facts { margin-top: var(--sp-5); }

.measure__status { margin-top: var(--sp-5); }
.measure__status .block-title { margin-bottom: var(--sp-4); }

/* --------------------------------------------------------------------------
   POSITION
   Where Climate Reality Colorado / Denver stands. This is an opinion, and it
   is labelled as one: it sits apart from the summary, which is not.
   -------------------------------------------------------------------------- */

.position {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--pos);
  border-radius: var(--radius-pill);
  overflow: hidden;
  color: var(--pos);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.position.is-support { --pos: var(--c-yes); }
.position.is-oppose { --pos: var(--c-no); }

.position__stance { padding: 0.45em 0.85em; }

/* The instruction half reverses out, so "vote yes" is the loudest thing in
   the row. Both fills clear 5.5:1 against bone text. */
.position__action {
  padding: 0.45em 0.85em;
  background: var(--pos);
  color: var(--c-bone);
  font-weight: 500;
}

/* --------------------------------------------------------------------------
   PRIMER
   Why Colorado is voting on any of this. Sits above the measures, because the
   difference between a proposition and an amendment is the single most useful
   thing a reader can know before looking at the three.
   -------------------------------------------------------------------------- */

.primer {
  padding-bottom: clamp(2rem, 4vw, 3rem);
  margin-bottom: clamp(2rem, 4.5vw, 3rem);
  border-bottom: 1px solid var(--line-strong);
}

.primer__title { font-size: var(--step-3); max-width: 24ch; }

.primer__body {
  display: grid;
  gap: var(--sp-4);
  margin-top: var(--sp-4);
  max-width: 70ch;
  font-size: var(--step-0);
  line-height: 1.62;
  color: var(--text-muted);
}

.primer__figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
}

/* --------------------------------------------------------------------------
   FIGURE
   The wrapper both diagrams share: a rule with the accent bar on it, exactly
   like .block. These are drawn in type and hairlines rather than set as
   images, so they reflow, stay sharp, and are readable by a screen reader.
   -------------------------------------------------------------------------- */

.figure {
  position: relative;
  margin: 0;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
}

.figure::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--bar-w);
  height: var(--bar-h);
  background: var(--accent);
}

.figure .block-title { margin-bottom: var(--sp-4); text-align: left; }

/* --------------------------------------------------------------------------
   COMPARE
   Proposition against amendment. A real table, because it is one: two things
   compared across the same three questions.
   -------------------------------------------------------------------------- */

.compare {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--step--1);
}

.compare caption {
  text-align: left;
  caption-side: top;
}

.compare th,
.compare td {
  text-align: left;
  vertical-align: top;
  padding: var(--sp-3) var(--sp-4) var(--sp-3) 0;
  border-bottom: 1px solid var(--line);
}

.compare thead th {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-text);
  border-bottom: 1px solid var(--line-strong);
}

.compare tbody th {
  width: 8.5rem;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.compare td { line-height: 1.5; color: var(--text); }

.compare tbody tr:last-child th,
.compare tbody tr:last-child td { border-bottom: 0; }

/* Three columns of prose will not fit a phone. Stack each row and let the
   column name label its own value. */
@media (max-width: 40rem) {
  .compare thead { display: none; }

  /* Once the table is display:block the caption stops taking the table's
     width and wraps to the widest cell. Make it a block too. */
  .compare caption { display: block; }

  .compare,
  .compare tbody,
  .compare tr,
  .compare th,
  .compare td { display: block; }

  .compare tbody tr {
    padding-block: var(--sp-3);
    border-bottom: 1px solid var(--line);
  }

  .compare tbody tr:last-child { border-bottom: 0; }

  .compare tbody th {
    width: auto;
    padding: 0 0 var(--sp-2);
    border-bottom: 0;
    color: var(--text);
  }

  .compare td {
    padding: 0 0 var(--sp-3);
    border-bottom: 0;
  }

  .compare tbody tr td:last-child { padding-bottom: 0; }

  .compare td::before {
    content: attr(data-col);
    display: block;
    margin-bottom: 0.15em;
    font-family: var(--font-mono);
    font-size: var(--step--2);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent-text);
  }
}

/* --------------------------------------------------------------------------
   FLOW
   How a measure reaches the ballot. Shares the node and connector vocabulary
   of .stages without its done/current states: this is a fixed path, not a
   live position on one.
   -------------------------------------------------------------------------- */

.flow {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  margin: 0;
  padding: 0;
  list-style: none;
}

.flow__step {
  position: relative;
  display: grid;
  justify-items: start;
  gap: var(--sp-2);
  padding-right: var(--sp-4);
}

/* The connector runs from this node to the next one. */
.flow__step::after {
  content: "";
  position: absolute;
  top: 0.3125rem;
  left: 0.75rem;
  right: 0;
  height: 2px;
  background: var(--line-strong);
  opacity: 0.5;
}

.flow__step:last-child::after { display: none; }

.flow__node {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  background: var(--accent);
  position: relative;
  z-index: 1;
}

.flow__index {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.14em;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}

.flow__name {
  font-size: var(--step--2);
  line-height: 1.4;
  color: var(--text-muted);
  text-wrap: balance;
}

@media (max-width: 46rem) {
  .flow {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    gap: var(--sp-4);
  }

  .flow__step {
    grid-template-columns: auto auto minmax(0, 1fr);
    align-items: baseline;
    gap: 0 var(--sp-3);
    padding-right: 0;
  }

  .flow__node { align-self: center; }

  /* The spine now runs upward from this node to the previous one. */
  .flow__step::after {
    top: auto;
    bottom: 100%;
    left: 0.3125rem;
    right: auto;
    width: 2px;
    height: var(--sp-4);
    transform: translateX(-50%);
  }

  .flow__step:last-child::after { display: block; }
  .flow__step:first-child::after { display: none; }
}

/* --------------------------------------------------------------------------
   OUTCOMES
   What each vote actually does. Deliberately uncoloured: yes and no are the
   two ballot options, not endorsements, and the position pill above is the
   only thing on the page that says which one the chapter recommends.
   -------------------------------------------------------------------------- */

.outcomes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
  gap: var(--sp-4) var(--sp-5);
  margin: var(--sp-5) 0 0;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
}

.outcome dt {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: var(--tracking-micro);
  text-transform: uppercase;
  color: var(--text-faint);
}

.outcome dd {
  margin: var(--sp-2) 0 0;
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--text);
}

/* --------------------------------------------------------------------------
   SOURCE AND AFFILIATION
   -------------------------------------------------------------------------- */

.measure__source {
  margin-top: var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* Who maintains this, once, at the foot of the tracker. Small on purpose:
   it answers why a climate tool lives on a personal site, nothing more. */
.affiliation {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* --------------------------------------------------------------------------
   STAGES, the tracker's signature component
   A bill's path through the legislature. Reused verbatim on every bill page,
   with .stage--done / .stage--current moved along the line.
   -------------------------------------------------------------------------- */

.stages {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.stage {
  position: relative;
  display: grid;
  justify-items: center;
  gap: var(--sp-3);
  padding-inline: var(--sp-2);
  text-align: center;
}

/* The connector runs behind the node, from the previous stage to this one. */
.stage::before {
  content: "";
  position: absolute;
  top: 0.3125rem;
  right: 50%;
  left: -50%;
  height: 2px;
  background: var(--line-strong);
  opacity: 0.5;
}

.stage:first-child::before { display: none; }

.stage--done::before,
.stage--current::before { background: var(--accent); opacity: 1; }

.stage__node {
  position: relative;
  z-index: 1;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  background: var(--bg-raised);
  border: 2px solid var(--line-strong);
}

.stage--done .stage__node {
  background: var(--accent);
  border-color: var(--accent);
}

.stage--current .stage__node {
  background: var(--accent);
  border-color: var(--accent);
  outline: 4px solid color-mix(in srgb, var(--accent) 20%, transparent);
}

.stage__name {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  line-height: 1.35;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  text-wrap: balance;
}

.stage--done .stage__name,
.stage--current .stage__name {
  color: var(--accent-text);
  font-weight: 500;
}

.stage__note {
  font-size: 0.6875rem;
  line-height: 1.4;
  color: var(--text-faint);
  text-wrap: balance;
}

/* Six stages will not fit across a phone. Turn the line vertical: the
   connector becomes the spine, and each stage keeps its own row. */
@media (max-width: 46rem) {
  .stages {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    gap: var(--sp-4);
  }

  .stage {
    grid-template-columns: auto 1fr;
    grid-template-areas: "node name" "node note";
    justify-items: start;
    gap: 0 var(--sp-4);
    text-align: left;
    padding-inline: 0;
  }

  .stage__node { grid-area: node; align-self: center; }
  .stage__name { grid-area: name; }
  .stage__note { grid-area: note; }

  .stage::before {
    top: auto;
    bottom: 100%;
    left: 0.3125rem;
    right: auto;
    width: 2px;
    height: var(--sp-4);
    transform: translateX(-50%);
  }
}

/* --------------------------------------------------------------------------
   BILL PAGE
   One page per bill, and there will eventually be thousands. Structure is
   fixed so the pages are comparable at a glance: identifier and status, the
   plain-language summary, the structured facts, the dated action log, then
   the sources everything came from.
   -------------------------------------------------------------------------- */

/* The identifier line above the title: bill number, chamber, session. */
.bill-id {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3) var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.bill-id__number {
  font-weight: 500;
  color: var(--accent-text);
}

.bill-id__sep {
  width: 1px;
  height: 0.9em;
  background: var(--line-strong);
}

.bill-id__session { color: var(--text-faint); }

/* The status line is the thing most readers came for, and the one part that
   changes week to week, so it gets the accent bar rather than a panel. */
.bill-status {
  position: relative;
  margin: clamp(1.5rem, 3.5vw, 2.25rem) 0;
  padding-block: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--line);
}

.bill-status::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: var(--bar-w);
  height: var(--bar-h);
  background: var(--accent);
}

.bill-status__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}

.bill-status__label {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: var(--tracking-micro);
  text-transform: uppercase;
  color: var(--text-faint);
}

.bill-status__updated {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   ACTION LOG
   Every action taken on the bill, most recent first. Meticulous by design:
   a date, what happened, and where that is recorded.
   -------------------------------------------------------------------------- */

.log {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
  max-width: 52rem;
}

.log > li {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  gap: 0.25rem var(--sp-5);
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--line);
}

.log time {
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: 0.06em;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  padding-top: 0.15em;
}

.log__what {
  font-size: var(--step--1);
  line-height: 1.6;
}

.log__where {
  grid-column: 2;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--text-faint);
}

/* The newest action is the live one. */
.log > li:first-child .log__what {
  font-weight: 500;
  color: var(--accent-text);
}

@media (max-width: 40rem) {
  .log > li {
    grid-template-columns: 1fr;
    gap: 0.2rem;
  }
  .log time { padding-top: 0; }
  .log__where { grid-column: 1; }
}

/* --------------------------------------------------------------------------
   EMPTY STATE placement
   -------------------------------------------------------------------------- */

.empty { margin-top: clamp(2rem, 4vw, 3rem); }

.empty code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  padding: 0.1em 0.35em;
  border-radius: var(--radius-sm);
  background: rgba(11, 19, 26, 0.06);
}
