/* ============================================================
   琢藝 demo 共用樣式
   ----------------------------------------------------------
   📱 手機/PWA 設計原則（2026-05-21 拍板）：
   1. 全員 PWA — 員工 + 醫師 + 客戶 LINE LIFF，0 個 Native App
   2. 主要流程（建檔/預約/結帳/核銷）用「單欄式」設計
   3. 多步驟表單用 stepper（.zy-stepper），不要一頁塞滿
   4. 互動熱區（button, a, input）≥ 44 × 44 px（iOS 標準）
   5. 提示用 Modal / Toast，禁用 native alert()
   6. 字級：手機正文 ≥ 14px、標題 ≥ 18px
   7. 響應式斷點：sm 640 / md 768 / lg 1024 / xl 1280
   8. 桌機 hover 效果在手機改為 :active
   ----------------------------------------------------------
   🎨 設計語言 v1.0（2026-05-26 套用 — 05_設計語言.md）：
   - Snow（米白）為主背景、玫瑰金為強調色
   - iOS 系統色：blue / green / orange / red / yellow / indigo / pink / mint / brown
   - SF Pro 字型 stack 為首選，Noto Sans TC 為中文回退
   - Light / Dark mode 雙模式（prefers-color-scheme）
   - iOS 圓角：sm 6 / md 10 / lg 14 / xl 18 / 2xl 24 / full 9999
   ============================================================ */

/* ---------- iOS Design Tokens — Light Mode ---------- */
:root {
  /* Snow & 玫瑰金 主色 */
  --color-primary: #B8847C;
  --color-primary-hover: #8E5F58;
  --color-snow-bg: #FAF7F2;
  --color-snow-secondary: #F5EFE6;
  --color-snow-tertiary: #ECE9E2;
  --color-ink: #2E2A26;
  --color-ink-soft: #5A554E;

  /* iOS 系統色 */
  --color-ios-blue: #007AFF;
  --color-ios-green: #34C759;
  --color-ios-orange: #FF9500;
  --color-ios-red: #FF3B30;
  --color-ios-yellow: #FFCC00;
  --color-ios-indigo: #5856D6;
  --color-ios-pink: #FF2D55;
  --color-ios-mint: #00C7BE;
  --color-ios-brown: #A2845E;

  /* iOS Gray */
  --color-gray-1: #F2F2F7;
  --color-gray-2: #E5E5EA;
  --color-gray-3: #D1D1D6;
  --color-gray-4: #C7C7CC;
  --color-gray-5: #AEAEB2;
  --color-gray-6: #8E8E93;

  /* 語意色（狀態）：文字用深色版確保白底/淺底上 ≥4.5:1 對比；-bg 為對應淺底 */
  --color-success: #1B7A3D;  --color-success-bg: #E3F6EA;
  --color-warning: #9A5B00;  --color-warning-bg: #FBEFD8;
  --color-danger:  #C42B1C;  --color-danger-bg:  #FBE3E0;
  --color-info:    #15639E;  --color-info-bg:    #E3F0FA;

  /* 圓角 */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 18px;
  --radius-2xl: 24px;

  /* 陰影 */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.06);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.08);
  --shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.12);

  /* 動畫 */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);

  /* === Mobile-specific tokens（46_SPEC_手機操作優化 Phase 1.3）=== */
  /* spacing */
  --mobile-page-padding: 12px;
  --mobile-card-padding: 14px;
  --mobile-card-gap: 10px;
  --mobile-section-gap: 16px;
  /* touch */
  --mobile-touch-target: 44px;
  --mobile-touch-gap: 8px;
  /* mobile chrome heights */
  --mobile-bottom-tab-h: 56px;
  --mobile-bottom-action-h: 64px;
  --mobile-fab-size: 56px;
  /* safe area (iPhone notch / Android nav bar) */
  --safe-area-top: env(safe-area-inset-top, 0px);
  --safe-area-bottom: env(safe-area-inset-bottom, 0px);
  /* z-index 規範 */
  --z-bottom-tab: 50;
  --z-bottom-sheet-backdrop: 90;
  --z-bottom-sheet: 100;
  --z-fab: 45;
  --z-toast: 200;
}

/* ---------- Dark Mode（僅手動切換，不跟系統） ---------- */
/* 註：移除 @media (prefers-color-scheme: dark) 因為既有 HTML 用大量 Tailwind class
   (text-slate-800 / bg-white) 沒辦法跟著翻；自動切到 Dark 會半破半亮。
   後續若要完整支援 Dark Mode，需把所有 Tailwind 顏色 class 改成 CSS vars。 */
[data-theme="dark"] {
  --color-primary: #D4A39A;
  --color-primary-hover: #E5B5AC;
  --color-snow-bg: #1C1A18;
  --color-snow-secondary: #2A2724;
  --color-snow-tertiary: #38332F;
  --color-ink: #F5EFE6;
  --color-ink-soft: #A8A29A;
  --color-ios-blue: #0A84FF;
  --color-ios-green: #30D158;
  --color-ios-orange: #FF9F0A;
  --color-ios-red: #FF453A;
  --color-ios-yellow: #FFD60A;
  --color-ios-indigo: #5E5CE6;
  --color-ios-pink: #FF375F;
  --color-gray-1: #1C1C1E;
  --color-gray-2: #2C2C2E;
  --color-gray-3: #3A3A3C;
  --color-gray-4: #48484A;
  --color-gray-5: #636366;
  --color-success: #4CD964;  --color-success-bg: #14301E;
  --color-warning: #FFB340;  --color-warning-bg: #3A2A0E;
  --color-danger:  #FF6B5E;  --color-danger-bg:  #3A1714;
  --color-info:    #5AAEF0;  --color-info-bg:    #122A3D;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5);
}

/* ---------- iOS Polish — 套用於 customer.html / sales-order.html / mobile-showcase 等 ---------- */
/* 透過 <body data-ios-polish="true"> 啟用，不影響其他既有頁面 */
[data-ios-polish] {
  background-color: var(--color-snow-bg) !important;
}
[data-ios-polish] .bg-white,
[data-ios-polish] .bg-slate-50 {
  background-color: var(--color-snow-secondary) !important;
}
[data-ios-polish] .border-slate-200 {
  border-color: var(--color-snow-tertiary) !important;
}
[data-ios-polish] h2.text-2xl {
  font-size: 28px;
  line-height: 34px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--color-ink);
}
[data-ios-polish] h3.font-bold {
  letter-spacing: -0.01em;
  color: var(--color-ink);
}
/* iOS chevron 在可點 row */
[data-ios-polish] .ios-row {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  background: var(--color-snow-secondary);
  border-radius: var(--radius-lg);
  margin-bottom: 6px;
  transition: background 150ms;
}
[data-ios-polish] .ios-row:active { background: var(--color-snow-tertiary); }
[data-ios-polish] .ios-row::after {
  content: '›';
  margin-left: auto;
  color: var(--color-gray-5);
  font-size: 20px;
  font-weight: 300;
}
/* iOS bottom safe area */
[data-ios-polish] main { padding-bottom: env(safe-area-inset-bottom, 20px); }

/* iOS link 樣式（玫瑰金 + 無底線） */
[data-ios-polish] a.text-blue-600 {
  color: var(--color-primary) !important;
}
[data-ios-polish] .text-blue-600 {
  color: var(--color-primary) !important;
}

