/* Monitor Test Online — monitor-only rules. Shared tokens and components (header bar,
 * stats, readout cards, panels, log table, chips, FAQ/troubleshooting) live in
 * ../base.css, loaded before this file.
 *
 * One rule that matters here: the canvas is a measuring instrument, not decoration.
 * Everything painted on it is a literal sRGB value chosen by the pattern — never a
 * theme token — because the whole point is judging what the panel does with a known
 * colour. Only the chrome around it reads tokens.
 */

/* Half the screen filled — the black-and-white split used for contrast and black level — so
   the mark says "test pattern" rather than just "monitor". The fill meets the screen's inner
   edge exactly, and its corners carry the stroke's radius less half the stroke width, so the
   split sits flush inside the outline instead of poking through it. */
.logo-plate { fill: var(--accent); }
.logo-half { fill: var(--on-accent); }
.logo-screen { fill: none; stroke: var(--on-accent); stroke-width: 1.7; }
.logo-stand { fill: none; stroke: var(--on-accent); stroke-width: 1.7; stroke-linecap: round; }

/* ---------- stage ---------- */
/* Canvas and catalog side by side: picking the next pattern is the main thing you do while
   looking at one, so the list belongs within reach of the preview rather than further down
   the page. The column stretches to the canvas, and the list scrolls inside it. */
/* The canvas column is sized to the canvas plus the card's own padding, not to whatever
   space is going, so the card's background and border stop at the preview instead of
   trailing a few hundred pixels of empty panel either side. The pair is then centred. */
.stage-wrap {
  /* The card is the preview plus its own padding and border — the one width both the grid
     column and the stacked layout are sized from. */
  --card-w: calc(var(--preview-max-w, 700px) + 2 * clamp(12px, 2vw, 20px) + 2px);
  margin: 18px 0 10px;
  display: grid;
  /* Card sized to the preview, catalog takes everything left over: left-aligned rather than
     centred so the slack goes into the list instead of sitting either side of the pair. */
  grid-template-columns: minmax(0, var(--card-w)) minmax(240px, 1fr);
  gap: 10px; align-items: stretch;
}
.stage-main { min-width: 0; }

/* The column is the positioning context and the panel fills it absolutely, so the panel's
   own content cannot size the grid row. Otherwise 37 items stack to ~1400px and stretch the
   canvas column to match instead of scrolling. */
.catalog-col { position: relative; min-width: 0; min-height: 340px; }
.catalog-panel {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; min-height: 0;
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  padding: 12px 13px; box-shadow: var(--shadow);
}
.catalog-panel h2 { margin-bottom: 8px; }

.stage {
  position: relative;
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
  padding: 14px clamp(12px, 2vw, 20px) 10px;
  box-shadow: var(--shadow);
}

/* The overlays centre on the canvas, not on the padded card around it, so this wrapper is
   the positioning context rather than .stage.
   Capping the width here rather than the canvas's height is deliberate: the canvas is
   width:100% of this box with an aspect-ratio, so the ratio always holds. Clamping the
   canvas with max-height instead just squashed the box wider than the panel it represents,
   which is the one thing a scale-model preview must not do. */
.screen-wrap { position: relative; max-width: var(--preview-max-w, 700px); margin: 0 auto; }

/* The canvas keeps the panel's own aspect ratio so the preview is a scale model of what
   full screen will show — a 16:9 pattern previewed in a 4:3 box would mislead. */
/* No max-height: any height clamp fights the aspect-ratio and squashes the box wider than
   the panel. The wrapper's max-width already bounds the height to about 400px. */
canvas#screen {
  display: block; width: 100%; aspect-ratio: var(--panel-ratio, 16 / 9);
  background: #000; border: 1px solid var(--line); border-radius: 10px;
}

/* The stage takes focus so arrow keys can drive it without hijacking the whole page. */
.stage:focus { outline: none; }
.stage:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }

/* ---------- full-screen call to action ---------- */
/* Compact and centred, never a full-bleed cover: the pattern has to stay visible around it,
   which is the entire point of having a preview. */
.cta {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 2; font: inherit; cursor: pointer; text-align: center;
  display: grid; justify-items: center; gap: 5px;
  width: min(64%, 288px); padding: 14px 16px;
  border: 1px solid var(--line); border-radius: 16px;
  /* Plain tokens, not color-mix: Chrome does not re-resolve a color-mix over a custom
     property when the theme stamp changes, so the card kept its dark background in light
     mode. Everything here has to flip with the theme. */
  background: var(--panel-2);
  color: var(--text);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .16);
  transition: border-color .15s ease, transform .15s ease;
}
.cta:hover { border-color: var(--accent); }
.cta:active { transform: translate(-50%, -50%) scale(.985); }
.cta:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 3px; }
.cta[hidden] { display: none; }

