/* ===========================================================================
   Myosorie · shared site stylesheet
   Warm analog paper-and-shelf language, extracted from the homepage.
   Tokens + global chrome (nav, footer) + reusable components (buttons, cards,
   forms, section heads, tags, breadcrumbs, badges, empty states).
   =========================================================================== */
/* 字体改由每个引用本文件的页面在 <head> 里直接 <link preconnect + stylesheet> 加载
   (原来这里用 @import,是渲染阻塞的串行瀑布:得先下完整个 site.css、解析出 @import、
   再去请求字体 CSS、再解析出 woff2 URL——比并行的 <link> 多一整轮 RTT,2026-08-29 改)。 */

/* ===== 响应式标准断点(约定,非强制,2026-08-29 起新增/修改规则请遵循)=====
   ≤420  手机窄(iPhone SE / 小屏安卓)
   ≤600  手机(含大屏手机竖屏)
   ≤900  平板竖屏(iPad 竖屏 768-834 落在此区间)
   ≤1080 平板横屏 / 小笔记本
   新增或修改断点规则时优先复用以上四个数值;现有的 520/560/780/920/1280/1560
   等断点各有历史设计意图,不做批量重写,仅新代码向标准值收敛。
   ========================================================================= */

:root{
  --cream:#f3ecdc; --paper:#f7f1e2; --paper-2:#fbf4e1;
  --ink:#3c3327; --ink-soft:#6f6555; --ink-faint:#958a76;
  --line:#d9cbae; --line-soft:#e4d9c2;
  --blue:#56689e; --blue-deep:#48588a;
  --gold:#a9824e; --gold-deep:#946f3f; --bag:#b8945e; --wood:#c98f4a; --brass-d:#6f5d3f;
  --rust:#b06a52; --stamp-blue:#5f6c99; --stamp-red:#b65c47;
  --shadow:rgba(86,70,42,.16);
  --display:"Cormorant Garamond",Georgia,serif;
  --text:"EB Garamond",Georgia,serif;
  --mono:"Courier Prime","SFMono-Regular",ui-monospace,Menlo,monospace;
  --lane:1320px;
  --pad:clamp(22px,5vw,72px);
  --r-sm:5px; --r:13px; --r-lg:18px;
  --flower:url("../_ds/myosorie-design-system-9bd9b895-dce4-461e-93ed-d4f5a1cf0616/assets/flower-logo.webp");
}

*{box-sizing:border-box;}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;scroll-behavior:smooth;background:var(--cream);}
html,body{overflow-x:clip;}
body{
  margin:0;background:var(--cream);color:var(--ink);
  font-family:var(--text);font-size:17px;line-height:1.62;position:relative;min-height:100vh;
  display:flex;flex-direction:column;
}
/* paper grain — baked into the body background (NOT a fixed top overlay,
   which reallocates as a black frame on resize / breakpoint reflow) */
body::before{display:none;}
a{color:inherit;text-decoration:none;}
img{display:block;max-width:100%;}
h1,h2,h3,h4{margin:0;font-weight:600;font-family:var(--display);letter-spacing:.3px;}
p{margin:0;}
button{font:inherit;}

.lane{width:100%;max-width:var(--lane);margin:0 auto;padding:0 var(--pad);position:relative;}
.page{flex:1 1 auto;padding:clamp(34px,4.5vw,68px) 0 clamp(48px,6vw,90px);}
.flower-i{width:1em;height:1em;display:inline-block;vertical-align:-.12em;}
.mono{font-family:var(--mono);text-transform:uppercase;letter-spacing:.22em;}

/* ===================== TOP NAV ===================== */
.nav{
  display:flex;align-items:center;gap:clamp(18px,3vw,48px);
  padding:clamp(12px,1vw,16px) var(--pad);
  background:var(--cream);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:50;
}
.nav-brand{display:flex;align-items:center;gap:10px;flex:0 0 auto;font-family:var(--display);font-weight:600;font-size:clamp(26px,2.1vw,34px);color:var(--ink);}
.nav-brand img{width:clamp(22px,1.5vw,27px);height:auto;}
.nav-links{display:flex;gap:clamp(16px,2.6vw,42px);flex:1 1 auto;justify-content:center;}
.nav-links a{
  font-family:var(--text);font-size:clamp(15px,1.05vw,17px);color:var(--ink);letter-spacing:.4px;padding-bottom:5px;
  background:linear-gradient(var(--blue),var(--blue)) center 100%/0% 2px no-repeat;
  transition:color .2s,background-size .34s cubic-bezier(.34,1.56,.64,1);
}
.nav-links a:hover{color:var(--blue-deep);background-size:100% 2px;}
.nav-links a.active{color:var(--ink);background:linear-gradient(var(--ink),var(--ink)) center 100%/22px 1px no-repeat;}
.nav-icons{display:flex;gap:clamp(15px,1.4vw,24px);align-items:center;flex:0 0 auto;}
.nav-icons a{color:var(--ink);display:inline-flex;position:relative;transition:transform .25s cubic-bezier(.34,1.56,.64,1),color .2s;}
/* 触控热区扩容(不改视觉图标尺寸/不挤压相邻布局):::after 叠加透明命中区,
   而非改 a 自身 padding——避免连带影响 .pip 角标的绝对定位偏移量。
   水平方向必须 ≤ 相邻图标最小间距的一半,否则命中区互相重叠导致误触:
   .nav-icons gap 最小 15px、.nav-icons[data-guest] gap 最小 8px(见下方),
   横向按最紧的 8px 折算(单侧 ≤4px,取 3px 留安全余量);纵向无相邻元素冲突,放宽到 12px */
