/*
 * The invoice editor application shell: left form panel + sticky right
 * preview on desktop, stacked tabs on mobile. Scoped to `.app-shell` so it
 * never leaks into marketing pages.
 */

.app-shell {
  display: grid;
  grid-template-columns: minmax(360px, 460px) 1fr;
  gap: var(--space-5);
  align-items: start;
  padding-block: var(--space-5);
}

.app-toolbar {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  position: sticky;
  top: calc(var(--header-height) + var(--space-3));
  z-index: 50;
}
.app-toolbar .toolbar-group { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.autosave-status { font-size: 0.8125rem; color: var(--color-text-muted); }

.editor-panel {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  min-width: 0;
}

.editor-panel-header {
  background: var(--color-bg-subtle);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-5);
}
.editor-panel-header .field { margin-bottom: 0; }
.editor-panel-header label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
}

/* Compact form density inside the editor. This is a data-entry-dense
   panel with 10 sections — the spacious, extra-touch-friendly sizing in
   components.css (44px targets) is right for marketing/contact forms
   elsewhere, but here it wastes vertical space and forces excess
   scrolling. 36px still clears the WCAG 2.2 AA (24px) target-size
   minimum with room to spare. */
.editor-panel .field { margin-bottom: var(--space-3); }
.editor-panel .field label,
.editor-panel .field .field-label { margin-bottom: 3px; font-size: 0.75rem; }
.editor-panel .field .field-hint { margin-top: 3px; font-size: 0.75rem; }
.editor-panel .input,
.editor-panel .select,
.editor-panel .textarea {
  min-height: 36px;
  padding: 7px 10px;
  font-size: 0.875rem;
}
.editor-panel .textarea { min-height: 64px; }
.editor-panel .input-row { gap: var(--space-2); }
.editor-panel input[type="color"] { min-height: 36px; padding: 3px; }
.editor-panel .field-group-title { margin: var(--space-4) 0 var(--space-2); padding-top: var(--space-3); }
.editor-panel .field-group-title:first-child { margin-top: 0; padding-top: 0; }

.preview-panel {
  position: sticky;
  top: calc(var(--header-height) + 76px);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

.preview-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.zoom-control { align-items: center; }
.zoom-control .select { width: 84px; min-height: 36px; padding: 4px 8px; }
.zoom-control .btn-icon { min-width: 32px; min-height: 32px; padding: 4px; }

.preview-frame {
  background: #6b6f7d;
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  overflow: auto;
  max-height: calc(100vh - var(--header-height) - 220px);
  min-height: 400px;
  display: flex;
  justify-content: center;
  position: relative;
}

/* Shown only once a preview render has been in flight for a bit — see the
   150ms delay note in ui/preview/serverPreview.js. Fast renders (a normal
   field edit) never trigger it at all; this is for genuinely slower ones,
   like switching to a heavier template. */
.preview-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(20, 22, 31, 0.35);
  border-radius: var(--radius-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
  z-index: 5;
}
.preview-loading.is-visible { opacity: 1; }
.preview-loading-spinner {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 4px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  animation: preview-spin 0.8s linear infinite;
}
@keyframes preview-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .preview-loading-spinner { animation-duration: 2s; }
}

/* The iframe is a fixed-size real page (A4/Letter @ 96dpi) that gets
   transform: scale()'d down by JS to fit the available panel width — the
   wrapper's own box is sized to the SCALED dimensions so the scroll
   container reserves the right amount of space (a bare CSS transform
   doesn't affect layout flow, so without this the page would either
   overflow or leave a stale gap). See ui/preview/pageScale.js. */
.page-scale-wrap {
  flex-shrink: 0;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  border-radius: 2px;
}

.invoice-page {
  background: #ffffff;
  color: #14161f;
  width: 794px; /* A4 @ 96dpi */
  height: 1123px;
  font-family: var(--font-doc);
  flex-shrink: 0;
  border: 0;
  display: block;
  transform-origin: top left;
}
.invoice-page[data-page-size="letter"] { width: 816px; height: 1056px; }

/* Line items render as a stacked list of cards, not a table — an
   invoice-type with 8+ columns (SKU, HS code, origin, weight, tax, ...)
   either squeezes every field unreadably narrow in a table or forces a
   horizontal scrollbar most people never notice is there. Cards keep
   Description/Qty/Rate/Amount always visible and tuck invoice-type-
   specific extras behind an explicit "More fields" toggle — costs
   vertical space (which just scrolls normally) instead of hidden
   horizontal space. */
.line-items-list { display: flex; flex-direction: column; gap: var(--space-2); }

