/* ==========================================================================
   About · full-screen sections that snap into place
   1 Hero (title + portrait on the bottom edge) · 2 Process (animated art + copy) ·
   3 Experience (pinned; logos float along an arc as you scroll) · 4 Testimonial carousel
   --------------------------------------------------------------------------
   Built from shared pieces: type roles, .view-btn, .icon-btn, .lamp, and the
   case-study pin / snap / reveal / swap / count patterns. Process art uses the
   Services SVG motion vocabulary (draw, pop, rise, then idle loops).
   ========================================================================== */
.page-about {
  --pad: max(var(--side), calc((100vw - var(--max-w)) / 2 + var(--side)));   /* same inset as case-study heroes */
  --vh: 100svh;
}
html:has(> body.page-about) { scroll-snap-type: y mandatory; }
html, body { overflow-x: clip; }

/* ---------- Sections ---------- */
.ab-sec {
  position: relative;
  min-height: var(--vh);
  display: flex; flex-direction: column; justify-content: center;
  padding: 104px var(--pad) 80px;
  scroll-snap-align: start; scroll-snap-stop: always;
}
.ab-inner { width: 100%; }
.ab-sec .lamp { z-index: -1; }
.about-main { transition: transform .7s var(--ease); }
.about-main p, .about-main h1, .about-main h2 { text-wrap: pretty; }

/* ---------- 1. Hero: title left, portrait standing on the bottom edge ---------- */
.ab-hero { padding-bottom: 0; justify-content: flex-end; }
.ab-hero .ab-inner {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 64px;
  align-items: end; min-height: calc(var(--vh) - 104px);
}
.ab-hero h1 { max-width: 9.5em; align-self: center; }
.ab-portrait {
  height: min(calc(var(--vh) - 104px), 56vw, 880px); aspect-ratio: 1;
  margin-right: calc(var(--pad) * -.5);
  /* the photo's backdrop melts into the page: soft left/right/top edges, hard bottom edge */
  --fade: linear-gradient(90deg, transparent, #000 18%, #000 82%, transparent), linear-gradient(transparent, #000 16%);
  -webkit-mask-image: var(--fade); -webkit-mask-composite: source-in;
          mask-image: var(--fade);         mask-composite: intersect;
}
.ab-portrait img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 100%; display: block; }
.about-main figure { margin: 0; }                                             /* WordPress image blocks */
.ab-portrait > figure { width: 100%; height: 100%; }                 /* WordPress image block */
.about-main .arc.wp-block-gallery { display: block; margin: 32px 0 0; }        /* logo Gallery → arc (about.js) */
.ab-next { position: absolute; left: 50%; bottom: 32px; translate: -50% 0; z-index: 2; }
.ab-next svg { animation: nudgeDown 1.8s ease-in-out 2.4s infinite; }

/* ---------- 1b. Statement: outlined words fill in as you scroll ----------
   The section is 2.5 screens tall; its content stays pinned while about.js fills
   the letters in order and shifts the colour from mint to orange halfway through. */
.ab-fill { height: calc(var(--vh) * 2.5); min-height: 0; padding: 0; display: block; }
.ab-fill { scroll-snap-align: none; }                 /* snaps at its start, middle and end instead (.snap, added by about.js) */
.ab-sec > .snap { position: absolute; left: 0; width: 1px; height: var(--vh); scroll-snap-align: start; scroll-snap-stop: always; pointer-events: none; }
.ab-fill .pin {
  position: sticky; top: 0; height: var(--vh);
  display: flex; align-items: center; justify-content: center;
  padding: 104px var(--pad) 80px;
}
.fill-text {
  --c: var(--accent);
  max-width: 14ch; margin: 0 auto; text-align: center; text-wrap: balance;
  font-size: clamp(48px, 7.2vw, 120px); line-height: 1.08; font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-heading); color: var(--c);
}
.fill-text .w { display: inline-block; white-space: nowrap; }
.fill-text .ch {
  color: transparent; -webkit-text-stroke: 1.5px var(--c);
  transition: color .3s var(--ease);
}
.fill-text .ch.on { color: var(--c); }
/* The closing period is the logo. The tile is painted with the text colour (--c),
   so it goes mint → orange in exact step with the words; the logo's line art sits
   on top as a mask (logo-header-lines.webp) in the logo's ink colour. */
