/* ── Self-hosted fonts (OFL 1.1 — see /fonts/LICENSE-*.txt) ── */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/inter-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/inter-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../fonts/inter-600.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/jetbrains-mono-400.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('../fonts/jetbrains-mono-500.woff2') format('woff2');
}

/* ── Design tokens ─────────────────────────────────────── */
:root {
  --bg-base:       #0d0f12;
  --bg-panel:      #13161b;
  --bg-surface:    #1a1e26;
  --bg-hover:      #1f2430;
  --bg-active:     #252c3a;
  --border:        #2a2f3d;
  --border-focus:  #4a90e2;

  --text-primary:  #e2e6f0;
  --text-secondary:#7a8299;
  --text-muted:    #4a5068;
  --text-accent:   #4a90e2;
  --text-success:  #4caf82;
  --text-error:    #e25c5c;
  --text-warn:     #e2a94a;

  --accent:        #4a90e2;
  --accent-dim:    rgba(74,144,226,0.12);
  --success:       #4caf82;
  --error:         #e25c5c;

  --sidebar-w:     220px;
  --font-mono:     'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Consolas', monospace;
  --font-ui:       'Inter', system-ui, -apple-system, sans-serif;
  --code-line-h:   1.65;   /* line-height shared by code panes, gutters, diff rows */
  --radius:        6px;
  --radius-sm:     4px;
  --transition:    150ms ease;
}

body.light {
  --bg-base:       #f4f5f7;
  --bg-panel:      #ffffff;
  --bg-surface:    #eceef2;
  --bg-hover:      #e4e6ec;
  --bg-active:     #d8dbe6;
  --border:        #d0d3de;
  --border-focus:  #4a90e2;

  --text-primary:  #1a1d27;
  --text-secondary:#4a5068;
  --text-muted:    #9099b2;
  --text-accent:   #2e6ec4;
  --text-success:  #2e8a5c;
  --text-error:    #c0392b;
  --text-warn:     #b07a1a;

  --accent:        #2e6ec4;
  --accent-dim:    rgba(46,110,196,0.10);
  --success:       #2e8a5c;
  --error:         #c0392b;
}

/* ── Reset ─────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; }
body {
  font-family: var(--font-ui);
  font-size: 13px;
  background: var(--bg-base);
  color: var(--text-primary);
  line-height: 1.5;
}

/* ── Scrollbars ─────────────────────────────────────────── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }

/* ── Layout ─────────────────────────────────────────────── */
#app {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

/* Header */
#header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 16px;
  height: 48px;
  background: var(--bg-panel);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  z-index: 10;
}
#header .logo {
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.3px;
}
#header .logo span { color: var(--accent); }
#sidebar-toggle {
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  padding: 5px 8px;
  font-size: 14px;
  line-height: 1;
  transition: var(--transition);
}
#sidebar-toggle:hover { border-color: var(--accent); color: var(--accent); }
#theme-toggle {
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  padding: 4px 6px;
  display: flex;
  align-items: center;
  transition: var(--transition);
  margin-left: 8px;
}
#theme-toggle:hover { border-color: var(--accent); color: var(--accent); }
#theme-toggle svg { width: 16px; height: 16px; }
.header-spacer { flex: 1; }
.header-meta {
  font-size: 11px;
  color: var(--text-muted);
  font-family: var(--font-mono);
}

/* Main body */
#body {
  display: flex;
  flex: 1;
  overflow: hidden;
}

/* Sidebar */
#sidebar {
  width: var(--sidebar-w);
  background: var(--bg-panel);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  overflow-y: auto;
  transition: width 200ms ease, opacity 200ms ease;
}
#sidebar.collapsed {
  width: 0;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.sidebar-section { margin-top: 8px; }
.sidebar-group-label {
  padding: 8px 14px 4px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  user-select: none;
}
.sidebar-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  cursor: pointer;
  color: var(--text-secondary);
  font-size: 12.5px;
  border-radius: 0;
  transition: var(--transition);
  border-left: 2px solid transparent;
  white-space: nowrap;
  user-select: none;
}
.sidebar-item:hover { background: var(--bg-hover); color: var(--text-primary); }
.sidebar-item.active {
  background: var(--accent-dim);
  color: var(--accent);
  border-left-color: var(--accent);
}
.sidebar-item .icon { font-size: 13px; opacity: 0.7; }

/* Content area */
#content {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Tool panels */
.tool-panel {
  display: none;
  flex: 1;
  flex-direction: column;
  overflow: hidden;
  content-visibility: auto;
}
.tool-panel.active {
  display: flex;
}

/* Utility: small number/text input used in tool headers */
.tool-input-sm {
  width: 52px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  padding: 3px 6px;
  font-size: 12px;
  outline: none;
}

/* Generic toggle switch (.sw-label / .sw-track / .sw-thumb) */
.sw-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  user-select: none;
  font-size: 12px;
  color: var(--text-secondary);
}
.sw-label input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.sw-track {
  display: inline-flex;
  align-items: center;
  width: 28px;
  height: 16px;
  background: var(--border);
  border-radius: 8px;
  transition: background 0.15s;
  flex-shrink: 0;
}
.sw-label input:checked + .sw-track { background: var(--accent); }
.sw-thumb {
  width: 12px;
  height: 12px;
  background: #fff;
  border-radius: 50%;
  margin-left: 2px;
  transition: transform 0.15s;
}
.sw-label input:checked + .sw-track .sw-thumb { transform: translateX(12px); }

/* Auto-render toggle switch (ZPL) — aliases to generic */
.zpl-toggle-label { display: flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; }
.zpl-toggle-label input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; }
.zpl-toggle-track  { display: inline-flex; align-items: center; width: 28px; height: 16px; background: var(--border); border-radius: 8px; transition: background 0.15s; flex-shrink: 0; }
.zpl-toggle-label input:checked + .zpl-toggle-track { background: var(--accent); }
.zpl-toggle-thumb  { width: 12px; height: 12px; background: #fff; border-radius: 50%; margin-left: 2px; transition: transform 0.15s; }
.zpl-toggle-label input:checked + .zpl-toggle-track .zpl-toggle-thumb { transform: translateX(12px); }

/* Utility: vertical divider used in tool headers */
.tool-divider {
  width: 1px;
  height: 18px;
  background: var(--border);
  margin: 0 4px;
  display: inline-block;
  flex-shrink: 0;
}

/* Utility: muted label text in tool headers */
.tool-label-sm {
  font-size: 11px;
  color: var(--text-muted);
}

/* Tool header bar */
.tool-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg-panel);
}
.tool-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}
.tool-desc {
  font-size: 11px;
  color: var(--text-muted);
}
.tool-spacer { flex: 1; }