/* A left accent stripe + tinted background per row type is the "identify
   at a glance" mechanism: a plain uniform border made every card look
   identical when scrolling a long list, especially once section/text/
   subtotal/page-break rows are mixed in among regular line items. */
.line-item-card {
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-primary);
  border-radius: var(--radius-md);
  padding: 10px 12px;
  background: var(--color-bg);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  transition: box-shadow 0.15s ease;
}
.line-item-card:hover { box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08); }

.line-item-card-section { border-left-color: var(--color-accent); background: var(--color-bg-subtle); }
.line-item-card-text { border-left-color: var(--color-text-muted); }
.line-item-card-subtotal { border-left-color: var(--color-success); background: var(--color-bg-subtle); }
.line-item-card-pagebreak { border-left-style: dashed; border-left-color: var(--color-warning); }

.line-item-card-header { display: flex; align-items: center; gap: var(--space-2); }
.line-item-description-input { flex: 1 1 auto; min-width: 0; font-weight: 600; }

.line-item-badge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.6875rem;
  font-weight: 700;
}

.line-item-type-tag {
  flex: 0 0 auto;
  display: inline-block;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 0.6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
  background: var(--color-bg-subtle);
  border: 1px solid var(--color-border);
}
.line-item-card-section .line-item-type-tag { color: var(--color-accent); }
.line-item-card-subtotal .line-item-type-tag { color: var(--color-success); }
.line-item-card-pagebreak .line-item-type-tag { color: var(--color-warning); }

.line-item-card-primary { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.line-item-card-primary .line-item-field { flex: 1 1 90px; min-width: 80px; }

.line-item-field { display: flex; flex-direction: column; gap: 3px; }
.line-item-field-label {
  font-size: 0.6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}
.line-item-field .input, .line-item-field .select { width: 100%; min-height: 36px; padding: 6px 8px; font-size: 0.875rem; }
.line-item-readonly-value { display: block; min-height: 36px; padding: 6px 8px; font-size: 0.875rem; font-weight: 700; }

.line-item-more-toggle {
  display: block;
  margin-top: var(--space-2);
  padding: 4px 0;
  background: none;
  border: none;
  color: var(--color-primary, #2952e3);
  font-size: 0.8125rem;
  font-weight: 600;
  cursor: pointer;
}
.line-item-more-toggle:hover { text-decoration: underline; }

.line-item-card-secondary {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
  gap: var(--space-2);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px dashed var(--color-border);
}

.line-item-tax-list { display: flex; flex-direction: column; gap: 2px; padding-top: 4px; }
.line-item-tax-option { display: flex; align-items: center; gap: 4px; font-size: 0.75rem; }

.line-item-card-section, .line-item-card-text, .line-item-card-subtotal, .line-item-card-pagebreak {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.line-item-card-section { background: var(--color-bg-subtle); font-weight: 700; }
.line-item-card-section .input, .line-item-card-text .input { flex: 1; }
.line-item-card-subtotal { justify-content: flex-end; }
.line-item-subtotal-label { font-weight: 700; }
.line-item-card-pagebreak { justify-content: center; color: var(--color-text-muted); }

.line-items-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }

.item-row-controls { display: flex; gap: var(--space-1); }
.drag-handle { cursor: grab; touch-action: none; color: var(--color-text-muted); padding: 4px; }
.drag-handle:active { cursor: grabbing; }

/* Mobile: tabbed editor / preview. The element in the DOM
   (public/app/index.php) carries BOTH class="mobile-tabs tabs" — the
   generic .tabs (display:flex, a plain flex-row component style) and
   this desktop-hides-it .mobile-tabs, on the same element. Both are
   single-class selectors, so whichever one is declared LATER in the
   cascade wins their shared `display` property — a real regression hit
   once .tabs moved into this same file (from the old components.css)
   after this block: with .tabs now literally later in the stylesheet,
   `display: none` here was silently losing to .tabs' `display: flex`,
   making the mobile tabs render unconditionally on desktop too. Since
   .mobile-tabs sits inside `.app-shell`'s CSS grid with no grid-column
   override, becoming visible meant it started actually occupying grid
   column 1, shoving .editor-panel into column 2 and .preview-panel
   down into a whole extra row — a fully scrambled desktop layout from
   one lost specificity tie. Compound selector (.mobile-tabs.tabs) below
   fixes it structurally instead of by source order, which is exactly
   the kind of thing that's fragile to a future file reorganization. */
.mobile-tabs.tabs { display: none; }

@media (max-width: 980px) {
  .app-shell { grid-template-columns: 1fr; }
  .mobile-tabs.tabs { display: flex; }
  .preview-panel { position: static; }
  .preview-frame { max-height: none; }
  .app-shell[data-mobile-view="editor"] .preview-panel { display: none; }
  .app-shell[data-mobile-view="preview"] .editor-panel { display: none; }
}

/* Full-screen preview */
.fullscreen-preview {
  position: fixed;
  inset: 0;
  background: #6b6f7d;
  z-index: 500;
  display: flex;
  flex-direction: column;
}
.fullscreen-preview .preview-frame { flex: 1; max-height: none; border-radius: 0; }

@media print {
  .site-header, .site-footer, .app-toolbar, .editor-panel, .preview-toolbar, .mobile-tabs, .skip-link {
    display: none !important;
  }
  .app-shell { display: block; padding: 0; }
  .preview-frame { background: none; padding: 0; overflow: visible; max-height: none; }
  .page-scale-wrap { box-shadow: none !important; width: auto !important; height: auto !important; overflow: visible; }
  .invoice-page { box-shadow: none; width: auto; height: auto; transform: none !important; }
}

/* ============================================================
   Moved here from the old components.css (now merged into
   app.css) — these are only ever rendered on /app/ (tabs, tax
   rows, payment-method rows, the 3 <dialog> modals, the template
   gallery, the saved-drafts list), confirmed by grep against every
   marketing-page .php file before moving anything. Keeping them
   out of the universal app.css means marketing-page visitors don't
   download ~29KB of CSS for UI they'll never see (the exact gap
   Lighthouse's "reduce unused CSS" audit measured).
   ============================================================ */

/* Tabs */
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--color-border); overflow-x: auto; }
.tab-btn {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: var(--space-3) var(--space-4);
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
  white-space: nowrap;
  min-height: 44px;
}
.tab-btn[aria-selected="true"] { color: var(--color-primary); border-bottom-color: var(--color-primary); }
.tab-panel { padding-top: var(--space-4); }
.tab-panel[hidden] { display: none; }

