/* ── Reset & variables ─────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --primary: #1d6f42;
  --primary-dark: #155234;
  --primary-light: #d1fae5;
  --bg: #f1f5f9;
  --card: #ffffff;
  --text: #1e293b;
  --muted: #64748b;
  --border: #e2e8f0;
  --danger: #dc2626;
  --danger-bg: #fef2f2;
  --success: #16a34a;
  --warning: #92400e;
  --warning-bg: #fef3c7;
  --radius: 12px;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans Thai', sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  font-size: 16px;
  line-height: 1.5;
}

/* ── Layout ────────────────────────────────────────────────────────────────── */
.page {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.page-header {
  background: var(--primary);
  color: white;
  padding: 1rem 1.25rem 1rem;
  position: sticky;
  top: 0;
  z-index: 10;
}

.page-header h1 {
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.header-logo {
  width: 28px;
  height: 28px;
  object-fit: contain;
  border-radius: 50%;
  background: white;
  padding: 2px;
  flex-shrink: 0;
}

.page-header .subtitle {
  font-size: 0.85rem;
  opacity: 0.85;
  margin-top: 0.15rem;
}

.page-header-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}

.header-back {
  color: white;
  text-decoration: none;
  font-size: 1.3rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  flex-shrink: 0;
}

.header-back:hover,
.header-back:active {
  background: rgba(255,255,255,0.15);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

.header-logout,
.header-link {
  color: white;
  opacity: 0.85;
  font-size: 0.85rem;
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
  padding: 0.35rem 0.7rem;
  border: 1px solid rgba(255,255,255,0.5);
  border-radius: 6px;
}

.header-logout:hover,
.header-link:hover {
  opacity: 1;
  background: rgba(255,255,255,0.15);
}

.header-date {
  color: white;
  opacity: 0.85;
  font-size: 0.85rem;
  white-space: nowrap;
  flex-shrink: 0;
}

.page-content {
  flex: 1;
  padding: 1rem 1rem 2rem;
}

/* ── Card / sections ───────────────────────────────────────────────────────── */
.card {
  background: var(--card);
  border-radius: var(--radius);
  padding: 1.25rem;
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
}

.section {
  margin-bottom: 1rem;
}

.section-title {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--primary);
  margin-bottom: 1rem;
}

.section-title-sub {
  font-weight: 600;
  color: var(--muted);
  font-size: 0.85rem;
}

.conditional-block {
  background: var(--bg);
  border-radius: 8px;
  padding: 0.75rem;
  margin-top: 0.5rem;
}

/* ── Form layout (single column on mobile, two panes on desktop) ───────────── */
.form-grid {
  display: grid;
  gap: 1rem;
  align-items: start;
}

.form-col {
  min-width: 0;
}

/* Two short fields sharing a row - collapses to one per row on narrow screens. */
.field-row {
  display: grid;
  gap: 0 1rem;
}

.form-actions {
  margin-top: 1rem;
}

.textarea-tall {
  min-height: 150px;
}

/* ── Login page ────────────────────────────────────────────────────────────── */
.login-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1.5rem;
  background: var(--bg);
}

.login-logo {
  margin-bottom: 0.75rem;
}

.login-logo-img {
  width: 90px;
  height: 90px;
  object-fit: contain;
  border-radius: 50%;
  background: white;
  padding: 8px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.12);
}

.page-logo {
  width: 64px;
  height: 64px;
  object-fit: contain;
  border-radius: 50%;
  background: white;
  padding: 6px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.10);
  margin-bottom: 0.75rem;
}

.login-title {
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--primary);
  margin-bottom: 0.25rem;
  text-align: center;
}

.login-sub {
  color: var(--muted);
  font-size: 0.9rem;
  margin-bottom: 1.75rem;
  text-align: center;
}

.login-card {
  width: 100%;
  max-width: 360px;
  background: var(--card);
  border-radius: var(--radius);
  padding: 1.75rem 1.5rem;
  box-shadow: 0 4px 20px rgba(0,0,0,.1);
}

/* ── Form elements ─────────────────────────────────────────────────────────── */
.field {
  margin-bottom: 1rem;
}

.field:last-child {
  margin-bottom: 0;
}

.field label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 0.4rem;
}

.field select,
.field input[type="text"],
.field input[type="password"],
.field input[type="date"],
.field input[type="datetime-local"],
.field input[type="number"],   /* 2026-10-06: a number box (points amount, wait days) had no style at all */
.field input[type="tel"],
.field input[type="email"],
.field textarea {
  width: 100%;
  padding: 0.75rem 1rem;
  font-size: 1rem;
  border: 2px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  appearance: auto;
  -webkit-appearance: auto;
  font-family: inherit;
}

.field textarea {
  resize: vertical;
}

.field input[type="file"] {
  width: 100%;
  padding: 0.6rem;
  font-size: 0.85rem;
  border: 2px dashed var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--muted);
}

.field select:focus,
.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--primary);
  background: white;
}

.field select:disabled {
  opacity: 0.6;
}

/* ── Combobox (searchable branch picker) ──────────────────────────────────── */
.combobox-field {
  position: relative;
}

.combobox-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  margin-top: 0.25rem;
  max-height: 240px;
  overflow-y: auto;
  background: var(--card);
  border: 2px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,.12);
}

.combobox-option {
  padding: 0.7rem 1rem;
  font-size: 0.95rem;
  color: var(--text);
  cursor: pointer;
  border-bottom: 1px solid var(--border);
}

.combobox-option:last-child {
  border-bottom: none;
}

.combobox-option:hover,
.combobox-option:active {
  background: var(--primary-light);
  color: var(--primary-dark);
}

.combobox-option-hint {
  padding: 0.5rem 1rem;
  font-size: 0.8rem;
  color: var(--muted);
  cursor: default;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

/* ── @ mention picker on the Timeline textareas (2026-10-01, intake.js initMentions) ──────
   Same box as the branch combobox. JS sets top/bottom and max-height so it opens under the
   textarea, or above it when .modal-panel (overflow: hidden) would clip it below. */
.mention-field {
  position: relative;
}

.mention-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  max-height: 240px;
  overflow-y: auto;
  background: var(--card);
  border: 2px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,.12);
}

.mention-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 0.9rem;
  font-size: 0.95rem;
  color: var(--text);
  cursor: pointer;
  border-bottom: 1px solid var(--border);
}

.mention-option:last-child {
  border-bottom: none;
}

.mention-option:hover,
.mention-option.is-active {
  background: var(--primary-light);
  color: var(--primary-dark);
}

.mention-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mention-chip {
  flex: none;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  background: var(--primary-light);
  color: var(--primary-dark);
}

.mention-chip-qc {
  background: #ede9fe;
  color: #5b21b6;
}

.field-hint {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.8rem;
  color: var(--muted);
}

.field-hint.field-hint-ok {
  color: var(--primary-dark);
}

.field-hint.field-hint-error {
  color: var(--danger);
}

/* ── Attachment tray (browse + drag & drop + clipboard paste) ─────────────── */
/* One tray, not a stack of <input type=file> rows: a native multiple-input replaces its
   whole selection each time the dialog reopens, so the tray keeps its own file list and
   syncs it into a single hidden name="photos" input instead. Files therefore accumulate
   across several picks, drops and pastes without anything being silently dropped. */
.attach-tray {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  width: 100%;
  padding: 1.1rem 1rem;
  border: 2px dashed var(--border);
  border-radius: 10px;
  background: var(--bg);
  color: var(--text);
  font-family: inherit;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

.dropzone:hover,
.dropzone:focus-visible,
.dropzone.is-dragover {
  border-color: var(--primary);
  background: var(--primary-light);
  outline: none;
}

.dropzone-icon {
  font-size: 1.5rem;
  line-height: 1.2;
}

.dropzone-title {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--primary-dark);
}

.dropzone-sub {
  font-size: 0.78rem;
  color: var(--muted);
}

.dz-touch {
  display: none;
}

@media (pointer: coarse) {
  .dz-desktop {
    display: none;
  }
  .dz-touch {
    display: block;
  }
}

.dropzone kbd {
  display: inline-block;
  padding: 0.05rem 0.35rem;
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: white;
  color: var(--text);
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 700;
}

.thumb-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 0.5rem;
}

.thumb-grid:empty {
  display: none;
}

.thumb {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--card);
}

.thumb-media {
  display: block;
  width: 100%;
  height: 78px;
  object-fit: cover;
  background: #0f172a;
}

.thumb-generic {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 78px;
  font-size: 1.7rem;
  background: var(--bg);
}

