/* ==========================================================================
   SGTool · 组件层：图标、按钮、卡片、面板、表单、弹窗、输出
   ========================================================================== */

/* ---------------------------------------------------------------- 图标
   图标在所有使用场景中都是 flex 子元素，垂直位置由容器的 align-items 控制。
   这里刻意不设 vertical-align —— 它只在行内格式化上下文里生效，一旦图标
   被 span 之类的元素多包一层，就会把图标顶偏（顶栏主题按钮踩过一次）。 */

.icon {
  display: block;
  flex: 0 0 auto;
}

/* ---------------------------------------------------------------- 图标按钮
   顶栏的操作按钮：统一 36x36，带底色与描边，保证在半透明顶栏上清晰可见；
   悬停时整体转为品牌色。 */

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 36px;
  height: 36px;
  padding: 0;
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-subtle);
  color: var(--color-text);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--transition), color var(--transition),
              border-color var(--transition), box-shadow var(--transition);
}

.icon-btn:hover,
.icon-btn[aria-expanded="true"] {
  border-color: var(--color-primary);
  background: var(--color-primary-soft);
  color: var(--color-primary);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
}

/* 顶栏里的图标略放大，增强视觉存在感 */
.header-actions .icon {
  width: 18px;
  height: 18px;
}

.icon-btn--wide {
  width: auto;
  padding-inline: var(--space-3);
}

/* ---------------------------------------------------------------- 语言下拉
   外层是原生 <details>：展开/收起由浏览器负责，不依赖 JS。 */

.lang-menu {
  position: relative;
}

.lang-menu > summary {
  display: inline-flex;
  list-style: none;
}

/* 去掉 Safari 默认的三角标记 */
.lang-menu > summary::-webkit-details-marker {
  display: none;
}

.lang-menu[open] > summary {
  border-color: var(--color-primary);
  background: var(--color-primary-soft);
  color: var(--color-primary);
  box-shadow: var(--shadow-sm);
}

.lang-menu__list {
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  z-index: 110;
  min-width: 148px;
  margin: 0;
  padding: var(--space-1);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  box-shadow: var(--shadow-md);
  list-style: none;
}

.lang-menu__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-size: var(--text-sm);
  transition: background var(--transition), color var(--transition);
}

.lang-menu__item:hover {
  background: var(--color-primary-soft);
  color: var(--color-primary);
  text-decoration: none;
}

.lang-menu__item.is-active {
  color: var(--color-primary);
  font-weight: 500;
}

.lang-menu__item .icon {
  width: 15px;
  height: 15px;
}

/* 展开时给一个短促的落下动画，与搜索弹窗共用同一套缓动 */
.lang-menu[open] .lang-menu__list {
  animation: sg-pop-in 140ms cubic-bezier(.16, 1, .3, 1) both;
}

/* 主题按钮：月亮与太阳都是按钮的直接子元素，靠 display 切换。
   直接子元素才能作为 flex 子项被 align-items 正确居中。 */
.theme-icon--sun {
  display: none;
}

[data-theme="dark"] .theme-icon--moon {
  display: none;
}

[data-theme="dark"] .theme-icon--sun {
  display: block;
}

/* ---------------------------------------------------------------- 键盘按键 */

.kbd {
  display: inline-block;
  padding: 1px 5px;
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-text-subtle);
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.5;
  white-space: nowrap;
}

/* ---------------------------------------------------------------- 按钮 */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 7px var(--space-4);
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-sm);
  background: var(--color-bg-muted);
  color: var(--color-text);
  font-size: var(--text-sm);
  line-height: 1.4;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.btn:hover {
  background: var(--color-border);
  text-decoration: none;
}

.btn:disabled {
  opacity: .55;
  cursor: not-allowed;
}

.btn--primary {
  background: var(--color-primary);
  color: #fff;
}

.btn--primary:hover {
  background: var(--color-primary-hover);
}

