/* gridview.css — 全站清單的共用版型（2026-08-06）
   =========================================================================
   一份 DOM、兩種版型：桌機＝多欄對齊表格，手機＝60px 兩行列。
   純 CSS 切換，**不用 JS matchMedia** —— 轉螢幕要能自動重算。

   為什麼不是「桌機 <table> ＋ 手機卡片」兩套 HTML（2026-07-27 的舊做法）：
   兩套字串要各維護一次，改了桌機忘了改手機是常態；而且手機那套沒有表頭，
   使用者看不出每個欄位是什麼 —— 這正是這次要修的。

   ⚠ sticky 表頭能黏住的前提：
   1. `.fill-scroll` 是唯一捲動層（css/layout.css）。`.gv` 與它之間
      **不得再有 overflow:auto/hidden 的層** —— 多一層捲動容器，
      表頭會黏在那一層上，看起來就是「永遠不動」。
   2. `.fill-scroll` 上不要指定 display（見 CLAUDE.md）。
   ========================================================================= */

/* --gv-cols：欄寬，各頁自己覆寫（桌機）
   --gv-act-m：手機動作欄寬度，預設 auto（跟著按鈕數自動縮放） */
.gv{--gv-cols:48px 1fr 96px 1fr 120px;--gv-act-m:auto}

/* ── 表頭 ── */
.gv-head{
  position:sticky;top:0;z-index:5;
  display:grid;grid-template-columns:var(--gv-cols);gap:0 8px;align-items:center;
  padding:8px 12px;
  background:var(--gray-50);
  border-bottom:1px solid var(--gray-200);
  font-size:15px;font-weight:600;color:var(--gray-600);
  white-space:nowrap
}
.gv-h{overflow:hidden;text-overflow:ellipsis}
.gv-h.is-sortable{cursor:pointer;user-select:none}
.gv-h.is-sortable:hover{color:var(--primary-dark)}
.gv-h.is-sorted{color:var(--primary-dark)}
.gv-sort-arrow{font-size:11px;margin-left:2px}
.gv-h-actions{text-align:center}
/* 表頭右側的摘要（「共 N 筆」等）：桌機不佔位，手機才顯示 */
.gv-head-summary{display:none}

