/* ============================================
   FILE: public/style.css
   DESCRIPTION: I LOVE SNACKS brand styling for ils-translator UI.
   Palette (from ILS brandbook):
     - Background:      #FFFFFF (surface white)
     - Text:            #141414 (ink)
     - Accent (red):    #C60404, hover #A00303, tint #FBE4E4
     - Secondary UI:    #3D3D3D (soft-black — borders/icons/inactive)
     - Nav/meta text:   #7A6F61
     - Warm line/bg:    #E7E6E2 / #F6F6F4
   Font: Inter, loaded via <link> in index.html.
   ============================================ */

:root {
  --ils-red:        #C60404;
  --ils-red-dark:   #A00303;
  --ils-red-tint:   #FBE4E4;
  --ils-ink:        #141414;
  --ils-soft-black: #3D3D3D;
  --ils-meta:       #7A6F61;
  --ils-line:       #E7E6E2;
  --ils-bg:         #F6F6F4;
  --ils-white:      #FFFFFF;
  --ils-danger:     #D23A2C;
  --ils-warning:    #E0901E;
  --ils-info:       #3D3D3D;
  --ils-font:       'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: var(--ils-font);
  font-size: 14px;
  color: var(--ils-ink);
  background: var(--ils-white);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: 'cv11', 'ss01';
}

.hidden { display: none !important; }
.muted { color: var(--ils-meta); }

/* ---------------- login gate ---------------- */
.login-gate {
  position: fixed;
  inset: 0;
  background: var(--ils-white);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  font-family: var(--ils-font);
}
/* Mobile keyboard open: shrink gate to the visual viewport and pin the card
   to the bottom so there's a minimal (~5px) gap between the Sign in button
   and the top of the software keyboard. Toggled by JS via visualViewport. */
.login-gate--kb {
  align-items: flex-end;
  justify-content: center;
}
.login-gate--kb .login-card {
  padding-top: 16px;
  padding-bottom: 5px;
}
.login-card {
  background: var(--ils-white);
  border: none;
  box-shadow: none;
  padding: 32px 24px;
  width: 100%;
  max-width: 420px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.login-logo {
  display: block;
  width: 100%;
  max-width: 200px;
  height: auto;
  margin: 0 auto 10px;
}
.login-sublogo {
  font-size: 11px;
  letter-spacing: 0.35em;
  color: var(--ils-ink);
  margin-bottom: 40px;
  text-transform: uppercase;
  font-weight: 600;
}
.login-title {
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 6px;
  color: var(--ils-ink);
}
.login-hint {
  font-size: 14px;
  color: var(--ils-meta);
  margin: 0 0 20px;
}
.login-card input {
  width: 100%;
  padding: 12px 14px;
  border: 1.5px solid var(--ils-soft-black);
  border-radius: 5px;
  margin: 0 0 12px;
  font-size: 14px;
  background: #f4f4f2;
  outline: none;
  font-family: inherit;
  color: var(--ils-ink);
  -webkit-appearance: none;
  appearance: none;
}
.login-card input:focus {
  border-color: var(--ils-soft-black);
  box-shadow: none;
}
.login-card input:invalid {
  box-shadow: none;
}
.login-card button {
  width: 100%;
  padding: 12px 14px;
  background: var(--ils-red);
  color: #fff;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 15px;
  font-weight: 600;
  transition: background 0.15s;
  font-family: inherit;
}
.login-card button:hover { background: var(--ils-red-dark); }
.login-error {
  color: var(--ils-red);
  font-size: 13px;
  margin-top: 12px;
  min-height: 18px;
  width: 100%;
  text-align: center;
}

/* ---------------- app shell ---------------- */
.app {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

/* topbar */
.topbar {
  height: 60px;
  padding: 0 20px;
  background: var(--ils-white);
  border-bottom: 1px solid var(--ils-line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}
.topbar-left { display: flex; align-items: center; gap: 20px; min-width: 0; }
.topbar-right { display: flex; align-items: center; gap: 14px; }

/* TASK-2428: the old vertical brand block (logo + "TRANSLATIONS") is
   gone from the topbar — the horizontal brand logo now lives one row
   up in the hub header. What sits here is the name of the active hub
   section (Translator / URL Shortener / Cart Rewards). */
.section-title {
  margin: 0;
  padding: 0;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--ils-ink);
  line-height: 1;
  flex-shrink: 0;
  white-space: nowrap;
}

.breadcrumbs {
  color: var(--ils-meta);
  font-size: 13px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.breadcrumbs .crumb::after {
  content: " / ";
  color: #c9c8c3;
  padding: 0 2px;
}
.breadcrumbs .crumb:last-child::after { content: ""; }
.breadcrumbs .crumb--current {
  color: var(--ils-ink);
  font-weight: 500;
}
/* TASK-2428: breadcrumbs are Translator-only chrome. Hide them while
   the URL Shortener or Cart Rewards section is active so no Translator
   context leaks into other sections. */
#app[data-hub-section="url-shortener"] #breadcrumbs,
#app[data-hub-section="cart-rewards"] #breadcrumbs {
  display: none;
}

.nav-history { display: flex; gap: 6px; flex-shrink: 0; }
.btn--nav {
  white-space: nowrap;
  width: 96px;
  flex-shrink: 0;
  text-align: center;
  background: var(--ils-soft-black);
  color: #fff;
  border-color: var(--ils-soft-black);
  cursor: pointer;
}
.btn--nav:hover {
  background: var(--ils-soft-black);
  border-color: var(--ils-soft-black);
  color: #fff;
  cursor: pointer;
}
.btn--nav:disabled {
  background: #9A9A9A;
  border-color: #9A9A9A;
  color: #fff;
  cursor: default;
}
.btn--nav:disabled:hover {
  background: #9A9A9A;
  border-color: #9A9A9A;
  color: #fff;
}
.btn--nav-hard-refresh {
  width: auto;
  padding-left: 12px;
  padding-right: 12px;
}

.save-status {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--ils-meta);
  flex-shrink: 0;
}
.save-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}
.save-dot--clean { background: #C9C8C3; }
.save-dot--dirty { background: var(--ils-warning); box-shadow: 0 0 0 3px rgba(224, 144, 30, 0.18); }
.save-dot--saving { background: var(--ils-info); animation: pulse 1s infinite; }
.save-dot--error  { background: var(--ils-danger); }
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}

/* ---------------- buttons ---------------- */
.btn {
  font-family: var(--ils-font);
  padding: 8px 16px;
  border: 1px solid var(--ils-soft-black);
  border-radius: 5px;
  background: var(--ils-white);
  color: var(--ils-ink);
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: background 120ms, border-color 120ms, color 120ms;
}
.btn:hover {
  background: var(--ils-bg);
  border-color: var(--ils-ink);
}
.btn--primary {
  background: var(--ils-red);
  color: #fff;
  border-color: var(--ils-red);
}
.btn--primary:hover {
  background: var(--ils-red-dark);
  border-color: var(--ils-red-dark);
}
.btn--primary:disabled {
  background: #C9C8C3;
  border-color: #C9C8C3;
  color: #fff;
  cursor: not-allowed;
}

/* Section tabs + search combined into one row (fixed height, no vertical
   overflow — inner controls stay in-row via nowrap/scroll, not stacking). */
