/* =========================================================================
   Fixlark — the whole stylesheet.
   =========================================================================

   DIRECTION: a workshop instrument, not a marketing site.

   People arrive here with a problem and a file, usually annoyed, often on a
   phone. The design's whole job is to be believable in about two seconds:
   this thing is a tool, it will not upsell me, and it is telling me the truth
   about where my file goes. Everything below serves that.

   THE ONE IDEA WORTH KNOWING: colour carries meaning here, it does not
   decorate. Green means "this runs in your browser and the file never leaves
   your machine". Indigo means "this is uploaded to our server and deleted on a
   timer". Orange means "this is the thing you are about to do". Those three
   are never used for anything else, anywhere, which is what makes the
   run-location stamp on every tool readable at a glance instead of being one
   more badge.

   NO WEBFONTS, and that is a decision rather than a shortcut. A site whose
   pitch is "your file does not leave this machine" should not open by fetching
   two typefaces from Google. The type personality comes instead from the
   contrast between a heavy system grotesque for display and monospace for
   every single measurable thing — sizes, counts, page numbers, units, labels.
   If it can be counted, it is set in mono.
   ========================================================================= */

:root {
  color-scheme: light dark;

  /* Ground and ink. A cool grey-green paper, not cream: this is a workshop,
     not a stationery shop. */
  --paper: #f1f4f3;
  --surface: #ffffff;
  --surface-sunk: #e9eeed;
  --ink: #12212a;
  --ink-2: #55676f;
  --ink-3: #84969c;
  --rule: #d5dcdc;
  --rule-strong: #b4c0c2;

  /* The three meaning colours. Do not reuse them for anything else. */
  --signal: #d84a1e;        /* the action you are about to take */
  --signal-ink: #ffffff;
  --signal-soft: #fbe8e1;
  --local: #0f6f56;         /* runs in your browser */
  --local-soft: #dcefe8;
  --server: #3d5286;        /* runs on our server */
  --server-soft: #e2e8f5;
  --warn: #8a5300;
  --warn-soft: #fbf0dd;

  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --gutter: 20px;
  --radius: 6px;
  --shadow: 0 1px 2px rgba(18, 33, 42, .06), 0 8px 24px -16px rgba(18, 33, 42, .28);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0d1317;
    --surface: #151d22;
    --surface-sunk: #101820;
    --ink: #e9eff0;
    --ink-2: #9db0b6;
    --ink-3: #6f8188;
    --rule: #24313a;
    --rule-strong: #35454e;
    --signal: #ff7043;
    --signal-ink: #14181a;
    --signal-soft: #2b1a13;
    --local: #46c095;
    --local-soft: #10281f;
    --server: #90a6dd;
    --server-soft: #161f31;
    --warn: #e0a848;
    --warn-soft: #2a2210;
    --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 8px 24px -16px rgba(0, 0, 0, .8);
  }
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}

/* Focus is the signal colour and it is always visible. A tool people use in a
   hurry with a keyboard must never hide where they are. */
:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
  border-radius: 2px;
}

a { color: inherit; text-decoration-color: var(--rule-strong); text-underline-offset: 2px; }
a:hover { text-decoration-color: var(--signal); }

h1, h2, h3 { line-height: 1.15; letter-spacing: -.022em; margin: 0; font-weight: 750; }
h1 { font-size: clamp(28px, 5.4vw, 44px); letter-spacing: -.032em; font-weight: 800; }
h2 { font-size: clamp(20px, 3vw, 26px); }
h3 { font-size: 17px; letter-spacing: -.01em; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

/* Everything measurable is monospace. This is the type signature of the site. */
.mono, .eyebrow, .metric, .unit, kbd, code, .stamp b, .num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.eyebrow {
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
}

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 var(--gutter); }
.narrow { max-width: 680px; }

/* ---- header ------------------------------------------------------------ */

.site-head {
  border-bottom: 1px solid var(--rule);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: saturate(1.4) blur(8px);
  position: sticky;
  top: 0;
  z-index: 20;
}
.site-head .wrap {
  display: flex;
  align-items: center;
  gap: 18px;
  height: 60px;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-weight: 800;
  letter-spacing: -.03em;
  font-size: 19px;
  text-decoration: none;
  flex: none;
}
.brand svg { display: block; }
.brand .mark { color: var(--signal); }

/* The nav must never wrap. Four group names, two of them long, in a 375px
   header is the classic way a header collapses into three lines of overlapping
   text — which is exactly what happened here before this rule existed. Short
   labels below 720px, and it scrolls sideways rather than wrapping. */
