/* Flow charts on your own data: the guided paste flow. */

.kept {
  color: var(--muted);
  font-size: 0.9rem;
  margin-bottom: 1rem;
  overflow-wrap: anywhere;
}

.paste-flow {
  padding-top: 2rem;
}

.steps {
  list-style: none;
  counter-reset: step;
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

.step {
  counter-increment: step;
  max-width: 640px;
}

.step h2 {
  font-size: 1.2rem;
  letter-spacing: -0.01em;
  margin-bottom: 0.5rem;
}

.step h2::before {
  content: counter(step) ". ";
  color: var(--accent);
}

.step h3 {
  font-size: 1rem;
  margin: 1.5rem 0 0.5rem;
}

.step p {
  margin-bottom: 0.75rem;
}

.step-done {
  color: var(--muted);
  overflow-wrap: anywhere;
}

.change,
.forget {
  font: inherit;
  color: var(--accent);
  background: none;
  border: none;
  padding: 0;
  margin-left: 0.5rem;
  cursor: pointer;
}

.change:hover,
.forget:hover {
  text-decoration: underline;
}

.next {
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--accent);
  border: none;
  border-radius: 6px;
  padding: 0.5rem 1.5rem;
  margin-top: 1rem;
  cursor: pointer;
}

.next:hover {
  background: var(--accent-dark);
}

.next:disabled {
  background: var(--border);
  color: var(--muted);
  cursor: default;
}

/* Where the work lives: a card per source, side by side, one under the other
   on a phone. Only Azure DevOps and a file of your own are buttons; the
   coming-soon cards are plain, their logo grey whatever its colours, their
   link the one thing that does anything. */
.sources {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
}

@media (max-width: 1200px) {
  .sources {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 600px) {
  .sources {
    grid-template-columns: minmax(0, 1fr);
  }
}

.sources > li {
  display: flex;
}

.source-card {
  font: inherit;
  color: inherit;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 1.25rem 1rem;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
}

button.source-card {
  cursor: pointer;
}

button.source-card:hover,
button.source-card[aria-pressed="true"] {
  border-color: var(--accent);
}

button.source-card[aria-pressed="true"] {
  box-shadow: 0 0 0 1px var(--accent);
}

.source-logo {
  width: 48px;
  height: 48px;
  object-fit: contain;
}

.source-name {
  font-weight: 600;
}

.source-card.soon {
  background: var(--bg-alt);
  color: var(--muted);
}

.source-card.soon .source-logo {
  filter: grayscale(1);
  opacity: 0.55;
}

.soon-tag {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 999px;
}

.soon-note {
  font-size: 0.85rem;
  line-height: 1.4;
}

/* How to bring it over: the source cards' look, two of them, side by side
   down to a phone, where they go one under the other as the sources do. */
.sources.ways {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 600px) {
  .sources.ways {
    grid-template-columns: minmax(0, 1fr);
  }
}

.way-note {
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--muted);
}

.token-field {
  margin-top: 1rem;
}

.token-note {
  font-size: 0.9rem;
  color: var(--muted);
  margin-top: 0.5rem;
}

.token-note a:not([href]) {
  color: inherit;
  text-decoration: none;
}

.refresh-refused {
  margin-top: 0.5rem;
}

.fields {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

.fields label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-weight: 600;
  font-size: 0.9rem;
  flex: 1 1 12rem;
}

.fields input,
.step textarea,
.refresh textarea {
  font: inherit;
  font-weight: 400;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 100%;
}

.step textarea,
.refresh textarea {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
  resize: vertical;
}

.feed-link {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.8rem;
  line-height: 1.5;
  padding: 0.75rem 1rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow-wrap: anywhere;
}

.paste-error {
  color: #b91c1c;
  margin-top: 0.5rem;
}

/* A file of your own: the example in a scrolling code block, its Copy
   button in the corner, and the fields it holds. */
.file-example {
  position: relative;
  margin: 1rem 0;
}

.file-example pre {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.8rem;
  line-height: 1.5;
  padding: 0.75rem 1rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow-x: auto;
  max-width: 100%;
}

.file-copy {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
}

.file-fields {
  margin: 0 0 1rem 1.25rem;
  line-height: 1.5;
}

.file-fields ul {
  margin-left: 1.25rem;
}

.file-fields code {
  font-size: 0.85em;
  overflow-wrap: anywhere;
}

.progress {
  color: var(--muted);
  margin-top: 0.5rem;
}

.types {
  border: none;
  margin-top: 1rem;
}

.types legend {
  font-weight: 600;
  font-size: 0.9rem;
  margin-bottom: 0.5rem;
}

.types label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.15rem 0;
}

.types .count {
  color: var(--muted);
}

.summary {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.25rem 1.5rem;
}

.summary dt {
  color: var(--muted);
}

