/* ===========================================================================
   Marsoom human-review module — client styles.
   RTL-first, logical properties throughout, no third-party CSS, no web fonts.
   Targets WCAG 2.2 AA: contrast, visible focus, keyboard operation, reflow at
   320 CSS px, reduced motion, and error identification.
   =========================================================================== */

:root {
  --bg: #eef1f5;
  --surface: #ffffff;
  --surface-2: #f7f9fc;
  --ink: #10161d;          /* 16.1:1 on --surface */
  --ink-2: #47535f;        /* 7.4:1  on --surface */
  --line: #d6dde5;
  --line-strong: #b3bfcc;

  --accent: #14459c;       /* 8.1:1 on white */
  --accent-ink: #ffffff;
  --accent-soft: #e8eefb;

  --ok: #0b6b45;           /* 5.3:1 */
  --ok-soft: #e4f4ec;
  --warn: #7a4b00;         /* 6.4:1 */
  --warn-soft: #fdf1dc;
  --bad: #97231f;          /* 6.5:1 */
  --bad-soft: #fbe9e8;
  --owner: #4a2596;        /* 8.6:1 */
  --owner-soft: #efe9fc;

  --radius: 12px;
  --radius-sm: 9px;
  --tap: 44px;             /* minimum touch target */
  --shadow: 0 1px 2px rgba(16, 22, 29, .06), 0 4px 16px rgba(16, 22, 29, .05);

  --topbar-h: auto;
  --font: "Segoe UI", "Noto Naskh Arabic", "Geeza Pro", Tahoma, Arial, sans-serif;
}

* { box-sizing: border-box; }

html {
  /* Never disable user scaling. Keep Safari from silently resizing text. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;             /* Arabic body never below 16px */
  line-height: 1.65;
  /* Reflow: nothing may force a horizontal scrollbar on the page itself. */
  overflow-x: hidden;
  overflow-wrap: break-word;
}

/* Latin ids, hashes and counters inside Arabic sentences. */
bdi, .ltr { unicode-bidi: isolate; direction: ltr; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }

/* Visible focus everywhere, keyboard and mouse alike where it matters. */
:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden; white-space: nowrap;
}