.thumb-name {
  padding: 0.28rem 0.4rem;
  font-size: 0.68rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.thumb-remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 50%;
  background: rgba(15, 23, 42, 0.72);
  color: white;
  font-size: 0.7rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.thumb-remove:hover {
  background: var(--danger);
}

/* ── Checkbox group (multi-select) ────────────────────────────────────────── */
.checkbox-group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* Wraps one option together with its own "โปรดระบุ" text box so the pair always stays
   in the same grid cell once .checkbox-group goes multi-column on desktop. */
.checkbox-item {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.checkbox-pill {
  display: flex;
  align-items: center;
  flex-wrap: wrap;   /* so a ด่วนมาก tag drops below the words instead of squeezing them */
  gap: 0.6rem;
  padding: 0.7rem 0.9rem;
  border: 2px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
}

.checkbox-pill:has(input:checked) {
  border-color: var(--primary);
  background: var(--primary-light);
}

/* An answer that pins the case to ด่วนมาก (บังคับด่วนมาก on its row, 2026-09-22): said on the
   pill itself, so nobody picks it without knowing, and unmistakable once it is picked. */
.checkbox-pill-urgent:has(input:checked) {
  border-color: var(--danger, #b42318);
  background: #fdeceb;
}

.pill-urgent-tag {
  /* Sits right after the words, not pushed to the far edge: margin-left:auto squeezed the
     label into a tall narrow column in the two-up grid (caught in a screenshot). */
  align-self: center;
  flex: none;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: var(--danger, #b42318);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  white-space: nowrap;
}

.detail-input {
  width: 100%;
  padding: 0.6rem 0.8rem;
  font-size: 0.9rem;
  border: 2px solid var(--primary);
  border-radius: 8px;
  background: white;
  color: var(--text);
  margin-top: -0.15rem;
  font-family: inherit;
}

.detail-input:focus {
  outline: none;
  border-color: var(--primary-dark);
}

/* ── Buttons ───────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.85rem 1.5rem;
  border-radius: 10px;
  border: none;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  transition: opacity 0.15s, transform 0.1s;
}

.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }

.btn-primary {
  background: var(--primary);
  color: white;
  width: 100%;
}

.btn-primary:hover { background: var(--primary-dark); }

.btn-outline {
  background: transparent;
  color: var(--primary);
  border: 2px solid var(--primary);
  width: 100%;
}

/* One Platform's one solid green: the Approve button (--success-solid, the same in both themes;
   --success turns pale in dark mode and white on it was unreadable). 2026-10-06. */
.btn-success {
  background: var(--success-solid);
  color: var(--on-success-solid);
  width: 100%;
}

.btn-success:hover { background: color-mix(in srgb, var(--success-solid) 88%, black); }

.btn-danger {
  background: transparent;
  color: var(--danger);
  border: 2px solid var(--danger);
  width: 100%;
}

.btn-danger:hover {
  background: var(--danger-bg);
}

.qc-send-form {
  margin-top: 0.85rem;
}

.qc-send-form .btn-primary { width: auto; }   /* the primary button, its own width (was the violet .btn-qc) */

.qc-sent-note {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px dashed var(--border);
  font-size: 0.85rem;
  color: var(--muted);
}

.qc-status-card {
  margin-top: 1rem;
}

/* "หน้าตาพิเศษหน่อย" per the original request - a visibly distinct gold/star treatment so
   the คะแนนคืนลูกค้า action stands out from every other plain button on the page. */
.btn-points {
  background: linear-gradient(135deg, #f59e0b, #d97706);
  color: white;
  padding: 0.7rem 1.4rem;
  font-size: 0.95rem;
  box-shadow: 0 2px 10px rgba(217, 119, 6, 0.35);
}

.btn-points:hover {
  background: linear-gradient(135deg, #d97706, #b45309);
}

.points-card {
  margin-top: 1rem;
  border: 1px solid #fde68a;
}

.points-status-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}

.points-amount {
  font-weight: 700;
  color: var(--text);
}

.points-note {
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 0.75rem;
}

.points-form {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px dashed var(--border);
}

.points-form:first-of-type {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.points-approve-buttons {
  display: flex;
  gap: 0.75rem;
}

.points-approve-buttons .btn {
  flex: 1;
}

/* Whose turn it is in the คะแนนคืนลูกค้า flow (2026-09-14). */
.points-stage-hint {
  font-size: 0.9rem;
  font-weight: 600;
  color: #92400e;
  margin-bottom: 0.5rem;
}

.delete-form {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px dashed var(--border);
}

/* ── Alerts ────────────────────────────────────────────────────────────────── */
.alert {
  padding: 0.75rem 1rem;
  border-radius: 8px;
  font-size: 0.9rem;
  margin-bottom: 1rem;
}

.alert-danger {
  background: var(--danger-bg);
  color: var(--danger);
  border: 1px solid #fca5a5;
}

/* ── Success page ──────────────────────────────────────────────────────────── */
.success-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 2rem;
  text-align: center;
  background: var(--bg);
}

.success-icon {
  font-size: 5rem;
  margin-bottom: 1rem;
}

.success-title {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--success);
  margin-bottom: 0.5rem;
}

.success-sub {
  color: var(--muted);
  font-size: 1rem;
  margin-bottom: 2rem;
}

.success-actions {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  width: 100%;
  max-width: 280px;
}

/* ── Choose page ───────────────────────────────────────────────────────────── */
.choose-options {
  display: grid;
  gap: 0.85rem;
  max-width: 820px;
  margin: 0 auto;
}

.choose-card {
  display: block;
  background: var(--card);
  border-radius: var(--radius);
  padding: 1.25rem;
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
  text-decoration: none;
  color: var(--text);
  border: 2px solid transparent;
}

.choose-card:hover {
  border-color: var(--primary);
}

.choose-card-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--primary);
  margin-bottom: 0.25rem;
}

.choose-card-sub {
  font-size: 0.85rem;
  color: var(--muted);
}

/* ── Case dashboard ────────────────────────────────────────────────────────── */
.tabbar {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  margin-bottom: 0.85rem;
  padding-bottom: 0.2rem;
}

.tab {
  flex-shrink: 0;
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  border: 2px solid var(--border);
  background: var(--card);
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.tab:hover {
  border-color: var(--primary);
  color: var(--primary-dark);
}

.tab.is-active {
  background: var(--primary);
  border-color: var(--primary);
  color: white;
}

.tab-count {
  display: inline-block;
  min-width: 1.35rem;
  padding: 0 0.35rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.12);
  font-size: 0.78rem;
  text-align: center;
}

.tab.is-active .tab-count {
  background: rgba(255, 255, 255, 0.25);
}

.filterbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.85rem;
}

.filterbar input[type="search"] {
  flex: 1 1 160px;
  min-width: 0;
  max-width: 220px;
  padding: 0.55rem 0.8rem;
  border: 2px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
  font-family: inherit;
  font-size: 0.95rem;
}

.filterbar select {
  flex: 0 1 auto;
  max-width: 150px;
  padding: 0.55rem 0.5rem;
  border: 2px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
}

.filterbar input:focus,
.filterbar select:focus {
  outline: none;
  border-color: var(--primary);
}

/* จาก/ถึง stay paired as one unit so they wrap together, not split apart. */
.filter-date-group {
  display: flex;
  flex-wrap: nowrap;
  gap: 0.4rem;
  flex: 0 0 auto;
}

.filter-date-label {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.78rem;
  color: var(--muted);
  font-weight: 600;
  white-space: nowrap;
}

.filter-checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  color: var(--text);
  font-weight: 600;
}

.filter-date-label input[type="date"] {
  width: 128px;
  padding: 0.5rem 0.4rem;
  border: 2px solid var(--border);
  border-radius: 8px;
  background: var(--card);
  color: var(--text);
  font-family: inherit;
  font-size: 0.8rem;
}

.filter-date-label input[type="date"]:focus {
  outline: none;
  border-color: var(--primary);
}

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.85rem;
  margin-top: 1rem;
}

.pagination-label {
  font-size: 0.85rem;
  color: var(--muted);
}

.pagination .is-disabled {
  opacity: 0.4;
  pointer-events: none;
}

.btn-sm {
  padding: 0.55rem 1rem;
  font-size: 0.88rem;
  border-radius: 8px;
  background: var(--primary);
  color: white;
}

.btn-ghost {
  background: transparent;
  color: var(--muted);
  border: 2px solid var(--border);
}

.case-count {
  font-size: 0.82rem;
  color: var(--muted);
  margin-bottom: 0.5rem;
}

.case-list {
  display: grid;
  gap: 0.7rem;
}

.case-card {
  display: block;
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
  text-decoration: none;
  color: var(--text);
}

.case-card:hover {
  border-color: var(--primary);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .1);
}

.case-card.age-amber { border-left-color: #d97706; }
.case-card.age-red { border-left-color: var(--danger); }

.case-card-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.4rem;
}

