/* LocalGate audit instrument — grading-desk design.
   Chroma is semantic only: verdict inks + the reference yardstick. Everything
   instrumental speaks mono; everything read speaks serif. */

@font-face { font-family: "Source Serif 4"; src: url("fonts/source-serif-4-latin-400-normal.woff2") format("woff2");
             font-weight: 400; font-display: swap; }
@font-face { font-family: "Source Serif 4"; src: url("fonts/source-serif-4-latin-600-normal.woff2") format("woff2");
             font-weight: 600; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2");
             font-weight: 400; font-display: swap; }
@font-face { font-family: "IBM Plex Mono"; src: url("fonts/ibm-plex-mono-latin-600-normal.woff2") format("woff2");
             font-weight: 600; font-display: swap; }

:root {
  --ground: #f3f5f4;          /* cool exam paper, not cream */
  --field: #ffffff;
  --ink: #1c2430;             /* blue-black */
  --dim: #5c6672;
  --line: #d4dad8;
  --line-strong: #aeb8b4;
  --ref-ground: #fbf7e6;      /* annotation-yellow: the yardstick, nothing else */
  --ref-line: #e3d9ae;
  --match: #2f7a4d;
  --nomatch: #a63d2a;
  --noanswer: #58657a;
  --unsure: #7d6418;
  --yes: #2f7a4d;
  --no: #a63d2a;
  --serif: "Source Serif 4", Charter, "Iowan Old Style", Georgia, serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
}
@media (prefers-color-scheme: dark) {
  :root {
    --ground: #171b1f; --field: #1f242a; --ink: #dde3e8; --dim: #8b95a0;
    --line: #323a41; --line-strong: #49535c;
    --ref-ground: #2b2618; --ref-line: #4a3f1e;
    --match: #5cb885; --nomatch: #d9765f; --noanswer: #93a2b8; --unsure: #cfa93e;
    --yes: #5cb885; --no: #d9765f;
  }
}

* { box-sizing: border-box; }
html { height: 100%; }
body { margin: 0; min-height: 100%; background: var(--ground); color: var(--ink);
       font: 16.5px/1.62 var(--serif); }

/* ── header: instrument panel ── */
header { display: flex; gap: 1.2rem; align-items: baseline; flex-wrap: wrap;
         padding: .65rem 1.2rem; background: var(--field);
         border-bottom: 2px solid var(--ink); font-family: var(--mono); }
header h1 { margin: 0; font-size: .8rem; font-weight: 600; letter-spacing: .14em;
            text-transform: uppercase; }
#whoami { color: var(--dim); font-size: .75rem; }
#progress { margin-left: auto; color: var(--dim); font-size: .75rem;
            font-variant-numeric: tabular-nums; }

/* gauge with ticks every 10% */
#bar { height: 6px; background:
         repeating-linear-gradient(to right,
           transparent 0, transparent calc(10% - 1px),
           var(--line-strong) calc(10% - 1px), var(--line-strong) 10%),
         var(--line); }
#bar-fill { height: 100%; width: 0; background: var(--ink); transition: width .25s ease; }

#banner { padding: .55rem 1.2rem; font-family: var(--mono); font-size: .78rem;
          color: var(--unsure); background: color-mix(in srgb, var(--unsure) 9%, var(--field));
          border-bottom: 1px solid var(--line); }
#banner .banner-act { margin-left: .6rem; padding: .15rem .55rem; font: inherit;
                      color: inherit; background: none; cursor: pointer;
                      border: 1px solid currentColor; border-radius: 3px; }

/* ── layout: reading column + rubric rail on wide screens ── */
#layout { max-width: 100rem; margin: 0 auto; }
main { max-width: 46rem; margin: 1.1rem auto 12rem; padding: 0 1.2rem; }
@media (min-width: 1240px) {
  #layout { display: grid; grid-template-columns: 1fr 21rem; gap: 0; }
  main { grid-column: 1; margin-left: auto; margin-right: 3vw; }
  details#rubric { grid-column: 2; position: sticky; top: 0; align-self: start;
                   max-height: calc(100vh - 8rem); border-left: 1px solid var(--line);
                   border-top: none; background: transparent; }
  details#rubric[open] summary { border-bottom: 1px solid var(--line); }
}

/* ── fields ── */
.field { background: var(--field); border: 1px solid var(--line);
         border-left: 3px solid var(--line-strong); padding: .8rem 1.1rem;
         margin: .8rem 0; }
.field b { display: block; font-family: var(--mono); font-weight: 600;
           font-size: .66rem; letter-spacing: .12em; text-transform: uppercase;
           color: var(--dim); margin-bottom: .4rem; }
.field .content { white-space: pre-wrap; overflow-wrap: anywhere; }

/* the yardstick: only the reference wears the annotation highlight */
.field.reference { background: var(--ref-ground); border-color: var(--ref-line);
                   border-left-color: var(--unsure); }