.fill-text .mark {
  position: relative; display: inline-block; width: clamp(20px, .38em, 40px); aspect-ratio: 1;
  margin-left: .1em; border-radius: 3px; overflow: hidden; -webkit-text-stroke: 0;
  background: var(--c); transition: background-color .3s var(--ease);
}
.fill-text .mark::after {
  content: ""; position: absolute; inset: 0; background: #001D1B;
  -webkit-mask: url(../../images/logo-header-lines.webp) center / cover no-repeat;
          mask: url(../../images/logo-header-lines.webp) center / cover no-repeat;
}

/* ---------- 2. Process: art card left, copy right ---------- */
.ab-process .ab-inner { display: grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items: center; }
.ab-media { display: flex; justify-content: center; }
.ab-card {                                              /* same surface as the Services cards */
  width: min(100%, 560px, calc(var(--vh) - 208px)); aspect-ratio: 1;
  background: var(--fg); border-radius: var(--radius); box-shadow: var(--shadow-card);
  display: grid; place-items: center;
}
.ab-card .art { width: 92%; aspect-ratio: 1; }
.ab-card .art svg { width: 100%; height: 100%; display: block; overflow: visible; }
.ab-copy { display: flex; flex-direction: column; align-items: flex-start; gap: 16px; max-width: 580px; }
.ab-copy .t-meta { color: var(--soft); }
.ab-copy .view-btn { margin-top: 8px; }
/* Four paragraphs: on shorter laptop screens drop to 16px so the section still
   fits one screen (taller copy just scrolls within the section). */
@media (min-width: 769px) and (max-height: 880px) {
  .ab-copy .t-meta { font-size: var(--fs-base); }
}
@media (min-width: 769px) and (max-height: 800px) {
  .ab-process { padding-top: 88px; padding-bottom: 48px; }
}

/* ---------- 3. Experience: centred copy, logos orbiting along an arc ---------- */
.ab-exp { padding: 0; display: block; }
.ab-exp .pin {
  height: var(--vh); overflow: hidden;
  display: flex; flex-direction: column; justify-content: center;
  padding: 104px 0 0;
}
.ab-exp-copy {
  width: 100%; max-width: calc(1200px + var(--pad) * 2); margin: 0 auto; padding: 0 var(--pad);
  text-align: center; display: flex; flex-direction: column; gap: 16px;
  position: relative; z-index: 2;
}
.ab-exp-copy h2 { text-wrap: balance; }
.ab-exp-copy .t-meta { color: var(--muted); max-width: 960px; margin: 0 auto; text-wrap: balance; }
.arc-toggle { position: absolute; left: 50%; bottom: 32px; translate: -50% 0; z-index: 3; }
.arc-toggle .i-play, .arc-toggle[aria-pressed="true"] .i-pause { display: none; }
.arc-toggle[aria-pressed="true"] .i-play { display: block; }

/* The arc: logos ride along the crown of an invisible circle.
   --R (radius) and each tile's --x / --y / --a are set by about.js. */