.btn--outline {
  border-color: var(--color-border-strong);
  background: transparent;
}

.btn--outline:hover {
  border-color: var(--color-primary);
  background: var(--color-primary-soft);
  color: var(--color-primary);
}

.btn--block {
  width: 100%;
}

/* ---------------------------------------------------------------- 工具卡片 */

.tool-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--space-4);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-text);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.tool-card:hover {
  border-color: var(--color-primary-border);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
}

.tool-card__name {
  font-size: var(--text-lg);
  font-weight: 600;
}

.tool-card__desc {
  flex: 1;
  margin-top: var(--space-2);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.tool-card__version {
  margin-top: var(--space-3);
  color: var(--color-text-subtle);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

/* ---------------------------------------------------------------- 面板 */

.panel {
  padding: var(--space-5);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
}

.panel + .panel {
  margin-top: var(--space-4);
}

.panel__title {
  font-size: var(--text-xl);
}

.panel__desc {
  margin-top: var(--space-2);
  color: var(--color-text-muted);
}

.panel__actions {
  margin-top: var(--space-5);
}

/* ---------------------------------------------------------------- 定义列表 */

.meta-list {
  margin-top: var(--space-4);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
}

.meta-list__row {
  display: flex;
  gap: var(--space-4);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
}

.meta-list__row + .meta-list__row {
  border-top: var(--border-width) solid var(--color-border);
}

.meta-list dt {
  flex: 0 0 110px;
  color: var(--color-text-muted);
}

.meta-list dd {
  margin: 0;
  word-break: break-all;
}

/* ---------------------------------------------------------------- 表单 */

.field + .field {
  margin-top: var(--space-4);
}

.field__label {
  display: block;
  margin-bottom: var(--space-1);
  font-size: var(--text-sm);
  font-weight: 500;
}

.field__hint {
  margin-top: var(--space-1);
  color: var(--color-text-subtle);
  font-size: var(--text-xs);
}

.input,
.select,
.textarea {
  width: 100%;
  padding: 7px var(--space-3);
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: var(--ring);
}

.textarea {
  min-height: 140px;
  resize: vertical;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
}

/* ---------------------------------------------------------------- 结果输出 */

.result {
  display: block;
  margin-top: var(--space-4);
  padding: var(--space-3);
  border: var(--border-width) solid var(--color-border);
  border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-sm);
  background: var(--color-bg-subtle);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  white-space: pre-wrap;
  word-break: break-word;
}

.result--success {
  border-left-color: var(--color-success);
  background: var(--color-success-soft);
}

.result--error {
  border-left-color: var(--color-danger);
  background: var(--color-danger-soft);
}

/* ---------------------------------------------------------------- 徽章 */

.badge {
  display: inline-block;
  padding: 1px var(--space-2);
  border: var(--border-width) solid var(--color-primary-border);
  border-radius: var(--radius-sm);
  background: var(--color-primary-soft);
  color: var(--color-primary);
  font-size: var(--text-xs);
}

/* ---------------------------------------------------------------- 空状态 */

.empty-state {
  padding: var(--space-7) var(--space-4);
  border: var(--border-width) dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  color: var(--color-text-subtle);
  text-align: center;
}

/* ---------------------------------------------------------------- 搜索弹窗 */

/* 弹出动画：遮罩淡入，面板自上而下轻微下落并放大。
   时长与缓动刻意偏快偏干脆，符合工具站的手感。 */
@keyframes sg-overlay-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes sg-pop-in {
  from {
    opacity: 0;
    transform: translateY(-10px) scale(.97);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 12vh var(--space-4) var(--space-4);
}

.modal[hidden] {
  display: none;
}

.modal__backdrop {
  position: absolute;
  inset: 0;
  background: var(--overlay);
  animation: sg-overlay-in 160ms ease-out both;
}

.modal__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(560px, 100%);
  max-height: 60vh;
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  animation: sg-pop-in 180ms cubic-bezier(.16, 1, .3, 1) both;
}

.modal__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: var(--border-width) solid var(--color-border);
  color: var(--color-text-subtle);
}

