/* ============================================================
   规格卡片 —— 顾客端抽屉（/）和后台「商品预览」（/admin）共用这一份。
   2026-10-17 从 styles.css 抽出来：他原话「商品预览你直接用真实的网页的那种代码不可以吗，
   一旦我改了什么（比如温度特效）这里又没改」。所以两边吃同一套 class，改一处两边一起变。
   依赖的 --brand / --muted / --line 两个页面各自的 :root 里都有，值一致。
   ============================================================ */

.spec-group { padding: 16px 0 4px; }
.spec-group:first-child { padding-top: 8px; }
.spec-group__name { font-size: 14.5px; font-weight: 800; display: flex; gap: 5px; align-items: center; }
.spec-group__name .req { color: var(--brand); }

/* 卡片宽度：以前 minmax(104px) 排三只，结果杯型换成大图标后「大杯 +¥2.9」被挤成「大…」
   （2026-10-17 他「大杯都变成省略号了，你不能把按钮变长一点吗」）。
   提到 132px：375 宽的抽屉里正好两列，再宽的屏自动排三列。 */
.spec-opts { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 9px; margin-top: 11px; }
.spec-opt {
  position: relative; display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 47px;
  padding: 8px 10px; border-radius: 11px; background: #fff; border: 1px solid var(--line);
  font-size: 13.5px; color: #2c2022; text-align: center;
}
/* 图标 + 名字 + 容量整组居中：格子放宽到两列后，左对齐会让右边空出一大块（2026-10-17 他「选项文字可以置中显示啊」） */
.spec-opt__txt { min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 2px; }
/* 名字可以省略，加价必须留全，否则「+¥2.9」会被挤成省略号 */
.spec-opt__name { font-weight: 700; display: flex; align-items: baseline; justify-content: center; gap: 3px; min-width: 0; max-width: 100%; }
.spec-opt__name i { font-style: normal; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.spec-opt__name em { font-style: normal; flex: 0 0 auto; font-size: 11px; font-weight: 600; color: #9c8b8d; }
.spec-opt__sub { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.spec-opt.is-on { border-color: var(--brand); color: var(--brand); }
.spec-opt.is-on .spec-opt__name em { color: var(--brand); }
.spec-opt.is-on .spec-opt__sub { color: #cf8d95; }

/* 图标一律是后台从素材库挑的图片，图本身带颜色，不套 currentColor 描边。
   尺寸三档由选项上的 size-* 决定（对应 spec_options.icon_size）：
   sm 给「冰/热」那种小符号，md 给一般实物图，lg 给杯型那种「本体就是内容」的大图。 */
.spec-opt__ico { flex: 0 0 auto; display: grid; place-items: center; }
.spec-opt__ico img { object-fit: contain; display: block; }
.spec-opt.size-sm .spec-opt__ico, .spec-opt.size-sm .spec-opt__ico img { width: 22px; height: 22px; }
.spec-opt.size-md .spec-opt__ico, .spec-opt.size-md .spec-opt__ico img { width: 28px; height: 34px; }
.spec-opt.size-lg .spec-opt__ico, .spec-opt.size-lg .spec-opt__ico img { width: 36px; height: 46px; }
.spec-opt.size-md, .spec-opt.size-lg { gap: 6px; padding-left: 8px; }

/* 选中态发光色：冰=蓝、热=红，后台只在「温度」那一档给这个开关（fx 存 cool / warm） */
.spec-opt.fx-cool { --fx: #2f8ef7; --fx-bg: #f2f8ff; --fx-glow: rgba(47, 142, 247, .5); --fx-glow-0: rgba(47, 142, 247, 0); --fx-ink: #1d6fd0; }
.spec-opt.fx-warm { --fx: var(--brand); --fx-bg: #fff5f6; --fx-glow: rgba(200, 26, 48, .5); --fx-glow-0: rgba(200, 26, 48, 0); --fx-ink: var(--brand); }
.spec-opt.is-on[class*="fx-"] { border-color: var(--fx); color: var(--fx-ink); background: var(--fx-bg); }
.spec-opt.is-on[class*="fx-"] .spec-opt__name em { color: var(--fx); }
.spec-opt.is-on[class*="fx-"] .spec-opt__sub { color: var(--fx); opacity: .62; }

/* 描边「绕一圈」：rect 用 pathLength=1，dashoffset 1→0 就是把边框画出来。
   两个坑：① svg 必须 inset:-1px 盖到边框外沿，否则画在 padding box 上、圆角比边框小一圈，
   四角会露白（他圈的第二个问题）；② 动画期间把元素自己的 border 收透明，全场只留这一圈描边。 */
.spec-opt__ring {
  position: absolute; inset: -1px; width: calc(100% + 2px); height: calc(100% + 2px);
  overflow: visible; pointer-events: none; opacity: 0;
}
.spec-opt__ring rect {
  fill: none; stroke: var(--fx); stroke-width: 1.5px; stroke-linejoin: round;
  x: .75px; y: .75px; width: calc(100% - 1.5px); height: calc(100% - 1.5px); rx: 10.25px; ry: 10.25px;
  stroke-dasharray: 1; stroke-dashoffset: 1;
}
/* 一次点选 = 画边框(.5s) → 发光两次(.5s×2) → 图标从大弹回正常。
   动画期间只留 ring 那一圈描边：下面这条必须比 `.is-on[class*="fx-"]` 更具体，
   否则选中项的 border 颜色会把它盖回去，两层圆角描边一叠，四角就又露白了。 */
.spec-opt.is-fx, .spec-opt.is-on[class*="fx-"].is-fx { border-color: transparent; }
.spec-opt.is-fx .spec-opt__ring { opacity: 1; }
.spec-opt.is-fx .spec-opt__ring rect { animation: fx-draw .5s ease-out forwards; }
@keyframes fx-draw { to { stroke-dashoffset: 0; } }
.spec-opt.is-fx { animation: fx-glow .52s ease-out .46s 2; }
@keyframes fx-glow {
  0% { box-shadow: 0 0 0 0 var(--fx-glow-0); }
  45% { box-shadow: 0 0 13px 2px var(--fx-glow); }
  100% { box-shadow: 0 0 0 0 var(--fx-glow-0); }
}
.spec-opt.is-fx .spec-opt__ico img { animation: fx-pop .58s cubic-bezier(.34, 1.56, .64, 1) .28s both; }
@keyframes fx-pop { 0% { transform: scale(2.15); } 55% { transform: scale(.86); } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .spec-opt.is-fx, .spec-opt.is-fx .spec-opt__ring rect, .spec-opt.is-fx .spec-opt__ico img { animation: none; }
  .spec-opt.is-fx .spec-opt__ring rect { stroke-dashoffset: 0; }
}

/* 「推荐」角标骑在卡片右上角的描边上（跟参考图一样是颗小角标）。
   不能压在卡片里面：大杯那颗既要显示 +¥2.9 又要显示推荐，挤在一行会被角标盖住。 */
.spec-opt__rec {
  position: absolute; top: -8px; right: 7px; padding: 1px 5px; border-radius: 5px 5px 5px 0;
  background: #b98b52; color: #fff; font-size: 9.5px; font-weight: 700; line-height: 1.6;
}

/* 商品名下方的一排标签：浅米底 + 灰棕字，够显眼但不跟红色价格抢。永远只占一行。
   （从 styles.css 整条搬过来，顾客端商品行 / 抽屉 / 后台预览同一份，别再出现「预览和真机不一样」） */
.p-row__tags { display: flex; flex-wrap: nowrap; gap: 3px; margin-top: 4px; overflow: hidden; }
.p-row__tags span {
  /* 挤不下时让标签自己缩并出省略号，而不是被行的右边缘切掉半颗胶囊 */
  flex: 0 1 auto; min-width: 0;
  font-size: 9px; color: #8a7058; background: #f7efe3;
  border-radius: 4px; padding: 1px 3.5px; line-height: 1.5; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
