/* QR generator — Graphite design system tokens (copied from assets/graphite.css,
   this app runs on a different vhost so styles are not linked across apps). */
:root {
  --bg:#eeecea; --card:#fff; --ink:#111; --ink2:#1a1714;
  --line:#e8e8e8; --line2:#f0f0f0; --line3:#f6f6f6;
  --mut:#8e8e8e; --mut2:#a8a8a8; --dim:#b5b5b5; --faint:#c4c4c4;
  --red:#a33; --red-line:#e5c9c9;
  --accent:#b5533a;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  --sans:Archivo,Helvetica,Arial,sans-serif;
  --shadow:0 22px 54px -34px rgba(0,0,0,.45);
  --green:#2ecc71; --amber:#f1c40f; --red-dot:#e74c3c;
}

* { box-sizing:border-box; }
html, body { margin:0; }
body {
  background:var(--bg); color:var(--ink); font-family:var(--sans);
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; text-rendering:optimizeLegibility;
}
a { color:var(--ink2); text-decoration:none; }
a:hover { color:var(--accent); }
::-webkit-scrollbar { width:8px; height:8px; }
::-webkit-scrollbar-thumb { background:rgba(0,0,0,.18); border-radius:8px; }
button, input, textarea, select { font-family:inherit; color:inherit; }
input, textarea, select { outline:none; }

/* helpers */
.mono { font-family:var(--mono); }
.mut { color:var(--mut); }

@media (prefers-reduced-motion: reduce) {
  * { transition-duration:.001ms !important; animation-duration:.001ms !important; }
}

/* ---------- layout ---------- */
.wrap { max-width:1180px; margin:0 auto; padding:16px; }

.site-header { padding:8px 4px 20px; }
.site-header h1 { margin:0 0 4px; font-size:1.6rem; font-weight:700; letter-spacing:-.01em; }
.subtitle { margin:0; font-size:.9rem; }

.cols {
  display:grid;
  grid-template-columns:1fr 420px;
  gap:16px;
  align-items:start;
}
@media (max-width:900px) {
  .cols { grid-template-columns:1fr; }
  .col-right .card.preview-card { position:static; }
}

.col-left, .col-right { min-width:0; }

/* ---------- cards ---------- */
.card {
  background:var(--card);
  border:1px solid var(--line);
  border-radius:12px;
  padding:18px;
  margin-bottom:16px;
  box-shadow:var(--shadow);
}
.card h2 { margin:0 0 14px; font-size:1rem; font-weight:600; }

.col-right .card.preview-card {
  position:sticky;
  top:16px;
  margin-bottom:0;
}

/* ---------- tabs ---------- */
.tabs {
  display:flex;
  flex-wrap:wrap;
  gap:6px;
  margin-bottom:16px;
}
.tabs [role="tab"] {
  appearance:none;
  border:1px solid var(--line);
  background:var(--line3);
  color:var(--ink);
  font:500 13px/1 var(--sans);
  padding:9px 14px;
  border-radius:999px;
  cursor:pointer;
}
.tabs [role="tab"]:hover { border-color:var(--dim); }
.tabs [role="tab"][aria-selected="true"] {
  background:var(--ink);
  border-color:var(--ink);
  color:#fff;
}

/* ---------- forms ---------- */
form[role="tabpanel"] { display:flex; flex-direction:column; gap:12px; }

label.fld {
  display:flex;
  flex-direction:column;
  gap:6px;
  font:500 12px/1.2 var(--sans);
  color:var(--ink2);
}
label.fld.fld-inline { gap:8px; }

/* text-input "filled field" look, applied to every native control here */
input[type="text"],
input[type="tel"],
input[type="email"],
input[type="url"],
input[type="number"],
input[type="datetime-local"],
input[type="color"],
input[type="file"],
textarea,
select {
  border:1px solid #d8d8d8;
  border-radius:6px;
  background:#fff;
  padding:12px 13px;
  font:500 13px/1.3 var(--sans);
  width:100%;
}
textarea { resize:vertical; }
input::placeholder, textarea::placeholder { color:var(--dim); font-weight:400; }
input:focus, textarea:focus, select:focus { border-color:var(--ink); }

input[type="color"] { padding:4px; width:56px; height:40px; cursor:pointer; }
input[type="file"] { padding:9px 10px; cursor:pointer; }
input[type="number"] { width:auto; min-width:110px; }

fieldset {
  border:1px solid var(--line);
  border-radius:8px;
  padding:12px 12px 14px;
  margin:0;
}
fieldset legend {
  padding:0 6px;
  font:600 11px/1 var(--sans);
  color:var(--mut);
  text-transform:uppercase;
  letter-spacing:.04em;
}
fieldset .row:last-child { margin-bottom:0; }

.row {
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:10px;
  margin-bottom:10px;
}
@media (max-width:480px) {
  .row { grid-template-columns:1fr; }
}

/* plain checkbox labels */
form label:not(.fld) {
  display:flex;
  align-items:center;
  gap:8px;
  font:500 13px/1.2 var(--sans);
  cursor:pointer;
}
input[type="checkbox"], input[type="radio"] { accent-color:var(--ink); width:15px; height:15px; }

