/* InstantPalette - contrast checker (layer 5, /contrast-checker only)
   Loaded after tokens.css -> base.css -> site.css -> tools.css.
   Only what is genuinely specific to this tool lives here: the paired colour inputs, the score card, the
   criteria list, the preview specimen, the suggestion tiles and the N x N contrast grid.
   Buttons, inputs, sliders, segmented controls, result headings and swatch tiles come from the shared layers. */

/* ================= Paired colour inputs ================= */
/* Foreground | swap | background. The swap button sits on the control baseline, never above the labels. */
.cc-pair {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: end;
  gap: 12px 14px;
}
.cc-pair .field { min-width: 0; }
.cc-swap {
  width: 44px; height: 44px; min-height: 44px; padding: 0;
  flex: none;
}
.cc-swap .i { width: 20px; height: 20px; }

/* A native colour input wearing the shared .twell shape */
.cc-well {
  -webkit-appearance: none; appearance: none;
  cursor: pointer;
}
.cc-well::-webkit-color-swatch-wrapper { padding: 0; }
.cc-well::-webkit-color-swatch { border: 0; border-radius: calc(var(--r) - 1px); }
.cc-well::-moz-color-swatch { border: 0; border-radius: calc(var(--r) - 1px); }
.cc-eye { width: 44px; height: 44px; min-height: 44px; flex: none; padding: 0; }
.cc-eye .i { width: 20px; height: 20px; }

/* Opacity row: the slider and the blended value it produces */
.cc-alpha { max-width: 420px; }
/* A 24px slider is a thin tap target; the shared track stays centred inside a taller hit area */
@media (hover: none), (pointer: coarse) { .cc-alpha .trange { height: 44px; } }
.cc-blend { margin: 6px 0 0; font: 400 12px/1.5 var(--f-sans); color: var(--ink-2); }
.cc-blend .mono { font: 500 12px/1 var(--f-mono); }

@media (max-width: 640px) {
  .cc-pair { grid-template-columns: 1fr; }
  .cc-swap { justify-self: start; margin: -2px 0; }
}

/* ================= Score card ================= */
.cc-res {
  display: grid;
  grid-template-columns: minmax(200px, 260px) 1fr;
  gap: 16px 24px;
  padding: 16px;
  border: 1px solid var(--line-2); border-radius: var(--r-lg);
  background: var(--raised);
}
.cc-score { min-width: 0; }
.cc-score .tbig { margin: 0; font-size: 44px; }
.cc-sum { margin: 6px 0 0; font: 600 15px/1.4 var(--f-sans); }
.cc-apca { margin: 10px 0 0; font: 400 12px/1.5 var(--f-sans); color: var(--ink-2); }
.cc-apca .mono { font: 500 12px/1 var(--f-mono); color: var(--ink-1); }
.cc-apca .cc-tag {
  display: inline-block; margin-left: 4px; padding: 1px 6px;
  border: 1px solid var(--line-2); border-radius: var(--r-sm);
  font-size: 12px; color: var(--ink-2);
}

/* Criteria: name, required ratio, pass or fail. Never colour alone. */
.cc-crit { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; align-content: start; }
.cc-crit li {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 8px 12px;
  min-height: 34px;
  padding: 4px 0;
  border-top: 1px solid var(--line);
}
.cc-crit li:first-child { border-top: 0; }
.cc-crit .cc-c-n { font: 400 14px/1.35 var(--f-sans); min-width: 0; }
.cc-crit .cc-c-n b { font-weight: 600; }
.cc-crit .cc-c-n small { display: block; font: 400 12px/1.4 var(--f-sans); color: var(--ink-2); }
.cc-crit .cc-c-r { font: 500 13px/1 var(--f-mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }
.cc-crit .tpass, .cc-crit .tfail { justify-self: end; min-width: 74px; justify-content: center; }

.cc-acts { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 10px; }

@media (max-width: 700px) {
  .cc-res { grid-template-columns: 1fr; padding: 14px; }
  .cc-score .tbig { font-size: 38px; }
}

/* ================= Live preview specimen ================= */
.cc-prev {
  margin: 14px 0 0;
  padding: 20px;
  border-radius: var(--r-lg);
  background: var(--pbg, var(--sunken));
  color: var(--pfg, var(--ink-1));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-1) 12%, transparent);
}
.cc-prev-h { margin: 0 0 10px; font: 700 26px/1.2 var(--f-sans); letter-spacing: -.01em; color: inherit; }
.cc-prev-p { margin: 0 0 14px; font: 400 16px/1.6 var(--f-sans); max-width: 58ch; color: inherit; }
/* The link sample is a specimen, not a link: it wears whatever pair is being tested, and a real anchor at a
   failing ratio would be a genuine 1.4.3 failure on this page and an unreadable tab stop for a keyboard user.
   The button and caption samples are inert spans for the same reason. */
