/* PinkyDolly V2 · pd-v2-header
 * 从定稿原型抽出,参数已实测。⚠️ 图片/视频路径需换成 SHOPLINE CDN 地址。
 * 不要修改数值 —— 见 docs/pd-v2-brief.md
 */

/* ══ STICKY NAV ══ */
/* Was plain .nav — collided with a legacy Bootstrap-style .nav{display:flex}
   in theme.css (nav content rendered as a narrow, auto-centered cluster
   instead of a full desktop bar). Renamed to pd-v2-nav rather than patched;
   no display:block override needed now that nothing else matches it. */
.pd-v2-nav{position:fixed;top:0;left:0;right:0;z-index:60;height:var(--navh);
  background:var(--navbg);backdrop-filter:blur(16px);border-bottom:1px solid var(--line);
  transition:background .4s var(--e),border-color .4s var(--e)}
.pd-v2-nav__in{max-width:var(--maxw);margin:0 auto;height:100%;padding:0 var(--gut);
  display:flex;align-items:center;gap:26px}
.pd-v2-nav__lg{display:inline-flex;align-items:center;white-space:nowrap}
/* Real wordmark art, not the text fallback — both images render and the inactive one is
   display:none, swapped by html[data-mode] like the rest of the theme's mode-aware
   assets (fixed CTA colors on the hero use the same on/off-by-mode pattern, just with
   a different property). Sized to match the OLD text logo's overall visual size, not
   its cap-height — this is a script wordmark with flourishes (1455×520, ~2.8:1), so
   cap-height alone (16px) read far too small. 36px desktop / 30px ≤1000px (the same
   breakpoint the nav itself switches to mobile mode at). */
.pd-v2-nav__lg-img{height:36px;width:auto;display:none}
html[data-mode="dark"] .pd-v2-nav__lg-img--dark{display:block}
html[data-mode="light"] .pd-v2-nav__lg-img--light{display:block}
@media (max-width:1000px){.pd-v2-nav__lg-img{height:30px}}
/* 13.5px, not the original 12.5px — Yimei's feedback: nav/UI text reads too small
   sitewide (same round as the .cap bump in pd-v2-base.css). */
.pd-v2-nav__l{display:flex;gap:24px;font-size:13.5px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase}
.pd-v2-nav__l a{position:relative;padding:5px 0;color:var(--tx-dim);transition:color .18s}
.pd-v2-nav__l a::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;
  background:var(--act);scale:0 1;transform-origin:left;transition:scale .32s var(--e)}
.pd-v2-nav__l a.on,.pd-v2-nav__l a:hover{color:var(--tx)}
.pd-v2-nav__l a.on::after,.pd-v2-nav__l a:hover::after{scale:1 1}
.pd-v2-nav__t{margin-left:auto;display:flex;align-items:center;gap:6px;color:var(--tx-dim)}
/* .pd-v2-nav__account is an <a>, same as .pd-v2-nav__cart — neither is a <button>, so
   the element selector below never reached it (only .pd-v2-nav__cart was named
   explicitly). It had no box at all: no 40×40 size, no centering, no hover — just the
   bare 18×18 SVG sized to content, visually smaller than its three siblings and
   throwing off the gap rhythm between icon centres even though `gap` itself is
   constant (found while evening up the four header icons — search/account/mode are
   genuinely identical now, cart differs only by its badge, which is positioned
   absolutely so it doesn't add to the box). */
/* 44px, not 40px — mobile-audit tap-target floor (E2, 2026-10-11). The icon
   graphic itself stays 18x18 either way; only the surrounding hit box grows. */
.pd-v2-nav__t button,.pd-v2-nav__cart,.pd-v2-nav__account{width:44px;height:44px;display:grid;place-items:center;border-radius:var(--r);
  transition:background .18s,color .18s}
.pd-v2-nav__account:hover{background:var(--raise);color:var(--tx)}
/* Defensive addendum (not part of the deploy package). theme.css has a bare
   button{padding:10px 20px} reset — 40px horizontal padding on a 40px-wide
   button leaves 0px for content, so the search/mode icons rendered at 0
   width and were invisible (buttons that are <a>, like cart/account, aren't
   hit by this since the legacy rule only targets <button>). */