.errors { margin:0; padding:0; list-style:none; }
.errors li {
  color:var(--red);
  font-size:12px;
  padding:2px 0;
}

/* ---------- options ---------- */
.opt-group {
  padding:14px 0;
  border-top:1px solid var(--line2);
  display:flex;
  flex-direction:column;
  gap:10px;
}
.opt-group:first-of-type { border-top:none; padding-top:0; }
.opt-label {
  font:600 11px/1 var(--sans);
  color:var(--mut);
  text-transform:uppercase;
  letter-spacing:.04em;
}
.opt-row {
  flex-direction:row;
  flex-wrap:wrap;
  align-items:center;
  gap:16px;
}
.opt-row label:not(.fld) { cursor:pointer; }
.opt-row .fld { flex:1 1 160px; min-width:140px; }
.opt-row .fld-inline { flex-direction:row; align-items:center; gap:8px; }
.opt-row .fld-inline input,
.opt-row .fld-inline select { width:auto; }
.opt-row .fld-inline input[type="color"] { width:56px; }

.logo-row {
  display:flex;
  align-items:center;
  gap:8px;
  flex-wrap:wrap;
}
.logo-thumb {
  width:28px;
  height:28px;
  border:1px solid var(--line);
  border-radius:4px;
  object-fit:contain;
  flex:none;
}

output#version-out { font-size:13px; color:var(--mut); }

/* segmented control */
.seg {
  display:inline-flex;
  border:1px solid var(--line);
  border-radius:8px;
  overflow:hidden;
  width:fit-content;
}
.seg label {
  position:relative;
  padding:8px 14px;
  font:500 13px/1 var(--sans);
  cursor:pointer;
  border-right:1px solid var(--line);
  display:flex;
  align-items:center;
}
.seg label:last-child { border-right:none; }
.seg input[type="radio"] {
  position:absolute;
  opacity:0;
  width:0;
  height:0;
  margin:0;
}
.seg label:has(:checked) {
  background:var(--ink);
  color:#fff;
}

/* toggle pill (logo-pad) */
label.tg {
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:8px;
  cursor:pointer;
  font:500 13px/1.2 var(--sans);
  padding-left:40px;
  min-height:18px;
}
label.tg input[type="checkbox"] {
  position:absolute;
  left:0;
  top:0;
  width:32px;
  height:18px;
  margin:0;
  appearance:none;
  border:1px solid var(--line);
  border-radius:999px;
  background:var(--line3);
  cursor:pointer;
  transition:background .15s ease;
}
label.tg input[type="checkbox"]::after {
  content:"";
  position:absolute;
  top:1px;
  left:1px;
  width:14px;
  height:14px;
  border-radius:999px;
  background:#fff;
  box-shadow:0 1px 2px rgba(0,0,0,.3);
  transition:margin-left .15s ease;
}
label.tg input[type="checkbox"]:checked {
  background:var(--ink);
  border-color:var(--ink);
}
label.tg input[type="checkbox"]:checked::after { margin-left:14px; }

/* range slider — track colour is painted at runtime via style.background (CSSOM), so
   this block only sets shape/appearance, never a background shorthand */
input[type="range"] {
  appearance:none;
  -webkit-appearance:none;
  width:100%;
  height:6px;
  border-radius:999px;
  background:var(--line2);
}
input[type="range"]::-webkit-slider-thumb {
  appearance:none;
  -webkit-appearance:none;
  width:16px;
  height:16px;
  border-radius:999px;
  background:var(--ink);
  border:2px solid #fff;
  box-shadow:0 0 0 1px var(--line);
  cursor:pointer;
  margin-top:-5px;
}
input[type="range"]::-moz-range-thumb {
  width:16px;
  height:16px;
  border-radius:999px;
  background:var(--ink);
  border:2px solid #fff;
  box-shadow:0 0 0 1px var(--line);
  cursor:pointer;
}
input[type="range"]::-moz-range-track { height:6px; border-radius:999px; }
input[type="range"]:disabled { opacity:.5; cursor:not-allowed; }

/* details / encoded text */
#payload-details summary {
  cursor:pointer;
  font:500 13px/1.2 var(--sans);
  display:flex;
  align-items:center;
  gap:8px;
  list-style:none;
}
#payload-details summary::-webkit-details-marker { display:none; }
#payload-details summary::before {
  content:"▸";
  display:inline-block;
  color:var(--mut);
}
#payload-details[open] summary::before { content:"▾"; }
#payload-text {
  margin:10px 0 0;
  padding:10px 12px;
  background:var(--line3);
  border:1px solid var(--line);
  border-radius:6px;
  font-size:12px;
  white-space:pre-wrap;
  word-break:break-all;
  max-height:220px;
  overflow:auto;
}