/* ── 資料列 ── */
.gv-row{
  display:grid;grid-template-columns:var(--gv-cols);gap:0 8px;align-items:center;
  padding:8px 12px;
  border-bottom:1px solid var(--gray-100);
  cursor:pointer
}
.gv-row:hover{background:var(--gray-50)}
.gv-row:last-child{border-bottom:0}
.gv-c{min-width:0;overflow:hidden;text-overflow:ellipsis}
.gv-idx{color:var(--gray-400);font-size:15px}
.gv-name{min-width:0;font-weight:500;color:var(--gray-800);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.gv-actions{display:flex;gap:4px;justify-content:center;align-items:center}
/* 動作欄的 icon 鈕：桌機要壓得比 .btn-sm 更小，否則三顆就撐破欄寬
   （tests/26 的「容器內橫滑」會抓到）。手機在下面的 @media 放大成 44px 觸控目標。
   ⚠ 用 .gv-icon 單一 class 而不是 `.gv-actions .btn` 後代選擇器 ——
     後者的權重會連帶壓過報名模式的 .mm-enroll-btn，把它的 44px 觸控高度也吃掉。 */
.gv-icon{padding:4px 8px;min-height:0;gap:0}
.gv-icon svg{width:14px;height:14px}

/* .gv-meta 是「手機要併成第二行」的那幾欄的容器。
   桌機用 display:contents 把它拆掉，子元素直接變成 .gv-row 的 grid item，
   於是欄位照 --gv-cols 對齊，跟真正的表格一模一樣。 */
.gv-meta{display:contents}

.gv-empty{padding:24px 14px;text-align:center;color:var(--gray-400);font-size:15px}

/* 同一格裡「桌機顯示完整、手機只顯示摘要」的兩份內容。
   例：修班歷程桌機列出全部班程，手機只列最新一筆（點進去看得到完整歷程）。 */
.gv-only-m{display:none}

/* ── 專頁連結（survey.html）的呈現，全站共用（2026-08-07 使用者指定）──
   專頁之所以好讀的三件事：
   1. 一塊白底圓角表格框住整份名單，不是一張張分離的卡片
      （分離卡片每張都有外框＋間距，視覺噪音比內容還多）
   2. 欄位標題做成金褐底白字的區塊帶並且黏頂（＝專頁的 table.stk tr.sec th）
   3. 姓名左對齊粗體
   用法：清單外層加 .gv-list，表頭那條 .gv-cardhead 再加 .gv-band。
   ⚠ 這組原本寫在 js/pages/report.js 的 RP_STYLE 裡，2026-08-07 搬來共用 ——
     公壇報表與班別出席總表都要同一個樣子，別再各留一份。 */
.gv-list{background:#fff;border:1px solid var(--gray-200);border-radius:12px;overflow:hidden}
.gv-list>*{border-bottom:1px solid var(--gray-200);border-left:0;border-right:0;
  border-top:0;border-radius:0;margin:0!important;background:#fff}
.gv-list>*:last-child{border-bottom:0}

/* ── 資料表：.gv-lhead（金褐 sticky 表頭）+ .gv-list + .gv-lrow（2026-08-08）──
   報表各頁的「純資料表」共用這一組，取代各頁自己的 .ta-card / .lo-card /
   .bm-card / .notify-item / .course-card（實測列高 107~1027px，一屏只看得到
   1~2 筆）。列高硬指標 ≤52px —— 使用者指定資料要佔 3/4 版面。

   欄寬由各頁在容器上設 `--gv-list-cols`，表頭與資料列吃同一個變數才會對齊；
   少了這一條就會變成「表頭寫著壇名、下面那欄其實是姓名」。

   ⚠ 表頭桌機手機都顯示（不要沿用 .gv-cardhead 的手機專用規則）——
     班程日報表 2026-08-07 換版時就漏了這件事，桌機的列沒有表頭。 */
.gv-lhead{
  position:sticky;top:0;z-index:5;
  display:grid;grid-template-columns:var(--gv-list-cols,1fr);gap:0 8px;align-items:center;
  padding:8px 10px;
  background:var(--primary);color:#fff;
  font-size:15px;font-weight:600;white-space:nowrap;
  border-radius:12px 12px 0 0
}
.gv-lhead>*{min-width:0;overflow:hidden;text-overflow:ellipsis}
/* 表頭與表格要接得起來：中間不留縫、圓角只留下面兩個 */
.gv-lhead+.gv-list{border-top:0;border-radius:0 0 12px 12px}
.gv-lrow{
  display:grid;grid-template-columns:var(--gv-list-cols,1fr);gap:0 8px;align-items:center;
  padding:6px 10px;min-height:48px;font-size:15px
}
/* ⚠ 每格都要 min-width:0 + hidden：少了它某一欄字一長就撐破整列變成橫滑
   （report.js 的 .rp-d-name 實測踩過，名字看不全可以點進去，橫滑是整頁壞掉） */
.gv-lrow>*{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gv-l-name{font-size:17px;font-weight:700;color:var(--gray-800)}
.gv-l-num{text-align:center;font-variant-numeric:tabular-nums}
.gv-l-muted{color:var(--gray-500)}
/* 合計列：跟資料同一張表、同樣欄位對齊，不再另外做一塊統計卡 */
.gv-lfoot{background:var(--gray-50);font-weight:700}
/* 動作欄不能截斷（按鈕會被切掉），自己撐開 */
.gv-l-act{display:flex;gap:4px;justify-content:center;align-items:center;overflow:visible}
.gv-l-act .btn{min-height:34px;padding:4px 8px}

.gv-lsec{margin-top:10px}

@media (max-width:768px){
  .gv-lhead{padding:9px 8px}
  .gv-lrow{padding:5px 8px;min-height:52px}
  .gv-l-name{font-size:19px}
  .gv-l-act .btn{min-width:44px;min-height:44px;padding:0;justify-content:center}
}


/* ── 手機專用的清單表頭（.gv-cardhead）──
   報表類的一列天生有三行資訊（姓名+出席率／班程／本月次數與出席請假缺席），
   壓不進 .gv 的兩行版型，所以那些頁維持既有卡片、只在上面補一條 sticky 表頭。
   桌機不需要（<table> 的 <thead> 本來就 sticky，見 css/pages.css）。 */
/* ⚠ 只有 display 由媒體查詢控制，**外觀一律定義在這裡**。
   2026-08-09 踩過：把外觀寫在 @media(max-width:768px) 裡，
   等到「桌機也改用同一份版型」時，桌機拿到的是完全沒有樣式的裸文字
   （班別出席總表在 1440px 變成「班程 1班員 67出席 62/67未到 3」黏成一行）。
   要在所有寬度都顯示的頁面，在元素上加 .is-always。 */
.gv-cardhead{
  display:none;align-items:center;gap:8px;
  position:sticky;top:0;z-index:5;
  margin:0 0 6px;padding:6px 10px;
  background:var(--gray-50);
  border-bottom:1px solid var(--gray-200);
  font-size:15px;font-weight:600;color:var(--gray-600);
  white-space:nowrap
}
.gv-cardhead.is-always{display:flex}
.gv-ch-main{flex:0 0 auto}
.gv-ch-sub{flex:1 1 auto;min-width:0;text-align:right;font-weight:400;color:var(--gray-400);overflow:hidden}
.gv-ch-end{flex:0 0 auto}
/* 搜尋框與表頭一起釘住：捲到第 30 個人時，改搜尋條件不該還要先捲回最上面 */
.gv-stickyhead{position:sticky;top:0;z-index:6;background:var(--gray-50);margin:0 0 6px;padding-top:2px}
.gv-stickyhead .gv-cardhead{margin-bottom:0}
/* 金褐區塊帶（專頁版型）—— 同樣不放在媒體查詢裡 */
.gv-band{
  background:var(--primary)!important;color:#fff!important;
  border-bottom:0!important;border-radius:12px 12px 0 0;
  font-weight:600;padding:11px 14px!important
}
.gv-band .gv-ch-sub,.gv-band .gv-ch-end{color:rgba(255,255,255,.85)!important;font-weight:400}
.gv-band+.gv-list,
.gv-stickyhead:has(.gv-band)+.gv-list{border-top:0;border-radius:0 0 12px 12px}
.gv-stickyhead:has(.gv-band){margin-bottom:0}

/* =========================== 手機 =========================== */
@media (max-width:768px){
  /* 表頭改 flex 一列：姓名（左）｜次要欄位標題或摘要（中，靠右）｜操作（右）。
     不沿用 grid-template-areas —— 那會讓表頭跟資料列一樣變成兩行。 */
  .gv-head{
    display:flex;align-items:center;gap:8px;
    padding:6px 6px 6px 10px;
    font-size:15px
  }
  .gv-head .gv-h-idx{display:none}
  .gv-head .gv-h-name{flex:0 0 auto}
  .gv-head .gv-meta{
    display:flex;flex:1 1 auto;min-width:0;
    justify-content:flex-end;gap:6px;
    font-weight:400;color:var(--gray-400);overflow:hidden
  }
  /* 欄位標題之間用「/」分隔，讀起來像「佛堂 / 班程」 */
  .gv-head .gv-meta>.gv-h+.gv-h::before{content:"/ ";color:var(--gray-300)}
  .gv-head .gv-h-actions{flex:0 0 var(--gv-act-m)}
  .gv-head-summary{display:inline;font-weight:400;color:var(--gray-400)}

  /* ── 單列版型 .gv--oneline（2026-08-06 使用者指定）──
     一列＝姓名 - 壇別 - 班名 - [主要動作]。修改／刪除移進詳細頁，
     省下的兩顆 44px icon 正好讓姓名擠得進同一行。
     ⚠ 2026-08-03 曾因「壇名·姓名·班程·三顆動作」擠在一行而退回兩行版
       （姓名被推出畫面、中文被硬斷成「今年道／親51」）。這次能成立的前提
       就是動作只剩一顆 —— 之後若要在列上加回按鈕，先量姓名還放不放得下。 */
  .gv--oneline .gv-row{
    grid-template-columns:auto minmax(0,1fr) var(--gv-act-m);
    grid-template-areas:"name meta actions";
    align-items:center;gap:0 8px;
    padding:4px 6px 4px 10px;min-height:52px
  }
  .gv--oneline .gv-name{
    grid-area:name;font-size:19px;font-weight:700;line-height:1.25;
    white-space:nowrap;overflow:visible;flex:0 0 auto
  }
  .gv--oneline .gv-meta{
    grid-area:meta;display:flex;align-items:center;gap:6px;min-width:0;
    font-size:15px;line-height:1.3;white-space:nowrap;overflow:hidden
  }
  /* 班名是這一行裡最先該讓位的：壇別只有兩個字，班名可以截斷（點進去看得到全名） */
  .gv--oneline .gv-meta>.gv-c-grow{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}
  .gv--oneline .gv-actions{grid-area:actions}
  .gv--oneline .gv-head{padding:6px 6px 6px 10px}

  /* 資料列：姓名獨佔第一行、次要資訊第二行、動作鈕靠右跨兩行。
     ⚠ 高度 60px 是刻意的（2026-08-03 校準）：姓名 19px 不斷行不截斷，
       一頁還留得住 6~8 人。改這裡之前先讀 CLAUDE.md 的 UI 慣例。 */
  .gv-row{
    grid-template-columns:minmax(0,1fr) var(--gv-act-m);
    grid-template-areas:"name actions" "meta actions";
    gap:1px 8px;
    padding:5px 6px 5px 10px;
    border:1px solid var(--gray-200);border-radius:var(--radius-sm);
    background:#fff
  }
  .gv-row+.gv-row{margin-top:6px}
  .gv-row:last-child{border-bottom:1px solid var(--gray-200)}
  /* 姓名是「找人」時唯一真正被讀的字：不斷行、不截斷、不讓位 */
  .gv-name{grid-area:name;font-size:19px;font-weight:700;line-height:1.25;
    color:var(--gray-800);white-space:nowrap;overflow:visible;text-overflow:clip}
  /* 第二行是次要資訊，空間不足時由它截斷（點進去看得到完整內容） */
  .gv-meta{
    grid-area:meta;display:flex;align-items:center;gap:6px;min-width:0;
    font-size:15px;line-height:1.3;white-space:nowrap;overflow:hidden
  }
  .gv-meta>.gv-c{flex:0 0 auto}
  .gv-meta>.gv-c-grow{flex:1 1 auto;min-width:0}
  /* ⚠ grid-area 不能省：少了它動作鈕會被自動放進第一列，
     44px 的觸控高度直接把姓名那列撐成 44px，整張卡從 60px 變 86px。 */
  .gv-actions{grid-area:actions;gap:2px}
  /* 桌機才有的欄位（序號等）手機收掉 */
  .gv-row .gv-idx,.gv-hide-m{display:none}
  .gv-only-m{display:inline}

  /* ⚠ 它自己不能是捲動容器，也要直接放在 .fill-scroll 底下，
     否則 sticky 會黏錯層（跟 .gv-head 同一個道理）。外觀定義在檔案上方。 */
  .gv-cardhead{display:flex}

  .gv-icon{min-width:44px;min-height:44px;padding:0;justify-content:center;border-color:transparent}
  .gv-icon svg{width:16px;height:16px}
  .gv-icon-danger{color:var(--danger)}
}

/* ==========================================================================
   工具列溢出選單（.tb-*）
   桌機：次要動作照舊攤在工具列上。
   手機：收進一顆「⋯」，點開變底部抽屜。
   ⚠ DOM 只有一份，靠 CSS 切換 —— 用 JS 判斷螢幕寬會在轉螢幕時失效。
   ========================================================================== */
.tb-overflow,.tb-filter{display:inline-flex;align-items:center;gap:8px;position:relative}
.tb-overflow-btn,.tb-filter-btn{display:none}
.tb-overflow-items,.tb-filter-items{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tb-overflow-backdrop{display:none}
/* 桌機：篩選欄位留在工具列原位，外觀與改版前完全一樣 */
.tb-filter-items{display:contents}
.tb-f-field{display:contents}
.tb-f-field--m{display:none!important}
.tb-f-field>label,.tb-f-foot{display:none}

@media (max-width:768px){
  .tb-overflow-btn,.tb-filter-btn{
    display:inline-flex;align-items:center;justify-content:center;
    min-width:44px;min-height:44px;padding:0;flex:0 0 auto
  }
  /* 有篩選中就把按鈕點亮並顯示數量 —— 收起來之後看不出「現在有沒有篩」是最容易
     出事的地方（使用者會以為資料不見了） */
  .tb-filter.has-filter .tb-filter-btn{border-color:var(--primary);color:var(--primary-dark)}
  .tb-filter-badge:empty{display:none}
  /* ⚠ 字級不得 <15px（全站鐵則，tests/27 會抓到）—— 徽章也是要讀的字 */
  .tb-filter-badge{
    position:absolute;top:0;right:0;min-width:20px;height:20px;padding:0 4px;
    border-radius:10px;background:var(--primary);color:#fff;
    font-size:15px;line-height:20px;text-align:center;font-weight:700
  }
  .tb-overflow-items,.tb-filter-items{display:none}
  /* 抽屜裡一列一個欄位：左邊標籤、右邊控制項 */
  .tb-filter-items.open .tb-f-field--m{display:flex!important}
  .tb-filter-items.open .tb-f-field{
    display:flex;align-items:center;gap:10px;width:100%;padding:6px 20px;min-height:52px}
  .tb-filter-items.open .tb-f-field>label{display:block;flex:0 0 64px;font-size:15px;color:var(--gray-500)}
  .tb-filter-items.open .tb-f-field>:not(label){flex:1 1 auto;min-width:0;width:auto;max-width:none}
  .tb-filter-items.open .tb-f-foot{
    display:flex;gap:8px;padding:8px 20px 0;border-top:1px solid var(--gray-100)}
  .tb-filter-items.open .tb-f-foot .btn{flex:1 1 0;min-height:48px}
  .tb-overflow-items.open,.tb-filter-items.open{
    display:flex;flex-direction:column;align-items:stretch;gap:0;flex-wrap:nowrap;
    position:fixed;left:0;right:0;bottom:0;z-index:200;
    background:#fff;
    border-radius:var(--radius-sheet) var(--radius-sheet) 0 0;
    padding:8px 0 calc(8px + env(safe-area-inset-bottom));
    box-shadow:0 -6px 28px rgba(60,50,35,.24);
    animation:tbSheetUp .18s ease
  }
  .tb-overflow-items.open>*{
    width:100%;justify-content:flex-start;
    min-height:52px;
    border:0;border-radius:0;
    background:transparent;color:var(--gray-700);
    font-size:16px;padding:0 20px
  }
  .tb-overflow-items.open>*+*{border-top:1px solid var(--gray-100)}
  .tb-overflow-items.open>*:active{background:var(--primary-light)}
  /* 抽屜裡的按鈕文字一律顯示（工具列上可能被 icon 化藏起來了） */
  .tb-overflow-items.open .btn-label{display:inline!important}
  .tb-overflow-backdrop.open{
    display:block;position:fixed;inset:0;z-index:199;
    background:rgba(45,38,28,.45)
  }
}

/* 模式切換的手機版下拉（見 js/utils/overflow-menu.js 的 mirrorToggleToSelect）。
   ⚠ 只藏「有對應 select 的」那個 toggle —— 直接寫 .report-toggle{display:none}
     會把還沒接上的頁面切換鈕整個弄不見。 */
.rt-select{display:none}
@media (max-width:768px){
  .rt-select{
    display:inline-block;flex:0 0 auto;max-width:100px;
    min-height:44px;padding:8px 22px 8px 8px;
    border:1px solid var(--gray-200);border-radius:6px;background:#fff;
    font-size:16px;font-family:inherit
  }
  .rt-select+.report-toggle{display:none!important}
}

/* ── 報表工具列：手機固定一列（2026-08-08 使用者：資料要佔 3/4 版面）──
   [主控制項 吃滿剩餘寬][篩選 ②][⋯]，每顆 ≥44px，不換行也不橫滑。
   實測改版前：今日缺席 3 列、班別總表 138px、公壇出席 158px。 */
@media (max-width:768px){
  .tb-onerow{
    display:flex!important;flex-wrap:nowrap!important;align-items:center;gap:6px;
    overflow:visible;padding-bottom:0
  }
  /* 固定尺寸的：導航鈕、篩選、⋯ */
  .tb-onerow>.btn,
  .tb-onerow>.tb-filter,
  .tb-onerow>.tb-overflow,
  .tb-onerow>.page-info-btn{flex:0 0 auto}
  .tb-onerow>.btn{min-width:44px;padding:8px;justify-content:center}
  .tb-onerow>.btn .btn-label,
  .tb-onerow>.btn .nav-label{display:none}
  /* 吃滿剩餘寬的：日期／班程／月份選單（含只是包一層的 span/div 容器） */
  .tb-onerow>select,
  .tb-onerow>input,
  .tb-onerow>.class-dropdown,
  .tb-onerow>.tb-grow,
  .tb-onerow>.multi-select-wrap{flex:1 1 60px;min-width:0!important;width:auto!important;max-width:none!important}
  .tb-onerow>.tb-grow>select,
  .tb-onerow>.tb-grow>input{width:100%!important;min-width:0!important;max-width:none!important;min-height:44px}
  /* 提示文字（第 3 / 12 課日）手機不放 —— 一列就這麼寬，日期本身比它重要。
     ⚠ 用 .tb-hint 而不是 `>span`：報表頁的 #reportClassControl 也是 span，
       用標籤選會把班程下拉整個弄不見。 */
  .tb-onerow>.tb-hint{display:none}

  /* 三組主控制項的頁（公壇出席、點名簽到）允許換行成兩列。
     ⚠ 這不是放寬標準 —— 硬塞一列只能犧牲 44px 觸控或製造橫滑，兩條都是鐵則。
       .tb-daterow 把「‹ 日期 ›」綁成一個 flex item，整組換到第二列，
       不會出現「‹ 在第一列、日期在第二列」這種散開的排法。 */
  .tb-onerow.tb-wrap{flex-wrap:wrap!important}
  /* ⚠ 一定要寫成 `.tb-onerow>.tb-daterow`：responsive.css 有一條
     `.report-header>div>*{flex:0 1 auto}`，權重比單一個 .tb-daterow 高，
     只寫 class 名的話 flex-basis 會被壓回 auto，整組就不換行 ——
     結果是「佛堂鈕和日期擠在同一列互相重疊」（2026-08-08 實測）。 */
  /* order:9 把日期那一組排到最後 —— 不然它 flex-basis:100% 會把後面的「⋯」
     擠到第三列（實測 154px）。第一列 [佛堂][模式][⋯]、第二列 [‹ 日期 ›]。 */
  .tb-onerow>.tb-daterow{display:flex;align-items:center;gap:6px;order:9;
    flex:1 1 100%;min-width:0;max-width:100%}
  .tb-daterow>.btn{flex:0 0 40px;min-width:40px;padding:0;justify-content:center}
  .tb-daterow>.btn .btn-label,.tb-daterow>.btn .nav-label{display:none}
  .tb-daterow>select,.tb-daterow>input{flex:1 1 60px;min-width:0!important;width:auto!important;max-width:none!important}
  .tb-daterow>.tb-hint{display:none}
  /* 模式下拉是固定寬的，不要跟著長 */
  .tb-onerow>.rt-select{flex:0 0 auto}
  /* 多選鈕預設 min-width:180px，格子被壓窄時會整顆溢出去疊到隔壁 */
  .tb-onerow>.multi-select-wrap{flex:1 1 140px}
  .tb-onerow .multi-select-btn{min-width:0;width:100%}
}

@keyframes tbSheetUp{from{transform:translateY(100%)}to{transform:translateY(0)}}

@media(prefers-reduced-motion:reduce){
  .tb-overflow-items.open{animation:none}
}
