

/* ==== features: static/features/link.css ==== */
/* link：連結卡（對應 LinkPreviewCard）與播放面板（對應 LinkPlayerView）。
 * 這組沒有自己的頁面，樣式給 compose／stash 用。只用 var(--…) token，深淺色都由 token 決定。
 *
 * 版面三種（LinkLayout）：.is-large 圖上文下、.is-compact 左小方圖右文字、.is-plain 不放圖。
 * 圓角走 --link-radius：放進分組清單（框裡有框）時由外層覆寫成更小的值，
 * 精簡版面的小方圖跟著縮（max(4px, radius − 4px)），否則縮圖比卡片還圓。 */

.link-card {
  --link-radius: var(--radius);
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-width: 0;
  overflow: hidden;
  border-radius: var(--link-radius);
  background: var(--sunk);              /* iOS 的 appTertiaryFill：卡自己站在灰底上 */
  color: var(--ink);
  text-align: left;
}
.link-card.is-compact {
  flex-direction: row;
  align-items: flex-start;
  gap: 12px;
  padding: 10px;
}
.link-card.is-compact:not(:has(.link-thumb)) { padding: 12px; }
.link-card.is-plain {
  flex-direction: row;
  align-items: flex-start;
  gap: 10px;
}

/* ---------- 縮圖 ---------- */
/* 大圖：盒子的形狀由圖自己決定，高度不寫死——寬度由版面決定、高度照比例算（JS 寫 aspect-ratio）。
   精簡：固定 64 正方，文字才對得齊。 */
.link-thumb {
  position: relative;
  display: block;
  width: 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  background: var(--sunk);
  color: inherit;
  font: inherit;
}
button.link-thumb { cursor: pointer; }
.link-card.is-large .link-thumb { aspect-ratio: 16 / 9; }
.link-card.is-compact .link-thumb {
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: max(4px, calc(var(--link-radius) - 4px));
}
/* 兩條路都要 fill：盒子的比例已經夾過了，圖與盒子不一定同比例，差額用裁的而不是留白——
   留白會在卡片裡露出底色，看起來像沒載完。 */
.link-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 播放記號。疊在圖上，所以底要用材質（--bar-glass ＋ 模糊）——底下那張圖的亮度不可知。
   .is-live（真的按得動）才是實心的播放鍵。 */
.link-badge {
  position: absolute;
  left: 10px;
  bottom: 10px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--bar-glass);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--ink);
}
.link-badge .ms { --ms-size: 14px; --ms-opsz: 20; }
.link-card.is-compact .link-badge { left: 4px; bottom: 4px; width: 24px; height: 24px; }
.link-card.is-compact .link-badge .ms { --ms-size: 11px; --ms-opsz: 20; }

/* 純文字版面：代表來源的符號（按「那是什麼東西」給，不是按品牌給）。 */
.link-symbol {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  margin: 12px 0 0 12px;
  color: var(--ink-3);
}
.link-symbol .ms { --ms-size: 22px; --ms-opsz: 24; }

/* ---------- 文字 ---------- */
.link-info {
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  min-width: 0;
  min-height: 44px;                     /* 2.5.5：可點目標不得小於 44 */
  padding: 10px 12px;
  color: inherit;
  text-decoration: none;
}
.link-card.is-compact .link-info { min-height: 64px; padding: 0 4px 0 0; }
.link-card.is-compact:not(:has(.link-thumb)) .link-info { min-height: 44px; }
.link-card.is-plain .link-info { padding: 12px 12px 12px 0; }
.link-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--link-lines, 3);
  overflow: hidden;
  overflow-wrap: anywhere;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
}
.link-summary {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
  color: var(--ink-3);
  font-size: 13px;
  line-height: 1.4;
}
.link-byline {
  overflow: hidden;
  color: var(--ink-3);
  font-size: 13px;
  line-height: 1.4;
  white-space: nowrap;
  text-overflow: ellipsis;
}
a.link-info:hover .link-title { text-decoration: underline; }

/* ---------- 播放面板 ---------- */
/* 底色寫死黑：那是**內容的底**，不是介面的底，不隨深淺色翻面（影片本來就在黑底上播）。
   所以它是這裡自己的 token，不掛在 :root 的主題色上。 */
.link-player {
  --link-player-bg: #000;
  position: relative;
  width: 100%;
  min-width: 0;
  overflow: hidden;
  background: var(--link-player-bg);
}
.link-player.is-fill { height: 70vh; }
.link-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}
.link-sheet .ui-sheet-body { padding: 0; }
.link-sheet .link-player-body {
  --link-player-bg: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--link-player-bg);
}
.link-sheet .link-player-body:has(.link-empty) { background: transparent; }
.link-open { color: var(--ink); text-decoration: none; }