.cc-prev-a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.cc-prev-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; }
.cc-prev-btn {
  min-height: 40px; padding: 0 16px;
  display: inline-flex; align-items: center; gap: 8px;
  border: 1.5px solid currentColor; border-radius: var(--r);
  background: transparent; color: inherit;
  font: 600 15px/1 var(--f-sans);
}
.cc-prev-icon { display: inline-flex; align-items: center; gap: 8px; font: 400 14px/1 var(--f-sans); color: inherit; }
.cc-prev-icon .i { width: 22px; height: 22px; color: inherit; }
.cc-prev-small { margin: 14px 0 0; font: 400 12px/1.5 var(--f-sans); color: inherit; opacity: .85; }
@media (max-width: 600px) {
  .cc-prev { padding: 16px; }
  .cc-prev-h { font-size: 22px; }
}

/* ================= Suggestions ================= */
.cc-sugg-top { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; }
.cc-sugg-top .field-l { margin-right: -6px; }
/* A wrapping row rather than a grid: with one suggestion the tile grows to a readable card instead of
   sitting in a single 168px track beside 750px of empty panel. */
.cc-tiles { display: flex; flex-wrap: wrap; gap: 10px; }
.cc-tiles > .cc-hint { flex: 1 1 100%; margin: 0; }
/* The tile itself stays chrome, so its labels always read; the strip inside it is the real pair preview. */
.cc-tile {
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px 12px;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--raised); color: var(--ink-1);
  text-align: left;
  flex: 1 1 200px; max-width: 320px; min-width: 0;
}
.cc-tile.is-off { flex-basis: 280px; max-width: 420px; }
.cc-tile .t-step { font: 400 12px/1.3 var(--f-sans); color: var(--ink-2); }
.cc-tile .t-prev {
  display: flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 10px;
  border-radius: var(--r-sm);
  background: var(--tbg, var(--sunken)); color: var(--tfg, var(--ink-1));
  font: 600 17px/1 var(--f-sans);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-1) 12%, transparent);
}
.cc-tile .t-code { font: 500 14px/1.2 var(--f-mono); letter-spacing: -.01em; }
.cc-tile .t-meta { margin-top: auto; font: 500 12px/1.3 var(--f-mono); font-variant-numeric: tabular-nums; color: var(--ink-2); }
.cc-tile:focus-visible { outline: 2px solid var(--ink-1); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { button.cc-tile:hover { border-color: var(--ink-1); } }
/* A target nothing can reach: no colour to show, so the tile just says so */
.cc-tile.is-off { border-style: dashed; background: transparent; cursor: default; }
.cc-tile.is-off .t-code { color: var(--ink-2); font: 400 13px/1.4 var(--f-sans); }
.cc-undo { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.cc-undo p { margin: 0; font: 400 12px/1.5 var(--f-sans); color: var(--ink-2); }
.cc-undo .dot {
  display: inline-block; width: 12px; height: 12px; flex: none;
  border-radius: 3px; background: var(--c, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-1) 20%, transparent);
}

/* ================= Palette contrast grid ================= */
/* The wrapper holds two edge masks over the scroller:
   - the left one covers the gutter beside the frozen row-header column, so a cell scrolled halfway under
     it fades out instead of showing a sliver of half-drawn glyphs (--frz is the frozen width, set in JS);
   - the right one, plus a thin always-visible scrollbar, is the signal that more columns exist.
   Both are toggled by the scroll handler and are inert to the pointer. */
/* isolate, so the masks only have to outrank the grid's own sticky column (z-index 1) and its cells */
.cc-gouter { position: relative; isolation: isolate; }
.cc-gouter::before, .cc-gouter::after {
  content: ''; position: absolute; top: 0; bottom: 0; z-index: 2;
  pointer-events: none; opacity: 0;
}
/* --over is how much of the column being scrolled under the frozen one still pokes out (capped in JS), so a
   thin fragment is painted out completely and a wide one keeps enough of itself to read as a partial cell */
.cc-gouter::before {
  left: var(--frz, 97px);
  width: var(--over, 28px);
  background: linear-gradient(to right, var(--raised) 0 max(0px, calc(var(--over, 28px) - 10px)), transparent);
}
/* The right edge has to read as "more columns", not as a soft vignette, so it keeps a solid band at the very
   edge and fades over a wider run. The written hint below the grid carries the same message in words. */
.cc-gouter::after {
  right: 0; width: 56px;
  background: linear-gradient(to left, var(--raised) 0 16px,
    color-mix(in srgb, var(--raised) 75%, transparent) 45%, transparent);
}
.cc-gouter.is-sl::before, .cc-gouter.is-sr::after { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .cc-gouter::before, .cc-gouter::after { transition: opacity .12s linear; }
}
.cc-gwrap {
  overflow-x: auto; overscroll-behavior-x: contain; padding-bottom: 2px;
  scrollbar-width: thin; scrollbar-color: var(--ink-3) transparent;
}
.cc-gwrap::-webkit-scrollbar { height: 10px; }
.cc-gwrap::-webkit-scrollbar-track { background: transparent; }
.cc-gwrap::-webkit-scrollbar-thumb {
  background: var(--ink-3); border-radius: 999px;
  border: 3px solid transparent; background-clip: content-box;
}
.cc-gwrap:focus-visible { outline: 2px solid var(--ink-1); outline-offset: 2px; }
/* Fixed layout so a two-colour grid keeps tidy cells instead of stretching them across the panel. The
   columns are sized so that all eight of them fit inside the panel at the usual desktop widths; only a
   window narrow enough for the ad rails to eat the column (1280 and 1600 with a rail in use) still scrolls,
   and then the hint below the grid says so.
   min-width: max-content is what stops such a panel from squeezing the columns below the widths set here -
   the scroller is there to be scrolled, the cells are not there to be clipped. */
.ccg {
  border-collapse: separate; border-spacing: 3px; margin: 0 auto 0 0;
  table-layout: fixed; width: auto; min-width: max-content;
}
.ccg th, .ccg td { padding: 0; vertical-align: middle; }
/* The first column is the frozen one, so every pixel it takes is a pixel of grid the reader has to scroll
   for. It is sized to the widest thing it must hold - a swatch plus '#RRGGBB' - and the corner legend wraps
   inside that width instead of setting it. */
.ccg-corner {
  width: 96px;
  font: 400 12px/1.4 var(--f-sans); color: var(--ink-2);
  text-align: left; padding: 0 10px 0 0;
}
.ccg-corner span { display: block; }
.ccg-h {
  width: 97px; padding: 4px;
  font: 500 12px/1.3 var(--f-mono); color: var(--ink-1); text-align: left; white-space: nowrap;
}
.ccg-h .dot, .ccg-corner .dot {
  display: inline-block; width: 12px; height: 12px; margin-right: 4px; vertical-align: -1px;
  border-radius: 3px; background: var(--c, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-1) 20%, transparent);
}
/* The colour of each row travels with the reader when the grid scrolls sideways */
.ccg-corner, .ccg-row { position: sticky; left: 0; z-index: 1; background: var(--raised); }
.ccg-row { padding-right: 10px; }
/* Shown by the script whenever the grid really does overflow, at any width - not by a width guess */
.cc-scrollnote { margin: 10px 0 0; }
.ccg-c {
  display: flex; flex-direction: column; justify-content: center; gap: 4px;
  width: 100%; min-width: 97px; min-height: 62px; padding: 8px 7px;
  border: 0; border-radius: var(--r-sm);
  background: var(--cbg, var(--sunken)); color: var(--cink, var(--ink-1));
  text-align: left;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink-1) 12%, transparent);
}
.ccg-c .n {
  display: flex; align-items: baseline; gap: 6px; white-space: nowrap;
  font: 500 13px/1.1 var(--f-mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
/* The specimen: the row colour written on the column colour, the pair exactly as it would appear */
.ccg-c .aa { font: 600 17px/1 var(--f-sans); color: var(--cspec, currentColor); }
.ccg-c .b { display: inline-flex; align-items: center; gap: 4px; font: 500 12px/1.1 var(--f-sans); }
.ccg-c .b .i { width: 13px; height: 13px; stroke-width: 2.6; }
/* Fail keeps a dashed inner edge, pass a plain one, so the state survives a greyscale print */
.ccg-c { position: relative; }
.ccg-c.is-fail::after {
  content: ''; position: absolute; inset: 3px;
  border: 1.5px dashed currentColor; border-radius: 4px; opacity: .7;
  pointer-events: none;
}
/* Chrome ink, because the ring sits on the panel and the cell's own ink can match it */
.ccg-c:focus-visible { outline: 2px solid var(--ink-1); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .ccg-c:hover { box-shadow: inset 0 0 0 2px currentColor; } }
.ccg-same {
  min-width: 92px; min-height: 62px; padding: 8px;
  border: 1px dashed var(--line-2); border-radius: var(--r-sm);
  font: 400 12px/1.3 var(--f-sans); color: var(--ink-2);
  display: flex; align-items: center;
}
.cc-gsum { margin: 12px 0 0; font: 400 14px/1.6 var(--f-sans); color: var(--ink-2); }
.cc-gsum b { color: var(--ink-1); font-weight: 600; }
.cc-empty { margin: 0; font: 400 15px/1.6 var(--f-sans); color: var(--ink-2); max-width: 62ch; }
.cc-empty a { color: var(--ink-1); }
.cc-gactions { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; }
.cc-gactions .field { flex: 1 1 260px; }

/* Phones: the frozen column is the only thing between the reader and a third column of data, so it drops to
   the swatch plus the hex with no slack around it. The hex itself stays - the swatch alone would leave the
   rows unnameable - and the column headers keep the same hexes for the other axis. */
@media (max-width: 600px) {
  /* A 56px fade is a fifth of a phone screen, and the written hint below the grid already carries the
     message here, so the edge keeps only enough of itself to read as an edge. */
  .cc-gouter::after { width: 32px; background: linear-gradient(to left, var(--raised) 0 10px, transparent); }
  .ccg-h { width: 90px; padding-left: 4px; padding-right: 4px; }
  .ccg-corner, .ccg-row { width: 84px; }
  .ccg-corner { padding-right: 6px; }
  .ccg-row { padding-right: 4px; }
  .ccg-h .dot, .ccg-corner .dot { margin-right: 4px; }
  /* Same content, tuned to the narrowest ratio that has to fit ('19.6:1'), so a third column starts on screen */
  .ccg-c { min-width: 90px; padding: 8px 7px; }
  .ccg-c .n { font-size: 12px; gap: 5px; }
  .ccg-c .aa { font-size: 16px; }
  .ccg-same { min-width: 90px; }
}

/* The three ratio buttons are targets, so each keeps 44px of width. Below 420px they take their own row
   in the panel head instead of being squeezed (and clipped) beside the heading. */
#lvl button { min-width: 44px; }
@media (max-width: 420px) {
  .cc-gridhd { flex-wrap: wrap; }
  .cc-gridhd #lvl { flex: 1 0 100%; justify-content: flex-start; }
}

/* ================= Misc ================= */
.cc-note { margin: 12px 0 0; font: 400 12px/1.6 var(--f-sans); color: var(--ink-2); max-width: 68ch; }
.cc-hint { margin: 0; font: 400 12px/1.5 var(--f-sans); color: var(--ink-2); }
.tres + .tpanel { margin-top: 24px; }
.cc-openin { margin: 24px 0 0; }
