/* Garden motion: the storefront as a garden that grows with the order.
   Loaded after redesign.css and owned by it for tokens (--ink, --paper, --citron, --muted, --line, --ease-out).
   House rules hold: ink, citron and paper only, thin strokes, no shadows, exponential ease-out, and motion that
   stays on transform, opacity and clip-path in small areas. Everything that moves sits inside
   prefers-reduced-motion: no-preference and has a still, readable state without it.
   Concept map, timings and the list of what was left still: docs/design/garden-motion.md. */

:root {
  --dir: 1;
  --ease-in-out: cubic-bezier(.77, 0, .175, 1);
  --swing: cubic-bezier(.37, 0, .63, 1);
  --sprout: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21V11'/%3E%3Cpath d='M12 14C8 14 5.5 11.5 5.5 8c3.5 0 6.5 2 6.5 6Z'/%3E%3Cpath d='M12 11c0-3.5 2.5-6 6.5-6 0 3.5-2.5 6-6.5 6Z'/%3E%3Cpath d='M7 21h10'/%3E%3C/svg%3E");
  --flower: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 8C7-2 0 8 7 12c-7 5 3 12 5 5 3 7 13-1 5-5 8-4 0-14-5-4Z'/%3E%3Ccircle cx='12' cy='12' r='2'/%3E%3C/svg%3E");
  --check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7'/%3E%3C/svg%3E");
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  --leaf-ok: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M20 3C8 2 2 9 7 16c7 5 14-1 13-13Z' fill='%23fef145' stroke='%23370338' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='m8.5 13 2.5 2.5 5-6' stroke='%23370338' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
:root:dir(rtl) { --dir: -1; }

/* 1 · Waiting is sprouting. A stem rises, two leaves open, the sprout rests, and it starts again. */
.button[aria-busy=true] { cursor: progress; }
.button[aria-busy=true]:disabled { opacity: .9; }
.button[aria-busy=true] > .zf-icon { display: none; }
.button[aria-busy=true]::after,
[data-basket-items][aria-busy=true]::before,
[data-advisor-results][aria-busy=true]::before,
.builder:not([data-ready]) .builder-status:not([data-tone=error])::before {
  content: ""; flex: none; display: inline-block; inline-size: 1.3em; block-size: 1.3em;
  background: currentColor; -webkit-mask: var(--sprout) center / contain no-repeat; mask: var(--sprout) center / contain no-repeat;
}
[data-basket-items][aria-busy=true] { display: grid; justify-items: center; gap: .5rem; padding-block: 1.25rem; color: var(--muted); text-align: center; }
[data-basket-items][aria-busy=true]::before { inline-size: 2.6rem; block-size: 2.6rem; color: var(--ink); }
[data-advisor-results][aria-busy=true] { position: relative; }
[data-advisor-results][aria-busy=true]::before { position: absolute; inset-block-start: 1rem; inset-inline: 0; margin-inline: auto; inline-size: 2.6rem; block-size: 2.6rem; color: var(--ink); z-index: 1; }
[data-advisor-results][aria-busy=true] > * { opacity: .4; }
.builder:not([data-ready]) .builder-status:not([data-tone=error])::before { vertical-align: -.3em; margin-inline-end: .5rem; }
.studio-preview:has([data-studio-generate][aria-busy=true]) [data-studio-status]::before {
  content: ""; display: inline-block; inline-size: 1.5em; block-size: 1.5em; vertical-align: -.4em; margin-inline-end: .5rem;
  background: var(--ink); -webkit-mask: var(--flower) center / contain no-repeat; mask: var(--flower) center / contain no-repeat;
}
@media (prefers-reduced-motion: no-preference) {
  .button[aria-busy=true]::after, [data-basket-items][aria-busy=true]::before, [data-advisor-results][aria-busy=true]::before,
  .builder:not([data-ready]) .builder-status:not([data-tone=error])::before { animation: sprout-rise 1150ms var(--ease-out) infinite; }
  .studio-preview:has([data-studio-generate][aria-busy=true]) [data-studio-status]::before { animation: flower-open 1900ms var(--ease-out) infinite; }
  @keyframes sprout-rise { 0% { clip-path: inset(100% 0 0 0); opacity: 1; } 55%, 84% { clip-path: inset(0); opacity: 1; } 100% { clip-path: inset(0); opacity: 0; } }
  @keyframes flower-open { 0% { scale: .5; rotate: -40deg; opacity: 0; } 40% { opacity: 1; } 65%, 85% { scale: 1; rotate: 0deg; opacity: 1; } 100% { scale: 1; rotate: 12deg; opacity: 0; } }
}
@media (prefers-reduced-motion: reduce) {
  .button[aria-busy=true]::after, [data-basket-items][aria-busy=true]::before, [data-advisor-results][aria-busy=true]::before,
  .builder:not([data-ready]) .builder-status:not([data-tone=error])::before { animation: sprout-breathe 1600ms ease-in-out infinite; }
  @keyframes sprout-breathe { 50% { opacity: .35; } }
}

/* 2 · The menu is a trellis. The button folds into two crossing stems with a bud at the crossing, the panel unrolls from it,
   a stem runs down the inline-start edge and every row puts out a leaf: a bud for a plain link, a leaf for a branch of the tree. */
.menu-icon { inline-size: 1.4em; }
.menu-icon :is(.m1, .m2, .m3, .m-bud) { transform-box: view-box; transform-origin: 12px 12px; }
.menu-icon .m-bud { fill: var(--citron); opacity: 0; scale: .4; }
.site-menu[open]:not([data-closing]) .menu-icon .m1 { transform: rotate(45deg) translateY(6px); }
.site-menu[open]:not([data-closing]) .menu-icon .m3 { transform: rotate(-45deg) translateY(-6px); }
.site-menu[open]:not([data-closing]) .menu-icon .m2 { opacity: 0; transform: scaleX(.2); }
.site-menu[open]:not([data-closing]) .menu-icon .m-bud { opacity: 1; scale: 1; }
.site-menu nav > * { position: relative; padding-inline-start: 2rem; }
.site-menu nav > *::before { content: ""; position: absolute; inset-block: 0 -1px; inset-inline-start: .6rem; inline-size: 1.5px; background: var(--line); transform-origin: top; pointer-events: none; }
.site-menu nav > a::after { content: ""; position: absolute; inset-block-start: calc(.65rem + .825em - .2rem); inset-inline-start: calc(.6rem - .2rem + .75px); inline-size: .4rem; block-size: .4rem; border-radius: 50%; background: var(--ink); pointer-events: none; }
.site-menu nav > details::after { content: ""; position: absolute; inset-block-start: calc(.5rem + 22px - .95rem); inset-inline-start: calc(.6rem + .75px); inline-size: .95rem; block-size: .95rem; border: 1px solid var(--ink); border-radius: 0 100% 0 100%; background: linear-gradient(to top right, transparent calc(50% - .5px), var(--ink) calc(50% - .5px) calc(50% + .5px), transparent calc(50% + .5px)), var(--citron); rotate: -90deg; scale: var(--dir) 1; pointer-events: none; }
.site-menu nav > details[open]::after { rotate: -62deg; scale: calc(var(--dir) * 1.15) 1.15; }
.site-menu nav summary { list-style: none; display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; }
.site-menu nav summary::-webkit-details-marker { display: none; }
.site-menu nav summary::after { content: ""; flex: none; inline-size: 1rem; block-size: 1rem; margin-block-start: .3rem; background: currentColor; -webkit-mask: var(--chevron) center / contain no-repeat; mask: var(--chevron) center / contain no-repeat; }
.site-menu nav details[open] > summary::after { rotate: 180deg; }
.site-menu nav details a::before { content: ""; display: inline-block; inline-size: .5rem; block-size: 1px; background: var(--line); vertical-align: middle; margin-inline-end: .5rem; }
.site-menu nav :is(a, summary):focus-visible { outline-offset: -3px; }
.site-menu nav > :nth-child(2) { --i: 1; } .site-menu nav > :nth-child(3) { --i: 2; } .site-menu nav > :nth-child(4) { --i: 3; } .site-menu nav > :nth-child(5) { --i: 4; }
.site-menu nav > :nth-child(6) { --i: 5; } .site-menu nav > :nth-child(7) { --i: 6; } .site-menu nav > :nth-child(8) { --i: 7; } .site-menu nav > :nth-child(9) { --i: 8; }
.site-menu nav > :nth-child(10) { --i: 9; } .site-menu nav > :nth-child(11) { --i: 10; } .site-menu nav > :nth-child(n+12) { --i: 11; }
@media (prefers-reduced-motion: no-preference) {
  .menu-icon :is(.m1, .m2, .m3) { transition: transform 240ms var(--ease-out), opacity 160ms var(--ease-out); }
  .menu-icon .m-bud { transition: scale 240ms var(--ease-out) 60ms, opacity 160ms var(--ease-out) 60ms; }
  .site-menu nav > details::after, .site-menu nav summary::after { transition: rotate 260ms var(--ease-out), scale 260ms var(--ease-out); }
  .site-menu[open] > nav { animation: menu-unroll 280ms var(--ease-out) backwards; }
  .site-menu[data-closing] > nav { animation: menu-furl 150ms var(--ease-out) both; }
  .site-menu[open]:not([data-closing]) > nav > * { animation: row-sprout 260ms var(--ease-out) backwards; animation-delay: calc(70ms + var(--i, 0) * 24ms); }
  .site-menu[open]:not([data-closing]) > nav > *::before { animation: spine-grow 220ms var(--ease-out) backwards; animation-delay: calc(40ms + var(--i, 0) * 24ms); }
  .site-menu[open]:not([data-closing]) > nav > *::after { animation: leaf-unfurl 340ms var(--ease-out) backwards; animation-delay: calc(150ms + var(--i, 0) * 24ms); }
  @keyframes menu-unroll { from { clip-path: inset(0 0 100% 0 round 12px); } to { clip-path: inset(0 0 0 0 round 12px); } }
  @keyframes menu-furl { from { clip-path: inset(0 0 0 0 round 12px); } to { clip-path: inset(0 0 100% 0 round 12px); opacity: 0; } }
  @keyframes row-sprout { from { opacity: 0; translate: 0 .45rem; } }
  @keyframes spine-grow { from { scale: 1 0; } }
  @keyframes leaf-unfurl { from { opacity: 0; scale: calc(var(--dir) * .15) .15; rotate: -160deg; } }
}
@media (prefers-reduced-motion: reduce) { .site-menu[open] > nav { animation: fade-in 120ms ease backwards; } }
@keyframes fade-in { from { opacity: 0; } }

/* 3 · Planting. A seed leaves the button for the bag, the bag catches it, and the count blooms. */
.seed-fly { position: fixed; left: 0; top: 0; z-index: 70; inline-size: 12px; block-size: 18px; pointer-events: none; border: 1px solid var(--ink); background: var(--citron); border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%; will-change: transform; }
.petal-burst { position: fixed; left: 0; top: 0; z-index: 70; inline-size: 0; block-size: 0; pointer-events: none; }
.petal-burst i { position: absolute; left: -4px; top: -8px; inline-size: 8px; block-size: 14px; border: 1px solid var(--ink); border-radius: 50% 50% 50% 50% / 70% 70% 30% 30%; background: var(--citron); }
@media (prefers-reduced-motion: no-preference) {
  .cart-link.is-catching .zf-icon-bag { animation: bag-catch 380ms var(--ease-out); }
  [data-basket-count].is-blooming { animation: badge-bloom 460ms var(--ease-out); }
  .petal-burst i { animation: petal-out 520ms var(--ease-out) both; animation-delay: calc(var(--k) * 18ms); }
  @keyframes bag-catch { 30% { transform: translateY(2px) scale(1.1, .9); } 62% { transform: translateY(-1px) scale(.96, 1.05); } }
  @keyframes badge-bloom { 0% { scale: .55; } 55% { scale: 1.22; } 100% { scale: 1; } }
  @keyframes petal-out { 0% { opacity: 1; transform: rotate(var(--a)) translateY(-2px) scale(.4); } 100% { opacity: 0; transform: rotate(var(--a)) translateY(-26px) scale(1); } }
}
@media (prefers-reduced-motion: reduce) { .petal-burst, .seed-fly { display: none; } [data-basket-count].is-blooming { animation: fade-in 200ms ease; } }

/* 4 · Arriving at the front door (home only, and only when the visitor comes from outside the site or reloads: html.zf-arrive is set
   in the head). The wordmark flower draws itself, each packet's label is pulled out from the reading side, the tags are hung and
   settle, and the corner ornament opens. One short sequence, never on scroll and never when moving around inside the site. */
@media (prefers-reduced-motion: no-preference) {
  html.zf-arrive body.home .brand-flower path { stroke-dasharray: 1 2; animation: draw 900ms var(--ease-out) backwards; }
  html.zf-arrive body.home .brand-flower circle { animation: fade-in 300ms ease 620ms backwards; }
  html.zf-arrive .world h2 span { animation: label-pull-ltr 460ms var(--ease-out) backwards; animation-delay: calc(60ms + var(--w, 0) * 110ms); }
  html.zf-arrive .world h2 span:dir(rtl) { animation-name: label-pull-rtl; }
  html.zf-arrive .world + .world { --w: 1; }
  html.zf-arrive .gift-tag { animation: tag-hang 1150ms var(--swing) 360ms backwards; }
  html.zf-arrive .world .botanical-ornament { animation: ornament-settle 720ms var(--ease-out) 220ms backwards; }
  @keyframes draw { from { stroke-dashoffset: 1.03; } to { stroke-dashoffset: 0; } }
  @keyframes label-pull-rtl { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0); } }
  @keyframes label-pull-ltr { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
  @keyframes tag-hang {
    0% { rotate: 16deg; opacity: 0; translate: 0 -.8rem; transform-origin: 50% 0; }
    16% { opacity: 1; }
    34% { rotate: -9deg; translate: 0 0; }
    54% { rotate: 5deg; }
    72% { rotate: -2.5deg; transform-origin: 50% 0; }
    100% { rotate: 0deg; transform-origin: 50% 50%; }
  }
  @keyframes ornament-settle { from { opacity: 0; scale: .9; translate: 0 .6rem; rotate: -8deg; } }
}