.mapping {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.phase-group h5 {
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 0.35rem;
}

/* Room to drop into, even with no states left in it. */
.phase-states {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-height: 3rem;
  padding: 0.4rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.state-card {
  padding: 0.45rem 0.75rem 0.45rem 1.75rem;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: grab;
  user-select: none;
  position: relative;
}

/* A grip, saying the card can be picked up. */
.state-card::before {
  content: "⋮⋮";
  position: absolute;
  left: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  letter-spacing: -0.15em;
}

.state-card.dragging {
  cursor: grabbing;
  z-index: 1000;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}

.drop-placeholder {
  border: 2px dashed var(--accent);
  border-radius: 6px;
}

.state-card .state {
  font-weight: 600;
  display: block;
}

.state-card .hint {
  display: block;
  font-size: 0.85rem;
  color: var(--muted);
}

.standing {
  margin-top: 1rem;
  font-variant-numeric: tabular-nums;
}

.article-header + .past {
  padding-top: 1.5rem;
}

/* Each view's heading but Data's (see spec.md's "Views"), naming the view
   alone, at the top of its main area; on Estimates its switches sit beside
   it, in the look of the CFD's "Show states" but in the flow. */
.view-heading {
  font-size: 1.25rem;
  letter-spacing: -0.01em;
  margin: 0;
}

.view-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 1rem;
  margin-bottom: 0.75rem;
}

.estimates-switches {
  display: flex;
  column-gap: 1rem;
}

.estimates-switches[hidden] {
  display: none;
}

.estimates-switches .estimates-percentiles-switch,
.estimates-switches .estimates-wip-switch {
  position: static;
}

/* What the charts leave room for on a wide screen, besides what each view
   counts below: under them the section's trimmed bottom padding and the
   compact footer, which stays on the screen. The footer room adds up the
   section's 0.75rem bottom padding, the footer's 0.8rem padding, its one
   line of 0.75rem text at the site's 1.6 line height (1.2rem) and its top
   border, rounded up: change the footer below and this changes with it. */
body {
  --footer-room: 2.85rem;
}

@media (min-width: 1025px) {
  footer {
    padding: 0.4rem 2rem;
    font-size: 0.75rem;
  }
}

/* The past on a wide screen (see spec.md's "The past"): sized as on Team
   Northbound's charts slide in presentation mode. The three charts stay side
   by side and grow as large as the screen allows: a third of the width each,
   or less when the height runs out first (the charts are 4:3, taller while
   the CFD's legend needs more lines: pastCharts.ts sets their shape). 18.5rem is
   what else has to fit on the screen besides the footer:
   the nav, the view's heading, the chart headings and the replay controls. On
   a short window the charts stop shrinking at 16rem and the page scrolls
   instead; that floor gives way to the width, though, so on a narrow window
   (the sidebar and How to read this taking their share) the three still fit
   side by side and the page never scrolls sideways. The replay controls keep matching one chart's width. The refresh
   banner takes another 4.5rem (opened, it pushes the charts down and the
   page scrolls). The present works out the same width, to size its dots by
   the scatter plot's. */
@media (min-width: 1025px) {
  section.alt.past {
    padding-bottom: 0.75rem;
  }

  section.alt.past > .inner {
    max-width: none;
  }

  .past .charts-and-transport,
  .past .present,
  .past .estimates {
    --past-refresh-height: 0rem;
    --past-chart-width: min((100% - 3rem) / 3, max(16rem, (100dvh - 18.5rem - var(--past-refresh-height) - var(--footer-room)) * var(--past-chart-width-per-height, 4 / 3)));
  }

  .past:has(.refresh:not([hidden])) .charts-and-transport,
  .past:has(.refresh:not([hidden])) .present,
  .past:has(.refresh:not([hidden])) .estimates {
    --past-refresh-height: 4.5rem;
  }

  .past .refresh {
    max-width: 960px;
    margin-left: auto;
    margin-right: auto;
  }

  .past .charts-message {
    max-width: 960px;
    margin: 0 auto;
  }

  .past .charts-row {
    grid-template-columns: repeat(3, var(--past-chart-width));
    justify-content: center;
  }

  .past .chart {
    max-width: none;
  }

  .past .replay-transport {
    width: var(--past-chart-width);
  }
}

/* The future (see spec.md's "The future"): the forecast chart and its
   controls, across the width left beside the sidebar and How to read this,
   redrawn as that changes. It draws itself at whatever size it's
   given: on a phone as tall as on Northbound, on a wide screen as tall as
   fits from the top of the main area down to the footer. 9.75rem is what else
   has to fit above it: the nav, the view's heading and the section's own
   padding; the footer and the banner take their room as for the past, and the
   past's replay controls (windowReplay.ts) under it as much as the run
   charts' take. On a phone they pin to the bottom of the screen in the past's
   replay bar (past-charts.css), sticky within .future-chart. On a short
   window the chart stops shrinking at 260px and the page scrolls instead. */
.past .future-chart {
  --future-controls-height: 5.5rem;
}

.past .forecast-chart {
  height: clamp(260px, 37.5vw, calc(100svh - 12rem - var(--future-controls-height)));
}

.past .future-chart[hidden],
.past .forecast-chart[hidden] {
  display: none;
}

@media (min-width: 1025px) {
  .past .future-chart {
    --future-controls-height: 4.75rem;
  }

  .past .forecast-chart {
    --future-refresh-height: 0rem;
    height: max(260px, calc(100dvh - 9.75rem - var(--future-refresh-height) - var(--future-controls-height) - var(--footer-room)));
  }

  .past:has(.refresh:not([hidden])) .forecast-chart {
    --future-refresh-height: 4.5rem;
  }

  /* Centred under the chart, as the run charts' are. */
  .past .future-chart .replay-transport {
    width: min(100%, 26rem);
    margin: 0.75rem auto 0;
  }
}

/* The present (see spec.md's "WIP age"): one chart across the full
   width, sized as the future's, with its column names and counts under it.
   4.5rem is room for the names on one or two lines and the counts' line; on
   a phone a long name wraps onto more rather than make the page scroll
   sideways. Its controls are the past's (windowReplay.ts), under the names:
   the run charts' room for them (see below) and a line for the handle's
   date. On a phone they pin to the bottom of the screen in the past's replay
   bar (past-charts.css), sticky within .present. */
.past .present {
  --present-controls-height: 6.75rem;
}

.past .present[hidden] {
  display: none;
}

.past .present-chart {
  display: block;
  width: 100%;
  height: clamp(260px, 37.5vw, calc(100svh - 16.5rem - var(--present-controls-height)));
}

/* The replay bar's own padding, and the handle's date under the scrubber. */
.past .present .replay-transport {
  padding-bottom: calc(2rem + env(safe-area-inset-bottom));
}

@media (min-width: 1025px) {
  .past .present {
    --present-controls-height: 6rem;
  }

  /* Centred under the chart, as the run charts' are. */
  .past .present .replay-transport {
    width: min(100%, 26rem);
    margin: 0.75rem auto 0;
    padding-bottom: 1.25rem;
  }

  .past .present-chart {
    --present-refresh-height: 0rem;
    height: max(260px, calc(100dvh - 14.25rem - var(--present-refresh-height) - var(--present-controls-height) - var(--footer-room)));
  }

  .past:has(.refresh:not([hidden])) .present-chart {
    --present-refresh-height: 4.5rem;
  }
}

/* Takes no room, only the width the past's scatter plot has at this page
   width: the full width up to the past's charts' cap on a narrower screen,
   one of the three charts' width on a wide one. presentChart.ts and
   estimatesChart.ts size their dots by it. */
.scatter-dot-size {
  width: min(100%, 400px);
  height: 0;
}

@media (min-width: 1025px) {
  .past .scatter-dot-size {
    width: var(--past-chart-width);
  }
}

.present-columns {
  display: grid;
  margin: 0.25rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.85rem;
  color: var(--muted);
  text-align: center;
}

/* Every item is as tall as the longest wrapped name, and its count sits at
   the bottom, so the counts read across as a row. */
.present-columns li {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 0 0.25rem;
  overflow-wrap: anywhere;
}

.present-columns .present-count {
  font-weight: 600;
  color: var(--text);
}

/* The handle's label sits under it and slides from starting at the handle,
   at the timeline's start, to ending at it, at "now", so it never runs past
   the scrubber's ends, by --at, the handle's place along the scrubber from 0
   to 1, set on the handle and read here through it. */
.present-playhead-label {
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(calc(-1 * var(--at, 1) * 100%));
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  white-space: nowrap;
  pointer-events: none;
}

.present-chart .present-frame {
  fill: none;
  stroke: var(--border);
  stroke-width: 1;
}

.present-chart .present-grid,
.present-chart .present-column-edge {
  stroke: var(--border);
  stroke-width: 1;
  stroke-opacity: 0.6;
}

.present-chart .present-tick-label {
  fill: var(--muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.present-chart .present-axis-label {
  fill: var(--muted);
  font-size: 12px;
}

/* The scatter plot's lines, dots and pointing look, drawn here in CSS pixels
   rather than the scatter plot's own chart units, so the labels take a
   readable size. Each dot is a link to its item. */
.present-chart .reference-line-label,
.present-chart .guide-tag-text {
  font-size: 11px;
}

/* The To Do lines' labels sit inside the plot, over the dots. */
.present-chart .present-waiting-label-bg {
  fill: #fff;
}

.present-chart .band-tag-text {
  font-size: 12px;
}

.present-chart .dot.active {
  cursor: pointer;
}

/* A dot still waiting in To Do, in the CFD's To Do grey (../styles.css). */
.present-chart .dot.active.waiting {
  fill: var(--phase-todo);
}

/* Between the To Do columns and the Doing columns. */
.present-chart .present-phase-edge {
  stroke: var(--muted);
  stroke-width: 1;
}

/* The shared dot setting is in the scatter plot's own units: in CSS pixels
   here, it's scaled by how many of them one of those units takes on screen,
   which presentChart.ts sets. */
.present-chart .chart .dot {
  r: calc(var(--scatter-dot-radius) * var(--present-dot-scale, 1) * 1px);
}

/* The past's scatter plot dots are links to their items too. */
.dot-link .dot {
  cursor: pointer;
}

/* An item from a file of your own without a url links nowhere. */
.dot-link:not([href]) .dot,
.present-link:not([href]) .dot {
  cursor: default;
}

/* A focused dot grows as a pointed-at one does; that's its focus mark. */
.present-chart .present-link:focus {
  outline: none;
}

/* The WIP run chart (see spec.md's "WIP run chart"): the count and total age
   plots stacked in one svg across the width left beside the sidebar and How
   to read this, redrawn as that changes, sized as the future's, tall enough
   for both to read, the past's replay controls under it (runChart.ts and
   windowReplay.ts): the svg leaves them their room, so the charts and their
   controls fit one screen together. On a phone the controls pin to the
   bottom of the screen in the past's replay bar (past-charts.css), sticky
   within .wip-run. A finger dragged sideways points at days; one dragged up
   or down still scrolls the page. The To Do run chart is the same pair of
   plots, in To Do's grey. */
.past .wip-run[hidden] {
  display: none;
}

/* The phone's replay bar: its padding, the buttons, the gap under them and
   the scrubber. */
.past .wip-run {
  --run-transport-height: 5.5rem;
}

/* Less the run chart's legend, while it shows (see below). */
.past .wip-run-chart {
  display: block;
  width: 100%;
  height: calc(clamp(380px, 37.5vw, calc(100svh - 12rem - var(--run-transport-height))) - var(--wip-run-legend-height, 0rem));
}

@media (min-width: 1025px) {
  /* The controls' room above them, the buttons, the gap under them and the
     scrubber. */
  .past .wip-run {
    --run-transport-height: 4.75rem;
  }

  .past .wip-run-chart {
    --wip-run-refresh-height: 0rem;
    height: calc(
      max(380px, calc(100dvh - 9.75rem - var(--wip-run-refresh-height) - var(--footer-room) - var(--run-transport-height))) -
        var(--wip-run-legend-height, 0rem)
    );
  }

  .past:has(.refresh:not([hidden])) .wip-run-chart {
    --wip-run-refresh-height: 4.5rem;
  }

  /* Centred under the total age chart, as wide as the past's under one of
     its charts can be, narrower when the chart is. */
  .past .wip-run .replay-transport {
    width: min(100%, 26rem);
    margin: 0.75rem auto 0;
  }
}

.wip-run-chart .wip-run-capture {
  cursor: crosshair;
  touch-action: pan-y;
}

.wip-run-chart .wip-run-frame {
  fill: none;
  stroke: var(--border);
  stroke-width: 1;
}

.wip-run-chart .wip-run-grid {
  stroke: var(--border);
  stroke-width: 1;
  stroke-opacity: 0.6;
}

.wip-run-chart .wip-run-tick-label {
  fill: var(--muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.wip-run-chart .wip-run-axis-label {
  fill: var(--muted);
  font-size: 12px;
}

/* In the CFD's Doing orange (../styles.css). */
.wip-run-chart .wip-run-line {
  fill: none;
  stroke: var(--phase-doing);
  stroke-width: 2;
  stroke-linejoin: round;
}

/* In the CFD's To Do grey. */
.todo-run-chart .wip-run-line {
  stroke: var(--phase-todo);
}

/* The scatter plot's pills, in CSS pixels here, as on WIP age. */
.wip-run-chart .guide-tag-text {
  font-size: 11px;
}

/* Each run chart's "Show states" switch, in the CFD's switch's look, at
   the count chart's right edge in the svg's top margin, over the line its
   axis label sits on, so the chart below stays where it is whatever the
   switch says. With it on, the legend takes that line, leaving the switch
   its room, and the svg shrinks by as much, so both still fit one screen. */
.wip-run {
  position: relative;
}

.wip-run:has(.wip-run-legend:not([hidden])) {
  --wip-run-legend-height: 1.5rem;
}

.wip-run-legend {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  height: 1.5rem;
  margin: 0;
  padding-right: 7.5rem;
  font-size: 0.8rem;
  overflow: hidden;
}

.wip-run-legend[hidden] {
  display: none;
}

/* Each entry shrinks to fit the line, its name cut short with "…". */
.wip-run-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
}

.wip-run-legend-swatch {
  flex: none;
  width: 14px;
  height: 3px;
}

.wip-run-legend-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Each state's band in the CFD's shade for it, as strong as on the CFD, the
   lines between states as thin as the CFD's between states of one phase. */
.wip-run-chart .wip-run-band {
  fill-opacity: 0.3;
  stroke: none;
}

.wip-run-chart .wip-run-band-line {
  fill: none;
  stroke-width: 0.75;
  stroke-linejoin: round;
}

/* The state tags at the guide are the CFD's band tags (past-charts.css),
   their text in CSS pixels. */
.wip-run-chart .band-tag-text {
  font-size: 11px;
}

/* Estimates (see spec.md's "Estimates"): under the view's heading and its
   switches, the count, a one-line legend, and the chart across the width
   left beside the sidebar and How to read this, as tall as its rows need, so
   many rows make the page scroll. */
.past .estimates[hidden] {
  display: none;
}

.estimates-count {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
}

.estimates-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.9rem;
  margin: 0.75rem 0 0.25rem;
  font-size: 0.85rem;
  color: var(--muted);
}

.estimates-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

/* With the bands on, their entries join the legend's line. Off, they still
   hold their room, so the switch never moves the chart even where they wrap
   the legend onto more lines. */
.estimates-band-legend {
  display: contents;
}

.estimates-band-legend[hidden] {
  visibility: hidden;
}

/* Likewise the work in progress's entry. */
.estimates-wip-legend[hidden] {
  visibility: hidden;
}

.estimates-band-swatch {
  width: 12px;
  height: 10px;
  border: 1px solid var(--border);
  background: var(--estimates-band);
}

.estimates-band-note {
  color: #999;
  font-size: 0.8rem;
}

/* Each row's percentile bands, pale so the dots read over them; the swatches
   take the same colours. */
.estimates .under50 {
  --estimates-band: #e3f4e1;
}

.estimates .from50to85 {
  --estimates-band: #fbf3cf;
}

.estimates .from85to95 {
  --estimates-band: #fde3c8;
}

.estimates .over95 {
  --estimates-band: #f9d7d3;
}

.estimates-chart .estimates-band {
  fill: var(--estimates-band);
}

/* The swatch borrows the dots' look from `.chart`, not its chart size. */
.past .estimates-legend .chart {
  flex: none;
  width: 10px;
  height: 10px;
}

.estimates-legend .dot {
  r: 4px;
}

.past .estimates-chart {
  display: block;
  width: 100%;
}

.estimates-chart .estimates-grid {
  stroke: var(--border);
  stroke-width: 1;
  stroke-opacity: 0.6;
}

.estimates-chart .estimates-axis {
  stroke: var(--muted);
  stroke-width: 1;
}

.estimates-chart .estimates-tick-label {
  fill: var(--muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.estimates-chart .estimates-axis-label {
  fill: var(--muted);
  font-size: 12px;
}

/* A planning poker card labelling each row. */
.estimates-chart .estimate-card rect {
  fill: #fff;
  stroke: var(--border);
  stroke-width: 1;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.15));
}

.estimates-chart .estimate-card text {
  fill: var(--text);
  font-size: 13px;
  font-weight: 700;
}

.estimates-chart .band-tag-text {
  font-size: 12px;
}

/* A row's tip: each percentile chip on its band's colour. */
.estimates-chart .estimates-tip-chip {
  fill: var(--estimates-band);
  stroke: var(--border);
  stroke-width: 1;
}

/* In CSS pixels here, scaled as the present's are; estimatesChart.ts sets
   the scale. */
.estimates-chart .chart .dot {
  r: calc(var(--scatter-dot-radius) * var(--estimates-dot-scale, 1) * 1px);
}

/* An item in progress, in the scatter plot's in-progress orange, a little
   larger, ringed in the page's colour so stacked ones stay apart. */
.estimates-chart .chart .dot.wip {
  r: calc(var(--scatter-dot-radius) * var(--estimates-dot-scale, 1) * 1.3px);
  stroke: var(--bg);
  stroke-width: 1px;
}

/* The banner suggesting to get what changed since the last query, above the
   charts. Opened, it holds a paste step like the revisions step. */
.refresh {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem 1rem;
  margin-bottom: 1.25rem;
}

.refresh-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
}

.refresh-line .next {
  margin-top: 0;
}

.refresh-line .next[hidden] {
  display: none;
}

.refresh-body {
  margin-top: 0.75rem;
}

.refresh-body p {
  margin-bottom: 0.75rem;
}

.refresh-body .change {
  margin: 0.75rem 0 0;
}

/* The sidebar (see spec.md's "The sidebar"): the four groups, Teams, Types,
   Views and Settings, each headed and marking its own choice, set apart by a
   rule between them, a stronger one between the two halves, below. Laid out
   beside the page on a wide screen and over it on a phone, further below. */
.sidebar-group,
.sidebar-entries {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.sidebar-group[hidden],
.sidebar-backdrop[hidden] {
  display: none;
}

.sidebar-group:not([hidden]) ~ .sidebar-group {
  border-top: 1px solid var(--border);
  margin-top: 0.85rem;
  padding-top: 0.85rem;
}

/* Between the two halves, what's shown (Teams, Types) and which page shows
   it (Views, Settings), a clearly stronger break than within a half. Views
   is hidden until the data is in, Settings alone then, with no break. */
.sidebar-group.sidebar-half:not([hidden]) {
  border-top: 2px solid var(--muted);
  margin-top: 1.4rem;
  padding-top: 1.1rem;
}

.sidebar h2 {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  padding: 0 0.6rem;
  margin-bottom: 0.2rem;
}

.sidebar button {
  font: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  color: var(--muted);
  background: none;
  border: none;
  border-radius: 6px;
  padding: 0.35rem 0.6rem;
  cursor: pointer;
}

.sidebar button:hover {
  color: var(--text);
  background: #fff;
}

.sidebar button[aria-pressed="true"],
.sidebar button[aria-current="page"],
.sidebar button[aria-current="true"] {
  color: #fff;
  background: var(--accent);
}

/* The type on show's row: its name, then the ⚙ opening its State mapping at
   the row's right end. A long name wraps beside it. */
.sidebar-type-row {
  display: flex;
  align-items: flex-start;
  gap: 0.15rem;
}

.sidebar-type-row > button:first-child {
  flex: 1;
  min-width: 0;
}

/* Both ⚙, the type's and the Teams heading's, as big a target as an entry;
   marked as an entry is while their page shows. */
.sidebar .sidebar-cog {
  flex: none;
  padding: 0.35rem 0.45rem;
}

/* The Teams heading, its ⚙ opening the Teams page at the right end. */
.sidebar-heading-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.15rem;
  margin-bottom: 0.2rem;
}

.sidebar-heading-row h2 {
  margin-bottom: 0;
}

/* Teams and Types collapsed: the choice on show alone, no heading above it,
   a small ▾ at the line's end saying it opens. Open, the heading's name
   collapses it again, a small ▴ beside it. */
.sidebar .sidebar-collapsed {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.4rem;
  color: var(--text);
}

/* The team or type on show, marked as it is in the open group. */
.sidebar button.sidebar-collapsed-marked {
  color: #fff;
  background: var(--accent);
}

.sidebar-collapsed-marked .sidebar-group-mark {
  color: inherit;
}

.sidebar h2[hidden],
.sidebar-heading-row[hidden] {
  display: none;
}

.sidebar h2 .sidebar-group-toggle {
  font: inherit;
  color: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  margin: 0 -0.15rem;
  padding: 0 0.15rem;
  border-radius: 4px;
}

.sidebar h2 .sidebar-group-toggle:hover {
  color: var(--text);
  background: none;
}

.sidebar-group-mark {
  font-size: 0.75em;
  color: var(--muted);
}

.sidebar-group-toggle .sidebar-group-mark {
  margin-left: 0.3rem;
}

/* No team made yet: a plain line, not an entry. */
.sidebar-none {
  font-size: 0.9rem;
  line-height: 1.3;
  color: var(--muted);
  padding: 0.35rem 0.6rem;
}

/* The Teams page (see spec.md's "Teams"): the teams one under the other,
   each a summary to open it, naming it over its areas, and a Delete; the open
   one's name field, what it's missing, and its area tree under it. Everything
   wraps, so nothing scrolls sideways on a phone. */
.teams-page {
  padding-top: 2rem;
}

.teams-page .view-heading,
.mapping-page .view-heading,
.preferences-page .view-heading {
  margin-bottom: 1rem;
}

/* The Preferences page (see spec.md's "Views"): one checkbox, its label
   wrapping on a phone. */
.preferences-page {
  padding-top: 2rem;
}

.preference {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  max-width: 40rem;
  cursor: pointer;
}

.teams {
  list-style: none;
  padding: 0;
  max-width: 40rem;
}

.team {
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #fff;
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.6rem;
}

.team-head {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}

.team-head .change {
  flex: none;
  padding: 0.35rem 0;
}

/* With two teams or more, a grip before the name moves the team: big enough
   for a thumb, and the only place a drag starts. */
.team-grip {
  flex: none;
  min-width: 2.75rem;
  min-height: 2.75rem;
  margin: -0.25rem 0 -0.25rem -0.5rem;
  font: inherit;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--muted);
  background: none;
  border: none;
  border-radius: 6px;
  cursor: grab;
  user-select: none;
}

.team-grip:hover,
.team-grip:focus-visible {
  color: var(--accent);
  background: var(--bg-alt);
}

.team.dragging {
  z-index: 1000;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}

.team.dragging .team-grip {
  cursor: grabbing;
}

.teams .drop-placeholder {
  margin-bottom: 0.6rem;
}

.team-summary {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  font: inherit;
  text-align: left;
  color: var(--text);
  background: none;
  border: none;
  border-radius: 6px;
  padding: 0.35rem 0.4rem;
  overflow-wrap: anywhere;
  cursor: pointer;
}

.team-summary:hover {
  background: var(--bg-alt);
}

.team-name {
  font-weight: 600;
}

.team-areas {
  font-size: 0.85rem;
  color: var(--muted);
}

.team-name-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-weight: 600;
  font-size: 0.9rem;
  margin: 0.5rem 0.4rem 0;
}

