/* charts.css — the three programmatic clusters: /strategy-charts/, /compare/
   and /calculator/. Loaded alongside rules.css, which already carries the page
   frame, the rule definition list and the index table.

   The strategy matrix is restated here rather than shared with game.css.
   game.css is the game surface bundle and is not loaded outside /game/, and
   pulling it in for a static page would cost the whole game stylesheet for one
   table. Both copies read the same tokens, so a token change moves both.

   Every colour, size and space below is a token. There is no literal colour in
   this file, so both themes and the AA contrast pairs come for free. */

/* ── the strategy matrix ─────────────────────────────────────────────────── */
/* N6. The matrix is wider than a phone at every rule set, so the wrapper is a
   scroller. It now says so: a thin visible scrollbar, an edge fade keyed off the
   data-scroll attribute site.js sets when there is genuinely something off
   screen, and a focus ring for when the region is reached from the keyboard.
   site.js also gives the wrapper a name and a tabindex, which is what makes it
   scrollable without a pointer. */
.chartwrap {
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-bottom: var(--space-2);
  scrollbar-width: thin;
  scrollbar-color: var(--border-ui) transparent;
}
.chartwrap[data-scroll="end"] {
  -webkit-mask-image: linear-gradient(to right, transparent, black var(--space-7));
          mask-image: linear-gradient(to right, transparent, black var(--space-7));
}
.chartwrap[data-scroll="start"] {
  -webkit-mask-image: linear-gradient(to left, transparent, black var(--space-7));
          mask-image: linear-gradient(to left, transparent, black var(--space-7));
}
.chartwrap[data-scroll="both"] {
  -webkit-mask-image: linear-gradient(to right, transparent, black var(--space-7),
                                     black calc(100% - var(--space-7)), transparent);
          mask-image: linear-gradient(to right, transparent, black var(--space-7),
                                     black calc(100% - var(--space-7)), transparent);
}
.chartwrap:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
table.chart {
  border-collapse: separate;
  border-spacing: var(--cell-gap);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}
table.chart caption {
  caption-side: top;
  text-align: left;
  padding-bottom: var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--text-2);
  max-width: var(--measure-prose);
  overflow-wrap: anywhere;
}
table.chart th {
  font-weight: var(--weight-medium);
  color: var(--text-3);
  padding: 0 var(--space-1);
  min-width: var(--cell-size);
  text-align: center;
}
/* The header row sticks while a long grid scrolls, so the dealer upcard is
   always visible. The row header sticks for the same reason on the other axis. */
table.chart thead th {
  position: sticky;
  top: 0;
  background: var(--bg);
  z-index: 2;
}
table.chart tbody th {
  position: sticky;
  left: 0;
  background: var(--bg);
  text-align: right;
  padding-right: var(--space-2);
  z-index: 1;
  min-width: 2.5rem;
}
table.chart tbody th[colspan] {
  text-align: left;
  padding: var(--space-3) 0 var(--space-1);
  font-family: var(--font-sans);
  font-size: var(--text-2xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--text-2);
  position: static;
  background: none;
}
.cell {
  width: var(--cell-size);
  height: var(--cell-size);
  min-width: var(--cell-size);
  border-radius: var(--radius-cell);
  color: var(--cell-ink);
  font-weight: var(--weight-bold);
  text-align: center;
  vertical-align: middle;
}
.c-H { background: var(--cell-hit); }
.c-S { background: var(--cell-stand); }
.c-D { background: var(--cell-dbl); }
.c-P { background: var(--cell-split); }
.c-R { background: var(--cell-surr); }

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin: var(--space-4) 0 var(--space-5);
}
.legend span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-2);
  overflow-wrap: anywhere;
}
.legend__h {
  font-size: var(--text-2xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--text-3);
}
.legend i {
  width: 1.25rem;
  height: 1.25rem;
  flex: 0 0 auto;
  border-radius: var(--radius-cell);
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  color: var(--cell-ink);
  font-style: normal;
}
/* 18 rows by 10 columns does not fit 360px at the full cell size. The dense
   token keeps the whole grid on screen with one horizontal scroll rather than
   two, and the mono digits stay legible at 11px. */