.nav {
  display: flex; gap: 2px; margin-left: auto; align-items: center;
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  min-width: 0;
}
.nav::-webkit-scrollbar { display: none; }
.nav a { white-space: nowrap; }
.nav .narrow { display: none; }
.nav a {
  font-size: 13.5px;
  padding: 7px 11px;
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--ink-2);
}
.nav a:hover { background: var(--surface-sunk); color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); font-weight: 600; }

@media (max-width: 720px) {
  .site-head .wrap { height: 56px; gap: 8px; }
  .nav a { padding: 7px 7px; font-size: 13px; }
  .nav .wide { display: none; }
  .nav .narrow { display: inline; }
  .brand span { font-size: 17px; }
}
@media (max-width: 344px) {
  .brand span { display: none; }
}

/* ---- the run-location stamp: the signature element ---------------------- */

/* Stamped, not styled. Square corners, a solid meaning-coloured bar down the
   left, mono label, plain-English second line. It sits in the same place on
   every tool page and on every card in the index, because the point is that
   you learn to find it once. */
.stamp {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 10px;
  align-items: start;
  border: 1px solid var(--rule);
  border-left: 4px solid var(--stamp-colour, var(--rule-strong));
  background: var(--stamp-bg, var(--surface));
  padding: 9px 12px;
  border-radius: 3px;
  max-width: 420px;
}
.stamp .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--stamp-colour, var(--rule-strong));
  margin-top: 6px;
  grid-row: 1 / span 2;
}
.stamp b {
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--stamp-colour, var(--ink));
  font-weight: 600;
}
.stamp span { font-size: 13px; color: var(--ink-2); line-height: 1.4; }
.stamp--local { --stamp-colour: var(--local); --stamp-bg: var(--local-soft); }
.stamp--server { --stamp-colour: var(--server); --stamp-bg: var(--server-soft); }

/* The compact form used on index cards. */
.stamp-mini {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em;
  text-transform: uppercase; font-weight: 500;
}
.stamp-mini::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.stamp-mini--local { color: var(--local); }
.stamp-mini--server { color: var(--server); }

/* ---- home -------------------------------------------------------------- */

.hero { padding: 38px 0 26px; }
.hero h1 { max-width: 21ch; }
.hero .lede {
  font-size: clamp(16px, 2.2vw, 19px);
  color: var(--ink-2);
  max-width: 52ch;
  margin-top: 14px;
}

/* The hero is not a slogan over a gradient — it is the tool itself. Drop any
   file and the site tells you what it can do with that file. It is the most
   characteristic thing this site does, so it is the first thing it does. */
.router {
  margin-top: 22px;
  border: 2px dashed var(--rule-strong);
  border-radius: 10px;
  background: var(--surface);
  padding: 20px 22px;
  display: flex;
  gap: 18px;
  align-items: center;
  flex-wrap: wrap;
  transition: border-color .12s, background .12s;
}
.router > .said { flex: 1 1 300px; min-width: 0; }
/* The file types it knows, set in mono so the box says something concrete
   rather than being a large empty rectangle asking to be filled. */
.router .kinds { display: flex; gap: 5px; flex-wrap: wrap; }
.router .kinds span {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .07em; text-transform: uppercase;
  border: 1px solid var(--rule); color: var(--ink-3); padding: 4px 7px; border-radius: 3px;
}
.router.is-over { border-color: var(--signal); background: var(--signal-soft); border-style: solid; }
.router h2 { font-size: 19px; letter-spacing: -.015em; }
.router p { color: var(--ink-2); font-size: 14px; margin: 8px 0 0; }
.router .matches { display: flex; flex-wrap: wrap; gap: 8px; flex: 1 1 100%; }
.router .matches:empty { display: none; }
.router .matches a {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--rule-strong); background: var(--surface);
  padding: 7px 12px; border-radius: 999px; font-size: 14px; text-decoration: none;
}
.router .matches a:hover { border-color: var(--signal); color: var(--signal); }
.router .filename {
  font-family: var(--mono); font-size: 13px; color: var(--ink);
  background: var(--surface-sunk); padding: 2px 7px; border-radius: 3px;
}

/* ---- the tool index ---------------------------------------------------- */

.group { padding: 30px 0 6px; border-top: 1px solid var(--rule); margin-top: 34px; }
.group:first-of-type { border-top: 0; margin-top: 6px; }
.group-head { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 6px; }
.group-head h2 { letter-spacing: -.02em; }
/* The eyebrow states a fact — how many tools, and where they run — rather than
   labelling the section twice. */
.group-head .eyebrow { margin-left: auto; }
.group-note { color: var(--ink-2); font-size: 14.5px; max-width: 62ch; margin: 0 0 18px; }