.team-name-field input {
  font: inherit;
  font-weight: 400;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 100%;
  min-width: 0;
}

.team-problem {
  color: #b91c1c;
  font-size: 0.9rem;
  margin: 0.4rem 0.4rem 0;
}

.team-tree {
  margin-top: 0.6rem;
}

/* The area tree: each line indented by its depth, a branch's control to
   open or close it before its name, a leaf's place for one left empty so
   the names line up. */
.area-line {
  display: flex;
  align-items: flex-start;
  padding-left: calc(var(--depth, 0) * 0.9rem);
}

/* An area's name, the label of its tick box beside it, so clicking either
   ticks the area; a brought area's does nothing, as its box doesn't. */
.area-name {
  display: flex;
  align-items: flex-start;
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: 0.9rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--muted);
  border-radius: 6px;
  cursor: pointer;
}

.area-name > span {
  padding: 0.35rem 0.6rem 0.35rem 0.2rem;
}

.area-name:hover {
  color: var(--text);
  background: #fff;
}

.area-name:has(.area-tick:disabled) {
  cursor: default;
}

.area-name:has(.area-tick:disabled):hover {
  color: var(--muted);
  background: none;
}

.area-toggle,
.area-leaf {
  flex: none;
  width: 1.4rem;
  text-align: center;
  padding: 0.35rem 0;
}