/* 5 · A pot with a sprout waits in every empty place. In the lost-page version the bud stays closed ("this page has not bloomed yet"). */
.empty:has(> .pot) { text-align: center; display: grid; justify-items: center; }
.empty:has(> .pot) .actions { justify-content: center; }
.pot { inline-size: clamp(6rem, 24vw, 8rem); block-size: auto; margin-block-end: 1rem; color: var(--ink); overflow: visible; }
.pot-lost { inline-size: clamp(7.5rem, 30vw, 10.5rem); }
.pot :is(.p-leaf, .p-bud > path:first-child) { fill: var(--citron); }
.pot :is(.p-stem, .p-leaf, .p-bud) { transform-box: view-box; }
.pot .p-stem { stroke-dasharray: 1 2; }
.pot .p-leaf-l { transform-origin: 60px 54px; }
.pot .p-leaf-r { transform-origin: 60px 48px; }
.pot .p-bud { transform-origin: 60px 36px; }
@media (prefers-reduced-motion: no-preference) {
  .pot .p-stem { animation: stem-up 520ms var(--ease-out) 120ms backwards; }
  .pot .p-leaf { animation: leaf-open 420ms var(--ease-out) backwards; }
  .pot .p-leaf-l { animation-delay: 520ms; }
  .pot .p-leaf-r { animation-delay: 620ms; }
  .pot .p-bud { animation: bud-rise 520ms var(--ease-out) 700ms backwards, bud-nod 1500ms var(--swing) 1400ms 2; }
  @keyframes stem-up { from { stroke-dashoffset: 1.03; } }
  @keyframes leaf-open { from { opacity: 0; scale: .2; rotate: -25deg; } }
  @keyframes bud-rise { from { opacity: 0; scale: .3; translate: 0 .4rem; } }
  @keyframes bud-nod { 25% { rotate: 4deg; } 75% { rotate: -4deg; } }
}
.basket-empty { display: grid; justify-items: center; text-align: center; padding-block: 1rem; }
.basket-empty p { margin-inline: auto; }