.response { max-height: 26rem; overflow-y: auto; border-left-color: var(--ink); }
.endmark { text-align: center; color: var(--dim); font-family: var(--mono);
           font-size: .68rem; letter-spacing: .18em; padding-top: .6rem; }

.warmup-note { font-family: var(--mono); font-size: .78rem; padding: .55rem .9rem;
               border: 1px dashed var(--line-strong); color: var(--dim); }
.independence { color: var(--dim); font-style: italic; }

button.signin { font: 600 .95rem var(--mono); padding: .7rem 1.5rem; cursor: pointer;
                border: 2px solid var(--ink); background: var(--ink); color: var(--ground); }
button.signin:hover { background: transparent; color: var(--ink); }

/* ── rubric ── */
details#rubric { background: var(--field); border-top: 1px solid var(--line);
                 font-family: var(--mono); font-size: .74rem; line-height: 1.55;
                 overflow-y: auto; }
details#rubric summary { cursor: pointer; padding: .55rem 1.1rem; font-weight: 600;
                         letter-spacing: .08em; text-transform: uppercase;
                         font-size: .66rem; color: var(--dim); list-style: none; }
details#rubric summary::before { content: "▸ "; }
details#rubric[open] summary::before { content: "▾ "; }
details#rubric pre { white-space: pre-wrap; font: inherit; margin: 0;
                     padding: .3rem 1.1rem 1rem; }
@media (max-width: 1239px) {
  details#rubric { position: fixed; bottom: 5.9rem; left: 0; right: 0; max-height: 38vh;
                   border-top: 2px solid var(--line-strong); }
}

/* ── controls: the bench ── */
#controls { position: fixed; bottom: 0; left: 0; right: 0; background: var(--field);
            border-top: 2px solid var(--ink); padding: .65rem 1.2rem;
            display: flex; gap: .7rem; align-items: center; flex-wrap: wrap;
            font-family: var(--mono); }
#controls .grp { display: flex; gap: .4rem; align-items: center; }
#controls .lbl { font-size: .68rem; letter-spacing: .08em; text-transform: uppercase;
                 color: var(--dim); }
#controls button { font: 600 .82rem var(--mono); padding: .48rem .8rem; cursor: pointer;
                   background: var(--field); color: var(--ink);
                   border: 2px solid var(--line-strong); }
#controls button:hover { border-color: var(--ink); }

/* verdict identity: a colored stamp edge; full ink when committed */
#controls button[data-v] { border-left-width: 5px; }
#controls button[data-v="match"], #controls button[data-v="yes"] { border-left-color: var(--match); }
#controls button[data-v="no_match"], #controls button[data-v="no"] { border-left-color: var(--nomatch); }
#controls button[data-v="no_answer"] { border-left-color: var(--noanswer); }
#controls button[data-v].sel { color: var(--field); }
#controls button[data-v="match"].sel, #controls button[data-v="yes"].sel
  { background: var(--match); border-color: var(--match); }
#controls button[data-v="no_match"].sel, #controls button[data-v="no"].sel
  { background: var(--nomatch); border-color: var(--nomatch); }
#controls button[data-v="no_answer"].sel
  { background: var(--noanswer); border-color: var(--noanswer); }

#controls button.unsure { border-style: dashed; color: var(--dim); }
#controls button.unsure.sel { background: var(--unsure); border-color: var(--unsure);
                              border-style: solid; color: var(--field); }

#controls kbd { display: inline-block; font-size: .62rem; font-weight: 400;
                padding: 0 .3em; margin-left: .45em; border: 1px solid currentColor;
                border-bottom-width: 2px; border-radius: 3px; opacity: .65; }

#controls #note { font: .8rem var(--mono); padding: .45rem .6rem; width: 13rem;
                  border: 1px solid var(--line); background: var(--ground);
                  color: var(--ink); }
#controls #note::placeholder { color: var(--dim); }
#controls .nav { margin-left: auto; display: flex; gap: .4rem; }

/* ── the signature: the verdict stamp ── */
#controls .last { width: 100%; color: var(--dim); font-size: .72rem;
                  display: flex; align-items: center; gap: .5rem; }
#controls .last .stamp { display: inline-block; font-weight: 600; font-size: .7rem;
                         letter-spacing: .06em; padding: .12rem .5rem;
                         border: 2px solid var(--stamp, var(--dim));
                         color: var(--stamp, var(--dim));
                         transform: rotate(-1.2deg);
                         /* confirm, then get out of the way: the chip fades
                            ~2s after each grade; the dim "last · Axxx" line
                            stays as the j-to-revisit reference */
                         animation: stamp .14s ease-out,
                                    stampfade .5s ease-in 2.2s forwards; }