.area-toggle {
  font: inherit;
  font-size: 0.9rem;
  line-height: 1.3;
  color: var(--muted);
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

.area-toggle:hover {
  color: var(--text);
  background: #fff;
}

/* An area's tick box, beside its name; dimmed when a ticked area above it
   brings it. */
.area-tick {
  flex: none;
  margin: 0.45rem 0.1rem 0 0.2rem;
  accent-color: var(--accent);
  cursor: pointer;
}

.area-tick:disabled {
  opacity: 0.45;
  cursor: default;
}

.area-toggle[aria-expanded="true"] .area-toggle-icon {
  transform: rotate(90deg);
}

.area-toggle-icon {
  display: inline-block;
  transition: transform 0.1s;
}

/* The phone's sidebar (see spec.md's "On a phone"): opened from the menu
   button at the top of the main area, which sticks just under the site's
   header (index.ts keeps --nav-height to the header's height) and names
   what's on, How to read this's button beside it, sticking with it. Open,
   the sidebar covers the page's left edge from top to bottom, above the
   site's header, the page dimmed beside it and kept from scrolling
   underneath. */
@media (max-width: 1024px) {
  .menu-bar {
    position: sticky;
    top: var(--nav-height, 60px);
    z-index: 60;
    display: flex;
    background: #fff;
    border-bottom: 1px solid var(--border);
  }

  .menu-button {
    display: block;
    flex: 1;
    min-width: 0;
    font: inherit;
    font-size: 0.95rem;
    font-weight: 500;
    text-align: left;
    overflow-wrap: anywhere;
    color: var(--text);
    background: none;
    border: none;
    padding: 0.6rem 1.25rem;
    cursor: pointer;
  }

  .how-to-read-button {
    flex: none;
    font: inherit;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--accent);
    background: none;
    border: none;
    border-left: 1px solid var(--border);
    padding: 0.6rem 1rem;
    cursor: pointer;
  }

  .sidebar {
    display: none;
  }

  /* Not every phone browser honours overflow on body alone; the backdrop
     taking no touch scroll keeps the page still where it doesn't. */
  html:has(body[data-menu-open]),
  body[data-menu-open] {
    overflow: hidden;
  }

  .sidebar-backdrop {
    touch-action: none;
  }

  body[data-menu-open] .sidebar {
    display: block;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 300;
    width: min(18rem, 85vw);
    background: var(--bg-alt);
    border-right: 1px solid var(--border);
    box-shadow: 4px 0 16px rgba(0, 0, 0, 0.15);
  }

  .sidebar-slot {
    height: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0.5rem 0.6rem 1.5rem;
  }

  .sidebar .sidebar-close {
    display: block;
    margin-left: auto;
    font-size: 1.6rem;
    line-height: 1;
    padding: 0.25rem 0.6rem;
  }

  .sidebar-backdrop {
    position: fixed;
    inset: 0;
    z-index: 250;
    background: rgba(0, 0, 0, 0.35);
  }
}