/* Two-pane layout for tools with input/output */
.pane-layout {
  display: flex;
  flex: 1;
  overflow: hidden;
  gap: 0;
  border-top: 1px solid var(--border);
}
.pane {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}
/* Resize divider between panes */
.pane-divider {
  flex: 0 0 9px;
  background: var(--bg-surface);
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  cursor: col-resize;
  display: flex;
  align-items: center;
  justify-content: center;
  user-select: none;
  transition: background 0.15s;
  position: relative;
  z-index: 1;
}
.pane-divider:hover,
.pane-divider.dragging {
  background: var(--accent-dim);
  border-color: var(--accent);
}

/* Horizontal resize divider (row height) */
.pane-divider-h {
  flex: 0 0 9px;
  background: var(--bg-surface);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  cursor: row-resize;
  display: flex;
  align-items: center;
  justify-content: center;
  user-select: none;
  transition: background 0.15s;
  z-index: 1;
}
.pane-divider-h:hover,
.pane-divider-h.dragging {
  background: var(--accent-dim);
  border-color: var(--accent);
}
/* Five-dot horizontal grip */
.divider-grip-h {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--text-muted);
  box-shadow: 6px 0 0 var(--text-muted), -6px 0 0 var(--text-muted),
              12px 0 0 var(--text-muted), -12px 0 0 var(--text-muted);
  pointer-events: none;
}
.pane-divider-h:hover .divider-grip-h,
.pane-divider-h.dragging .divider-grip-h {
  background: var(--accent);
  box-shadow: 6px 0 0 var(--accent), -6px 0 0 var(--accent),
              12px 0 0 var(--accent), -12px 0 0 var(--accent);
}