@keyframes stampfade { to { opacity: 0; visibility: hidden; } }
#controls .last .stamp.v-match { --stamp: var(--match); }
#controls .last .stamp.v-no_match { --stamp: var(--nomatch); }
#controls .last .stamp.v-no_answer { --stamp: var(--noanswer); }
@keyframes stamp { from { transform: rotate(-1.2deg) scale(1.12); opacity: .4; }
                   to   { transform: rotate(-1.2deg) scale(1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .last .stamp { animation: none; }
  #bar-fill { transition: none; }
}

:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ── hardening + review fixes (2026-08-15 UX batch) ── */
/* The UA [hidden] rule loses to `display:flex` above — without this, the
   completion screen kept a live, invisible grading bench. */
#controls[hidden] { display: none; }

#banner { color: var(--ink); border-left: 3px solid var(--unsure); }
#banner.err { border-left-color: var(--no); }

.item-id { font-family: var(--mono); font-size: .72rem; letter-spacing: .04em;
           color: color-mix(in srgb, var(--ink) 55%, var(--field)); margin: 0 0 .35rem; }

/* long responses: keep the label pinned while scrolling — negative margin +
   padding so its background also masks the container's padding band (text
   used to smear behind the label at every scroll position) */
.field.response > b { position: sticky; top: 0; display: block;
                      background: var(--field); z-index: 1;
                      margin: -.8rem -1.1rem .4rem; padding: .8rem 1.1rem .4rem; }

/* key hints are noise on touch screens (either signal suffices) —
   must match #controls kbd's specificity, which otherwise wins */
@media (hover: none), (pointer: coarse) {
  kbd, #controls kbd { display: none; }
}

/* KaTeX inherits our reading size; display math gets breathing room */
.content .katex { font-size: 1.06em; }
.content .katex-display { margin: .5em 0; overflow-x: auto; }

/* borderline wears the same slate as no_answer (both are "the amber path") */
#controls button[data-v="borderline"] { border-left-color: var(--noanswer); }
#controls button[data-v="borderline"].sel
  { background: var(--noanswer); border-color: var(--noanswer); }

/* mobile: the rubric must never hide beneath the bench — pin it to the
   bench's real measured height (set from JS each render) */
@media (max-width: 1239px) {
  details#rubric { bottom: var(--bench-h, 5.9rem); }
  #controls .nav button, #controls button.unsure { padding: .6rem .9rem; }
  #banner .banner-act { padding: .55rem .8rem; }
}

/* rubric rail: one size up for a 2-3h read, and an honest scroll cue */
details#rubric pre { font-size: .78rem; }
details#rubric { scrollbar-gutter: stable; }
details#rubric[open]::after { content: ""; position: sticky; display: block;
  bottom: 0; height: 1.6rem; margin-top: -1.6rem; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--field)); }

/* note grows into free bench space instead of truncating at 13rem */
#controls #note { flex: 1 1 13rem; min-width: 9rem; max-width: 24rem; }

/* ── mobile compatibility batch (2026-08-15) ── */
/* Fixed-layer stack: bench over rubric over banner — the sticky response
   label used to paint on top of all three (it has z-index:1; they had none). */
#controls { z-index: 30; }
details#rubric { z-index: 20; }
#banner { position: sticky; top: 0; z-index: 10; max-height: 40vh; overflow-y: auto;
          display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
#banner[hidden] { display: none; }
#banner .banner-act { order: -1; margin-left: 0; }  /* recovery actions first, above the fold */

/* Content must always clear the bench's real height. PADDING, not margin:
   a bottom margin collapses through body (html/body are height-pinned) and
   never creates the scroll room — the item's tail then hides under the fixed
   bench, unreachable. Found on a real phone, item A022. */
main { margin-bottom: 0; padding-bottom: calc(var(--bench-h, 8rem) + 4rem); }
#controls button { white-space: nowrap; }
#controls .grp { flex-wrap: wrap; }

/* screens without a bench (landing, locked, done) also need no rubric strip */
body:has(#controls[hidden]) details#rubric { display: none; }

@media (max-width: 1239px) {
  #controls button { min-height: 44px; }        /* the 250-500x buttons were 36px */
  #controls #note { min-height: 44px; }
  #banner .banner-act { min-height: 44px; }
  details#rubric { max-height: min(38vh, calc(100dvh - var(--bench-h, 5.9rem) - 9rem)); }
}
/* small phones / landscape: compact the bench to give the item room to breathe */
@media (max-width: 430px), (max-height: 420px) {
  #controls { padding: .4rem .6rem; gap: .35rem; }
  #controls .lbl { flex-basis: 100%; margin: 0; }
  #controls #note { order: 9; flex: 1 1 100%; }
  #controls .last { display: none; }
}

/* onward links (unlock, completion, locked gate) — buttons, not bare anchors */
a.open-out { display: inline-block; margin-top: .8rem; padding: .7rem 1.3rem;
             font: 600 .9rem var(--mono); text-decoration: none;
             color: var(--ground); background: var(--ink); border: 2px solid var(--ink); }
a.open-out:hover { background: transparent; color: var(--ink); }

/* the signed-out "your work is safe" reassurance */
.resume-note { font-family: var(--mono); font-size: .8rem; padding: .6rem .9rem;
               border: 1px solid var(--match); border-left-width: 4px;
               color: var(--ink); background: color-mix(in srgb, var(--match) 7%, var(--field)); }
