/* LabelForge — print-shop workbench. Ink machine on the left, paper bench
   on the right, label as a physical object under inch rulers. Mono type
   throughout: this is a tool that makes barcodes. */

:root {
  --ink: #16130e;
  --ink-2: #2a251d;
  --ink-3: #5c5344;
  --paper: #f5f1e8;
  --paper-2: #ece5d6;
  --line: #d8cfbc;
  --accent: #e0561f;
  --accent-dark: #b8431a;
  --ok: #3a7d44;
  --warn: #a87708;
  --err: #b3261e;
  --rail: #1d1913;
  --rail-2: #292318;
  --rail-line: #3b3425;
  --rail-text: #ece5d4;
  --rail-muted: #9c917b;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --shadow-label: 0 1px 2px rgba(22, 19, 14, .18), 0 8px 24px rgba(22, 19, 14, .16);
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink);
  background: var(--paper);
  display: flex;
  flex-direction: column;
}

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

/* ---------- top bar ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 14px;
  height: 52px;
  background: var(--ink);
  color: var(--paper);
  border-bottom: 3px solid var(--accent);
  flex: none;
}

.brand { display: flex; align-items: baseline; gap: 10px; min-width: 0; }

.brand-bars { width: 26px; height: 18px; fill: var(--paper); align-self: center; flex: none; }
.brand-bars .bar-accent { fill: var(--accent); }

.brand h1 {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: .14em;
  white-space: nowrap;
}
.brand h1 em { font-style: normal; color: var(--accent); }

.brand-sub {
  color: #8d8470;
  font-size: 11px;
  letter-spacing: .04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar-actions { display: flex; gap: 8px; flex: none; }

/* ---------- buttons ---------- */

.btn {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .06em;
  padding: 6px 12px;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--ink-2);
  border-radius: 2px;
  cursor: pointer;
  box-shadow: 0 1px 0 rgba(22,19,14,.25);
  transition: transform .05s ease, box-shadow .05s ease, background .12s ease;
}
.btn:hover { background: #fff; }
.btn:active { transform: translateY(1px); box-shadow: none; }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }

.btn-accent {
  background: var(--accent);
  border-color: var(--accent-dark);
  color: #fff;
}
.btn-accent:hover { background: #ef6228; }

.btn-ghost {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}
.btn-ghost:hover { background: rgba(22,19,14,.07); }

/* ---------- layout ---------- */

.workbench {
  flex: 1;
  display: grid;
  grid-template-columns: 340px 1fr;
  min-height: 0;
}

/* ---------- chat rail (the machine) ---------- */

.chat-rail {
  background: var(--rail);
  color: var(--rail-text);
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--rail-line);
}

.rail-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--rail-line);
  flex: none;
}

.rail-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 6px rgba(224, 86, 31, .8);
  animation: pulse 3s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: .45; } }

.rail-head h2 {
  margin: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--rail-muted);
}

.chat-log {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  scrollbar-width: thin;
  scrollbar-color: var(--rail-line) transparent;
}

.msg {
  max-width: 92%;
  padding: 8px 10px;
  border-radius: 3px;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  animation: msg-in .18s ease-out;
}
@keyframes msg-in { from { opacity: 0; transform: translateY(4px); } }

.msg-user {
  align-self: flex-end;
  background: var(--accent);
  color: #fff;
  border-radius: 3px 3px 0 3px;
}

.msg-assistant {
  align-self: flex-start;
  background: var(--rail-2);
  border: 1px solid var(--rail-line);
  border-radius: 3px 3px 3px 0;
}

.msg-note {
  align-self: center;
  font-size: 11px;
  color: var(--rail-muted);
  background: none;
  padding: 2px 0;
}

.msg-html-badge {
  display: inline-block;
  margin-top: 6px;
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid var(--accent-dark);
  border-radius: 2px;
  padding: 1px 5px;
}

.chat-empty {
  margin: auto;
  text-align: center;
  color: var(--rail-muted);
  font-size: 12px;
  padding: 0 18px;
}
.chat-empty strong { color: var(--rail-text); font-size: 14px; }