/* Five-dot vertical grip via box-shadow */
.divider-grip {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--text-muted);
  box-shadow: 0 6px 0 var(--text-muted), 0 -6px 0 var(--text-muted),
              0 12px 0 var(--text-muted), 0 -12px 0 var(--text-muted);
  pointer-events: none;
  flex-shrink: 0;
}
.pane-divider:hover .divider-grip,
.pane-divider.dragging .divider-grip {
  background: var(--accent);
  box-shadow: 0 6px 0 var(--accent), 0 -6px 0 var(--accent),
              0 12px 0 var(--accent), 0 -12px 0 var(--accent);
}
.pane-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  background: var(--bg-panel);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.pane-label {
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

/* Textareas */
.editor-wrap {
  flex: 1;
  display: flex;
  overflow: hidden;
  background: var(--bg-base);
}
.editor-wrap:focus-within { background: var(--bg-surface); }
.line-numbers {
  padding: 12px 8px 12px 10px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: var(--code-line-h);
  color: var(--text-muted);
  text-align: right;
  user-select: none;
  white-space: pre;
  overflow: hidden;
  flex-shrink: 0;
  min-width: 32px;
  border-right: 1px solid var(--border);
}
.editor-inner {
  position: relative;
  flex: 1;
  overflow: hidden;
}
.zpl-highlight {
  position: absolute;
  inset: 0;
  padding: 12px 14px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: var(--code-line-h);
  white-space: pre-wrap;
  word-break: break-all;
  overflow: auto;
  pointer-events: none;
  scrollbar-width: none;
}
.zpl-highlight::-webkit-scrollbar { display: none; }
textarea.code-input {
  flex: 1;
  background: var(--bg-base);
  color: var(--text-primary);
  border: none;
  outline: none;
  resize: none;
  padding: 12px 14px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: var(--code-line-h);
  tab-size: 2;
  overflow: auto;
}
textarea.code-input:focus { background: var(--bg-surface); }
textarea.code-input::placeholder { color: var(--text-muted); }

/* ZPL editor only: transparent text so the highlight layer shows through */
.editor-inner textarea.code-input {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  background: transparent;
  color: transparent;
  caret-color: var(--text-primary);
  padding: 12px 14px;     /* must match .zpl-highlight padding exactly */
  word-break: break-all;  /* must match .zpl-highlight word-break exactly */
  scrollbar-width: none;
}
.editor-inner textarea.code-input::-webkit-scrollbar { display: none; }
.editor-inner textarea.code-input:focus { background: transparent; }
/* ZPL syntax token colors */
.zpl-cmd     { color: #4a90e2; }
.zpl-tilde   { color: #c792ea; }
.zpl-string  { color: #4caf82; }
.zpl-num     { color: #e8963a; }
.zpl-comment { color: var(--text-muted); }

/* Output display (non-editable) */
.code-output {
  flex: 1;
  background: var(--bg-base);
  color: var(--text-primary);
  padding: 12px 14px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: var(--code-line-h);
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  cursor: text;
}

/* ── Line numbers gutter ─────────────────────────────────────────── */
.code-editor-wrap {
  display: flex;
  flex: 1;
  overflow: hidden;
  min-height: 0;
}
.line-gutter {
  flex-shrink: 0;
  width: 42px;
  background: var(--bg-surface);
  border-right: 1px solid var(--border);
  padding: 12px 8px 12px 0;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: var(--code-line-h);
  color: var(--text-muted);
  text-align: right;
  overflow: hidden;
  user-select: none;
  white-space: pre;
}
.line-gutter span { display: flex; align-items: flex-start; justify-content: flex-end; }

/* code-output and code-input now live inside .code-editor-wrap */
.code-editor-wrap .code-output,
.code-editor-wrap textarea.code-input {
  flex: 1;
  min-width: 0;
}

/* JSON/XML pane header strip — sits above the resizable pane-layout */
.jx-pane-headers {
  display: flex;
  flex-shrink: 0;
}
.jwt-pane-headers {
  display: flex;
  flex-shrink: 0;
}
.jwt-col-headers {
  display: flex;
  flex: 1;
  min-width: 0;
}
#jwt-decode-left-hdr,
#jwt-encode-left-hdr { flex: 0 0 50%; min-width: 0; overflow: hidden; white-space: nowrap; }
#jx-header-left  { flex: 0 0 50%; min-width: 0; overflow: hidden; white-space: nowrap; }
#jx-header-right { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; }
#b64-header-left  { flex: 0 0 50%; min-width: 0; overflow: hidden; white-space: nowrap; }
#b64-header-right { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; }
#diff-label-left  { flex: 0 0 50%; min-width: 0; overflow: hidden; white-space: nowrap; }
/* itz-header-right intentionally excluded — it holds interactive controls
   (buttons/sliders), which overflow:hidden would clip out of reach; only the
   text-only left side gets the same clip-instead-of-wrap treatment as jx/b64. */
#itz-header-left { overflow: hidden; white-space: nowrap; }

.jx-tree-controls { display: flex; gap: 4px; }

/* JSON/XML tool: tighter left padding next to the gutter */
#panel-formatter .code-editor-wrap .code-output,
#panel-formatter .code-editor-wrap textarea.code-input {
  padding-left: 8px;
}
#panel-formatter .jx-error-line {
  margin-left: -8px;
  padding-left: 5px;
}

/* ── highlight.js theme (CSS-variable-driven, dark/light aware) ── */
.hljs                          { background: transparent; color: var(--text-primary); }
.hljs-attr, .hljs-name        { color: #7eb8f7; }          /* JSON keys / XML tag names  */
.hljs-string                   { color: #98d9a0; }          /* string values               */
.hljs-number                   { color: #f2a96a; }          /* numbers                     */
.hljs-literal                  { color: #c792ea; }          /* true / false / null         */
.hljs-punctuation,
.hljs-operator                 { color: var(--text-secondary); }
.hljs-tag .hljs-name           { color: #7eb8f7; }          /* XML tag                     */
.hljs-tag .hljs-attr           { color: #ffd580; }          /* XML attribute name          */
.hljs-tag                      { color: var(--text-secondary); } /* < > brackets            */
.hljs-comment                  { color: var(--text-muted); font-style: italic; }

body.light .hljs-attr,
body.light .hljs-name          { color: #1a5fb4; }
body.light .hljs-string        { color: #1e7c3c; }
body.light .hljs-number        { color: #b5500b; }
body.light .hljs-literal       { color: #6b3fa0; }
body.light .hljs-tag .hljs-attr{ color: #8c6a00; }
body.light .tree-key           { color: #1a5fb4; }
body.light .tree-str           { color: #1e7c3c; }
body.light .tree-num           { color: #b5500b; }
body.light .tree-bool          { color: #6b3fa0; }
body.light .tree-null          { color: #6b3fa0; }

/* ── JSON error list panel ───────────────────────────────────────── */
.jx-error-panel {
  flex-shrink: 0;
  border-top: 1px solid var(--border);
  background: var(--bg-surface);
  max-height: 160px;
  display: flex;
  flex-direction: column;
}
.jx-error-panel.hidden { display: none; }
.jx-error-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-error);
  flex-shrink: 0;
  border-bottom: 1px solid var(--border);
}
.jx-error-panel-toggle {
  font-size: 10px;
  background: none;
  border: none;
  color: var(--text-secondary, var(--text-primary));
  cursor: pointer;
  padding: 0;
  opacity: 0.7;
}
.jx-error-panel-toggle:hover { opacity: 1; color: var(--text-primary); }
.jx-error-panel-list {
  overflow-y: auto;
  flex: 1;
}
.jx-error-item {
  display: flex;
  gap: 12px;
  padding: 3px 10px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.6;
  border-bottom: 1px solid var(--border);
}
.jx-error-item:last-child { border-bottom: none; }
.jx-error-item:hover { background: color-mix(in srgb, var(--border) 40%, transparent); }
.jx-error-item-active { background: color-mix(in srgb, var(--error) 10%, transparent) !important; }
.jx-error-item-pos  { color: var(--text-primary); opacity: 0.6; white-space: nowrap; flex-shrink: 0; }
.jx-error-item-msg  { color: var(--text-error); }

/* Column-level error marker (wavy underline) */
.jx-err-col {
  text-decoration: underline wavy var(--error);
  text-underline-offset: 2px;
}

/* Input gutter error line marker */
.jx-gutter-error {
  color: var(--error) !important;
  box-shadow: inset 3px 0 0 var(--error);
  cursor: default;
}
.jx-gutter-error-focused { background: rgba(226, 92, 92, 0.15); }
.jx-gutter-error-dimmed  { opacity: 0.3; }

/* Input pane error overlay (sits over the textarea, pointer-events:none) */
#jx-input-wrap { position: relative; }
.jx-input-overlay {
  position: absolute;
  top: 0; bottom: 0; right: 0;
  left: 42px; /* gutter width */
  pointer-events: none;
  overflow: hidden;
  padding-top: 12px;
  padding-left: 8px;
  padding-bottom: 12px;
  box-sizing: border-box;
}
.jx-input-overlay.hidden { display: none; }
.jx-input-overlay-line         { }
.jx-input-overlay-line.error   { background: rgba(226,92,92,0.12); box-shadow: inset 3px 0 0 var(--error); margin-left: -8px; padding-left: 5px; }
.jx-input-overlay-line.focused { background: rgba(226,92,92,0.20); box-shadow: inset 3px 0 0 var(--error); margin-left: -8px; padding-left: 5px; }
.jx-input-overlay-line.dimmed  { background: rgba(226,92,92,0.03); box-shadow: inset 3px 0 0 rgba(226,92,92,0.2); margin-left: -8px; padding-left: 5px; }

/* Dimmed non-focused error lines */
.jx-error-line.jx-error-dimmed {
  background: rgba(226,92,92,0.04);
  border-left-color: rgba(226,92,92,0.2);
  color: var(--text-muted);
}

/* Error annotation in output pane */
.jx-error-line {
  background: rgba(226, 92, 92, 0.12);
  border-left: 3px solid var(--error);
  margin-left: -14px;
  padding-left: 11px;
}
.jx-error-output {
  color: var(--text-error);
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: var(--code-line-h);
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── Buttons ─────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-family: var(--font-ui);
  cursor: pointer;
  transition: var(--transition);
  border: 1px solid var(--border);
  background: var(--bg-surface);
  color: var(--text-secondary);
  white-space: nowrap;
  user-select: none;
}
.btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-dim); }
.btn.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn.primary:hover { background: #5a9ee8; }
.btn.danger { color: var(--error); border-color: var(--error); }
.btn.danger:hover { background: rgba(226,92,92,0.1); }
.btn.active { background: var(--accent-dim); color: var(--accent); border-color: var(--accent); }
#zpl-mode-overlay.active { background: rgba(180,0,0,0.12); color: #c84040; border-color: rgba(180,0,0,0.5); }

/* ── Lucide icons ───────────────────────────────────────── */
.btn svg { width: 13px; height: 13px; vertical-align: -2px; flex-shrink: 0; }
.icon svg { width: 15px; height: 15px; vertical-align: -3px; }
#sidebar-toggle svg { width: 16px; height: 16px; vertical-align: -3px; }

/* ── Badges / tags ──────────────────────────────────────── */
.badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  background: var(--accent-dim);
  color: var(--accent);
  font-family: var(--font-mono);
}
.badge.success { background: rgba(76,175,130,0.12); color: var(--success); }
.badge.error   { background: rgba(226,92,92,0.12);  color: var(--error); }
.badge.warn    { background: rgba(226,169,74,0.12); color: var(--text-warn); }

/* ── Status bar ──────────────────────────────────────────── */
.status-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 14px;
  border-top: 1px solid var(--border);
  background: var(--bg-panel);
  font-size: 11px;
  font-family: var(--font-mono);
  color: var(--text-muted);
  flex-shrink: 0;
  min-height: 26px;
}
.status-bar .status-ok {
  color: var(--success);
  background: color-mix(in srgb, var(--success) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 35%, transparent);
  border-radius: 4px;
  padding: 1px 7px;
  font-weight: 500;
}
.status-bar .status-err {
  color: var(--error);
  background: color-mix(in srgb, var(--error) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--error) 35%, transparent);
  border-radius: 4px;
  padding: 1px 7px;
  font-weight: 500;
}
.status-bar .status-info  { color: var(--accent); }
.status-bar .status-muted { color: var(--text-primary); opacity: 0.75; margin-right: auto; }
.code-output[contenteditable]:focus { outline: none; }

.b64-filetype-tag {
  color: var(--accent);
  font-weight: 500;
}
#b64-output img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
  margin: auto;
  padding: 12px;
}

/* ── Options row ─────────────────────────────────────────── */
.options-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-panel);
  flex-shrink: 0;
  flex-wrap: wrap;
}
.options-row label {
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 12px;
  user-select: none;
}
.options-row input[type=checkbox] { accent-color: var(--accent); }
.options-row select, .options-row input[type=number] {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  padding: 3px 7px;
  font-size: 12px;
  font-family: var(--font-ui);
  outline: none;
}
.options-row select:focus, .options-row input:focus { border-color: var(--accent); }

/* Groups of controls that toggle visibility together as a unit (e.g.
   maxicode.js's #mc-image-controls) need their own flex context — as a
   plain inline span, buttons/labels/inputs inside default to mismatched
   inline baselines, clamping together with no gap and skewing the row's
   height when it wraps. */
.options-row-group {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Render spin buttons using dark-mode native style */
input[type=number] { color-scheme: dark; }
body.light input[type=number] { color-scheme: light; }

/* Range slider — accent colour for thumb/fill; scheme matches current theme */
input[type=range] {
  accent-color: var(--accent);
  color-scheme: dark;
}
body.light input[type=range] { color-scheme: light; }

/* ── Tree view ───────────────────────────────────────────── */
.tree-view { flex: 1; overflow-y: auto; padding: 10px 12px; font-family: var(--font-mono); font-size: 12px; line-height: 1.8; min-height: 0; }
.tree-view:focus { outline: none; }
.tree-node { padding-left: 18px; position: relative; }
.tree-node > .tree-toggle {
  cursor: pointer;
  user-select: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.tree-toggle:hover { color: var(--accent); }
.tree-arrow { font-size: 10px; color: var(--text-muted); transition: transform 150ms; display: inline-block; width: 10px; }
.tree-arrow.open { transform: rotate(90deg); }
.tree-key   { color: #7eb8f7; }
.tree-index { color: var(--text-muted); }
.tree-dash  { color: var(--text-muted); }
.tree-str   { color: #98d9a0; }
.tree-num   { color: #f2a96a; }
.tree-bool  { color: #c792ea; }
.tree-null  { color: #c792ea; }
.tree-children.collapsed { display: none; }
.tree-count { color: var(--text-muted); font-size: 11px; margin-left: 4px; }

/* ── Diff side-by-side overlay ───────────────────────────────── */
.diff-sbs-wrap {
  position: relative;
  flex: 1;
  display: flex;
  overflow: hidden;
}
.diff-sbs-overlay {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  pointer-events: none;
  overflow: scroll;
  padding: 12px 14px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  box-sizing: border-box;
}
.diff-sbs-overlay::-webkit-scrollbar { display: none; }
.diff-sbs-overlay.hidden { display: none; }
.diff-sbs-line   { height: calc(12.5px * var(--code-line-h)); }
.diff-sbs-del    { background: rgba(226, 92, 92, 0.10); }
.diff-sbs-ins    { background: rgba(76, 175, 130, 0.10); }
.diff-sbs-filler { background: repeating-linear-gradient(45deg, rgba(127,127,127,0.07) 0 4px, transparent 4px 8px); }

/* Side-by-side readonly textareas: dim caret area slightly, keep text visible */
textarea.code-input[readonly] { background: var(--bg-base); }

/* ── Diff side-by-side location map ──────────────────────────── */
.diff-minimap {
  flex: 0 0 24px;
  background: var(--bg-surface);
  border-left: 1px solid var(--border);
  position: relative;
  cursor: pointer;
  transition: flex-basis 0.15s;
}
.diff-minimap.hidden { display: none; }
.diff-minimap-track {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
}
.diff-minimap-tick {
  position: absolute;
  left: 2px; right: 2px;
  border-radius: 1px;
  pointer-events: none;
}
.diff-minimap-tick.del { background: #e07b7b; }
.diff-minimap-tick.ins { background: #7dc98a; }
.diff-minimap-viewport {
  position: absolute;
  left: 0; right: 0;
  background: rgba(255,255,255,0.10);
  border: 1px solid var(--accent);
  box-sizing: border-box;
  pointer-events: none;
}

/* ── Diff view ───────────────────────────────────────────── */
.diff-pane-labels {
  display: flex;
  flex-shrink: 0;
  border-top: 1px solid var(--border);
}
.diff-pane-labels .pane-header { border-bottom: none; }

/* ── Diff input pane line-number gutter ──────────────────── */
.diff-ln-gutter {
  width: 40px;
  flex-shrink: 0;
  overflow-y: scroll;
  overflow-x: hidden;
  user-select: none;
  pointer-events: none;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: var(--code-line-h);
  padding: 12px 6px 12px 0;
  text-align: right;
  color: var(--text-muted);
  background: var(--bg-surface);
  border-right: 1px solid var(--border);
  box-sizing: border-box;
}
.diff-ln-gutter::-webkit-scrollbar { display: none; }
.diff-ln-gutter { scrollbar-width: none; }
.diff-ln-gutter div { height: calc(12.5px * var(--code-line-h)); }

/* Inner wrapper that scopes the absolute side-by-side overlay to just the textarea */
.diff-ta-cell {
  position: relative;
  flex: 1;
  display: flex;
  overflow: hidden;
}

/* Bottom split divider — flex item between the two d2h-file-side-diff columns */
#diff-split-divider {
  flex: 0 0 9px;
  align-self: stretch;
  align-items: flex-start; /* grip positions from the top, then sticks */
  z-index: 10;
}
/* Keep the grip dots visible mid-viewport while the diff scrolls */
#diff-split-divider .divider-grip {
  position: sticky;
  top: 50%;
}

/* Hunk-gap expand/collapse button, lives in the @@ row's line-number cell.
   No background of its own — blends with the info row. */
.diff-exp-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--accent);
  padding: 0;
  direction: ltr; /* the line-number cells are rtl */
}
.diff-exp-btn svg { width: 14px; height: 14px; }
.diff-exp-btn:hover { color: var(--text-primary); }

/* Diff pane header status counts (+N added / -N removed) */
#diff-status .status-ok   { color: var(--text-success); }
#diff-status .status-err  { color: var(--text-error); }
#diff-status .status-info { color: var(--text-accent); }

/* Expand/collapse-all button in the Diff pane header — same borderless style */
.diff-fold-btn {
  display: inline-flex;
  align-items: center;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-secondary);
  padding: 0 4px;
  margin-left: 6px;
}
.diff-fold-btn svg { width: 14px; height: 14px; }
.diff-fold-btn:hover { color: var(--accent); }
.diff-fold-btn.hidden { display: none; }
/* diff2html puts a zero-width-space ::after in line-number cells; with the
   block-level button it adds a phantom second line — drop it */
#diff-output td:has(> .diff-exp-btn)::after { content: none; }
/* Cells hosting an expander: no asymmetric padding (keeps the icon centred),
   and the button spans a normal text row so @@ / start / end rows match. */
#diff-output td:has(> .diff-exp-btn),
#diff-output.diff-mode-split .d2h-code-side-linenumber:has(> .diff-exp-btn) { padding: 0; }
.diff-exp-btn { font: inherit; min-height: calc(var(--code-line-h) * 1em); }

#diff-output:focus { outline: none; }
#diff-output-section { display: flex; flex-direction: column; }
#diff-input-section  { min-height: 0; }

/* ── diff2html theme override ──────────────────────────────── */
#diff-output {
  overflow: auto;
  /* Map diff2html CSS vars to our design tokens (both light and dark sets
     point to the same app vars, which already switch per theme). */
  --d2h-bg-color:                           var(--bg-surface);
  --d2h-dark-bg-color:                      var(--bg-surface);
  --d2h-color:                              var(--text-primary);
  --d2h-dark-color:                         var(--text-primary);
  --d2h-dim-color:                          var(--text-secondary);
  --d2h-dark-dim-color:                     var(--text-secondary);
  --d2h-border-color:                       var(--border);
  --d2h-dark-border-color:                  var(--border);
  --d2h-line-border-color:                  var(--border);
  --d2h-dark-line-border-color:             var(--border);
  --d2h-ins-bg-color:                       rgba(76,175,130,.10);
  --d2h-dark-ins-bg-color:                  rgba(76,175,130,.10);
  --d2h-ins-border-color:                   rgba(76,175,130,.30);
  --d2h-dark-ins-border-color:              rgba(76,175,130,.30);
  --d2h-ins-highlight-bg-color:             rgba(76,175,130,.35);
  --d2h-dark-ins-highlight-bg-color:        rgba(76,175,130,.35);
  --d2h-ins-label-color:                    var(--success);
  --d2h-dark-ins-label-color:               var(--success);
  --d2h-del-bg-color:                       rgba(226,92,92,.10);
  --d2h-dark-del-bg-color:                  rgba(226,92,92,.10);
  --d2h-del-border-color:                   rgba(226,92,92,.30);
  --d2h-dark-del-border-color:              rgba(226,92,92,.30);
  --d2h-del-highlight-bg-color:             rgba(226,92,92,.35);
  --d2h-dark-del-highlight-bg-color:        rgba(226,92,92,.35);
  --d2h-del-label-color:                    var(--error);
  --d2h-dark-del-label-color:               var(--error);
  --d2h-change-ins-color:                   rgba(76,175,130,.10);
  --d2h-dark-change-ins-color:              rgba(76,175,130,.10);
  --d2h-change-del-color:                   rgba(226,92,92,.10);
  --d2h-dark-change-del-color:              rgba(226,92,92,.10);
  --d2h-change-label-color:                 var(--text-secondary);
  --d2h-dark-change-label-color:            var(--text-secondary);
  --d2h-info-bg-color:                      var(--bg-active);
  --d2h-dark-info-bg-color:                 var(--bg-active);
  --d2h-info-border-color:                  var(--accent-dim);
  --d2h-dark-info-border-color:             var(--accent-dim);
  --d2h-file-header-bg-color:               var(--bg-hover);
  --d2h-dark-file-header-bg-color:          var(--bg-hover);
  --d2h-file-header-border-color:           var(--border);
  --d2h-dark-file-header-border-color:      var(--border);
  --d2h-empty-placeholder-bg-color:         var(--bg-base);
  --d2h-dark-empty-placeholder-bg-color:    var(--bg-base);
  --d2h-empty-placeholder-border-color:     var(--border);
  --d2h-dark-empty-placeholder-border-color:var(--border);
  --d2h-selected-color:                     var(--bg-active);
  --d2h-dark-selected-color:                var(--bg-active);
  --d2h-moved-label-color:                  var(--accent);
  --d2h-dark-moved-label-color:             var(--accent);
}
#diff-output .d2h-wrapper     { min-width: max-content; }
#diff-output .d2h-file-header { display: none; }
/* Strip diff2html's outer chrome so columns align with the input gutters */
#diff-output .d2h-file-wrapper { border: none; border-radius: 0; margin: 0; }
#diff-output .d2h-code-side-linenumber,
#diff-output .d2h-code-linenumber { border-left: none; }
#diff-output .d2h-file-diff   { overflow: visible; }
#diff-output .d2h-files-diff  { overflow: visible; }
/* Match app font — same metrics as the input textareas (12.5px / 1.65) */
#diff-output .d2h-diff-table  { font-family: var(--font-mono); font-size: 12.5px; line-height: var(--code-line-h); }
#diff-output .d2h-code-line,
#diff-output .d2h-code-side-line,
#diff-output .d2h-code-linenumber,
#diff-output .d2h-code-side-linenumber { line-height: var(--code-line-h); }
/* Anchor absolute line-number cells to their row so they scroll with the table */
#diff-output tr { position: relative; }

/* Unified mode's line-number cell holds TWO numbers (old + new) — twice the gutter width */
#diff-output .d2h-code-linenumber { width: calc(var(--diff-ln-width, 36px) * 2); }
#diff-output .d2h-code-linenumber .line-num1,
#diff-output .d2h-code-linenumber .line-num2 { width: 50%; white-space: nowrap; padding: 0 6px 0 2px; }
#diff-output .d2h-code-line {
  padding: 0 10px 0 calc(var(--diff-ln-width, 36px) * 2 + 10px);
  width: auto;
}
/* A little breathing room around the +/- indicator */
#diff-output .d2h-code-line .d2h-code-line-prefix { margin: 0 1px; }

/* Split mode: column widths follow the input pane divider.
   Both columns share #diff-output as the sole scroll container. */
#diff-output.diff-mode-split .d2h-wrapper    { min-width: unset; width: 100%; }
#diff-output.diff-mode-split .d2h-files-diff { display: flex; width: 100%; overflow: visible; }
#diff-output.diff-mode-split .d2h-file-side-diff:first-child { flex: 0 0 var(--diff-split-left-w, 50%); overflow: visible; }
#diff-output.diff-mode-split .d2h-file-side-diff:last-child  { flex: 1 1 0; min-width: 0; overflow: visible; }

/* Split mode: word-wrap long lines instead of horizontal scrolling.
   The line-number cell becomes a real table column (diff2html makes it
   absolute by default) so table-layout:fixed gives the code cell the rest. */
#diff-output.diff-mode-split .d2h-diff-table { table-layout: fixed; width: 100%; }
#diff-output.diff-mode-split .d2h-code-side-linenumber {
  position: static;
  display: table-cell;
  width: var(--diff-ln-width, 36px);
  vertical-align: top; /* match the input gutters: number at the top of wrapped lines */
  white-space: nowrap;   /* digits must NEVER wrap — a wrapped number doubles the row height */
  padding: 0 6px 0 2px;  /* right padding matches the input gutters' 6px before the border */
}
#diff-output.diff-mode-split .d2h-code-side-line {
  padding: 0 10px;
  width: auto;
  white-space: normal; /* NOT pre-wrap: diff2html's markup has formatting newlines between spans */
  display: flex;       /* keep the +/- prefix and code on one line (ctn is width:100%) */
  align-items: flex-start;
}
/* Fixed-width +/- indicator: uniform gap before the code in all rows */
#diff-output.diff-mode-split .d2h-code-side-line .d2h-code-line-prefix { flex: 0 0 18px; }
#diff-output.diff-mode-split .d2h-code-side-line .d2h-code-line-ctn {
  flex: 1 1 0;
  width: auto;
  min-width: 0;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── Shared: calendar-icon button, used both inline-in-a-field and as a plain
   flex sibling — .calendar-btn carries the common look, .dt-calendar-btn adds
   the absolute-overlay positioning needed only inside a .dt-field-wrap ────── */
.dt-field-wrap { position: relative; }
.calendar-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 4px;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.calendar-btn:hover { color: var(--accent); }
.calendar-btn svg { width: 14px; height: 14px; }
.dt-calendar-btn {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  border-radius: var(--radius-sm);
}
.dt-calendar-btn:hover { background: var(--accent-dim); }
.dt-hidden-date { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; left: 0; top: 0; border: none; }

/* ── Timestamp tool ─────────────────────────────────────── */
.ts-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.ts-card {
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  cursor: pointer;
}
.ts-card:hover { border-color: var(--accent); }
.ts-card:hover .ts-card-value { color: var(--accent); }
.ts-card-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.ts-card-value { font-family: var(--font-mono); font-size: 15px; color: var(--text-primary); word-break: break-all; }

/* ── Timezone tool ──────────────────────────────────────── */
.tz-list { display: flex; flex-direction: column; overflow-y: auto; }
.tz-entry {
  background: transparent;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid var(--border);
}
.tz-input-row:hover { background: transparent; }

/* Input row fields — bordered/filled so they read as editable at a glance,
   with a hover state that invites the click before the user even focuses. */
.tz-edit-field {
  box-sizing: border-box;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 5px 8px;
  outline: none;
  transition: border-color .12s ease;
}
.tz-edit-field:hover { border-color: var(--accent); }
.tz-edit-field:focus { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-dim); }
.tz-entry:hover { background: var(--bg-surface); }
.tz-entry-highlight { background: var(--accent-dim); }
.tz-iana {
  flex: 1;
  min-width: 160px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tz-abbr { width: 56px; flex-shrink: 0; font-family: var(--font-mono); font-size: 11.5px; color: var(--text-secondary); text-align: center; }
.tz-offset { width: 84px; flex-shrink: 0; font-size: 11.5px; color: var(--text-secondary); font-family: var(--font-mono); text-align: center; }
.tz-dst-slot { width: 40px; flex-shrink: 0; display: flex; justify-content: center; }
.tz-dst { font-size: 10px; padding: 1px 5px; border-radius: 3px; background: rgba(226,169,74,0.12); color: var(--text-warn); }
.tz-time { width: 230px; flex-shrink: 0; font-family: var(--font-mono); font-size: 13px; color: var(--text-primary); }
.tz-remove {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px 4px;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.tz-remove:hover { color: var(--error); }
.tz-remove svg { width: 14px; height: 14px; }
.tz-empty { padding: 24px 14px; text-align: center; color: var(--text-muted); font-size: 12.5px; }

/* ── Toasts ─────────────────────────────────────────────── */
#toast-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 1000;
  pointer-events: none;
}
.toast {
  background: var(--bg-active);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 14px;
  font-size: 12px;
  color: var(--text-primary);
  animation: toastIn 200ms ease;
  pointer-events: all;
  max-width: 280px;
}
.toast.ok     { border-left: 3px solid var(--success); }
.toast.error  { border-left: 3px solid var(--error); }
.toast.info   { border-left: 3px solid var(--accent); }
@keyframes toastIn { from { opacity:0; transform: translateY(8px); } to { opacity:1; transform: none; } }

/* ── Utility ─────────────────────────────────────────────── */
.hidden { display: none !important; }

/* ── ZPL Per-page sections ────────────────────────────────── */
#zpl-pages-container {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
  padding-bottom: 24px;
}
.zpl-page-section {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0 auto; /* centers when smaller than wrap; clamps to left edge when overflowing so left side stays scrollable */
}
.zpl-page-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
  flex-wrap: wrap;
}
.btn-label-compact { display: none; }
.zpl-page-header.compact .btn-label { display: none; }
.zpl-page-header.compact .btn-label-compact { display: inline; }
.zpl-page-header.compact-actions .zpl-pg-copy .btn-label,
.zpl-page-header.compact-actions .zpl-pg-dl .btn-label,
.zpl-page-header.compact-actions .zpl-pg-print .btn-label { display: none; }

.zpl-page-label {
  font-size: 12px;
  font-family: var(--font-mono);
  font-weight: 400;
  color: var(--text-primary);
  margin-right: 4px;
}
.btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}
.zpl-page-canvas {
  display: block;
  align-self: center;
  border: 1px solid var(--border);
  border-radius: 0 0 var(--radius) var(--radius);
}
.zpl-page-section:not(:has(.zpl-page-header)) .zpl-page-canvas {
  border-radius: var(--radius);
}
.zpl-page-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 0 4px;
}
#zpl-render-spinner {
  display: none;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  z-index: 10;
  pointer-events: none;
}
#zpl-render-spinner::after {
  content: '';
  width: 32px;
  height: 32px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: zpl-spin 0.7s linear infinite;
}
@keyframes zpl-spin { to { transform: rotate(360deg); } }

/* Labelary warning modal */
.zpl-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.zpl-modal {
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
  max-width: 420px;
  width: 90%;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.zpl-modal-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
}
.zpl-modal-body {
  font-size: 13px;
  color: var(--text-secondary);
  display: flex;
  flex-direction: column;
  gap: 10px;
  line-height: 1.6;
}
.zpl-modal-body p { margin: 0; }
.zpl-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
.btn-primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
.btn-primary:hover {
  opacity: 0.88;
}

/* ── JWT tool ─────────────────────────────────────────────── */
:root {
  --jwt-header:  #e05c7a;
  --jwt-payload: #a87ad6;
  --jwt-sig:     #3ab5d8;
}
body.light {
  --jwt-header:  #c0244a;
  --jwt-payload: #7a28b8;
  --jwt-sig:     #1478aa;
}
.jwt-seg-header  { color: var(--jwt-header); }
.jwt-seg-payload { color: var(--jwt-payload); }
.jwt-seg-sig     { color: var(--jwt-sig); }
.jwt-dot         { color: var(--text-secondary); user-select: none; }

/* Contenteditable token display — matches textarea.code-input look */
div.jwt-token-display {
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.55;
  padding: 10px 12px;
  background: var(--bg-surface);
  white-space: pre-wrap;
  word-break: break-all;
  overflow: auto;
  flex: 1;
  min-height: 0;
  outline: none;
  border: none;
  transition: background var(--transition);
  cursor: text;
}
div.jwt-token-display:focus { background: var(--bg-surface); }
div.jwt-token-display:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  pointer-events: none;
}

/* Signature secret input */
.jwt-secret-wrap {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px 6px;
  flex-shrink: 0;
}
.jwt-secret-input {
  width: 100%;
  font-family: var(--font-mono);
  font-size: 11px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  color: var(--text-primary);
  outline: none;
  transition: border-color var(--transition);
  box-sizing: border-box;
}
.jwt-secret-input:focus { border-color: var(--accent); }
.jwt-secret-input::placeholder { color: var(--text-muted); }

/* ── Find Bar ─────────────────────────────────────────────────────────────── */
.find-bar {
  display: none;
  position: fixed;
  z-index: 9999;
  align-items: center;
  gap: 4px;
  padding: 5px 8px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 4px 16px rgba(0,0,0,.35);
  min-width: 280px;
}
.find-bar.fb-visible { display: flex; }

.fb-input {
  flex: 1;
  font-size: 13px;
  font-family: var(--font-mono);
  background: var(--bg-base);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 3px 8px;
  outline: none;
  min-width: 0;
  transition: border-color var(--transition);
}
.fb-input:focus { border-color: var(--accent); }

.fb-count {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  min-width: 52px;
  text-align: center;
}
.fb-no-results { color: var(--danger, #e05c5c); }

.fb-btn, .fb-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.fb-btn:hover, .fb-close:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
  border-color: var(--border);
}
.fb-btn svg, .fb-close svg { width: 14px; height: 14px; }

/* Textarea find overlay */
.fb-ta-overlay {
  position: absolute;
  pointer-events: none;
  overflow: hidden;
  color: transparent;
  background: transparent;
  white-space: pre-wrap;
  word-wrap: break-word;
  box-sizing: border-box;
  z-index: 2;
}

/* Match highlights */
.fb-mark {
  background: rgba(255, 213, 0, 0.45);
  border-radius: 2px;
  color: inherit;
}
.fb-mark-cur {
  background: rgba(255, 140, 0, 0.75);
  color: var(--bg-base);
  border-radius: 2px;
  outline: 2px solid rgba(255, 140, 0, 0.9);
}

/* Light theme overrides */
body.light .fb-mark     { background: rgba(255, 213, 0, 0.55); }
body.light .fb-mark-cur { background: rgba(255, 120, 0, 0.75); color: #fff; }

/* ── Image to ZPL ────────────────────────────────────────── */
.itz-dropzone {
  flex: 1;
  display: flex;
  /* No align-items/justify-content:center — flex-centering clips the
     start-side scrollable overflow once the image is zoomed in and panned.
     margin:auto on the two possible children (below) centers them when they
     fit, while still allowing the full pan range when they don't. */
  border: 2px dashed var(--border);
  border-radius: var(--radius-sm);
  margin: 10px;
  cursor: pointer;
  position: relative;
  overflow: auto;
  transition: border-color 0.15s, background 0.15s;
}
.itz-dropzone.drag-over {
  border-color: var(--accent);
  background: var(--accent-dim);
}
.itz-dropzone.panning {
  cursor: grabbing;
  user-select: none;
}
#itz-dropzone-empty {
  margin: auto;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
  pointer-events: none;
  padding: 20px;
}
#itz-dropzone-empty i { width: 32px; height: 32px; margin-bottom: 8px; }

#itz-source-wrap {
  position: relative;
  display: inline-flex;
  margin: auto;
  cursor: grab;
}
#itz-source-canvas {
  /* Sized explicitly via JS (fit-to-pane baseline × Ctrl+scroll zoom) — no
     max-width/max-height clamp, which would otherwise silently override the
     zoom-driven size and make Ctrl+scroll appear to do nothing. */
  display: block;
}
/* Crop handles — always visible once an image is loaded. Dragging a handle
   resizes #itz-crop-frame; dim divs darken the (excluded) area outside it
   without ever touching the underlying image data. */
.itz-crop-dim {
  position: absolute;
  background: rgba(0, 0, 0, 0.45);
  pointer-events: none;
}
#itz-crop-frame {
  position: absolute;
  border: 1.5px dashed var(--accent);
  box-sizing: border-box;
  pointer-events: none; /* only the handles themselves are interactive */
}
.itz-crop-handle {
  /* Hitbox is larger than the visible dot (drawn via ::after) so the handle
     is easier to grab without looking oversized. */
  position: absolute;
  width: 22px;
  height: 22px;
  transform: translate(-50%, -50%);
  pointer-events: auto;
}
.itz-crop-handle::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 11px;
  height: 11px;
  background: var(--accent);
  border: 1.5px solid #fff;
  border-radius: 2px;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.itz-crop-handle[data-pos="nw"] { top: 0;   left: 0;   cursor: nwse-resize; }
.itz-crop-handle[data-pos="n"]  { top: 0;   left: 50%; cursor: ns-resize; }
.itz-crop-handle[data-pos="ne"] { top: 0;   left: 100%; cursor: nesw-resize; }
.itz-crop-handle[data-pos="e"]  { top: 50%; left: 100%; cursor: ew-resize; }
.itz-crop-handle[data-pos="se"] { top: 100%; left: 100%; cursor: nwse-resize; }
.itz-crop-handle[data-pos="s"]  { top: 100%; left: 50%; cursor: ns-resize; }
.itz-crop-handle[data-pos="sw"] { top: 100%; left: 0;   cursor: nesw-resize; }
.itz-crop-handle[data-pos="w"]  { top: 50%; left: 0;   cursor: ew-resize; }

.itz-preview-canvas {
  image-rendering: pixelated;
  flex-shrink: 0;
  background: #fff;
  border: 1px solid var(--border);
  /* margin:auto (not align-items/justify-content:center on the parent) so the
     canvas still centers when it fits, but panning can reach every edge once
     it overflows — flex/grid centering otherwise clips the start-side
     overflow out of scroll range. */
  margin: auto;
}

#itz-preview-section {
  cursor: grab;
}
#itz-preview-section.panning {
  cursor: grabbing;
  user-select: none;
}