/* The sidebar on a wide screen (see spec.md's "The sidebar"): all the
   navigation down the left edge, the page beside it taking the rest of the
   width, so nothing hides under it. The sidebar stretches the whole page
   between the nav and the footer, as wide as its longest label, a long type
   name wrapping rather than widen it much. Its entries stick just under the
   nav, with no more room than the screen leaves under it and above whatever
   of the footer is in view (index.ts measures that), so they stay put while
   the page scrolls and never slide under the nav once the footer shows. The
   menu button and the sidebar's close button are the phone's. index.ts's
   wideScreen holds this breakpoint too. */
@media (min-width: 1025px) {
  .menu-bar,
  .sidebar-close,
  .sidebar-backdrop {
    display: none;
  }

  .workspace {
    flex: 1 0 auto;
    display: flex;
  }

  .workspace-main {
    flex: 1;
    min-width: 0;
  }

  .sidebar {
    flex: 0 0 auto;
    width: max-content;
    max-width: 10.5rem;
    background: var(--bg-alt);
    border-right: 1px solid var(--border);
  }

  .sidebar-slot {
    position: sticky;
    top: var(--nav-height, 60px);
    max-height: calc(100dvh - var(--nav-height, 60px) - var(--footer-showing, 0px));
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 1rem 0.6rem;
  }

  section.alt.past {
    padding-left: 1.5rem;
  }
}

