/* The castomo family shelf under the footer, and the Pop animation on the dash-b mark.
   Ported from castomapi.com / castomflow.com (assets/site.css there) and restated in this site's own
   tokens (--surface, --border, --text, --sub, --muted, --lift, --accent-warm). Linked from
   pages/_shell.html and index.html, so the front page and every sub-page share one copy.

   The shelf: large rounded tiles in ONE row that scrolls sideways and snaps tile by tile, starting at
   the content column and running out to both window edges (after apple.com's product shelves). Every
   tile links straight to that product's own website. Without assets/family.js it is a native
   scrolling row; family.js makes it circular, adds the arrows (.shelf-nav) and the faint background
   mark (.shelf-bg). */

/* `overflow-x: clip` because the row bleeds to the window edges and 100vw counts the scrollbar. */
footer { overflow-x: clip; }

.foot-family { position: relative; padding-block: clamp(32px, 5vw, 48px) 8px; border-block-start: 1px solid var(--border-soft); }
.foot-family h2 { font-size: clamp(1.6rem, 3vw, 2.2rem); font-weight: 700; line-height: 1.15; letter-spacing: -.025em; color: var(--text); margin: 0 0 clamp(16px, 2.5vw, 28px); text-wrap: balance; }
.foot-family h2 span { color: var(--muted); }
/* The negative margin pulls the row out of the content column; the same amount as padding puts the
   first tile back on it, and scroll-padding makes every snap land a tile on that line. The vertical
   padding leaves room for the hover lift and its shadow. */
.foot-family ul { display: flex; gap: 20px; list-style: none; margin: 0 calc(50% - 50vw); padding: 12px calc(50vw - 50%) 28px; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-padding-inline: calc(50vw - 50%); scrollbar-width: none; }
.foot-family ul::-webkit-scrollbar { display: none; }
.foot-family li { flex: 0 0 min(372px, 82vw); margin: 0; scroll-snap-align: start; }

/* One link per tile. Grid rows: the name as a small uppercase eyebrow, the line as the headline, the
   mark large below, the domain as a pill at the foot. The mark is aria-hidden. */