/* ---------- iOS 字型 stack（SF Pro + 中文回退） ---------- */
html { -webkit-text-size-adjust: 100%; }
body, .font-tc {
  font-family:
    -apple-system, BlinkMacSystemFont,
    'SF Pro Display', 'SF Pro Text',
    'PingFang TC', 'Microsoft JhengHei',
    'Noto Sans TC', 'Helvetica Neue', sans-serif;
  font-variant-numeric: tabular-nums;
  /* 全域 base typography — 中文行距 1.6 才舒服（agent audit P0 #1） */
  font-size: 16px;
  line-height: 1.6;
  color: var(--color-ink, #2E2A26);
}
h1, h2, h3, h4, h5, h6 { line-height: 1.3; }
p { line-height: 1.65; }

/* 數字對齊 */
.font-mono, .tabular {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum';
}

/* iOS 字級 utility */
.text-largeTitle { font-size: 34px; line-height: 41px; font-weight: 700; }
.text-title1 { font-size: 28px; line-height: 34px; font-weight: 700; }
.text-title2 { font-size: 22px; line-height: 28px; font-weight: 600; }
.text-title3 { font-size: 20px; line-height: 25px; font-weight: 600; }
.text-headline { font-size: 17px; line-height: 22px; font-weight: 600; }
.text-body-ios { font-size: 17px; line-height: 22px; font-weight: 400; }
.text-callout { font-size: 16px; line-height: 21px; font-weight: 400; }
.text-subheadline { font-size: 15px; line-height: 20px; font-weight: 400; }
.text-footnote { font-size: 13px; line-height: 18px; font-weight: 400; }
.text-caption1 { font-size: 12px; line-height: 16px; font-weight: 400; }
.text-caption2 { font-size: 11px; line-height: 13px; font-weight: 400; }

/* ---------- iOS 100vh + safe-area fix（agent audit P0 #2） ---------- */
.sidebar, .min-h-screen {
  /* fallback ladder for iOS Safari */
  min-height: 100vh;
  min-height: 100dvh;
}
.sidebar {
  height: 100vh;
  height: 100dvh;
}
/* 角色頁 header 改 fixed 強制永久置頂 — 原 sticky 受 #header-mount 父容器高度限制失效 */
/* 用 max(safe-area, 8px) 確保通知列不擋（特別是 iPhone Dynamic Island / Android status bar） */
header.sticky {
  position: fixed !important;
  top: 0;
  left: 0;
  right: 0;
  padding-top: max(env(safe-area-inset-top, 0px), 8px) !important;
  background: #fff !important;
  z-index: 50 !important;
}
/* main / body padding-top 抵消 fixed header 高度（避免內容被蓋） */
body:has(> #header-mount) {
  padding-top: calc(72px + max(env(safe-area-inset-top, 0px), 8px));
}
.zy-sticky-cta {
  padding-top: env(safe-area-inset-top, 0);
}
.zy-sticky-cta {
  position: sticky;
  bottom: 0;
  background: #fff;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0));
  border-top: 1px solid #e2e8f0;
  z-index: 30;
  box-shadow: 0 -4px 12px rgba(0,0,0,0.04);
}
/* toast 從上方滑入也要避開瀏海 */
.zy-toast {
  top: calc(env(safe-area-inset-top, 0) + 24px) !important;
}

/* ---------- hover 只套桌機（agent audit P0 #3） — 避免手機觸控後 hover 卡住 ---------- */
@media (hover: hover) and (pointer: fine) {
  .role-card:hover,
  .feedback-toolbar button:hover,
  .kpi-card:hover,
  .sidebar-item:hover,
  .nav-tab:hover,
  .zy-table tr:hover {
    /* 既有 hover 規則保留在 media 內 */
  }
}
/* iOS press 效果 — 提供 :active feedback */
.role-card:active,
.sidebar-item:active,
.kpi-card:active,
.btn-primary:active,
.btn-secondary:active,
.btn-danger:active {
  transform: scale(0.97);
  transition: transform 80ms ease;
}

/* ---------- 月曆 grid 例外（不被 [class*="grid-cols-"] 收成 1 欄） ---------- */
.zy-calendar,
.zy-calendar-grid {
  display: grid !important;
  grid-template-columns: repeat(7, 1fr) !important;
  gap: 4px;
}

/* 拍照按鈕 grid 例外：mobile 保 2 欄（375 寬下 6 顆按鈕變 2x3 而非 1x6 巨型）
   桌機保原本的 grid-cols-3 自動 inherit */
.zy-photo-grid {
  display: grid !important;
}
@media (max-width: 768px) {
  .zy-photo-grid {
    grid-template-columns: repeat(2, 1fr) !important;
  }
}

/* ---------- 表格 wrap 容器 — 限制寬度 + 內部水平捲動（regress sweep fix） ---------- */
/* 不管桌機 / mobile，所有 .zy-table-wrap 都要 overflow-x: auto，否則表格會撐爆 main-view */
.zy-table-wrap {
  overflow-x: auto;
  max-width: 100%;
  -webkit-overflow-scrolling: touch;
}

/* ---------- 防止任何內容造成 page-level horizontal scroll（mobile）---------- */
/* ⚠️ 用 overflow-x:clip 而非 hidden：hidden 會讓瀏覽器把 overflow-y 算成 auto →
   html/body/#main-view 變成「巢狀捲動容器」，position:sticky 會黏在 #main-view 而非視窗，
   手機往下捲時 sticky 工具列會跟著捲走（業主回報「常用/看明細那列沒固定住」）。
   clip 一樣擋掉水平溢出，但不建立捲動容器、不強制 overflow-y:auto → sticky 正常。 */
@media (max-width: 768px) {
  html, body { overflow-x: clip; }
  #main-view { overflow-x: clip; max-width: 100vw; }
  /* tab list 仍可自己水平捲動（nav-tab flex-shrink: 0 保留時） */
  .flex:has(> .nav-tab) {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

/* ---------- 響應式 table → 卡片化的 helper（agent 提議） ---------- */
@media (max-width: 768px) {
  /* 為長表格加右側 fade 提示「右邊還有」 */
  .zy-table-wrap {
    position: relative;
  }
  .zy-table-wrap::after {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: 24px;
    background: linear-gradient(to right, transparent, rgba(255,255,255,0.95));
    pointer-events: none;
  }
  /* 表格內 action button 強制 44px touch target（解 NUR/BCN agent #1 issue） */
  table .btn-primary,
  table .btn-secondary,
  table .btn-danger,
  table button.btn-primary,
  table button.btn-secondary,
  table button.btn-danger {
    min-height: 44px !important;
    padding: 10px 14px !important;
    display: inline-block;
  }
  /* table 內若有多顆按鈕，垂直堆疊 + gap */
  table td > .flex.gap-2 > button,
  table td > .flex.gap-2 > .btn-primary,
  table td > .flex.gap-2 > .btn-secondary {
    flex: 1;
    min-height: 44px;
  }
  /* 密集表單在手機強制 1 欄 + sticky CTA */
  .mobile-form-stack {
    display: flex !important;
    flex-direction: column !important;
    gap: 12px !important;
  }
  .mobile-form-stack > * {
    width: 100% !important;
  }
}

/* ---------- mobile-tabs：把多欄資訊壓成 tab pill 切換（DOC chart 用） ---------- */
.zy-mobile-tabs {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 8px 0;
  margin: -4px 0 12px 0;
  position: sticky;
  top: 0;
  background: #fff;
  z-index: 20;
  border-bottom: 1px solid #e2e8f0;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.zy-mobile-tabs::-webkit-scrollbar { display: none; }
.zy-mobile-tab {
  flex-shrink: 0;
  padding: 10px 14px;
  border-radius: 999px;
  background: #f1f5f9;
  color: #475569;
  font-size: 14px;
  font-weight: 500;
  border: none;
  cursor: pointer;
  white-space: nowrap;
  min-height: 40px;
  transition: all 150ms ease;
}
.zy-mobile-tab.active {
  background: var(--color-primary);
  color: #fff;
}
.zy-mobile-tab .badge {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(255,255,255,0.25);
  font-size: 11px;
}
.zy-mobile-tab-panel { display: none; }
.zy-mobile-tab-panel.active { display: block; }
/* 桌機回到「全部展開」: tab 變章節 label，panel 全部展開 */
@media (min-width: 769px) {
  .zy-mobile-tabs.desktop-collapse {
    display: none;
  }
  .zy-mobile-tabs.desktop-collapse + .zy-mobile-tab-panels .zy-mobile-tab-panel {
    display: block;
  }
}

/* ---------- anchor-chips：頁面內 sticky 跳轉（customer.html long scroll 用） ---------- */
.zy-anchor-chips {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 10px 16px;
  position: sticky;
  top: 56px; /* header 之下 */
  background: rgba(255,255,255,0.95);
  backdrop-filter: blur(8px);
  z-index: 25;
  border-bottom: 1px solid #e2e8f0;
  margin: 0 -16px 16px -16px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.zy-anchor-chips::-webkit-scrollbar { display: none; }
.zy-anchor-chip {
  flex-shrink: 0;
  padding: 8px 14px;
  border-radius: 999px;
  background: #f1f5f9;
  color: #334155;
  font-size: 13px;
  text-decoration: none;
  white-space: nowrap;
  border: 1px solid transparent;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  transition: all 150ms ease;
}
.zy-anchor-chip:hover,
.zy-anchor-chip:active {
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
  border-color: color-mix(in srgb, var(--color-primary) 40%, transparent);
  color: var(--color-primary);
}
/* anchor target 加 scroll-margin-top 避免被 sticky header + chips 蓋 */
[data-anchor-target] {
  scroll-margin-top: 120px;
}
@media (min-width: 769px) {
  .zy-anchor-chips { display: none; }
}

/* ---------- ZyVoice 語音輸入按鈕 ---------- */
.zy-voice-wrap {
  position: relative;
  display: block;
}
.zy-voice-wrap > textarea,
.zy-voice-wrap > input {
  padding-right: 44px !important;
}
.zy-voice-btn {
  position: absolute;
  top: 6px; right: 6px;
  width: 36px; height: 36px;
  border-radius: 999px;
  background: #f1f5f9;
  border: none;
  cursor: pointer;
  font-size: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 150ms ease;
  z-index: 2;
}
.zy-voice-btn:hover, .zy-voice-btn:active {
  background: #e2e8f0;
}
.zy-voice-btn.voice-recording {
  background: #ef4444;
  color: #fff;
  animation: zyVoicePulse 1.2s infinite;
}
@keyframes zyVoicePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.5); }
  50%      { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0); }
}

/* ---------- ZyPush 通知啟用 banner ---------- */
.zy-push-banner {
  position: fixed;
  left: 16px; right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0));
  background: #1e293b;
  color: #f1f5f9;
  border-radius: 14px;
  padding: 12px 14px;
  display: flex; align-items: center; gap: 10px;
  z-index: 70;
  box-shadow: 0 16px 40px rgba(0,0,0,0.32);
  animation: zyPwaSlideUp 280ms cubic-bezier(.32,.72,.34,1);
}
.zy-push-banner-icon { font-size: 28px; flex-shrink: 0; }
.zy-push-banner-text { flex: 1; font-size: 13px; line-height: 1.4; }
.zy-push-banner-text b { font-size: 14px; }
.zy-push-banner-text small { color: #94a3b8; font-size: 11px; }
.zy-push-banner-yes {
  padding: 8px 14px; border-radius: 8px;
  background: #10b981; color: #fff; border: none;
  font-weight: 600; font-size: 13px; cursor: pointer;
  min-height: 36px;
}
.zy-push-banner-no {
  width: 32px; height: 32px;
  border-radius: 999px; background: rgba(255,255,255,0.1);
  color: #94a3b8; border: none;
  cursor: pointer; flex-shrink: 0;
}
@media (min-width: 769px) {
  .zy-push-banner { left: auto; right: 24px; bottom: 24px; max-width: 400px; }
}

/* ---------- PWA install prompt（iOS / Android 加到主畫面） ---------- */
.zy-pwa-prompt {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0));
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 14px;
  padding: 12px 14px;
  box-shadow: 0 16px 40px rgba(0,0,0,0.18);
  display: flex;
  align-items: center;
  gap: 10px;
  z-index: 80;
  animation: zyPwaSlideUp 280ms cubic-bezier(.32,.72,.34,1);
}
@keyframes zyPwaSlideUp {
  from { transform: translateY(100%); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
.zy-pwa-prompt-icon {
  font-size: 32px;
  flex-shrink: 0;
}
.zy-pwa-prompt-text {
  flex: 1;
  font-size: 13px;
  line-height: 1.5;
  color: #1e293b;
}
.zy-pwa-prompt-text b { font-size: 14px; }
.zy-pwa-prompt-text small { color: #64748b; font-size: 11px; }
.zy-pwa-prompt-install {
  padding: 8px 14px !important;
  font-size: 13px !important;
  min-height: 36px !important;
}
.zy-pwa-prompt-close {
  width: 32px; height: 32px;
  border: none; background: #f1f5f9;
  border-radius: 999px;
  font-size: 14px; cursor: pointer;
  color: #64748b;
  flex-shrink: 0;
}
.zy-pwa-prompt-close:hover, .zy-pwa-prompt-close:active {
  background: #e2e8f0;
}
@media (min-width: 769px) {
  .zy-pwa-prompt {
    left: auto; right: 24px; bottom: 24px;
    max-width: 380px;
  }
}

/* ---------- 客戶 360 KPI horizontal swiper（手機橫滑省直向空間，已停用，留向後相容） ---------- */
@media (max-width: 768px) {
  .zy-kpi-swiper {
    display: flex !important;
    gap: 10px !important;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    margin-left: -16px;
    margin-right: -16px;
    padding: 0 16px 8px;
  }
  .zy-kpi-swiper::-webkit-scrollbar { display: none; }
  .zy-kpi-swiper-item {
    flex: 0 0 78%;
    scroll-snap-align: start;
    min-width: 260px;
  }
}

/* 業主 2026-06-24 #5：客戶 360 概況 6 格 mini-grid（取代橫滑 swiper），不依賴 Tailwind JIT，永遠生效 */
.zy-kpi-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
  margin-bottom: 12px;
}
@media (min-width: 768px) {
  .zy-kpi-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ---------- mobile cart sheet：sales-order.html 點 cart bar 上滑展開明細 ---------- */
.zy-mobile-cart-sheet-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.4);
  z-index: 45;
}
.zy-mobile-cart-sheet-backdrop.open { display: block; }
.zy-mobile-cart-sheet {
  display: none;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  max-height: 80vh;
  background: #fff;
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -16px 40px rgba(0,0,0,0.18);
  z-index: 46;
  transform: translateY(100%);
  transition: transform 240ms cubic-bezier(.32,.72,.34,1);
  flex-direction: column;
  overscroll-behavior: contain;
}
.zy-mobile-cart-sheet.open {
  display: flex;
  transform: translateY(0);
}
.zy-mobile-cart-sheet .sheet-handle {
  width: 36px; height: 4px; background: #cbd5e1; border-radius: 2px;
  margin: 8px auto; flex-shrink: 0;
}
.zy-mobile-cart-sheet .sheet-header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 0 16px 12px; font-weight: 600;
  border-bottom: 1px solid #e2e8f0; flex-shrink: 0;
}
.zy-mobile-cart-sheet .sheet-close {
  width: 36px; height: 36px; border-radius: 999px;
  background: #f1f5f9; border: none; cursor: pointer; font-size: 16px;
}
.zy-mobile-cart-sheet .sheet-body {
  flex: 1; overflow-y: auto; padding: 12px 16px;
  -webkit-overflow-scrolling: touch;
}
.zy-mobile-cart-sheet .sheet-footer {
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0));
  border-top: 1px solid #e2e8f0; flex-shrink: 0;
  background: #fff;
}
@media (min-width: 769px) {
  .zy-mobile-cart-sheet, .zy-mobile-cart-sheet-backdrop { display: none !important; }
}

/* ---------- mobile cart bar：sales-order.html sticky 購物車按鈕 ---------- */
.zy-mobile-cart-bar {
  display: none;
}
@media (max-width: 768px) {
  .zy-mobile-cart-bar {
    display: flex !important;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    background: #fff;
    color: #334155;
    padding: 8px 14px calc(8px + env(safe-area-inset-bottom, 0));
    z-index: 40;
    border-top: 1px solid #ead9d3;
    box-shadow: 0 -4px 16px rgba(184,132,124,0.12);
    align-items: center;
    gap: 12px;
    cursor: pointer;
  }
  .zy-mobile-cart-bar .cart-count {
    background: #f3e3dd;
    color: #8B5E54;
    border-radius: 999px;
    padding: 2px 10px;
    font-size: 14px;
    font-weight: 600;
    min-width: 28px;
    text-align: center;
  }
  .zy-mobile-cart-bar .cart-total {
    flex: 1;
    font-size: 16px;
    font-weight: 600;
    color: #334155;
  }
  .zy-mobile-cart-bar .cart-cta {
    background: #B8847C;
    color: #fff;
    padding: 10px 18px;
    border-radius: 8px;
    font-weight: 600;
    border: none;
    font-size: 15px;
    min-height: 44px;
  }
  /* 有 cart bar 時頁面底部留空避免被擋（配合下方送單列縮短後的高度） */
  body.has-mobile-cart-bar {
    padding-bottom: 64px;
  }
}

/* ---------- sales-order qty / 改價按鈕在手機強制 44px（agent 4 P0） ----------
   ⚠️ 2026-07-21 修正：原本只列舉 w-6/w-8 兩種尺寸，結果 ZyPicker 商品列用的
   w-7 整組漏掉（實測寬度只有 28px）→ 現場回報「按不到」。列舉尺寸是打補丁，
   下一個新尺寸還是會漏。**正解＝掛語意 class `.qty-btn`**（components.js 的
   6 顆數量鈕已全部掛上），尺寸列舉只留作舊碼安全網。新增數量鈕請掛 .qty-btn。
   放大方式是放大元件本身（bg / border 一起長大）→ 熱區＝視覺，符合業主鐵則。 */