/* How to read this (see spec.md's "How to read this"): each of the view's
   charts explained in its three parts, one under the other, about a
   comfortable reading line wide. */
.how-to-read-text {
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text);
}

.how-to-read-text h2 {
  font-size: 1.05rem;
  letter-spacing: -0.01em;
  margin-bottom: 0.5rem;
}

.how-to-read-text ul + h2 {
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}

.how-to-read-text h3 {
  font-size: 0.9rem;
  font-weight: 600;
  font-style: italic;
  margin: 0.9rem 0 0.3rem;
}

.how-to-read-text em {
  font-weight: 600;
}

.how-to-read-text ul {
  padding-left: 1.1rem;
}

.how-to-read-text li + li {
  margin-top: 0.3rem;
}

.how-to-read .how-to-read-close {
  display: block;
  margin-left: auto;
  font: inherit;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--muted);
  background: none;
  border: none;
  border-radius: 6px;
  padding: 0.25rem 0.6rem;
  cursor: pointer;
}

.how-to-read .how-to-read-close:hover {
  color: var(--text);
  background: #fff;
}

.how-to-read-slot {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0.5rem 1rem 1.5rem;
}

/* On a phone it opens over the page from the right edge, full height, above
   the site's header, the page dimmed beside it and kept from scrolling
   underneath, as the sidebar does from the left. There's no tab. */