.starters {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 14px;
  text-align: left;
}
.starter {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.35;
  text-align: left;
  color: var(--rail-text);
  background: var(--rail-2);
  border: 1px solid var(--rail-line);
  border-radius: 3px;
  padding: 8px 10px;
  cursor: pointer;
  transition: border-color .12s ease, background .12s ease;
}
.starter::before { content: "› "; color: var(--accent); font-weight: 700; }
.starter:hover { border-color: var(--accent); background: #2f2920; }
.starter:active { transform: translateY(1px); }

.chat-status {
  flex: none;
  padding: 6px 14px;
  font-size: 11px;
  color: var(--rail-muted);
  border-top: 1px solid var(--rail-line);
}
.chat-status.error { color: #e08d85; }

/* thinking shimmer: three little bars like a barcode being read */
.thinking { display: inline-flex; gap: 3px; align-items: center; }
.thinking i {
  width: 3px; height: 12px;
  background: var(--accent);
  animation: scan 1s ease-in-out infinite;
}
.thinking i:nth-child(2) { animation-delay: .15s; height: 9px; }
.thinking i:nth-child(3) { animation-delay: .3s; }
@keyframes scan { 50% { opacity: .25; transform: scaleY(.55); } }

.composer {
  flex: none;
  display: flex;
  gap: 8px;
  padding: 12px 14px;
  border-top: 1px solid var(--rail-line);
  background: var(--rail-2);
}

.composer textarea {
  flex: 1;
  resize: none;
  background: var(--rail);
  color: var(--rail-text);
  border: 1px solid var(--rail-line);
  border-radius: 2px;
  padding: 8px;
  min-height: 38px;
}
.composer textarea:focus { outline: 1px solid var(--accent); outline-offset: 0; }
.composer textarea::placeholder { color: var(--rail-muted); }

/* ---------- bench (preview + editor) ---------- */

.bench {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}

.bench-toolbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 8px 14px;
  background: var(--paper-2);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
}

.ctl { display: inline-flex; align-items: center; gap: 6px; }
.ctl > span:first-child {
  font-size: 10px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.ctl select, .ctl input[type="number"] {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 4px 6px;
  font-size: 12px;
}
.ctl input[type="number"] { width: 64px; }

/* affiliate "Order on Amazon.com" link — sits just right of the size control */
.buy-link {
  font-size: 12px;
  font-style: italic;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px dotted var(--accent);
  padding-bottom: 1px;
  white-space: nowrap;
}
.buy-link:hover { color: var(--accent-dark); border-bottom-style: solid; }

/* push the zoom control to the far right of the toolbar */
.zoom-ctl { margin-left: auto; }

/* the stage: graph paper, rulers, label */

.stage {
  flex: 1;
  position: relative;
  min-height: 140px;
  overflow: hidden;
  --inch: 96px; /* set by JS to 96 * zoom */
  background:
    linear-gradient(to right, rgba(22,19,14,.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(22,19,14,.05) 1px, transparent 1px),
    linear-gradient(to right, rgba(22,19,14,.09) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(22,19,14,.09) 1px, transparent 1px),
    var(--paper);
  background-size:
    calc(var(--inch) / 8) calc(var(--inch) / 8),
    calc(var(--inch) / 8) calc(var(--inch) / 8),
    var(--inch) var(--inch),
    var(--inch) var(--inch);
}

.ruler {
  position: absolute;
  z-index: 2;
  background: var(--paper-2);
  pointer-events: none;
}

.ruler-h {
  top: 0; left: 18px; right: 0; height: 18px;
  border-bottom: 1px solid var(--line);
  background-image:
    repeating-linear-gradient(to right,
      var(--ink-3) 0 1px, transparent 1px calc(var(--inch) / 8)),
    repeating-linear-gradient(to right,
      var(--ink) 0 1px, transparent 1px var(--inch));
  background-size: 100% 6px, 100% 12px;
  background-position: bottom left, bottom left;
  background-repeat: repeat-x;
}

.ruler-v {
  top: 18px; left: 0; bottom: 0; width: 18px;
  border-right: 1px solid var(--line);
  background-image:
    repeating-linear-gradient(to bottom,
      var(--ink-3) 0 1px, transparent 1px calc(var(--inch) / 8)),
    repeating-linear-gradient(to bottom,
      var(--ink) 0 1px, transparent 1px var(--inch));
  background-size: 6px 100%, 12px 100%;
  background-position: top right, top right;
  background-repeat: repeat-y;
}

.stage-inner {
  position: absolute;
  inset: 18px 0 0 18px;
  display: grid;
  place-items: center;
  overflow: auto;
  padding: 24px;
}

/* Thermal die-cut labels have ~0.1in rounded corners; scale the radius
   with zoom and clip the content like the cutter would. The radius lives
   on both the sheet (shadow shape) and the iframe (content clip) so the
   dims caption below the sheet stays outside any overflow clipping. */
.label-sheet {
  position: relative;
  background: transparent;
  box-shadow: var(--shadow-label);
  flex: none;
  border-radius: calc(var(--inch, 96px) * 0.1);
}

.label-sheet iframe {
  display: block;
  border: 0;
  background: #fff;
  /* 0.1in at base scale (9.6px); the zoom transform scales it to match
     the sheet's calc(var(--inch) * 0.1). */
  border-radius: 9.6px;
}

.label-dims {
  position: absolute;
  right: 0;
  bottom: -22px;
  font-size: 10px;
  letter-spacing: .08em;
  color: var(--ink-3);
  white-space: nowrap;
}

/* ---------- editor ---------- */

.editor {
  flex: none;
  display: flex;
  flex-direction: column;
  border-top: 2px solid var(--ink);
  background: var(--paper-2);
  max-height: 80%;
  height: 240px;
  min-height: 0;
}
.editor.collapsed { height: auto !important; }
.editor.collapsed .editor-body { display: none; }
.editor.collapsed .splitter { display: none; }
.editor.collapsed .caret { transform: rotate(-90deg); }

.splitter {
  flex: none;
  height: 8px;
  margin-top: -2px; /* overlap the border so the grab area includes it */
  cursor: row-resize;
  position: relative;
  touch-action: none;
}
.splitter::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 3px;
  width: 44px;
  height: 3px;
  transform: translateX(-50%);
  border-radius: 2px;
  background: var(--line);
}
.splitter:hover::before,
.splitter:focus-visible::before,
.splitter.dragging::before { background: var(--accent); }
.splitter:focus-visible { outline: 1px solid var(--accent); }

.editor-bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 6px 14px;
  flex-wrap: wrap;
}

.editor-title {
  background: none;
  border: 0;
  padding: 2px 0;
  cursor: pointer;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.caret { display: inline-block; transition: transform .12s ease; }

.validation { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--ink-3); }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.dot-ok { background: var(--ok); }
.dot-warn { background: var(--warn); }
.dot-err { background: var(--err); }

.editor-actions { margin-left: auto; display: inline-flex; gap: 8px; }

.editor-body { flex: 1; display: flex; flex-direction: column; min-height: 0; }

/* The code editor is a transparent textarea over a highlighted <pre>
   underlay. Both layers MUST share identical font metrics, padding, and
   whitespace handling or the caret drifts off the colored text. */
.codewrap {
  flex: 1;
  position: relative;
  min-height: 60px;
  border-top: 1px solid var(--line);
  background: var(--ink);
}

.codewrap textarea,
.codewrap pre.hl {
  position: absolute;
  inset: 0;
  margin: 0;
  border: 0;
  padding: 10px 14px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  tab-size: 2;
  /* Soft-wrap so a minified one-liner wraps instead of scrolling off-screen.
     Both layers must wrap identically (the highlight underlay sits under the
     transparent textarea): same wrapping mode, same break rule, and a stable
     scrollbar gutter so the text width — and thus the wrap points — match. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-gutter: stable;
  /* Disable ligatures/kerning so the textarea and the highlighted underlay
     advance every glyph identically — otherwise the pre would ligate
     sequences like :// or /> and the caret would drift off the colored text. */
  font-variant-ligatures: none;
  font-feature-settings: "liga" 0, "calt" 0;
  font-kerning: none;
}

.codewrap textarea {
  resize: none; /* the splitter resizes the whole pane instead */
  background: transparent;
  color: transparent;
  caret-color: var(--accent);
  z-index: 1;
}
.codewrap textarea::placeholder { color: var(--rail-muted); }
.codewrap textarea::selection { background: rgba(224, 86, 31, .30); color: transparent; }
.codewrap textarea:focus { outline: none; }

.codewrap pre.hl {
  pointer-events: none;
  overflow: hidden;
  color: var(--paper);
}

/* The highlighted text sits in a <code>, whose UA rule (code{font-family:
   monospace}) would otherwise override our font and trigger the monospace
   font-size bug — making the underlay a different font/size than the textarea
   and drifting the caret. Force it to inherit the real editor font + size. */
.codewrap pre.hl code {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  letter-spacing: inherit;
}

/* token palette — warm ink-and-ribbon scheme */
.tok-punct { color: #8d8470; }
.tok-tag { color: #e8a87c; }
.tok-placeholder { color: #8fc98f; font-weight: 700; }
.tok-bad { color: #e0635f; text-decoration: underline wavy #e0635f 1px; }
.tok-attr { color: #d9c178; }
.tok-str { color: #b8d8b8; }
.tok-junk { color: #8d8470; font-style: italic; }
.tok-comment { color: #6f6452; font-style: italic; }
.tok-prop { color: #d9c178; }
.tok-num { color: #c9a3e0; }
.tok-sel { color: #e8a87c; }

.issues {
  flex: none;
  margin: 0;
  padding: 6px 14px;
  list-style: none;
  max-height: 96px;
  overflow-y: auto;
  background: #f8e8e4;
  border-top: 1px solid #e3b8ae;
}
.issues li { color: var(--err); font-size: 11px; padding: 1px 0; }
.issues li::before { content: "▸ "; }

/* ---------- tab bar (mobile) ---------- */

.tabbar { display: none; }

/* ---------- templates modal ---------- */

.modal {
  width: min(880px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  border: 2px solid var(--ink);
  border-radius: 3px;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono);
}
.modal::backdrop { background: rgba(22, 19, 14, .55); }
.modal.modal-sm { width: min(420px, calc(100vw - 32px)); }

.affiliate-body { padding: 16px 20px 18px; }
.affiliate-body p { margin: 0 0 16px; font-size: 13px; line-height: 1.5; }
.affiliate-actions { display: flex; justify-content: flex-end; gap: 8px; }
.affiliate-actions .btn { text-decoration: none; }

.modal-head {
  position: relative;
  padding: 16px 20px 12px;
  border-bottom: 1px solid var(--line);
}
.modal-head h2 {
  margin: 0 0 2px;
  font-size: 15px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.modal-head p { margin: 0; font-size: 12px; color: var(--ink-3); }
.modal-head .modal-aside { margin-top: 6px; }
.modal-head a { color: var(--accent); text-decoration: none; }
.modal-head a:hover { text-decoration: underline; }
.modal-head #modal-close { position: absolute; top: 10px; right: 10px; }

.template-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px;
  padding: 16px 20px 20px;
  overflow-y: auto;
  max-height: calc(100vh - 200px);
}

.tcard {
  border: 1px solid var(--line);
  border-radius: 3px;
  background: #fff;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.tcard-preview {
  position: relative;
  height: 120px;
  background:
    linear-gradient(to right, rgba(22,19,14,.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(22,19,14,.05) 1px, transparent 1px),
    var(--paper-2);
  background-size: 12px 12px, 12px 12px;
  display: grid;
  place-items: center;
  overflow: hidden;
}

.tcard-thumb {
  position: relative;
  overflow: hidden;
  box-shadow: 0 1px 4px rgba(22,19,14,.25);
  background: #fff;
}

.tcard-preview iframe {
  border: 0;
  background: #fff;
  pointer-events: none;
  border-radius: 9.6px; /* die-cut corners; scales with the transform */
}

.tcard-info { padding: 8px 10px 10px; display: flex; flex-direction: column; gap: 4px; }

.tcard-name { font-weight: 700; font-size: 12px; display: flex; align-items: center; gap: 6px; }

.tcard-badge {
  font-size: 9px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #fff;
  background: var(--accent);
  border-radius: 2px;
  padding: 1px 5px;
}

.tcard-desc { font-size: 11px; color: var(--ink-3); min-height: 30px; }
.tcard-meta { font-size: 10px; color: var(--ink-3); letter-spacing: .06em; }
.tcard .btn { align-self: flex-start; margin-top: 4px; }

/* ---------- toast ---------- */

.toast {
  position: fixed;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--ink);
  color: var(--paper);
  border-left: 3px solid var(--accent);
  padding: 9px 16px;
  font-size: 12px;
  border-radius: 2px;
  box-shadow: 0 6px 20px rgba(22,19,14,.35);
  z-index: 50;
  animation: msg-in .18s ease-out;
}

.muted { color: var(--ink-3); }

/* ---------- mobile ---------- */

@media (max-width: 1023px) {
  .brand-sub { display: none; }
  .topbar { padding: 0 10px; gap: 8px; }
  .topbar .btn { padding: 5px 8px; font-size: 11px; }
  .bench-toolbar { gap: 8px; padding: 6px 10px; }

  .workbench { grid-template-columns: 1fr; }

  .chat-rail, .bench { display: none; }
  body[data-tab="chat"] .chat-rail { display: flex; }
  body[data-tab="preview"] .bench, body[data-tab="editor"] .bench { display: flex; }
  body[data-tab="preview"] .editor { display: none; }
  body[data-tab="editor"] .stage, body[data-tab="editor"] .bench-toolbar { display: none; }
  body[data-tab="editor"] .editor { max-height: none; flex: 1; }

  .tabbar {
    display: flex;
    flex: none;
    background: var(--ink);
    border-top: 1px solid var(--rail-line);
  }
  .tabbar button {
    flex: 1;
    background: none;
    border: 0;
    color: var(--rail-muted);
    padding: 12px 0 14px;
    font-size: 11px;
    letter-spacing: .18em;
    text-transform: uppercase;
    cursor: pointer;
    border-top: 2px solid transparent;
  }
  .tabbar button.active { color: var(--paper); border-top-color: var(--accent); }

  .editor { max-height: 55%; }
  .splitter { display: none; } /* tabs replace the splitter on mobile */
  body[data-tab="editor"] .editor { height: auto !important; }

  /* iOS Safari auto-zooms when focusing a control whose font-size is < 16px,
     which on a phone shoves the Send button off-screen. 16px stops the zoom
     without disabling pinch-zoom (kept for accessibility). */
  .composer textarea,
  .codewrap textarea,
  .ctl select,
  .ctl input[type="number"],
  #chat-input,
  #editor { font-size: 16px; }
}

/* Use the dynamic viewport height on mobile so the layout (and the Send
   button) stay within the visible area when the on-screen keyboard opens. */
@media (max-width: 1023px) {
  @supports (height: 100dvh) {
    html, body { height: 100dvh; }
  }
}

/* ---------- print: just the label, at actual physical size ---------- */
@media print {
  /* Hide all the app chrome — only the label prints. */
  .topbar, .chat-rail, .bench-toolbar, .editor, .tabbar,
  .ruler, .label-dims, .toast, dialog { display: none !important; }

  /* Collapse the layout so the label sits at the page origin, untransformed. */
  html, body, .workbench, .bench, .stage, .stage-inner, .label-sheet {
    display: block !important;
    position: static !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    width: auto !important;
    height: auto !important;
    min-height: 0 !important;
    overflow: visible !important;
    background: #fff !important;
    box-shadow: none !important;
  }
  .stage { background: none !important; }
  .label-sheet { border-radius: 0 !important; }

  /* Render the preview iframe at the label's true inch dimensions (no zoom),
     matching the @page size set just before printing. */
  #preview {
    display: block !important;
    transform: none !important;
    border: 0 !important;
    border-radius: 0 !important;
    width: var(--print-w, 2.25in) !important;
    height: var(--print-h, 1.25in) !important;
  }
}
