/* ccshan · base: reset, links, scrolling, page transitions, reduced motion */
*,*::before,*::after{box-sizing:border-box}
body{margin:0;font-family:var(--font);color:var(--ink);background:var(--bg);line-height:1.5;-webkit-font-smoothing:antialiased;
  text-spacing-trim:space-all}   /* full-width CJK punctuation, as Figma sets it (Chrome would otherwise squeeze 「）。」) */
img{max-width:100%;display:block;height:auto}
a{color:inherit;text-decoration:none;transition:opacity var(--motion-duration-fast) var(--ease-standard)}
/* bare text links only; components define their own states in ui.css */
@media (hover:hover){a:where(:not([class])):hover{opacity:.72}}
a:where(:not([class])):active{opacity:.72;transition-duration:var(--motion-duration-instant)}
a:focus-visible,button:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.skip-link{position:absolute;left:-9999px;top:auto}
.skip-link:focus{left:16px;top:16px;z-index:100;background:#fff;padding:8px 12px;border:1px solid #ccc}

/* In-page anchors land below the sticky header (+ case chapter nav) */
html:has(.case-subnav){--subnav-h:var(--case-subnav-h)}
html{scroll-padding-top:calc(var(--header-h) + var(--subnav-h, 0px) + 12px)}
@media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}

/* ---------- Page transitions: cross-document View Transitions (Chrome / Edge 126+, Safari 18.2+) ----------
 * Desktop / tablet: the page cross-fades, 450ms emphasized. Mobile: push — the new page slides in from the right
 * (from the left when going back; js/transitions.js tags back navigations). The header has its own
 * view-transition-name, so it stays put while the content changes. Other browsers navigate normally. */
@view-transition{navigation:auto}
.site-header{view-transition-name:site-header}
::view-transition-group(root){animation-duration:var(--motion-duration-page);animation-timing-function:var(--ease-emphasized)}
::view-transition-old(root),::view-transition-new(root){animation-duration:var(--motion-duration-page);animation-timing-function:var(--ease-emphasized)}
::view-transition-group(site-header){animation:none;z-index:2}
::view-transition-old(site-header){display:none}
::view-transition-new(site-header){animation:none}
@media (max-width:767px) and (prefers-reduced-motion:no-preference){
  ::view-transition-old(root){animation-name:vt-push-out}
  ::view-transition-new(root){animation-name:vt-push-in}
  html:active-view-transition-type(back)::view-transition-old(root){animation-name:vt-push-out-back}
  html:active-view-transition-type(back)::view-transition-new(root){animation-name:vt-push-in-back}
}
@keyframes vt-push-in{from{transform:translate3d(100%,0,0)}}
@keyframes vt-push-out{to{transform:translate3d(-30%,0,0);opacity:.6}}
@keyframes vt-push-in-back{from{transform:translate3d(-30%,0,0);opacity:.6}}
@keyframes vt-push-out-back{to{transform:translate3d(100%,0,0)}}

/* ---------- Reduced motion: one switch for the whole site ----------
 * Components already gate movement (reveal, parallax, intro, hover scale) behind no-preference; this is the
 * safety net: nothing moves, and what remains is a short opacity change (≤ 200ms). */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-delay:0s!important;transition-delay:0s!important}
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation-duration:var(--motion-duration-fast)!important}
}