.case-ticket {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.badge {
  display: inline-block;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
}

.badge-b2c { background: #e0e7ff; color: #3730a3; }
.badge-b2b { background: #fae8ff; color: #86198f; }
.badge-backoffice { background: #ccfbf1; color: #115e59; }
.badge-brandops { background: #ffedd5; color: #9a3412; }
.badge-status { background: var(--primary-light); color: var(--primary-dark); }
.badge-urgent { background: var(--danger-bg); color: var(--danger); }
.badge-warn { background: var(--warning-bg); color: var(--warning); }
.badge-follow { background: #cffafe; color: #155e75; }
.badge-frontline { background: #fef3c7; color: #92400e; }
.badge-age { background: var(--bg); color: var(--muted); }
.badge-sla-overdue { background: var(--danger-bg); color: var(--danger); }
.badge-sla-due { background: var(--warning-bg); color: var(--warning); }
.badge-sla-ok { background: var(--primary-light); color: var(--primary-dark); }
.badge-dept { background: #fef3c7; color: #92400e; }
.badge-points { background: #fef9c3; color: #854d0e; }
.badge-points-type { background: #e0e7ff; color: #3730a3; }

.case-card-title {
  font-size: 0.98rem;
  font-weight: 700;
  color: var(--primary-dark);
  margin-bottom: 0.25rem;
}

.case-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.85rem;
  font-size: 0.82rem;
  color: var(--muted);
}

.case-card-details {
  margin-top: 0.4rem;
  font-size: 0.85rem;
  color: var(--text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.case-row-id {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}

.case-row-date {
  font-size: 0.78rem;
  color: var(--muted);
  white-space: nowrap;
}

.case-row-branch {
  margin-bottom: 0.4rem;
}

.case-row-subject-top {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.2rem;
}

.case-row-owner {
  font-size: 0.85rem;
  color: var(--text);
  margin-top: 0.4rem;
}

.case-row-owner em {
  color: var(--muted);
  font-style: normal;
}

.case-row-attach {
  font-size: 0.76rem;
  color: var(--muted);
  font-weight: 600;
}

.case-row-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem;
  margin-top: 0.55rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border);
}

.empty-state {
  padding: 3rem 1rem;
  text-align: center;
  color: var(--muted);
}

.empty-icon {
  font-size: 2.5rem;
  margin-bottom: 0.5rem;
}

.alert-info {
  background: #eff6ff;
  color: #1e40af;
  border: 1px solid #bfdbfe;
}

.alert-success {
  background: var(--primary-light);
  color: var(--primary-dark);
  border: 1px solid var(--primary);
}

/* ── Case detail ───────────────────────────────────────────────────────────── */
.detail-badges {
  margin-bottom: 0.9rem;
}

.kv {
  display: grid;
  /* The label takes its own width up to 45%, then wraps (2026-10-05): with `auto` a long form
     question ("QR Code สแกนไม่ได้ / ชำรุด-ข้อมูลใบเสร็จ เช่น ID สาขา ...") took the whole row and
     squeezed its answer to a few letters a line, on the case page and its PDF. */
  grid-template-columns: fit-content(45%) minmax(0, 1fr);
  gap: 0.35rem 0.85rem;
  margin-bottom: 1rem;
  font-size: 0.9rem;
}

.kv dt {
  font-weight: 600;
  color: var(--muted);
  word-break: break-word;
}

.kv dd {
  color: var(--text);
  word-break: break-word;
}

/* A value somebody typed on several lines (the points request's รายละเอียดเพิ่มเติม). */
.kv dd.kv-multiline {
  white-space: pre-wrap;
}

.kv-owner-label {
  color: var(--text);
  font-weight: 800;
}

.kv-owner-value {
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--primary-dark);
}

.readonly-text {
  padding: 0.75rem 1rem;
  border: 2px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-word;
}

.more-fields {
  margin-bottom: 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem 0.85rem;
  background: var(--bg);
}

.more-fields summary {
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
}

.more-fields .kv {
  grid-template-columns: 1fr;
  margin-top: 0.75rem;
  margin-bottom: 0;
  font-size: 0.85rem;
}

.more-fields .kv dt {
  margin-top: 0.6rem;
}

.more-fields .kv dt:first-child {
  margin-top: 0;
}

.field select:disabled,
.field textarea:disabled,
.field input:disabled {
  background: var(--bg);
  color: var(--muted);
  cursor: not-allowed;
}

/* ── Legacy follow-up rows on the Timeline (the separate comment card was removed 2026-09-14) */
.badge-followup-entry {
  background: var(--primary-light);
  color: var(--primary-dark);
}

/* ── Print / PDF export ────────────────────────────────────────────────────── */
.print-toolbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.25rem;
  background: var(--card);
  border-bottom: 1px solid var(--border);
}

.print-toolbar .btn-primary {
  width: auto;
  padding: 0.65rem 1.25rem;
}

.print-sheet {
  max-width: 780px;
  margin: 1.5rem auto;
  padding: 0 1.25rem 3rem;
}

.print-head {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: 1rem;
  padding-bottom: 1rem;
  border-bottom: 2px solid var(--primary);
}

.print-logo {
  width: 44px;
  height: 44px;
  object-fit: contain;
  border-radius: 50%;
  background: white;
  padding: 4px;
  box-shadow: 0 1px 4px rgba(0,0,0,.15);
}

.print-title {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--primary-dark);
}

.print-sub {
  font-size: 0.82rem;
  color: var(--muted);
}

.print-badges {
  display: flex;
  gap: 0.4rem;
  margin-bottom: 1rem;
}

.print-section {
  margin-top: 1.25rem;
}

.print-section-title {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--primary);
  margin-bottom: 0.5rem;
}

.print-comment {
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
}

.print-comment:last-child {
  border-bottom: none;
}

.print-comment-head {
  font-weight: 700;
  color: var(--muted);
  font-size: 0.78rem;
  margin-bottom: 0.2rem;
}

.print-comment-attach {
  margin-top: 0.2rem;
  font-size: 0.78rem;
  color: var(--muted);
}

@media print {
  .no-print {
    display: none !important;
  }

  body {
    background: white;
  }

  .print-sheet {
    margin: 0;
    max-width: none;
  }
}

/* ── Overview / stats ──────────────────────────────────────────────────────── */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.7rem;
  margin-bottom: 1rem;
}

.stat-card {
  padding: 1rem;
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
  text-align: center;
}

.stat-card-danger {
  background: var(--danger-bg);
}

.stat-card-warn {
  background: var(--warning-bg);
}

.stat-value {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--primary-dark);
}

.stat-card-danger .stat-value {
  color: var(--danger);
}

.stat-card-warn .stat-value {
  color: var(--warning);
}

.stat-label {
  font-size: 0.78rem;
  color: var(--muted);
  margin-top: 0.2rem;
}

.overview-grid {
  display: grid;
  gap: 1rem;
}

.bar-list {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.bar-row {
  display: grid;
  grid-template-columns: minmax(6rem, auto) 1fr 2.2rem;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.85rem;
}

.bar-label {
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bar-track {
  height: 10px;
  border-radius: 999px;
  background: var(--bg);
  overflow: hidden;
}

.bar-fill {
  height: 100%;
  background: var(--primary);
  border-radius: 999px;
}

.bar-count {
  text-align: right;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* ── Wide screens ──────────────────────────────────────────────────────────── */
/* Everything above is the phone layout and stays untouched below 640px. From 640px up
   short field pairs sit side by side; from 1024px up the shell goes full-bleed (green
   header spanning the whole window, content centred at a readable max width) and the
   form splits into two panes so a desktop screen isn't a narrow strip down the middle. */

@media (min-width: 640px) {
  .field-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .choose-options {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .page {
    max-width: none;
  }

  .page-header {
    padding: 1rem 2rem;
  }

  .page-header-row,
  .page-header .subtitle {
    max-width: 1240px;
    margin-left: auto;
    margin-right: auto;
  }

  .page-header h1 {
    font-size: 1.25rem;
  }

  .page-content {
    width: 100%;
    max-width: 1240px;
    margin: 0 auto;
    padding: 1.75rem 2rem 3rem;
  }

  .card {
    padding: 1.5rem 1.75rem;
  }

  .form-grid {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: 1.5rem;
  }

  .textarea-tall {
    min-height: 200px;
  }

  .checkbox-group {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }

  .combobox-results {
    max-height: 320px;
  }

  .form-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 1.25rem;
  }

  .form-actions .btn-primary {
    width: auto;
    min-width: 260px;
  }

  /* Two cards alone on a wide screen look lost at phone proportions - give them room. */
  .choose-options {
    gap: 1.5rem;
    margin-top: 3rem;
  }

  .choose-card {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 150px;
    padding: 2rem;
  }

  .choose-card-title {
    font-size: 1.3rem;
    margin-bottom: 0.4rem;
  }

  .choose-card-sub {
    font-size: 0.95rem;
  }

  .choose-card-wide {
    grid-column: 1 / -1;
    min-height: 0;
  }

  /* A single column of table-style rows, not a card grid - scannable like a spreadsheet
     (ID/date, branch/customer, subject, owner, status as aligned columns per row). */
  /* 2026-10-06 (Amm: "shouldn't it be all aligned?"): every row is its own grid, so a track that
     can grow past its share (a bare fr) let a long QC chip widen that row's last column and shove
     the others left. minmax(0, …) holds every row to the same columns; the first fits the
     "ส่ง QC dd/mm/yyyy hh:mm" line; a long chip wraps inside its column. */
  .case-card {
    display: grid;
    grid-template-columns: 180px minmax(0, 1.1fr) minmax(0, 1.6fr) minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: center;
    gap: 0 1.1rem;
    padding: 0.7rem 1.1rem;
  }

  .case-row-id {
    flex-direction: column;
    align-items: flex-start;
    margin-bottom: 0;
    gap: 0.15rem;
  }

  .case-row-branch {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    margin-bottom: 0;
  }

  .case-row-branch span {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .case-row-subject {
    min-width: 0;
  }

  .case-row-owner {
    margin-top: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .case-row-status {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
    justify-content: flex-start;
  }

  .case-row-status .badge {
    white-space: normal;
    max-width: 100%;
  }

  .stat-grid {
    grid-template-columns: repeat(7, minmax(0, 1fr));
  }

  .overview-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .overview-wide {
    grid-column: 1 / -1;
  }
}

/* ── Cases dashboard v2 (sidebar + welcome banner + stat tiles + 4-cell cards) ───────────
   Mobile-first: sidebar is a horizontally-scrollable pill row up top (reusing the same
   look as .tabbar), stat tiles wrap 2-up, case cards stack their 4-cell grid 2x2. From
   1024px the sidebar becomes a fixed left column and the grid opens up - same breakpoint
   convention as the rest of this file. */

.cases-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  width: 100%;
}

.cases-sidebar {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  background: var(--card);
  border-bottom: 1px solid var(--border);
  padding: 0.75rem 1rem;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  color: var(--primary-dark);
  margin-bottom: 0.25rem;
}

.sidebar-logo {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: contain;
}

.sidebar-profile {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}

.sidebar-avatar,
.topbar-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--primary);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.9rem;
  flex-shrink: 0;
}

.sidebar-profile-name {
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-nav {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  padding-bottom: 0.2rem;
}

.sidebar-link {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.8rem;
  border-radius: 999px;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.sidebar-link:hover {
  color: var(--primary-dark);
}

.sidebar-link.is-active {
  background: var(--primary);
  color: white;
}

.sidebar-badge {
  display: inline-block;
  min-width: 1.2rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.12);
  font-size: 0.72rem;
  text-align: center;
}

.sidebar-link.is-active .sidebar-badge {
  background: rgba(255, 255, 255, 0.28);
}

.sidebar-badge-danger {
  background: var(--danger);
  color: white;
}

.sidebar-help {
  font-size: 0.8rem;
  color: var(--muted);
  text-decoration: none;
}

.sidebar-help:hover {
  color: var(--primary-dark);
}

.cases-main {
  flex: 1;
  padding: 0.85rem 1rem 2rem;
  min-width: 0;
}

/* ── Top bar ─────────────────────────────────────────────────────────────────────────── */
.cases-topbar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.85rem;
}

.topbar-search-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--card);
  border: 2px solid var(--border);
  border-radius: 999px;
  padding: 0.5rem 0.9rem;
}

.topbar-search-wrap input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--text);
}

.topbar-search-icon {
  opacity: 0.6;
  flex-shrink: 0;
}

.topbar-date-pill {
  flex-shrink: 0;
  display: none;
  padding: 0.5rem 0.8rem;
  border-radius: 999px;
  background: var(--primary-light);
  color: var(--primary-dark);
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

.topbar-bell {
  position: relative;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--card);
  border: 2px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  font-size: 1rem;
}

.topbar-bell-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 1.1rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  background: var(--danger);
  color: white;
  font-size: 0.65rem;
  font-weight: 700;
  text-align: center;
  line-height: 1.3;
}