@media (max-width: 768px) {
  button.w-8.h-8,
  button.w-7.h-7,
  button.w-6.h-6,
  .qty-btn,
  .price-edit-btn {
    width: 44px !important;
    height: 44px !important;
    min-width: 44px !important;
    min-height: 44px !important;
    font-size: 18px !important;
  }
  /* ZyPicker 在手機解掉雙層 scroll — 商品清單長就跟頁面一起捲 */
  [data-zy-picker] .max-h-\[420px\] {
    max-height: none !important;
    overflow-y: visible !important;
  }
  /* picker 內部 card 在手機留 padding 給 sticky cart bar */
  [data-zy-picker] {
    margin-bottom: 12px;
  }
}

/* ---------- REC checkin 卡操作鈕：手機改 horizontal pill row（agent 4 P0） ---------- */
@media (max-width: 768px) {
  .checkin-actions {
    display: flex !important;
    flex-wrap: nowrap !important;
    gap: 6px !important;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    grid-template-columns: none !important;
    padding-bottom: 4px;
  }
  .checkin-actions::-webkit-scrollbar { display: none; }
  .checkin-actions > button,
  .checkin-actions > .btn-primary,
  .checkin-actions > .btn-secondary {
    flex: 1 0 auto;
    min-width: 88px;
    white-space: nowrap;
  }
}

/* ---------- 手機/PWA 觸控熱區（44px iOS 標準） ---------- */
@media (max-width: 768px) {
  /* 所有可點擊元素強制 ≥ 44px — iOS HIG / Material 折衷 */
  button,
  a.btn-primary, a.btn-secondary, a.btn-danger,
  .btn-primary, .btn-secondary, .btn-danger,
  .sidebar-item, .nav-tab,
  input[type="submit"], input[type="button"], input[type="checkbox"], input[type="radio"],
  select {
    min-height: 44px;
  }
  .btn-primary, .btn-secondary, .btn-danger {
    padding-top: 10px;
    padding-bottom: 10px;
  }
  input, select, textarea {
    min-height: 44px;
    font-size: 16px; /* iOS 防 zoom-in */
  }
  /* table 內 inline link / button — 加 padding 拉大 hit area，但不撐爆整列 */
  table a, table button {
    padding: 10px 6px !important;
    display: inline-block;
    min-height: auto;
  }
  /* checkbox / radio 視覺放大 */
  label > input[type="checkbox"], label > input[type="radio"] {
    transform: scale(1.3);
    margin-right: 8px;
  }
  /* icon-only button 強制方塊 hit area */
  button.icon-only, a.icon-only {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* ---------- 多步驟表單 stepper ---------- */
.zy-stepper {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 20px;
  overflow-x: auto;
}

.zy-stepper-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 13px;
  color: #94a3b8;
  background: #f1f5f9;
  white-space: nowrap;
}

.zy-stepper-item.active {
  color: white;
  background: var(--color-primary);
  font-weight: 500;
}

.zy-stepper-item.done {
  color: var(--color-success);
  background: var(--color-success-bg);
}

.zy-stepper-divider {
  flex-shrink: 0;
  width: 16px;
  height: 1px;
  background: #cbd5e1;
}

/* ---------- 響應式：手機收成單欄 + sidebar drawer + mobile-first typography ---------- */
@media (max-width: 768px) {
  /* === mobile typography scale — 校準字級下限避免眼睛酸 === */
  body { font-size: 15px; }
  .text-xs       { font-size: 13px !important; line-height: 18px !important; }
  .text-sm       { font-size: 14px !important; line-height: 20px !important; }
  .text-base     { font-size: 15px !important; line-height: 22px !important; }
  .text-\[10px\] { font-size: 12px !important; line-height: 16px !important; }
  .text-\[11px\] { font-size: 12px !important; line-height: 16px !important; }
  .text-\[12px\] { font-size: 13px !important; line-height: 17px !important; }
  /* 標題在手機保持有明確 hierarchy */
  h1, .text-2xl { font-size: 22px !important; line-height: 28px !important; }
  h2 { font-size: 19px !important; line-height: 24px !important; }
  h3 { font-size: 17px !important; line-height: 22px !important; }
  /* 表格 cell 文字升 13 + 拉高行距方便點擊 */
  table th, table td { font-size: 13px !important; }
  .zy-table td       { padding: 12px 10px !important; }
  /* 徽章 / pill 在手機保持小但不擠 */
  .badge, .pill { font-size: 12px !important; padding: 3px 8px !important; }

  /* 內容卡（大塊）一律收成 1 欄 — 涵蓋全部 grid-cols-N（2 到 12）
     opt-out：.zy-calendar / .zy-calendar-grid（月曆要保 7 欄）
              .zy-photo-grid（拍照按鈕 grid 保多欄不被拉成 aspect-square 巨型）
              .zy-keep-grid（其他 case-by-case 需要保留 grid） */
  [class*="grid-cols-"]:not(.zy-calendar):not(.zy-calendar-grid):not(.zy-photo-grid):not(.zy-keep-grid) {
    grid-template-columns: 1fr !important;
  }
  /* sidebar 手機改成「滿版 launcher」— 按 hamburger 後整個螢幕變 menu */
  /* 注意：z-index 必須 !important，因為下方還有全域 .sidebar 規則會覆蓋 */
  .sidebar {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    transform: translateX(-100%);
    width: 100vw !important;
    max-width: 100vw !important;
    height: 100vh !important;
    /* 業主 2026-06-24 #3：手機 sidebar 底部加 safe-area + 96px 預留(home indicator + iOS Safari 底部工具列)，避免「字體大小/粗體」鈕被吃掉 */
    padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 96px) !important;
    box-shadow: none;
    z-index: 110 !important;
  }
  .sidebar.mobile-open {
    transform: translateX(0) !important;
  }
  /* launcher 模式：grid 變 3 欄、按鈕大顆 */
  .sidebar.mobile-open .sidebar-items-grid {
    grid-template-columns: repeat(auto-fit, minmax(95px, 1fr));
    gap: 8px;
    padding: 0 12px calc(var(--safe-area-bottom, 0) + 24px);
  }
  .sidebar.mobile-open .sidebar-item {
    min-height: 80px;
    border-radius: 12px;
    background: var(--color-snow-secondary, #f8fafc);
  }
  .sidebar.mobile-open .sidebar-item .sidebar-item-icon { font-size: 28px; }
  .sidebar.mobile-open .sidebar-item .sidebar-item-label { font-size: 13px; margin-top: 4px; }
  .sidebar.mobile-open .sidebar-item.active {
    background: color-mix(in srgb, var(--color-primary) 16%, transparent);
    border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
  }
  /* launcher header 大一點 */
  .sidebar.mobile-open .sidebar-header {
    /* 關閉叉叉往下移：避開手機狀態列/瀏海，好點 */
    padding: calc(env(safe-area-inset-top, 0px) + 28px) 18px 12px;
    margin-bottom: 12px;
    border-bottom: 1px solid #f1f5f9;
    min-height: 56px;
  }
  .sidebar.mobile-open .sidebar-header .text-xs {
    font-size: 16px !important;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 700;
    color: #0f172a;
  }
  .sidebar.mobile-open .sidebar-close {
    width: 40px;
    height: 40px;
    border-radius: 999px;
    background: #f1f5f9;
  }
  /* group header 大一點 */
  .sidebar.mobile-open .sidebar-group-header {
    padding: 12px 14px 4px;
  }
  .sidebar.mobile-open .sidebar-group-header > div {
    font-size: 11px !important;
    letter-spacing: 0.08em;
  }
  /* launcher 模式下 backdrop 不需要（sidebar 蓋滿） */
  .sidebar.mobile-open ~ #sidebar-backdrop,
  body.sidebar-locked #sidebar-backdrop { display: none !important; }
  /* drawer 打開時藏 feedback toolbar，避免攔截 sidebar 底部項目的點擊 */
  body.sidebar-locked .feedback-toolbar { display: none !important; }
  /* drawer 打開時藏 header 的 sticky 防干擾 */
  body.sidebar-locked header { z-index: 5 !important; }
  /* main view 在 drawer 收起時撐滿 */
  main.flex-1 {
    padding: 12px !important;
  }
  /* header 右側資訊（日期/時間/ESS menu）在手機收起來 */
  header .header-right-info {
    display: none !important;
  }
  /* header padding 緊湊 */
  header > div {
    padding-left: 12px !important;
    padding-right: 12px !important;
  }
  /* header role name 與 avatar 緊湊 */
  header .role-name { font-size: 14px !important; }
  header .role-code { font-size: 11px !important; }
  /* h2 大標題在手機縮一級 */
  .view h2.text-2xl { font-size: 18px !important; line-height: 1.3 !important; }
  /* KPI 卡兩欄一行 */
  .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 8px !important; }
  .kpi-value { font-size: 18px !important; }
  /* zy-card 縮 padding */
  .zy-card { padding: 12px !important; }
  /* 大表格在手機強制橫向捲動避免溢出 */
  .zy-table { display: block; overflow-x: auto; white-space: nowrap; }

  /* 全域防破版 — 任何元素都不能超出 viewport 寬度（用 clip：不建立捲動容器，才不會破壞 sticky） */
  body { overflow-x: clip; }

  /* Modal 滿版 */
  .modal-content { width: 95% !important; max-width: 95vw !important; max-height: 90vh !important; }

  /* 多欄 flex toolbar 在手機自動 wrap */
  .flex.gap-3, .flex.gap-4, .flex.gap-6,
  .flex.items-center.gap-2, .flex.items-center.gap-3, .flex.items-center.gap-4 {
    flex-wrap: wrap;
  }
  /* 但 sidebar-header / header role 區塊保持 nowrap */
  .sidebar-header, header > div > div { flex-wrap: nowrap !important; }

  /* 寬度寫死 ≥ 500px 的元素強制縮 */
  [style*="width: 5"][style*="px"],
  [style*="width: 6"][style*="px"],
  [style*="width: 7"][style*="px"],
  [style*="width: 8"][style*="px"],
  [style*="width: 9"][style*="px"],
  [style*="min-width: 5"][style*="px"],
  [style*="min-width: 6"][style*="px"] {
    max-width: 100% !important;
  }

  /* min-w-[…px] Tailwind 也限制 */
  [class*="min-w-["] { min-width: 0 !important; }

  /* 大尺寸 padding 縮 */
  .p-8, .p-10 { padding: 16px !important; }
  .px-8, .px-10 { padding-left: 16px !important; padding-right: 16px !important; }

  /* 結帳/購買等步驟條橫向捲動 */
  .zy-stepper { overflow-x: auto; }

  /* feedback toolbar 縮小 */
  .feedback-toolbar { bottom: 8px; padding: 6px 10px; }
  .feedback-toolbar button { font-size: 12px; padding: 5px 9px; }

  /* picker / dropdown 滿版 */
  .zy-picker, [data-zy-picker] { width: 100% !important; }

  /* 文字輸入框 / textarea 不超寬 */
  input, select, textarea { max-width: 100% !important; }
  /* 原生 date/time/datetime-local 在 iOS 有「內建最小寬」，width:100% 會被它蓋過而撐出畫面；
     強制 min-width:0 + width:100% → 控制項壓縮到欄寬（與下拉選單同寬），不再超出 */
  input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"] {
    min-width: 0 !important;
    width: 100% !important;
  }

  /* form 的 grid 全變 1 欄並改窄 gap */
  form .grid { grid-template-columns: 1fr !important; gap: 10px !important; }

  /* 動態渲染的表單欄位 grid（非 <form> 包覆，Tailwind Play-CDN JIT 偶未生成 grid-cols-N，
     導致欄寬以內容自動撐大）→ 手機強制單欄、每欄全寬，杜絕原生 date/time/datetime-local
     內建寬度把欄位撐出畫面（grid blowout）。1fr＝鎖死欄寬不超過容器（與下拉選單同寬）；
     children grid-column:auto＝避免殘留的 col-span-2 產生幽靈欄。
     排除已含 grid-cols-1 的響應式 grid（leaveBalance 等本就正確不動）。 */
  .view .grid[class*="grid-cols-2"]:not([class*="grid-cols-1"]) {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }
  .view .grid[class*="grid-cols-2"]:not([class*="grid-cols-1"]) > * {
    grid-column: auto !important;
  }

  /* 固定三欄/四欄版面在手機改兩欄（統計卡/表單欄位不再擠爆）。
     排除：已響應式(sm:/md:/lg:grid-cols-*)、含 grid-cols-1 基底、照片格(.zy-photo-grid 另有規則)。
     children grid-column:auto＝避免殘留 col-span-N 在兩欄模板產生幽靈欄／溢出。 */
  .view .grid[class*="grid-cols-3"]:not([class*="grid-cols-1"]):not([class*="sm:grid-cols"]):not([class*="md:grid-cols"]):not([class*="lg:grid-cols"]):not(.zy-photo-grid),
  .view .grid[class*="grid-cols-4"]:not([class*="grid-cols-1"]):not([class*="sm:grid-cols"]):not([class*="md:grid-cols"]):not([class*="lg:grid-cols"]):not(.zy-photo-grid) {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 10px !important;
  }
  .view .grid[class*="grid-cols-3"]:not([class*="grid-cols-1"]):not([class*="sm:grid-cols"]):not([class*="md:grid-cols"]):not([class*="lg:grid-cols"]):not(.zy-photo-grid) > *,
  .view .grid[class*="grid-cols-4"]:not([class*="grid-cols-1"]):not([class*="sm:grid-cols"]):not([class*="md:grid-cols"]):not([class*="lg:grid-cols"]):not(.zy-photo-grid) > * {
    grid-column: auto !important;
  }

  /* tab 列在手機自動 wrap */
  .nav-tab, [role="tab"] { flex-shrink: 0; }

  /* Flex / Grid children with content wider than parent — 允許縮（防原生 date/time 撐爆）*/
  .flex > * { min-width: 0; }
  .grid > * { min-width: 0; }

  /* 長字串（email / URL / UUID / 客戶碼）強制斷行 */
  .view, .zy-card, td, th, p, span, div, button, a, code {
    word-break: break-word;
    overflow-wrap: anywhere;
  }

  /* 強制每個 div 不超出父容器（catch inline-block content overflow） */
  main div { max-width: 100%; }

  /* canvas / svg / img 自適應 */
  canvas, svg, img, video { max-width: 100% !important; height: auto !important; }

  /* pre / code block 強制橫向捲動而非撐爆 */
  pre, .json, .code-block { overflow-x: auto; max-width: 100%; }
}