/* Editor section nav: wraps onto multiple rows instead of horizontal-scrolling
   with browser scroll-arrows — there are too many sections for a single row. */
.editor-section-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  border-bottom: none;
  overflow-x: visible;
  padding-bottom: var(--space-3);
  margin-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}
.editor-section-nav .tab-btn {
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 5px 12px;
  min-height: 30px;
  font-size: 0.78rem;
  color: var(--color-text-muted);
  background: var(--color-bg-subtle);
  transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-base), box-shadow var(--transition-smooth);
}
.editor-section-nav .tab-btn:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
  background: var(--color-primary-soft);
}
.editor-section-nav .tab-btn[aria-selected="true"] {
  background: var(--gradient-brand);
  border-color: transparent;
  color: var(--color-primary-contrast);
  box-shadow: var(--shadow-sm);
}
.editor-section-nav .tab-btn[aria-selected="true"]:hover {
  color: var(--color-primary-contrast);
}

.tax-row {
  margin-bottom: var(--space-2);
  display: grid;
  grid-template-columns: 1fr 90px 1fr auto auto;
  gap: var(--space-2);
  align-items: center;
}
@media (max-width: 480px) { .tax-row { grid-template-columns: 1fr; } }
.tax-row-compound { display: flex; align-items: center; gap: 4px; font-size: 0.8125rem; white-space: nowrap; }

.payment-method-row { margin-bottom: var(--space-2); }
.payment-method-row-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-2); text-transform: capitalize; }
.custom-field-row { align-items: center; }
.custom-field-value-wrap { display: flex; gap: 4px; }

/* .modal is applied directly to a native <dialog> element (see
   public/app/index.php's #dialog-save-draft/#dialog-load-draft/
   #dialog-templates, opened via .showModal()). The browser's UA
   stylesheet gives <dialog> its own border/padding/color by default;
   border: none below is a real reset, not a no-op, or every modal on
   the site shows a stray gray border no class here previously overrode. */
.modal {
  background: var(--color-surface);
  color: var(--color-text);
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  max-width: 560px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  padding: var(--space-5);
  animation: modal-pop var(--transition-smooth);
}
.modal-lg { max-width: 960px; }

.modal::backdrop {
  background: rgba(10, 11, 16, 0.6);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: modal-fade var(--transition-smooth);
}