@media (max-width: 40rem) {
  .chart-page .chartwrap { --cell-size: var(--cell-size-dense); }
}
/* At 360px the dense grid still runs 24px past the scroller, so the ace column
   sits off screen with nothing to signal it. One step smaller puts all ten
   upcards on a 360px screen at once. The cells are not tap targets, and the
   glyph stays at 12px. */
@media (max-width: 23.5rem) {
  .chart-page .chartwrap { --cell-size: 1.55rem; }
}

.chartprov {
  font-size: var(--text-xs);
  color: var(--text-3);
  max-width: var(--measure-prose);
}
/* Visually hidden, still read by a screen reader. The corner cell of the grid
   names the row axis, which a sighted reader gets from the row headers. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ── the house edge block ────────────────────────────────────────────────── */
/* A house edge is a number to compare, so it is set in the mono face with
   tabular figures. Two figures in a column line up on the decimal point. */
.edge-table dd {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-num-sm);
  color: var(--text-1);
}

.spread-table,
.disagree-table,
.cmp-rules,
.cmp-cells {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.spread-table th,
.spread-table td,
.disagree-table th,
.disagree-table td,
.cmp-rules th,
.cmp-rules td,
.cmp-cells th,
.cmp-cells td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: top;
}
.spread-table thead th,
.disagree-table thead th,
.cmp-rules thead th,
.cmp-cells thead th {
  color: var(--text-3);
  font-weight: var(--weight-medium);
  border-bottom: 1px solid var(--border-ui);
  white-space: nowrap;
}
.spread-table tbody th,
.disagree-table tbody th,
.cmp-rules tbody th,
.cmp-cells tbody th {
  font-weight: var(--weight-medium);
  color: var(--text-1);
}
.spread-table td,
.disagree-table td,
.cmp-rules td,
.cmp-cells td {
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
/* M15. A link in a data cell is a standalone action, so it fills a 44px target
   rather than the 19px its text occupies. */
/* Browser re-verification found the same 21px target surviving on the authors
   hub, because the earlier selector list named the chart and comparison tables
   only. Every link in any data cell on any of these tables is covered now, and
   the tables themselves are named rather than the pages that carry them, so a
   new page reusing the table gets the floor without a further CSS edit. */
.spread-table a,
.disagree-table a,
.cmp-rules a,
.cmp-cells a,
.rules-table td a,
.rules-table tbody th a,
.rules-index td a,
.rules-index tbody th a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
}
.spread-table a { overflow-wrap: anywhere; }
.disagree-table td:nth-child(5) { font-family: var(--font-mono); }

/* The row that actually differs is the answer on a comparison page, so it is
   marked with a tint and a word. The word carries it on its own, because a
   tint alone is not a difference a colour blind reader can read. */
.cmp-rules tbody tr[data-differs] {
  background: var(--surface-2);
}
.cmp-rules tbody tr[data-differs] th,
.cmp-rules tbody tr[data-differs] .cmp-mark {
  color: var(--text-1);
}
.cmp-mark {
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  white-space: nowrap;
}

/* ── shared lists ────────────────────────────────────────────────────────── */
.rules-index-list {
  max-width: var(--measure-prose);
  margin: 0 0 var(--space-5);
  padding-left: var(--space-5);
  display: grid;
  gap: var(--space-2);
}
.rules-index-list li {
  font-size: var(--text-sm);
  color: var(--text-2);
  overflow-wrap: anywhere;
}
.shared-edge {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--text-3);
}
.cmp-play { list-style: none; padding-left: 0; }
.cmp-play li { margin: 0; }

.byline {
  max-width: var(--measure-prose);
  margin: 0 0 var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface-1);
}
.byline p {
  margin: 0 0 var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-2);
  overflow-wrap: anywhere;
}
.byline p:last-child { margin-bottom: 0; }
.natext {
  font-size: var(--text-xs);
  color: var(--text-3);
  max-width: var(--measure-prose);
}