/* 走不到的空狀態（按鈕只在 playable 時出現）：面板單獨被用時不會是一片空白。 */
.link-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 32px var(--pad);
  color: var(--ink-2);
  font-size: 14px;
  text-align: center;
}
.link-empty strong { color: var(--ink); font-size: 16px; }
.link-empty-icon .ms { --ms-size: 36px; --ms-opsz: 40; color: var(--ink-3); }


/* ==== features: static/features/compose.css ==== */
/* compose：建立頁（作成）。對照 iOS 的 ComposeEditorView——整頁是一個 Form，
 * 這裡沿用 osuha.ui 的 .grouped-* 度量（一組一張卡、列高 48、左右內距 12），
 * 自己的 class 一律 .compose-* 前綴。
 * 顏色只用 var(--…)，深色是預設；可點目標一律 ≥ 44。 */

.compose {
  padding-bottom: 12px;
  /* 這兩個值刻意不跟著主題走，所以收成自己的 token 而不是直接寫在下面。
     刪除鈕坐在**照片上**，不是坐在某一層介面底色上——照片是亮是暗由使用者
     決定，深色／淺色主題管不到它。iOS 的作法是 `.foregroundStyle(.white,
     .black.opacity(0.5))`：白色的叉、半透明黑的圓底，兩個都是絕對值。
     換成 var(--ink)／var(--surface) 的話，淺色主題下會變成「深色的叉配
     淺色的底」，壓在一張淺色照片上就整個消失。 */
  --compose-scrim: rgba(0, 0, 0, .55);
  --compose-scrim-ink: #fff;
}

/* ---------- 頂列：捨棄 ／ 種類切換 ／ 發布 ---------- */
/* iOS 是導覽列：左「捨棄」、中間分段控制、右「發布」。 */
.compose-head {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin: 4px 0 14px;
}
.compose-kinds { justify-content: center; }
.compose-discard, .compose-publish {
  min-height: 44px;
  padding: 0 4px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 15px;
  cursor: pointer;
  border-radius: var(--radius);
}
/* 「捨棄」不標危險色：它只是打開確認，真正毀掉東西的是確認裡那一顆——紅色留給那裡。 */
.compose-discard { justify-self: start; color: var(--ink-2); }
.compose-publish { justify-self: end; color: var(--accent); font-weight: 700; }
/* 不能發就停用，不是按了跳錯誤——缺什麼在畫面上看得到。 */
.compose-publish:disabled { opacity: .45; cursor: not-allowed; }

/* ---------- 列：左標題、右輸入格（Form 裡最標準的一列） ---------- */
.compose-row { cursor: default; }
.compose-row .grouped-label { flex: 0 0 auto; }
.compose-row input, .compose-row select, .compose-row textarea, .compose-select {
  flex: 1;
  min-width: 0;
  min-height: 32px;
  margin-left: auto;
  padding: 4px 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: right;
}
.compose-row select, .compose-select {
  /* 原生選單：右側目前值＋小箭頭，對齊 iOS 的 .menu picker */
  appearance: auto;
  -webkit-appearance: menulist;
  color: var(--ink-2);
  text-align: right;
  direction: rtl;               /* 讓文字靠右、箭頭在最右 */
}
.compose-row select option, .compose-select option { direction: ltr; text-align: left; }
.compose-row select:disabled, .compose-select:disabled { opacity: .7; }
.compose-row input::placeholder, .compose-row textarea::placeholder, .compose-textarea::placeholder { color: var(--ink-3); opacity: 1; }
.compose-row input:focus-visible, .compose-row select:focus-visible, .compose-textarea:focus-visible,
.compose-row textarea:focus-visible { outline-offset: 0; }

/* 整列的單行輸入（標題）與多行（內容）：文字靠左、吃滿整列 */
.compose-row.is-full input { text-align: left; margin-left: 0; }
.compose-textarea {
  display: block;
  width: 100%;
  min-height: 92px;
  padding: 12px;
  border: 0;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  resize: vertical;
}
.compose-unit { color: var(--ink-3); flex: 0 0 auto; margin-left: 6px; }

/* 開關（可以遠端進行） */
.compose-row input[type="checkbox"] {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin: 0 0 0 auto;
  accent-color: var(--accent);
}

/* 靜態說明列（連結網址、抽取來源）。
   iOS 是中間截斷；這裡整條印出來並允許換行——網址的頭（是哪一家）與
   尾（是哪一則）都有意義，兩端都留著比截斷更好。 */
.compose-static { margin: 0; color: var(--ink-3); font-size: 13px; overflow-wrap: anywhere; word-break: break-word; }
.compose-row.is-static { cursor: default; }
.compose-row.is-static .compose-static { flex: 1; text-align: left; }