.tabs {
  height: 44px;
  padding: 0 20px;
  background: var(--ils-white);
  border-bottom: 1px solid var(--ils-line);
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
}
.tabs--with-search {
  align-items: center;
}
.tab {
  flex-shrink: 0;
}
.tabs-search {
  margin-left: 20px;
  margin-right: 20px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  flex: 1 1 auto;
  min-width: 80px;
}
.tabs-search input {
  flex: 1 1 auto;
  min-width: 60px;
  padding: 6px 10px;
  border: 1.5px solid var(--ils-soft-black);
  border-radius: 5px;
  font-size: 13px;
  font-family: inherit;
  color: var(--ils-ink);
  background: var(--ils-white);
}
.tabs-search input:focus {
  outline: none;
  border-color: var(--ils-soft-black);
}
/* Search "Clean" button — sits INSIDE the input's left edge, full height of
   the input, sharing its border colour. Rounded on the left to match the
   input's own corner radius, square on the right where it meets the text.
   Clicking clears #search-input and re-triggers the same input handler that
   typing/deleting would (see bindSearch in app.js) so results hide and the
   status text resets exactly as if the user had erased the text by hand. */
.search-input-wrap {
  position: relative;
  flex: 1 1 auto;
  min-width: 60px;
  display: flex;
}
.search-input-wrap input {
  flex: 1 1 auto;
  padding-left: 78px;
}
.search-clear-btn {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 69px;
  padding: 0;
  border: 1.5px solid var(--ils-soft-black);
  border-right: none;
  border-radius: 5px 0 0 5px;
  background: var(--ils-soft-black);
  color: #fff;
  font-family: var(--ils-font);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  z-index: 1;
}
.search-clear-btn:hover {
  background: var(--ils-ink);
}
.langbar-bulk .btn {
  background: var(--ils-soft-black);
  color: #fff;
  border: none;
}
.langbar-bulk .btn:hover {
  background: var(--ils-ink);
  color: #fff;
}
.langbar-bulk .btn:disabled {
  background: #C9C8C3;
  color: #fff;
  opacity: 1;
}
.reindex-status {
  font-size: 12px;
  color: var(--ils-meta);
  white-space: nowrap;
}
.reindex-status--running { color: var(--ils-red); }
.reindex-status--error { color: #b00020; }
.tab {
  padding: 12px 14px;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  font-family: var(--ils-font);
  font-size: 14px;
  font-weight: 500;
  color: var(--ils-meta);
  margin-bottom: -1px;
  transition: color 120ms, border-color 120ms;
}
.tab:hover { color: var(--ils-ink); }
.tab--active {
  color: var(--ils-red);
  border-bottom-color: var(--ils-red);
  font-weight: 600;
}

/* search */
.searchbar {
  padding: 0;
  background: transparent;
  border: none;
  display: block;
  flex-shrink: 0;
  position: relative;
}
.searchbar--anchor {
  height: 0;
}
.searchbar input {
  flex: 1;
  padding: 10px 14px;
  border: 1px solid var(--ils-line);
  border-radius: 5px;
  font-size: 14px;
  font-family: inherit;
  color: var(--ils-ink);
  background: var(--ils-white);
  transition: border-color 120ms, box-shadow 120ms;
}
.searchbar input:focus {
  outline: none;
  border-color: var(--ils-red);
  box-shadow: 0 0 0 3px var(--ils-red-tint);
}
.search-status {
  font-size: 12px;
  color: var(--ils-meta);
  min-width: 120px;
  text-align: right;
}

/* langbar */
.langbar {
  padding: 10px 20px;
  background: var(--ils-bg);
  border-bottom: 1px solid var(--ils-line);
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  flex-wrap: nowrap;
  overflow-x: auto;
  /* TASK-2212 — unified typography tokens for the whole row.
     Labels (Base / Translation / LLM / Bulk) and values (base locale,
     target-locale + LLM selects) all share the same font-family and
     font-size; they differ only by weight + gray-shade so the row reads
     as a single consistent line. Change here, not in every rule. */
  --langbar-font-size: 13px;
  --langbar-label-color: var(--ils-meta);
  --langbar-value-color: var(--ils-ink);
  --langbar-label-weight: 500;
  --langbar-value-weight: 600;
}
.langbar label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--langbar-font-size);
}
.langbar-label,
.langbar-base-heading {
  font-family: var(--ils-font);
  font-size: var(--langbar-font-size);
  font-weight: var(--langbar-label-weight);
  color: var(--langbar-label-color);
  text-transform: uppercase;
}
.langbar select {
  padding: 6px 10px;
  border: 1px solid var(--ils-line);
  border-radius: 5px;
  background: var(--ils-white);
  color: var(--langbar-value-color);
  font-family: var(--ils-font);
  font-size: var(--langbar-font-size);
  font-weight: var(--langbar-value-weight);
  min-width: 140px;
  transition: border-color 120ms;
}
.langbar select:focus {
  outline: none;
  border-color: var(--ils-red);
}
.base-locale-fixed {
  padding: 0;
  border: none;
  background: transparent;
  font-family: var(--ils-font);
  color: var(--langbar-value-color);
  font-size: var(--langbar-font-size);
  font-weight: var(--langbar-value-weight);
  display: inline-block;
  cursor: default;
  user-select: none;
}
/* BASE cell — stacked hierarchy: small label on top, value below.
   Deliberately non-interactive: no border, no cursor, no hover. */