.itz-stats {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
}

.itz-threshold-group {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* MaxiCode reader */
#mc-dropzone-empty {
  margin: auto;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
  pointer-events: none;
  padding: 20px;
}
#mc-dropzone-empty i { width: 32px; height: 32px; margin-bottom: 8px; }
#mc-preview-wrap {
  position: relative;
  display: inline-flex;
  margin: auto;
  cursor: grab;
}
#mc-preview-canvas {
  /* Sized explicitly via JS (fit-to-pane baseline × Ctrl+scroll zoom) — no
     max-width/max-height clamp, which would otherwise override the
     zoom-driven size. */
  display: block;
  background: #fff;
  border: 1px solid var(--border);
}
/* Crop handles — reuses .itz-crop-dim / .itz-crop-handle (shared visuals),
   but the frame border itself is ID-scoped in imageToZpl's CSS, so it needs
   its own rule here. */
#mc-crop-frame {
  position: absolute;
  border: 1.5px dashed var(--accent);
  box-sizing: border-box;
  /* auto (not none): lets dragging inside the crop move it — see
     initCropMove in maxicode.js. Dragging outside it (over the dimmed
     areas, which stay pointer-events:none) still pans the view. */
  pointer-events: auto;
  cursor: move;
}
.mc-threshold-group {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Rotate button, floated over the image preview instead of the toolbar
   (which has no room left) — anchored to #mc-pane-left (position:relative,
   set inline), NOT #mc-dropzone itself, so it stays put in the corner
   rather than scrolling away when the image is panned. Inset well past
   the top-right crop handle's hitbox so the two don't overlap. */