/* ── Welcome banner ──────────────────────────────────────────────────────────────────── */
.welcome-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: white;
  border-radius: var(--radius);
  padding: 1.1rem 1.25rem;
  margin-bottom: 0.85rem;
}

.welcome-title {
  font-size: 1.1rem;
  font-weight: 700;
}

.welcome-sub {
  font-size: 0.85rem;
  opacity: 0.9;
  margin-top: 0.15rem;
}

.welcome-cta {
  flex-shrink: 0;
  background: white;
  color: var(--primary-dark);
  font-weight: 700;
  text-decoration: none;
  padding: 0.6rem 1.1rem;
  border-radius: 8px;
  white-space: nowrap;
}

.welcome-cta:hover {
  background: var(--primary-light);
}

/* ── Stat tiles (clickable filters) ─────────────────────────────────────────────────── */
.stat-tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
  margin-bottom: 0.85rem;
}

.stat-tile {
  display: block;
  background: var(--card);
  border: 2px solid transparent;
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  text-decoration: none;
  color: var(--text);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
}

.stat-tile:hover {
  border-color: var(--primary);
}

.stat-tile.is-active {
  border-color: var(--primary);
  background: var(--primary-light);
}

.stat-tile-count {
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--primary-dark);
  font-variant-numeric: tabular-nums;
}

.stat-tile-label {
  font-size: 0.85rem;
  font-weight: 700;
  margin-top: 0.1rem;
}

.stat-tile-sub {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 0.1rem;
}

/* ── QC board (/cases/qc-board, 2026-09-15) ─────────────────────────────────────────── */
.qc-pending-tiles {
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}

.stat-tile.stat-tile-highlight {
  border-color: var(--warning);
  background: var(--warning-bg);
}

.stat-tile.stat-tile-highlight .stat-tile-count {
  color: var(--warning);
}

.qc-status-tiles {
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.45rem;
}

.qc-status-tiles .stat-tile {
  padding: 0.55rem 0.7rem;
}

.qc-status-tiles .stat-tile-count {
  font-size: 1.1rem;
}

.qc-status-tiles .stat-tile-label {
  font-size: 0.75rem;
  font-weight: 600;
}

.qc-status-tiles .stat-tile.is-empty {
  opacity: 0.6;
}

.case-card.qc-waiting-cx {
  border-left-color: var(--warning);
}

.badge-qc-cx { background: var(--warning-bg); color: var(--warning); }

.case-row-successor {
  font-size: 0.78rem;
  color: var(--muted);
}

/* ── Advanced filters (collapsed by default, holds the original filter bar) ────────────── */
.filter-details {
  margin-bottom: 0.85rem;
}

.filter-details > summary {
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
  padding: 0.4rem 0;
  list-style: none;
}

.filter-details > summary::-webkit-details-marker {
  display: none;
}

.filter-details > summary::before {
  content: "▸ ";
}

.filter-details[open] > summary::before {
  content: "▾ ";
}

.filter-details .filterbar {
  margin-top: 0.5rem;
  margin-bottom: 0;
}

/* ── Priority badge + status dot (shared by case cards + case detail) ──────────────────── */
.priority-badge.priority-p1 { background: var(--danger-bg); color: var(--danger); }
.priority-badge.priority-p2 { background: var(--warning-bg); color: var(--warning); }
.priority-badge.priority-p3 { background: var(--bg); color: var(--muted); }

.status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--primary);
  margin-right: 0.35rem;
}

.status-dot.status-dot-done {
  background: var(--muted);
}

.overdue-tag {
  display: inline-block;
  margin-top: 0.15rem;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--danger);
}

.strip-overdue {
  color: var(--danger);
}

/* ── 4-cell case cards ───────────────────────────────────────────────────────────────── */
.case-card-v2 {
  display: block;
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
  text-decoration: none;
  color: var(--text);
  margin-bottom: 0.7rem;
}

.case-card-v2:last-child {
  margin-bottom: 0;
}

.case-card-v2:hover {
  border-color: var(--primary);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .1);
}

.case-card-v2.age-amber { border-left-color: #d97706; }
.case-card-v2.age-red { border-left-color: var(--danger); }

.case-card-v2-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.4rem;
}

.case-card-v2-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; }

/* 1200px and up (2026-10-16, Amm): case + chips left, the state centred on the card, when right.
   The side columns are equal, so the middle one is the card's own centre. Narrower, the three
   squeezed each other (the date broke at 1024), so there the state follows the chips. */
@media (min-width: 1200px) {
  .case-card-v2-top { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); column-gap: 1rem; }
  .case-card-v2-state { justify-content: center; margin-left: 0; }
  .case-card-v2-when { grid-column: 3; justify-self: end; }
}