.langbar-base {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
  line-height: 1.2;
  cursor: default;
  user-select: none;
}
.autotranslate-indicator {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--ils-meta);
  font-size: 13px;
}
.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}
.dot--on    { background: var(--ils-red); }
.dot--off   { background: #C9C8C3; }
.dot--mixed { background: var(--ils-warning); }

/* main */
.main {
  flex: 1;
  display: flex;
  overflow: hidden;
  min-height: 0;
}

/* sidebar */
.sidebar {
  width: 280px;
  min-width: 150px;
  max-width: 70vw;
  background: var(--ils-white);
  border-right: 1px solid var(--ils-line);
  overflow-y: auto;
  flex-shrink: 0;
}
.sidebar-divider {
  width: 5px;
  background: var(--ils-line);
  cursor: col-resize;
  flex-shrink: 0;
  transition: background 120ms;
}
.sidebar-divider:hover,
.sidebar-divider.dragging { background: var(--ils-red); }
.sidebar-status {
  padding: 14px 16px;
  font-size: 13px;
}
.resource-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.resource-item {
  padding: 10px 16px;
  border-bottom: 1px solid #F0EFEB;
  cursor: pointer;
  transition: background 100ms;
}
.resource-item:hover { background: var(--ils-bg); }
.resource-item--open { background: var(--ils-bg); }
.resource-title {
  font-weight: 500;
  font-size: 13px;
  color: var(--ils-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.resource-sub {
  font-size: 11px;
  color: var(--ils-meta);
  margin-top: 2px;
}
.field-list {
  list-style: none;
  padding: 6px 0 10px 26px;
  margin: 0;
  border-top: 1px solid #F0EFEB;
  background: var(--ils-bg);
}
.field-item {
  padding: 6px 12px;
  font-size: 13px;
  cursor: pointer;
  border-radius: 4px;
  color: var(--ils-ink);
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
}
.field-item span:last-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.field-item:hover { background: #EEEEEC; }
.field-item--active {
  background: var(--ils-soft-black);
  color: #fff;
  font-weight: 700;
}
.field-item--active:hover { background: var(--ils-soft-black); }
.field-item--active .field-badge--translated {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}
.field-item--active .field-badge--dirty {
  background: var(--ils-warning);
  color: #fff;
}
.field-badge {
  font-size: 10px;
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 700;
  text-transform: uppercase;
}
.field-badge--dirty      { background: #FBEFD6; color: #8A5A0B; }
.field-badge--translated { background: #DCF5E3; color: #1F7A3A; }

.section-header {
  padding: 8px 16px;
  font-size: 11px;
  text-transform: uppercase;
  color: var(--ils-meta);
  background: var(--ils-bg);
  border-bottom: 1px solid var(--ils-line);
  border-top: 1px solid var(--ils-line);
  font-weight: 700;
}

/* editor / panes */
.editor {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
}
.editor-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--ils-meta);
  padding: 40px;
  text-align: center;
}
.editor-empty h2 {
  margin: 0 0 6px;
  color: var(--ils-ink);
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* TASK-2203: country picker panel (shown for `mf:custom.country`).
   TASK-2210: two-column layout — controls on the left, multilingual preview
   on the right — so on a wide monitor the preview grows horizontally
   instead of being stacked underneath the checkbox list. */
.editor-picker {
  flex: 1;
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 24px;
  padding: 16px 40px 32px;
  overflow: auto;
  background: var(--ils-white);
}
.editor-picker.hidden { display: none; }
.editor-picker__col {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}
.editor-picker__col--left {
  flex: 0 0 480px;
  max-width: 480px;
}
.editor-picker__col--right {
  flex: 1 1 auto;
}
.editor-picker__title {
  font-size: 18px;
  font-weight: 700;
  color: var(--ils-ink);
  margin: 0;
}
.editor-picker__hint {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
}
.editor-picker__current {
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 10px 12px;
  border: 1px solid var(--ils-line);
  border-radius: 6px;
  background: #fafafa;
  flex-wrap: wrap;
}
.editor-picker__current-label {
  color: var(--ils-meta);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.editor-picker__current-value {
  font-size: 15px;
  font-weight: 600;
  color: var(--ils-ink);
  word-break: break-word;
}
.editor-picker__label {
  display: block;
  font-size: 12px;
  color: var(--ils-meta);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 6px 0 0;
}
/* TASK-2210: search filter above the checkbox list. */
.editor-picker__search {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--ils-line);
  border-radius: 5px;
  font-size: 14px;
  font-family: inherit;
  background: var(--ils-white);
  color: var(--ils-ink);
  box-sizing: border-box;
}
.editor-picker__search:focus {
  outline: 2px solid #4c8bf5;
  outline-offset: -1px;
}
/* TASK-2206: checkbox list for multi-country selection.
   TASK-2213: height = exactly 8 rows. Row is fixed at --row-h; container
   height derives from --row-h × 8 + gaps + padding + border (box-sizing is
   border-box globally, so all three must be included in the value).
   Overflow scrolls the remaining countries inside the same box. */
.editor-picker__checkboxes {
  --row-h: 28px;
  --row-gap: 2px;
  display: flex;
  flex-direction: column;
  gap: var(--row-gap);
  height: calc(var(--row-h) * 8 + var(--row-gap) * 7 + 8px * 2 + 1px * 2);
  flex-shrink: 0;
  overflow-y: auto;
  padding: 8px 10px;
  border: 1px solid var(--ils-line);
  border-radius: 5px;
  background: var(--ils-white);
}
.editor-picker__checkbox-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 4px;
  font-size: 14px;
  line-height: 20px;
  color: var(--ils-ink);
  cursor: pointer;
}
.editor-picker__checkbox-row.is-hidden { display: none; }
.editor-picker__checkbox-row:hover {
  background: #fafafa;
}
.editor-picker__checkbox {
  margin: 0;
  cursor: pointer;
}
.editor-picker__checkbox-label {
  flex: 1;
}
.editor-picker__status {
  font-size: 12px;
  min-height: 16px;
}

/* TASK-2205: multilingual preview panel — was under the checkboxes, now
   lives in the right column (TASK-2210).
   TASK-2210: grid layout — first column = locale codes (en:/ru:/…),
   following columns = one per selected country. New countries push the
   grid rightward; horizontal scroll kicks in if the viewport can't fit
   them. */
.editor-picker__preview {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--ils-line);
  border-radius: 6px;
  background: #fafafa;
  max-width: 100%;
  overflow-x: auto;
}
.editor-picker__preview.hidden { display: none; }
.editor-picker__preview-label {
  font-size: 12px;
  color: var(--ils-meta);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.editor-picker__preview-grid {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(6, auto);
  grid-auto-columns: max-content;
  column-gap: 20px;
  row-gap: 4px;
  align-items: baseline;
}
.editor-picker__preview-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--ils-meta);
  text-transform: lowercase;
  min-width: 32px;
  text-align: left;
}
.editor-picker__preview-cell {
  font-size: 14px;
  font-weight: 500;
  color: var(--ils-ink);
  white-space: nowrap;
  text-align: left;
}

.panes {
  flex: 1;
  display: flex;
  min-height: 0;
  /* Horizontal auto-scroll: if the editor area is too narrow to fit 4×150px
     min-width panes + 3×5px dividers (~615px), user can still reach every
     pane instead of the rightmost ones being clipped by overflow:hidden. */
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--ils-white);
  padding: 8px;
  gap: 0;
}
.pane {
  display: flex;
  flex-direction: column;
  min-width: 150px;
  min-height: 0;
  overflow: hidden;
  background: var(--ils-white);
  border: 1px solid var(--ils-line);
  border-radius: 5px;
}
.pane-head {
  position: relative;
  min-height: 26px;
  padding: 4px 12px;
  background: var(--ils-bg);
  border-bottom: 1px solid var(--ils-line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-shrink: 0;
  font-size: 12px;
}
/* TASK-2152: drag handle in the center of each pane head, used to reorder
   panes by drag-and-drop. Uses the Braille "8 dots" glyph (⣿) so it renders
   as a compact 2×4 dot grip without needing an SVG. Absolute-positioned so
   the handle sits at the exact horizontal center of the pane head regardless
   of the title / meta widths on either side. */
.pane-drag-handle {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  color: var(--ils-meta);
  font-size: 14px;
  line-height: 1;
  letter-spacing: -2px;
  padding: 2px 4px;
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  opacity: 0.55;
  transition: opacity 120ms, color 120ms;
}
.pane-drag-handle:hover {
  opacity: 1;
  color: var(--ils-red);
}
.pane-drag-handle:active { cursor: grabbing; }
.pane--dragging {
  opacity: 0.4;
}
.pane--drop-target {
  outline: 2px dashed var(--ils-red);
  outline-offset: -2px;
}
.pane-title {
  font-weight: 700;
  color: var(--ils-ink);
}
.pane-title .btn--icon {
  margin-left: 8px;
  vertical-align: middle;
}

/* TASK-2159: toggle button in pane-head that shows/hides the HTML formatting
   toolbar. Sized like a small chip so it doesn't compete with the pane title. */
.pane-toolbar-toggle {
  margin-left: 8px;
  padding: 1px 6px;
  font-family: var(--ils-font);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--ils-ink);
  background: var(--ils-white);
  border: 1px solid var(--ils-soft-black);
  border-radius: 4px;
  cursor: pointer;
  vertical-align: middle;
  transition: background 120ms, border-color 120ms, color 120ms;
}
.pane-toolbar-toggle:hover {
  background: var(--ils-red-tint);
  border-color: var(--ils-red);
  color: var(--ils-red-dark);
}
.pane-toolbar-toggle--active {
  background: var(--ils-red-tint);
  border-color: var(--ils-red);
  color: var(--ils-red-dark);
}

/* Formatting toolbar sits between .pane-head and the textarea. Hidden by
   default; the toggle button flips .hidden. Buttons wrap textarea selection
   with HTML tags — see applyHtmlFormat() in app.js. */
.pane-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  align-items: center;
  padding: 4px 6px;
  background: var(--ils-bg);
  border-bottom: 1px solid var(--ils-line);
  flex-shrink: 0;
}
.pane-toolbar-btn {
  min-width: 26px;
  height: 24px;
  padding: 0 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 3px;
  color: var(--ils-ink);
  font-family: var(--ils-font);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: background 100ms, border-color 100ms;
}
.pane-toolbar-btn:hover {
  background: var(--ils-white);
  border-color: var(--ils-line);
}
.pane-toolbar-btn:active {
  background: var(--ils-red-tint);
  border-color: var(--ils-red);
  color: var(--ils-red-dark);
}
.pane-toolbar-btn--bold { font-weight: 700; }
.pane-toolbar-btn--italic { font-style: italic; }
.pane-toolbar-btn--underline { text-decoration: underline; }
.pane-toolbar-btn--strike { text-decoration: line-through; }
.pane-toolbar-sep {
  width: 1px;
  height: 16px;
  background: var(--ils-line);
  margin: 0 3px;
}