.modal__input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--color-text);
  font-size: var(--text-base);
}

.modal__input:focus {
  outline: none;
}

.modal__input::placeholder {
  color: var(--color-text-subtle);
}

.modal__body {
  overflow-y: auto;
  padding: var(--space-2);
}

.modal__foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border-top: var(--border-width) solid var(--color-border);
  background: var(--color-bg-subtle);
  color: var(--color-text-subtle);
  font-size: var(--text-xs);
}

.modal__foot span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

/* 搜索结果 */

.search-result {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  color: inherit;
  cursor: pointer;
}

/* 压掉 base.css 里 a:hover 的下划线。搜索项用背景色表达选中，
   文字再带下划线会显得杂乱。
   注意必须显式带上 :hover —— a:hover 的优先级 (0,1,1) 高于单个类
   (0,1,0)，光写在基础规则里会被它盖回去。 */
.search-result,
.search-result:hover,
.search-result:focus-visible {
  text-decoration: none;
}

/* 只保留 .is-active 一种高亮来源。
   鼠标悬停也走同一状态（见 search.js 的 mouseover），
   否则键盘移动高亮时，静止的指针会再亮起一项，出现两个高亮。 */
.search-result.is-active {
  background: var(--color-primary-soft);
  text-decoration: none;
}

.search-result__main {
  flex: 1;
  min-width: 0;
}

.search-result__name {
  font-weight: 500;
}

.search-result__desc {
  display: block;
  margin-top: 2px;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 箭头图标被包在 span 里，容器要是 flex 才能垂直居中 */
.search-result__go {
  display: flex;
  align-items: center;
  color: var(--color-text-subtle);
}

.search-result.is-active .search-result__go {
  color: var(--color-primary);
}

.search-empty {
  padding: var(--space-6) var(--space-4);
  color: var(--color-text-subtle);
  text-align: center;
  font-size: var(--text-sm);
}

/* ---------------------------------------------------------------- Hero 搜索框
   外观是输入框，实际是打开搜索弹窗的按钮，比顶栏图标更好发现。 */

.hero-search {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: min(520px, 100%);
  height: 48px;
  padding-inline: var(--space-4);
  border: var(--border-width) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-text-subtle);
  font-size: var(--text-base);
  cursor: pointer;
  transition: border-color var(--transition), box-shadow var(--transition), color var(--transition);
}

.hero-search:hover {
  border-color: var(--color-primary);
  color: var(--color-text-muted);
  box-shadow: var(--shadow-sm);
}

.hero-search__label {
  flex: 1;
  text-align: left;
}

/* ---------------------------------------------------------------- 分类卡片 */

.category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-4);
}

.category-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: 100%;
  padding: var(--space-4);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  color: var(--color-text);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.category-card:hover {
  border-color: var(--color-primary-border);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
}

.category-card__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  background: var(--color-primary-soft);
  color: var(--color-primary);
}

.category-card__body {
  flex: 1;
  min-width: 0;
}

.category-card__name {
  display: block;
  font-weight: 600;
}

.category-card__meta {
  display: block;
  margin-top: 2px;
  color: var(--color-text-subtle);
  font-size: var(--text-xs);
}

.category-card__go {
  display: flex;
  align-items: center;
  color: var(--color-text-subtle);
}

.category-card:hover .category-card__go {
  color: var(--color-primary);
}

/* ---------------------------------------------------------------- 筛选栏 */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.filter-chip {
  padding: 6px var(--space-3);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg-subtle);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}