.case-card-v2-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.75rem;
  font-size: 0.88rem;
  color: var(--text);
}

/* 2026-10-16 (Amm): the card in four short lines - when (top right), what and where, who and
   how, where it stands - with the photos in a column of the same width on every card. */
.case-card-v2-when {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-size: 0.82rem;
  line-height: 1.4;
  text-align: right;
}

.case-card-v2-when strong { color: var(--text); white-space: nowrap; }
.case-card-v2-age { font-size: 0.75rem; color: var(--muted); }

.case-card-v2-about {
  margin-top: 0.15rem;
  font-size: 0.82rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 2026-09-29: a search hit that came from the case's Timeline, not from the card's own fields. */
.case-card-v2-comment-hit {
  font-size: 0.78rem;
  color: var(--muted);
  margin-top: 0.2rem;
}

/* in the top row: after the badges, centred from 1200px (2026-10-16, Amm) */
.case-card-v2-state {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  margin-left: 0.4rem;
  font-size: 0.85rem;
}

.case-card-v2-status { font-weight: 700; }
.case-card-v2-action { color: var(--muted); }
.case-card-v2-due { font-size: 0.8rem; color: var(--muted); }
.case-card-v2-who { margin-left: auto; font-size: 0.8rem; color: var(--muted); }

.case-card-v2 { min-width: 0; }   /* a grid item: the one-line .case-card-v2-about must not widen it */
.case-card-v2-main { display: block; }
.case-card-v2-body { min-width: 0; }

/* Phone: one row of small thumbs under the text. */
.case-card-media.thumb-grid {
  display: flex;
  gap: 0.35rem;
  margin-top: 0.55rem;
}

.case-card-media .thumb {
  display: block;
  flex: 0 0 48px;
  cursor: zoom-in;
}

.case-card-media .thumb-media,
.case-card-media .thumb-generic,
.thumb-more {
  width: 48px;
  height: 48px;
}

.thumb-more {
  flex: 0 0 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--muted);
  font-weight: 700;
  font-size: 0.85rem;
}

/* Desktop: the photos' column is there on every card, empty or not, so the text lines up. */
@media (min-width: 900px) {
  .case-card-v2-main {
    display: grid;
    grid-template-columns: minmax(0, 1fr) calc(4 * 48px + 3 * 0.35rem);
    column-gap: 1rem;
    align-items: start;
  }

  .case-card-media.thumb-grid { margin-top: 0; }
}

/* Phone: the when line drops under the badges, left-aligned on one line. */
@media (max-width: 559px) {
  .case-card-v2-state { margin-left: 0; }
  .case-card-v2-when { margin-left: 0; flex: 1 1 100%; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 0.5rem; text-align: left; }
}

/* ── Dashboard top bar + filter panel (2026-09-15: no top search box, filters always open) ── */
.cases-topbar {
  justify-content: flex-end;
}

.filter-panel {
  margin-bottom: 0.85rem;
}

.filter-panel-title {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
  padding: 0.4rem 0;
}

.filter-panel .filterbar {
  margin-top: 0.3rem;
  margin-bottom: 0;
}

/* ── Case detail header (priority/id/company line + 3-cell strip) ──────────────────────── */
.case-top-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}

.case-detail-id {
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--text);
}

.case-detail-sub {
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 0.85rem;
}

.strip-3cell {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  gap: 0.6rem;
  background: var(--card);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
  margin-bottom: 0.85rem;
}

.strip-cell {
  min-width: 0;
}

.strip-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  margin-bottom: 0.2rem;
}

.strip-value {
  font-size: 0.95rem;
  font-weight: 700;
}

/* ── Progress composer ───────────────────────────────────────────────────────────────── */
.composer-card {
  margin-bottom: 0.85rem;
}

.composer-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}

.composer-recorder {
  font-size: 0.8rem;
  color: var(--muted);
  font-weight: 600;
}

.composer-sub {
  font-size: 0.82rem;
  color: var(--muted);
  margin-bottom: 0.9rem;
}

.composer-note {
  font-size: 0.75rem;
  color: var(--muted);
  margin-bottom: 0.75rem;
}

/* ── Timeline ────────────────────────────────────────────────────────────────────────── */
.timeline-card {
  margin-bottom: 0.85rem;
}

.timeline-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  /* Taller since 2026-09-14: this is now the only feed, carrying full comments + QC findings. */
  max-height: 640px;
  overflow-y: auto;
  position: relative;
  padding-left: 1.4rem;
}

/* The rail: one continuous line down the left, one dot per entry (mockup's look). */
.timeline-list::before {
  content: "";
  position: absolute;
  left: 0.42rem;
  top: 0.5rem;
  bottom: 0.5rem;
  width: 2px;
  background: var(--border);
}

.timeline-item {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.6rem;
  padding-bottom: 0.9rem;
  font-size: 0.85rem;
  position: relative;
}

.timeline-item::before {
  content: "";
  position: absolute;
  left: -1.4rem;
  top: 0.3rem;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  background: #2f6fed;
  border: 2px solid #fff;
  box-shadow: 0 0 0 2px #dbe6fb;
  margin-left: 0.12rem;
}

.timeline-item:last-child {
  padding-bottom: 0;
}

.timeline-time {
  flex-shrink: 0;
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  width: 100%;
}

.timeline-text {
  color: var(--text);
  font-weight: 600;
  width: 100%;
  white-space: pre-wrap;
  word-break: break-word;
}

.timeline-item-followup::before {
  background: var(--primary);
}

.timeline-followup {
  width: 100%;
  font-size: 0.82rem;
  color: var(--text);
}

.timeline-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.6rem;
  width: 100%;
  margin-top: 0.15rem;
}