/* 6 · Roots. Three of them under the page, one for each generation, draw themselves once when the footer comes into view. */
.site-footer { padding-block-start: 0; }
.footer-roots { display: flex; justify-content: space-around; align-items: flex-start; margin-block-end: 2.25rem; color: var(--citron); pointer-events: none; }
.footer-roots .root { inline-size: clamp(5.25rem, 12vw, 8.5rem); block-size: auto; overflow: visible; }
.footer-roots path { stroke-dasharray: 1 2; stroke-dashoffset: 0; }
@media (prefers-reduced-motion: no-preference) {
  html.zf-js .footer-roots:not(.is-seen) path { stroke-dashoffset: 1.03; }
  .footer-roots.is-seen path { animation: root-draw 1000ms var(--ease-out) backwards; animation-delay: calc(var(--k) * 180ms + var(--j, 0) * 140ms); }
  @keyframes root-draw { from { stroke-dashoffset: 1.03; } }
}

/* 7 · The order grows. A seed, a stem, leaves, a bud, a bloom: the four steps are the four states the product keeps apart
   (saved, confirmed by the shop, paid, arrived). The step list is real text; the plant is its picture. */
.receipt-head { display: grid; gap: .25rem; }
.growth { --off: .7; display: grid; justify-items: center; gap: 1rem; margin-block: 1rem 1.25rem; }
.growth[data-stage="2"] { --off: .38; } .growth[data-stage="3"] { --off: .1; } .growth[data-stage="4"] { --off: 0; }
.growth-scene { inline-size: min(100%, 18rem); block-size: auto; aspect-ratio: 240 / 80; overflow: clip; color: var(--ink); }
.growth[data-stage="2"] .growth-scene { aspect-ratio: 240 / 108; } .growth[data-stage="3"] .growth-scene { aspect-ratio: 240 / 128; } .growth[data-stage="4"] .growth-scene { aspect-ratio: 240 / 136; }
.growth-scene :is(.g-leaf, .g-seed, .g-bud, .g-petal) { fill: var(--citron); }
.growth-scene .g-centre { fill: var(--ink); }
.growth-scene :is(.g-crumbs, .g-sepal) { stroke: var(--muted); }
.growth-scene :is(.g-soil, .g-stem) { stroke-dasharray: 1 2; stroke-dashoffset: 0; }
.growth-scene .g-stem { stroke-dashoffset: var(--off); }
.growth-scene .g-seed { transform: rotate(-24deg); }
.growth-scene .g-leaf { transform-origin: 0 0; }
.growth-scene .g-petal { transform: rotate(var(--r)); }
.growth[data-stage="1"] :is([data-from="2"], [data-from="3"], [data-at]), .growth[data-stage="2"] :is([data-from="3"], [data-at]),
.growth[data-stage="3"] [data-at="4"], .growth[data-stage="4"] [data-at="3"] { display: none; }
.growth-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .5rem; inline-size: 100%; max-inline-size: 36rem; }
.growth-steps li { display: flex; align-items: center; gap: .5rem; min-inline-size: 0; padding-block-start: .65rem; border-block-start: 4px solid var(--line); color: var(--muted); font-size: .9rem; font-weight: 700; line-height: 1.3; }
.growth-steps li:is([data-done], [aria-current]) { color: var(--ink); border-color: var(--ink); }
@container page (width < 30rem) {
  .growth-steps { gap: .35rem; }
  .growth-steps li { flex-direction: column; align-items: flex-start; gap: .4rem; font-size: .8rem; }
}
.g-mark { display: grid; place-items: center; flex: none; inline-size: 1.25rem; block-size: 1.25rem; border: 1px solid currentColor; border-radius: 50%; background: var(--paper); }
.growth-steps li[aria-current] .g-mark { background: var(--citron); border-color: var(--ink); }
.growth-steps li[data-done] .g-mark { background: var(--ink); }
.growth-steps li:not([data-done]) .g-done { display: none; }
.growth-steps li[data-done] .g-mark::after { content: ""; inline-size: .8rem; block-size: .8rem; background: var(--paper); -webkit-mask: var(--check) center / contain no-repeat; mask: var(--check) center / contain no-repeat; }
@media (prefers-reduced-motion: no-preference) {
  .growth.is-growing .g-soil { animation: stem-up 360ms var(--ease-out) backwards; }
  .growth.is-growing .g-crumbs { animation: fade-in 300ms ease 300ms backwards; }
  .growth.is-growing .g-seed { animation: seed-drop 420ms var(--ease-out) 120ms backwards; }
  .growth.is-growing .g-stem { animation: stem-up 520ms var(--ease-out) 420ms backwards; }
  .growth.is-growing .g-leaf { animation: leaf-open 420ms var(--ease-out) backwards; animation-delay: calc(640ms + var(--n) * 110ms); }
  .growth.is-growing .g-bud { transform-origin: 0 0; animation: bud-grow 460ms var(--ease-out) 880ms backwards; }
  .growth.is-growing .g-sepal { animation: fade-in 200ms ease 1100ms backwards; }
  .growth.is-growing .g-petal { animation: petal-open 520ms cubic-bezier(.34, 1.45, .64, 1) backwards; animation-delay: calc(900ms + var(--p) * 45ms); }
  .growth.is-growing .g-centre { animation: bud-grow 300ms var(--ease-out) 880ms backwards; }
  .growth.is-growing .growth-steps li[aria-current] .g-mark { animation: mark-pop 340ms var(--ease-out) 760ms backwards; }
  @keyframes seed-drop { from { opacity: 0; translate: 0 -34px; } 60% { opacity: 1; } }
  @keyframes bud-grow { from { opacity: 0; scale: .2; } }
  @keyframes petal-open { from { opacity: 0; transform: rotate(var(--r)) scale(.15); } }
  @keyframes mark-pop { from { scale: .6; } 60% { scale: 1.18; } }
}