.cta-icon {
  display: grid; place-items: center;
  width: 36px; height: 36px;
  border-radius: 10px;
  background: var(--panel);
  border: 1px solid var(--line);
}
.cta-icon svg {
  width: 18px; height: 18px;
  fill: none; stroke: var(--text); stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.cta-title { font-size: 0.85rem; font-weight: 600; letter-spacing: -0.01em; }

/* What to look for on the pattern currently shown. It sits under the canvas rather than in
   the card so it is not the same sentence twice within a few hundred pixels, and so it is
   still there on a narrow screen, where the card is down to an icon and one word. */
.stage-desc {
  margin: 6px 0 0;
  color: var(--muted); font-size: 0.8rem; line-height: 1.45;
  max-width: 68ch; text-wrap: pretty;
}


/* ---------- identity / hint strip under the canvas ---------- */
.stage-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px 16px; flex-wrap: wrap;
  margin-top: 10px;
  font-family: var(--mono); font-size: 0.76rem;
}
.foot-id { display: inline-flex; align-items: center; gap: 7px; min-width: 0; color: var(--text); }
.foot-id b { font-weight: 600; }
.foot-sep { color: var(--dim); }
.foot-id span:not(.foot-sep) { color: var(--muted); }
.foot-icon {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: var(--muted); stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.foot-key { color: var(--dim); }
.foot-key b { color: var(--muted); font-weight: 600; }

.stage-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  font: inherit; font-size: 1.1rem; line-height: 1; cursor: pointer;
  color: var(--text); background: var(--panel);
  border: 1px solid var(--line); border-radius: 999px;
  width: 34px; height: 34px; padding: 0;
  opacity: .75; box-shadow: var(--shadow);
}
.stage-nav:hover { opacity: 1; border-color: var(--accent); color: var(--accent); }
.stage-nav.prev { left: 4px; }
.stage-nav.next { right: 4px; }

/* ---------- full screen ---------- */
/* In full screen the stage IS the panel: no padding, no card, no rounding — any of those
   would put chrome-coloured pixels on a surface being judged. */
.stage:fullscreen {
  padding: 0; border: 0; border-radius: 0; background: #000;
  display: grid; place-items: center;
}
/* max-width and the auto margins are the preview's sizing and must be cleared here, or the
   cap leaks into full screen and the pattern renders at preview size in the middle of a
   black panel. It also has to be the full panel for the backing store to match the panel's
   real pixels — a "1 px" checkerboard is only one panel pixel if this box is 1:1. */
.stage:fullscreen .screen-wrap {
  width: 100vw; height: 100vh; max-width: none; margin: 0;
}
.stage:fullscreen canvas#screen {
  width: 100vw; height: 100vh; max-height: none; aspect-ratio: auto;
  border: 0; border-radius: 0;
}
.stage:fullscreen .stage-nav, .stage:fullscreen .cta,
.stage:fullscreen .stage-foot, .stage:fullscreen .stage-desc { display: none; }
.stage:fullscreen .hud { display: flex; }
.stage.hide-cursor:fullscreen { cursor: none; }