/* 桌機顯示 sidebar-close（X 按鈕）也可用，但桌機按了會直接收成 0 寬 */
@media (max-width: 768px) {
  .sidebar-close { display: inline-flex; }
}

/* ---------- Toast 提示（替代 alert） ---------- */
.zy-toast {
  position: fixed;
  top: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: #1e293b;
  color: white;
  padding: 12px 20px;
  border-radius: 999px;
  font-size: 14px;
  z-index: 200;
  box-shadow: 0 10px 25px rgba(0,0,0,0.2);
  animation: zyToastIn 0.2s ease;
}

@keyframes zyToastIn {
  from { opacity: 0; transform: translate(-50%, -10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

/* 角色卡 hover 效果 */
.role-card:hover {
  transform: translateY(-2px);
}

/* 回饋按鈕浮動位置（移到中下避開右下表單按鈕） */
.feedback-toolbar {
  position: fixed;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  z-index: 50;
  background: white;
  padding: 8px 12px;
  border-radius: 999px;
  box-shadow: 0 10px 25px rgba(0,0,0,0.15);
  border: 1px solid #e2e8f0;
  opacity: 0.92;
  transition: opacity 0.2s;
}

.feedback-toolbar:hover {
  opacity: 1;
}

.feedback-toolbar button {
  font-size: 13px;
  padding: 6px 12px;
  border-radius: 8px;
  font-weight: 500;
  transition: all 0.15s;
}

.feedback-toolbar button:hover {
  transform: scale(1.05);
}

/* 進度條 */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: #e2e8f0;
  z-index: 60;
}

.progress-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--color-primary), var(--color-primary-hover));
  transition: width 0.3s ease;
}