/* ── the calculators ─────────────────────────────────────────────────────── */
/* Eleven selectors. Two columns from 30rem up, one below, and every control is
   at least the minimum tap target on every viewport. */
.calc-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3) var(--space-5);
  margin: 0 0 var(--space-6);
  max-width: 44rem;
}
@media (min-width: 30rem) {
  .calc-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.calc-form .field {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  max-width: none;
}
.calc-form label {
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--text-3);
}
.calc-form select {
  min-height: var(--tap-min);
  width: 100%;
  padding: 0 var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--text-1);
  background: var(--surface-2);
  border: 1px solid var(--border-ui);
  border-radius: var(--radius-md);
  appearance: none;
}
.calc-form select:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
.calc-result {
  max-width: 44rem;
  margin: 0 0 var(--space-6);
}
.calc-result h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-base);
}
.calc-result p {
  font-size: var(--text-sm);
  color: var(--text-2);
}
.calc-result .rules-play { display: flex; flex-wrap: wrap; gap: var(--space-3); }

/* The D3 banner. A player-advantage rule set is selectable in the calculator
   and the trainer only, so wherever its figure appears this block appears above
   it. Warn rather than danger: the figure is correct, the table is not real. */
.calc-advantage {
  margin: 0 0 var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--warn);
  border-left-width: 4px;
  border-radius: var(--radius-md);
  background: var(--surface-2);
}
.calc-advantage h3 { margin: 0 0 var(--space-2); color: var(--warn); }
.calc-advantage p { margin: 0; }
.calc-advantage-note {
  max-width: var(--measure-prose);
  font-size: var(--text-sm);
  color: var(--text-2);
}
.rules-play .btn + .btn { margin-left: 0; }
.rules-page .rules-play { display: flex; flex-wrap: wrap; gap: var(--space-3); }

/* The hub table carries long table names in the first column and the house
   edge in the last one. At the shared nowrap setting the table runs 833px wide,
   so the house edge column sits off screen on a tablet. Wrapping the name
   column below 60rem keeps every figure in view without a scroll. */
@media (max-width: 60rem) {
  .charts-hub .rules-index tbody th,
  .cmp-hub .rules-index tbody th { white-space: normal; }
  .charts-hub .rules-index th,
  .charts-hub .rules-index td,
  .cmp-hub .rules-index th,
  .cmp-hub .rules-index td { padding-inline: var(--space-3); }
}
/* The comparison hub names two tables per row, so its first two columns are the
   longest strings on the site. They wrap at every width. */
.cmp-hub .rules-index tbody th,
.cmp-hub .rules-index td:first-of-type { white-space: normal; }

/* -------------------------------------------------------------------- FAQ --- */
/* A definition list, because a question and its answer are a term and its
   definition. The dt carries the weight so the list scans as a list of questions
   at a glance, and every answer stays inside the prose measure. */
.faq {
  max-width: var(--measure-prose);
  margin: 0 0 var(--space-6);
}
.faq dt {
  margin: var(--space-4) 0 var(--space-2);
  font-weight: var(--weight-bold);
  color: var(--text-1);
}
.faq dt:first-child { margin-top: 0; }
.faq dd {
  margin: 0;
  padding: 0;
  color: var(--text-2);
}

/* --------------------------------------------- reviewers and methodology --- */
.byline a { color: var(--text-1); }
.author-page .lede,
.authors-hub .lede,
.method-page .lede { max-width: var(--measure-prose); }
/* The refusals list on the methodology page is the part of it a reader is most
   likely to be looking for, so it is set as its own block rather than as another
   run of body text. */
.method-refusals {
  max-width: var(--measure-prose);
  margin: 0 0 var(--space-6);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--border-ui);
  border-radius: var(--radius-md);
  background: var(--surface-1);
}
.method-refusals li { margin: 0 0 var(--space-2); color: var(--text-2); }
.method-refusals li:last-child { margin-bottom: 0; }