/* Align icons drawn as three CSS-gradient stripes — no SVG assets needed. The
   middle stripe's width and horizontal offset encode the alignment. */
.align-icon {
  display: inline-block;
  width: 14px;
  height: 10px;
  background-image:
    linear-gradient(currentColor, currentColor),
    linear-gradient(currentColor, currentColor),
    linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
}
.align-icon--left {
  background-size: 14px 1.5px, 10px 1.5px, 14px 1.5px;
  background-position: 0 0, 0 4px, 0 9px;
}
.align-icon--center {
  background-size: 14px 1.5px, 10px 1.5px, 14px 1.5px;
  background-position: 0 0, 2px 4px, 0 9px;
}
.align-icon--right {
  background-size: 14px 1.5px, 10px 1.5px, 14px 1.5px;
  background-position: 0 0, 4px 4px, 0 9px;
}
.align-icon--justify {
  background-size: 14px 1.5px, 14px 1.5px, 14px 1.5px;
  background-position: 0 0, 0 4px, 0 9px;
}
.pane-meta { color: var(--ils-meta); font-size: 11px; text-align: right; }
.pane-body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 12px 14px;
  font-size: 14px;
  line-height: 1.55;
  font-family: var(--ils-font);
  color: var(--ils-ink);
}
.pane-body--preview {
  background: var(--ils-white);
  outline: none;
}
.pane-body--preview:focus { background: #FFFDFD; }
/* TASK-2208 / TASK-2211: reset the first block-level child's top margin (and
   last child's bottom margin) inside the WYSIWYG preview. Storefront themes
   already zero this out; the editor did not. TASK-2208 covered the baseline
   `<p>...` case. TASK-2211 extends it: real body_html often starts with a
   leading `<meta charset="utf-8">` (WYSIWYG editor artifact) that "steals"
   the first-child slot, or wraps the first block in an extra div. The rule
   below zeroes: (a) the direct first child, (b) the first element after one
   or two leading `<meta>` tags, and (c) first-children nested one level deep.
   `!important` defeats inline `style="margin-top:..."` from pasted content. */
.pane-body--preview > *:first-child,
.pane-body--preview > meta:first-child + *,
.pane-body--preview > meta:first-child + meta + *,
.pane-body--preview > *:first-child > *:first-child,
/* When the leading <p> is hidden by the display:none rule below, its next
   sibling becomes visually first, so reset its margin-top too. */
.pane-body--preview > p:first-child:empty + *,
.pane-body--preview > p:first-child:has(> br:only-child) + *,
.pane-body--preview > meta:first-child + p:empty + *,
.pane-body--preview > meta:first-child + p:has(> br:only-child) + * {
  margin-top: 0 !important;
  margin-block-start: 0 !important;
}
.pane-body--preview > *:last-child,
.pane-body--preview > *:last-child > *:last-child {
  margin-bottom: 0 !important;
  margin-block-end: 0 !important;
}
/* Collapse leading empty paragraphs (Word/Pages/rich-editor paste artifact).
   Catches <p></p> and <p><br></p>. Pure whitespace text (<p> </p>, <p>&nbsp;</p>)
   cannot be detected from CSS — those remain a data-side issue. */
.pane-body--preview > p:first-child:empty,
.pane-body--preview > p:first-child:has(> br:only-child),
.pane-body--preview > meta:first-child + p:empty,
.pane-body--preview > meta:first-child + p:has(> br:only-child) {
  display: none;
}
.pane-body--code {
  background: #FBFBFA;
  border: none;
  font-family: 'SFMono-Regular', Consolas, Menlo, monospace;
  font-size: 12.5px;
  line-height: 1.55;
  resize: none;
  color: var(--ils-ink);
  outline: none;
  white-space: pre-wrap;
  word-break: break-word;
}
.pane-body--code:focus { background: var(--ils-white); }
.pane-body img { max-width: 100%; height: auto; }

.pane-divider {
  width: 5px;
  background: var(--ils-line);
  cursor: col-resize;
  transition: background 120ms;
  flex-shrink: 0;
}
.pane-divider:hover,
.pane-divider.dragging { background: var(--ils-red); }

/* search results dropdown — TASK-2175 follow-up fix: this used to be
   anchored `right: 20px` against `.searchbar` (a full-width empty strip
   under #tabs), which happened to line up under the search input only
   because the input used to be the last element in that row. Adding the
   Errors button after the input pushed the row's right edge further right,
   so the fixed `right: 20px` stopped lining up with the input. Anchoring
   via `left` (set in JS from the input's own bounding rect) fixes this
   regardless of how many buttons sit to the input's right. */
.search-results {
  position: absolute;
  top: 8px;
  width: 360px;
  background: var(--ils-white);
  border: 1px solid var(--ils-line);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(20, 20, 20, 0.12);
  max-height: 400px;
  overflow-y: auto;
  z-index: 100;
  margin-top: 4px;
}
.search-result {
  padding: 10px 14px;
  border-bottom: 1px solid #F0EFEB;
  cursor: pointer;
}
.search-result:hover { background: var(--ils-bg); }
.search-result:last-child { border-bottom: none; }
.search-result-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ils-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.search-result-meta {
  font-size: 11px;
  color: var(--ils-meta);
  margin-top: 3px;
}
.search-result-hit {
  font-size: 12px;
  color: var(--ils-red-dark);
  margin-top: 3px;
}
.search-result mark {
  background: #FBEFD6;
  color: var(--ils-ink);
  padding: 0 2px;
  border-radius: 2px;
}
.searchbar-wrap { position: relative; flex: 1; }

/* ---------------- pane head actions (LLM buttons + lock) ---------------- */
.pane-head-left {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}
.pane-actions {
  display: flex;
  gap: 4px;
  align-items: center;
  flex-shrink: 0;
}
.btn--small {
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 500;
  border-radius: 5px;
  border: 1px solid var(--ils-soft-black);
  background: var(--ils-white);
  cursor: pointer;
  color: var(--ils-ink);
  font-family: var(--ils-font);
  transition: background 120ms, border-color 120ms, color 120ms;
}
.btn--small:hover {
  background: var(--ils-red-tint);
  border-color: var(--ils-red);
  color: var(--ils-red-dark);
}
.btn--small:disabled { opacity: 0.5; cursor: not-allowed; }
.btn--icon { padding: 2px 4px; font-size: 6.5px; line-height: 1; }
.btn--locked {
  background: #FBEFD6;
  border-color: var(--ils-warning);
  color: #6A430A;
}
.btn--locked:hover {
  background: #F6E0AE;
  border-color: var(--ils-warning);
  color: #6A430A;
}
.btn--danger {
  background: var(--ils-white);
  color: var(--ils-red-dark);
  border-color: #F2CFCF;
}
.btn--danger:hover {
  background: var(--ils-red-tint);
  border-color: var(--ils-red);
  color: var(--ils-red-dark);
}

/* ---------------- modal ---------------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 20, 20, 0.75);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.modal-panel {
  position: relative;
  background: var(--ils-white);
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(20, 20, 20, 0.28);
  width: min(960px, 92vw);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-head {
  padding: 16px 22px;
  border-bottom: 1px solid var(--ils-line);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.modal-title {
  margin: 0;
  font-size: 17px;
  font-weight: 700;
  color: var(--ils-ink);
  letter-spacing: -0.01em;
}
.modal-close {
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 22px;
  line-height: 1;
  color: var(--ils-meta);
  padding: 4px 10px;
  border-radius: 5px;
}
.modal-close:hover {
  background: var(--ils-bg);
  color: var(--ils-ink);
}
.modal-tabs {
  display: flex;
  gap: 4px;
  padding: 0 22px;
  background: var(--ils-bg);
  border-bottom: 1px solid var(--ils-line);
}
.modal-tab {
  padding: 10px 14px;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  font-family: var(--ils-font);
  font-size: 13px;
  font-weight: 500;
  color: var(--ils-meta);
  margin-bottom: -1px;
  transition: color 120ms, border-color 120ms;
}
.modal-tab:hover { color: var(--ils-ink); }
.modal-tab--active {
  color: var(--ils-red);
  border-bottom-color: var(--ils-red);
  font-weight: 600;
}
.modal-body {
  overflow-y: auto;
  padding: 22px;
}
.modal-panel--confirm {
  width: min(460px, 92vw);
}
.modal-panel--confirm .confirm-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ils-ink);
}
.modal-panel--lock {
  width: min(720px, 92vw);
}
.modal-panel--lock .confirm-text {
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ils-meta);
}
.lock-field-name {
  font-weight: 600;
  color: var(--ils-red);
  font-family: var(--ils-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 14px;
}
.lock-master {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--ils-line);
  border-radius: 8px;
  background: var(--ils-bg);
  cursor: pointer;
  font-size: 14px;
  color: var(--ils-ink);
  accent-color: var(--ils-red);
  margin-bottom: 10px;
}
.lock-list {
  list-style: none;
  margin: 0;
  padding: 0;
  column-count: 2;
  column-gap: 12px;
}
.lock-list li {
  margin: 0 0 4px;
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
}
.lock-list label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  color: var(--ils-ink);
  accent-color: var(--ils-red);
  transition: background 120ms, border-color 120ms;
}
.lock-list label:hover {
  background: var(--ils-bg);
  border-color: var(--ils-line);
}
.lock-list .lock-loc-code {
  font-weight: 600;
  min-width: 56px;
  color: var(--ils-red);
}
.lock-list .lock-country {
  color: var(--ils-meta);
}
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 14px 22px 18px;
  border-top: 1px solid var(--ils-line);
}
.settings-section p.muted {
  margin: 0 0 14px;
  font-size: 13px;
  color: var(--ils-meta);
  line-height: 1.55;
}

.settings-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  margin-bottom: 14px;
}
.settings-table th {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--ils-line);
  color: var(--ils-meta);
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
}
.settings-table td {
  padding: 8px 10px;
  border-bottom: 1px solid #F0EFEB;
  vertical-align: middle;
  color: var(--ils-ink);
}
.settings-table tr:last-child td { border-bottom: none; }
.settings-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  accent-color: var(--ils-red);
}
.settings-form {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 12px 0;
  border-top: 1px solid var(--ils-line);
  flex-wrap: wrap;
}
.settings-form input {
  padding: 8px 10px;
  border: 1px solid var(--ils-line);
  border-radius: 5px;
  font-size: 13px;
  min-width: 140px;
  font-family: inherit;
  color: var(--ils-ink);
  background: var(--ils-white);
  transition: border-color 120ms, box-shadow 120ms;
}
.settings-form input:focus {
  outline: none;
  border-color: var(--ils-red);
  box-shadow: 0 0 0 3px var(--ils-red-tint);
}
.settings-error {
  color: var(--ils-red);
  font-size: 12px;
  min-height: 16px;
  padding-top: 4px;
}

/* Translation rules preview (TASK-2120) — show the exact system prompt so
   the merchant can confirm rules are actually going to the LLM. */
.tr-preview-block {
  border-top: 1px solid var(--ils-line);
  margin-top: 10px;
  padding-top: 10px;
}
.tr-preview-out {
  background: var(--ils-bg);
  border: 1px solid var(--ils-line);
  border-radius: 6px;
  padding: 10px 12px;
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--ils-ink);
  max-height: 260px;
  overflow: auto;
  margin: 8px 0 0;
}
.tr-preview-out:empty {
  display: none;
}
/* Give textareas inside the rules form a bit of breathing room */
.settings-form--stacked {
  align-items: flex-start;
}
.tr-rule-cell {
  max-width: 420px;
  white-space: pre-wrap;
  word-break: break-word;
}
.tr-inline-input {
  width: 100%;
  min-width: 0;
  padding: 6px 8px;
  border: 1px solid var(--ils-line);
  border-radius: 5px;
  font-family: inherit;
  font-size: 12px;
  background: var(--ils-white);
  color: var(--ils-ink);
}
.tr-inline-input:focus {
  outline: none;
  border-color: var(--ils-red);
  box-shadow: 0 0 0 2px var(--ils-red-tint);
}