@media (max-width: 1024px) {
  .how-to-read-tab {
    display: none;
  }

  html:has(body[data-how-to-read-open]),
  body[data-how-to-read-open] {
    overflow: hidden;
  }

  .how-to-read {
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    z-index: 300;
    width: min(20rem, 85vw);
    background: var(--bg-alt);
    border-left: 1px solid var(--border);
    box-shadow: -4px 0 16px rgba(0, 0, 0, 0.15);
  }

  .how-to-read-slot {
    height: 100%;
  }

  .how-to-read-backdrop {
    position: fixed;
    inset: 0;
    z-index: 250;
    background: rgba(0, 0, 0, 0.35);
    touch-action: none;
  }
}

/* On a wide screen it mirrors the sidebar down the right edge: from just
   under the nav to the bottom of the screen, staying put while the page
   scrolls and ending above whatever of the footer is in view, the page
   between them taking the rest of the width. Closed, a slim tab at the right
   edge, sticking the same way, reopens it. */
@media (min-width: 1025px) {
  .how-to-read-backdrop {
    display: none;
  }

  .how-to-read {
    flex: 0 0 auto;
    width: 19rem;
    background: var(--bg-alt);
    border-left: 1px solid var(--border);
  }

  .how-to-read .how-to-read-slot {
    position: sticky;
    top: var(--nav-height, 60px);
    max-height: calc(100dvh - var(--nav-height, 60px) - var(--footer-showing, 0px));
  }

  .how-to-read-tab {
    flex: none;
    align-self: flex-start;
    position: sticky;
    top: calc(var(--nav-height, 60px) + 1rem);
    writing-mode: vertical-rl;
    font: inherit;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--accent);
    background: var(--bg-alt);
    border: 1px solid var(--border);
    border-right: none;
    border-radius: 6px 0 0 6px;
    padding: 0.9rem 0.35rem;
    cursor: pointer;
  }

  .how-to-read-tab:hover {
    color: var(--accent-dark);
    background: #fff;
  }
}

/* The State mapping page (see spec.md's "Views"): on a wide screen a board,
   the groups as columns side by side in flow order, each list stretched to
   the tallest so an empty column is as easy to drop into as a full one. The
   columns keep a readable width and the board scrolls sideways within itself
   rather than squeeze them; a phone keeps the groups one under the other.
   The wide screen is the sidebar's, so index.ts's wideScreen holds this
   breakpoint too. */
@media (min-width: 1025px) {
  .mapping-page .mapping {
    display: grid;
    grid-template-columns: repeat(4, minmax(10rem, 1fr));
    overflow-x: auto;
  }

  .mapping-page .phase-group {
    display: flex;
    flex-direction: column;
  }

  .mapping-page .phase-states {
    flex: 1;
  }
}

.mapping-page {
  padding-top: 2rem;
}

/* State mapping's back button, above its heading, naming the view it goes to. */
.mapping-back {
  display: block;
  font: inherit;
  font-size: 0.9rem;
  color: var(--accent);
  background: none;
  border: none;
  padding: 0;
  margin-bottom: 0.5rem;
  cursor: pointer;
}

.mapping-back:hover {
  text-decoration: underline;
}

.mapping-page .type-mapping {
  padding: 0;
}