.cards { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); }
.card {
  display: flex; flex-direction: column; gap: 8px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 15px 16px 14px;
  text-decoration: none;
  transition: border-color .12s, transform .12s;
}
.card:hover { border-color: var(--rule-strong); transform: translateY(-1px); }
.card:hover h3 { color: var(--signal); }
.card .top { display: flex; align-items: center; gap: 10px; }
.card .glyph { color: var(--ink-2); flex: none; }
.card:hover .glyph { color: var(--signal); }
.card h3 { flex: 1; }
.card p { font-size: 13.5px; color: var(--ink-2); line-height: 1.5; margin: 0; }
.card .foot { margin-top: auto; padding-top: 4px; }
.card[aria-disabled="true"] { opacity: .55; }

.filter-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 28px 0 4px; padding: 12px 14px;
  border: 1px solid var(--rule); border-radius: var(--radius); background: var(--surface);
}
.filter-bar label { display: inline-flex; align-items: center; gap: 9px; font-size: 14px; cursor: pointer; }
.filter-bar .count { margin-left: auto; }

/* ---- tool page --------------------------------------------------------- */

.tool-head { padding: 30px 0 22px; }
.tool-head .row { display: flex; gap: 24px; align-items: flex-start; flex-wrap: wrap; }
.tool-head .row > div:first-child { flex: 1 1 380px; }
.tool-head h1 { margin-top: 6px; }
.tool-head .lede { color: var(--ink-2); font-size: 17px; max-width: 56ch; margin-top: 12px; }

/* The working surface. Framed, so it reads as an instrument rather than as
   another block of page. */
.surface {
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: 8px;
  box-shadow: var(--shadow);
  overflow: hidden;
}
.surface > .bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px;
  border-bottom: 1px solid var(--rule);
  background: var(--surface-sunk);
}
.surface > .body { padding: 18px; }
@media (max-width: 560px) { .surface > .body { padding: 14px; } }

.drop {
  border: 2px dashed var(--rule-strong);
  border-radius: 8px;
  padding: 34px 18px;
  text-align: center;
  background: var(--surface);
  transition: border-color .12s, background .12s;
}
.drop.is-over { border-color: var(--signal); background: var(--signal-soft); border-style: solid; }
.drop h3 { font-size: 16px; }
.drop p { font-size: 13.5px; color: var(--ink-2); margin: 6px 0 0; }
.drop .hint { font-family: var(--mono); font-size: 11.5px; letter-spacing: .04em; color: var(--ink-3); margin-top: 12px; }

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