.filter-chip:hover {
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.filter-chip.is-active {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: #fff;
}

/* ---------------------------------------------------------------- 工具页布局 */

/* 宽屏左右双栏（输入 / 输出），窄屏自动堆叠 */
.tool-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

.tool-columns .field + .field {
  margin-top: 0;
}

/* 工具页的输入输出区给足高度：Base64 常要粘贴大段文本 */
.tool-columns .textarea {
  min-height: 240px;
}

@media (max-width: 720px) {
  .tool-columns {
    grid-template-columns: 1fr;
  }

  .tool-columns .textarea {
    min-height: 160px;
  }
}

/* 工具的操作按钮组 */
.tool-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

/* 主操作按钮的文案会在 Encode / Decode 之间切换，两者宽度略有差异。
   锁定最小宽度，避免每次切换时按钮跟着伸缩。 */
.tool-actions [data-b64-run] {
  min-width: 104px;
}

/* 自动转换开关推到右端。用样式表而非内联 style，
   窄屏适配才能覆盖它。 */
.tool-actions > .switch {
  margin-left: auto;
}

/* ---------------------------------------------------------------- 窄屏适配
   针对手机：收紧内边距、操作区改为纵向铺满，
   并修掉提示气泡在小屏上探出视口的问题。 */

@media (max-width: 560px) {
  /* 内边距收窄，把宽度让给内容本身 */
  .panel {
    padding: var(--space-4);
  }

  /* 横排时按钮和开关会挤成一团，改为纵向铺满、逐个居中 */
  .tool-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .tool-actions > .switch {
    margin-left: 0;
    order: -1; /* 开关放最前，紧跟在模式切换之后，符合操作顺序 */
  }

  .tool-actions > .btn {
    justify-content: center;
  }

  /* 分段开关撑满一行，两个选项各占一半 */
  .tool-modes .segmented {
    display: flex;
    width: 100%;
  }

  .segmented__item {
    flex: 1;
    min-width: 0;
  }

  /* 提示气泡默认「居中于触发元素」，在窄屏上容易探出视口。
     这里开关已被拉伸成整行、内容靠左，所以改为左对齐向右展开，
     宽度同时限制在视口之内。 */
  [data-tip]::after {
    left: 0;
    right: auto;
    max-width: calc(100vw - 2 * var(--space-3) - 2 * var(--space-4));
    transform: translate(0, 4px);
  }

  [data-tip]:hover::after,
  [data-tip]:has(:focus-visible)::after {
    transform: translate(0, 0);
  }

  /* 尖角跟着靠左，对准开关文字 */
  [data-tip]::before {
    left: 18px;
    right: auto;
    transform: rotate(45deg);
  }

  /* 一言的密文可能很长，窄屏收一下内边距 */
  .quote-box__code {
    padding: calc(var(--space-2) + var(--border-width)) calc(var(--space-3) + var(--border-width));
  }

  /* 搜索弹窗：顶部 12vh 的留白在手机上太浪费，
     改为贴着顶部；面板高度放宽到接近满屏 ——
     手机弹出输入法后可视高度会骤减，60vh 会让结果列表几乎看不见。 */
  .modal {
    padding: var(--space-3) var(--space-2) var(--space-2);
  }

  .modal__panel {
    /* 先给不支持 dvh 的浏览器一个兜底，再用动态视口单位覆盖 */
    max-height: calc(100vh - 2 * var(--space-3));
    max-height: calc(100dvh - 2 * var(--space-3));
  }

  /* 键盘快捷键提示在触屏上无意义 */
  .modal__foot {
    display: none;
  }
}

/* 工具底部的说明条 */
.tool-note {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: var(--border-width) solid var(--color-border);
  color: var(--color-text-subtle);
  font-size: var(--text-xs);
}

.tool-note .icon {
  color: var(--color-success);
}

/* ---------------------------------------------------------------- 每日一言
   密文本身就是按钮：点一下播放跳跃动画，同时换成明文。 */

.quote-box__head {
  margin-bottom: var(--space-3);
}

.quote-box__title {
  font-size: var(--text-lg);
}

.quote-box__hint {
  display: block;
  margin-top: var(--space-1);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.quote-box__code {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  /* 边框交给两层伪元素绘制：border-style 不可过渡，直接改样式会让
     虚线瞬间变实线（还是蓝的），看起来像两种边框错误地叠在一起。
     拆成两层之后，虚线淡出、实线淡入，是干净的交叉淡化。
     原先 1px 边框占的尺寸用 padding 补回来，避免内容位移。 */
  border: 0;
  padding: calc(var(--space-3) + var(--border-width)) calc(var(--space-4) + var(--border-width));
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  text-align: left;
  cursor: pointer;
  transition: background-color 400ms ease, box-shadow 400ms ease, opacity 160ms ease;
}

.quote-box__code::before,
.quote-box__code::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-sm);
  pointer-events: none;
  transition: opacity 400ms ease, border-color 400ms ease;
}