.pd-v2-nav__t button{padding:0;background:none;border:0}
.pd-v2-nav__t button:hover,.pd-v2-nav__cart:hover{background:var(--raise);color:var(--tx)}
/* Found by scripts/pd-v2-verify.mjs's prototype diff: in the prototype
   .nav__cart is a <button>, so it gets the sizing/hover rule above for
   free. Here it's deliberately an <a href=routes.cart_url
   data-pinky-cart-open> instead (real no-JS link + the cart-drawer
   component's own open hook) — an element selector can't reach it, so it
   needs the class added explicitly or it silently loses the 40×40 box,
   corner radius and hover highlight the other nav icons all get. */
.pd-v2-nav__cart{position:relative}
.pd-v2-nav__cart b{position:absolute;top:1px;right:-2px;min-width:21px;height:21px;padding:0 5px;
  background:var(--act);color:#fff;border-radius:var(--pill);font-size:13px;font-weight:800;
  display:grid;place-items:center}
.mode{width:44px;height:44px;display:grid;place-items:center;border-radius:var(--r)}
.pd-v2-nav__t button.burger{display:none}   /* 特异性要压过 .pd-v2-nav__t button */
@media (max-width:1000px){.pd-v2-nav__l{display:none}.pd-v2-nav__t button.burger{display:grid}}

/* ══ MOBILE MENU (T3 / SPEC §0.3) ══ */
/* Hidden state must win over .is-open by source order alone (no higher
   specificity available on a single class toggle), so it's declared last
   among the properties it shares with .is-open, and uses visibility
   (not display) per LESSONS L15 — the lesson from the hero's sound-icon
   bug, where a delayed opacity:0 got silently overridden by a later same-
   priority rule. The .is-open transition has no visibility delay (closes
   need the delay so the fade-out finishes before layout removes it;
   opens need to be immediately interactive). */
.pd-v2-mnav{position:fixed;z-index:59;top:var(--navh);left:0;right:0;
  background:var(--bg);border-bottom:1px solid var(--line);box-shadow:0 18px 40px rgba(0,0,0,.28);
  padding:6px var(--gut) 18px;display:grid;
  opacity:0;visibility:hidden;transform:translateY(-8px);
  transition:opacity .22s var(--e-out),transform .22s var(--e-out),visibility 0s .22s}
.pd-v2-mnav.is-open{opacity:1;visibility:visible;transform:none;
  transition:opacity .22s var(--e-out),transform .22s var(--e-out),visibility 0s}
.pd-v2-mnav a,.pd-v2-mnav__mode{display:flex;align-items:center;justify-content:space-between;min-height:52px;
  border-bottom:1px solid var(--line);font-size:15px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--tx-dim)}
.pd-v2-mnav a:last-child,.pd-v2-mnav__mode{border-bottom:0}
.pd-v2-mnav a.on{color:var(--tx)}
.pd-v2-mnav a.on::after{content:"";width:6px;height:6px;border-radius:50%;background:var(--act)}
.pd-v2-mnav a:hover,.pd-v2-mnav a:focus-visible,.pd-v2-mnav__mode:hover,.pd-v2-mnav__mode:focus-visible{color:var(--tx)}
/* E3 新加的一行:跟 .pd-v2-mnav a 共用排版,但本身是个 <button>(不是导航
   链接),清掉按钮默认样式,图标放在文字前面而不是后面的圆点位置。 */
.pd-v2-mnav__mode{width:100%;background:none;border-top:0;border-left:0;border-right:0;cursor:pointer;flex-direction:row-reverse}
.pd-v2-mnav__mode svg{width:18px;height:18px;max-width:none;flex:none;fill:none;stroke:currentColor;stroke-width:2;stroke-linejoin:round}
@media (min-width:1001px){.pd-v2-mnav{display:none}}
/* 2026-10-11 mobile audit (E3): mobile header keeps only Search / Bag / Menu
   — Account and dark mode move into the menu drawer as their own rows
   (markup above, .pd-v2-mnav__mode). Previously this only hid Account below
   400px and shrank the remaining icons to 36px to fit — both the 36px
   shrink (E2: icons must stay >=44px) and leaving Mode in the header on
   anything between 401-1000px contradicted the audit, so this now matches
   the same <=1000px breakpoint the burger itself already uses, and no
   longer shrinks anything: with only 3 icons left there's room to keep
   them at the full 44px tap target down to 320px. */