.timeline-chip {
  display: inline-block;
  background: var(--surface-sunken);
  color: var(--ink-secondary);
  border-radius: 6px;
  padding: 0.15rem 0.55rem;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

.timeline-action {
  color: var(--muted);
  font-size: 0.8rem;
}

.timeline-attachments {
  width: 100%;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  max-width: 320px;
  margin-top: 0.25rem;
}

/* The video tile is a static 🎬 since 2026-10-08 (it was a <video> loading its first frame):
   it keeps the height the frame had, so a row of Timeline tiles stays level. */
.timeline-attachments .thumb-media,
.timeline-attachments .thumb[data-media="video"] .thumb-generic {
  height: 56px;
}

/* 2026-09-29: a hidden entry (never deleted). The dot goes grey, the words become one muted line,
   and a lead's "ดูข้อความเดิม" opens the original under it. The ซ่อน control is a quiet text
   button beside the time, so it never competes with the entry itself. */
.timeline-item-hidden::before {
  background: var(--border);
  box-shadow: 0 0 0 2px var(--bg);
}

.timeline-hidden-line {
  width: 100%;
  color: var(--muted);
  font-size: 0.8rem;
  font-style: italic;
}

.timeline-hide-form {
  display: inline;
  margin: 0 0 0 0.35rem;
}

.timeline-hide-btn {
  background: none;
  border: none;
  padding: 0 0.15rem;
  color: var(--muted);
  font: inherit;
  font-size: 0.72rem;
  text-decoration: underline;
  cursor: pointer;
}

.timeline-hide-btn:hover,
.timeline-hide-btn:focus-visible {
  color: var(--danger, #b3261e);
}

.timeline-hide-btn:disabled {
  cursor: progress;
  opacity: 0.6;
}

.timeline-original {
  width: 100%;
  font-size: 0.8rem;
  margin-top: 0.1rem;
}

.timeline-original > summary {
  cursor: pointer;
  color: var(--muted);
  text-decoration: underline;
  width: fit-content;
}

.timeline-original-body {
  margin-top: 0.3rem;
  padding: 0.4rem 0.6rem;
  border-left: 3px solid var(--border);
  background: var(--bg);
  border-radius: 0 6px 6px 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.timeline-original-body .timeline-text {
  font-weight: 400;
}

.timeline-original-body .timeline-hide-form {
  margin: 0.2rem 0 0;
}

/* ── Activity Log (admin) - same "time + text" language as .timeline-*, but a full page of
   unbounded per-day groups rather than one capped-height widget, so no max-height/scroll. */
.activity-day-group {
  margin-bottom: 0.85rem;
}

.activity-list {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}

.activity-item {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.6rem;
  padding-bottom: 0.65rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
}

.activity-item:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.activity-time {
  flex-shrink: 0;
  width: 48px;
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.activity-body {
  flex: 1;
  min-width: 200px;
  color: var(--text);
}

.activity-actor {
  font-weight: 600;
}

.activity-ref {
  margin-top: 0.2rem;
  font-size: 0.75rem;
  color: var(--muted);
}

/* ── Case detail modal overlay (JS-driven, progressive enhancement over the plain page) ── */
.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  z-index: 100;
  padding: 1.25rem;
  overflow-y: auto;
}

.modal-overlay.is-open {
  display: flex;
  align-items: flex-start;
  justify-content: center;
}

body.modal-open {
  overflow: hidden;
}

.modal-panel {
  position: relative;
  width: 100%;
  max-width: 1000px;
  margin: 1.5rem auto;
  background: var(--bg);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .35);
}

.modal-panel .page {
  min-height: 0;
}

.modal-close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  /* Above the fragment's sticky .page-header (z-index 10), which shares this stacking
     context (.modal-panel is position: relative). At 5 the green header painted over the
     button and swallowed every click on it - found by a Playwright hit-test 2026-09-15. */
  z-index: 11;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.35);
  color: white;
  font-size: 1.1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-close:hover {
  background: rgba(0, 0, 0, 0.55);
}

/* .modal-loading (one line of white text while the fragment was in flight) was replaced by
   .modal-skeleton at the bottom of this file - see "Case-modal skeleton". */

/* ── Standalone dialog chrome for direct-URL intake pages (/, /b2c, /b2b) ───────────────
   A link shared straight to a branch (no dashboard behind it) still loads these as real,
   independent pages - but reuses the exact .modal-panel look the JS overlay above already
   uses, so it reads as a popup/dialog instead of the old plain full-width page. Below
   640px it drops the rounding/shadow/margin and goes edge-to-edge, matching how a dialog
   commonly becomes a fullscreen sheet on a phone. */
.standalone-dialog-backdrop {
  min-height: 100vh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 1.5rem 1.25rem;
}

.standalone-dialog-backdrop .modal-panel {
  margin: 0 auto;
}

@media (max-width: 639px) {
  .standalone-dialog-backdrop {
    padding: 0;
  }

  .standalone-dialog-backdrop .modal-panel {
    border-radius: 0;
    box-shadow: none;
    min-height: 100vh;
  }
}

@media (min-width: 640px) {
  .stat-tiles {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .strip-3cell {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .cases-shell {
    flex-direction: row;
    align-items: stretch;
  }

  .cases-sidebar {
    flex-direction: column;
    width: 240px;
    flex-shrink: 0;
    border-bottom: none;
    border-right: 1px solid var(--border);
    padding: 1.25rem 1rem;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
  }

  .sidebar-nav {
    flex-direction: column;
    overflow-x: visible;
  }

  .sidebar-link {
    justify-content: space-between;
  }

  .sidebar-help {
    margin-top: auto;
  }

  .cases-main {
    padding: 1.75rem 2rem 3rem;
    max-width: 1240px;
    margin: 0 auto;
    width: 100%;
  }

  .topbar-date-pill {
    display: block;
  }

  /* 5 tiles since the ส่งต่อหน่วยงาน tile was removed (2026-09-14). */
  .stat-tiles {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* ── Label row with a trailing gear link ──────────────────────────────────────────────────
   Used above the composer's "Action ถัดไป" select and the intake forms' topic select: the
   <label> keeps its .field look, and a small "⚙️ แก้ไขตัวเลือก" link sits right-aligned on the
   same baseline, opening /settings/options. The label is wrapped rather than having the link
   inside it, so the <label> element itself is untouched for anything that reads it. */
.label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}

.field .label-row label {
  margin-bottom: 0;
}

.gear-link {
  flex-shrink: 0;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}

.gear-link:hover,
.gear-link:focus-visible {
  color: var(--primary-dark);
  text-decoration: underline;
}

/* ── Settings panels (shared by /admin/sla-rules and /settings/options) ───────────────────
   Moved here verbatim from sla_rules.html's inline <style> so both pages share one look; the
   SLA page's own rule-editor styles (.sla-grid, .sla-rule*, .sla-kind-head, .sla-min) stay
   inline there. Values are unchanged so that page renders exactly as before. */
.sla-intro { background: #eef3fb; border: 1px solid #d6e2f5; border-radius: 14px; padding: 1rem 1.25rem; margin-bottom: 1rem; }
.sla-intro h2 { margin: 0 0 0.25rem; font-size: 1.05rem; }
.sla-intro p { margin: 0; color: #4b5563; font-size: 0.9rem; }
.sla-panel { background: #fff; border-radius: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); padding: 1rem 1.1rem; }
.sla-panel h3 { margin: 0; font-size: 1rem; }
.sla-panel .sub { color: #6b7280; font-size: 0.82rem; margin: 0.15rem 0 0.9rem; }
.sla-add { display: flex; gap: 0.5rem; margin-bottom: 0.9rem; }
.sla-add input[type=text] { flex: 1; }
.sla-row { display: flex; align-items: center; gap: 0.5rem; border: 1px solid #e5e7eb; border-radius: 12px; padding: 0.55rem 0.7rem; margin-bottom: 0.55rem; }
.sla-row .name { flex: 1; font-weight: 600; }
.btn-xs { padding: 0.3rem 0.6rem; font-size: 0.78rem; }

/* ── /settings/options (ตั้งค่าตัวเลือก) ────────────────────────────────────────────────
   Three .sla-panel cards: one column on a phone, two from 640px (the Action panel spans the
   whole first row so the two topic panels sit side by side), three across from 1024px. Rows
   wrap so a long topic name plus its ▲ / ▼ / remove tools never overflow a narrow panel. */
.options-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem;
}

.options-panel {
  min-width: 0;
  scroll-margin-top: 5rem; /* the sticky green header would otherwise cover an anchored panel */
}

.options-panel .sla-add input[type=text] {
  min-width: 0;
  padding: 0.55rem 0.8rem;
  font-size: 0.95rem;
  border: 2px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  font-family: inherit;
}

.options-panel .sla-add input[type=text]:focus {
  outline: none;
  border-color: var(--primary);
  background: white;
}

.options-row {
  flex-wrap: wrap;
}

.options-row .name {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.45rem;
  min-width: 8rem;
  overflow-wrap: anywhere;
}

.options-row-tools {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-left: auto;
  flex-shrink: 0;
}

.options-row-tools form {
  display: flex;
}

.btn-move {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: #1f2f5c;
  font-size: 0.65rem;
  line-height: 1;
  font-family: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.btn-move:hover:not(:disabled) {
  border-color: #1f2f5c;
  background: #e8f0fb;
}

.btn-move:disabled {
  opacity: 0.3;
  cursor: default;
}

.options-chip {
  display: inline-block;
  padding: 0.08rem 0.5rem;
  border-radius: 999px;
  background: #e8f0fb;
  color: #1f2f5c;
  font-size: 0.7rem;
  font-weight: 700;
  white-space: nowrap;
}

.options-chip-warn {
  background: var(--warning-bg);
  color: var(--warning);
}

.options-notice {
  background: var(--warning-bg);
  color: var(--warning);
  border: 1px solid #fcd34d;
  border-radius: 10px;
  padding: 0.55rem 0.75rem;
  font-size: 0.8rem;
  line-height: 1.45;
  margin-bottom: 0.75rem;
}

.options-notice-list {
  margin-top: 0.25rem;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.options-intro-link {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: #1f2f5c;
  text-decoration: none;
}

.options-intro-link:hover {
  text-decoration: underline;
}

@media (min-width: 640px) {
  .options-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }

  .options-panel-actions {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1024px) {
  .options-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .options-panel-actions {
    grid-column: auto;
  }
}

/* ── Case detail: numbered section order (2026-09-09) ──────────────────────────
   The case page is now read top-to-bottom as 1 รายละเอียดเคส → 2 ความคิดเห็น →
   3 การคืนคะแนน → 4 QC. .section-jump is the little index under the header; a
   .section-block wraps the three cards that make up section 2. */
.section-jump {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 0 1rem;
}

.section-jump a {
  font-size: 0.8rem;
  color: var(--muted);
  text-decoration: none;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  white-space: nowrap;
}

.section-jump a:hover {
  color: var(--primary);
  border-color: var(--primary);
}

.section-block {
  margin-top: 1rem;
}

.section-heading {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--primary);
  margin: 0 0 0.6rem;
}

/* A QC-only viewer gets no CS ดำเนินการ panel, so the details card takes the row. */
.form-grid.form-grid-single {
  grid-template-columns: minmax(0, 1fr);
}

/* ── Section 4: QC ──────────────────────────────────────────────────────────── */
.qc-card {
  margin-top: 1rem;
  border: 1px solid #ddd6fe;
}

.qc-state-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.85rem;
}

.qc-hint {
  font-size: 0.87rem;
  color: var(--muted);
  line-height: 1.6;
}

.qc-steps {
  background: #f5f3ff;
  border: 1px solid #ddd6fe;
  border-radius: var(--radius);
  padding: 0.8rem 1rem;
  margin-bottom: 1rem;
}

.qc-steps-title {
  font-weight: 700;
  color: #5b21b6;
  margin-bottom: 0.4rem;
  font-size: 0.92rem;
}

.qc-steps ol {
  margin: 0;
  padding-left: 1.2rem;
  font-size: 0.87rem;
  line-height: 1.7;
}

.qc-steps a {
  color: #6d28d9;
}

/* 2026-09-16: CS answers QC's request (resend) and CS takes a case / points request back. */
.qc-hint-cx {
  background: #fff7ed;
  border: 1px solid #fed7aa;
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
  color: #9a3412;
}

.qc-resend-form {
  max-width: 40rem;
}

.cs-recall {
  margin-top: 0.85rem;
  border-top: 1px dashed var(--border);
  padding-top: 0.6rem;
}

.cs-recall > summary {
  cursor: pointer;
  font-size: 0.87rem;
  font-weight: 600;
  color: var(--muted);
}

.cs-recall form {
  max-width: 40rem;
}

/* Status + findings + attachments since 2026-09-14, so wider than the old lone select. */
.qc-status-form {
  max-width: 40rem;
}

.qc-form-hint {
  display: block;
  margin-bottom: 0.6rem;
}

.owner-change-current {
  display: block;
  margin-bottom: 0.35rem;
}

/* ── Action ถัดไป, read-only + the media viewer (2026-09-09) ─────────────────── */
.readonly-field {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.6rem 0.85rem;
  font-weight: 600;
  color: var(--text);
  overflow-wrap: anywhere;
}

.readonly-field-empty {
  font-weight: 400;
  font-style: italic;
  color: var(--muted);
}

.action-field .field-hint {
  margin-top: 0.35rem;
}

/* A video attachment carries a play badge and opens in the viewer, instead of the old generic
   tile that could only link out to a new tab. Since 2026-10-08 the tile is a 🎬, not the video's
   own first frame: a <video> on the page fetched from every video each time a case was opened. */
.thumb {
  position: relative;
}

.thumb-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -60%);
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

body.media-open {
  overflow: hidden;
}

.media-viewer {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(15, 23, 42, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 1rem;
}

.media-viewer[hidden] {
  display: none;
}

.media-stage {
  margin: 0;
  max-width: min(1100px, 92vw);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}

.media-body {
  display: flex;
  align-items: center;
  justify-content: center;
  max-height: 80vh;
}

.media-el {
  max-width: min(1100px, 88vw);
  max-height: 80vh;
  border-radius: 8px;
  background: #000;
}

/* ── Zooming a picture (intake.js, 2026-09-22) ───────────────────────────────
   The image carries one transform written by every gesture. touch-action: none on the stage
   is what lets a two-finger pinch reach the handlers instead of the browser zooming the whole
   page, and transform-origin must stay centred - the maths in setMediaZoom assumes it. */
.media-viewer .media-stage {
  touch-action: none;
  user-select: none;
}

/* Belt and braces with img.draggable = false in renderMedia: the native image drag cancels
   the pointer, and a cancelled pointer is a dead pan. */
.media-viewer img.media-el {
  -webkit-user-drag: none;
}

.media-viewer img.media-el {
  transform-origin: center center;
  will-change: transform;
  cursor: zoom-in;
  /* No transition: a pinch or a wheel writes a new transform every few milliseconds, and an
     animation on each one lags a finger. */
}

.media-viewer.is-zoomed img.media-el {
  cursor: grab;
}

.media-viewer.is-zoomed img.media-el:active {
  cursor: grabbing;
}

/* Zoomed in, the picture is bigger than its box on purpose - the box must not clip it. */
.media-viewer.is-zoomed .media-body {
  overflow: visible;
}

.media-tools {
  position: absolute;
  top: 1rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3; /* above a zoomed picture, like .media-close */
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.45rem;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.72);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}

.media-tools[hidden] {
  display: none;
}

.media-tools button {
  width: 2.1rem;
  height: 2.1rem;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}

.media-tools button:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.28);
}

.media-tools button:disabled {
  opacity: 0.35;
  cursor: default;
}

.media-zoom-level {
  min-width: 3.1rem;
  text-align: center;
  color: #e2e8f0;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

.media-caption {
  color: #e2e8f0;
  font-size: 0.85rem;
  text-align: center;
  overflow-wrap: anywhere;
}

.media-download {
  color: #fff;
  background: var(--primary);
  padding: 0.7rem 1.2rem;
  border-radius: var(--radius);
  text-decoration: none;
}

.media-nav,
.media-close {
  border: none;
  cursor: pointer;
  /* Dark, not a white wash: since 2026-09-22 a zoomed picture fills the screen behind these,
     and a white ✕ on a photographed receipt is invisible (caught in a screenshot, not by the
     checks). The same treatment as .media-tools. */
  background: rgba(15, 23, 42, 0.72);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
  color: #fff;
  border-radius: 50%;
  flex: none;
}

.media-nav {
  width: 3rem;
  height: 3rem;
  font-size: 2rem;
  line-height: 1;
  /* Positioned, and above the stage: a zoomed picture is bigger than its box and would
     otherwise paint over these controls and swallow the clicks (caught on a phone, 2026-09-22 -
     the ✕ was unreachable at 150%). A transform paints like a positioned element, so plain
     DOM order is not enough. */
  position: relative;
  z-index: 2;
}

.media-nav[hidden] {
  visibility: hidden;
  display: block;
}

.media-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 2.5rem;
  height: 2.5rem;
  font-size: 1.1rem;
  z-index: 3; /* stays clickable over a zoomed picture - see .media-nav */
}

.media-nav:hover,
.media-close:hover {
  background: rgba(15, 23, 42, 0.9);
}

@media (max-width: 640px) {
  .media-nav {
    width: 2.4rem;
    height: 2.4rem;
    font-size: 1.5rem;
  }
}

/* ── Navigation feedback (static/nav.js, 2026-09-09) ─────────────────────────
   Several pages here take seconds server-side and used to give the person clicking
   absolutely nothing until the new document painted. These three pieces - a top bar, a
   "กำลังโหลด…" pill, and the clicked element dimming - are the whole answer. All of them
   are position:fixed or opacity-only, so nothing in the page reflows. */
.nav-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 2000;
  background: rgba(29, 111, 66, 0.16);
  overflow: hidden;
  pointer-events: none;
}

.nav-progress[hidden] {
  display: none;
}

.nav-progress-bar {
  display: block;
  height: 100%;
  width: 38%;
  background: var(--primary);
  border-radius: 0 3px 3px 0;
  animation: nav-progress-slide 1.05s ease-in-out infinite;
}

@keyframes nav-progress-slide {
  0% { transform: translateX(-105%); }
  100% { transform: translateX(365%); }
}

/* Bottom-centre, not top: the top is already the progress bar's, and a pill up there sits
   straight on the dashboard search box and on the case modal's own header. */
.nav-busy {
  position: fixed;
  bottom: 1.1rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2001;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  max-width: calc(100vw - 1.5rem);
  padding: 0.32rem 0.85rem;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.92);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.3);
  pointer-events: none;
}

.nav-busy[hidden] {
  display: none;
}

/* "บันทึกเรียบร้อยแล้ว" after an in-modal save (intake.js showSavedToast). Same spot and
   shape as .nav-busy so the eye already knows where to look; green because it is a result,
   not a wait. Above the modal overlay (z-index 100) and the busy pill (2001). */
.save-toast {
  position: fixed;
  bottom: 1.1rem;
  left: 50%;
  transform: translateX(-50%) translateY(0.5rem);
  z-index: 2002;
  max-width: calc(100vw - 1.5rem);
  padding: 0.42rem 1rem;
  border-radius: 999px;
  background: var(--primary, #1d6f42);
  color: #fff;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.3);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
}

.save-toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.save-toast[hidden] {
  display: none;
}

/* The row the person just wrote, on the feed before Lark has accepted it (intake.js
   pendingTimelineRow). Deliberately unmistakable: it is not history yet. */
.timeline-item-pending {
  opacity: 0.75;
  border-left: 3px dashed var(--primary, #1d6f42);
  padding-left: 0.6rem;
}

.timeline-item-pending .timeline-time {
  font-style: italic;
}

/* A save that finished while the person had already moved on, and failed (intake.js
   showSaveProblem). It stays until it is answered - what they typed is still in hand, so
   "ลองอีกครั้ง" sends the very same thing again. */
.save-toast-problem {
  background: var(--danger, #b42318);
  white-space: normal;
  max-width: min(30rem, calc(100vw - 1.5rem));
  padding: 0.6rem 0.9rem;
  border-radius: 12px;
  pointer-events: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  text-align: left;
}

.save-toast-problem button {
  flex: none;
  padding: 0.25rem 0.7rem;
  border: 1px solid rgba(255, 255, 255, 0.65);
  border-radius: 999px;
  background: transparent;
  color: #fff;
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
}

.save-toast-problem button:hover {
  background: rgba(255, 255, 255, 0.18);
}

.nav-busy-spin,
.is-busy.has-spin::after {
  content: "";
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  flex: none;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-right-color: transparent;
  animation: yoku-spin 0.7s linear infinite;
}

@keyframes yoku-spin {
  to { transform: rotate(360deg); }
}

/* Only opacity + cursor change, never a size change, so a pending link cannot shift the
   list under a finger that is still moving. */
.is-nav-pending {
  opacity: 0.55;
  cursor: progress;
}

.is-busy {
  cursor: progress;
}

/* ── Case-modal skeleton (intake.js) ────────────────────────────────────────
   The overlay used to sit on one line of text for however long the fetch took. This is the
   same shape the real fragment lands in, so the panel does not jump when it arrives. */
.modal-skeleton {
  background: var(--bg);
  padding: 1rem 1.25rem 1.5rem;
  width: 100%;
}

.modal-skeleton-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--primary);
  color: #fff;
  font-size: 0.95rem;
  font-weight: 700;
  margin: -1rem -1.25rem 1rem;
  padding: 1rem 1.25rem;
}

.sk-cols {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}

.sk-card {
  background: var(--card);
  border-radius: var(--radius);
  padding: 1rem;
}

.sk-line {
  height: 0.85rem;
  border-radius: 6px;
  margin-bottom: 0.7rem;
  background: linear-gradient(90deg, #e6ebf1 25%, #f2f6fa 37%, #e6ebf1 63%);
  background-size: 400% 100%;
  animation: sk-shimmer 1.3s ease-in-out infinite;
}

.sk-line:last-child { margin-bottom: 0; }
.sk-line.sk-title { height: 1.25rem; width: 45%; }
.sk-line.sk-w-70 { width: 70%; }
.sk-line.sk-w-55 { width: 55%; }
.sk-line.sk-w-85 { width: 85%; }
.sk-line.sk-block { height: 3.4rem; }

@keyframes sk-shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

@media (min-width: 900px) {
  .sk-cols { grid-template-columns: 1.6fr 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  /* Keep every indicator - drop every movement. The bar becomes a solid band, the spinners
     a static ring, the skeleton a flat grey block; the "กำลังโหลด…" pill carries the
     message in words either way. */
  .nav-progress-bar {
    width: 100%;
    animation: none;
  }
  .nav-busy-spin,
  .is-busy.has-spin::after,
  .sk-line {
    animation: none;
  }
  .sk-line {
    background: #e6ebf1;
  }
}

/* -- Dashboard B2C / B2B scope switch (2026-09-10) ---------------------------------
   Every count on /cases follows this; on "all" each stat tile also shows its split. */
.kind-switch {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.75rem;
}

.kind-switch-item {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--text);
  font-size: 0.86rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.kind-switch-item:hover {
  border-color: var(--primary);
  color: var(--primary);
}

.kind-switch-item.is-active {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.kind-switch-count {
  display: inline-block;
  min-width: 1.4rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.08);
  font-size: 0.78rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.kind-switch-item.is-active .kind-switch-count {
  background: rgba(255, 255, 255, 0.25);
}

.stat-tile-split {
  margin-top: 0.3rem;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--primary-dark);
  font-variant-numeric: tabular-nums;
}

/* ── สคริปต์ตอบกลับ: each person's floating copy-paste replies (2026-09-30, saved-replies.js) ──
   Bottom-right, above the case modal (z-index 100) and below the picture zoom (1000) and the
   loading pills (2000+). A bottom sheet at phone width. */
.saved-replies-fab {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 950;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.6rem 0.9rem;
  border: none;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  font: inherit;
  font-weight: 700;
  font-size: 0.9rem;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
  cursor: pointer;
}
.saved-replies-fab:hover { background: var(--primary-dark); }
.saved-replies-fab-count {
  min-width: 1.3rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background: #fff;
  color: var(--primary-dark);
  font-size: 0.75rem;
  text-align: center;
}
.saved-replies-panel {
  position: fixed;
  right: 16px;
  bottom: 72px;
  z-index: 950;
  width: 380px;
  max-height: min(70vh, 640px);
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2);
}
.saved-replies-panel[hidden] { display: none; }
.saved-replies-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--border);
}
.saved-replies-title { font-weight: 700; color: var(--primary-dark); }
.saved-replies-close { border: none; background: none; font-size: 1.1rem; cursor: pointer; color: var(--muted); }
.saved-replies-body { padding: 0.75rem 0.9rem; overflow-y: auto; display: flex; flex-direction: column; gap: 0.6rem; }
.saved-replies-search, .saved-replies-editor input, .saved-replies-editor textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  font: inherit;
  font-size: 0.9rem;
}
/* 2026-10-02: the search box stays in view while the list scrolls under it; the script the
   keyboard is on (arrows move, Enter copies) is outlined. */
.saved-replies-search { position: sticky; top: 0; z-index: 1; flex: none; background: var(--card); }
.saved-replies-search:focus { outline: 2px solid var(--primary); outline-offset: 0; border-color: var(--primary); }
.saved-replies-found { font-size: 0.75rem; color: var(--muted); }
.saved-replies-item { scroll-margin: 3.2rem 0 0.6rem; }
.saved-replies-item-active { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary); }
.saved-replies-editor textarea { resize: vertical; min-height: 7rem; }
.saved-replies-editor { display: flex; flex-direction: column; gap: 0.35rem; }
.saved-replies-label { font-size: 0.8rem; font-weight: 600; color: var(--muted); }
.saved-replies-editor-actions { display: flex; gap: 0.5rem; margin-top: 0.3rem; }
.saved-replies-list { display: flex; flex-direction: column; gap: 0.5rem; }
.saved-replies-item { border: 1px solid var(--border); border-radius: 10px; padding: 0.55rem 0.65rem; }
.saved-replies-item-title { font-weight: 700; font-size: 0.9rem; overflow-wrap: anywhere; }
.saved-replies-item-text {
  margin-top: 0.2rem;
  font-size: 0.85rem;
  color: var(--muted);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.saved-replies-item-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; margin-top: 0.45rem; }