/* 待解状态：蓝灰色虚线 */
.quote-box__code::before {
  border: var(--border-width) dashed var(--color-border-strong);
  opacity: 1;
}

/* 已解状态：中性实线，初始完全透明 */
.quote-box__code::after {
  border: var(--border-width) solid var(--color-border);
  opacity: 0;
}

.quote-box__code:hover:not(:disabled) {
  background: var(--color-bg-subtle);
  box-shadow: var(--shadow-sm);
}

.quote-box__code:hover:not(:disabled)::before {
  border-color: var(--color-primary);
}

/* 密文与明文共用同一套字号和行高：这样点击前后框体尺寸完全不变，
   只有「字色的深浅」和「边框虚实」在变，不会有跳变感。 */
.quote-box__text {
  flex: 1;
  min-width: 0;
  min-height: 1.7em; /* 与行高一致：密文取回来之前先占住高度，避免塌陷 */
  color: var(--color-text-subtle);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: 1.7;
  word-break: break-all;
  transition: color 220ms ease;
}

/* 右侧图标：不加底框，直接融入整块 —— 悬停时随主色一起变蓝 */
.quote-box__action {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--color-text-subtle);
  transition: color var(--transition), opacity 180ms ease;
}

.quote-box__code:hover:not(:disabled) .quote-box__action {
  color: var(--color-primary);
}

/* 解开后图标淡出，但保留占位 —— 从布局中移除会让文字区域变宽而重排 */
.quote-box__action.is-faded {
  opacity: 0;
}

/* 内容切换时的淡出相位：不淡到全透明，保留一点存在感，避免闪烁感 */
.quote-box__code.is-fading {
  opacity: .35;
}

/* 解开之后：蓝虚线淡出、中性实线淡入 —— 两条边框各自过渡，不会出现
   「蓝虚线瞬间变蓝实线」的中间态。这个类在点击瞬间挂上。 */
.quote-box__code.is-revealed {
  cursor: default;
}

.quote-box__code.is-revealed::before {
  opacity: 0;
}

.quote-box__code.is-revealed::after {
  opacity: 1;
}

/* 密文是异步取回的，分两段处理：
   取回前显示扫光骨架，取回后密文淡入 —— 让替换看起来是渐变的，
   而不是「骨架消失、文字突然出现」。 */

@keyframes quote-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

.quote-box__text:empty {
  display: block;
  /* 高度由 min-height 决定，与正文行高一致，填入内容时不会跳高 */
  border-radius: var(--radius-sm);
  background: linear-gradient(
    90deg,
    var(--color-bg-muted) 25%,
    var(--color-border-strong) 50%,
    var(--color-bg-muted) 75%
  );
  background-size: 200% 100%;
  animation: quote-shimmer 1.4s linear infinite;
}

/* 逐字淡入：间隔由 JS 按总跨度分配，这里只管单字的时长与缓动。
   密文与明文共用同一套出场方式。
   只动 opacity、不做位移 —— transform 的亚像素渲染会让文字发虚。 */