.mc-rotate-btn {
  position: absolute;
  top: 10px;
  right: 34px;
  z-index: 20;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 22, 28, 0.75);
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--text-primary);
  cursor: pointer;
  transition: var(--transition);
}
.mc-rotate-btn:hover { border-color: var(--accent); color: var(--accent); background: rgba(20, 22, 28, 0.9); }
.mc-rotate-btn svg { width: 15px; height: 15px; }
/* Crop-handle magnifier loupe — position:fixed and appended at the top
   level (see index.html) so it floats above the dropzone's own scroll/pan
   clipping instead of being cut off by it. Shown only while a crop handle
   is actively being dragged — see initCropHandles in maxicode.js. */
.mc-magnifier {
  position: fixed;
  z-index: 1000;
  width: 160px;
  height: 160px;
  overflow: hidden;
  border: 2px solid var(--accent);
  border-radius: var(--radius-sm);
  box-shadow: 0 4px 16px rgba(0,0,0,0.45);
  pointer-events: none;
  display: none;
}
.mc-magnifier.visible { display: block; }
.mc-magnifier canvas { display: block; }
/* Crosshair marking the exact handle position — a short, thick blue plus
   rather than a full-width hairline, so it reads clearly at a glance. The
   same mark (via #mc-crop-crosshair) is also overlaid on the real preview
   at the handle's actual position while dragging, so both views agree. */