.btn {
  appearance: none;
  font: 600 14.5px/1 var(--sans);
  padding: 11px 17px;
  border-radius: var(--radius);
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 8px;
}
.btn:hover:not(:disabled) { border-color: var(--ink-3); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn--go { background: var(--signal); border-color: var(--signal); color: var(--signal-ink); }
.btn--go:hover:not(:disabled) { filter: brightness(1.07); border-color: var(--signal); }
.btn--sm { padding: 7px 11px; font-size: 13px; }
.btn--quiet { background: transparent; border-color: transparent; color: var(--ink-2); }
.btn--quiet:hover:not(:disabled) { background: var(--surface-sunk); color: var(--ink); border-color: transparent; }

.field { display: flex; flex-direction: column; gap: 6px; }
.field > label { font-family: var(--mono); font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }
input[type="text"], input[type="number"], select, textarea {
  font: 400 15px/1.5 var(--sans);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  padding: 9px 11px;
  width: 100%;
}
textarea { font-family: var(--mono); font-size: 14px; line-height: 1.65; resize: vertical; min-height: 200px; }
input[type="range"] { width: 100%; accent-color: var(--signal); }
input[type="checkbox"], input[type="radio"] { accent-color: var(--signal); width: 16px; height: 16px; }

.controls { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 16px; }
.actions .spacer { flex: 1; }

/* ---- file list --------------------------------------------------------- */

.files { list-style: none; margin: 0 0 14px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.files li {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 9px 11px; background: var(--surface);
}
.files .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.files .size { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }
.files .idx { font-family: var(--mono); font-size: 11px; color: var(--ink-3); width: 2ch; }

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

.result {
  border: 1px solid var(--local);
  border-left-width: 4px;
  background: var(--local-soft);
  border-radius: 4px;
  padding: 14px 16px;
  margin-top: 16px;
}
.result.is-server { border-color: var(--server); background: var(--server-soft); }
.result h3 { font-size: 15px; margin-bottom: 4px; }
.result .meta { font-family: var(--mono); font-size: 12px; color: var(--ink-2); }
.result .row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 12px; }

/* The one orchestrated moment on the site: a finished result draws itself in,
   like a plotter laying down a line. Everything else is instant. */
@media (prefers-reduced-motion: no-preference) {
  .result { animation: draw-in .34s cubic-bezier(.2, .7, .3, 1); }
  @keyframes draw-in {
    from { opacity: 0; transform: translateY(-4px); clip-path: inset(0 100% 0 0); }
    to { opacity: 1; transform: none; clip-path: inset(0 0 0 0); }
  }
}

.notice { border: 1px solid var(--rule-strong); border-left: 4px solid var(--warn); background: var(--warn-soft); padding: 12px 14px; border-radius: 4px; font-size: 14px; }
.notice.is-error { border-left-color: var(--signal); background: var(--signal-soft); }
.notice strong { display: block; margin-bottom: 2px; }

.progress { height: 4px; background: var(--surface-sunk); border-radius: 2px; overflow: hidden; }
.progress i { display: block; height: 100%; background: var(--signal); width: 0; transition: width .25s; }

.queue-line { display: flex; align-items: baseline; gap: 10px; font-family: var(--mono); font-size: 13px; }
.queue-line .num { font-size: 22px; font-weight: 600; color: var(--signal); }

/* ---- prose: the part AdSense reads, and the part people read ----------- */

.article { padding: 34px 0 10px; }
.article-grid { display: grid; gap: 34px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 980px) { .article-grid { grid-template-columns: minmax(0, 1fr) 300px; gap: 46px; } }

.prose { max-width: 68ch; }
.prose h2 { margin: 30px 0 10px; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin: 22px 0 6px; }
.prose p, .prose li { color: var(--ink-2); }
.prose strong { color: var(--ink); font-weight: 650; }
.prose ul, .prose ol { padding-left: 1.15em; margin: 0 0 1em; }
.prose li { margin-bottom: .4em; }
.prose code { background: var(--surface-sunk); padding: 1px 5px; border-radius: 3px; font-size: .9em; }

.aside { display: flex; flex-direction: column; gap: 20px; }
.panel { border: 1px solid var(--rule); border-radius: var(--radius); background: var(--surface); padding: 14px 16px; }
.panel h3 { font-size: 12px; font-family: var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); font-weight: 500; margin-bottom: 10px; }
.spec { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; font-size: 13.5px; }
.spec li { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.spec .k { color: var(--ink-2); }
.spec .v { font-family: var(--mono); font-size: 12.5px; text-align: right; color: var(--ink); }
.lang-list { display: flex; flex-wrap: wrap; gap: 5px; }
.lang-list span { font-family: var(--mono); font-size: 11px; letter-spacing: .04em; border: 1px solid var(--rule); padding: 3px 6px; border-radius: 3px; color: var(--ink-2); }
.lang-list span.no { border-style: dashed; color: var(--ink-3); text-decoration: line-through; text-decoration-color: var(--rule-strong); }
.related { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; font-size: 14px; }

/* ---- ad slots ---------------------------------------------------------- */

/* Reserved, empty, and shipping with NO ad code. Ads must not run on the
   staging host: it is served noindex and the ad account must not be associated
   with it. The slot exists now so that the layout does not shift the day it is
   filled — reserving the space is the whole point. */
.ad-slot {
  min-height: 90px;
  display: flex; align-items: center; justify-content: center;
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  color: var(--ink-3);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  margin: 28px 0;
}
.ad-slot--wide { min-height: 100px; }
@media (min-width: 980px) { .ad-slot--rail { min-height: 250px; } }

/* ---- footer ------------------------------------------------------------ */

.site-foot { border-top: 1px solid var(--rule); margin-top: 48px; padding: 30px 0 46px; color: var(--ink-2); font-size: 14px; }
.site-foot .cols { display: grid; gap: 26px; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.site-foot h3 { font-size: 11px; font-family: var(--mono); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); font-weight: 500; margin-bottom: 9px; }
.site-foot ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.site-foot a { text-decoration: none; }
.site-foot a:hover { color: var(--ink); text-decoration: underline; }
.site-foot .fine { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--rule); font-size: 13px; color: var(--ink-3); max-width: 70ch; }

/* ---- diff / counter / json output -------------------------------------- */

.stat-row { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(104px, 1fr)); }
.stat {
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--surface); padding: 11px 12px;
}
.stat .v { font-family: var(--mono); font-size: 22px; font-weight: 600; letter-spacing: -.02em; display: block; font-variant-numeric: tabular-nums; }
.stat .k { font-family: var(--mono); font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3); }