@keyframes quote-char-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.quote-char {
  animation: quote-char-in 260ms ease both;
}

/* 字体与字色的切换单独一个类，等内容真正换成明文之后再挂。
   若跟着 is-revealed 一起生效，密文会先被渲染成无衬线 ——
   等宽字比无衬线宽，看起来就是密文突然「缩紧」了一下。 */
.quote-box__code.is-decoded .quote-box__text {
  color: var(--color-text);
  font-family: var(--font-sans);
}

/* ---------------------------------------------------------------- 分段开关
   互斥选项，连成一体；外层 .tool-modes 负责居中。 */

.tool-modes {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-5);
}

.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border: var(--border-width) solid var(--color-primary-border);
  border-radius: var(--radius-sm);
  background: var(--color-primary-soft);
}

.segmented__item {
  padding: 6px var(--space-5);
  /* 固定最小宽度并居中：Encode / Decode 的字母宽度不同，
     不锁定的话切换时整个开关会跟着抖一下。 */
  min-width: 92px;
  text-align: center;
  border: 0;
  border-radius: 1px;
  background: transparent;
  color: var(--color-primary);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}

.segmented__item:hover {
  background: var(--color-primary-border);
}

.segmented__item.is-active {
  background: var(--color-primary);
  color: #fff;
  font-weight: 500;
}

/* ---------------------------------------------------------------- 开关 */

.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  cursor: pointer;
  user-select: none;
}

/* 视觉上隐藏原生 checkbox，但保留键盘可达性 */
.switch input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.switch__track {
  position: relative;
  flex: 0 0 auto;
  width: 36px;
  height: 20px;
  border-radius: var(--radius-sm);
  background: var(--color-border-strong);
  transition: background var(--transition);
}

.switch__track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  transition: transform var(--transition);
}

.switch input:checked + .switch__track {
  background: var(--color-primary);
}

.switch input:checked + .switch__track::after {
  transform: translateX(16px);
}

.switch input:focus-visible + .switch__track {
  box-shadow: var(--ring);
}

/* ---------------------------------------------------------------- 提示气泡
   自绘而非用浏览器默认的 title：样式统一、跟随主题，出现与收起时机可控。
   只在鼠标悬停或键盘聚焦时出现 —— 用 :focus-visible 而不是 :focus-within，
   否则鼠标点完按钮焦点留在上面，气泡会一直钉在页面上。 */

[data-tip] {
  position: relative;
}

/* 气泡本体：白底 + 阴影，方角，与尖角拼成一个整体 */
[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  z-index: 50;
  width: max-content;
  max-width: 260px;
  padding: 8px var(--space-3);
  border: var(--border-width) solid var(--color-border);
  border-radius: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-size: var(--text-xs);
  font-weight: 400;
  line-height: 1.5;
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translate(-50%, 4px);
  transition: opacity var(--transition), transform var(--transition);
  pointer-events: none;
}

/* 尖角：旋转 45° 的正方形，只保留朝下的两条边。
   z-index 必须高于气泡 —— 它要盖住气泡底边那一小段，否则边框会横穿尖角，
   看起来像两者之间连了一条线。尖角内部填的是同一个背景色，因此和气泡融为一体。 */
[data-tip]::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 5px);
  left: 50%;
  z-index: 51;
  width: 10px;
  height: 10px;
  border-right: var(--border-width) solid var(--color-border);
  border-bottom: var(--border-width) solid var(--color-border);
  background: var(--color-bg);
  transform: translateX(-50%) rotate(45deg);
  opacity: 0;
  transition: opacity var(--transition);
  pointer-events: none;
}

[data-tip]:hover::after,
[data-tip]:hover::before,
[data-tip]:has(:focus-visible)::after,
[data-tip]:has(:focus-visible)::before {
  opacity: 1;
}

[data-tip]:hover::after,
[data-tip]:has(:focus-visible)::after {
  transform: translate(-50%, 0);
}