/* ---------------- MCP Connector settings tab (TASK-2135) ---------------- */
.mcp-code {
  display: inline-block;
  padding: 3px 8px;
  background: var(--ils-bg);
  border: 1px solid var(--ils-line);
  border-radius: 4px;
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--ils-ink);
  word-break: break-all;
  margin-right: 8px;
  vertical-align: middle;
}
.mcp-token {
  min-width: 120px;
}
.mcp-token-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.mcp-hint {
  font-size: 12px;
  line-height: 1.55;
  margin-top: 6px;
}
.mcp-hint code {
  background: var(--ils-bg);
  border: 1px solid var(--ils-line);
  border-radius: 3px;
  padding: 1px 5px;
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: 11px;
}
.mcp-health-status {
  font-size: 12px;
  font-family: 'SF Mono', Menlo, Consolas, monospace;
}
.mcp-health-status--ok { color: #1F7A3A; }
.mcp-health-status--fail { color: var(--ils-red); }
.mcp-h4 {
  margin: 18px 0 8px;
  font-size: 12px;
  text-transform: uppercase;
  color: var(--ils-meta);
}
.mcp-steps {
  margin: 0 0 12px;
  padding-left: 22px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ils-ink);
}
.mcp-steps li { margin-bottom: 4px; }
.mcp-steps code {
  background: var(--ils-bg);
  border: 1px solid var(--ils-line);
  border-radius: 3px;
  padding: 1px 5px;
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: 11px;
}
.mcp-troubleshoot {
  margin: 0;
  font-size: 12px;
  line-height: 1.55;
}
.mcp-troubleshoot code {
  background: var(--ils-bg);
  border: 1px solid var(--ils-line);
  border-radius: 3px;
  padding: 1px 5px;
  font-family: 'SF Mono', Menlo, Consolas, monospace;
  font-size: 11px;
}
#mcp-connector-table th {
  color: var(--ils-meta);
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  vertical-align: top;
  padding-top: 12px;
}
#mcp-connector-table td {
  padding: 10px;
}