/* 畫面切換動畫 */
.view {
  animation: fadeIn 0.2s ease;
  padding-bottom: 100px; /* 留空避免最底按鈕被浮動回饋工具列遮住 */
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 表格樣式 */
.zy-table {
  width: 100%;
  border-collapse: collapse;
}

.zy-table th {
  background: #f1f5f9;
  padding: 10px 12px;
  text-align: left;
  font-size: 12px;
  font-weight: 500;
  color: #64748b;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-bottom: 1px solid #e2e8f0;
}

.zy-table td {
  padding: 12px;
  font-size: 14px;
  color: #334155;
  border-bottom: 1px solid #f1f5f9;
}

.zy-table tr:hover {
  background: #f8fafc;
}

/* ---------- 報表表格（業績總表四個分頁共用．業主 2026-09-16）----------
   🔴 斑馬紋一定要寫在這裡，不可以寫在每一列的 inline style 上 ——
      inline 的 background 會蓋掉 :hover，加了 hover 等於沒加。
   目的：橫向很寬的表（名字在最左、佔比長條在最右），滑到哪一列就整列變色，
   眼睛才追得到同一列。 */
.zy-rpt { width: 100%; border-collapse: collapse; font-size: 14px; }
.zy-rpt thead th {
  background: #faf7f6;
  color: #64748b;
  font-size: 12px;
  font-weight: 600;
  padding: 8px 10px;
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid #ecdfdb;
}
.zy-rpt thead th.r { text-align: right; }
.zy-rpt thead th.c { text-align: center; }
.zy-rpt tbody td { padding: 7px 10px; }
.zy-rpt tbody tr + tr { border-top: 1px solid #f4f1f0; }
.zy-rpt tbody tr:nth-child(even) { background: #fbfaf9; }
.zy-rpt tbody tr.zy-rpt-note { background: #eff6ff; }       /* 公司業績那一列 */
.zy-rpt tfoot tr, .zy-rpt tbody tr.zy-rpt-sum {
  background: #f8fafc;
  font-weight: 700;
  border-top: 2px solid #e7c9c0;
}
/* hover 只套桌機 —— 手機觸控後高亮會卡住 */
@media (hover: hover) and (pointer: fine) {
  .zy-rpt tbody tr:hover { background: #fdf2f8; }
  .zy-rpt tbody tr.zy-rpt-note:hover { background: #dbeafe; }
  /* 合計列不跟著反白，免得看起來像可以點 */
  .zy-rpt tbody tr.zy-rpt-sum:hover { background: #f8fafc; }
}

/* 卡片（iOS 風格 — 圓角 14px / Snow Secondary） */
.zy-card {
  background: var(--color-snow-secondary, white);
  border-radius: var(--radius-lg, 14px);
  padding: 20px;
  border: 1px solid var(--color-snow-tertiary, #e2e8f0);
  box-shadow: var(--shadow-sm, none);
  transition: box-shadow 200ms var(--ease-standard);
}

.zy-card:hover {
  box-shadow: var(--shadow-md);
}

/* 業主 2026-06-23：選商品「分類 / 看明細」列捲動時固定置頂（切分類免一直往上滑）。
   分頁內(embed，無 header)→貼齊頂端 top:0；獨立頁(有 sticky header)→讓開 header 高度。 */
.zy-pick-toolbar {
  position: sticky;
  top: 56px;
  z-index: 30;
  background: var(--color-snow-secondary, #fff);
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 8px;
  box-shadow: 0 6px 6px -6px rgba(15, 23, 42, .12);
}
html.zy-embed .zy-pick-toolbar { top: 0; }

.zy-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--color-snow-tertiary, #f1f5f9);
  color: var(--color-ink);
}

/* 按鈕（iOS 風格 — 玫瑰金 primary / 白底邊框 secondary） */
.btn-primary {
  background: var(--color-primary, #B8847C);
  color: white;
  padding: 8px 16px;
  border-radius: var(--radius-md, 10px);
  font-weight: 600;
  font-size: 14px;
  transition: all 150ms var(--ease-standard);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.btn-primary:hover, .btn-primary:active {
  background: var(--color-primary-hover, #8E5F58);
}

.btn-secondary {
  background: var(--color-snow-bg, white);
  color: var(--color-primary, #475569);
  padding: 8px 16px;
  border-radius: var(--radius-md, 10px);
  font-weight: 500;
  font-size: 14px;
  border: 1px solid var(--color-snow-tertiary, #cbd5e1);
  transition: all 150ms var(--ease-standard);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.btn-secondary:hover, .btn-secondary:active {
  background: var(--color-snow-secondary, #f8fafc);
  border-color: var(--color-primary);
}

.btn-danger {
  background: var(--color-ios-red, #ef4444);
  color: white;
  padding: 8px 16px;
  border-radius: var(--radius-md, 10px);
  font-weight: 600;
  font-size: 14px;
  transition: all 150ms var(--ease-standard);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.btn-danger:hover, .btn-danger:active {
  filter: brightness(0.92);
}

/* iOS Plain button */
.btn-plain {
  background: transparent;
  color: var(--color-ink-soft);
  padding: 8px 12px;
  border-radius: var(--radius-md);
  font-weight: 500;
  font-size: 14px;
}
.btn-plain:hover { background: var(--color-snow-secondary); }

/* Modal */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fadeIn 0.2s;
}

.modal-content {
  background: white;
  border-radius: 16px;
  padding: 24px;
  max-width: 500px;
  width: 90%;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 20px 50px rgba(0,0,0,0.2);
}

/* 標籤（iOS pill 形 — 圓角 full / 半透明色 + 主色文字） */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 500;
  gap: 4px;
  white-space: nowrap;
}

.badge-green  { background: color-mix(in srgb, var(--color-ios-green)  20%, transparent); color: var(--color-success); }
.badge-blue   { background: color-mix(in srgb, var(--color-ios-blue)   20%, transparent); color: var(--color-info); }
.badge-amber  { background: color-mix(in srgb, var(--color-ios-orange) 20%, transparent); color: var(--color-warning); }
.badge-red    { background: color-mix(in srgb, var(--color-ios-red)    20%, transparent); color: var(--color-danger); }
.badge-purple { background: color-mix(in srgb, var(--color-ios-indigo) 20%, transparent); color: #3E3CAE; }
.badge-gray   { background: var(--color-gray-2); color: var(--color-ink-soft); }
.badge-pink   { background: color-mix(in srgb, var(--color-ios-pink)   20%, transparent); color: #B01B45; }
.badge-mint   { background: color-mix(in srgb, var(--color-ios-mint)   20%, transparent); color: #0A736D; }

/* 品牌色橋接：把零散的 Tailwind 飽和藍「動作色」統一成玫瑰金主色（全站一次到位） */
.bg-blue-500,
.bg-blue-600 { background-color: var(--color-primary) !important; }
.bg-blue-700,
.hover\:bg-blue-700:hover { background-color: var(--color-primary-hover) !important; }

/* 預約狀態鈕：手機 3 欄、平板/桌機 5 欄。用自家 class 不依賴 Tailwind Play-CDN（其 grid-cols-N 對動態插入的 modal 不一定生成） */
.zy-appt-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; width: 100%; }
@media (min-width: 640px) { .zy-appt-actions { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

/* 無障礙：鍵盤操作時顯示玫瑰金焦點框（滑鼠點擊不顯示，不干擾日常使用） */
*:focus-visible { outline: 2px solid var(--color-primary) !important; outline-offset: 2px !important; }

/* 線性圖示（lucide）統一尺寸：跟著文字大小走、與文字基線對齊；取代原本的 emoji */
.zy-ic { display: inline-block; width: 1.05em; height: 1.05em; vertical-align: -0.16em; flex-shrink: 0; }
.zy-ic-lg { width: 1.4em; height: 1.4em; vertical-align: -0.28em; }

/* 分頁/區段切換鈕：全站統一的 active 樣式（玫瑰金軟底，與導覽 active 一致） */
.zy-seg-btn { padding: 6px 14px; font-size: 14px; border-radius: 999px; border: 1px solid var(--color-snow-tertiary); background: transparent; color: var(--color-ink-soft); cursor: pointer; transition: all 150ms ease; white-space: nowrap; }
.zy-seg-btn:hover:not(.active) { background: var(--color-snow-secondary); }
.zy-seg-btn.active { background: color-mix(in srgb, var(--color-primary) 14%, transparent); color: var(--color-primary); border-color: color-mix(in srgb, var(--color-primary) 38%, transparent); font-weight: 600; }
/* 分頁切換列：桌機換行、手機改單列橫向滑動（避免 8~10 個頁籤在窄螢幕擠成好幾列） */
.zy-seg-tabbar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
@media (max-width: 640px) {
  .zy-seg-tabbar { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 4px; scrollbar-width: thin; }
  .zy-seg-tabbar > .zy-seg-btn { flex: 0 0 auto; }
}

/* navigation tabs（iOS 風） */
.nav-tab {
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 500;
  color: var(--color-ink-soft, #64748b);
  border-bottom: 2px solid transparent;
  transition: all 150ms var(--ease-standard);
  cursor: pointer;
  background: transparent;
}

.nav-tab.active {
  color: var(--color-primary, #B8847C);
  border-bottom-color: var(--color-primary, #B8847C);
  font-weight: 600;
}

.nav-tab:hover:not(.active) {
  color: var(--color-ink, #334155);
  background: var(--color-snow-secondary, #f8fafc);
}

/* ============================================================
   sidebar — 可摺疊（桌機）+ drawer（手機）
   ============================================================ */
.sidebar {
  box-sizing: border-box;  /* padding 計入寬高，避免底部 padding 把側欄撐高溢出視窗(大字級 zoom 下更明顯) */
  width: 240px;
  background: white;
  border-right: 1px solid #e2e8f0;
  /* 業主 2026-06-24 #3：底部加 padding 避免最後一個按鈕(字體大小/粗體)被視窗底邊或手機系統UI吃掉。2026-06-26：底部再加 safe-area-inset(手機底部手勢條/瀏海) */
  padding: 10px 0 calc(24px + env(safe-area-inset-bottom, 0px));
  position: sticky;
  /* 桌機：黏在 fixed header「下方」（與 body padding-top 對齊）。原本 top:0 會讓捲動後側欄上方(✕ 與第一排項目)滑進 fixed header 底下被蓋住→點不到、✕ 收不掉。手機 @media 用 !important 覆蓋為 top:0 全螢幕 drawer，不受影響。 */
  top: calc(72px + max(env(safe-area-inset-top, 0px), 8px));
  height: calc(100vh - 72px - max(env(safe-area-inset-top, 0px), 8px));
  overflow-y: auto;
  flex-shrink: 0;
  z-index: 30;  /* 桌機值；手機在 @media 區塊用 !important 拉到 110 */
  transition: width 220ms var(--ease-standard), transform 220ms var(--ease-standard);
}

.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 14px;
  margin-bottom: 8px;
}

.sidebar-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: transparent;
  color: var(--color-gray-5, #94a3b8);
  cursor: pointer;
  transition: background 150ms;
}
.sidebar-close:hover {
  background: var(--color-snow-secondary, #f1f5f9);
  color: var(--color-ink, #334155);
}

/* 桌機：側欄改 position:fixed 固定在 fixed header 下方。
   原本用 position:sticky 會壞——側欄被 #sidebar-mount 包裹層緊貼包住（mount 高度＝側欄高度），
   sticky 無移動空間→捲動後側欄頂端(✕＋第一排項目)滑進 fixed header 底下被蓋住→點不到、✕ 收不掉。
   且是否壞掉取決於該頁 main 內容長度（內容短時更嚴重）＝業主說的「有時候沒反應」。
   fixed 定位與捲動/包裹層無關，側欄永遠固定在 header 下方、整列可點。
   #sidebar-mount 在桌機保留 240px 佔位（fixed 已脫離文件流，否則 main 會滑到側欄底下被蓋住）；
   收合時 mount 也縮到 0，main 補滿整寬。 */
@media (min-width: 769px) {
  .sidebar {
    position: fixed;
    top: calc(72px + max(env(safe-area-inset-top, 0px), 8px));
    left: 0;
    /* 2026-07-03：改用 top+bottom 兩端定位(不再用 height:100vh)。position:fixed+top/bottom 對 body{zoom} 免疫(同已驗證免疫的 #zy-inapp inset:0)，
       避免大字級(zoom 1.6×)下 100vh×zoom 把側欄撐得比視窗高、底部項目(含「字體大小/粗體」鈕、靠下導覽)掉出視窗點不到。內容過長時由 overflow-y:auto 內捲。 */
    bottom: max(env(safe-area-inset-bottom, 0px), 8px);
    height: auto;
    min-height: 0;  /* 覆蓋全域 .sidebar{min-height:100dvh}，否則側欄被撐成滿高、底部超出視窗 */
  }
  #sidebar-mount {
    width: 240px;
    flex: 0 0 240px;
    transition: width 220ms var(--ease-standard), flex-basis 220ms var(--ease-standard);
  }
  #sidebar-mount:has(.sidebar.collapsed) {
    width: 0;
    flex-basis: 0;
  }
  /* 桌機收合：完全變 0 寬 */
  .sidebar.collapsed {
    width: 0 !important;
    padding-left: 0;
    padding-right: 0;
    border-right: 0;
    overflow: hidden;
  }
  .sidebar.collapsed > * { opacity: 0; pointer-events: none; }
}

/* ============================================================
   sidebar 2-col grid mode（方案 C — 圖示 + 短標）
   每組 header 跨 2 col；items 每個 60px 高，icon 上、文字下
   ============================================================ */
.sidebar-items-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  padding: 0 6px;
}
.sidebar-group-header {
  grid-column: 1 / -1;
  padding: 8px 8px 2px;
  margin-top: 4px;
}
.sidebar-group-header:first-child {
  margin-top: 0;
  padding-top: 4px;
}
.sidebar-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 8px 4px;
  font-size: 12px;
  color: #475569;
  cursor: pointer;
  transition: all 0.15s;
  border: 1px solid transparent;
  border-radius: 8px;
  text-align: center;
  min-height: 60px;
  white-space: nowrap;
  /* 修：兩欄 grid 內 nowrap 長標題會撐爆欄寬→第二欄被擠出/遮住，且文字溢出框外→點不到。
     min-width:0 讓欄位守住 1fr、overflow 把內容鎖在格子內（整格皆可點，點擊範圍＝整個按鈕）。 */
  min-width: 0;
  overflow: hidden;
}
.sidebar-item .sidebar-item-icon { font-size: 22px; line-height: 1; }
.sidebar-item .sidebar-item-label { font-size: 12px; line-height: 1.3; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.sidebar-item:hover {
  background: #f8fafc;
  color: #1e293b;
}
.sidebar-item.active {
  background: color-mix(in srgb, var(--color-primary) 12%, transparent);
  border-color: color-mix(in srgb, var(--color-primary) 35%, transparent);
  color: var(--color-primary);
  font-weight: 600;
}

/* 手機 drawer 寬一點空間更舒服 */
@media (max-width: 768px) {
  .sidebar-items-grid { gap: 6px; padding: 0 8px; }
  .sidebar-item { min-height: 64px; }
}

/* hamburger / 切換按鈕（在 header 內） */
.sidebar-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md, 10px);
  background: var(--color-snow-secondary, #f1f5f9);
  border: 1px solid var(--color-snow-tertiary, #e2e8f0);
  color: var(--color-ink-soft, #475569);
  cursor: pointer;
  transition: all 150ms var(--ease-standard);
}
.sidebar-toggle:hover, .sidebar-toggle:active {
  background: var(--color-snow-tertiary, #e2e8f0);
  color: var(--color-ink, #1e293b);
}

/* 背景遮罩（僅手機 drawer 用）— 緊貼 sidebar 之下 */
.sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  z-index: 105;  /* sidebar(110) 之下，但壓在所有其他內容 (header z-40 / feedback z-50) 之上 */
}
.sidebar-backdrop.active {
  display: block;
  animation: fadeIn 0.2s;
  pointer-events: auto;
}

/* drawer 開啟時 sidebar 內容明確可點 */
.sidebar.mobile-open,
.sidebar.mobile-open * {
  pointer-events: auto;
}

/* ============================================================
   收摺面板（<details> 樣式統一）
   用法：<details class="zy-card zy-collapsible">
            <summary class="zy-collapsible-summary">...</summary>
            <div>body</div>
         </details>
   ============================================================ */
.zy-collapsible > .zy-collapsible-summary {
  cursor: pointer;
  list-style: none;            /* Firefox / 桌機 Safari */
  outline: none;
  padding: 4px 0;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.zy-collapsible > .zy-collapsible-summary::-webkit-details-marker {
  display: none;               /* iOS Safari / Chrome */
}
.zy-collapsible > .zy-collapsible-summary::marker {
  display: none;
  content: '';
}
.zy-collapsible-chevron {
  transition: transform 200ms var(--ease-standard);
  display: inline-block;
  font-size: 16px;
  line-height: 1;
}
.zy-collapsible:not([open]) .zy-collapsible-chevron {
  transform: rotate(-90deg);   /* 收起時箭頭轉成 ▸ */
}
.zy-collapsible > .zy-collapsible-summary:hover {
  opacity: 0.8;
}
.zy-collapsible > .zy-collapsible-summary:active {
  opacity: 0.6;
}
/* 手機觸控目標保證 */
@media (max-width: 768px) {
  .zy-collapsible > .zy-collapsible-summary { min-height: 48px; display: flex; align-items: center; }
}

/* drawer 打開時鎖背景捲動 */
body.sidebar-locked {
  overflow: hidden;
}

/* KPI cards */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
}

.kpi-card {
  background: white;
  border-radius: 12px;
  padding: 16px 20px;
  border: 1px solid #e2e8f0;
}

.kpi-label {
  font-size: 12px;
  color: #64748b;
  margin-bottom: 6px;
}

.kpi-value {
  font-size: 24px;
  font-weight: 700;
  color: #1e293b;
}

.kpi-delta {
  font-size: 12px;
  margin-top: 4px;
}

.kpi-delta.up { color: #059669; }
.kpi-delta.down { color: #dc2626; }

/* phone mockup (LIFF) */
.phone-mockup {
  max-width: 375px;
  margin: 0 auto;
  background: #1e293b;
  border-radius: 32px;
  padding: 10px;
  box-shadow: 0 20px 50px rgba(0,0,0,0.2);
}

.phone-screen {
  background: white;
  border-radius: 24px;
  min-height: 600px;
  overflow: hidden;
}

/* 真實手機上 — 拿掉 mockup 邊框，整個畫面變客戶 LIFF 內容；同時拉大字 */
@media (max-width: 768px) {
  .phone-mockup {
    max-width: 100%;
    background: transparent;
    border-radius: 0;
    padding: 0;
    box-shadow: none;
    margin: 0;
  }
  .phone-screen {
    border-radius: 0;
    min-height: auto;
    overflow: visible;
  }
  /* 內容字體拉大方便閱讀 */
  .phone-screen { font-size: 16px; }
  .phone-screen .text-sm { font-size: 15px !important; }
  .phone-screen .text-xs { font-size: 13px !important; }
  /* 大型 CTA 按鈕保持 44px+ 並全寬 */
  .phone-screen button.w-full {
    min-height: 52px;
    font-size: 16px;
  }
}

/* ============================================================
   無障礙字級放大（手機 + 電腦都生效；標準/大/特大/超大/最大 五段）
   2026-06-05：改用 zoom 整體放大 → 連 Tailwind 固定 px 文字、彈窗都一起放大，
   且電腦版也適用（原本 html font-size 法對 px 字級無效）。
   ============================================================ */
html.zy-fs-lg   body { zoom: 1.12; }
html.zy-fs-xl   body { zoom: 1.25; }
html.zy-fs-xxl  body { zoom: 1.40; }
html.zy-fs-xxxl body { zoom: 1.60; }
/* 字級放大時：浮動工具鈕（字級/計時 FAB）反向縮放 → 維持原本大小與貼齊角落，
   避免放大後 FAB 變大又上移、蓋住底部操作按鈕（手機才有 FAB） */
html.zy-fs-lg   .zy-fab { zoom: 0.893; }
html.zy-fs-xl   .zy-fab { zoom: 0.80; }
html.zy-fs-xxl  .zy-fab { zoom: 0.714; }
html.zy-fs-xxxl .zy-fab { zoom: 0.625; }
/* 2026-07-04：修「字體放大時,固定頂欄的按鈕(漢堡/返回等)畫面位置與可點位置對不齊、只點得到一部分」。
   根因:高顯示縮放(dpr,業主機器 dpr≈3)× body{zoom} 會讓固定元件的 paint 與 hit-test 偏移幾px,小按鈕(36px)半顆點不到。
   解:固定頂欄反向 counter-zoom → 以原尺度(net 1×)渲染,點擊即與視覺對齊(業主 Chrome149 dpr≈3 console 實測:修後整顆漢堡鈕含下半都可點)。
   代價:頂欄本身不隨字級放大(僅內容區放大);頂欄為導覽 chrome,可接受。同 .zy-fab 既有做法。 */
html.zy-fs-lg   header.sticky { zoom: calc(1 / 1.12); }
html.zy-fs-xl   header.sticky { zoom: calc(1 / 1.25); }
html.zy-fs-xxl  header.sticky { zoom: calc(1 / 1.40); }
html.zy-fs-xxxl header.sticky { zoom: calc(1 / 1.60); }
/* 頂欄回復 1× 後,body 讓位(padding-top)不需再被 zoom 放大 → 反向縮小,避免頂欄與內容間空隙 */
html.zy-fs-lg   body:has(> #header-mount) { padding-top: calc((72px + max(env(safe-area-inset-top, 0px), 8px)) / 1.12); }
html.zy-fs-xl   body:has(> #header-mount) { padding-top: calc((72px + max(env(safe-area-inset-top, 0px), 8px)) / 1.25); }
html.zy-fs-xxl  body:has(> #header-mount) { padding-top: calc((72px + max(env(safe-area-inset-top, 0px), 8px)) / 1.40); }
html.zy-fs-xxxl body:has(> #header-mount) { padding-top: calc((72px + max(env(safe-area-inset-top, 0px), 8px)) / 1.60); }
/* 加粗（長輩易讀）：正文加重 + 淺灰字加深 */
html.zy-bold body { font-weight: 600; }
html.zy-bold .text-slate-400, html.zy-bold .text-slate-500 { color: #475569; }

/* 浮動工具按鈕（手機顯示，墊高避開底部 tab 列 64px） */
.zy-fab {
  position: fixed; z-index: 60;  /* 須低於彈窗(≥1000)，否則浮動鈕會蓋住 modal 底部按鈕（業主回報預約詳情報到鈕被遮）；仍高於底部 tab(50) */
  width: 54px; height: 54px; border-radius: 9999px;
  display: none; align-items: center; justify-content: center;
  box-shadow: 0 4px 14px rgba(0,0,0,.28); border: none; cursor: pointer; color: #fff;
}
@media (max-width: 768px) { .zy-fab { display: flex; } }
.zy-fab-font  { left: 16px;  bottom: 88px; background: #475569; font-size: 22px; font-weight: 800; }
.zy-fab-timer { right: 16px; bottom: 88px; background: #B8847C; flex-direction: column; line-height: 1.05; }
.zy-fab-timer.running { background: #dc2626; animation: zyTimerPulse 1s infinite; }
@keyframes zyTimerPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.08); } }

/* H4 spinner — 按鈕內 inline spinner（搭配 ZyComp.submitButton） */
.zy-spinner { display:inline-block;width:14px;height:14px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:zySpin .8s linear infinite;vertical-align:middle }
@keyframes zySpin { to { transform: rotate(360deg); } }
button[data-_zy-submitting] { opacity:.85;cursor:wait }

/* I2 零閃 — 右下角「資料已更新」浮動提示動畫 */
@keyframes zyBadgeIn { from { opacity:0; transform:translateY(8px) } to { opacity:1; transform:translateY(0) } }
#zy-update-badge:hover { background:#8e5468 !important }

/* ═══════════════════════════════════════════════════════════════════════════
   民國日期欄位（ZyComp.rocDateField）— 2026-07-21 觸控修正
   現場回報：點在欄位那格裡、但沒精準點到小方塊就沒反應。
   原因：民國/年/月/日 是純文字 <span>（不可點），三個控制項之間有死區，
        視覺上像「一格」但實際可點區只有中間幾個小方塊。
   業主鐵則：可點範圍必須＝視覺範圍（不可太大也不可太小）→
   解法：整組包成「一個看得見的欄位框」，內部每一塊都屬於某個控制項或它的 label，
        熱區恰好鋪滿整格、不多不少。不使用隱形 padding 或偽元素擴大熱區。
   ═══════════════════════════════════════════════════════════════════════════ */
.zy-rocdate {
  display: inline-flex;
  align-items: stretch;          /* 內部元素撐滿高度 → 熱區＝可見格高 */
  min-height: var(--mobile-touch-target);   /* 44px */
  border: 1px solid #cbd5e1;
  border-radius: 10px;
  background: #fff;
  overflow: hidden;
  max-width: 100%;
  /* ⚠️ 必須 wrap，不可 nowrap：窄父容器（手機兩欄 grid 的起訖日期欄約 180px）
     會被 overflow:hidden 把「日」下拉整個裁掉 → 日期選不了。實測 180px 以下即發生。
     換行後控制項全部保留、各自維持 44px 熱區，容器邊框仍包住整組（視覺＝熱區）。 */
  flex-wrap: wrap;
}
.zy-rocdate:focus-within { border-color: #b8847c; box-shadow: 0 0 0 3px rgba(184,132,124,.12); }
/* label 與控制項都撐滿高度：整格任何位置點下去都命中某個元素，沒有死區 */
.zy-rocdate > label,
.zy-rocdate > input,
.zy-rocdate > select {
  display: flex;
  align-items: center;
  min-height: var(--mobile-touch-target);
  border: 0;
  background: transparent;
  font-size: 15px;               /* 手機不要 <16px，避免 iOS 自動放大 */
  color: #33302f;
  padding: 0 6px;
  margin: 0;
  /* 🔴 業主 2026-08-02（員工卡的日期欄整個爆開成 150px 高的空白方塊）：
     有些頁面自己寫了 `input,select,textarea{width:100%}`（如 staff-card.html），
     而這裡原本只給 input 設寬度、沒給 select → 月/日兩個下拉各自撐滿整列，
     容器 flex-wrap 之下就一格一行、疊成五行。
     這裡明確鎖死尺寸（選擇器比頁面的 `select` 更精確，一定贏），
     以後任何頁面再寫 width:100% 都不會再把這個元件撐爆。 */
  flex: 0 0 auto;
}
.zy-rocdate > label {
  color: #8a8280;
  font-size: 13px;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  padding: 0 4px;
}
.zy-rocdate > label:active { background: #f6efed; }   /* 讓「這裡可以點」看得出來 */
.zy-rocdate > input { width: 58px; text-align: center; font-variant-numeric: tabular-nums; }
.zy-rocdate > select { width: auto; min-width: 44px; padding-right: 2px; -webkit-appearance: none; appearance: none; text-align: center; }
/* 填一半的提示：自己占滿一行（容器 flex-wrap:wrap），不擠壓年/月/日控制項；純文字、不可點 */
.zy-rocdate > .zy-rocdate-hint {
  flex: 0 0 100%;
  padding: 2px 8px 5px;
  font-size: 12px;
  line-height: 1.4;
  color: #b91c1c;
  background: #fef2f2;
  pointer-events: none;
}
.zy-rocdate > input:focus, .zy-rocdate > select:focus { outline: none; background: #f6efed; }

/* 觸控目標最小 44×44 —— 直接放大元件本身（背景／邊框跟著長大），
   使熱區恰好＝看得見的範圍。禁止改用隱形 padding 或 ::before 撐熱區。
   （2026-07-21：先套在已量到過小的元件；全站規則另開一批處理） */
.zy-tap {
  min-height: var(--mobile-touch-target);
  min-width: var(--mobile-touch-target);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* 業主 2026-07-27：預約詳情「有什麼才顯示什麼」——空欄位不佔位、四站只列有指派的、
   三個空區塊收成一行。內容精簡後不必分欄，維持單欄窄視窗（手機也好看）。
   Tailwind 是 Play-CDN(JIT)，模板字串裡動態組的 class 不保證生成 → 版面用自家 class。 */
.zy-apt-modal { max-width: 30rem; }
.zy-apt-stations { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.zy-apt-chip { font-size: 12px; padding: 3px 10px; border-radius: 8px; background: #f1f5f9; color: #334155; white-space: nowrap; }
.zy-apt-chip b { font-weight: 600; }
.zy-apt-chip span { color: #94a3b8; }

/* ── 我的開單紀錄：分頁與展開鈕（業主 2026-08-25）─────────────────────
   Tailwind 走 Play-CDN(JIT)，模板字串裡才組出來的 class 不保證會生成 → 用自家 class。 */
.zy-myo-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px;
  border-bottom: 2px solid #ece4e1; padding-bottom: 0; }
.zy-myo-tab { appearance: none; border: 0; cursor: pointer; background: transparent;
  font-size: 14px; font-weight: 600; color: #8a7f7b; padding: 8px 14px 9px;
  border-bottom: 3px solid transparent; margin-bottom: -2px; border-radius: 8px 8px 0 0;
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.zy-myo-tab:hover { background: #faf6f4; color: #6b5f5b; }
.zy-myo-tab.on { color: #B8847C; border-bottom-color: #B8847C; background: #fff; }
.zy-myo-badge { font-size: 11px; font-weight: 700; line-height: 1;
  padding: 3px 7px; border-radius: 999px; background: #ece4e1; color: #8a7f7b; }
.zy-myo-tab.on .zy-myo-badge { background: #B8847C; color: #fff; }

/* 展開明細鈕：原本是一個很小的 ▾，現場說看不到 */
.zy-myo-exp { appearance: none; cursor: pointer; font-size: 11px; font-weight: 600;
  line-height: 1; padding: 4px 8px; margin-left: 6px; border-radius: 6px;
  border: 1px solid #d9c9c4; background: #fff; color: #B8847C; white-space: nowrap; }
.zy-myo-exp:hover { background: #faf1ee; border-color: #B8847C; }

/* ---------- 客戶卡右側動作鈕（業主 2026-08-25【7】排列不整齊）---------- */
/* 原本是 flex-col + Tailwind 的 text-xs/px-3/py-1.5，跟 .btn-* 的 padding 互相覆蓋，
   每顆寬度與內距不一致，看起來參差。改用自己的 class 一次定死：等寬、圖示靠左對齊。
   （Tailwind 是 Play-CDN(JIT)，動態組出來的類別不保證會生成 → 版面規則走 style.css） */
.zy-cus-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 132px;
}
.zy-cus-actions > button {
  width: 100%;
  justify-content: flex-start;
  padding: 7px 10px;
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
}
.zy-cus-actions > button > .zy-ic {
  flex: 0 0 auto;
}
@media (max-width: 640px) {
  /* 手機：客戶卡本來就窄，改成兩欄不要拉長一整條 */
  .zy-cus-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    min-width: 0;
  }
}

/* ---------- 預約「建檔紀錄」（業主 2026-08-27）---------- */
/* 收合時只顯示建立人一行；點開看誰改的、改了什麼。
   三角形做明顯（業主 2026-08-25 提過「可展開的三角要明顯一點」）。
   熱區＝視覺範圍：整條就是按鈕本身，不另外加隱形 padding。 */
.zy-apt-hist-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 2px 0;
  min-height: 28px;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.zy-apt-hist-sum {
  flex: 1;
  min-width: 0;
  color: #334155;
  font-weight: 500;
}
.zy-apt-hist-tri {
  flex: 0 0 auto;
  font-size: 11px;
  color: #B8847C;
  background: #fdf2f8;
  border: 1px solid #f0d9e0;
  border-radius: 6px;
  padding: 2px 6px;
  line-height: 1;
}
.zy-apt-hist-toggle:hover .zy-apt-hist-tri {
  background: #fce7f0;
  border-color: #B8847C;
}
.zy-apt-hist-body {
  margin-top: 6px;
  padding-left: 8px;
  border-left: 2px solid #f0d9e0;
}
.zy-apt-hist-row {
  padding: 5px 0;
}
.zy-apt-hist-row + .zy-apt-hist-row {
  border-top: 1px dashed #e7e5e4;
}
.zy-apt-hist-head {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.zy-apt-hist-kind {
  font-size: 11px;
  font-weight: 700;
  border-radius: 5px;
  padding: 1px 6px;
}
.zy-apt-hist-who {
  font-size: 12px;
  font-weight: 600;
  color: #44403c;
}
.zy-apt-hist-at {
  font-size: 11px;
  color: #a8a29e;
}
.zy-apt-hist-chg {
  font-size: 12px;
  color: #57534e;
  padding: 2px 0 0 2px;
  line-height: 1.5;
}
.zy-apt-hist-arrow {
  color: #B8847C;
  font-weight: 700;
}
.zy-apt-hist-note {
  font-size: 11px;
  color: #a8a29e;
  padding-left: 2px;
}

/* ---------- 預約表：凍結表頭（業主 2026-08-27【2】）---------- */
/* 日／週檢視捲下去之後看不到自己在看哪一天、也按不到日期切換。
   工具列整塊釘在頂端；週檢視再多釘一層星期欄頭。
   z-index：工具列要壓過欄頭，欄頭要壓過卡片，但都遠低於彈窗(1000+)。 */
.zy-cal-sticky {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--color-snow-bg, #FBF7F4);
  padding-top: 4px;
  margin-left: -2px;
  padding-left: 2px;
  box-shadow: 0 6px 10px -8px rgba(15, 23, 42, .25);
}
.zy-week-head {
  position: sticky;
  top: 0;
  z-index: 20;
}

/* ---------- 月檢視「還有 N 筆」＋當天完整清單彈窗（業主 2026-08-27【1】）---------- */
.zy-month-more {
  width: 100%;
  margin-top: 3px;
  padding: 2px 4px;
  border: 1px dashed #e7c9c0;
  border-radius: 6px;
  background: #fdf2f8;
  color: #8a5a52;
  font-size: 10px;
  font-weight: 700;
  line-height: 1.4;
  cursor: pointer;
}
.zy-month-more:hover {
  background: #fce7f0;
  border-color: #B8847C;
}
.zy-daypop {
  background: #fff;
  border-radius: 16px;
  width: 100%;
  max-width: 620px;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .3);
  overflow: hidden;
}
.zy-daypop-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid #f1f5f9;
  flex: 0 0 auto;
}
.zy-daypop-title {
  font-size: 17px;
  font-weight: 800;
  color: #1e293b;
}
.zy-daypop-sub {
  font-size: 12px;
  color: #94a3b8;
  margin-top: 1px;
}
.zy-daypop-head > div:first-child {
  flex: 1;
  min-width: 0;
}
.zy-daypop-x {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border: 0;
  background: transparent;
  color: #94a3b8;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  border-radius: 8px;
}
.zy-daypop-x:hover {
  background: #f1f5f9;
  color: #334155;
}
.zy-daypop-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 16px 16px;
}

/* ---------- 預約表凍結表頭・第二版（業主 2026-08-27【1】【2】【3】）---------- */
/* 第一版只加了 position:sticky，但實測是無效的 —— 祖先只要有 overflow（週檢視的
   overflow-x-auto、日檢視的 overflow-hidden），sticky 就只對那個容器生效，而它們不垂直捲。
   兩個 overflow 都拿掉了（實測週表需要橫捲 0px，本來就多餘）。
   --zy-cal-top 由 JS 量出工具列實際高度後寫入：手機換行、以後多一顆按鈕都會自動跟上。 */
:root {
  --zy-cal-top: 0px;
}
/* 業主 2026-08-28【2】：醫師與人力配置改成「不凍結」。
   （兩輪前業主要求凍結，看過實際效果後改變主意 —— 展開後很高，黏著會吃掉畫面。） */
.zy-day-topbar {
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
}
/* 🔴 要黏的是「整列」不是每一格：sticky 只能在父容器的範圍內移動，
   格子的父容器就是那一列（約 40px 高），所以格子自己 sticky 等於馬上就滑出去。
   實測改之前：捲 228px → top 139 → -89。 */
.zy-week-head {
  position: sticky;
  top: var(--zy-cal-top, 0px);
  z-index: 20;
  background: #fff;
}
/* 拿掉 overflow 之後，卡片的直角會露在圓角外面 → 底部自己收一下 */
.zy-day-wrap {
  overflow: visible;
}

@media (max-width: 767px) {
  /* 手機：整條工具列黏住會吃掉 45% 螢幕（實測 261px / 576px）→ 只黏日期那一列。
     標題與圖例照常捲走，它們是說明性的，不影響操作。 */
  /* 🔴 display:contents 是關鍵：sticky 只能在「父容器的範圍內」移動。
     若日期列還包在工具列／那一排裡面，它的可移動範圍就只有那一排的高度，
     捲一點點就滑出去（實測小手機週檢視 145 → -30）。
     讓外面兩層不產生盒子，日期列就直接掛到整頁上，才黏得住。 */
  .zy-cal-sticky,
  .zy-cal-navrow {
    display: contents;
  }
  .zy-cal-nav {
    position: sticky;
    top: 0;
    z-index: 30;
    background: var(--color-snow-bg, #FBF7F4);
    padding: 5px 0;
    margin-left: -2px;
    padding-left: 2px;
    box-shadow: 0 6px 10px -8px rgba(15, 23, 42, .25);
  }
}

/* ---------- 列印當日預約表（業主 2026-08-27【4】）---------- */
/* 熱區＝視覺範圍（業主鐵則）：按鈕本身就是可點的那一格，不另外加隱形 padding */
.zy-print-btn {
  flex: 0 0 auto;
  border: 1px solid #e7c9c0;
  border-radius: 6px;
  background: #fff;
  color: #8a5a52;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.5;
  padding: 2px 7px;
  cursor: pointer;
}
.zy-print-btn:hover {
  background: #fdf2f8;
  border-color: #B8847C;
}
/* 彈窗的頭部按鈕排在「新增預約」左邊，高度對齊 */
.zy-daypop-head .zy-print-btn {
  font-size: 12px;
  padding: 6px 10px;
}

/* 日期列那一排的版面規則收回自己的 class（業主 2026-08-27【3】）：
   原本用 Tailwind 的 .flex，手機要改成 display:contents 時會被 .flex 蓋過去
   （同權重，而 Tailwind Play-CDN 注入在 style.css 後面）→ 實測 display 還是 flex，
   日期列的可黏範圍只剩那一排的高度，小手機捲一點就滑掉。
   ⚠️ 這條要放在檔尾、且在手機的 display:contents 之後不會被覆蓋 —— 媒體查詢優先。 */
.zy-cal-navrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
@media (max-width: 767px) {
  .zy-cal-navrow {
    display: contents;
  }
}

/* 列印鈕改放清單最下方（業主 2026-08-27）：要印的人再滑到底，平常不佔上面的空間 */
.zy-day-printbar {
  display: flex;
  justify-content: center;
  padding: 10px 12px 14px;
  border-top: 1px solid #f1f5f9;
  margin-top: 4px;
}
.zy-day-printbar .zy-print-btn {
  font-size: 13px;
  padding: 7px 16px;
}

/* 週檢視標題：電腦印整週範圍、手機印「選到的那一天」（業主 2026-08-27【2】）
   兩個都印在 HTML 裡、用 CSS 決定顯示哪個 —— 轉螢幕方向不用重畫也會對。 */
.zy-cal-title-day { display: none; }
@media (max-width: 767px) {
  .zy-cal-title-wk { display: none; }
  .zy-cal-title-day { display: inline; }
}

/* ---------- 客戶備註（習慣／偏好）業主 2026-08-27 ---------- */
/* 預約表／預約詳情：接在預約備註後面，粉紅色 */
.zy-appt-pref {
  color: #db2777;
  font-weight: 600;
}
/* 客戶卡那一列 */
.zy-pref-box {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  background: #fdf2f8;
  border: 1px solid #fbcfe8;
  border-radius: 8px;
  padding: 5px 8px;
  font-size: 13px;
  line-height: 1.6;
}
.zy-pref-label {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 700;
  color: #be185d;
  background: #fce7f3;
  border-radius: 5px;
  padding: 1px 6px;
  margin-top: 2px;
}
.zy-pref-txt {
  flex: 1;
  min-width: 0;
  color: #9d174d;
  word-break: break-word;
}
/* 熱區＝視覺範圍（業主鐵則）：鉛筆就是那一格，不另外加隱形 padding */
.zy-pref-edit,
.zy-pref-add {
  flex: 0 0 auto;
  border: 1px solid #fbcfe8;
  background: #fff;
  color: #be185d;
  border-radius: 6px;
  font-size: 12px;
  line-height: 1.4;
  padding: 2px 7px;
  cursor: pointer;
}
.zy-pref-edit:hover,
.zy-pref-add:hover {
  background: #fce7f3;
  border-color: #db2777;
}
.zy-pref-add {
  font-size: 11px;
  color: #9f1239;
  border-style: dashed;
}

/* 開預約時的客戶備註提醒（業主 2026-08-27）*/
.zy-book-pref-box {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin-top: 8px;
  background: #fdf2f8;
  border: 1px solid #f9a8d4;
  border-radius: 8px;
  padding: 7px 9px;
  font-size: 13px;
  line-height: 1.6;
}

/* 🔴 業主 2026-08-28：凍結表頭跑進彈窗裡了。
   .zy-day-topbar 的 top 是 var(--zy-cal-top)（＝主畫面工具列的高度，約 116px），
   但彈窗裡沒有那條工具列 → 醫師列被釘在距離彈窗內容區 116px 的位置，
   結果卡在清單中間、蓋住預約（截圖上就夾在 12:00 與 14:00 之間）。
   彈窗裡改成貼齊自己的頂端。 */
/* 彈窗裡不要黏 —— 黏住就會蓋掉捲過去的預約卡（業主回報「凍結畫面影響到 pop up 閱讀」）。
   彈窗的清單本來就短，醫師資訊放在最上面看一次就夠。 */
.zy-daypop .zy-day-topbar {
  position: static;
  border-radius: 8px;
}
/* 彈窗裡的日檢視外框不要再畫一層邊，跟彈窗自己的邊重疊很雜 */
.zy-daypop .zy-day-wrap {
  border: 0;
}

/* ---------- 手機週檢視的星期列凍結（業主 2026-08-28【1】）---------- */
/* 黏在日期列下面 —— top 用 --zy-cal-top（JS 量出來的日期列高度）。
   只有手機需要：電腦版是整週格狀，欄頭另有處理。 */
@media (max-width: 767px) {
  .zy-week-strip {
    position: sticky;
    top: var(--zy-cal-top, 0px);
    z-index: 25;
    background: var(--color-snow-bg, #FBF7F4);
    padding: 4px 0;
    margin-bottom: 4px;
  }
}

/* ---------- 預約表工具列：日/週/月與＋靠右（業主 2026-08-28【3】）---------- */
.zy-cal-modes {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}
/* 熱區＝視覺範圍（業主鐵則）：這顆就是可點的那一格，不另外加隱形 padding */
.zy-cal-add {
  border: 0;
  background: var(--color-primary, #B8847C);
  color: #fff;
  border-radius: 8px;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  min-width: 34px;
  height: 32px;
  cursor: pointer;
}
.zy-cal-add:hover {
  background: var(--color-primary-hover, #8E5F58);
}

/* 手機上那一列很擠（390px 要塞 ← 今天 → 日期 週 月 ＋）—— 實測「今天」與日期都被折成兩行。
   一律不換行，並把左右內距與字級收一點。（業主 2026-08-28【3】） */
.zy-cal-title {
  white-space: nowrap;
}
@media (max-width: 767px) {
  .zy-cal-nav > button {
    padding-left: 8px;
    padding-right: 8px;
    white-space: nowrap;
  }
  .zy-cal-title {
    margin-left: 2px;
    font-size: 13px;
  }
  /* 業主 2026-09-18：手機多了「日」→ 四顆按鈕要塞進同一列。
     再收一點內距與間距；.zy-cal-title 讓出剩餘寬度、不夠就自己截斷，
     不可以把按鈕擠到換行（2026-08-28 就是為了不換行才調過一次）。 */
  .zy-cal-title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .zy-cal-modes {
    gap: 3px;
    flex: 0 0 auto;
  }
  .zy-cal-modes button {
    padding-left: 7px;
    padding-right: 7px;
    white-space: nowrap;
  }
  .zy-cal-add {
    min-width: 30px;
    height: 30px;
    font-size: 16px;
  }
}

/* ---------- 圖示說明收成按鈕（業主 2026-08-28）---------- */
/* 熱區＝視覺範圍（業主鐵則）：按鈕就是可點的那一格 */
.zy-cal-legend-btn {
  /* 業主 2026-08-28：原本 24.8px（padding 3px + line-height 1.4）配 12px 字，
     上下留白太多、跟旁邊 28px 的放大鏡也對不齊 → 兩顆一起壓成 22px。
     熱區＝視覺範圍（業主鐵則）：不用隱形 padding 補回來。 */
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 22px;
  min-height: 0;   /* 全站手機規則 button{min-height:44px} 會蓋掉 height，必須明寫 */
  padding: 0 9px;
  border: 1px solid #e7c9c0;
  background: #fff;
  color: #8a5a52;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}
.zy-cal-legend-btn:hover {
  background: #fdf2f8;
  border-color: #B8847C;
}
.zy-cal-legend-btn [data-caret] {
  display: inline-block;
  font-size: 10px;
  transition: transform 150ms ease;
}
.zy-cal-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  padding: 7px 10px;
  background: #fff;
  border: 1px solid #f0e4e0;
  border-radius: 10px;
}

/* 日期在剩下的空間置中（業主 2026-08-28【1】）*/
.zy-cal-title {
  flex: 1 1 auto;
  text-align: center;
  min-width: 0;
}

/* ══ 預約搜尋（業主 2026-08-28）══════════════════════════════════════════
   層級 990：預約詳情是 1000 → 詳情蓋在搜尋結果上面，關掉詳情就回到清單。
   ⚠ 不可以調到 ≥1000，否則詳情會被搜尋視窗蓋掉。 */
.zy-cal-search-btn {
  /* 業主 2026-08-28 現場回報：20px 的圓「按圖示沒反應」。
     實測整顆（含圖示中心）都點得到 —— 問題是圓太小，手指偏一點就整個落空。
     改成橫向膠囊：高度維持不變（業主要的矮留著），寬度拉開 → 點擊面積約多一倍。
     熱區仍等於視覺範圍（業主鐵則），沒有用隱形 padding 偷偷放大。 */
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 22px;
  min-height: 0;   /* 不加會被全站 button{min-height:44px} 撐成 44px */
  border: 1px solid #e7c9c0;
  background: #fff;
  color: #8a5a52;
  border-radius: 999px;
  cursor: pointer;
  padding: 0;
}
.zy-cal-search-btn:hover { background: #fdf2f8; border-color: #B8847C; }
/* 🔴 業主 2026-08-28 現場連兩次回報「按圖示沒反應，只有邊框有」。
   我在部署版上用觸控逐點掃過整顆按鈕都點得到、重現不出來，但這種症狀的標準病因
   就是「子元素接走了點擊」。圖示本來就不需要自己接事件 → 一律讓點擊穿透到按鈕本體，
   把這一整類可能性關掉（不影響外觀、也不改變熱區範圍）。 */
.zy-cal-search-btn .zy-ic,
.zy-cal-search-btn svg,
.zy-cal-legend-btn .zy-ic,
.zy-cal-legend-btn svg,
.zy-cal-legend-btn [data-caret] { pointer-events: none; }
.zy-cal-search-btn .zy-ic { width: 14px; height: 14px; }

/* 手機：高度再壓一級（業主「比文字高一點就好」），寬度照樣拉開好點。
   ⚠ 這段一定要放在上面兩條 .zy-ic / :hover 之後，否則同分特異性會被後面的蓋掉
     （上一版就是把 media 插在中間，手機的 12px 圖示規則根本沒生效）。 */
@media (max-width: 768px) {
  .zy-cal-legend-btn,
  .zy-cal-search-btn { min-height: 0; height: 20px; }
  .zy-cal-search-btn { width: 36px; }
  .zy-cal-search-btn .zy-ic { width: 13px; height: 13px; }
}

.zy-aps-ov {
  position: fixed;
  inset: 0;
  z-index: 990;
  background: rgba(15, 23, 42, .5);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 24px 16px;
}
.zy-aps-box {
  background: #fff;
  border-radius: 16px;
  width: 100%;
  max-width: 46rem;
  max-height: calc(100vh - 48px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 20px 50px rgba(15, 23, 42, .25);
}
.zy-aps-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 14px 16px 10px;
  border-bottom: 1px solid #f1f5f9;
}
.zy-aps-title { font-weight: 700; font-size: 16px; color: #3a3236; }
.zy-aps-x {
  border: 0;
  background: none;
  color: #94a3b8;
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  min-width: 44px;
  min-height: 44px;
}
.zy-aps-x:hover { color: #334155; }

.zy-aps-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  padding: 12px 16px;
  border-bottom: 1px solid #f1f5f9;
  background: #fcfaf9;
}
.zy-aps-inwrap { position: relative; flex: 1 1 260px; min-width: 0; }
.zy-aps-inwrap input {
  width: 100%;
  padding: 9px 34px 9px 12px;
  border: 1.5px solid #e2e8f0;
  border-radius: 10px;
  font-size: 15px;
  color: #1e293b;
}
.zy-aps-inwrap input:focus { outline: none; border-color: #B8847C; }
.zy-aps-clr {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  border: 0;
  background: none;
  color: #cbd5e1;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  width: 28px;
  height: 28px;
}
.zy-aps-clr:hover { color: #64748b; }
.zy-aps-chk {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #475569;
  cursor: pointer;
  white-space: nowrap;
}
.zy-aps-chk input { width: 16px; height: 16px; accent-color: #B8847C; }

.zy-aps-body { flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.zy-aps-hint { padding: 28px 18px; text-align: center; font-size: 13px; color: #64748b; line-height: 1.8; }
.zy-aps-dim { color: #94a3b8; }
.zy-aps-sep {
  padding: 6px 16px;
  font-size: 12px;
  font-weight: 600;
  color: #8a5a52;
  background: #fdf2f8;
  border-top: 1px solid #f3d9e4;
  border-bottom: 1px solid #f3d9e4;
}
.zy-aps-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  width: 100%;
  text-align: left;
  padding: 10px 16px;
  border: 0;
  border-bottom: 1px solid #f1f5f9;
  background: #fff;
  cursor: pointer;
  font-size: 13px;
  color: #334155;
  line-height: 1.6;
}
.zy-aps-row:hover { background: #fdf2f8; }
.zy-aps-off { opacity: .55; }
.zy-aps-off .zy-aps-name { text-decoration: line-through; }
.zy-aps-c { min-width: 0; }
.zy-aps-when { font-variant-numeric: tabular-nums; color: #8a5a52; font-weight: 600; flex: 0 0 auto; }
.zy-aps-name { flex: 0 0 auto; color: #1e293b; }
.zy-aps-bd, .zy-aps-ph { flex: 0 0 auto; font-variant-numeric: tabular-nums; }
.zy-aps-note { flex: 1 1 160px; color: #64748b; overflow-wrap: anywhere; }
.zy-aps-status { flex: 0 0 auto; margin-left: auto; }
.zy-aps-st { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.zy-aps-st-pending { background: #f1f5f9; color: #64748b; }
.zy-aps-st-arrived { background: #fef3c7; color: #92400e; }
.zy-aps-st-done { background: #dcfce7; color: #166534; }
.zy-aps-st-cancel { background: #fee2e2; color: #b91c1c; }

.zy-aps-footbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 12px;
  padding: 9px 16px;
  border-top: 1px solid #f1f5f9;
  font-size: 12px;
  background: #fcfaf9;
}

/* 手機：整頁滿版，清單才有空間；分隔線用「｜」在窄螢幕會擠，改成換行排 */
@media (max-width: 640px) {
  .zy-aps-ov { padding: 0; }
  .zy-aps-box { max-width: none; border-radius: 0; max-height: 100vh; height: 100vh; }
  .zy-aps-row { font-size: 13px; padding: 12px 14px; }
  .zy-aps-status { margin-left: 0; }
  /* 「切換角色」浮動鈕在左下角，會蓋住底部說明 → 手機只留筆數 */
  .zy-aps-footbar { justify-content: flex-end; padding-bottom: 14px; }
  .zy-aps-footbar > :last-child { display: none; }
}

/* ── 選商品清單：多欄（業主 2026-09-08）──────────────────────────
   桌機是橫式螢幕，原本一列一項 → 每列 860px 寬、右邊整片空白，
   420px 的容器一次只看得到 5 項。改成隨寬度自動長欄：
   窄機 1 欄、平板 2 欄、寬螢幕 3 欄，同樣高度可以看到 3 倍的商品。
   ⚠️ 用 auto-fill + minmax 而不是寫死欄數 —— 這個元件在 iframe 裡，
      實際可用寬度會隨外殼側欄開合變動，寫死欄數會在窄的時候擠爆。 */
.zy-pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 8px;
  align-content: start;
}
.zy-pick-grid > * { min-width: 0; }          /* 讓長品名能省略，不要把格子撐開 */

/* ── 訂單明細：清單式（業主 2026-09-08）─────────────────────────
   原本每一項是一張含單價／數量／總價／四顆價格鈕的大卡，滿版很雜亂。
   改成一列，要改價／贈送／加購才點開。 */
.zy-cart-row { border-bottom: 1px solid #f1f5f9; }
.zy-cart-row:last-child { border-bottom: 0; }
/* 業主 2026-09-10（第三輪）：一列塞六樣東西（勾選框／▸／品名／數量／金額／✕），
   明細欄只有約 350px，品名被壓成三四行。→ 拆成兩層。
     第一層：☐ ▸ 品名（拿到整行寬度）……✕
     第二層：－ 1 ＋ ……………………… 標籤／金額
     第三層：只有「● 未選」「已改價」這種提醒才出現
   ⚠️ 舊的 .zy-cart-name / .zy-cart-title / .zy-cart-meta 已經沒人用，整組移除 ——
      留著只會讓下一個人以為那個結構還在（死碼是踩過的坑）。 */
.zy-cart-head { padding: 7px 2px; cursor: pointer; }
.zy-cart-head:hover { background: #fafafa; }

.zy-cart-r1 { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
/* 品名不截字：長品名（例「【活動】薇貝拉（白／黑）／Ellanse(S)／精靈針（四選一）」24 字）
   一截就看不出賣的是什麼。現在它拿到整行寬度，自然換行也只會是兩行。 */
.zy-cart-r1 > .zy-cart-t {
  flex: 1 1 auto; min-width: 0;
  font-size: 13px; font-weight: 600; color: #1e293b;
  white-space: normal; word-break: break-word; line-height: 1.35;
}
.zy-cart-del { align-self: flex-start; }

.zy-cart-r2 {
  display: flex; align-items: center; gap: 8px;
  margin-top: 3px; padding-left: 25px;   /* 對齊第一層的品名起點（勾選框 15 + gap 8 + caret） */
}
.zy-cart-qtybox { display: inline-flex; align-items: center; gap: 2px; flex: 0 0 auto; }
.zy-cart-money {
  margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  flex-wrap: wrap; justify-content: flex-end; min-width: 0;
}
.zy-cart-money .badge { white-space: nowrap; flex: 0 0 auto; }

.zy-cart-r3 {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
  margin-top: 3px; padding-left: 25px; min-width: 0;
}
.zy-cart-r3 .badge, .zy-cart-r3 .zy-cart-need { white-space: nowrap; flex: 0 0 auto; }

.zy-cart-sub { font-weight: 400; font-size: 11px; color: #94a3b8; min-width: 0; }
.zy-cart-qty { font-size: 12px; color: #64748b; font-variant-numeric: tabular-nums; white-space: nowrap; }
.zy-cart-sum {
  font-size: 13px; font-weight: 700; color: #8a5a52; text-align: right;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.zy-cart-caret { color: #cbd5e1; font-size: 11px; width: 1em; text-align: center; flex: 0 0 auto; line-height: 1.5; }
.zy-cart-body { padding: 2px 2px 10px; }

/* 訂單明細：多選一還沒選（業主 2026-09-08）──────────────────────
   那個下拉在展開區裡，收合時完全看不出來，一路到送單才被守門擋下來。
   整列標紅＋一顆紅點，收合狀態也一眼看得到。 */
.zy-cart-row.zy-cart-warn { background: #fef2f2; }
.zy-cart-row.zy-cart-warn .zy-cart-head:hover { background: #fee2e2; }
.zy-cart-need {
  font-size: 10px; font-weight: 700; line-height: 1.4;
  color: #b91c1c; background: #fee2e2; border: 1px solid #fecaca;
  border-radius: 999px; padding: 0 6px; white-space: nowrap;
}


/* ── 訂單明細：多選 ＋ 批次標記（業主 2026-09-10）───────────────── */
.zy-cart-sel { width: 15px; height: 15px; flex: 0 0 auto; cursor: pointer; accent-color: #B8847C; }
.zy-cart-bulk {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 2px 8px; margin-bottom: 2px; border-bottom: 1px solid #f1f5f9;
}
.zy-cart-bulk-all { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; font-size: 12px; color: #64748b; }
.zy-cart-bulk-all input { width: 15px; height: 15px; cursor: pointer; accent-color: #B8847C; }
.zy-cart-bulk-n { font-size: 12px; color: #334155; }
.zy-cart-bulk-hint { font-size: 11px; color: #cbd5e1; }
/* 兩顆批次按鈕在卡片標題右邊（buildCard 的 action 插槽） */
/* 業主 2026-09-12：三顆按鈕不可以換行（加了「贈送」之後會擠成兩排，
   連標題的「訂單明細 3 項」都被擠斷成兩行）。
   ・整組 flex-shrink:0 → 寬度不夠時先壓標題，不要把按鈕擠下去
   ・最多只會有一顆變成「取消◯◯」（一列只有一個標記），最壞情況也放得下 */
.zy-cart-bulk-btns { display: flex; gap: 4px; flex-wrap: nowrap; align-items: center; flex-shrink: 0; }
/* 標題那一格：寬度不夠時自己縮、不要斷字。
   ⚠️ 只限「有批次按鈕的那張卡」—— 全站的卡片標題都套 nowrap 的話，
      其他比較長的標題會被截成「…」。:has() 不支援的瀏覽器就整條忽略，不影響原本行為。 */
.zy-card-header:has(.zy-cart-bulk-btns) > h3 {
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 訂單明細的項目清單：最長跟「選商品」那欄齊平，超過就自己捲。
   選商品是 max-h-[62vh] md:max-h-[560px]；這裡要扣掉標題、全選列、合計那幾塊，
   所以給 470px（實測兩欄底部差在 20px 內）。 */
.zy-cart-list { max-height: 52vh; overflow-y: auto; }
@media (min-width: 768px) { .zy-cart-list { max-height: 470px; } }


/* 業主 2026-09-14：日期輸入框填完之後，旁邊顯示週幾（客人都講「約下週三」）。
   不佔位、空的時候完全看不到；不可以撐開那一格的高度。 */
.zy-rocdate-wd {
  font-size: 12px;
  color: #B8847C;
  font-weight: 600;
  margin-left: 2px;
  white-space: nowrap;
}
.zy-rocdate-wd:empty { display: none; }

/* 業主 2026-09-22：客人自助預約可以打很長的備註 —— 預約表的卡片不可以跟著無限拉長。
   夾成兩行、超過用 …，完整內容還是掛在 title 上（滑過去看得到）。
   ⚠️ 寫在這裡不用 Tailwind 的 line-clamp —— Play-CDN 的 JIT 不保證會生成那個 class。 */
.zy-note-clamp{
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
  word-break:break-word;
}