/* ---------- preview column ---------- */
.preview {
  aspect-ratio:1;
  width:100%;
  border:1px solid var(--line);
  border-radius:8px;
  overflow:hidden;
  display:flex;
  align-items:center;
  justify-content:center;
  margin-bottom:14px;
}
.checker,
.logo-thumb,
canvas.le-canvas,
canvas.le-result {
  background-image:
    linear-gradient(45deg, #ddd 25%, transparent 25%),
    linear-gradient(-45deg, #ddd 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #ddd 75%),
    linear-gradient(-45deg, transparent 75%, #ddd 75%);
  background-size:24px 24px;
  background-position:0 0, 0 12px, 12px -12px, -12px 0;
  background-color:#fff;
}
#preview {
  width:100%;
  height:auto;
  image-rendering:pixelated;
  display:block;
}

#status { margin-bottom:10px; font-size:12px; }

.warn {
  display:flex;
  align-items:flex-start;
  gap:10px;
  border:1px solid var(--line);
  border-radius:8px;
  padding:10px 12px;
  margin-bottom:12px;
  font-size:12px;
}
.warn-dot {
  width:10px;
  height:10px;
  border-radius:999px;
  margin-top:2px;
  flex:none;
  background:var(--mut);
}
.warn-text { flex:1; }
.warn-actions { display:flex; gap:8px; flex-wrap:wrap; }
.warn.green .warn-dot { background:var(--green); }
.warn.amber .warn-dot { background:var(--amber); }
.warn.red .warn-dot { background:var(--red-dot); }
.warn.red { background:#fdf2f1; border-color:var(--red-line); }

#detector-badge { font-size:12px; margin-bottom:12px; }

.btn-row {
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  margin-bottom:14px;
}

button,
.le-btn {
  appearance:none;
  border:1px solid var(--ink);
  background:var(--ink);
  color:#fff;
  font:600 13px/1 var(--sans);
  padding:10px 14px;
  border-radius:8px;
  cursor:pointer;
}
button:hover,
.le-btn:hover { background:var(--ink2); border-color:var(--ink2); }
button:disabled,
.le-btn:disabled { opacity:.5; cursor:not-allowed; }

button.ghost,
.le-btn.ghost {
  background:transparent;
  color:var(--ink);
  border:1px solid var(--line);
}
button.ghost:hover,
.le-btn.ghost:hover { border-color:var(--dim); background:var(--line3); }
.le-btn.primary {
  background:var(--ink);
  color:#fff;
  border-color:var(--ink);
}
.le-btn.primary:hover { background:var(--ink2); border-color:var(--ink2); }

.footnote { margin:0; font-size:12px; }

/* ---------- utility ---------- */
[hidden] { display:none !important; }

/* ---------- logo editor modal (built by qr/logo-editor.js via createElement) ---------- */
body.le-open { overflow:hidden; }

.le-backdrop {
  position:fixed;
  inset:0;
  background:rgba(0,0,0,.45);
  z-index:1000;
  display:flex;
  align-items:center;
  justify-content:center;
}

.le-modal {
  background:#fff;
  border-radius:12px;
  max-width:920px;
  width:calc(100% - 32px);
  max-height:calc(100vh - 32px);
  overflow:auto;
  padding:16px;
  display:grid;
  grid-template-columns:1fr 300px;
  gap:16px;
}
@media (max-width:760px) {
  .le-modal { grid-template-columns:1fr; }
}

.le-stage { position:relative; }

canvas.le-canvas {
  display:block;
  max-width:100%;
  max-height:480px;
}

canvas.le-result {
  max-width:120px;
  max-height:120px;
  border:1px solid var(--line);
}

.le-crop {
  position:absolute;
  box-sizing:border-box;
  outline:2px solid #111;
  box-shadow:0 0 0 9999px rgba(0,0,0,.35);
  cursor:move;
  touch-action:none;
}

.le-h {
  position:absolute;
  width:12px;
  height:12px;
  background:#fff;
  border:2px solid #111;
  border-radius:2px;
  touch-action:none;
}
.le-h-nw { top:-6px; left:-6px; cursor:nwse-resize; }
.le-h-n  { top:-6px; left:50%; transform:translateX(-50%); cursor:ns-resize; }
.le-h-ne { top:-6px; right:-6px; cursor:nesw-resize; }
.le-h-e  { top:50%; right:-6px; transform:translateY(-50%); cursor:ew-resize; }
.le-h-se { bottom:-6px; right:-6px; cursor:nwse-resize; }
.le-h-s  { bottom:-6px; left:50%; transform:translateX(-50%); cursor:ns-resize; }
.le-h-sw { bottom:-6px; left:-6px; cursor:nesw-resize; }
.le-h-w  { top:50%; left:-6px; transform:translateY(-50%); cursor:ew-resize; }

.le-controls {
  display:flex;
  flex-direction:column;
  gap:10px;
}

.le-row {
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  align-items:center;
}
.le-row input[type="range"] {
  flex:1;
  min-width:100px;
}

.le-actions {
  display:flex;
  gap:8px;
  justify-content:flex-end;
  margin-top:auto;
}

/* ---------- print ---------- */
@media print {
  .col-left { display:none; }
  .cols { grid-template-columns:1fr; }
  .col-right .card.preview-card { position:static; box-shadow:none; }
  #preview { display:block; }
}
