@charset "utf-8";
/* ==========================================================================
   /keyboard-key-counter/ — tool.css
   Page-specific rules only. Everything structural comes from
   /assets/css/design-system.css; this file adds the heat tiers, the sortable
   table header and a few layout tweaks that exist nowhere else on the site.
   ========================================================================== */

/* --------------------------------------------------------------- controls */

.kc-controls { margin-block-start: 0.9rem; }

/* The capture panel holds one short label, not a running measurement, so it
   does not need the full-height test stage. */
.kc-stage {
  min-block-size: clamp(148px, 22vh, 210px);
  gap: 0.6rem;
}

.kc-stage .stage__big {
  font-size: clamp(1.6rem, 1rem + 3.6vw, 3rem);
  max-inline-size: 100%;
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------- options */

.kc-opts {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.kc-check {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-block-size: 44px;
  font-size: 0.9375rem;
  color: var(--text);
  cursor: pointer;
}

.kc-check input {
  flex: none;
  inline-size: 20px;
  block-size: 20px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Align the explanation with the label text rather than the checkbox. */
.kc-opt-note {
  padding-inline-start: 1.85rem;
  margin-block-end: 0.55rem;
  max-inline-size: 62ch;
}

/* ------------------------------------------------------------ results bits */

.kc-lede { max-inline-size: 68ch; }

.kc-callouts {
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  margin-block-end: var(--space);
}

/* A long session can list a hundred keys; keep the table a fixed viewport
   block and let the sticky header from the design system do its job. */
.kc-tblwrap {
  max-block-size: min(60vh, 520px);
  overflow-y: auto;
}

/* --------------------------------------------------- sortable table header */

/* The heading cell hands its padding to the button so the whole cell is the
   hit target (>= 44px tall). aria-sort on the <th> carries the state; the
   glyph below is decorative reinforcement, never the only cue. */
.tbl thead th[data-col] { padding: 0; }

.kc-sort {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  inline-size: 100%;
  min-block-size: 44px;
  padding: 0.5rem 0.85rem;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-align: start;
  text-transform: inherit;
  cursor: pointer;
}

.kc-sort:hover { color: var(--text); }

.tbl thead th.num .kc-sort { justify-content: flex-end; }

.kc-sort__ind {
  flex: none;
  inline-size: 1em;
  text-align: center;
  opacity: 0.55;
}

.kc-sort__ind::after { content: "\2195"; }                       /* up-down arrow */

th[aria-sort="ascending"] .kc-sort__ind::after { content: "\25B2"; }
th[aria-sort="descending"] .kc-sort__ind::after { content: "\25BC"; }

th[aria-sort="ascending"] .kc-sort__ind,
th[aria-sort="descending"] .kc-sort__ind {
  opacity: 1;
  color: var(--accent);
}

.kc-keycell { font-weight: 600; }

/* ------------------------------------------------------------- heat map ui */

.kc-mapctl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr));
  gap: 0.75rem;
  margin-block-start: 0.9rem;
}

.kc-map-mount { margin-block-start: 0.9rem; }

/* Every cap here carries a legend AND a press count, so it needs more room
   than a plain map — but the FLOOR is the shared one (design-system.css §14:
   40px, 48px on coarse pointers). This only lifts the growth curve and the
   ceiling; it must never lower the floor, which is what used to leave this
   page at 24x24px caps with a 7.3px legend on a phone. */
.kc-map-mount .kbd-map { --u: clamp(40px, 4.4vw, 54px); }

@media (pointer: coarse) {
  .kc-map-mount .kbd-map { --u: clamp(48px, 4.4vw, 54px); }
}

/* Heat tiers. Intensity is expressed three ways at once — the printed count,
   the fill bar along the bottom edge, and the shade — so the map is readable
   without colour vision and in monochrome print. The strongest tier stays at
   40% accent because that is the point where --text still clears 4.5:1 on the
   mixed background in both themes. */
.kbd-key.kc-heat {
  color: var(--text);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border-ui));
}

.kbd-key.kc-heat--1 { --kc-fill: 25%;  background: color-mix(in srgb, var(--accent) 10%, var(--surface-2)); }
.kbd-key.kc-heat--2 { --kc-fill: 50%;  background: color-mix(in srgb, var(--accent) 20%, var(--surface-2)); }
.kbd-key.kc-heat--3 { --kc-fill: 75%;  background: color-mix(in srgb, var(--accent) 30%, var(--surface-2)); }
.kbd-key.kc-heat--4 { --kc-fill: 100%; background: color-mix(in srgb, var(--accent) 40%, var(--surface-2)); }

.kbd-key.kc-heat::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-end: 0;
  block-size: 3px;
  inline-size: var(--kc-fill, 25%);
  background: var(--accent);
}

.kbd-key.kc-heat .kbd-key__stat {
  color: var(--text);
  font-weight: 700;
}

/* The live press flash must still win over any heat tier, so it is restated
   here at matching specificity and later in the cascade. */
.kbd-key.kbd-key--active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

.kbd-key.kbd-key--active .kbd-key__stat { color: var(--accent-ink); }
.kbd-key.kbd-key--active::before { background: var(--accent-ink); opacity: 0.55; }

/* ----------------------------------------------------------------- misc */

#kc-excl-line { margin-block-end: 0.6rem; }

#kc-unmapped { margin-block-start: 0.6rem; }

@media print {
  .kc-tblwrap { max-block-size: none; overflow: visible; }
}
