@import url('tokens/colors.css');
@import url('tokens/typography.css');
@import url('tokens/spacing.css');
@import url('tokens/breakpoints.css');
@import url('tokens/effects.css');
@import url('tokens/fonts.css');
*{margin:0;padding:0;box-sizing:border-box}
html{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
body{font-family:var(--font-sans);font-size:var(--t-body);line-height:var(--lh-body);color:var(--ink);background:var(--paper)}
::selection{background:var(--sage);color:var(--ink)}

/* ---- Links ---- */
a{color:var(--sage-deep);text-decoration-thickness:1px;text-underline-offset:3px}
a:hover{color:var(--ink)}

/* ---- Focus. Never removed. ---- */
a:focus-visible,button:focus-visible,summary:focus-visible,[tabindex]:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:none;box-shadow:var(--focus)}

/* ---- Skip link. First focusable element on every page. ---- */
.ds-skip{position:absolute;left:-9999px;top:0;z-index:100;padding:14px 22px;background:var(--ink);color:var(--paper);border-radius:0 0 var(--r-sm) 0;font-size:var(--t-body-sm);font-weight:600;text-decoration:none}
.ds-skip:focus{left:0}
/* ---- Media bands. Inside a band the on-dark pair is lifted to the on-media pair, so
   any component's onDark prop gets the brighter white a moving image needs. ---- */
[data-media-band]{--on-dark:var(--on-media);--on-dark-mut:var(--on-media-mut)}

/* Offscreen text. For the rare case a decorative layer carries meaning the copy does not (MediaSection's alt). */
.ds-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* ---- Grid. The documented collapse order. Consumers never write repeat(3,1fr). ---- */
.ds-grid{display:grid;gap:var(--s-5)}
.ds-grid[data-cols="2"]{grid-template-columns:repeat(2,minmax(0,1fr))}
.ds-grid[data-cols="3"]{grid-template-columns:repeat(3,minmax(0,1fr))}
.ds-grid[data-cols="4"]{grid-template-columns:repeat(4,minmax(0,1fr))}
.ds-grid[data-cols="split"]{grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(32px,5vw,72px);align-items:center}
@media (max-width:1120px){.ds-grid[data-cols="4"]{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:880px){.ds-grid[data-cols="3"]{grid-template-columns:repeat(2,minmax(0,1fr))}.ds-grid[data-cols="split"]{grid-template-columns:minmax(0,1fr)}}
@media (max-width:620px){.ds-grid[data-cols="2"],.ds-grid[data-cols="3"],.ds-grid[data-cols="4"]{grid-template-columns:minmax(0,1fr)}}

/* ---- Flow. Vertical rhythm as a container, not a per-element decision.
   Every rule is written twice, because a wrapper can sit between the stack and its
   real blocks: the Design Component runtime inserts a div.sc-host-x per child with
   display:contents, which takes no margin of its own and hides the real Tag,
   Heading, Body or Button from an adjacency selector. So each rule pierces one level
   in both directions. Looking back: a block counts as a tag, heading, media or
   action when it carries data-flow itself or holds it as its only element child.
   Looking forward: the gap lands on the real element when the next child is a mount
   host. Any inline margin an author sets still wins, and Card supplies
   .ds-flow[data-card] itself. ---- */
.ds-flow>*,.ds-flow>[class*="sc-host"]>:only-child{margin-top:var(--flow-para)}
.ds-flow>:first-child,.ds-flow>:first-child[class*="sc-host"]>:only-child{margin-top:0}
.ds-flow>:where(h1,h2,h3,h4,h5,h6,:has(>:only-child:where(h1,h2,h3,h4,h5,h6)))+*,.ds-flow>:where(h1,h2,h3,h4,h5,h6,:has(>:only-child:where(h1,h2,h3,h4,h5,h6)))+[class*="sc-host"]>:only-child{margin-top:var(--flow-heading)}
.ds-flow>:where([data-flow="media"],figure,img,picture,video,:has(>:only-child:where([data-flow="media"],figure,img,picture,video)))+*,.ds-flow>:where([data-flow="media"],figure,img,picture,video,:has(>:only-child:where([data-flow="media"],figure,img,picture,video)))+[class*="sc-host"]>:only-child{margin-top:var(--flow-media)}
.ds-flow>:where([data-flow="tag"],:has(>:only-child[data-flow="tag"]))+*,.ds-flow>:where([data-flow="tag"],:has(>:only-child[data-flow="tag"]))+[class*="sc-host"]>:only-child{margin-top:var(--card-tag)}
.ds-flow>[data-flow="action"],.ds-flow>[class*="sc-host"]:has(>:only-child[data-flow="action"])>:only-child{margin-top:var(--flow-action)}
.ds-flow[data-card]>:where(h1,h2,h3,h4,h5,h6,:has(>:only-child:where(h1,h2,h3,h4,h5,h6)))+*,.ds-flow[data-card]>:where(h1,h2,h3,h4,h5,h6,:has(>:only-child:where(h1,h2,h3,h4,h5,h6)))+[class*="sc-host"]>:only-child{margin-top:var(--card-title)}
.ds-flow[data-card]>:where([data-flow="tag"],[data-flow="media"],:has(>:only-child:where([data-flow="tag"],[data-flow="media"])))+*,.ds-flow[data-card]>:where([data-flow="tag"],[data-flow="media"],:has(>:only-child:where([data-flow="tag"],[data-flow="media"])))+[class*="sc-host"]>:only-child{margin-top:var(--card-tag)}
.ds-flow>[class*="sc-host"]{margin-top:0}

/* ---- Reveal. Fade and rise, once, on enter. ---- */
.ds-reveal{opacity:0;transform:translateY(18px);transition:opacity var(--slow) var(--ease),transform var(--slow) var(--ease)}
.ds-reveal.is-in{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
.ds-reveal{opacity:1;transform:none}
}
