/* ==========================================================================
   Component Kit — Production CSS
   淺色簡約風格元件庫樣式表

   結構說明：
   1. 共用設定 (:root)：動畫曲線、背景圖案、陰影、版面等，所有配色組合共用
   2. 配色組合 (html[data-theme="..."])：唯一「色系專屬」的區塊
      - 新增色系：複製一整塊，改 data-theme 名稱與 7 個顏色值即可
      - 刪除色系：直接刪除整塊
   3. 其餘為各元件樣式 (按鈕/切換顯示/開關/滑桿/輸入框/核取單選/卡片/標籤/分頁)

   使用方式：在 HTML 的 <html> 標籤上加上 data-theme="pink" 或 data-theme="charcoal"
   即可切換配色，其餘所有元件皆會自動套用對應色彩。
   ========================================================================== */

/* ======================================================================
     共用設定（動畫曲線 / 背景圖案 / 陰影 / 版面）：所有配色組合共用同一份
     ====================================================================== */
  :root{
    --ease: cubic-bezier(.34,1.56,.64,1);   /* 輕彈 */
    --dur: 0.35s;
    --pattern-size: 44px;                    /* 背景網格大小 */
    --pattern-opacity: 0.12;                 /* 背景網格不透明度 */
    --card-shadow-blur: 6px;
    --card-shadow-offset: 3px;
    --page-bg:#FFFFFF;
    --card-bg:#FFFFFF;
    --toggle-off:#E4DBDA;
    --thumb-bg:#FFFFFF;
    --radius-sm: 8px;
    --radius-md: 14px;
  }

  /* ======================================================================
     配色組合：只有這一段是「色系專屬」。
     要增加新色系 → 複製一整塊，改 [data-theme="xxx"] 跟裡面 7 個顏色值即可。
     要刪除色系 → 直接刪掉整塊，並把下面 .theme-switch 裡對應的按鈕移除。
     ====================================================================== */
  html[data-theme="pink"]{
    --accent:      #E47789;
    --accent-rgb:  228,119,137;
    --accent-dark: #D93B55;
    --accent-light:#F5E6E8;
    --surface-alt: #F8F1F3;
    --text:        #2F2224;
    --text-secondary: #7F6C6F;
    --border:      #EADBDE;
  }

  html[data-theme="charcoal"]{
    --accent:      #797D86;
    --accent-rgb:  121,125,134;
    --accent-dark: #575A60;
    --accent-light:#BEC4CF;
    --surface-alt: #F5F5F5;
    --text:        #22272F;
    --text-secondary: #6C727F;
    --border:      #E2E3E4;
  }
  /* ====================================================================== */

  *{ box-sizing:border-box; }
  html{ scroll-behavior:smooth; }

  body{
    margin:0; color:var(--text);
    font-family:'Noto Sans TC', -apple-system, BlinkMacSystemFont, sans-serif;
    line-height:1.6; -webkit-font-smoothing:antialiased;
    background:var(--page-bg);
    transition: color .4s ease;
  }
  .mono{ font-family:'JetBrains Mono', 'Noto Sans TC', monospace; }

  /* ---------- Layout ---------- */
  .app{ display:grid; grid-template-columns:240px 1fr; min-height:100vh; }

  .sidebar{
    position:sticky; top:0; height:100vh; padding:32px 20px;
    border-right:1px solid var(--border); background:var(--card-bg);
    transition: border-color .4s ease;
  }
  .brand{ display:flex; align-items:center; gap:10px; margin-bottom:6px; }
  .brand-dot{ width:12px; height:12px; border-radius:50%; background:var(--accent); flex-shrink:0; transition: background-color .3s ease; }
  .brand-title{ font-weight:700; font-size:15px; letter-spacing:0.02em; }
  .brand-sub{ font-size:12px; color:var(--text-secondary); margin:0 0 24px 22px; }

  .theme-switch{
    display:inline-flex; background:var(--surface-alt); border-radius:999px; padding:4px; gap:2px; margin:0 0 28px 0;
  }
  .theme-switch button{
    font-family:inherit; font-size:12.5px; font-weight:500; padding:7px 14px; border-radius:999px; border:none;
    background:transparent; color:var(--text-secondary); cursor:pointer; display:flex; align-items:center; gap:6px;
    transition: transform var(--dur) var(--ease), background .15s ease, color .15s ease, box-shadow .15s ease;
  }
  .theme-switch button::before{ content:""; width:10px; height:10px; border-radius:50%; background:var(--sw); }
  .theme-switch button:hover{ transform:translateY(-2px); }
  .theme-switch button.active{ background:var(--card-bg); color:var(--text); box-shadow:0 1px 3px rgba(43,37,38,0.1); }

  .nav-list{ list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:2px; }
  .nav-list a{
    position:relative;
    display:flex; align-items:center; gap:10px; padding:9px 12px 12px; border-radius:var(--radius-sm);
    color:var(--text-secondary); text-decoration:none; font-size:13.5px;
    transition: background .15s ease, color .15s ease, transform var(--dur) var(--ease);
  }
  .nav-list a:hover{ background:var(--surface-alt); color:var(--text); transform:translateX(3px); }
  .nav-list a::after{
    content:""; position:absolute; left:40px; bottom:4px; width:0; height:2px;
    background:var(--accent); border-radius:999px; transition: width .2s ease, background-color .3s ease;
  }
  .nav-list a.active{ color:var(--text); font-weight:600; }
  .nav-list a.active::after{ width:16px; }
  .nav-index{ font-family:'JetBrains Mono', monospace; font-size:11px; color:var(--accent-dark); width:18px; }

  .main{
    padding:48px 56px 120px; max-width:1000px;
    background-color:var(--page-bg);
    background-image:
      linear-gradient(rgba(var(--accent-rgb), var(--pattern-opacity)) 1px, transparent 1px),
      linear-gradient(90deg, rgba(var(--accent-rgb), var(--pattern-opacity)) 1px, transparent 1px);
    background-size: var(--pattern-size) var(--pattern-size);
    background-attachment: fixed;
    transition: background-color .4s ease;
  }

  header.page-head{ margin-bottom:40px; }
  header.page-head h1{ font-size:30px; font-weight:700; margin:0 0 10px; letter-spacing:-0.01em; }
  header.page-head p{ color:var(--text-secondary); font-size:14.5px; margin:0; max-width:600px; }

  section.block{ margin-bottom:64px; scroll-margin-top:32px; }
  .block-head{ display:flex; align-items:baseline; gap:12px; margin-bottom:6px; }
  .block-index{
    font-family:'JetBrains Mono', monospace; font-size:12px; color:var(--accent-dark);
    background:var(--accent-light); padding:2px 8px; border-radius:999px;
    transition: background-color .3s ease, color .3s ease;
  }
  .block-head h2{ font-size:18px; font-weight:700; margin:0; }
  .block-desc{ color:var(--text-secondary); font-size:13.5px; margin:0 0 20px; }

  .card{
    background:var(--card-bg); border:1px solid var(--border); border-radius:var(--radius-md);
    box-shadow: 0 var(--card-shadow-offset) var(--card-shadow-blur) rgba(43,37,38,0.13); padding:28px;
    transition: border-color .4s ease;
  }

  .demo-row{ display:flex; flex-wrap:wrap; align-items:center; gap:14px; }
  .demo-row + .demo-row{ margin-top:18px; }
  .demo-label{ font-size:12px; color:var(--text-secondary); width:100%; margin-bottom:4px; }

  .readout{
    display:inline-flex; align-items:center; gap:7px; font-family:'JetBrains Mono', monospace; font-size:11.5px;
    color:var(--accent-dark); background:var(--accent-light); border-radius:999px; padding:5px 12px 5px 8px; margin-top:16px;
    transition: background-color .3s ease, color .3s ease;
  }
  .readout-dot{ width:6px; height:6px; border-radius:50%; background:var(--accent); transition: background-color .3s ease; }
  .readout.pulse .readout-dot{ animation:pulse 0.5s ease; }
  @keyframes pulse{ 0%{ transform:scale(1); } 40%{ transform:scale(1.9); } 100%{ transform:scale(1); } }

  /* ---------- Buttons ---------- */
  .btn{
    font-family:inherit; font-size:13.5px; font-weight:500; border-radius:999px; padding:10px 20px; border:1px solid transparent;
    cursor:pointer; transition: transform var(--dur) var(--ease), background .2s ease, color .2s ease;
  }
  .btn:hover{ transform:translateY(-3px) scale(1.035); }
  .btn:active{ transform:scale(0.95); transition: transform 0.1s ease; }
  .btn-primary{ background:var(--accent); color:#fff; }
  .btn-primary:hover{ background:var(--accent-dark); }
  .btn-secondary{ background:var(--card-bg); color:var(--accent-dark); border-color:var(--accent); }
  .btn-secondary:hover{ background:var(--accent-light); }
  .btn-ghost{ background:transparent; color:var(--text-secondary); }
  .btn-ghost:hover{ background:var(--surface-alt); color:var(--text); }
  .btn-disabled{ background:var(--surface-alt); color:#C9BFC0; cursor:not-allowed; border-color:var(--border); }
  .btn-disabled:hover{ transform:none; }
  .btn-disabled:active{ transform:none; }
  .btn-icon{
    width:38px; height:38px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; padding:0;
    background:var(--card-bg); border:1px solid var(--border); color:var(--text-secondary);
    transition: transform var(--dur) var(--ease), border-color .2s ease, color .2s ease;
  }
  .btn-icon:hover{ border-color:var(--accent); color:var(--accent-dark); transform:rotate(-10deg) scale(1.12); }
  .btn-icon:active{ transform:scale(0.92); transition: transform .1s ease; }

  .segmented{ display:inline-flex; flex-wrap:wrap; row-gap:4px; background:var(--surface-alt); border-radius:999px; padding:4px; gap:2px; transition: background-color .3s ease; }
  .segmented button{
    font-family:inherit; font-size:13px; font-weight:500; padding:8px 16px; border-radius:999px; border:none;
    background:transparent; color:var(--text-secondary); cursor:pointer;
    transition: transform var(--dur) var(--ease), background .15s ease, color .15s ease, box-shadow .15s ease;
  }
  .segmented button:hover:not(.active){ transform:translateY(-2px); color:var(--text); }
  .segmented button.active{ background:var(--card-bg); color:var(--accent-dark); box-shadow: 0 1px 3px rgba(43,37,38,0.08); }

  /* ---------- Disclosure ---------- */
  .disclosure-btn{
    display:inline-flex; align-items:center; gap:8px; background:var(--card-bg); border:1px solid var(--border); border-radius:var(--radius-sm);
    padding:10px 16px; font-family:inherit; font-size:13.5px; font-weight:500; color:var(--text); cursor:pointer;
    transition: transform var(--dur) var(--ease), border-color .2s ease;
  }
  .disclosure-btn:hover{ border-color:var(--accent); transform:translateY(-2px); }
  .chevron{ width:14px; height:14px; transition: transform .25s ease; color:var(--accent-dark); }
  .disclosure-btn[aria-expanded="true"] .chevron{ transform:rotate(180deg); }
  .disclosure-panel{ overflow:hidden; max-height:0; transition:max-height 0.25s ease; }
  .disclosure-panel-inner{ margin-top:14px; padding:16px 18px; background:var(--surface-alt); border-radius:var(--radius-sm); font-size:13.5px; color:var(--text-secondary); transition: background-color .3s ease; }

  /* ---------- Switch ---------- */
  .switch-row{ display:flex; align-items:center; justify-content:space-between; padding:14px 0; }
  .switch-row + .switch-row{ border-top:1px solid var(--border); }
  .switch-text strong{ display:block; font-size:13.5px; font-weight:600; }
  .switch-text span{ font-size:12px; color:var(--text-secondary); }
  .switch{ position:relative; width:42px; height:24px; flex-shrink:0; }
  .switch input{ opacity:0; width:100%; height:100%; margin:0; cursor:pointer; position:relative; z-index:2; }
  .switch-track{ position:absolute; inset:0; background:var(--toggle-off); border-radius:999px; transition: background .2s ease, box-shadow .2s ease; }
  .switch-thumb{ position:absolute; top:3px; left:3px; width:18px; height:18px; border-radius:50%; background:var(--thumb-bg); box-shadow: 0 1px 3px rgba(43,37,38,0.15); transition: transform var(--dur) var(--ease); }
  .switch input:checked ~ .switch-track{ background:var(--accent); }
  .switch input:checked ~ .switch-thumb{ transform:translateX(18px); }
  .switch:hover .switch-track{ box-shadow: 0 0 0 5px var(--accent-light); }

  /* ---------- Slider ---------- */
  .slider-wrap{ display:flex; align-items:center; gap:14px; }
  input[type="range"]{ -webkit-appearance:none; appearance:none; flex:1; height:4px; border-radius:999px; background:var(--border); outline:none; }
  input[type="range"]::-webkit-slider-runnable-track{ height:4px; border-radius:999px; background:linear-gradient(to right, var(--accent) 0%, var(--accent) var(--fill,50%), var(--border) var(--fill,50%), var(--border) 100%); }
  input[type="range"]::-webkit-slider-thumb{ -webkit-appearance:none; width:18px; height:18px; border-radius:50%; background:var(--card-bg); border:2px solid var(--accent); margin-top:-7px; cursor:pointer; box-shadow: 0 1px 3px rgba(43,37,38,0.15); transition: transform var(--dur) var(--ease); }
  input[type="range"]::-webkit-slider-thumb:hover{ transform:scale(1.25); }
  input[type="range"]::-moz-range-track{ height:4px; border-radius:999px; background:var(--border); }
  input[type="range"]::-moz-range-progress{ height:4px; border-radius:999px; background:var(--accent); }
  input[type="range"]::-moz-range-thumb{ width:16px; height:16px; border-radius:50%; background:var(--card-bg); border:2px solid var(--accent); cursor:pointer; }

  .slider-number{
    width:64px; text-align:center; font-family:'JetBrains Mono', monospace; font-size:13px; font-weight:500;
    color:var(--accent-dark); background:var(--card-bg); border:1px solid var(--border); border-radius:8px; padding:7px 4px; outline:none;
    transition: border-color .2s ease, box-shadow .2s ease, color .3s ease; -moz-appearance:textfield;
  }
  .slider-number::-webkit-inner-spin-button, .slider-number::-webkit-outer-spin-button{ -webkit-appearance:none; margin:0; }
  .slider-number:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-light); }

  /* ---------- Inputs ---------- */
  .field{ margin-bottom:18px; }
  .field label{ display:block; font-size:12.5px; font-weight:500; color:var(--text-secondary); margin-bottom:7px; }
  .field input[type="text"], .field input[type="search"], .field textarea{
    width:100%; font-family:inherit; font-size:13.5px; color:var(--text); background:var(--card-bg); border:1px solid var(--border);
    border-radius:var(--radius-sm); padding:11px 14px; outline:none;
    transition: border-color .15s ease, box-shadow .15s ease;
  }
  .field input:focus, .field textarea:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-light); }
  .field textarea{ resize:vertical; min-height:80px; }
  .input-icon-wrap{ position:relative; }
  .input-icon-wrap svg{ position:absolute; left:14px; top:50%; transform:translateY(-50%); width:15px; height:15px; color:var(--text-secondary); }
  .input-icon-wrap input{ padding-left:38px !important; }
  .char-count{ text-align:right; font-size:11px; color:var(--text-secondary); margin-top:6px; font-family:'JetBrains Mono', monospace; }

  /* ---------- Checkbox / Radio ---------- */
  .choice-group{ display:flex; flex-direction:column; gap:12px; }
  .choice{ display:flex; align-items:center; gap:10px; cursor:pointer; font-size:13.5px; }
  .choice input{ display:none; }
  .choice-box{
    width:18px; height:18px; border:1.5px solid var(--border); background:var(--card-bg); flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    transition: background .15s ease, border-color .15s ease, transform var(--dur) var(--ease);
  }
  .choice:hover .choice-box{ transform:scale(1.12); border-color:var(--accent); }
  .choice-box.round{ border-radius:50%; }
  .choice-box.square{ border-radius:5px; }
  .choice-box svg{ width:11px; height:11px; opacity:0; transition:opacity 0.1s ease; }
  .choice-box .dot{ width:8px; height:8px; border-radius:50%; background:#fff; opacity:0; transition:opacity 0.1s ease; }
  .choice input:checked + .choice-box{ background:var(--accent); border-color:var(--accent); }
  .choice input:checked + .choice-box svg{ opacity:1; }
  .choice input:checked + .choice-box .dot{ opacity:1; }

  /* ---------- Cards / Blocks ---------- */
  .grid-3{ display:grid; grid-template-columns:repeat(3, 1fr); gap:16px; }
  .mini-card{
    background:var(--card-bg); border:1px solid var(--border); border-radius:var(--radius-md); padding:20px;
    box-shadow: 0 var(--card-shadow-offset) var(--card-shadow-blur) rgba(43,37,38,0.13);
    transition: box-shadow .25s ease, transform var(--dur) var(--ease), border-color .3s ease;
  }
  .mini-card:hover{ box-shadow: 0 calc(var(--card-shadow-offset) + 10px) calc(var(--card-shadow-blur) + 14px) rgba(43,37,38,0.2); transform:translateY(-6px) scale(1.015); }
  .mini-card .icon-tile{
    width:36px; height:36px; border-radius:10px; background:var(--accent-light); color:var(--accent-dark);
    display:flex; align-items:center; justify-content:center; margin-bottom:14px;
    transition: transform var(--dur) var(--ease), background-color .3s ease, color .3s ease;
  }
  .mini-card:hover .icon-tile{ transform:rotate(-8deg) scale(1.1); }
  .mini-card .icon-tile svg{ width:18px; height:18px; }
  .mini-card h3{ font-size:14px; margin:0 0 6px; }
  .mini-card p{ font-size:12.5px; color:var(--text-secondary); margin:0; }
  .stat-card{ display:flex; align-items:center; justify-content:space-between; }
  .stat-card .num{ font-size:28px; font-weight:700; font-family:'JetBrains Mono', monospace; }
  .stat-card .label{ font-size:12px; color:var(--text-secondary); }
  .stat-card .badge-up{ font-size:11.5px; font-family:'JetBrains Mono', monospace; color:var(--accent-dark); background:var(--accent-light); padding:3px 8px; border-radius:999px; transition: background-color .3s ease, color .3s ease; }

  /* ---------- Tags ---------- */
  .tag-row{ display:flex; flex-wrap:wrap; gap:8px; }
  .tag{
    display:inline-flex; align-items:center; gap:6px; font-size:12px; padding:5px 12px; border-radius:999px;
    background:var(--accent-light); color:var(--accent-dark);
    transition: transform var(--dur) var(--ease), background-color .3s ease, color .3s ease;
  }
  .tag:hover{ transform:translateY(-2px) scale(1.06); }
  .tag.outline{ background:var(--card-bg); border:1px solid var(--border); color:var(--text-secondary); }
  .tag button{ border:none; background:transparent; color:inherit; cursor:pointer; padding:0; display:flex; opacity:0.7; }
  .tag button:hover{ opacity:1; }

  /* ---------- Tabs ---------- */
  .tabs{ display:flex; gap:4px; border-bottom:1px solid var(--border); margin-bottom:18px; }
  .tab-btn{
    font-family:inherit; font-size:13.5px; font-weight:500; padding:10px 4px; margin-right:22px; border:none;
    background:transparent; color:var(--text-secondary); cursor:pointer; position:relative;
    transition: transform var(--dur) var(--ease), color .15s ease;
  }
  .tab-btn:hover{ transform:translateY(-2px); color:var(--text); }
  .tab-btn::after{ content:""; position:absolute; left:0; right:0; bottom:-1px; height:2px; background:var(--accent); transform:scaleX(0); transition: transform .2s ease, background-color .3s ease; }
  .tab-btn.active{ color:var(--text); }
  .tab-btn.active::after{ transform:scaleX(1); }
  .tab-panel{ display:none; font-size:13.5px; color:var(--text-secondary); }
  .tab-panel.active{ display:block; }

  @media (max-width: 860px){
    .app{ grid-template-columns:1fr; }
    .sidebar{ position:relative; height:auto; }
    .main{ padding:32px 20px 80px; }
    .grid-3{ grid-template-columns:1fr; }
  }

  /* ======================================================================
     以下為 Live2D 參數快照面板新增的通用元件。
     原元件庫沒有提供，但屬於可跨專案複用的基礎樣式，故併入本檔而非 app.css：
       下拉選單 / 摺疊容器 / 對話框 / 訊息提示 / 拖曳
     ====================================================================== */

  /* ---------- Select 下拉選單 ---------- */
  .select-native{
    width:100%; font-family:inherit; font-size:13.5px; color:var(--text);
    background:var(--card-bg); border:1px solid var(--border); border-radius:var(--radius-sm);
    padding:9px 34px 9px 12px; outline:none; cursor:pointer;
    -webkit-appearance:none; appearance:none;
    background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat:no-repeat; background-position:right 10px center; background-size:14px;
    transition: border-color .15s ease, box-shadow .15s ease;
  }
  .select-native:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-light); }
  .select-native:disabled{ background-color:var(--surface-alt); color:var(--text-secondary); cursor:not-allowed; }

  /* ---------- Collapsible 摺疊容器 ----------
     使用 grid-template-rows 0fr → 1fr 做動畫。
     相較於 maxHeight = scrollHeight 的作法，此法在巢狀且高度會變動的內容下
     不會發生內容被裁切的問題，也不需要在內容變動時重新計算高度。            */
  .collapsible{
    display:grid; grid-template-rows:0fr;
    transition: grid-template-rows .26s var(--ease);
  }
  .collapsible.open{ grid-template-rows:1fr; }
  /* 這一層是裁切層，必須維持零內距零邊框。
     內距一旦寫在這裡，摺疊到 0fr 時內距仍會佔據高度而露出內容，
     所以所有內距一律寫在下一層的 .collapsible-inner。                     */
  .collapsible > div{
    overflow:hidden; min-height:0; padding:0; border:0; margin:0;
  }
  .collapsible-inner{ min-height:0; }

  /* ---------- Modal 對話框 ---------- */
  .modal-overlay{
    position:fixed; inset:0; z-index:9000; display:none;
    align-items:center; justify-content:center; padding:24px;
    background:rgba(43,37,38,0.38); backdrop-filter:blur(2px);
  }
  .modal-overlay.open{ display:flex; animation:modalFade .18s ease; }
  @keyframes modalFade{ from{ opacity:0; } to{ opacity:1; } }
  .modal{
    width:100%; max-width:440px; background:var(--card-bg); border:1px solid var(--border);
    border-radius:var(--radius-md); padding:26px;
    box-shadow:0 18px 48px rgba(43,37,38,0.24);
    animation:modalPop .26s var(--ease);
  }
  @keyframes modalPop{ from{ transform:translateY(14px) scale(.96); } to{ transform:none; } }
  .modal-title{ margin:0 0 10px; font-size:15px; font-weight:700; }
  .modal-message{ margin:0 0 18px; font-size:13.5px; color:var(--text-secondary); white-space:pre-wrap; }
  .modal-field{ margin-bottom:18px; }
  .modal-input-label{ display:block; font-size:12.5px; color:var(--text-secondary); margin-bottom:7px; }
  .modal-input{
    width:100%; font-family:inherit; font-size:13.5px; color:var(--text); background:var(--card-bg);
    border:1px solid var(--border); border-radius:var(--radius-sm); padding:10px 13px; outline:none;
    transition: border-color .15s ease, box-shadow .15s ease;
  }
  .modal-input:focus{ border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-light); }
  .modal-actions{ display:flex; justify-content:flex-end; gap:10px; }

  /* ---------- Toast 訊息提示 ---------- */
  .toast-container{
    position:fixed; right:20px; bottom:20px; z-index:9500;
    display:flex; flex-direction:column; gap:10px; align-items:flex-end; pointer-events:none;
  }
  .toast{
    max-width:360px; font-size:13px; line-height:1.5; padding:11px 16px; border-radius:var(--radius-sm);
    background:var(--card-bg); color:var(--text); border:1px solid var(--border); border-left-width:4px;
    box-shadow:0 6px 20px rgba(43,37,38,0.18);
    opacity:0; transform:translateY(10px); transition:opacity .24s ease, transform .24s var(--ease);
  }
  .toast.open{ opacity:1; transform:none; }
  .toast-info{ border-left-color:var(--accent); }
  .toast-success{ border-left-color:#4A9B6E; }
  .toast-warn{ border-left-color:#D89A2E; }
  .toast-error{ border-left-color:#C9503F; }

  /* ---------- Drag 拖曳 ---------- */
  .drag-handle{
    display:inline-flex; align-items:center; justify-content:center; flex-shrink:0;
    width:22px; height:26px; padding:0; border:none; background:transparent;
    color:var(--text-secondary); cursor:grab; border-radius:6px; opacity:.55;
    transition: opacity .15s ease, background .15s ease, color .15s ease;
  }
  .drag-handle:hover{ opacity:1; background:var(--surface-alt); color:var(--accent-dark); }
  .drag-handle:focus-visible{ outline:2px solid var(--accent); outline-offset:1px; opacity:1; }
  body.drag-disabled .drag-handle{ cursor:not-allowed; opacity:.2; }
  body.drag-disabled .drag-handle:hover{ background:transparent; color:var(--text-secondary); }

  body.is-dragging{ user-select:none; cursor:grabbing; }
  body.is-dragging .drag-handle{ cursor:grabbing; }

  /* 選擇器帶上 body 是刻意的：拖曳影像會被掛到 body 底下，
     而下方「hover 碰撞區補償」會把 .mini-card 設成 position:relative，
     兩者同為單一類別選擇器時後者會勝出，導致最愛卡片的拖曳影像跟不動。
     提高一級優先權即可，不需要 !important。 */
  body > .drag-ghost{
    position:fixed; z-index:9800; pointer-events:none; margin:0;
    opacity:.92; transform:rotate(-.6deg);
    box-shadow:0 14px 34px rgba(43,37,38,0.26);
    border-radius:var(--radius-sm);
  }
  .drag-placeholder{
    border:2px dashed var(--accent); border-radius:var(--radius-sm);
    background:var(--accent-light); opacity:.5;
  }

  /* ======================================================================
     動畫曲線修正

     問題一：--ease 是帶過衝的曲線（cubic-bezier(.34,1.56,.64,1)）。
       套在 hover 上時，游標移入會有回彈感，但游標「移開」時同樣會過衝一次，
       看起來像元素先彈出去一點再跳回原位。
       → 平常（含滑出、按下）用不過衝的 ease-out，只有 :hover 才換成 --ease。

     問題二：顏色與透明度不應該有回彈。
       過衝曲線套在 color / background / opacity 上會讓顏色「衝過頭再回來」，
       在深淺對比大的主題切換時特別明顯。
       → 位移類（transform）與外觀類（顏色、透明度、陰影）分開指定曲線。

     問題三：hover 位移後，游標可能落在元素原本範圍之外而中斷 hover，
       造成反覆進出的抖動。
       → 用 ::before 補一塊涵蓋位移前後範圍的透明碰撞區。
     ====================================================================== */
  :root{
    --ease-out: cubic-bezier(.22,.61,.36,1);   /* 不過衝，用於退場 */
    --dur-out: .18s;
    --dur-color: .2s;
  }

  .btn{
    transition: transform var(--dur-out) var(--ease-out),
                background-color var(--dur-color) ease,
                color var(--dur-color) ease,
                border-color var(--dur-color) ease;
  }
  .btn:hover{
    transition-duration: var(--dur), var(--dur-color), var(--dur-color), var(--dur-color);
    transition-timing-function: var(--ease), ease, ease, ease;
  }
  .btn:active{
    transition: transform .09s var(--ease-out),
                background-color var(--dur-color) ease,
                color var(--dur-color) ease,
                border-color var(--dur-color) ease;
  }

  .btn-icon{
    transition: transform var(--dur-out) var(--ease-out),
                border-color var(--dur-color) ease,
                color var(--dur-color) ease,
                background-color var(--dur-color) ease;
    /* 讓圖示自成一個合成層。不這麼做的話，縮放後的 SVG 在 100% 顯示比例下
       會被四捨五入到整數像素，放開游標的瞬間看起來像跳了一格；
       瀏覽器縮放到 125% 時像素格變密，問題就自然消失了。 */
    will-change: transform;
    transform: translateZ(0);
    backface-visibility: hidden;
  }
  .btn-icon:hover{
    transition-duration: var(--dur), var(--dur-color), var(--dur-color), var(--dur-color);
    transition-timing-function: var(--ease), ease, ease, ease;
  }
  .btn-icon:active{ transition: transform .09s var(--ease-out); }
  .btn-icon svg{ display:block; shape-rendering:geometricPrecision; }

  .tag, .mini-card, .segmented button, .theme-switch button,
  .nav-list a, .disclosure-btn, .drag-handle{
    transition: transform var(--dur-out) var(--ease-out),
                background-color var(--dur-color) ease,
                color var(--dur-color) ease,
                border-color var(--dur-color) ease,
                box-shadow var(--dur-color) ease,
                opacity var(--dur-color) ease;
  }
  .tag:hover, .mini-card:hover, .segmented button:hover, .theme-switch button:hover,
  .nav-list a:hover, .disclosure-btn:hover, .drag-handle:hover{
    transition-duration: var(--dur), var(--dur-color), var(--dur-color),
                         var(--dur-color), var(--dur-color), var(--dur-color);
    transition-timing-function: var(--ease), ease, ease, ease, ease, ease;
  }

  input[type="range"]::-webkit-slider-thumb{ transition: transform var(--dur-out) var(--ease-out); }
  input[type="range"]:hover::-webkit-slider-thumb{ transition: transform var(--dur) var(--ease); }

  .switch-thumb{ transition: transform var(--dur) var(--ease); }
  .switch-track{ transition: background-color var(--dur-color) ease, box-shadow var(--dur-color) ease; }

  /* ---------- hover 位移的碰撞區補償 ----------
     ::before 佔住「位移前 + 位移後」的聯集範圍，
     游標在這塊區域內都持續算 hover，元素就不會因為往上跑而脫離游標。 */
  .btn, .btn-icon, .mini-card, .tag, .segmented button, .disclosure-btn{ position:relative; }
  /* 拖曳影像不需要碰撞區補償，也不該被上面那條改掉定位方式 */
  .drag-ghost::before{ display:none; }
  .btn::before, .btn-icon::before, .mini-card::before,
  .tag::before, .segmented button::before, .disclosure-btn::before{
    content:""; position:absolute; z-index:-1;
    left:-4px; right:-4px; top:-6px; bottom:-6px;
  }
  .mini-card::before{ left:-6px; right:-6px; top:-8px; bottom:-10px; }

  /* ---------- 分頁面板切換動畫 ---------- */
  .tab-panel.active{ animation: tabPanelIn .3s var(--ease-out); }
  @keyframes tabPanelIn{
    from{ opacity:0; transform:translateY(10px); }
    to{ opacity:1; transform:none; }
  }
