/* Selective motion and name-story treatment adopted for the production About page. */

/* Sticky keeps the header in flow with the scroll-driven page. */
.about-page .site-header { position: sticky; }
.about-main { padding-top: 0; }

/* --- the name story ----------------------------------------------------- */

.namemark { position: relative; width: min(230px, 92%); aspect-ratio: 200 / 268; overflow: visible; }
.nm-brand { position: absolute; top: 0; left: 0; width: 100%; aspect-ratio: 1; }
.nm-bracket { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; filter: brightness(0) invert(1); opacity: .88; }
.nm-bracket--left { clip-path: polygon(0 0, 49% 0, 49% 14%, 24% 32%, 24% 68%, 49% 86%, 49% 100%, 0 100%); }
.nm-bracket--right { clip-path: polygon(51% 0, 100% 0, 100% 100%, 51% 100%, 51% 86%, 76% 68%, 76% 32%, 51% 14%); }
.nm-drop { position: absolute; top: 17.96875%; left: 34.375%; width: 31.25%; height: auto; filter: brightness(0) invert(1); opacity: var(--nm-drop-o, .92); }
.nm-pool { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.nm-surface { fill: none; stroke: rgba(137, 211, 207, .4); stroke-width: 1.6; stroke-linecap: round; }
.nm-ring { fill: none; stroke: #89d3cf; stroke-width: 1.6; transform-box: fill-box; transform-origin: center; }

/* Resting state — the intact mark above still water, with one ripple already
   spread. Narrow screens, reduced motion, and no-JS all get exactly this. */
.nm-ring:nth-of-type(1) { opacity: .5; }
.nm-ring:nth-of-type(2) { opacity: .28; }
.nm-ring:nth-of-type(3) { opacity: .13; }

/* When the drop travels, the mark shows only its brackets and the water it falls
   to is the one at the closing call to action, not the one drawn here. */
.js.motion .nm-drop, .js.motion .nm-pool { display: none; }

/* Letting go, not coming apart: the brackets ease outward once and settle. This
   is the same beat in both falls, so it is not scoped to either one. */
.nm-bracket { transform-origin: center; }
.js .about-name.is-released .nm-bracket--left { animation: nm-breath-left 1.15s cubic-bezier(.22, .7, .2, 1); }
.js .about-name.is-released .nm-bracket--right { animation: nm-breath-right 1.15s cubic-bezier(.22, .7, .2, 1); }

@keyframes nm-breath-left { 0%, 100% { transform: translateX(0); } 34% { transform: translateX(-4px); } }
@keyframes nm-breath-right { 0%, 100% { transform: translateX(0); } 34% { transform: translateX(4px); } }

/* Narrow screens: the whole descent happens inside the mark, so the drop and
   the pool below it both stay drawn — the drop travels between them and the
   rings wait for it rather than sitting pre-spread. Coordinates are the mark's
   own units, which is why this needs no page geometry at all. */
.js.local .nm-drop { transform: translateY(var(--nm-drop-y, 0)); opacity: var(--nm-drop-o, 1); }
.js.local .nm-ring { opacity: 0; }
.js.local .about-name.is-landed .nm-ring { animation: nm-spread 4.2s cubic-bezier(.16, .74, .3, 1) infinite; }
.js.local .about-name.is-landed .nm-ring:nth-of-type(2) { animation-delay: 1.4s; }
.js.local .about-name.is-landed .nm-ring:nth-of-type(3) { animation-delay: 2.8s; }

@keyframes nm-spread {
  0% { opacity: 0; transform: scale(.25); }
  18% { opacity: .5; }
  100% { opacity: 0; transform: scale(1.12); }
}

/* --- the travelling drop and the water it lands in ---------------------- */

/* The drop sits below the light section it crosses, which has no background of
   its own — so the drop shows through the section box but the heading paints
   over it. That lets the drop fall straight down from the mark without landing
   on top of the type. The dark sections at either end are not raised, so the
   drop stays visible over them.
   Painting order alone is not enough: behind a heading, the drop still shows
   through the gaps between lines and letters and reads as stray punctuation.
   Elements marked [data-veil] fade it out as it crosses them — see about-motion.js. */
.dropfall { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.about-local { position: relative; z-index: 1; }
.fdrop { position: absolute; top: 0; left: 0; display: none; background: var(--drop-fill, #eaf6ff); opacity: var(--drop-opacity, 1); -webkit-mask: url("/assets/drop-in-a-bucket-drop.png") center / contain no-repeat; mask: url("/assets/drop-in-a-bucket-drop.png") center / contain no-repeat; }
.js.motion .fdrop { display: block; }

/* The closing section goes dark, matching the name story. The drop then leaves
   one dark section and lands in another, which makes the two bands read as the
   same water rather than as one stray dark stripe in a light page. Rings also
   read as water on dark and as stray geometry on white.
   The water is anchored here, so the section has to be a positioning context;
   the production stylesheet does not make it one. */
.about-contact { position: relative; background: var(--ink); }
.about-contact > div:not(.cta-water) { position: relative; z-index: 1; }
.about-contact .eyebrow { color: #89d3cf; }
.about-contact h2 { color: var(--paper); }
.about-contact .contact-panel { border-color: rgba(159, 197, 233, .24); background: #12304e; }
.about-contact .contact-panel p { color: #c3d7ea; }
.about-contact .contact-reassurance { color: #a9c2d8; }
/* Room for the water, below the closing content rather than across it. The
   conditions are the ones about-motion.js calls quiet(), plus JavaScript, so the band
   only exists where something actually lands in it. It is a media query rather
   than a class the scroll handler toggles, so it does not move under the
   reader. */
@media (min-width: 1025px) and (prefers-reduced-motion: no-preference) {
  .js .about-contact { padding-bottom: clamp(190px, 21vh, 280px); }
}

/* Ripples exist below the surface only, so nothing floats over the heading. */
.cta-water { position: absolute; inset: 0; z-index: 0; display: none; overflow: hidden; pointer-events: none; -webkit-mask-image: linear-gradient(to bottom, transparent calc(var(--surface, 80%) - 1px), #000 var(--surface, 80%)); mask-image: linear-gradient(to bottom, transparent calc(var(--surface, 80%) - 1px), #000 var(--surface, 80%)); }
.js.motion .cta-water { display: block; }
.cw-surface { position: absolute; top: var(--surface, 80%); right: 0; left: 0; height: 1px; background: linear-gradient(90deg, rgba(137, 211, 207, 0), rgba(137, 211, 207, .3) 30%, rgba(137, 211, 207, .3) 70%, rgba(137, 211, 207, 0)); opacity: 0; transition: opacity .7s ease; }
.cw-rings { position: absolute; top: var(--surface, 80%); left: var(--land-x, 50%); opacity: 0; transition: opacity .5s ease; }
.cw-rings span { position: absolute; top: 0; left: 0; width: var(--ring-w, min(600px, 64vw)); height: 138px; border: 1.4px solid rgba(137, 211, 207, .7); border-radius: 50%; transform: translate(-50%, -50%); }
.about-contact.is-landed .cw-surface, .about-contact.is-landed .cw-rings { opacity: 1; }
.about-contact.is-landed .cw-rings span { animation: nm-ripple 4.2s cubic-bezier(.16, .74, .3, 1) infinite; }
.about-contact.is-landed .cw-rings span:nth-child(2) { animation-delay: 1.4s; }
.about-contact.is-landed .cw-rings span:nth-child(3) { animation-delay: 2.8s; }

@keyframes nm-ripple {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.18); }
  14% { opacity: .45; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.15); }
}

/* --- parallax ----------------------------------------------------------- */

/* Deliberately small: the offsets are clamped to ±18px in about-motion.js. This is meant
   to give a few elements a little life, not to make the page feel like it is
   sliding around. */
.js.motion [data-parallax] { will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  [data-parallax] { transform: none !important; }
}