.nav-icons a::after{content:"";position:absolute;inset:-12px -3px;}
.nav-icons a:hover{color:var(--blue-deep);transform:translateY(-2px) scale(1.12);}
.nav-icons svg{width:clamp(20px,1.4vw,23px);height:clamp(20px,1.4vw,23px);}
.nav-icons a[aria-label="Bag"]{overflow:visible;}
.nav-icons .pip{position:absolute;top:-5px;right:-7px;min-width:15px;height:15px;padding:0 3.5px;border-radius:7.5px;background:var(--blue);color:#fdf8ec;font-family:var(--text);font-weight:700;font-size:10px;line-height:15px;text-align:center;letter-spacing:.01em;font-variant-numeric:tabular-nums;box-shadow:0 0 0 2px var(--cream),0 1px 3px rgba(60,45,25,.35);}
.nav-icons a:hover .pip{transform:none;}
.nav-burger{display:none;width:42px;height:42px;flex-direction:column;align-items:center;justify-content:center;gap:5px;border:1px solid var(--line);border-radius:9px;background:rgba(248,242,228,.6);cursor:pointer;}
.nav-burger span{display:block;width:20px;height:2px;border-radius:2px;background:var(--ink);transition:.25s;}
.nav-burger[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg);}
.nav-burger[aria-expanded="true"] span:nth-child(2){opacity:0;}
.nav-burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg);}
/* 汉堡菜单触发点统一收敛到 880px(原来 600-880px 区间是"换行+横向滚动"的
   半吊子态,覆盖大量竖屏平板如 iPad 768px,体验不清晰,2026-08-29 合并)。
   沿用既有的 880 而非上方新定的标准值 900:880 是这条规则原本就在用、已验证过的值,
   合并时复用它比换成未经验证的新值风险更低,不是漏改——新增规则才应优先套 900 */
@media(max-width:880px){
  .nav-burger{display:flex;}
  .nav-brand{margin-right:auto;}
  /* code review 2026-08-29(第21轮):汉堡菜单折叠态此前只用 max-height:0+overflow:hidden
     隐藏,没有退出 Tab 顺序——链接在零高度容器里视觉不可见但键盘仍能依次聚焦到,焦点框
     无处可看,违反 WCAG 2.4.7。同文件 435 行 .nav-icons:not(.auth-ready){visibility:hidden}
     已经是这个问题的正确解法,这里补上同款处理;visibility 不参与过渡(默认瞬时切换),
     不影响 max-height 那条本来就有的展开/收起动画观感 */
  .nav-links{position:absolute;top:100%;left:0;right:0;flex-direction:column;gap:0;background:var(--cream);border-bottom:1px solid var(--line);box-shadow:0 20px 30px -20px rgba(60,45,25,.5);padding:0 var(--pad);max-height:0;overflow:hidden;visibility:hidden;transition:max-height .32s ease;}
  .nav-links.open{max-height:70vh;visibility:visible;overflow-y:auto;}
  .nav-links a{padding:15px 2px;border-bottom:1px solid var(--line);background:none;}
}

/* ===================== PAGE HEADER / BREADCRUMB ===================== */
.crumbs{display:flex;align-items:center;gap:9px;font-family:var(--mono);font-size:clamp(11px,.82vw,15px);letter-spacing:.2em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:clamp(18px,2vw,28px);flex-wrap:wrap;}
.crumbs a{color:var(--ink-faint);transition:color .2s;}
.crumbs a:hover{color:var(--ink);}
.crumbs .sep{opacity:.55;}

.page-head{margin-bottom:clamp(26px,3vw,40px);}
.kicker{display:block;font-family:var(--mono);font-size:12px;letter-spacing:.3em;text-transform:uppercase;color:var(--ink-faint);margin-bottom:10px;}
.page-title{font-family:var(--display);font-weight:600;font-size:clamp(34px,4.4vw,58px);line-height:1.04;color:var(--ink);text-wrap:balance;}
.page-title .flower-i{width:.62em;height:.62em;margin-left:.25em;}
.page-sub{color:var(--ink-soft);font-size:clamp(15px,1.1vw,19px);margin-top:14px;max-width:60ch;text-wrap:pretty;}

.sec-head{display:flex;align-items:flex-end;gap:24px;border-bottom:1px solid var(--line-soft);padding-bottom:clamp(20px,2.2vw,30px);margin-bottom:clamp(22px,2.6vw,34px);flex-wrap:wrap;}
.sec-head .sec-title{font-family:var(--display);font-size:clamp(26px,3vw,40px);font-weight:600;line-height:1;color:var(--ink);}
.sec-head .sec-sub{color:var(--ink-soft);font-size:15px;margin-left:6px;}