/* 列裡的按鈕（移除連結、還原、播放預覽） */
.compose-rowbtn {
  width: 100%;
  min-height: 48px;
  padding: 8px 12px;
  border: 0;
  background: var(--surface);
  color: var(--accent);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.compose-rowbtn.is-danger { color: var(--danger); }
.compose-rowbtn .ms { --ms-size: 20px; --ms-opsz: 20; flex: 0 0 auto; }

/* ---------- 照片列 ---------- */
/* 一列裡放橫捲，縮圖可以捲到貼齊邊緣（「訊息」與「備忘錄」的做法）。

   [!note] 四邊留白要一樣（8）
     縮圖本身是圓角的，而它外面那張區塊卡片也是圓角的——兩個圓角疊在一起時，
     留白只要不等寬，轉角處的白邊就會一邊細一邊粗。右邊那 8 由「加照片」
     自己帶（見底下的 .compose-add）。 */
.compose-media {
  position: relative;
  padding: 0;
  cursor: default;
}
.compose-strip {
  display: flex;
  gap: 8px;
  padding: 8px 0 8px 8px;
  overflow-x: auto;
  /* 加減一張之後把「加照片」捲回視野的那一段動效（JS 只設位置）。
     放在 CSS 而不是 scrollTo 的 behavior：後者在停用平滑捲動的環境裡
     會整個不捲，而不是退回瞬間捲動。 */
  scroll-behavior: smooth;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.compose-strip::-webkit-scrollbar { display: none; }
/* [!important] 同心圓角：內半徑 = 外半徑 − 留白
     內框與外框的圓角要同心才不會打架。這裡是 8 − 8，夾在 4 以上——
     外框本來就小的時候，內框再減下去會變成直角。
     （iOS 那邊這個數字會隨系統版本變：15.5 的區塊外框是 10、iOS 26 是 24，
     所以那邊是算出來的；網頁的外框是我們自己的 --radius，固定。） */
.compose-thumb, .compose-add {
  position: relative;
  flex: 0 0 84px;
  width: 84px;
  height: 84px;
  border-radius: 4px;
  overflow: hidden;
}
.compose-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* 加一張、刪一張共用同一條曲線：easeInOut .28s，**不用彈簧**（見 JS 的說明） */
.compose-thumb.is-new { animation: compose-in .28s ease-in-out; }
@keyframes compose-in { from { opacity: 0; transform: scale(.92); } to { opacity: 1; transform: none; } }
/* 白色的叉、半透明黑的圓底——不論照片亮暗都看得見（系統相簿刪除鈕的做法）。
   視覺 24，可點範圍用 ::after 撐到 44。 */
.compose-thumb-remove {
  position: absolute;
  top: 4px; right: 4px;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  padding: 0; border: 0;
  border-radius: 50%;
  background: var(--compose-scrim);
  color: var(--compose-scrim-ink);
  cursor: pointer;
}
.compose-thumb-remove::after { content: ""; position: absolute; inset: -10px; }
.compose-thumb-remove .ms { --ms-size: 14px; --ms-opsz: 20; }
.compose-add {
  display: grid;
  place-items: center;
  align-content: center;
  gap: 4px;
  padding: 0;
  border: 0;
  background: var(--sunk);
  color: var(--ink-2);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  /* [!caution] 右邊那 8px 要併進捲動目標裡
       捲到底時對齊的是最後一個元素的右緣。留白若加在外層（strip 的
       padding-right），它就在目標之後——捲到底時那 8px 被推到畫面外，
       按鈕貼死在卡片邊緣（iOS 實測：右緣 384pt ＝ 卡片右緣 384pt，
       一點縫都沒有）。放進按鈕自己的 margin，捲動目標就含了它。 */
  margin-right: 8px;
}
.compose-add .ms { --ms-size: 22px; --ms-opsz: 24; }
.compose-add input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
/* > [!important] 焦點指示器要畫在標籤上，不是那個 1×1 的 input 上
   > `<input type="file">` 被視覺隱藏成 1×1、opacity 0，但它**仍然在 Tab 順序裡**
   > （沒有也不該有 tabindex="-1"——它才是真正的控制項，標籤只是它的外觀）。
   > 全域的 `:focus-visible` 會把 3px 外框畫在那個 1×1 的點上，等於看不見。
   > WCAG 2.4.7（焦點可見）要求焦點位置看得出來。
   >
   > 用 `:has()` 把外框轉移到看得見的標籤上。Safari 15.4＋、Chrome 105＋，
   > 這個專案其他地方也用了 `:has()`。 */
.compose-add:has(input:focus-visible) {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
/* 有東西正被拖在上方：給一圈框，沒有回饋的話使用者不知道這裡收不收。
   收的範圍是整個頁面（見 JS），所以整頁也要有一層淡淡的回饋——
   只框照片列的話，使用者會以為一定要拖到那一小條上面才算。 */
.compose.is-dropping { outline: 2px dashed var(--accent); outline-offset: 6px; border-radius: var(--radius); }
.compose-media.is-dropping::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px solid var(--accent);
  border-radius: var(--radius);
  pointer-events: none;
}

/* ---------- 標籤 ---------- */
.compose-tags { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px 12px; background: var(--surface); }
/* 籌碼：已加入的填強調色（borderedProminent）、建議的淡底（bordered）、膠囊形。
   視覺 32 高，可點範圍用 ::after 撐到 44。 */
.compose-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 12px;
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  background: var(--sunk);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.compose-chip::after { content: ""; position: absolute; inset: -6px 0; }
.compose-chip.is-on { border-color: transparent; background: var(--accent); color: var(--accent-ink); font-weight: 700; }
.compose-chip .ms { --ms-size: 12px; --ms-opsz: 20; }
.compose-chip-text { white-space: nowrap; }

/* ---------- 連結預覽（link 組不在時的退化版） ---------- */
.compose-preview { padding: 8px; background: var(--surface); }
.compose-preview-fallback {
  display: grid;
  gap: 4px;
  padding: 12px;
  border: 1px solid var(--line-soft);
  border-radius: 4px;
  background: var(--sunk);
}
.compose-preview-fallback .host { color: var(--ink-3); font-size: 12px; }
.compose-preview-fallback .title { font-weight: 700; }
.compose-preview-fallback .url { color: var(--ink-3); font-size: 12px; word-break: break-all; }
.compose-preview-fallback.is-compact { grid-template-columns: 64px 1fr; align-items: center; }
.compose-preview-fallback img { display: block; width: 100%; border-radius: 4px; background: var(--sunk); object-fit: cover; }
.compose-preview-fallback.is-large img { aspect-ratio: var(--compose-aspect, auto); }
.compose-preview-fallback.is-compact img { width: 64px; height: 64px; }
.compose-preview-fallback .text { display: grid; gap: 4px; min-width: 0; }
.compose-embed { display: grid; place-items: center; min-height: 200px; }
.compose-embed > * { max-width: 100%; }

/* 樣式段的分段控制（版面）——沿用 .segs/.seg 但收在一列裡。
   窄畫面收不下三段時整列改成上下堆，不要讓字被壓成兩個字一行。 */
.compose-row .segs { margin-left: auto; gap: 14px; flex-wrap: wrap; justify-content: flex-end; }
.compose-row .seg { font-size: 14px; min-height: 44px; }
@media (max-width: 400px) {
  .compose-row:has(.segs) { flex-wrap: wrap; }
  .compose-row .segs { margin-left: 0; width: 100%; justify-content: flex-start; }
}

/* 解析中的小轉圈 */
.compose-spinner {
  width: 18px; height: 18px;
  flex: 0 0 auto;
  margin-left: 8px;
  border: 2px solid var(--line-soft);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: ui-spin .8s linear infinite;
}
.compose-error { color: var(--danger); }
.compose-section .grouped-group > .compose-textarea { border-radius: 0; }
.compose-link-input { min-height: 110px; }
.compose-link-actions { display: flex; align-items: center; gap: 8px; padding: 10px 12px; background: var(--surface); }
.compose-link-actions .ui-btn { flex: 1; min-height: 44px; }
.compose-link-actions .compose-spinner { margin-left: 0; }
/* 標籤輸入框：可點目標要 ≥ 44。
   [!important] 選擇器要贏得過 `.compose-row input`
     那一條（.compose-row + 元素選擇器＝特異性 0,0,1,1）比原本寫的
     `.compose-tag-input`（0,0,1,0）**高**，所以它的 min-height: 32px 一路
     蓋掉這裡宣告的 44——瀏覽器量出來是 32，而原始碼上寫著 44，
     看程式碼是看不出來的。多加一層 .compose-row 才真的生效。
     （這一格與標題那一格不一樣：標題那一列是 <label>，整列 48 都可以點；
      這一列包著輸入框的是 <label> 之後也一樣，但輸入框自己也要夠大。） */
.compose-row .compose-tag-input { width: 100%; min-height: 44px; border: 0; background: transparent; color: var(--ink); font: inherit; }
.compose-media .compose-add input { margin: 0; }

@media (prefers-reduced-motion: reduce) {
  .compose-thumb.is-new { animation: none; }
  .compose-spinner { animation: none; border-top-color: var(--line-soft); }
  .compose-strip { scroll-behavior: auto; }
}