/* 8 · Small confirmations. A success line gets a citron leaf with a check; notices and errors rise into place. */
[data-status][data-state=ok]::before { content: ""; display: inline-block; inline-size: 1.25em; block-size: 1.25em; margin-inline-end: .4em; vertical-align: -.25em; background: var(--leaf-ok) center / contain no-repeat; }
@media (prefers-reduced-motion: no-preference) {
  .error-summary:not([hidden]), [data-status]:not(:empty) { animation: note-in 220ms var(--ease-out) backwards; }
  [data-status][data-state=ok]::before { animation: leaf-open 420ms var(--ease-out) backwards; }
  @keyframes note-in { from { opacity: 0; translate: 0 .4rem; } }
}

/* 9 · Hands and light. Buttons lead the eye to where they go, a card leans toward the light, the search field puts down roots. */
.header-search { position: relative; }
.header-search::after { content: ""; position: absolute; inset-inline: 0; inset-block-end: 0; block-size: 3px; background: var(--citron); scale: 0 1; pointer-events: none; }
.header-search:focus-within::after { scale: 1 1; }
@media (prefers-reduced-motion: no-preference) {
  .header-search::after { transition: scale 280ms var(--ease-out); }
  .product-image img { transition: scale 240ms var(--ease-out); }
  :is(.button, .text-link) .zf-icon-arrow { transition: translate 220ms var(--ease-out); }
  .consent { animation: consent-in 260ms var(--ease-out) backwards; }
  @keyframes consent-in { from { opacity: 0; translate: 0 1rem; } }
}
@media (prefers-reduced-motion: no-preference) and (hover: hover) and (pointer: fine) {
  .product-card:hover .product-image img { scale: 1.03; }
  :is(.button, .text-link):hover .zf-icon-arrow { translate: calc(4px * var(--dir)) 0; }
}