/* ---------------- bulk translate (TASK-2102) ---------------- */
/* TASK-2444: bulk-translation progress bar as its own dedicated row that
   sits between the topbar and the section tabs. Same height/padding as
   the tabs row so it visually reads as an extra chrome band. Only exists
   in the flow while a bulk job is running — when hidden, the layout
   collapses (tabs row hugs the topbar). Progress bar is pinned to the
   left; the current-step label expands to take the remaining width; the
   counts and Cancel button anchor to the right. Superseded the old
   inline placement inside .topbar-right (TASK-2437 / TASK-2438) — long
   current_step labels were pushing Settings / Pending publish / Save &
   publish / Log out off the edge. */
.bulk-progress {
  height: 44px;
  padding: 0 20px;
  background: var(--ils-white);
  border-bottom: 1px solid var(--ils-line);
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}
.bulk-progress.hidden { display: none; }
.bulk-progress-step {
  font-size: 12px;
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ils-meta);
}
.bulk-progress-counts {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
  color: var(--ils-meta);
}
.bulk-progress-bar-outer {
  position: relative;
  flex: 0 0 280px;
  height: 18px;
  background: #F0DFB4;
  border-radius: 9px;
  overflow: hidden;
}
.bulk-progress-bar-inner {
  height: 100%;
  background: var(--ils-warning);
  transition: width 250ms ease;
}
.bulk-progress-pct {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: #4A2F00;
}
.bulk-progress .btn { flex-shrink: 0; }

/* Inline bulk-translate cluster in the langbar (TASK-2144, TASK-2145).
   Sits between the LLM selector and the autotranslate indicator.
   Three visually-separated pairs of ultra-compact buttons. MUST stay on
   a single row: if it doesn't fit, the cluster gets its own horizontal
   scrollbar rather than wrapping — vertical space in the langbar is
   the scarce resource. */
.langbar-bulk {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
}
.langbar-bulk-group {
  display: flex;
  align-items: center;
  gap: 3px;
  flex-shrink: 0;
}
.langbar-bulk .langbar-label { flex-shrink: 0; }
.langbar-bulk .btn { flex-shrink: 0; white-space: nowrap; padding: 3px 7px; border-radius: 5px; }

/* TASK-2154 — Undo cluster.
   Visually detached from the 8 bulk buttons with an explicit gap so a click
   on Site→∀ can't slide into Undo by accident. Colour scheme uses the amber
   /-warning tokens so it reads as "reversible correction", not "start a job".
   The button flips to a slightly darker amber on hover. */
.langbar-bulk-undo {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  margin-left: 18px;
  padding-left: 14px;
  border-left: 1px dashed var(--ils-line);
}
.btn--undo {
  background: #FFF6DC;
  border-color: var(--ils-warning);
  color: #6A430A;
  font-weight: 600;
}
.btn--undo:hover {
  background: #F6E0AE;
  border-color: #C58C10;
  color: #3E2B04;
}
.btn--undo:disabled {
  background: #FCFAF3;
  border-color: #E4E1D8;
  color: #A8A497;
}

/* TASK-2156 — URL Shortener screen. Full-page replacement for the translator
   editor: hides tabs/langbar/main and takes over the entire viewport below the
   topbar. Layout is a plain vertical stack (head → form → list) — no panes,
   no sidebar. Kept close to the settings-panel visual language so it doesn't
   feel like a separate app. */