@media (max-width:1000px){
  .pd-v2-nav__account,#mode{display:none}
}

/* 15px, not the original 14px — same readability round as .cap/.pd-v2-nav__l.
   This is the one shared primary/secondary button base every page reuses.
   text-transform:none — parity audit (SPEC-parity.md) caught this cascading
   sitewide: a legacy WooCommerce-era bare `button{text-transform:uppercase}`
   rule (public/css/frontend.css and friends) was winning on every <button>
   using this class (confirmed on the homepage "Join" newsletter button;
   pd-v2-product-card.css's .p__add button had the same issue independently
   patched before this was traced to its real, shared source). No prototype
   anywhere in this theme's .btn/.pd-v2-action base ever sets uppercase. */
.pd-v2-action{position:relative;min-height:48px;padding:0 24px;display:inline-flex;align-items:center;justify-content:center;
  gap:8px;font-size:15px;font-weight:700;text-transform:none;border-radius:var(--r);border:1.5px solid transparent;
  transition:background .18s var(--e),color .18s,border-color .18s,transform 90ms}
.pd-v2-action--1{background:var(--act);color:#fff}
/* background:none is NOT a no-op default here: pd-v2-tokens.css remaps the
   legacy --pls-button-bg-color token to var(--pd-act) sitewide (Phase 1's
   rebrand of the old WooCommerce button defaults), so a bare <button> with
   no background of its own already renders solid brand-pink via that
   legacy variable, not transparent. --1/--3 never needed an explicit
   background because they want a solid fill anyway (and it happens to be
   the same pink/a different hue); --2 is the first real use of the
   outline/secondary variant anywhere in the theme, and without this line
   it silently inherited the legacy pink fill instead of its intended
   outline look (confirmed: an isolated <button class="pd-v2-action
   pd-v2-action--2"> appended straight to <body> with zero other context
   still rendered solid pink). */
.pd-v2-action--2{background:none;border-color:var(--line);color:var(--tx)}
/* --3: global outline button (SPEC-shipping-care.md "Sitewide fixes" — ported
   from the shipping/care prototypes' .btn--3, same $NAME-rename convention as
   --1/--2). Repurposes this variant number: the old solid---act2-fill --3 was
   confirmed dead code (zero matches anywhere in sections/components/templates)
   before this change, so there's no real instance to migrate off the old look. */
.pd-v2-action--3{background:transparent;border-color:var(--tx-faint);color:var(--tx)}
.pd-v2-action:active{transform:scale(.985)}
/* --1 hover used to jump straight to the full raw colour (--btn2) — exactly
   the pairing brief rule #15 names as forbidden ("never use the raw colour
   behind text"), just reached via :hover instead of the base state the rule
   was clearly written about. Contrast audit (feedback item 5) measured
   white-on-raw at 3.62–4.00:1 on real buttons ("Pick Your Type of Trouble",
   "Return to shop"). A 25% mix toward raw keeps a real brightening on hover
   (not just the same flat --act) while staying at 4.8+:1 — computed with the
   same WCAG formula the audit itself uses.
   color:#fff on that :hover rule is new, and turned out to be necessary, not
   decorative: theme.css's bare a:hover{color:var(--pls-link-hover-color)} is
   (0,1,1), and .pd-v2-action--1's own color:#fff (on the non-hover rule,
   above) is only (0,1,0) — on hover, with no hover color of its own, the legacy
   rule was winning and silently swapping this button's white text for the
   darkened-pink link-hover colour (confirmed: re-running the audit after adding
   the [class*="pd-v2-"] a:hover:not(.pd-v2-action) safety net in pd-v2-base.css
   — deliberately excluding .pd-v2-action there, see its own comment — surfaced
   this as a new failure, 1.55:1, where excluding it from that fallback simply
   exposed the original bug instead of fixing it). (0,1,1) here ties the legacy
   rule's specificity; this file loads after theme.css, so source order wins it. */
@media (hover:hover) and (pointer:fine){
  .pd-v2-action--1:hover{background:color-mix(in srgb, var(--act) 75%, var(--btn2) 25%);color:#fff}
  .pd-v2-action--2:hover{border-color:var(--tx)}
  .pd-v2-action--3:hover{border-color:var(--tx);background:var(--raise)}
}
/* Housekeeping (post-T3 review): ported from the now-deleted .pd-v2-btn
   system in pd-v2-tokens.css — that system had a real disabled/loading
   state that this one never did, confirmed dead code otherwise (zero
   references anywhere outside its own file). Disabled collapses every
   variant to the same flat, mode-aware neutral (reusing --line/--tx-faint
   rather than the dead system's fixed, light-only --pd-ink-* rgba values,
   since this live system already carries proper dark-mode tokens).
   :focus-visible is deliberately NOT ported — the sitewide
   :where(...):focus-visible rule in pd-v2-base.css already covers
   .pd-v2-action, and a second, competing focus treatment here would just
   fight it. */
.pd-v2-action:disabled,
.pd-v2-action[aria-disabled="true"]{
  cursor:not-allowed;background:var(--line);color:var(--tx-faint);border-color:var(--line)
}
/* Loading — text hides, spinner shows, button stays inert. The consuming
   component's JS must read offsetWidth and lock it as an inline style
   before toggling .is-loading, or the label swap reflows the layout
   (brief §4 "loading 状态要求"); this stylesheet can't enforce that. */
.pd-v2-action.is-loading{color:transparent;pointer-events:none}
.pd-v2-action.is-loading::after{
  content:"";position:absolute;top:50%;left:50%;width:1em;height:1em;
  margin:-.5em 0 0 -.5em;border:2px solid currentColor;border-right-color:transparent;
  border-radius:50%;animation:pd-v2-spin .6s linear infinite
}
.pd-v2-action--1.is-loading::after{color:#fff}
.pd-v2-action--2.is-loading::after,
.pd-v2-action--3.is-loading::after{color:var(--tx)}
@keyframes pd-v2-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){
  .pd-v2-action.is-loading::after{animation:none;opacity:.7}
}

/* Was plain .btn/.btn--1/.btn--2/.btn--3 — collided with theme.css's own
   generic .btn (background-color, hover color, and a higher-specificity
   .btn:not([href]):not([tabindex]) rule), which made the secondary variant
   render as a solid filled block instead of a transparent outline, and its
   text invisible on hover. Renamed to pd-v2-action rather than patched
   (and not pd-v2-btn — that name was taken at the time by an unused,
   parallel --pd-btn-* token-layer button system in pd-v2-tokens.css,
   since deleted in favour of this one being the single button system);
   both workaround rules this used to need are gone now that nothing else
   matches the class. */
.sec{max-width:var(--maxw);margin:0 auto;padding:clamp(52px,8vh,104px) var(--gut)}
.band{background:var(--surface);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;
  flex-wrap:wrap;margin-bottom:clamp(22px,4vh,42px)}
/* --act2 alone measured 2.91–3.37:1 against this page's dark-mode backgrounds —
   contrast audit (feedback item 5). It already clears 5.17+ on light, so only dark
   mode needs a swap: same mode-pairing the newsletter heading's em already uses
   (.news h2 em in pd-v2-footer.css — --main2 for dark, --act for light), just the
   purple pair instead of the pink one. --main1 measures 9.47+ against both dark
   backgrounds used sitewide. */
.head .cap{color:var(--act2);display:block;margin-bottom:10px}
html[data-mode="dark"] .head .cap{color:var(--main1)}
.more{font-size:14px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  border-bottom:2px solid var(--act);padding-bottom:4px}
/* No hover rule of its own meant .more (and .foot__mail below) fell back to
   theme.css's bare a:hover{color:var(--pls-link-hover-color)}, and pd-v2-tokens.css
   points that at color-mix(in srgb, var(--pd-act) 80%, black) — a darkened pink
   that reads fine on light backgrounds but measured 2.01:1 against dark ink
   (contrast audit, feedback item 5). Same mode-pairing as .head .cap above:
   --main2 for dark (8.3+), --act for light (already the darkened mix's own base
   color family, and already passing there). */
@media (hover:hover) and (pointer:fine){
  .more:hover{color:var(--act)}
  html[data-mode="dark"] .more:hover{color:var(--main2)}
}