/* 10 · Branches. A category opens like a stem putting out shoots; the FAQ opens the same way. Browsers without it open at once. */
.site-menu nav details, .prose details { interpolate-size: allow-keywords; }
.site-menu nav details::details-content, .prose details::details-content { block-size: 0; overflow: clip; margin-inline: -8px; padding-inline: 8px; }
.site-menu nav details[open]::details-content, .prose details[open]::details-content { block-size: auto; }
@media (prefers-reduced-motion: no-preference) {
  .site-menu nav details::details-content, .prose details::details-content { transition: block-size 260ms var(--ease-out), content-visibility 260ms allow-discrete; }
}

/* 11 · Pages hand over without a flash. Where the browser supports it every page crossfades in 160ms with no movement, and a click on a
   card morphs its picture into the product page. Only the picture is a named element: naming the header would make it slide in from
   wherever the old page was scrolled to, and would trap the open menu in a stacking context. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  .product-gallery > figure:first-child img { view-transition-name: product-hero; }
  ::view-transition-group(root) { animation-duration: 160ms; }
  ::view-transition-group(product-hero) { animation-duration: 420ms; animation-timing-function: var(--ease-out); }
}

/* 12 · Advice arrives like seedlings: the cards come up one after another. */
[data-advisor-results] > :nth-child(2) { --i: 1; } [data-advisor-results] > :nth-child(3) { --i: 2; } [data-advisor-results] > :nth-child(4) { --i: 3; }
[data-advisor-results] > :nth-child(5) { --i: 4; } [data-advisor-results] > :nth-child(6) { --i: 5; } [data-advisor-results] > :nth-child(n+7) { --i: 6; }
@media (prefers-reduced-motion: no-preference) {
  [data-advisor-results] > :is(.notice, .product-card, .small) { animation: row-sprout 300ms var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 45ms); }
}

/* 13 · Forced colours (Windows High Contrast). Chevrons, leaves and the step marks are painted with backgrounds, which that mode drops, so they are redrawn with system colours. */
@media (forced-colors: active) {
  .site-menu nav summary::after, .button[aria-busy=true]::after, [data-basket-items][aria-busy=true]::before, [data-advisor-results][aria-busy=true]::before,
  .builder:not([data-ready]) .builder-status::before, .studio-preview:has([data-studio-generate][aria-busy=true]) [data-studio-status]::before { forced-color-adjust: none; background: CanvasText; }
  .site-menu nav > a::after, .site-menu nav > details::after { forced-color-adjust: none; background: CanvasText; border-color: CanvasText; }
  .growth-steps li[data-done] .g-mark { forced-color-adjust: none; background: CanvasText; border-color: CanvasText; }
  .growth-steps li[data-done] .g-mark::after { background: Canvas; }
  .growth-steps li[aria-current] .g-mark { forced-color-adjust: none; background: Highlight; border-color: Highlight; }
  .growth-steps li:not([data-done], [aria-current]) .g-mark { background: Canvas; }
}