.skip-link {
  position: absolute;
  inset-block-start: -100px;
  inset-inline-start: 8px;
  z-index: 100;
  background: var(--accent);
  color: var(--accent-ink);
  padding: 10px 16px;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.skip-link:focus { inset-block-start: 0; }

[hidden] { display: none !important; }

/* ============================== app frame ================================= */

.app {
  min-height: 100vh;
  min-height: 100dvh;          /* dynamic viewport: browser chrome may collapse */
  display: flex;
  flex-direction: column;
}

.topbar {
  position: sticky;
  inset-block-start: 0;
  z-index: 30;
  background: var(--surface);
  border-block-end: 1px solid var(--line);
  padding-block-start: env(safe-area-inset-top);
}

.hold-strip {
  background: var(--bad-soft);
  color: var(--bad);
  border-block-end: 1px solid #f0cdcb;
  font-size: 12px;
  font-weight: 700;
  text-align: center;
  padding: 6px 12px;
  line-height: 1.45;
}

.topbar-row {
  display: flex;
  align-items: center;
  gap: 8px 10px;
  flex-wrap: wrap;
  padding: 8px 12px;
  padding-inline: max(12px, env(safe-area-inset-inline-start)) max(12px, env(safe-area-inset-inline-end));
}
.brand { font-weight: 700; font-size: 15px; white-space: nowrap; }
.spacer { flex: 1 1 auto; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--ink-2);
  white-space: nowrap;
}
.chip.ok   { background: var(--ok-soft);   color: var(--ok);   border-color: #bfe3d1; }
.chip.warn { background: var(--warn-soft); color: var(--warn); border-color: #efd9a9; }
.chip.bad  { background: var(--bad-soft);  color: var(--bad);  border-color: #f0cdcb; }
.chip.owner{ background: var(--owner-soft);color: var(--owner);border-color: #d3c4f4; }
.chip.practice { background: var(--warn-soft); color: var(--warn); border-color: #efd9a9; font-weight: 700; }

.progress-chip { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }

.btn {
  min-height: var(--tap);
  min-width: var(--tap);
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  font-size: 15px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.btn:hover { filter: brightness(1.08); }
.btn:disabled { opacity: .45; cursor: not-allowed; filter: none; }
.btn.secondary { background: var(--surface); color: var(--ink); border-color: var(--line-strong); }
.btn.secondary:hover { background: var(--accent-soft); border-color: var(--accent); }
.btn.ghost { background: transparent; color: var(--accent); border-color: transparent; }
.btn.ok { background: var(--ok); }
/* .small buys a smaller LABEL, never a smaller target. A UI/UX pass measured
   these header buttons at 36.3px on desktop and 38px on mobile, under the 44px
   minimum the rest of the app holds to — a fingertip does not care that the
   text is 13.5px. Padding shrinks; the hit area does not. */
.btn.small { min-block-size: var(--tap); padding: 6px 12px; font-size: 13.5px; }

/* Banners for the required states. */
.banner {
  padding: 10px 14px;
  font-size: 14px;
  border-block-end: 1px solid;
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
}
.banner.info    { background: var(--accent-soft); color: var(--accent); border-color: #c3d2f2; }
.banner.warn    { background: var(--warn-soft);   color: var(--warn);   border-color: #efd9a9; }
.banner.error   { background: var(--bad-soft);    color: var(--bad);    border-color: #f0cdcb; }
.banner.practice{ background: var(--warn-soft);   color: var(--warn);   border-color: #efd9a9; font-weight: 600; }

/* ============================== main layout =============================== */

main {
  flex: 1 1 auto;
  width: 100%;
  max-width: 1400px;
  margin-inline: auto;
  padding: 12px;
  padding-inline: max(12px, env(safe-area-inset-inline-start)) max(12px, env(safe-area-inset-inline-end));
  /* room for the sticky action bar so it never covers an input */
  padding-block-end: calc(96px + env(safe-area-inset-bottom));
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  margin-block-end: 12px;
  box-shadow: var(--shadow);
}
.card h2 { margin: 0 0 6px; font-size: 17px; }
.card .sub { color: var(--ink-2); font-size: 13.5px; }

/* Two panes side by side once there is genuinely room for both.
   The threshold is 860 CSS px, not 1000: a nominal 1024x768 iPad landscape
   reports far fewer CSS pixels once browser UI scaling or 110% zoom is applied
   (measured at ~931x698), so at 1000 the two-pane rule silently failed to fire.
   860 keeps the whole 850-999 reflow range in two panes while leaving 768 and
   820 iPad portrait single-column, and each pane keeps a usable minimum width. */
@media (min-width: 860px) {
  .work {
    display: grid;
    grid-template-columns: minmax(320px, 1.05fr) minmax(330px, 0.95fr);
    gap: 14px;
    align-items: start;
  }
  .evidence-col {
    position: sticky;
    inset-block-start: 84px;
  }
  .questions-col { min-inline-size: 0; }
}

/* ============================== evidence ================================== */

.evidence-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-block-end: 8px;
}
.evidence-head h2 { margin: 0; font-size: 15px; }
.page-label { color: var(--ink-2); font-size: 13px; font-variant-numeric: tabular-nums; }

/* Compact by default: on phone and iPad portrait the evidence takes a bounded
   slice of the *small* viewport so the questions never begin far below the fold.
   svh is used deliberately: it is the height that survives browser-chrome
   expansion on iOS, so the region cannot grow and push content away. */
.page-frame {
  position: relative;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: auto;
  overscroll-behavior: contain;
  height: 34svh;
  min-height: 190px;
  touch-action: pan-x pan-y pinch-zoom;   /* pinch zoom stays available */
}
@media (min-width: 860px) {
  /* Sized so the whole evidence card fits between the sticky top bar and the
     sticky action bar. Measured at 1024x768: top bar 92, action bar 68, page
     padding 24, card chrome 196 -> the frame must not exceed ~388px there.
     A flat 60svh produced a card that ran underneath the action bar. */
  .page-frame { height: clamp(200px, calc(100svh - 380px), 560px); }
}
.page-frame.expanded {
  height: min(78svh, 900px);
}

.page-surface { position: relative; width: 100%; }
.page-image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: fill;
  user-select: none;
  pointer-events: none;
}

.blk {
  position: absolute;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 1px 4px;
  font-size: 11px;
  line-height: 1.2;
  background: #fff;
  color: #2a3541;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
}
.blk.faded { opacity: .34; }
.blk.hiddenblk { display: none; }
.blk.in {
  background: rgba(232, 238, 251, .88);
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  font-weight: 600;
  color: var(--ink);
}
.blk.focusline { background: rgba(255, 245, 207, .9); border-color: var(--warn); box-shadow: inset 0 0 0 1px var(--warn); }
.blk.furniture { background: rgba(238, 241, 245, .88); color: #36414c; font-style: italic; }
.blk.conflict { border-color: var(--warn); background: rgba(255, 245, 207, .9); }
.blk.picked { outline: 3px solid var(--ok); outline-offset: 1px; }
button.blk { cursor: pointer; text-align: start; font-family: inherit; }
button.blk:hover { border-color: var(--accent); }
/* Selection state must never be colour-only. */
.blk.in::after { content: "✓"; margin-inline-start: 6px; color: var(--accent); font-weight: 800; }
.blk.picked::after { content: "◉"; margin-inline-start: 6px; color: var(--ok); }

.draw-rect {
  position: absolute;
  border: 2px solid var(--ok);
  background: rgba(11, 107, 69, .12);
  pointer-events: none;
}

.evidence-tools { display: flex; gap: 8px; flex-wrap: wrap; margin-block-start: 8px; }
.hint { font-size: 12.5px; color: var(--ink-2); margin-block-start: 8px; }

/* ============================== questions ================================= */

fieldset {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px;
  margin: 0 0 12px;
  background: var(--surface);
  box-shadow: var(--shadow);
}
legend {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--accent);
  padding-inline: 6px;
  text-transform: none;
}
.qtext { font-size: 16px; font-weight: 600; margin: 2px 0 10px; }
.qhelp { font-size: 13px; color: var(--ink-2); margin: -4px 0 10px; }

.opts { display: flex; flex-direction: column; gap: 8px; }
.opts.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@media (max-width: 430px) { .opts.grid { grid-template-columns: 1fr; } }

.opt {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: var(--tap);
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: 15px;
}
.opt:hover { border-color: var(--accent); background: var(--accent-soft); }
.opt input { inline-size: 20px; block-size: 20px; margin-block-start: 3px; accent-color: var(--accent); flex: none; }
.opt.selected { border-color: var(--accent); background: var(--accent-soft); font-weight: 600; }
/* State is never conveyed by colour alone. */
.opt.selected .opt-label::after { content: " ✓"; color: var(--ok); font-weight: 800; }
.opt small { display: block; color: var(--ink-2); font-weight: 400; font-size: 13px; margin-block-start: 2px; }

/* What the page ACTUALLY SAYS — the printed title, the flagged value, the
   proposed subtitle. It used to share --surface-2 and --line with .opt, so the
   thing being judged looked exactly like one of the answers, and a reviewer had
   to read the words to tell them apart. It now reads as a quotation from the
   page: tinted, with a heavy leading rule down its start edge. */
.proposed {
  background: var(--accent-soft);
  border: 1px solid #c3d3f0;
  border-inline-start: 5px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin-block-end: 12px;
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink);
}

.badge {
  display: inline-block;
  background: var(--warn-soft);
  color: var(--warn);
  border: 1px solid #efd9a9;
  border-radius: 999px;
  padding: 2px 10px;
  font-size: 12px;
  font-weight: 700;
  margin-inline-start: 6px;
}

.crop {
  background: #fff;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 12px;
  margin-block-end: 10px;
  font-size: 18px;
  line-height: 1.9;
}
.crop mark {
  background: #ffe9a8;
  color: var(--ink);
  padding: 0 2px;
  border-block-end: 3px solid var(--bad);
}

.note {
  font-size: 13px;
  color: var(--ink-2);
  background: var(--surface-2);
  border-inline-start: 3px solid var(--line-strong);
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  margin-block: 8px;
}
.note.warn { background: var(--warn-soft); color: var(--warn); border-inline-start-color: var(--warn); }
.note.error { background: var(--bad-soft); color: var(--bad); border-inline-start-color: var(--bad); }

.correction {
  border: 1px solid var(--ok);
  background: var(--ok-soft);
  border-radius: var(--radius-sm);
  padding: 12px;
  margin-block-start: 10px;
}
.correction h3 { margin: 0 0 6px; font-size: 14px; color: var(--ok); }

/* Every text-like field gets the same treatment. Listing only [type=text] left
   the password input unstyled and visibly narrower - found in live browser use. */
input[type="text"],
input[type="password"],
input[type="email"],
input[type="search"],
input:not([type]),
textarea,
select {
  inline-size: 100%;
  min-block-size: var(--tap);
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--ink);
  font-size: 16px;            /* 16px also stops iOS Safari zooming on focus */
}
input[type="text"]:focus-visible,
input[type="password"]:focus-visible,
textarea:focus-visible,
select:focus-visible { border-color: var(--accent); }
/* :user-invalid, not :invalid — an untouched required field must NOT look like
   an error before the person has done anything (WCAG 3.3.1 is about identifying
   real errors, not pre-announcing them). */
input:user-invalid { border-color: var(--bad); }
input[aria-invalid="true"] { border-color: var(--bad); }

/* Owner-only confidence panel. */
.owner-panel {
  border: 1px solid #d3c4f4;
  background: var(--owner-soft);
  border-radius: var(--radius);
  padding: 12px;
  margin-block-end: 12px;
}
.owner-panel h3 { margin: 0 0 8px; font-size: 13.5px; color: var(--owner); }
.exp-badge {
  display: inline-block;
  background: var(--warn-soft); color: var(--warn);
  border: 1px solid #efd9a9; border-radius: 999px;
  padding: 2px 10px; font-size: 12px; font-weight: 700; margin-block-end: 8px;
}
.conf-row {
  display: flex; justify-content: space-between; gap: 10px;
  font-size: 13.5px; padding: 4px 0; border-block-end: 1px dashed #d3c4f4;
}
.conf-row:last-of-type { border-block-end: 0; }
.conf-row b { font-variant-numeric: tabular-nums; }
.owner-meta { font-size: 12px; color: var(--owner); margin-block-start: 6px; line-height: 1.6; }

/* ============================== action bar ================================ */

.actionbar {
  position: sticky;
  inset-block-end: 0;
  z-index: 25;
  background: var(--surface);
  border-block-start: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  padding-block-end: calc(10px + env(safe-area-inset-bottom));
  padding-inline: max(12px, env(safe-area-inset-inline-start)) max(12px, env(safe-area-inset-inline-end));
}
.actionbar .save-line { flex: 1 1 auto; font-size: 12.5px; color: var(--ink-2); min-width: 0; }

/* ============================== lists / results =========================== */

.row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 0; border-block-end: 1px dashed var(--line);
}
.row:last-child { border-block-end: 0; }
.row .grow { flex: 1 1 200px; min-width: 0; }
.row .row-title { font-weight: 600; }
.row .row-sub { font-size: 13px; color: var(--ink-2); }

table { border-collapse: collapse; inline-size: 100%; font-size: 13.5px; }
.table-scroll { overflow-x: auto; }
th, td { border: 1px solid var(--line); padding: 8px 10px; text-align: start; vertical-align: top; }
th { background: var(--surface-2); font-size: 12.5px; }

.metric-row {
  display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
  padding: 10px 0; border-block-end: 1px dashed var(--line);
}
.metric-row .value { font-weight: 700; font-variant-numeric: tabular-nums; }
.metric-row .denom { font-size: 12.5px; color: var(--ink-2); font-weight: 400; }

.spinner {
  inline-size: 18px; block-size: 18px;
  border: 2px solid var(--line-strong);
  border-block-start-color: var(--accent);
  border-radius: 50%;
  animation: spin .8s linear infinite;
  display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

.skeleton {
  background: linear-gradient(90deg, #e9edf2 25%, #f3f6f9 37%, #e9edf2 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
  border-radius: var(--radius-sm);
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

/* ============================== dialogs =================================== */

dialog {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0;
  max-inline-size: min(560px, 92vw);
  inline-size: 100%;
  color: var(--ink);
  background: var(--surface);
}
dialog::backdrop { background: rgba(16, 22, 29, .45); }
.dialog-body { padding: 16px; }
.dialog-actions { display: flex; gap: 10px; justify-content: flex-start; padding: 0 16px 16px; flex-wrap: wrap; }

/* Full-screen evidence sheet for phone and tablet portrait. */
dialog.sheet {
  max-inline-size: 100vw;
  inline-size: 100vw;
  block-size: 100dvh;
  max-block-size: 100dvh;
  margin: 0;
  border: 0;
  border-radius: 0;
}
dialog.sheet .page-frame { height: calc(100dvh - 150px); }
dialog.sheet .sheet-head {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  padding-block-start: calc(10px + env(safe-area-inset-top));
  border-block-end: 1px solid var(--line);
}

/* ============================== motion ==================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================== high contrast ============================= */

@media (prefers-contrast: more) {
  :root { --line: #7d8894; --line-strong: #566370; --ink-2: #2b3540; }
  .opt.selected { outline: 2px solid var(--accent); }
}

/* ============================== narrow reflow ============================= */

@media (max-width: 360px) {
  .topbar-row { gap: 6px; padding: 6px 10px; }
  .brand { font-size: 14px; }
  .chip { font-size: 12px; padding: 3px 8px; }
  main { padding: 10px; padding-block-end: calc(92px + env(safe-area-inset-bottom)); }
}

/* ===========================================================================
   Phone / tablet-portrait density.
   Measured during viewport testing: with the default chrome the first question
   began at y=806 in an 844px viewport, i.e. effectively below the fold. These
   rules buy that space back so evidence AND a question are genuinely in view.
   =========================================================================== */

@media (max-width: 859px) {
  .hold-strip { font-size: 11.5px; padding: 4px 10px; line-height: 1.35; }
  .hold-strip .hold-long { display: none; }
  .topbar-row { padding: 6px 10px; gap: 6px 8px; }
  .brand { font-size: 14px; }
  .chip { font-size: 11.5px; padding: 3px 8px; }
  /* Density comes out of the padding and the type, NOT the touch target:
      these are the narrow viewports where a finger is the only pointer. */
  .btn.small { min-block-size: var(--tap); padding: 5px 10px; font-size: 13px; }

  /* A bounded evidence slice: enough to read the target, never enough to push
     the questions away. Full page stays one tap away in the sheet. */
  .page-frame { height: 30svh; min-height: 168px; }
  .page-frame.expanded { height: 52svh; }

  .evidence-col .card { padding: 10px; margin-block-end: 10px; }
  .evidence-head { margin-block-end: 6px; }
  .evidence-head h2 { font-size: 14px; }
  .evidence-tools {
    gap: 6px;
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    padding-block-end: 2px;
    margin-block-start: 6px;
  }
  .evidence-tools .btn { flex: 0 0 auto; }
  /* The standing hint is redundant on a small screen once the target is
     highlighted; correction-mode guidance still shows, because that is the
     moment the instruction actually matters. */
  .hint:not(.correcting) { display: none; }

  #questions > .card:first-child { padding: 10px; }
  #questions > .card:first-child h2 { font-size: 15px; margin-block-end: 2px; }
  fieldset { padding: 10px; margin-block-end: 10px; }
  .qtext { font-size: 15.5px; margin-block-end: 8px; }
}

/* Very short viewports (phone landscape).
   Measured at 667x375: with the standard compact layout the first question
   started at y=441 in a 375px viewport. In a viewport this short there is no
   honest way to show a USABLE evidence region and a question at once, so the
   inline evidence becomes a small preview and the full page moves to the
   one-tap sheet. The questions then start in view. */
@media (max-height: 480px) {
  .page-frame { height: 30svh; min-height: 104px; }
  .page-frame.expanded { height: 62svh; }
  .hold-strip { padding: 3px 8px; font-size: 11px; }
  .evidence-col .card { padding: 8px; margin-block-end: 8px; }
  .evidence-head { margin-block-end: 4px; }
  .evidence-head h2 { font-size: 13px; }
  /* Shortest viewport, and still the 44px minimum. */
  .btn.small { min-block-size: var(--tap); padding: 4px 10px; }
  .evidence-tools { margin-block-start: 4px; }
  main { padding-block: 8px; padding-block-end: calc(84px + env(safe-area-inset-bottom)); }
  /* The group summary collapses to one line so the question itself comes into view. */
  #questions > .card:first-child { padding: 6px 10px; margin-block-end: 8px; }
  #questions > .card:first-child h2 { display: inline; font-size: 13.5px; }
  #questions > .card:first-child .sub { display: inline; margin-inline-start: 8px; font-size: 12.5px; }
  fieldset { padding: 8px 10px; margin-block-end: 8px; }
  .qtext { font-size: 15px; margin: 0 0 6px; }
  legend { font-size: 12px; }
}

/* Viewport testing at 360x800 showed the page-navigation buttons pushed past the
   right edge of the nowrap toolbar. A horizontally scrolling toolbar hides
   controls behind a gesture, so below 430px the tools wrap onto a second row
   instead: every control stays visible and reachable without scrolling. */
@media (max-width: 430px) {
  .evidence-tools { flex-wrap: wrap; overflow-x: visible; }
}

/* The sticky action bar must never be the reason a control cannot be reached.
   `main` already reserves its height at the end of the document; this makes the
   reservation explicit and generous enough for the tallest bar state. */
main { scroll-padding-block-end: 120px; }

/* ===========================================================================
   Classes replacing the static inline style attributes.

   The strict CSP (`style-src 'self'`, no `unsafe-inline`) blocks BOTH markup
   `style="..."` and `setAttribute('style', ...)`. It does NOT block CSSOM
   property writes (`el.style.left = ...`), which is how the evidence pane
   positions page blocks - verified in the live browser, see VIEWPORT_REPORT.
   Every static style attribute is therefore a class, and none may come back.
   =========================================================================== */

.auth-card {
  max-inline-size: 520px;
  margin-inline: auto;
}

.form-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.form-actions-top { margin-block-start: 14px; }

.skeleton-block { block-size: 120px; margin-block: 10px; }
.skeleton-line  { block-size: 60px; }

.sheet-hint { padding-inline: 12px; }

.dialog-body h2 { margin-block-start: 0; }

.owner-tools-row { display: flex; gap: 10px; flex-wrap: wrap; }
.opts-spaced { margin-block-start: 10px; }

/* ===========================================================================
   Owner confidence: compact summary first, detail behind a disclosure.

   Nasser still sees all four values, their bands, the UNCALIBRATED badge and
   the weight version BEFORE answering. The long fired-check list moved into a
   <details>, because it was visually dominating the actual review task.
   =========================================================================== */

.owner-panel {
  border: 1px solid #d3c4f4;
  background: linear-gradient(180deg, var(--owner-soft), #f6f3fe);
  border-radius: var(--radius);
  padding: 10px 12px;
  margin-block-end: 12px;
}
.owner-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-block-end: 8px;
}
.owner-head h3 {
  margin: 0;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--owner);
  letter-spacing: .2px;
}
.exp-badge {
  display: inline-block;
  background: var(--warn-soft); color: var(--warn);
  border: 1px solid #efd9a9; border-radius: 999px;
  padding: 1px 9px; font-size: 11px; font-weight: 700;
}
.weights-tag {
  font-size: 11px; color: var(--owner); opacity: .85;
  font-family: var(--mono, ui-monospace, Consolas, monospace);
}

/* Four values as a compact row of tiles instead of four stacked lines. */
.conf-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
}
@media (max-width: 520px) { .conf-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.conf-tile {
  background: #fff;
  border: 1px solid #ddd0f7;
  border-radius: var(--radius-sm);
  padding: 6px 8px;
  min-inline-size: 0;
}
.conf-tile .k { display: block; font-size: 11px; color: var(--owner); }
.conf-tile .v {
  display: block; font-size: 15px; font-weight: 700;
  font-variant-numeric: tabular-nums; line-height: 1.25;
}
.conf-tile .b { display: block; font-size: 11px; color: var(--ink-2); }
.conf-tile.high   { border-color: #b6dcc8; }
.conf-tile.medium { border-color: #efd9a9; }
.conf-tile.low    { border-color: #f0cdcb; }
/* Band is never colour-only. */
.conf-tile.high   .b::before { content: "▲ "; color: var(--ok); }
.conf-tile.medium .b::before { content: "■ "; color: var(--warn); }
.conf-tile.low    .b::before { content: "▼ "; color: var(--bad); }

.owner-details { margin-block-start: 8px; }
.owner-details > summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--owner);
  padding: 6px 4px;
  min-block-size: 32px;
  display: flex;
  align-items: center;
  border-radius: var(--radius-sm);
}
.owner-details > summary:hover { background: #ece4fb; }
.owner-details > summary:focus-visible { outline: 3px solid var(--owner); outline-offset: 2px; }
.owner-meta {
  font-size: 11px; color: var(--owner); opacity: .9;
  line-height: 1.45; margin-block-start: 3px;
  overflow-wrap: anywhere;
}
.owner-details[open] > summary { margin-block-end: 4px; }
.owner-meta code {
  font-family: var(--mono, ui-monospace, Consolas, monospace);
  background: #fff; border: 1px solid #e3d8f9; border-radius: 4px; padding: 0 4px;
}

/* ===========================================================================
   Hierarchy polish: make the current review action the loudest thing on screen.
   =========================================================================== */

/* The question the reviewer is on should read as the primary surface; the
   supporting cards should recede. */
fieldset {
  border-color: #cfd8e2;
  box-shadow: 0 1px 2px rgba(16,22,29,.05);
}
fieldset:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
legend {
  background: var(--accent-soft);
  border: 1px solid #c9d6f7;
  border-radius: 999px;
  padding: 2px 10px;
  margin-inline-start: 2px;
}

/* The group summary is context, not content: quieter than a question. */
#questions > .card:first-child {
  background: var(--surface-2);
  box-shadow: none;
  border-style: dashed;
}
#questions > .card:first-child h2 { font-size: 15px; }

/* Evidence card: the frame is the subject, the chrome recedes. */
.evidence-col .card { padding: 12px; }
.evidence-head h2 { font-size: 14px; color: var(--ink-2); font-weight: 700; }
.page-frame { background: #fbfcfe; border-color: #cfd8e2; }

/* Top bar: group the status chips so they stop crowding the brand. */
.topbar-row { padding-block: 6px; }
.brand { letter-spacing: -.2px; }
.progress-chip { background: #fff; border-color: var(--line-strong); }

/* Primary action carries the weight; secondary actions stay quiet. */
.actionbar .btn:not(.secondary) { box-shadow: 0 1px 2px rgba(20,69,156,.25); }
.actionbar { box-shadow: 0 -2px 10px rgba(16,22,29,.05); }

/* Cards should not be large and empty. */
.card { padding: 14px 16px; }
.card > *:last-child { margin-block-end: 0; }
.row:first-child { padding-block-start: 4px; }

/* Auth screen proportions. */
.auth-card label {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-2);
  margin-block-end: 4px;
}
.auth-card p { margin-block: 0 14px; }
.auth-card .sub { margin-block-end: 16px; }

/* ===========================================================================
   Owner confidence on stacked layouts (phone / tablet portrait).

   Measured as owner at 390x844: the summary was 273px tall and sat between the
   evidence and the questions, pushing the first question to y=941 - a full
   screen down. That is the dominance Nasser flagged, and it survives closing
   the disclosure, so the SUMMARY itself has to get denser here.

   All four values, the band, the UNCALIBRATED badge and the weight version
   remain visible before answering. Only their layout changes.
   =========================================================================== */

@media (max-width: 859px) {
  .owner-panel { padding: 8px 10px; margin-block-end: 10px; }

  /* The heading is redundant next to the badge; it moves into the disclosure. */
  .owner-head { gap: 6px; margin-block-end: 6px; }
  .owner-head h3 { font-size: 11.5px; }
  .owner-head h3 .owner-head-long { display: none; }

  /* Four across, always: a 2x2 grid was costing ~140px for four numbers. */
  .conf-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; }
  .conf-tile { padding: 4px 5px; text-align: center; }
  .conf-tile .k { font-size: 10px; line-height: 1.3; }
  .conf-tile .v { font-size: 14px; line-height: 1.2; }
  /* Band becomes a glyph beside the number instead of its own line. */
  .conf-tile .b { font-size: 0; line-height: 1; }
  .conf-tile .b::before { font-size: 11px; }

  .owner-details > summary { font-size: 11.5px; min-block-size: 30px; padding: 4px; }
}

/* Even tighter where the viewport is short as well as narrow. */
@media (max-height: 480px) {
  .owner-panel { padding: 6px 8px; margin-block-end: 8px; }
  .conf-tile .k { font-size: 9.5px; }
  .conf-tile .v { font-size: 13px; }
}

/* ===========================================================================
   Owner + stacked layout: the confidence summary costs vertical space that a
   reviewer does not pay. Measured at 390x844 as owner, the first question still
   started at y=833 with the summary already compacted, because the stack is
   top bar + evidence + summary + group card.

   Rather than shrink the summary below legibility or hide required confidence,
   the evidence preview gives up the difference FOR THE OWNER ONLY. Reviewers,
   who have no panel, keep the larger preview. The full page stays one tap away
   in the sheet for both.
   =========================================================================== */

@media (max-width: 859px) {
  body.role-owner .page-frame { height: 26svh; min-height: 150px; }
  body.role-owner .evidence-col .card { padding: 8px 10px; }
  body.role-owner #questions > .card:first-child { padding: 6px 10px; }
  body.role-owner #questions > .card:first-child h2 { display: inline; font-size: 14px; }
  body.role-owner #questions > .card:first-child .sub { display: inline; margin-inline-start: 8px; }
}

/* ===========================================================================
   Evidence viewer: modes, zoom, and tap targets that a human can actually hit.

   Measured against the real package: 100% of 13,062 lines render under 44px at
   every required viewport (median 3.5-10.8px, smallest 0.61px on a 360px
   phone). Precision tapping on newspaper text is not a usable interaction, so
   selection now has its own padded hit layer, explicit modes, zoom, and a
   synchronized list fallback.
   =========================================================================== */

.evidence-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-block-end: 8px;
}
.toolbar-sep {
  inline-size: 1px; block-size: 24px; background: var(--line); margin-inline: 2px;
}
.mode-group {
  display: inline-flex;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.modebtn, .zoombtn {
  min-block-size: var(--tap);
  min-inline-size: var(--tap);
  padding: 6px 12px;
  border: 1px solid transparent;
  background: var(--surface);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
}
.mode-group .modebtn { border-radius: 0; border-inline-start: 1px solid var(--line); }
.mode-group .modebtn:first-child { border-inline-start: 0; }
.modebtn.on {
  background: var(--accent);
  color: var(--accent-ink);
}
.modebtn.on::after { content: " ✓"; }
.zoombtn {
  border-color: var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.zoombtn.wide { font-size: 13px; padding: 6px 10px; }
.modebtn:hover, .zoombtn:hover { background: var(--accent-soft); border-color: var(--accent); }
.modebtn:focus-visible, .zoombtn:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.zoom-label {
  min-inline-size: 52px; text-align: center;
  font-size: 13px; font-variant-numeric: tabular-nums; color: var(--ink-2);
}

/* In select mode the frame stops treating a drag as a pan gesture on touch,
   so a deliberate tap lands on a block instead of scrolling the page. */
.page-frame.mode-select { touch-action: pan-x pan-y pinch-zoom; cursor: crosshair; }

/* The transparent hit layer. It carries NO source geometry: the visual .blk
   keeps the exact rectangle, and nothing here reaches an export. */
.blk-hit {
  position: absolute;
  padding: 0;
  margin: 0;
  background: transparent;
  border: 1px dashed transparent;
  border-radius: 6px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.blk-hit:hover { border-color: var(--accent); background: rgba(20, 69, 156, .10); }
.blk-hit:focus-visible { outline: 3px solid var(--accent); outline-offset: 1px; background: rgba(20, 69, 156, .12); }
.blk-hit.on { border-color: var(--ok); background: rgba(11, 107, 69, .14); }
.blk-hit.on:hover { background: rgba(11, 107, 69, .22); }

/* A selected block must be unmistakable at a glance, and never colour-only. */
.blk.in {
  background: #d7ecdf;
  border-color: var(--ok);
  box-shadow: inset 0 0 0 2px var(--ok);
  color: #06301f;
  font-weight: 700;
}
.blk.in::after { content: "✓"; margin-inline-start: 6px; color: var(--ok); font-weight: 800; }

/* Sticky selection bar: count, undo, clear, confirm - reachable by thumb. */
.selectionbar {
  position: sticky;
  inset-block-end: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-block-start: 8px;
  padding: 8px 10px;
  padding-block-end: calc(8px + env(safe-area-inset-bottom));
  background: var(--surface);
  border: 1px solid var(--ok);
  border-radius: var(--radius-sm);
  box-shadow: 0 -2px 10px rgba(16, 22, 29, .08);
}
.selectionbar .sel-count { font-weight: 700; font-size: 14px; font-variant-numeric: tabular-nums; }

/* Accessible list mirror of every selectable block. */
.block-list-wrap {
  margin-block-start: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  background: var(--surface-2);
}
.block-list-wrap > summary {
  cursor: pointer; font-size: 13px; font-weight: 600; color: var(--accent);
  min-block-size: 32px; display: flex; align-items: center;
}
.block-list-wrap > summary:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.block-list {
  list-style: none; margin: 8px 0 0; padding: 0;
  max-block-size: 40svh; overflow-y: auto;
}
.block-list-item + .block-list-item { border-block-start: 1px dashed var(--line); }
.block-list-label {
  display: flex; align-items: flex-start; gap: 10px;
  min-block-size: var(--tap); padding: 8px 4px; cursor: pointer;
}
.block-list-label:hover { background: var(--accent-soft); }
.block-list-label input {
  inline-size: 22px; block-size: 22px; margin-block-start: 2px;
  accent-color: var(--ok); flex: none;
}
.block-list-label input:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.block-list-text { font-size: 14px; line-height: 1.5; }

/* NOT_APPLICABLE notice for questions a TOP_PAGE_REFERENCE decision suppressed. */
.na-card {
  background: var(--warn-soft);
  border-color: #efd9a9;
  border-style: dashed;
  box-shadow: none;
}
.na-card h2 { color: var(--warn); font-size: 15px; }

@media (max-width: 859px) {
  .evidence-toolbar { gap: 4px; }
  .zoombtn.wide { font-size: 12px; padding: 5px 8px; }
  .modebtn { padding: 6px 10px; font-size: 13px; }
}