.saved-replies-item-actions .btn { width: auto; }
.saved-replies-link { border: none; background: none; padding: 0.2rem 0.3rem; font: inherit; font-size: 0.82rem; color: var(--primary-dark); cursor: pointer; }
.saved-replies-link:disabled { color: var(--border); cursor: default; }
.saved-replies-danger { color: var(--danger); }
.saved-replies-add { align-self: flex-start; width: auto; }
.saved-replies-empty { font-size: 0.85rem; color: var(--muted); padding: 0.4rem 0; }
.saved-replies-error { font-size: 0.85rem; color: var(--danger); }
.saved-replies-foot { border-top: 1px solid var(--border); padding-top: 0.5rem; }
.saved-replies-note { font-size: 0.75rem; color: var(--muted); }
.saved-replies-tools { display: flex; gap: 0.6rem; margin-top: 0.2rem; }
.saved-replies-toast {
  position: fixed;
  right: 16px;
  bottom: 72px;
  z-index: 951;
  padding: 0.45rem 0.8rem;
  border-radius: 999px;
  background: #1f2937;
  color: #fff;
  font-size: 0.85rem;
}
.saved-replies-toast[hidden] { display: none; }
@media (max-width: 520px) {
  .saved-replies-panel { left: 8px; right: 8px; width: auto; bottom: 68px; max-height: 75vh; }
  .saved-replies-fab-label { display: none; }
}
@media print { .saved-replies-fab, .saved-replies-panel, .saved-replies-toast { display: none !important; } }
/* 2026-10-02: pictures on a script (a click copies one), and the panel as a page of its own -
   /replies/panel, what the desktop pet opens. */
.saved-replies-thumbs { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.4rem; }
.saved-replies-thumb {
  position: relative;
  width: 56px;
  height: 56px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: #f8fafc;
}
.saved-replies-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.saved-replies-thumb-copy { cursor: copy; }
.saved-replies-thumb-copy:hover, .saved-replies-thumb-copy:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.saved-replies-thumb-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.7);
  color: #fff;
  font-size: 0.7rem;
  line-height: 20px;
  cursor: pointer;
}
.saved-replies-pick { align-self: flex-start; }
.replies-page { min-height: 100vh; box-sizing: border-box; padding: 16px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.replies-page.is-pet { padding: 0; }
.saved-replies-page.saved-replies-panel {
  position: static;
  width: 100%;
  max-width: 560px;
  max-height: none;
  min-height: calc(100vh - 32px);
}
.replies-page.is-pet .saved-replies-page.saved-replies-panel { max-width: none; min-height: 100vh; border: none; border-radius: 0; box-shadow: none; }
.replies-page.is-pet .saved-replies-body { flex: 1; }
.replies-page-back { font-size: 0.85rem; color: var(--primary-dark); }