.readout { font-family: var(--mono); font-size: 13px; line-height: 1.7; white-space: pre-wrap; word-break: break-word; background: var(--surface-sunk); border: 1px solid var(--rule); border-radius: var(--radius); padding: 12px 14px; max-height: 420px; overflow: auto; margin: 0; }

.diff { font-family: var(--mono); font-size: 13px; line-height: 1.65; border: 1px solid var(--rule); border-radius: var(--radius); overflow: auto; max-height: 560px; background: var(--surface); }
.diff div { display: flex; gap: 0; white-space: pre-wrap; word-break: break-word; }
.diff .ln { flex: none; width: 4.5ch; text-align: right; padding: 0 8px 0 6px; color: var(--ink-3); font-size: 11.5px; background: var(--surface-sunk); border-right: 1px solid var(--rule); user-select: none; }
.diff .tx { flex: 1; padding: 0 10px; min-width: 0; }
.diff .add { background: color-mix(in srgb, var(--local) 13%, transparent); }
.diff .del { background: color-mix(in srgb, var(--signal) 13%, transparent); }
.diff mark { background: color-mix(in srgb, var(--signal) 30%, transparent); color: inherit; border-radius: 2px; }
.diff .add mark { background: color-mix(in srgb, var(--local) 32%, transparent); }

/* Grammar check: the text with its problems marked, and the list beside it. */
.marked { white-space: pre-wrap; word-break: break-word; font-size: 15px; line-height: 1.8; }
.marked u { text-decoration: none; border-bottom: 2px solid; cursor: pointer; padding-bottom: 1px; }
.marked u.spelling { border-color: var(--signal); }
.marked u.grammar { border-color: var(--server); }
.marked u.style { border-color: var(--ink-3); border-bottom-style: dotted; }
.marked u.is-active { background: var(--signal-soft); }
.match-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; max-height: 460px; overflow: auto; }
.match {
  border: 1px solid var(--rule); border-left: 3px solid var(--ink-3);
  border-radius: 4px; padding: 10px 12px; background: var(--surface); font-size: 14px;
}
.match.spelling { border-left-color: var(--signal); }
.match.grammar { border-left-color: var(--server); }
.match .kind { font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.match .fixes { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.match .fixes button { font-family: var(--mono); font-size: 12.5px; padding: 4px 9px; border: 1px solid var(--rule-strong); border-radius: 3px; background: var(--surface); cursor: pointer; }
.match .fixes button:hover { border-color: var(--signal); color: var(--signal); }

/* The marked text and the list of findings sit side by side once there is room
   for both to be readable, and stack below that. Set here rather than inline,
   because an inline grid-template-columns cannot be overridden by a media
   query and the page would have stayed single-column at every width. */
.check-grid { display: grid; gap: 18px; grid-template-columns: minmax(0, 1fr); margin-top: 18px; }
@media (min-width: 900px) { .check-grid { grid-template-columns: minmax(0, 1fr) 360px; } }

/* Image previews sit on a checkerboard so transparency is visible rather than
   implied. A "background removed" result on a white card looks like a failure. */
.checker {
  background-image:
    linear-gradient(45deg, var(--surface-sunk) 25%, transparent 25%),
    linear-gradient(-45deg, var(--surface-sunk) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--surface-sunk) 75%),
    linear-gradient(-45deg, transparent 75%, var(--surface-sunk) 75%);
  background-size: 16px 16px;
  background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}
.preview { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.preview figure { margin: 0; }
.preview img, .preview canvas { display: block; width: 100%; height: auto; border: 1px solid var(--rule); border-radius: 4px; }
.preview figcaption { font-family: var(--mono); font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); margin-top: 6px; }

.crop-stage { position: relative; display: inline-block; max-width: 100%; touch-action: none; user-select: none; }
.crop-stage canvas { display: block; max-width: 100%; height: auto; border-radius: 4px; }
.crop-box { position: absolute; border: 2px solid var(--signal); box-shadow: 0 0 0 9999px rgba(18, 33, 42, .45); cursor: move; }
.crop-box i { position: absolute; width: 14px; height: 14px; background: var(--signal); border-radius: 2px; }
.crop-box i.se { right: -7px; bottom: -7px; cursor: nwse-resize; }
.crop-box i.nw { left: -7px; top: -7px; cursor: nwse-resize; }

.qr-out { display: flex; gap: 20px; flex-wrap: wrap; align-items: flex-start; }
.qr-out canvas { background: #fff; padding: 12px; border: 1px solid var(--rule); border-radius: 4px; image-rendering: pixelated; }

.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 50;
  background: var(--surface); border: 1px solid var(--signal); padding: 10px 14px; border-radius: 0 0 var(--radius) 0;
}
.skip:focus { left: 0; }