.arc {
  --tile: 176px; --R: 1600px;
  position: relative; flex: none; height: calc(var(--tile) + 200px); margin-top: 32px;   /* tile + the arc's dip at the edges */
}
.arc-list { list-style: none; position: absolute; left: 50%; top: 40px; width: 0; height: var(--tile); }
.arc-list li {
  position: absolute; left: calc(var(--tile) / -2); top: 0;
  width: var(--tile); height: var(--tile);
  transform: translate(var(--x, 0px), var(--y, 0px)) rotate(var(--a, 0deg)) scale(var(--s, 1));
  opacity: var(--o, 1);
  will-change: transform;
}
.arc-list .tile {
  display: block; width: 100%; height: 100%;
  border-radius: var(--radius-md); overflow: hidden; background: var(--glass);
  box-shadow: var(--shadow-tile);
}
.arc-list img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- 4. Testimonials: count above, quote, controls below ---------- */
.ab-words { min-height: calc(var(--vh) - 64px); }        /* the footer row completes the last screen */
.quotes { max-width: 960px; margin: 0 auto; text-align: center; display: flex; flex-direction: column; align-items: center; }
.qcount { display: flex; align-items: center; justify-content: center; gap: 16px; margin-bottom: 40px; font-variant-numeric: tabular-nums; color: var(--muted); }
.qcount > span:not(.bar) { position: relative; top: var(--cap-shift); }
.qcount .bar { position: relative; flex: 0 0 72px; height: 1px; background: color-mix(in srgb, currentColor 35%, transparent); overflow: hidden; }
.qcount .bar i { position: absolute; inset: 0; background: var(--fg); transform-origin: left; transform: scaleX(var(--p, .333)); transition: transform .6s var(--ease); }
.quote-stage { display: grid; width: 100%; }
.quote {
  grid-area: 1 / 1; align-self: center;
  display: flex; flex-direction: column; align-items: center; gap: 40px;
  transition: opacity .55s var(--ease), transform .75s var(--ease), filter .55s var(--ease);
}
.quote:not(.on) { opacity: 0; filter: blur(8px); transform: translateY(var(--dir, 24px)); pointer-events: none; }
.quote.on { transition-delay: .12s; }
.quote blockquote p, .quote > .t-h2 { color: var(--fg); }                      /* .quote > p: WordPress blocks */
.quote figcaption, .quote-by { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.quote figcaption .t-caption, .quote-by .t-caption { color: var(--muted); }
.quote-ctrls { margin-top: 56px; display: flex; align-items: center; justify-content: center; gap: 16px; }
.qplay .i-play, .qplay[aria-pressed="true"] .i-pause { display: none; }
.qplay[aria-pressed="true"] .i-play { display: block; }

/* ---------- Reveals ----------
   Each section lights up when it snaps into view (about.js toggles .in, both directions). */
.reveal {
  opacity: 0; transform: translateY(24px); filter: blur(8px);
  transition: opacity .8s var(--ease), transform 1s var(--ease), filter .8s var(--ease);
}
.reveal-pop {
  opacity: 0; transform: translateY(16px) scale(.85);
  transition: opacity .6s var(--ease), transform .9s cubic-bezier(.34,1.4,.5,1);
}
.reveal-up {                                            /* portrait rises from the bottom edge (case-study phone) */
  opacity: 0; transform: translateY(24%);
  transition: opacity .9s var(--ease), transform 1.3s var(--ease);
}
.in .reveal, .in .reveal-pop, .in .reveal-up { opacity: 1; transform: none; filter: none; transition-delay: calc(.15s + var(--r, 0) * 110ms); }
.in 
/* ---------- Process art motion ----------
   Blobs and phone rise in, UI cards pop in around it, then each settles into its
   own idle loop. Replays each time the section snaps into view. */
.art .t { transform-box: fill-box; transform-origin: center; }
.art .t:not(.m-pen):not(.m-heart):not(.m-bag-in):not(.m-star-in) { opacity: 0; }
.in .art .t { opacity: 1; }
.in .art .blob-a  { animation: popIn .9s var(--ease) .2s both, breatheA 6s ease-in-out 1.2s infinite; }
.in .art .blob-b  { animation: popIn .9s var(--ease) .32s both, breatheB 6s ease-in-out 1.2s infinite; }
.in .art .m-ground { animation: growX .9s var(--ease) .3s both; }
.in .art .m-phone { animation: riseIn .9s var(--ease) .4s both; }
.in .art .m-chat  { animation: popIn .8s var(--ease) .7s both; }
.in .art .m-avatar { animation: popIn .6s var(--ease) 1s both; }
.in .art .m-b1    { animation: popIn .5s var(--ease) 1.1s both, bubble 6s var(--ease) 2.4s infinite; }
.in .art .m-b2    { animation: popIn .5s var(--ease) 1.25s both, bubble 6s var(--ease) 3.4s infinite; }
.in .art .m-send  { animation: popIn .5s var(--ease) 1.35s both, send 6s var(--ease) 4.2s infinite; }
.in .art .m-acct  { animation: slideIn .8s var(--ease) .85s both; }
.in .art .m-pen   { animation: wiggle 4s var(--ease) 2s infinite; }
.in .art .m-star  { animation: popIn .7s var(--ease) 1s both; }
.in .art .m-star-in { animation: floatA 5s ease-in-out 1.8s infinite; }
.in .art .m-bag   { animation: popIn .7s var(--ease) 1.15s both; }
.in .art .m-bag-in { animation: floatB 4.4s ease-in-out 1.9s infinite; }
.in .art .m-nav   { animation: riseIn .8s var(--ease) .95s both; }
.in .art .m-heart { animation: beat 3s ease-in-out 2.2s infinite; }

/* Page transition: content pushes in behind the curtain */
.is-leaving .about-main { transform: scale(1.04); }

/* ---------- Footer ---------- */
.at-end .to-top { bottom: calc(var(--gutter) + 40px); }        /* lifts above the social icons, as on the Project page */
.site-foot--page {
  padding: 0 var(--gutter) calc(var(--gutter) - 12px + env(safe-area-inset-bottom));
  min-height: 64px; scroll-snap-align: end;
}

/* ---------- Responsive ---------- */
@media (max-width: 1200px) {
  .ab-process .ab-inner { gap: 48px; }
  .ab-hero .ab-inner { gap: 32px; }
  .arc { --tile: 144px; }
}
@media (max-width: 768px) {
  .ab-fill { height: calc(var(--vh) * 2); }
  .ab-fill .pin { padding: 96px var(--side) 64px; }
  .fill-text { font-size: clamp(40px, 11vw, 64px); }
  .fill-text .ch { -webkit-text-stroke-width: 1px; }
  /* Phones snap firmly too (same as the Project page); a section taller than the
     screen scrolls freely inside itself, then snaps to the next one */
  .ab-sec { padding: 96px var(--pad) 64px; }
  .ab-hero { padding-bottom: 0; }
  .ab-hero .ab-inner { grid-template-columns: 1fr; gap: 24px; min-height: calc(var(--vh) - 96px); align-content: space-between; }
  .ab-hero h1 { align-self: start; }
  .ab-portrait { height: min(60svh, 136vw); justify-self: start; margin: 0 0 0 calc(50% - min(30svh, 68vw)); }
  .ab-process .ab-inner { grid-template-columns: 1fr; gap: 40px; }
  .ab-card { width: min(100%, 400px); }
  .ab-copy { gap: 16px; }
  .ab-copy .view-btn { margin-top: 8px; }
  .ab-exp .pin { padding-top: 96px; min-height: var(--vh); height: auto; }
  .arc { height: calc(var(--tile) + 120px); }
  .arc { --tile: 112px; }
  .ab-words { min-height: calc(var(--vh) - 48px); }
  .qcount { margin-bottom: 32px; }
  .quote { gap: 32px; }
  .quote blockquote p, .quote > .t-h2 { font-size: var(--fs-h3); line-height: 32px; }
  .quote-ctrls { margin-top: 40px; gap: 12px; }
  .site-foot--page { min-height: 48px; padding-bottom: calc(8px + env(safe-area-inset-bottom)); }
}
@media (min-width: 769px) and (max-height: 720px) {   /* short desktop windows · scale-ok: complement of 768 */
  .ab-sec { padding-top: 96px; padding-bottom: 64px; }
  .ab-hero { padding-bottom: 0; }
  .arc { --tile: 136px; }
}

/* ---------- Keyframes ---------- */
@keyframes nudgeDown { 0%, 100% { transform: none; } 50% { transform: translateY(4px); } }
@keyframes popIn {
  0%   { opacity: 0; transform: scale(.4); }
  60%  { opacity: 1; transform: scale(1.06); }
  100% { opacity: 1; transform: none; }
}
@keyframes riseIn  { from { opacity: 0; transform: translateY(32px); } to { opacity: 1; transform: none; } }
@keyframes slideIn { from { opacity: 0; transform: translateX(48px); } to { opacity: 1; transform: none; } }
@keyframes growX   { from { opacity: 0; transform: scaleX(0); } to { opacity: 1; transform: none; } }
@keyframes breatheA { 0%, 100% { transform: none; } 50% { transform: scale(1.06) translate(-6px, 4px); } }
@keyframes breatheB { 0%, 100% { transform: none; } 50% { transform: scale(1.05) translate(6px, -4px); } }
@keyframes floatA  { 0%, 100% { transform: none; } 50% { transform: translateY(-8px) rotate(-3deg); } }
@keyframes floatB  { 0%, 100% { transform: none; } 50% { transform: translateY(7px) rotate(4deg); } }
@keyframes wiggle  { 0%, 70%, 100% { transform: none; } 76% { transform: rotate(-14deg); } 82% { transform: rotate(10deg); } 88% { transform: rotate(-6deg); } }
@keyframes beat    { 0%, 60%, 100% { transform: none; } 68% { transform: scale(1.3); } 76% { transform: scale(.94); } 84% { transform: scale(1.12); } }
@keyframes bubble  { 0%, 80%, 100% { transform: none; } 86% { transform: scale(1.06); } 92% { transform: scale(.98); } }
@keyframes send    { 0%, 78%, 100% { transform: none; } 84% { transform: translateY(-4px) scale(1.12); } 90% { transform: scale(.96); } }

/* Reduced motion: the statement shows filled, with no scroll-linked change */
@media (prefers-reduced-motion: reduce) {
  .ab-fill { height: auto; min-height: var(--vh); }
  .ab-fill .pin { position: static; }
  .fill-text .ch { color: var(--c); transition: none; }
  .fill-text .mark { transition: none; }
}