.mc-magnifier::before, .mc-magnifier::after,
#mc-crop-crosshair::before, #mc-crop-crosshair::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--accent);
}
.mc-magnifier::before, #mc-crop-crosshair::before { width: 24px; height: 5px; margin-top: -2.5px; margin-left: -12px; }
.mc-magnifier::after,  #mc-crop-crosshair::after  { width: 5px; height: 24px; margin-top: -12px; margin-left: -2.5px; }
#mc-crop-crosshair {
  position: absolute;
  width: 24px;
  height: 24px;
  transform: translate(-50%, -50%);
  pointer-events: none;
  display: none;
  z-index: 5;
}
#mc-crop-crosshair.visible { display: block; }
.mc-results {
  flex: 1;
  overflow: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.mc-empty {
  margin: auto;
  color: var(--text-muted);
  font-size: 13px;
  text-align: center;
  max-width: 320px;
}
.mc-result-title {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.mc-result-text {
  display: block;
  width: 100%;
  max-height: 260px;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-sizing: border-box;
  white-space: pre-wrap;
  word-break: break-word;
}
.mc-result-text:focus { outline: 1px solid var(--accent); border-color: var(--accent); }
.mc-fields {
  border-collapse: collapse;
  margin-bottom: 10px;
  font-size: 12px;
}
.mc-fields caption {
  caption-side: top;
  text-align: left;
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.mc-fields th, .mc-fields td {
  border: 1px solid var(--border);
  padding: 4px 8px;
  text-align: left;
}
.mc-fields th {
  color: var(--text-secondary);
  font-weight: 600;
  white-space: nowrap;
}
.mc-fields td {
  font-family: var(--font-mono);
}