@keyframes modal-pop {
  from { opacity: 0; transform: translateY(16px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
@keyframes modal-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}
/* Belt-and-suspenders: app.css's global `h1..h6 { font-family:
   var(--font-heading) }` already covers this (and every other dialog's
   bare <h2>) with nothing here overriding it. Declared again here
   anyway since it costs nothing and removes any doubt for this
   specific heading. */
.modal-header h2 { margin: 0; font-family: var(--font-heading); }
.modal-close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: var(--color-bg-subtle);
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast), transform var(--transition-smooth);
}
.modal-close:hover { background: var(--color-danger); border-color: var(--color-danger); color: #fff; transform: rotate(90deg); }

/* Empty state */
.empty-state { text-align: center; padding: var(--space-7) var(--space-4); color: var(--color-text-muted); }

/* Template gallery modal (public/app/index.php's #dialog-templates,
   rendered by ui/gallery/templateGallery.js) — a dedicated set of classes
   instead of the inline styles the JS used to set directly, so hover/
   focus states and dark mode are actually stylable. */
.search-field { position: relative; flex: 1; min-width: 180px; }
.search-field .input { padding-left: 38px; }
.search-field::before {
  content: '';
  position: absolute;
  left: 12px;
  top: 50%;
  width: 16px;
  height: 16px;
  transform: translateY(-50%);
  background: var(--color-text-muted);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3C/svg%3E") center / contain no-repeat;
  pointer-events: none;
}

.template-gallery-toolbar { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; margin-bottom: var(--space-4); }
.template-favorites-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 0.875rem; color: var(--color-text-muted); white-space: nowrap; }

.template-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: var(--space-4);
  max-height: 60vh;
  overflow-y: auto;
  padding: 3px;
}

/* Each card gets --tpl-accent set inline by templateGallery.js from that
   template's own defaultAccentColor (app/Config/Templates.php). First
   pass used it for a bold colored top bar + tinted thumbnail background
   on every card — too loud/busy for this tool's tone. Restrained take:
   the card stays a plain neutral white/gray by default, the template's
   color only shows up as a small swatch dot next to its name and a
   gentle tint that fades in on hover — present for quick scanning, not
   shouting on every card at once. */
.template-card { position: relative; cursor: pointer; overflow: hidden; }
.template-card-thumb {
  position: relative;
  padding: 16px 16px 0;
  background: var(--color-bg-subtle);
  transition: background var(--transition-smooth);
}
.template-card:hover .template-card-thumb {
  background: color-mix(in srgb, var(--tpl-accent, var(--color-primary)) 8%, var(--color-bg-subtle));
}
.template-card-thumb img {
  width: 100%;
  display: block;
  aspect-ratio: 240 / 310;
  object-fit: contain;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  box-shadow: 0 2px 10px rgba(20, 22, 31, 0.1);
}
.template-card-body { padding: var(--space-3); }
.template-card-title-row { display: flex; align-items: center; gap: 7px; margin-bottom: 5px; }
.template-card-swatch {
  width: 9px;
  height: 9px;
  border-radius: 999px;
  flex-shrink: 0;
  background: var(--tpl-accent, var(--color-primary));
}
.template-card-title { font-weight: 700; font-size: 0.8125rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.template-card-fav {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  border: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--color-surface) 85%, transparent);
  box-shadow: var(--shadow-sm);
  color: var(--color-warning);
  font-size: 0.9375rem;
  cursor: pointer;
  transition: transform var(--transition-smooth), background var(--transition-fast);
}
.template-card-fav:hover { transform: scale(1.12); }

/* A quiet 1px ring, not a bold outline, plus a small checkmark chip in
   the app's own brand color (not the per-template accent — selection is
   a state of the *app*, consistent regardless of which template, while
   the swatch dot is the template's own identity). */
.template-card.is-selected { box-shadow: 0 0 0 2px var(--color-primary); }
.template-card-selected-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  line-height: 1;
  box-shadow: var(--shadow-sm);
}

/* Saved-drafts list (public/app/index.php's #dialog-load-draft, rendered
   by renderDraftList() in app.js) — replaces what used to be inline
   flex/margin styles on a plain .card row with real classes, plus a
   small document-icon avatar per row instead of just two lines of text. */
.draft-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-3);
  transition: border-color var(--transition-smooth), box-shadow var(--transition-smooth);
}
.draft-row:hover { border-color: var(--color-primary); box-shadow: var(--shadow-sm); }
.draft-row-icon {
  position: relative;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  background: var(--color-primary-soft);
}
.draft-row-icon::before {
  content: '';
  position: absolute;
  inset: 9px;
  background: var(--color-primary);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpolyline points='14 2 14 8 20 8'/%3E%3Cline x1='16' y1='13' x2='8' y2='13'/%3E%3Cline x1='16' y1='17' x2='8' y2='17'/%3E%3C/svg%3E") center / contain no-repeat;
}
.draft-row-info { min-width: 0; flex: 1; }
.draft-row-title { font-weight: 700; font-size: 0.9375rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.draft-row-meta { font-size: 0.8125rem; color: var(--color-text-muted); margin-top: 2px; }
.draft-row-actions { display: flex; gap: var(--space-2); flex-shrink: 0; }
