    /* ── 「回報問題」的底部小卡（93-report.js／index.html #report-sheet）──────────
       全站第一個「浮在畫面上」的表單。founder 2026-08-25 從三個版型裡選了底部小卡，
       並把說明文字整段拿掉：**「回報問題」本身已經是一個額外岔路，越不像表單越好**。
       所以這裡只有三樣東西：標題、輸入框、整寬送出鈕（＋一個 ×）。

       ⚠️ 這支的 <link> 現在是**最後一支**：原本排在它後面的 80-nav.css（雙分頁導航）
          在「旅程當首頁」那批整支退場了。要新增樣式排在這之後時先想一次覆寫關係——
          順序就是行為（acceptance X6d 釘住最後一支是誰，見 index.html）。

       ── 鍵盤：直接讀 --chat-vh／--chat-offset，**不掛在 .screen 身上**（2026-08-25 走查修）──
       第一版是「開啟時把小卡搬進 .screen.active」（抄複製選單那招）。**那是錯的**，桌機走查
       當場現形：那一層的高度與位移是跟著鍵盤**即時被改寫**的（30-ui.js syncChatViewportHeight
       每幀寫 --chat-vh／--chat-offset），小卡與遮罩掛在上面 ＝ 掛在一個會動的東西上——
       宿主的框一改，**整片畫面連遮罩一起位移**。手機上那次改寫剛好就是鍵盤升起、看起來對；
       桌機沒有鍵盤，同一次改寫就變成沒來由的移入。
       ⚠️ 複製選單**必須**搬進 .screen 是它自己的理由（要讓某一則泡泡疊到遮罩之上，
          那是 stacking context 的需求）。這張卡沒有那個需求，**別照抄那招**。

       現在的做法：小卡留在 body 層，自己把上緣對到可視視窗的**底**——
       `top: calc(var(--chat-offset) + var(--chat-vh))`。那兩個變數掛在 <html> 上，
       任何一層都讀得到，鍵盤一動它們就更新，小卡自然跟著走。
       關閉態 `translateY(0)` ＝ 整張躺在可視視窗底下（看不見）；開啟態 `translateY(-100%)`
       ＝ 剛好升到底邊上。**進場與離場是同一條 transform transition**，不必兩套。
       ⚠️ 仍然不准自己去讀 `visualViewport`：那兩個變數就是唯一真源（26_R9 有斷言）。 */

    /* ══ 想調手感就改這一組 ═══════════════════════════════════════════════════
       ⚠️ --report-anim 會被 JS 讀（93-report.js 要知道離場動畫跑多久才能 display:none），
          **必須留單位**（`s` 或 `ms`），別寫成裸數字。 */
    :root {
      --report-anim: 0.24s;          /* 滑上／滑下與遮罩淡入的時間 */
      --report-dim: var(--copy-dim); /* 背景暗下來的程度。預設跟著長按複製的遮罩走：
                                        同一個 App 裡「背景暗下來」只該有一種深淺。
                                        真要讓這張卡自己一個值，就把 var() 換成數字。 */
      --report-note-min: 3.5rem;     /* 輸入框初始高度（56px）。比 #skipform-note 的 4.25rem
                                        矮一階（founder 2026-08-25）：這張卡要小、要不像表單。 */
    }

    /* 蓋住**可視視窗**，不是整份文件：鍵盤升起時遮罩的下緣要跟著縮到鍵盤上緣，
       否則會有一截暗色壓在鍵盤底下。用同兩個變數，不另外算。 */
    .report-backdrop {
      position: fixed; left: 0; right: 0; z-index: 40;
      top: var(--chat-offset, 0px); height: var(--chat-vh, 100dvh);
      /* 墨色的透明版，不是純黑——純黑在暖紙底上會發灰（同 .copy-backdrop） */
      background: rgba(44, 40, 37, var(--report-dim));
      opacity: 0; transition: opacity var(--report-anim) ease;
      /* 背後的對話在卡片開著時不該還能捲：遮罩自己吃掉手勢就夠，不必去鎖 scroll port。
         桌機的滾輪落在遮罩上，往上找不到可捲的祖先（chat-fullscreen 把 html/body 都
         overflow:hidden 了），所以也捲不動。 */
      touch-action: none;
    }
    .report-backdrop[hidden] { display: none; }
    .report-backdrop.is-open { opacity: 1; }

    /* 圓角只有上緣兩顆：它是從畫面下緣長出來的一張紙，下緣不存在於畫面裡。
       用 --radius(14px) 那一級：它是「卡片／可選擇的表面」，不是控件（⑤ 兩級圓角）。
       框線：主體要界線（visual-foundation ⑤ 第 5 條），所以給 1px --border，不給底色差。 */
    .report-sheet {
      position: fixed; left: 0; right: 0; z-index: 50;
      /* 上緣 ＝ 可視視窗的底。整張因此躺在畫面外，靠 transform 升上來（見檔頭）。 */
      top: calc(var(--chat-offset, 0px) + var(--chat-vh, 100dvh));
      max-width: calc(var(--content-w) - 2.5rem); margin: 0 auto;  /* 桌機與輸入框同寬、置中 */
      background: var(--bg);
      border: 1px solid var(--border); border-bottom: none;
      border-radius: var(--radius) var(--radius) 0 0;
      padding: 1.125rem var(--body-pad-x) calc(1.5rem + env(safe-area-inset-bottom, 0px));
      display: flex; flex-direction: column; gap: 1rem;
      /* 防呆上限，不是版面目標：內容自然高度約可視高的 25%（founder 要的是 40–45% 以內）。
         寫成「可視高減 3rem」而不是固定百分比，是因為鍵盤開著時可視高只剩 350–420px，
         固定 45% 會把輸入框和送出鈕壓進內部捲動——那正是這條上限要防的事的相反。
         ⚠️ 這裡不能用 100%：本元素的包含塊是初始包含塊（layout viewport），
         鍵盤開著時它不會縮，只有 --chat-vh 會。 */
      max-height: calc(var(--chat-vh, 100dvh) - 3rem);
      overflow-y: auto; overscroll-behavior: contain;
      transform: translateY(0); transition: transform var(--report-anim) ease;
    }
    .report-sheet[hidden] { display: none; }
    .report-sheet.is-open { transform: translateY(-100%); }

    .report-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; }
    /* 17px/600：它是一張卡的標題，不是一頁的 h1（h1 是 20px）。 */
    .report-title { font-size: var(--font-primary); font-weight: 600; line-height: 1.5; }
    /* 44px 熱區、20px 圖示：手機上只點得到 20px 的叉是常見的挫折來源（同 .skipform-check 那條）。
       負 margin 讓 44px 的框不把標題往下推、圖示仍與標題對齊。 */
    .report-close {
      background: none; border: none; padding: 0; cursor: pointer;
      width: 44px; height: 44px; margin: -0.625rem -0.75rem 0 0;
      flex-shrink: 0; display: flex; align-items: center; justify-content: center;
      color: var(--text-muted);
    }
    .report-close:hover { background: none; color: var(--text); }
    .report-close svg {
      width: 20px; height: 20px;
      fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round;
    }

    /* 寫法比照 #skipform-note（20-screens.css）——**不要另外寫一支 autogrow**：
       resize:none 蓋掉全域的 textarea{resize:vertical}（高度由 fitTextarea 管）；
       overflow-y:hidden 超過上限時由 fitTextarea 自己改成 auto；
       line-height 1.5 明寫，否則 UA 的 normal 會蓋掉 body 的 1.75、高度換算得靠實測。
       max-height 8rem ≈ 4 行才進入內部捲動；實際上限仍由 fitTextarea 的「可視高 35%」動態夾。 */
    #report-note {
      margin-bottom: 0;
      border-radius: var(--radius-sm);
      padding: 0.8rem 0.9rem;
      line-height: 1.5;
      min-height: var(--report-note-min); max-height: 8rem;
      resize: none; overflow-y: hidden;
    }
    /* 整寬（founder 定）＋ 48px 高：拇指在畫面底部，這顆是唯一的主要動作。
       不放第二顆取消鈕——× 已經是出口。 */
    .report-submit { width: 100%; min-height: 48px; font-size: 0.95rem; font-weight: 500; }
    /* 沒有錯誤時不佔位（同 #err-skipform）：這張卡的高度本來就要小。 */
    #err-report:empty { display: none; min-height: 0; margin-top: 0; }

    /* 會動的東西一律收在同一個開關底下（同 40-chat.css 末段那組）。 */
    @media (prefers-reduced-motion: reduce) {
      .report-backdrop, .report-sheet { transition: none; }
    }