.url-shortener {
  padding: 24px 32px 48px;
  max-width: 1240px;
  margin: 0 auto;
  width: 100%;
  box-sizing: border-box;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.url-shortener-head { margin-bottom: 20px; }
.url-shortener-title {
  margin: 0 0 6px;
  font-size: 22px;
  font-weight: 700;
}
.url-shortener-hint { margin: 0 0 14px; font-size: 13px; }
.url-shortener-hint code {
  background: var(--ils-cream, #F7F1E0);
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 12px;
}
.url-shortener-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}
/* TASK-2387: async sync progress bar. Grows to fill everything to the
   right of the "Sync SKU redirects" button; the percent text sits inside
   the bar (centred) so no separate slot is needed. */
.url-shortener-sync-progress {
  flex: 1 1 auto;
  min-width: 200px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.url-shortener-sync-progress-bar-outer {
  position: relative;
  width: 100%;
  height: 18px;
  background: #F0DFB4;
  border-radius: 9px;
  overflow: hidden;
}
.url-shortener-sync-progress-bar-inner {
  height: 100%;
  background: var(--ils-warning, #E5A100);
  transition: width 400ms ease;
}
.url-shortener-sync-progress-text {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: #4A2F00;
}
.url-shortener-sync-progress-step {
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.url-shortener-h3 {
  margin: 0 0 10px;
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--ils-meta, #7C7666);
  letter-spacing: 0.4px;
}
.url-shortener-form-block,
.url-shortener-list-block {
  border-top: 1px solid var(--ils-line, #E4E1D8);
  padding-top: 18px;
  margin-top: 18px;
}
.url-shortener-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}
.url-shortener-form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  min-width: 160px;
}
.url-shortener-form-grow { flex: 1 1 240px; }
.url-shortener-form-label {
  font-size: 11px;
  text-transform: uppercase;
  color: var(--ils-meta, #7C7666);
  letter-spacing: 0.4px;
}
.url-shortener-form input,
.url-shortener-form select {
  padding: 7px 10px;
  border: 1px solid var(--ils-line, #E4E1D8);
  border-radius: 5px;
  font-family: inherit;
  font-size: 13px;
  background: white;
}
.url-shortener-preview {
  margin-top: 10px;
  font-family: monospace;
  font-size: 12.5px;
}
.url-shortener-table td, .url-shortener-table th {
  vertical-align: top;
  padding: 8px 10px;
}
.url-shortener-table code {
  background: var(--ils-cream, #F7F1E0);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 12px;
  word-break: break-all;
}
.url-shortener-empty { margin-top: 16px; font-size: 13px; }
.url-shortener-kind-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 3px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.url-shortener-kind-badge--sku {
  background: #E6F1E9;
  color: #2F6B3E;
}
.url-shortener-kind-badge--manual {
  background: #FFF6DC;
  color: #6A430A;
}
.url-shortener-locales-list {
  margin-top: 4px;
  font-size: 11px;
  color: var(--ils-meta, #7C7666);
}

/* -------------------- TASK-2157: status badges + filter -------------------- */
/* Sidebar resource-title row hosts the status badge inline with the title.   */
.resource-title-row {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.resource-title-row .resource-title {
  min-width: 0;
  flex: 1 1 auto;
}
.status-badge {
  font-size: 9px;
  padding: 2px 6px;
  border-radius: 999px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  flex: 0 0 auto;
  line-height: 1;
  white-space: nowrap;
}
.status-badge--active   { background: #DCF5E3; color: #1F7A3A; }
.status-badge--draft    { background: #EAE7DE; color: #6A6659; }
.status-badge--archived { background: #F6DADA; color: #8B2626; }
.status-badge--unknown  { background: #EEECE6; color: #7C7666; }

/* Filter bar above the resource list (only visible on Products / Pages).    */
/* TASK-2178 — sticky within the sidebar scroll container so the label +     */
/* chips + "shown / total" counter stay pinned while the list scrolls.       */
.status-filter-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--ils-line);
  background: var(--ils-bg);
  position: sticky;
  top: 0;
  z-index: 3;
}
.status-filter-label {
  font-size: 11px;
  text-transform: uppercase;
  color: var(--ils-meta);
  font-weight: 700;
  letter-spacing: 0.03em;
}
.status-filter-count {
  margin-left: auto;
  font-size: 11px;
}
.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid var(--ils-line);
  background: #fff;
  color: var(--ils-ink);
  transition: opacity 100ms, background 100ms;
}
.status-chip--off {
  opacity: 0.5;
  background: transparent;
}
.status-chip--on {
  background: #fff;
  border-color: var(--ils-soft-black);
}
.status-chip-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 999px;
  padding: 0;
  font-size: 0;
  line-height: 0;
}
.status-chip-dot.status-badge--active   { background: #2FA858; }
.status-chip-dot.status-badge--draft    { background: #8A8880; }
.status-chip-dot.status-badge--archived { background: #C64545; }
.status-chip-dot.status-badge--unknown  { background: #B8B4A6; }

/* Bulk confirm modal — status includer block.                                */
.bulk-confirm-status {
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid var(--ils-line);
  border-radius: 6px;
  background: var(--ils-bg);
}
.bulk-confirm-status.hidden { display: none; }
.bulk-status-heading {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 8px;
  font-weight: 700;
}
.bulk-status-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding: 4px 0;
}
.bulk-status-title {
  font-size: 12px;
  font-weight: 600;
  min-width: 140px;
}
.bulk-status-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  cursor: pointer;
}
.bulk-status-check input[type="checkbox"] { margin: 0; }

/* TASK-2175 — Errors button in the tabs-search toolbar. Sits between the
   Search input and the "Refresh search data" button. Neutral by default, red
   when there are stuck drafts (badge count > 0). */
.btn--errors {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.errors-btn-icon {
  font-size: 13px;
  line-height: 1;
}
.errors-btn-label {
  font-weight: 500;
}
.errors-btn-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--ils-red);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}
.errors-btn-badge.hidden { display: none; }
.btn--errors.btn--errors--hot {
  background: var(--ils-red-tint);
  border-color: var(--ils-red);
  color: var(--ils-red-dark);
}
.btn--errors.btn--errors--hot:hover {
  background: var(--ils-red);
  color: #fff;
  border-color: var(--ils-red);
}

/* TASK-2175 — Publish errors modal panel. */
.modal-panel--errors {
  width: min(920px, 94vw);
  max-height: 88vh;
}
.errors-modal-head-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}
.errors-modal-count {
  font-size: 13px;
  font-weight: 500;
  margin-left: 8px;
}
.errors-modal-hint {
  margin: 0 0 12px 0;
  font-size: 12px;
  line-height: 1.4;
}
.errors-modal-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  overflow-y: auto;
  padding-right: 4px;
}
.errors-modal-empty {
  padding: 24px 0;
  text-align: center;
  font-size: 13px;
}
.errors-modal-empty.hidden { display: none; }
.errors-group {
  border: 1px solid var(--ils-line);
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
}
.errors-group-head {
  padding: 8px 12px;
  background: var(--ils-bg);
  border-bottom: 1px solid var(--ils-line);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ils-ink);
  display: flex;
  align-items: center;
  gap: 8px;
}
.errors-group-count {
  font-size: 11px;
  color: var(--ils-meta);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}
.errors-row {
  padding: 10px 12px;
  border-bottom: 1px solid var(--ils-line);
  cursor: pointer;
  transition: background 100ms;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-column-gap: 12px;
  align-items: start;
}
.errors-row:last-child { border-bottom: none; }
.errors-row:hover { background: var(--ils-bg); }
.errors-row-main {
  min-width: 0;
}
.errors-row-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ils-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.errors-row-sub {
  font-size: 12px;
  color: var(--ils-meta);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.errors-row-msg {
  font-size: 12px;
  color: var(--ils-red-dark);
  margin-top: 4px;
  line-height: 1.35;
}
.errors-row-meta {
  font-size: 11px;
  color: var(--ils-meta);
  text-align: right;
  white-space: nowrap;
  padding-top: 2px;
}

/* TASK-2441 — Pending publish button in the topbar-right cluster. Sits
   between Settings and Save & publish. Neutral by default, tinted when
   the badge count > 0 so the user notices there is work waiting.
   TASK-2444: uses the same `.btn` sizing as its topbar-right neighbours
   (Settings / Save & publish / Log out) — no `.btn--small`, no icon —
   so the button height matches the rest of the cluster exactly. */
.btn--pending {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.pending-publish-btn-label {
  font-weight: 500;
}
.pending-publish-btn-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 18px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--ils-blue, #2563eb);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}
.pending-publish-btn-badge.hidden { display: none; }
.btn--pending.btn--pending--hot {
  background: var(--ils-blue-tint, #dbeafe);
  border-color: var(--ils-blue, #2563eb);
  color: var(--ils-blue-dark, #1e40af);
}
.btn--pending.btn--pending--hot:hover {
  background: var(--ils-blue, #2563eb);
  color: #fff;
  border-color: var(--ils-blue, #2563eb);
}

/* TASK-2441 — Pending publish modal panel. Shares layout with the Errors
   panel but is a separate DOM subtree so the two lists can be opened/closed
   independently. Rows are grouped by section (navigation / product / …) and
   the group header is a collapsible summary. */
.modal-panel--pending {
  width: min(920px, 94vw);
  max-height: 88vh;
}
.pending-publish-modal-head-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}
.pending-publish-modal-count {
  font-size: 13px;
  font-weight: 500;
  margin-left: 8px;
}
.pending-publish-modal-hint {
  margin: 0 0 12px 0;
  font-size: 12px;
  line-height: 1.4;
}
.pending-publish-modal-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  overflow-y: auto;
  padding-right: 4px;
}
.pending-publish-modal-empty {
  padding: 24px 0;
  text-align: center;
  font-size: 13px;
}
.pending-publish-modal-empty.hidden { display: none; }
.pending-group {
  border: 1px solid var(--ils-line);
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
}
.pending-group-head {
  padding: 8px 12px;
  background: var(--ils-bg);
  border-bottom: 1px solid var(--ils-line);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ils-ink);
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  user-select: none;
}
.pending-group-head:hover { background: var(--ils-line); }
.pending-group-caret {
  display: inline-block;
  width: 10px;
  transition: transform 120ms;
}
.pending-group.collapsed .pending-group-caret { transform: rotate(-90deg); }
.pending-group.collapsed .pending-group-body { display: none; }
.pending-group-count {
  font-size: 11px;
  color: var(--ils-meta);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}
.pending-row {
  padding: 10px 12px;
  border-bottom: 1px solid var(--ils-line);
  cursor: pointer;
  transition: background 100ms;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-column-gap: 12px;
  align-items: start;
}
.pending-row:last-child { border-bottom: none; }
.pending-row:hover { background: var(--ils-bg); }
.pending-row-main {
  min-width: 0;
}
.pending-row-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ils-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pending-row-sub {
  font-size: 12px;
  color: var(--ils-meta);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pending-row-preview {
  font-size: 12px;
  color: var(--ils-ink);
  margin-top: 4px;
  line-height: 1.35;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 8px;
}
.pending-row-preview-label {
  font-weight: 600;
  color: var(--ils-meta);
  font-size: 11px;
}
.pending-row-preview-text {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.pending-row-meta {
  font-size: 11px;
  color: var(--ils-meta);
  text-align: right;
  white-space: nowrap;
  padding-top: 2px;
}

/* ============================================
   TASK-2405 — Unified admin-hub navigation header
   Single-row dark bar above the translator topbar. Three zones in one row:
     left: brand "I ♥ SNACKS · Admin"
     center: horizontal tabs (Translator / URL Shortener / Cart Rewards)
     right: env indicator
   Desktop-only — no responsive rules.
   ============================================ */
.hub-header {
  height: 52px;
  padding: 0 20px;
  background: var(--ils-ink);
  color: #fff;
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 24px;
  flex-shrink: 0;
  font-family: var(--ils-font);
  border-bottom: 1px solid #000;
}
.hub-header__left {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
}
/* TASK-2428: horizontal graphic logo (white variant) replaces the
   text-based hub-brand. Height fits inside the 52px bar with breathing
   room; width is intrinsic to the SVG viewBox aspect ratio. */
.hub-brand__logo {
  display: block;
  height: 22px;
  width: auto;
  flex-shrink: 0;
}
.hub-brand__sub {
  padding-left: 14px;
  border-left: 1px solid rgba(255, 255, 255, 0.18);
  color: rgba(255, 255, 255, 0.55);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
}

.hub-nav {
  display: flex;
  align-items: stretch;
  gap: 4px;
  flex: 1 1 auto;
  min-width: 0;
  padding: 0 8px;
}
.hub-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 100%;
  padding: 0 16px;
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: rgba(255, 255, 255, 0.55);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: color 120ms, border-color 120ms;
  white-space: nowrap;
  position: relative;
  top: 1px; /* keeps the 2px underline flush with the bar's bottom */
}
.hub-tab:hover {
  color: rgba(255, 255, 255, 0.85);
}
.hub-tab--active {
  color: #fff;
  border-bottom-color: var(--ils-red);
}
.hub-tab--active:hover {
  color: #fff;
}
.hub-tab__icon {
  font-size: 15px;
  line-height: 1;
}
.hub-tab__label {
  line-height: 1;
}
.hub-tab__badge {
  display: inline-block;
  padding: 2px 6px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.75);
  border-radius: 3px;
  line-height: 1;
  margin-left: 4px;
}

.hub-header__right {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.hub-env {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.45);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

/* The old "🔗 URL Shortener" button in the translator topbar is now redundant
   — the hub header owns that navigation. Hide it via CSS to keep app.js
   binding logic untouched (TASK-2405). */
#url-shortener-btn { display: none !important; }

/* TASK-2406 — Cart Rewards config screen. Layout mirrors the URL Shortener
   screen (padded vertical stack, 1240px cap) so the two admin surfaces feel
   like the same app. */
.cart-rewards {
  padding: 24px 32px 48px;
  max-width: 1240px;
  margin: 0 auto;
  width: 100%;
  box-sizing: border-box;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.cart-rewards.hidden { display: none; }
.cart-rewards-head { margin-bottom: 20px; }
.cart-rewards-title {
  margin: 0 0 6px;
  font-size: 22px;
  font-weight: 700;
}
.cart-rewards-hint {
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.5;
}
.cart-rewards-hint code {
  background: var(--ils-cream, #F7F1E0);
  padding: 1px 6px;
  border-radius: 3px;
  font-size: 12px;
}
.cart-rewards-h3 {
  margin: 0 0 10px;
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--ils-meta, #7C7666);
  letter-spacing: 0.4px;
}
.cart-rewards-block {
  border-top: 1px solid var(--ils-line, #E4E1D8);
  padding-top: 18px;
  margin-top: 18px;
}
.cart-rewards-sku-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 360px;
}
.cart-rewards-sku-label {
  font-size: 11px;
  text-transform: uppercase;
  color: var(--ils-meta, #7C7666);
  letter-spacing: 0.4px;
}
.cart-rewards-sku-row input {
  padding: 7px 10px;
  border: 1px solid var(--ils-line, #E4E1D8);
  border-radius: 5px;
  font-family: inherit;
  font-size: 13px;
  background: white;
}
.cart-rewards-sku-hint {
  margin: 8px 0 0;
  font-size: 12px;
}
.cart-rewards-table td, .cart-rewards-table th {
  vertical-align: middle;
  padding: 6px 10px;
}
.cart-rewards-table input {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid var(--ils-line, #E4E1D8);
  border-radius: 4px;
  font-family: inherit;
  font-size: 13px;
  background: white;
  box-sizing: border-box;
}
.cart-rewards-add-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--ils-line, #E4E1D8);
  flex-wrap: wrap;
}
.cart-rewards-add-row input {
  padding: 7px 10px;
  border: 1px solid var(--ils-line, #E4E1D8);
  border-radius: 5px;
  font-family: inherit;
  font-size: 13px;
  background: white;
  min-width: 140px;
}
.cart-rewards-save-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid var(--ils-line, #E4E1D8);
}
.cart-rewards-status { font-size: 12px; }
.cart-rewards-status--ok { color: #2F6B3E; }
.cart-rewards-status--err { color: var(--ils-red); }