.hud {
  display: none;
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%); z-index: 3;
  align-items: center; gap: 14px; flex-wrap: wrap; justify-content: center;
  max-width: min(92vw, 640px);
  padding: 9px 16px; border-radius: 999px;
  background: rgba(12, 14, 20, .82); border: 1px solid rgba(255, 255, 255, .14);
  color: #e7eaf3; font-family: var(--mono); font-size: 0.76rem;
  backdrop-filter: blur(3px);
  transition: opacity .4s ease;
}
.hud.faded { opacity: 0; }
.hud-name { font-weight: 600; }
.hud-keys { color: #98a1b5; }
.hud-keys b { color: #e7eaf3; font-weight: 600; }

/* ---------- stage bar ---------- */
.stage-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  margin-top: 12px;
}
.counter {
  font-family: var(--mono); font-size: 0.8rem; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.verdict-btns { display: flex; flex-wrap: wrap; gap: 6px; margin-right: auto; }
/* v-pass / v-flag, not pass / flag: base.css already owns .flag as a chip component and
   it would style these buttons as chips. */
.btn.v-pass[aria-pressed="true"] { color: var(--good); border-color: var(--good); font-weight: 600; }
.btn.v-flag[aria-pressed="true"] { color: var(--bad); border-color: var(--bad); font-weight: 600; }

.swatch-pick {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 0.68rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.09em;
}
.swatch-pick input[type="color"] {
  width: 40px; height: 28px; padding: 2px; cursor: pointer;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
}
.swatch-pick[hidden] { display: none; }

/* Shown only on a pattern flagged photosensitive, which holds a warning card until this
   is pressed. */
.btn.v-start { color: var(--warn); border-color: var(--warn); font-weight: 600; }
.btn.v-start[hidden] { display: none; }

/* ---------- info block, under the canvas ---------- */
/* base.css sizes these for the keyboard and mic pages, where the stats are the first thing
   on the page. Here they sit below the canvas as a reference strip you glance at, so every
   measurement is tighter. Scoped to this stylesheet, so the siblings are unaffected. */
.stats { grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 8px; margin-top: 14px; }
.stat { padding: 8px 11px; }
.stat .k { font-size: 1rem; }
.stat .v { font-size: 0.62rem; letter-spacing: 0.07em; }
.bar-track { margin-top: 6px; height: 3px; }

.readout { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 8px; margin-top: 8px; }
.now, .flags { padding: 10px 13px; }
.now-meta { grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 6px 14px; }
.now-meta span { font-size: 0.6rem; }
.now-meta code { font-size: 0.78rem; }
.flags h2 { margin-bottom: 7px; font-size: 0.66rem; }
/* Flex, not the shared grid: fixed columns forced six chips onto two rows and wrapped
   "Reduced motion" inside its own chip, which set the height of the whole readout.
   Sized to content, they fit one row and the row is half as tall. */
.flag-grid { display: flex; flex-wrap: wrap; gap: 5px; }
.flag { font-size: 0.66rem; padding: 5px 9px; white-space: nowrap; }


/* ---------- pattern catalog ---------- */
.catalog {
  /* 170px, not less: at four columns the longest names ("9-zone uniformity",
     "1 px checkerboard") ellipsised, and a truncated list is worse than a shorter one. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 5px;
  overflow-y: auto; min-height: 0; flex: 1;
  padding-right: 2px;
}
.cat-head {
  grid-column: 1 / -1; margin: 8px 0 0;
  font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--dim); font-weight: 600;
}

.cat-head:first-child { margin-top: 0; }

/* Category headings stay put while the list scrolls under them. */
.catalog .cat-head {
  position: sticky; top: 0; z-index: 1;
  background: var(--panel); padding: 4px 0 3px;
}
.cat-item {
  font: inherit; text-align: left; cursor: pointer;
  display: flex; align-items: center; gap: 7px; min-width: 0;
  padding: 6px 8px; border-radius: 8px;
  color: var(--muted); background: var(--panel-2);
  border: 1px solid var(--line);
}
.cat-item:hover { color: var(--text); border-color: var(--accent); }
.cat-item.on { color: var(--text); border-color: var(--accent); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--accent) 35%, transparent); }
.cat-item .dot {
  width: 9px; height: 9px; border-radius: 3px; flex: none;
  border: 1px solid color-mix(in oklab, var(--line) 70%, transparent);
}
.cat-item .nm {
  font-family: var(--mono); font-size: 0.7rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cat-item.is-pass .dot { background: var(--good); border-color: var(--good); }
.cat-item.is-flag .dot { background: var(--bad); border-color: var(--bad); }
.cat-item.is-flag .nm { color: var(--bad); }

/* ---------- chips ---------- */
.chips li.pass { color: var(--good); border-color: color-mix(in oklab, var(--good) 45%, var(--line)); }
.chips li.warn { color: var(--warn); border-color: color-mix(in oklab, var(--warn) 45%, var(--line)); }
.chips li.fail { color: var(--bad); border-color: color-mix(in oklab, var(--bad) 45%, var(--line)); }

/* ---------- responsive ---------- */
/* Every media query lives here, at the end of the file, in descending breakpoint order.
 * They are all single-class overrides of rules above, so they only win by coming after
 * them. Scattered next to the rules they modified, three of these silently lost — the
 * readout stayed two-up on a phone, the catalog panel collapsed to its heading, and the
 * phone column count never applied. Add new ones here, not beside the rule they change.
 */

@media (max-width: 1020px) {
  /* Canvas and catalog stack. Only the card follows the preview width: the catalog below
     keeps the full width, or on a phone — where the preview is a narrow portrait strip —
     the list would inherit that too. The narrower column minimum fits two columns there
     rather than one half-empty one. */
  .stage-wrap { grid-template-columns: 1fr; justify-content: stretch; }
  .stage-main { width: min(100%, var(--card-w)); margin-inline: auto; }
  .catalog-col { position: static; }
  .catalog-panel { position: static; max-height: 320px; }
  .catalog { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}

@media (max-width: 820px) {
  /* base.css collapses the readout at this width, but this file's column override loads
     after it and wins, so it has to be restated. */
  .readout { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  /* The full label and hint wrap into a block taller than the narrow portrait preview a
     phone gets, so drop to the icon and one word. */
  .cta { width: max-content; max-width: 86%; padding: 12px 14px; }
  .cta-word { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hud, .cta { transition: none; }
}