/* ===================== BUTTONS ===================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:12px;cursor:pointer;white-space:nowrap;
  font-family:var(--text);font-size:clamp(15px,1.05vw,17px);letter-spacing:.3px;
  padding:13px 24px;border-radius:var(--r-sm);border:1px solid transparent;transition:.2s;
}
.btn .arr{transition:transform .2s;}
.btn:hover .arr{transform:translateX(4px);}
.btn-fill{background:var(--gold);color:#f8f2e4;box-shadow:0 10px 22px -12px rgba(120,86,38,.7);}
.btn-fill:hover{background:var(--gold-deep);}
.btn-outline{background:rgba(248,242,228,.5);color:var(--ink);border-color:#b69a6a;}
.btn-outline:hover{background:rgba(248,242,228,.95);border-color:var(--gold);}
.btn-blue{background:var(--blue);color:#f6f1e6;}
.btn-blue:hover{background:var(--blue-deep);}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line);}
.btn-ghost:hover{border-color:var(--ink-faint);background:rgba(248,242,228,.6);}
.btn-block{width:100%;}
.btn-lg{padding:16px 30px;font-size:clamp(16px,1.15vw,19px);}
.btn-sm{padding:9px 16px;font-size:14px;min-height:44px;}
.btn[disabled]{opacity:.5;cursor:not-allowed;}

/* ledger tag — parchment "see all" link */
.tag-link{
  position:relative;display:inline-flex;align-items:center;gap:12px;
  font-family:var(--text);color:#3e3322;white-space:nowrap;
  padding:9px 26px 10px;border:1px solid #ab8e5e;border-radius:10px;background:#ead9b4;
  box-shadow:0 4px 10px -3px rgba(86,70,42,.28),0 1px 2px rgba(86,70,42,.18);transition:.2s;
}
.tag-link::before{content:"";position:absolute;inset:5px;border:1px solid #c4aa7d;border-radius:6px;pointer-events:none;}
.tag-link .arr{transition:transform .2s;}
.tag-link:hover{background:#eedfbe;border-color:#9d8152;transform:translateY(-1px);}
.tag-link:hover .arr{transform:translateX(4px);}

/* ===================== CARDS ===================== */
.card{
  background:var(--paper);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:inset 0 1px 0 #fff,0 16px 30px -24px var(--shadow);
}
.card-pad{padding:clamp(22px,2.4vw,34px);}

/* product card (shelf vocabulary, simplified for grids) */
.pcard{
  background:var(--paper-2);border:1px solid #e0d0ac;border-radius:var(--r);
  padding:8px 8px 14px;display:flex;flex-direction:column;
  box-shadow:inset 0 1px 0 #fff,2px 1px 3px -2px #50300e33;transition:transform .22s,box-shadow .22s;
}
.pcard:hover{box-shadow:inset 0 1px 0 #fff,0 16px 26px -16px #50300e55;}
/* position:relative 是给库存角标(.pstock)当定位祖先用的——单图卡片没有 .pmedia 那层 */
.pcard > a{display:block;position:relative;border-radius:8px;overflow:hidden;border:1px solid #e6d9bb;}
.pcard .pimg{width:100%;aspect-ratio:1/1;object-fit:cover;display:block;}
/* 库存文案由 SSR 与 api.js 孪生产出;纸签使用不透明底色保证照片上的可读性。
   基础样式也供系列页行内复用,仅卡片叠加绝对定位;不能拦截点击与拖动。 */
.pstock{
  display:inline-flex;align-items:center;line-height:1.2;white-space:nowrap;
  font-family:var(--text,"EB Garamond",Georgia,serif);font-size:14px;font-weight:500;
  letter-spacing:0;text-transform:none;
  padding:4px 8px;border-radius:2px;pointer-events:none;
  border:1px solid var(--line);background:var(--paper);color:var(--ink);
}
.pstock.is-oos{background:var(--ink-soft);color:var(--paper);border-color:var(--ink-soft);}
.pstock.is-low{background:var(--paper);color:#76552f;border-color:#cdb894;}
.pcard .pstock{position:absolute;z-index:3;top:8px;left:8px;}
/* 详情页库存行(product.html 的 .pd-stock-wrap / {{SSR_STOCK_NOTE}});
   三态文案由服务端 SSR 与 Myo.stockNote() 孪生产出,这里只有小圆点 + 文字的排版。
   位于评分行右侧,空间不足时随 .pd-meta 换行。 */
.pd-stock-wrap:empty{display:none;}
/* 评分行:左=星级+keepers(包成一组),右=库存徽章。用 space-between 而不是
   margin-left:auto —— 换行点取决于库存文案长度("Only 12 left in stock" 比 "In stock" 宽得多),
   媒体查询卡不准;space-between 在只剩一个元素独占一行时会自动靠行首,任何宽度下都对。 */
.pd-meta{flex-wrap:wrap;justify-content:space-between;}
.pd-meta-rate{display:inline-flex;align-items:center;gap:12px;}
/* 详情页用正文衬线字体承接评分行,以文字和小墨点表达状态,避免装饰抢过价格。 */
.pd-stock{
  display:inline-flex;align-items:center;gap:7px;line-height:1.4;white-space:nowrap;
  font-family:var(--text);font-size:16px;font-weight:400;
  letter-spacing:0;text-transform:none;
}
.pd-stock::before{content:"";flex:0 0 auto;width:5px;height:5px;border-radius:50%;background:currentColor;}
.pd-stock.is-in{color:#536449;}
.pd-stock.is-low{color:#76552f;}
.pd-stock.is-oos{color:#97523f;}
/* 商品卡照片翻页图廊(.pmedia 包住 <a>,补上 .pcard>a 因层级不再命中的纸框三件套);
   交互在 api.js Myo.initPreviewGalleries,与 productCard 模板同层维护 */
.pmedia{position:relative;overflow:hidden;border:1px solid #e6d9bb;border-radius:8px;touch-action:pan-y;user-select:none;}
.pmedia > a{display:block;overflow:hidden;}
.pmedia .pimg{transition:opacity .1s ease,transform .1s ease;will-change:transform,opacity;}
.pmedia .pimg.gallery-exit{opacity:.25;transform:translateX(var(--gallery-shift));}
.pmedia .pimg.gallery-enter{transition:none;opacity:.25;transform:translateX(calc(-1 * var(--gallery-shift)));}
.pmedia-nav{
  position:absolute;z-index:2;top:50%;width:44px;height:44px;padding:0;border:0;
  transform:translateY(-50%);display:grid;place-items:center;cursor:pointer;
  color:rgba(72,46,20,.75);background:rgba(238,221,184,.76);
  box-shadow:inset 0 1px rgba(255,249,232,.65);opacity:0;pointer-events:none;
  transition:opacity .18s ease,background .18s ease,color .18s ease;
}
.pmedia-nav svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;}
.pmedia-prev{left:0;border-radius:0 8px 8px 0;}
.pmedia-next{right:0;border-radius:8px 0 0 8px;}
.pmedia.gallery-ready .pmedia-nav,.pmedia:focus-within .pmedia-nav{opacity:.56;pointer-events:auto;}
.pmedia-nav:hover{opacity:1!important;background:rgba(242,226,191,.94);color:#493016;}
.pmedia-nav:focus-visible{opacity:1;outline:2px solid var(--blue);outline-offset:-3px;}
.pmedia-nav[hidden]{display:none;}
.pmedia-count{
  position:absolute;z-index:2;right:9px;bottom:8px;padding:3px 7px;border-radius:7px;
  font-family:var(--mono);font-size:10px;letter-spacing:.08em;color:#554126;
  background:rgba(247,239,217,.82);box-shadow:0 2px 7px rgba(66,43,18,.14);
  opacity:0;transition:opacity .18s ease;pointer-events:none;
}
.pmedia.gallery-ready .pmedia-count,.pmedia:focus-within .pmedia-count{opacity:.9;}
@media(prefers-reduced-motion:reduce){
  .pmedia .pimg,.pmedia-nav,.pmedia-count{transition:none;}
}
.pcard .ptop{display:flex;align-items:flex-start;gap:10px;margin:10px 4px 0;}
.pcard h4{font-family:var(--display);font-weight:600;font-size:19px;color:var(--kraft-ink,#4d3d26);line-height:1.22;flex:1 1 auto;}
.pcard .pin{flex:0 0 auto;width:9px;height:9px;border-radius:50%;margin-top:4px;background:radial-gradient(circle at 35% 30%,#f0d9a8,#c19a55 55%,#8a6630);box-shadow:0 1px 2px #00000040,inset 0 -1px 1px #00000033;}
.pcard .pfoot{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:12px 4px 0;}
.pcard .price{font-family:var(--display);font-weight:600;font-size:22px;color:#4c3a1d;line-height:1;}
/* 促销划线原价(Phase 3):商品卡/PDP/购物袋行共用,list_price>price 时前置 */
.price-was{font-size:.72em;font-weight:400;color:var(--ink-faint);text-decoration:line-through;margin-right:2px;}
.pbtns{display:flex;gap:8px;}
.pbtn{width:42px;height:38px;border-radius:8px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:.2s;border:1px solid #e0d0ac;}
.pbtn svg{width:17px;height:17px;transition:transform .2s cubic-bezier(.34,1.56,.64,1);}
.pbtn.fav{background:#fdf8eb;color:#7d6638;}
.pbtn.fav:hover{border-color:#b29457;background:#fffdf5;}
.pbtn.fav:hover svg{animation:heartbeat 1.1s ease-in-out infinite;}
.pbtn.fav.on{color:var(--stamp-red);border-color:#c79d83;background:#fdf0e3;}
.pbtn.fav.on svg path{fill:currentColor;}
.pbtn.fav.on svg{animation:heartpop .5s cubic-bezier(.34,1.7,.5,1);}
.pbtn.bag{background:var(--bag);border:none;color:#fdf6e3;}
.pbtn.bag:hover{background:#a98551;}
.pbtn.bag:hover svg{animation:bagsquish .65s cubic-bezier(.36,1.5,.5,1) infinite;}
.pbtn.bag:active{background:#9c7a47;transform:scale(.86,.94);}
.pbtn.bag:active svg{animation:none;transform:scale(1.1,.8);}
/* 售罄卡片的加购钮此前 disabled 后毫无视觉差别,看着像能点却没反应;跟 .btn[disabled] 同口径 */
/* :hover / :active 在 disabled 元素上照样匹配,而 .pbtn.bag:hover(0,3,0)比 .pbtn[disabled](0,2,0)
   特异性高——只置 opacity 压不住背景,鼠标一悬停按钮又亮成实心金色,"看着能点"的错觉原封不动。
   用 .pbtn.bag[disabled]:hover(0,4,0)把背景/位移一并按回基础态。 */
.pbtn[disabled]{opacity:.45;cursor:not-allowed;}
.pbtn.bag[disabled]:hover,.pbtn.bag[disabled]:active{background:var(--bag);transform:none;}
.pbtn[disabled]:hover svg,.pbtn[disabled]:active svg{animation:none;transform:none;}
@keyframes photoSquish{0%{transform:scale(1,1);}30%{transform:scale(1.04,.95);}60%{transform:scale(.985,1.025);}100%{transform:scale(1,1);}}
@keyframes heartbeat{0%,100%{transform:scale(1);}14%{transform:scale(1.3);}28%{transform:scale(.96);}42%{transform:scale(1.18);}58%{transform:scale(1);}}
@keyframes heartpop{0%{transform:scale(.5);}55%{transform:scale(1.4);}100%{transform:scale(1);}}
@keyframes bagsquish{0%,100%{transform:scale(1,1);}28%{transform:scale(1.2,.82);}52%{transform:scale(.88,1.14);}76%{transform:scale(1.06,.95);}}

.grid{display:grid;gap:clamp(16px,1.8vw,24px);}
.grid-2{grid-template-columns:repeat(2,1fr);}
.grid-3{grid-template-columns:repeat(3,1fr);}
.grid-4{grid-template-columns:repeat(4,1fr);}
.grid-auto{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));}
@media(max-width:920px){.grid-4,.grid-3{grid-template-columns:repeat(2,1fr);}}
@media(max-width:560px){.grid-2,.grid-3,.grid-4,.grid-auto{grid-template-columns:1fr 1fr;}}
/* 极窄屏单列兜底:560px 档强制 2 列在 ≤420px 机型上会把商品卡(含 38px 高按钮)压得过窄 */
@media(max-width:420px){.grid-2,.grid-3,.grid-4,.grid-auto{grid-template-columns:1fr;}}

/* badge / wax-seal-ish tag */
.badge{display:inline-flex;align-items:center;gap:7px;font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;padding:5px 12px;border-radius:999px;}
.badge-blue{background:rgba(86,104,158,.14);color:var(--blue-deep);}
.badge-gold{background:rgba(169,130,78,.16);color:var(--gold-deep);}
.badge-green{background:rgba(95,130,90,.18);color:#4d6a48;}
.badge-red{background:rgba(182,92,71,.16);color:var(--stamp-red);}

/* corkboard / wood wells */
.cork{background:url("../_ds/myosorie-design-system-9bd9b895-dce4-461e-93ed-d4f5a1cf0616/assets/textures/tex-cork-ref.webp") var(--wood);background-size:72px 560px;border-radius:var(--r-lg);padding:clamp(18px,2.2vw,32px);box-shadow:inset 0 2px 0 #ffe9bf4d,inset 0 0 0 1px #7e521f4d,inset 0 -26px 34px -30px #5e3a128c,0 30px 50px -36px rgba(80,52,20,.55);}

/* ===================== FORMS ===================== */
/* code review 2026-08-29:author 样式的 display:flex 会盖过 UA 默认的 [hidden]{display:none}
   (同源同权重时后者的 author 声明总赢,跟选择器写在前面后面无关)——.field/.notice 都会被
   hidden 属性"标记为隐藏"却仍然可见(contact.html/checkout.html 都吃过这个亏)。跟已有的
   .pmedia-nav[hidden] 同一套补丁模式 */
.field[hidden]{display:none;}
.field{display:flex;flex-direction:column;gap:7px;margin-bottom:18px;}
.field > label{font-family:var(--mono);font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-soft);}
.field input,.field select,.field textarea{
  font-family:var(--text);font-size:16px;color:var(--ink);
  padding:12px 14px;border:1px solid var(--line);border-radius:var(--r-sm);background:#fffdf6;
  transition:border-color .2s,box-shadow .2s;width:100%;
}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--blue);box-shadow:0 0 0 3px rgba(86,104,158,.15);}
.field textarea{resize:vertical;min-height:120px;}
.field .hint{font-size:13px;color:var(--ink-faint);}
.field-error input{border-color:var(--stamp-red);}
.field-error .hint{color:var(--stamp-red);}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
@media(max-width:520px){.field-row{grid-template-columns:1fr;}}
.checkrow{display:flex;align-items:center;gap:10px;font-size:15px;color:var(--ink-soft);}
.checkrow input{width:17px;height:17px;accent-color:var(--blue);}

/* ===================== AUTH / CENTERED CARD ===================== */
.auth-wrap{flex:1 1 auto;display:flex;align-items:center;justify-content:center;padding:clamp(34px,5vw,72px) var(--pad);}
.auth-card{width:100%;max-width:440px;background:var(--paper);border:1px solid var(--line);border-radius:var(--r-lg);padding:clamp(30px,3vw,46px);box-shadow:0 30px 54px -30px rgba(86,70,42,.4),inset 0 1px 0 #fff;position:relative;}
.auth-card .auth-brand{display:flex;align-items:center;justify-content:center;gap:9px;font-family:var(--display);font-weight:600;font-size:30px;margin-bottom:6px;}
.auth-card .auth-brand img{width:22px;}
.auth-sub{text-align:center;color:var(--ink-soft);margin-bottom:26px;}
.auth-alt{text-align:center;margin-top:22px;font-size:15px;color:var(--ink-soft);}
.auth-alt a{color:var(--blue-deep);border-bottom:1px solid currentColor;padding-bottom:1px;}
.divider-or{display:flex;align-items:center;gap:14px;margin:22px 0;color:var(--ink-faint);font-family:var(--mono);font-size:11px;letter-spacing:.2em;}
.divider-or::before,.divider-or::after{content:"";flex:1;height:1px;background:var(--line);}

/* ===================== ACCOUNT SHELL ===================== */
.acct{display:grid;grid-template-columns:248px 1fr;gap:clamp(22px,2.6vw,40px);align-items:start;}
.acct-side{position:sticky;top:96px;display:flex;flex-direction:column;gap:4px;background:var(--paper);border:1px solid var(--line);border-radius:var(--r);padding:14px;box-shadow:inset 0 1px 0 #fff;}
.acct-side a{display:flex;align-items:center;gap:12px;padding:11px 14px;border-radius:8px;color:var(--ink-soft);font-size:16px;transition:.18s;}
.acct-side a svg{width:18px;height:18px;flex:0 0 auto;}
.acct-side a:hover{background:rgba(86,104,158,.07);color:var(--ink);}
.acct-side a.active{background:var(--blue);color:#f6f1e6;}
.acct-side .sep{height:1px;background:var(--line-soft);margin:8px 6px;}
@media(max-width:780px){.acct{grid-template-columns:1fr;}.acct-side{position:static;flex-direction:row;flex-wrap:wrap;}}

/* ===== Account pages — wider lane + larger type on big screens ===== */
.lane:has(.acct){max-width:min(1660px,94vw);}
@media(min-width:781px){
  .acct{grid-template-columns:clamp(252px,17vw,312px) 1fr;}
  .acct-side a{font-size:clamp(16px,1.02vw,18.5px);padding:12px 16px;}
  .acct-side a svg{width:clamp(19px,1.2vw,22px);height:clamp(19px,1.2vw,22px);}
}
@media(min-width:1280px){
  .acct .card-pad{padding:clamp(26px,2.2vw,40px);}
  .acct .field label{font-size:clamp(13px,.92vw,15px);}
  .acct .field input,.acct .field select,.acct .field textarea{font-size:clamp(16px,1.05vw,18px);padding:13px 16px;}
  .acct .checkrow{font-size:clamp(15px,1.02vw,17.5px);}
  .acct .pcard h4{font-size:clamp(19px,1.3vw,23px);}
  .acct .pcard .price{font-size:clamp(22px,1.45vw,27px);}
  .acct .badge{font-size:clamp(11px,.8vw,13px);}
}
@media(min-width:1560px){
  .acct:has(.grid-3) .grid-3{grid-template-columns:repeat(4,1fr);}
  .acct:has(.pay-grid) .pay-grid,.acct:has(.addr-grid) .addr-grid{grid-template-columns:repeat(3,1fr);}
}

/* ===================== TABLES / ROWS ===================== */
.rows{display:flex;flex-direction:column;}
.row-item{display:flex;align-items:center;gap:18px;padding:18px 0;border-bottom:1px solid var(--line-soft);}
.row-item:last-child{border-bottom:none;}

/* ===================== HELP / DOC LAYOUT ===================== */
.lane:has(.doc){max-width:1480px;}
.doc{display:grid;grid-template-columns:240px minmax(0,1fr);gap:clamp(28px,2.6vw,52px);align-items:start;max-width:1180px;margin:0 auto;}
.doc-toc{position:sticky;top:96px;font-size:15px;max-height:calc(100vh - 120px);overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:rgba(169,130,78,0.32) transparent;padding-right:10px;}
.doc-toc::-webkit-scrollbar{width:6px;}
.doc-toc::-webkit-scrollbar-track{background:transparent;}
.doc-toc::-webkit-scrollbar-thumb{background:rgba(169,130,78,0.28);border-radius:99px;}
.doc-toc::-webkit-scrollbar-thumb:hover{background:rgba(169,130,78,0.5);}
.toc-crumbs{flex-wrap:wrap;margin-bottom:clamp(18px,2vw,26px);}
.doc-toc .mono{display:block;font-size:11px;color:var(--ink-faint);margin-bottom:14px;}
.doc-toc a{display:block;padding:7px 0;color:var(--ink-soft);border-left:2px solid transparent;padding-left:14px;margin-left:-2px;transition:.18s;}
.doc-toc a:hover{color:var(--ink);border-color:var(--line);}
.doc-body{max-width:none;}
.doc-body section{scroll-margin-top:96px;}
.doc-body h2{font-family:var(--display);font-size:clamp(24px,2.4vw,32px);margin:clamp(30px,3vw,44px) 0 12px;}
/* code review 2026-08-29(第20轮):此前这里有 .doc-body h2:first-child{margin-top:0;}——
   静态兜底 HTML 每个 <section> 各自包一个 h2,该 h2 都是自己父元素(section)的第一个
   子元素,这条选择器因此对全部 ~27 个小节标题都命中,把整篇政策文档的 margin-top 集体
   清零;而 md.js 注水后是没有 <section> 包裹的扁平结构,任何 h2 都不再是"某个直接父元素
   的第一个子元素"(唯一的 first-child 是 h1),这条规则命中不了任何元素——水合完成的
   瞬间全部 ~27 个标题同时从 0 跳到最多 44px 顶部间距,单次同步重排造成上千像素的页面
   高度突变,正在阅读中的访客会被硬拽到完全不同的滚动位置。直接删掉这条覆盖规则,让
   静态兜底与水合后同一个视觉状态(都有完整间距),消除这次跳变,不产生新的不一致 */
/* code review 2026-08-30(第23轮):此前这里有两条"给首个 h2 放大成大标题"的规则
   (.doc-body section:first-child h2 对应静态兜底、.doc-body>h2:first-child 对应注水后)——
   实测两条都是死代码,从未命中过任何元素:5 篇政策文档静态兜底的 .doc-body 首子元素固定是
   <h1 class="page-title">(其后才是 section),不是 section 本身,section:first-child 选不
   中;content_md 也统一以 "# 标题" 开头,MyoMd.render() 的首个输出元素固定是 h1(且已带
   class="page-title"),.doc-body 的首子元素同样不是 h2,>h2:first-child 也选不中。真正的
   大标题放大效果全靠 h1 自带的 .page-title(site.css:119,clamp(34px,4.4vw,58px))完成,
   这两条规则连同约 10 行描述性注释一起删除,不影响任何页面的实际渲染 */
/* 纯锚点(## {#id}):零高不占版面,带吸顶偏移让深链定位不被头部遮挡 */
.doc-body .md-anchor{display:block;height:0;scroll-margin-top:96px;}
.doc-body h3{font-family:var(--display);font-size:21px;margin:26px 0 8px;}
.doc-body p,.doc-body li{color:var(--ink-soft);font-size:17px;line-height:1.7;text-wrap:pretty;}
.doc-body ul,.doc-body ol{margin:10px 0 10px 2px;padding-left:22px;}
.doc-body li{margin:6px 0;}
.doc-body a.inline{color:var(--blue-deep);border-bottom:1px solid currentColor;}
/* Markdown 渲染补充(政策页正文改由 policy 表 MD 渲染):引用框/分隔线/行内码/标题锚点偏移 */
.doc-body blockquote{margin:14px 0;padding:10px 16px;border-left:3px solid var(--gold,#a9824e);background:rgba(169,130,78,.08);border-radius:0 8px 8px 0;}
.doc-body blockquote p{margin:0;font-size:16px;}
.doc-body code{font-family:var(--mono);font-size:.88em;background:rgba(169,130,78,.12);padding:1px 6px;border-radius:5px;}
.doc-body hr{border:0;height:1px;background:var(--line);margin:clamp(20px,2vw,32px) 0;}
.doc-body .md-table-wrap{max-width:100%;overflow-x:auto;margin:16px 0 22px;border:1px solid var(--line);border-radius:9px;background:rgba(255,253,246,.45);}
.doc-body table{width:100%;border-collapse:collapse;font-size:16px;line-height:1.55;}
.doc-body th,.doc-body td{padding:10px 13px;border-right:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft);vertical-align:top;color:var(--ink-soft);}
.doc-body th{font-weight:600;color:var(--ink);background:rgba(169,130,78,.1);}
.doc-body th:last-child,.doc-body td:last-child{border-right:0;}
.doc-body tbody tr:last-child td{border-bottom:0;}
.doc-body .md-align-left{text-align:left;}
.doc-body .md-align-center{text-align:center;}
.doc-body .md-align-right{text-align:right;}
.doc-body h1[id],.doc-body h2[id],.doc-body h3[id],.doc-body h4[id]{scroll-margin-top:96px;}
/* code review 2026-08-30(第24轮):5 篇政策页的静态兜底 h1 各自手打 style="margin:0",
   md.js/md.ts 渲染 h1 时又各自把这串内联样式重复写成字符串字面量——4 处手打+2 处硬编码
   共 6 个地方要保持一致,不如直接收进共享规则一次到位。跟全站其它 .page-title 用法
   (product.html 用的是不同的 margin-top:6px)分开,只在 .doc-body 上下文里生效,
   product.html 不受影响 */
.doc-body .page-title{margin:0;}
/* code review 2026-08-30(第22轮):此前注释写"对齐旧静态版 p.mono 小号灰字版式"——与实际
   CSS 不符,.mono 是 text-transform:uppercase + letter-spacing:.22em,doc-sub 既不大写也
   字距更窄,两者观感明显不同,注释误导后来维护者。doc-sub 真正对齐的目标其实是 md.js 里
   -# 指令自己渲染出的同一个 class(见 md.js headings 的 "-#" 分支),两处样式要保持一致
   才不会在注水瞬间(静态 HTML → MyoMd.render 输出替换)出现可见的版式跳变,不是在还原
   旧 p.mono 的视觉效果 */
.doc-body .doc-sub{font-family:var(--mono);font-size:11.5px;letter-spacing:.08em;color:var(--ink-faint);margin:6px 0 clamp(20px,2.2vw,34px);}
/* code review 2026-08-30(第22轮):深链纠正(见 api.js hydratePolicy)给注水后的目标标题
   补了 tabindex="-1" + focus(),但全站没有针对 .doc-body 内可编程聚焦元素的 outline 样式,
   触发时会露出浏览器默认焦点框(观感与站点其余自定义 focus 样式不一致)。跟 .field
   input:focus(site.css:266)同款配色,统一走 --blue 强调色 */
.doc-body [tabindex="-1"]:focus{outline:2px solid var(--blue);outline-offset:4px;border-radius:2px;}
@media(max-width:780px){.doc{grid-template-columns:1fr;}.doc-toc{display:none;}}
/* code review 2026-08-29(第20轮):政策文档(隐私/条款/Cookie 等)是最可能被顾客打印/存 PDF
   的页面类型,此前全站没有任何 @media print 规则——.doc-toc 的 position:sticky 在打印
   引擎里表现不一致,.doc 的 grid 分栏在分页时可能裁切内容,240px 侧栏在纸面上也没有意义。
   打印时侧栏收起、正文占满宽度 */
@media print{.doc-toc,.nav,.nav-burger,.site-footer{display:none;}.doc{grid-template-columns:1fr;}.doc-body{max-width:none;}}

/* accordion (FAQ) */
.acc details{border:1px solid var(--line);border-radius:var(--r);background:var(--paper);margin-bottom:12px;overflow:hidden;}
.acc summary{list-style:none;cursor:pointer;padding:18px 22px;font-family:var(--display);font-size:20px;color:var(--ink);display:flex;align-items:center;justify-content:space-between;gap:16px;}
.acc summary::-webkit-details-marker{display:none;}
.acc summary .ic{width:20px;height:20px;flex:0 0 auto;transition:transform .28s cubic-bezier(.34,1.56,.64,1),color .2s;color:var(--ink-faint);}
.acc details[open] summary .ic{transform:rotate(180deg);color:var(--blue);}
.acc details[open] summary{border-bottom:1px solid var(--line-soft);}
.acc .acc-body{padding:18px 22px 22px;color:var(--ink-soft);font-size:16px;line-height:1.7;background:var(--cream);box-shadow:inset 0 2px 4px -2px rgba(60,45,25,.14);}

/* ===================== EMPTY STATE ===================== */
.empty{text-align:center;padding:clamp(40px,6vw,80px) 20px;}
.empty .seal{width:96px;height:96px;margin:0 auto 22px;color:var(--stamp-blue);opacity:.5;}
.empty h3{font-family:var(--display);font-size:28px;margin-bottom:10px;}
.empty p{color:var(--ink-soft);margin-bottom:24px;}

/* ===================== NOTICE / ALERT ===================== */
.notice[hidden]{display:none;}
.notice{display:flex;gap:14px;align-items:flex-start;padding:16px 18px;border-radius:var(--r);border:1px solid var(--line);background:var(--paper);font-size:15px;color:var(--ink-soft);}
.notice svg{width:20px;height:20px;flex:0 0 auto;margin-top:2px;}
.notice-blue{border-color:#bcc6df;background:rgba(86,104,158,.08);}
.notice-gold{border-color:#d9c191;background:rgba(169,130,78,.1);}

/* ===================== FOOTER ===================== */
.site-footer{
  position:relative;margin-top:auto;
  background:linear-gradient(180deg,#f8f2e5,#f5edda);border-top:1px solid #E3D2B8;
  box-shadow:inset 0 11px 20px -16px rgba(90,69,47,.34);
  font-family:var(--text);color:#6F5D4B;overflow:hidden;
}
/* footer 花朵水印已移除(用户要求) */
.site-footer .lane{position:relative;z-index:1;max-width:none;padding-top:clamp(30px,3vw,46px);}
.ftr-top{display:flex;align-items:center;justify-content:space-between;gap:24px 40px;flex-wrap:nowrap;padding-bottom:clamp(22px,2.4vw,36px);}
.ftr-name{display:inline-flex;align-items:center;gap:11px;font-family:var(--display);font-weight:600;font-size:clamp(28px,2.4vw,42px);color:#5A452F;line-height:1;}
.ftr-name img{width:clamp(20px,1.6vw,30px);transform:translateY(3px);}
.ftr-brand{display:flex;align-items:center;gap:clamp(16px,1.7vw,28px);flex-wrap:wrap;min-width:0;}
.ftr-rule-v{width:1px;height:clamp(22px,2vw,32px);background:#E3D2B8;}
.ftr-tag{font-style:italic;font-size:clamp(15px,1.15vw,20px);color:#6F5D4B;}
.ftr-links{display:flex;align-items:center;gap:clamp(20px,2.4vw,40px);flex-wrap:nowrap;justify-content:flex-end;flex:0 0 auto;}
.ftr-links a{display:inline-flex;align-items:center;gap:9px;font-size:clamp(15px,1.1vw,18px);color:#6F5D4B;transition:color .2s;}
.ftr-links a svg{width:1.1em;height:1.1em;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;opacity:.82;}
.ftr-links a:hover{color:#B8955E;}
.ftr-bottom{display:flex;align-items:center;justify-content:space-between;gap:clamp(16px,3vw,48px);flex-wrap:wrap;border-top:1px solid #E3D2B8;padding:clamp(15px,1.4vw,21px) 0 clamp(18px,1.8vw,26px);font-size:clamp(13px,.98vw,16px);}
.ftr-legal{display:flex;align-items:center;gap:clamp(10px,1vw,16px);flex-wrap:wrap;}
.ftr-legal .sep{color:#c2ae84;}
.ftr-legal a{padding-bottom:2px;background:linear-gradient(#cbb78f,#cbb78f) left 100%/100% 1px no-repeat;transition:color .2s;}
.ftr-legal a:hover{color:#B8955E;background-image:linear-gradient(#B8955E,#B8955E);}
/* 页脚分隔符「·」在**能换行的宽度下一律不显示**(2026-09-13 第二次修正)。

   为什么不是"把分隔符挂到链接上":上一版把它改成 `a:not(:last-of-type)::after`,
   以为伪元素跟着链接走就不会被拆开 —— **那是错的,而且实测过才发现**。
   伪元素确实跟着链接走,可它跟的是**前一个**链接,于是换行后行尾变成
   「Cookie Policy ·」,那个点还在原地,只是从独立 flex item 变成了链接盒子的一部分
   (实测 about.html @390px:链接盒子右 323.9 / 文字右 309.5,差 14.3px 就是它)。
   挂到后一个链接(`a + a::before`)也一样,只是从行尾挪到行首。
   **CSS 无从知道行在哪断,任何绑在某个链接上的分隔符都会在断点处露出来。**

   所以改成:能换行就不显示。实测换行区间只有一段 —— about.html 320–440px、
   index.html 320–448px(全宽度扫描,>448 一直是一行),断点取 480px 留足余量。
   窄屏下把 gap 调大到 18px 顶替分隔符的视觉分隔作用。

   分隔符退回真实的 <span class="sep">(不再用伪元素),顺带解掉两个副作用:
   · 伪元素在链接盒子内,会把 .ftr-legal a 那条 1px 下划线一起拖长 ~14px,
     前三条链接的下划线因此比第四条长一截,点还成了链接热区的一部分;
   · `content:"\00b7" / ""` 的空 alt 语法要 Chrome 77+/Safari 17.4+/Firefox 133+,
     老引擎整条声明作废 —— 而 .sep 又是 display:none,结果是分隔符**彻底消失**。
   真实 span 没有这两个问题;屏幕阅读器的问题用 aria-hidden="true" 解决
   (此前只有 index.html 加了,其余 27 页会念出来,本次一并补齐)。 */
@media(max-width:480px){.ftr-legal{gap:18px;}.ftr-legal .sep{display:none;}}

.ftr-ref{font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:#a08c6a;}
@media(max-width:760px){.ftr-top{flex-wrap:wrap;flex-direction:column;align-items:flex-start;gap:18px;}.ftr-bottom{flex-direction:column;align-items:flex-start;gap:18px;}.ftr-links{justify-content:flex-start;flex-wrap:wrap;}}

/* 全局键盘与减少动画规则由 accessibility.css 统一提供。 */

/* ── #2 加购飞入购物车动画(飞行元素由 JS 克隆走 WAAPI;reduce 模式 JS 直接跳过) ── */
.myo-fly{position:fixed;z-index:2000;width:46px;height:46px;border-radius:50%;background:var(--blue) center/cover no-repeat;box-shadow:0 6px 16px rgba(60,45,25,.35),inset 0 0 0 2px #ffffff99;pointer-events:none;will-change:transform,opacity;}
@keyframes myoBagBump{0%{transform:none;}30%{transform:scale(1.3) translateY(-2px);}60%{transform:scale(.9);}100%{transform:none;}}
.nav-icons a.bag-bump{animation:myoBagBump .45s cubic-bezier(.34,1.56,.64,1);}

/* ── #8 未登录 header:Log in / Sign up 按钮 ── */
/* auth 判定前隐藏 header 动作区(保留占位不抖动),判定后淡入,消除图标先闪后变 */
.nav-icons:not(.auth-ready),.v8icons:not(.auth-ready){visibility:hidden;}
.nav-icons.auth-ready,.v8icons.auth-ready{animation:navAuthIn .25s ease both;}
@keyframes navAuthIn{from{opacity:0}to{opacity:1}}
.nav-icons[data-guest]{gap:clamp(8px,.8vw,12px);}
/* 作用域用 .nav-icons 提权:按钮注入在 .nav-icons 内,容器规则 .nav-icons a(0,1,1)会压过裸 .nav-auth(0,1,0),
   导致 fill 文字被强制成 ink、hover 时文字与背景同为 blue-deep 而消失。故这四条一律带 .nav-icons 前缀。 */
.nav-icons .nav-auth{display:inline-flex;align-items:center;font-family:var(--text);font-size:clamp(13px,1vw,15px);font-weight:600;letter-spacing:.01em;padding:8px 16px;border-radius:999px;color:var(--ink);border:1px solid var(--line);white-space:nowrap;transition:background .2s,color .2s,border-color .2s,transform .2s;}
.nav-icons .nav-auth:hover{border-color:var(--blue);color:var(--blue-deep);transform:translateY(-1px);}
.nav-icons .nav-auth--fill{background:var(--blue);color:#fdf8ec;border-color:var(--blue);}
.nav-icons .nav-auth--fill:hover{background:var(--blue-deep);color:#fff;transform:translateY(-1px);}

/* ── #5 profile:email 只读字段(即使 edit 态也明确不可编辑,虚线框+浅灰+禁用光标) ── */
.field-locked input,.field-locked input:disabled{background:var(--cream,#f4efe3);color:var(--ink-faint);-webkit-text-fill-color:var(--ink-faint);cursor:not-allowed;border-style:dashed!important;opacity:1;}
.field-locked > label{color:var(--ink-faint);}
.lock-tag{text-transform:none;letter-spacing:0;font-size:11px;color:var(--ink-faint);font-style:italic;}