.foot-family a { position: relative; display: grid; grid-template-rows: auto auto 1fr auto; justify-items: start; height: 100%; min-height: clamp(380px, 50vh, 460px); padding: clamp(24px, 3vw, 34px); overflow: hidden; color: var(--sub); text-decoration: none; background: var(--surface); border: 1px solid var(--border); border-radius: calc(var(--radius) * 1.5); transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease; }
.foot-family b { grid-row: 1; font-size: .82rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.foot-family span { grid-row: 2; margin-top: 10px; font-size: 1.45rem; font-weight: 700; line-height: 1.2; letter-spacing: -.02em; color: var(--text); text-wrap: balance; }
.foot-family svg { grid-row: 3; align-self: center; justify-self: center; width: clamp(96px, 11vw, 132px); height: auto; aspect-ratio: 1; margin: 24px 0; }
.foot-family small { grid-row: 4; display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; border: 1px solid var(--border); border-radius: 999px; font-size: .88rem; font-weight: 600; line-height: 1.2; color: var(--sub); transition: background-color .25s ease, border-color .25s ease, color .25s ease; }

/* Hover and keyboard focus, never an underline: the tile lifts, a line in the BRAND'S colour draws
   across its top (each tile carries --hue inline, from the brand kit), and the domain pill fills
   with that colour while its arrow nudges forward. The site's warm accent is the fallback. */
.foot-family a:hover, .foot-family a:focus-visible { text-decoration: none; transform: translateY(-4px); box-shadow: var(--lift); border-color: var(--hue, var(--accent-warm)); }
.foot-family a::before { content: ""; position: absolute; inset-block-start: 0; inset-inline: 0; height: 3px; background: var(--hue, var(--accent-warm)); transform: scaleX(0); transform-origin: 0 50%; transition: transform .25s ease; pointer-events: none; }
.foot-family a:hover::before, .foot-family a:focus-visible::before { transform: scaleX(1); }
.foot-family small::after { content: ""; display: inline-block; flex: none; width: .9em; height: .9em; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center / contain no-repeat; transition: transform .25s ease; }
.foot-family a:hover small, .foot-family a:focus-visible small { background: var(--hue, var(--accent-warm)); border-color: var(--hue, var(--accent-warm)); color: var(--bg); }
/* The pill's text follows its fill: OKLCH lightness below .58 writes white, above writes black. */
@supports (color: oklch(from red l c h)) {
  .foot-family a:hover small, .foot-family a:focus-visible small { color: oklch(from var(--hue, var(--accent-warm)) clamp(0, (.58 - l) * 1000, 1) 0 0); }
}
.foot-family a:hover small::after, .foot-family a:focus-visible small::after { transform: translateX(3px); }
/* The contrast style keeps one high-contrast accent, so brand colours give way to it and the
   background mark (a tint) is dropped. `!important` because --hue arrives as an inline style. */
:root[data-theme="contrast"] .foot-family a { --hue: var(--accent-warm) !important; }
:root[data-theme="contrast"] .foot-family .shelf-bg { display: none; }

/* The tile's own mark again, large and faint, turned and pushed off the bottom corner. family.js adds
   it; every other child of the link is positioned, so they paint above it. */
.foot-family .shelf-bg { position: absolute; inset-block-end: -18%; inset-inline-end: -18%; width: 74%; height: auto; aspect-ratio: 1; margin: 0; opacity: .08; transform: rotate(-14deg); transition: transform .6s ease, opacity .25s ease; pointer-events: none; }
.foot-family a > :not(.shelf-bg) { position: relative; }
.foot-family a:hover .shelf-bg, .foot-family a:focus-visible .shelf-bg { opacity: .14; transform: rotate(-6deg) scale(1.06); }

/* The two arrow buttons family.js adds. The row is circular, so neither is ever disabled. */
.shelf-nav { display: flex; justify-content: flex-end; gap: 12px; }
.shelf-nav button { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 1px solid var(--border); border-radius: 999px; background: var(--surface-2); color: var(--text); cursor: pointer; transition: background-color .25s ease, color .25s ease; }
.shelf-nav button::before { content: ""; width: 18px; height: 18px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E") center / contain no-repeat; }
.shelf-nav .shelf-prev::before { transform: scaleX(-1); }
[dir="rtl"] .shelf-nav .shelf-prev::before { transform: none; }
[dir="rtl"] .shelf-nav .shelf-next::before { transform: scaleX(-1); }
.shelf-nav button:hover { background: var(--text); color: var(--bg); }
@media (max-width: 600px) {
  .foot-family ul { gap: 12px; }
  .foot-family a { min-height: 340px; }
}

/* Marks pop on hover, after the brand kit's "Draw — Pop" cut (kupisiewicz/brand-kit): each tile of a
   mark pops in from 45% with a small overshoot, one after another, and settles — once per hover. The
   dash-b wordmark's tiles are the direct children of its <svg>; a family tile's mark likewise, with
   the faint background copy (.shelf-bg) left out. None of these shapes carries its own transform
   attribute, which a CSS transform would override. The hover rules set longhands so the per-tile
   delays below survive. The reduced-motion rule in pages.css collapses the animation to nothing. */
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > * { transform-box: fill-box; transform-origin: center; }
:is(.wordmark:hover, .wordmark:focus-visible) svg > *, :is(.foot-family a:hover, .foot-family a:focus-visible) > svg:not(.shelf-bg) > * {
  animation-name: mk-pop; animation-duration: .64s; animation-timing-function: cubic-bezier(.2, .7, .3, 1); animation-fill-mode: both;
}
@keyframes mk-pop {
  0% { opacity: 0; transform: scale(.45); }
  70% { opacity: 1; transform: scale(1.08); }
  100% { opacity: 1; transform: scale(1); }
}
/* Tile k of n starts (k-1) × 0.42 s / (n-1) after the hover begins; marks of up to five tiles. */
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(2):nth-last-child(1) { animation-delay: .42s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(2):nth-last-child(2) { animation-delay: .21s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(3):nth-last-child(1) { animation-delay: .42s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(2):nth-last-child(3) { animation-delay: .14s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(3):nth-last-child(2) { animation-delay: .28s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(4):nth-last-child(1) { animation-delay: .42s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(2):nth-last-child(4) { animation-delay: .105s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(3):nth-last-child(3) { animation-delay: .21s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(4):nth-last-child(2) { animation-delay: .315s; }
:is(.wordmark svg, .foot-family a > svg:not(.shelf-bg)) > :nth-child(5):nth-last-child(1) { animation-delay: .42s; }
