/* =====================================================================
   CUTSCENE — ABOUT
   Two chapters, Our Craft and The Team. Each opens on a title card
   ("Our | Craft", "Humans Behind | the Work") that is spliced down the
   middle and pulled apart like a curtain onto the chapter underneath.
   Each chapter sits in a large frame over a faint still; its words
   slide in letter by letter and its paragraphs come in line by line
   (rack focus by default; other ways in the Tune panel).
   Scrolling on from a chapter plays the next card; past the last one
   it goes back round to the first (js/about.js).
   ===================================================================== */

:root{
  --about-top: 118px;                  /* top of the page -> the frame       */
  --about-bottom: 48px;                /* frame -> bottom of the page        */
  --about-max: 1320px;                 /* frame never wider than this        */
  --about-pad: clamp(24px, 3.4vw, 56px);  /* inside the frame               */
  --about-bg-alpha: .2;                /* the still behind a chapter          */
  --about-bg-gray: .35;                /* ...0 = full colour, 1 = black & white */

  --about-card-fit: 60;                /* title card: longest line spans this
                                          much of the page width (%)          */
  --about-card-tall: 56;               /* ...but the title is never taller than
                                          this much of the page height (%)    */
  --about-card-thin: 100;              /* weight of the light words (100-900)  */
  --about-card-shave: .02em;           /* light words thinner still than the
                                          font's thinnest weight (0 = off)    */
  --about-card-heavy: 500;             /* weight of the heavy words            */
  --about-kicker-scale: .17;           /* "Chapter 01": its size as a share of
                                          the first card's title size (the
                                          same on every card)                 */
  --about-kicker-weight: 300;          /* ...and its weight (300 / 400 / 500) */
  --about-kicker-space: .08;             /* ...and its gap above the title, the same way */
  --about-card-hold: 900ms;            /* card holds once its words are in    */
  --about-cut: 260ms;                  /* the cut running down the card       */
  --about-cut-snap: 3;                 /* the cut runs down the middle, unless a
                                          gap between words is within this % of
                                          the page width of it (0 = always the
                                          middle)                             */
  --about-open: 1000ms;                /* the halves sliding apart            */
  --about-reveal-at: .6;               /* chapter words come in this far
                                          through the halves sliding apart     */
  --about-leave: 650ms;                /* a chapter fading out before the next card */
  --about-wheel: 60;                   /* on a title card: scroll that skips its hold */
  --about-pull: 300;                   /* at the end of a chapter: scroll needed to
                                          fill the "Next" line and move on
                                          (a mouse-wheel notch ≈ 100)          */
  --about-go-size: 14px;               /* "Next" / "Back" markers: text size (the
                                          line and arrow scale with it)        */
  --about-pull-touch: 150px;           /* ...the same on a touch screen: how far
                                          the finger travels                  */

  --about-title-size: clamp(20px, 1.8vw, 30px);  /* service titles, names   */
  --about-num-size: clamp(26px, 2.5vw, 44px);    /* 01 02 03 over the clips */
  --about-text-size: 15px;             /* paragraphs                          */
  --about-text-lh: 1.65;
  --about-text-dur: 1300ms;            /* paragraphs: each line coming in     */
  --about-text-delay: 250ms;           /* words in -> paragraphs start        */
  --about-text-stagger: 160ms;         /* ...each paragraph a moment after    */
  --about-line-step: 110ms;            /* ...each line a moment after the last */
  --about-word-step: 22ms;             /* "word by word": next word after     */
  --about-focus-blur: 9px;             /* "rack focus": how soft it starts    */
  --about-media-fade: 900ms;           /* clips and portraits fading in       */

  --about-demo-ratio: 16 / 9;          /* shape of the service clips          */
  --about-photo-h: min(36vh, 460px);   /* team portraits: height at most      */
  --about-col-stagger: 56px;           /* the middle column sits this much lower */
}

/* ---- Which page is showing ---- */
.app.view-about .stage{ visibility: hidden; pointer-events: none; }

.about{
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: hidden;
}
.about[hidden]{ display: none; }
.app.is-playing .about{ opacity: 0; pointer-events: none; }

/* ---- A chapter: one frame over a faint still ---- */
.ab-chapter{
  position: absolute;
  inset: 0;
  visibility: hidden;
  opacity: 0;
}
.ab-chapter.is-current{ visibility: visible; opacity: 1; }
.ab-chapter.is-leaving{ opacity: 0; transition: opacity var(--about-leave) ease calc(var(--about-leave) * .25); }

.ab-frame{
  position: absolute;
  top: var(--about-top);
  bottom: var(--about-bottom);
  left: max(var(--gutter), calc((100% - var(--about-max)) / 2));
  right: max(var(--gutter), calc((100% - var(--about-max)) / 2));
}
.ab-bg{
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  background: var(--bg);
}
.ab-bg img{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: var(--about-bg-alpha);
  filter: grayscale(var(--about-bg-gray));
}
.ab-frame .corner{ z-index: 1; }

.ab-body{
  position: absolute;
  inset: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  padding: var(--about-pad);
  display: flex;
  flex-direction: column;
}
.ab-body::-webkit-scrollbar{ display: none; }
.ab-body{ padding-bottom: calc(var(--about-pad) + var(--about-go-size) * 4); }   /* room for "Next" */
/* more below: the bottom edge fades, so it reads as "keep scrolling" */
.ab-body.is-more{
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 72px), transparent);
          mask-image: linear-gradient(to bottom, #000 calc(100% - 72px), transparent);
}

.ab-head{
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: var(--label-size);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  white-space: nowrap;
}
.ab-count{ color: var(--fg-2); font-variant-numeric: tabular-nums; }

/* the chapter's content sits in the middle of the space under the heading */
.ab-list{ margin-block: auto; padding-top: clamp(20px, 3vh, 40px); }

/* Three columns, the middle one set a little lower, so the row has a
   rhythm instead of a straight edge (Our Craft and The Team alike). */
.ab-services,
.ab-people{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(24px, 3.4vw, 60px);
  row-gap: clamp(32px, 5vh, 56px);
  align-items: start;
}
.ab-svc:nth-child(3n+2),
.ab-person:nth-child(3n+2){ margin-top: var(--about-col-stagger); }

/* ---- Our Craft: a big clip per service, numbered ---- */
.ab-num{
  margin-bottom: 14px;
  font-family: var(--font-display);
  font-size: var(--about-num-size);
  font-weight: var(--about-card-thin);
  line-height: .9;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: rgb(var(--fg-rgb) / .85);
}
.ab-demo{
  position: relative;
  aspect-ratio: var(--about-demo-ratio);
  overflow: hidden;
  background: var(--frame-empty);
}
.ab-demo img,
.ab-demo video{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;
  transition: transform .9s cubic-bezier(.16, 1, .3, 1);
}
.ab-demo video{ opacity: 0; transition: opacity .45s ease, transform .9s cubic-bezier(.16, 1, .3, 1); }
.ab-demo video.is-ready{ opacity: 1; }
.ab-svc:hover .ab-demo img,
.ab-svc:hover .ab-demo video{ transform: scale(1.04); }
.ab-svc-text{ padding-top: 20px; }

/* titles and names: the heavy voice of the title cards, smaller */
.ab-title{
  display: block;
  font-family: var(--font-display);
  font-size: var(--about-title-size);
  font-weight: 700;
  font-stretch: 82%;
  letter-spacing: -.01em;
  line-height: 1;
  text-transform: uppercase;
}
.ab-role{
  display: block;
  margin-top: 9px;
  font-size: 11px;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--fg-2);
}

/* ---- The Team: big portraits ---- */
.ab-photo{
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 5;
  max-height: var(--about-photo-h);      /* short windows: cropped, not shrunk */
  overflow: hidden;
  background: var(--frame-empty);
}
.ab-photo img{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .9s cubic-bezier(.16, 1, .3, 1);
}
.ab-person:hover .ab-photo img{ transform: scale(1.04); }
/* no portrait yet: an empty frame with a note */
.ab-photo-tbc{
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 10.5px;
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--fg-2);
  border: 1px solid rgb(var(--fg-rgb) / .14);
}
.ab-who{ padding-top: 20px; }

/* clips and portraits fade in with the words */
.ab-demo, .ab-photo{ opacity: 0; }
.ab-chapter.is-lit .ab-demo,
.ab-chapter.is-lit .ab-photo{
  opacity: 1;
  transition: opacity var(--about-media-fade) ease-out calc(var(--n, 0) * 140ms);
}

/* ---- Next / Back markers ----
   "Next · <chapter>" sits at the bottom of the frame once you reach the
   end. Carrying on fills its thin line (and the content gives a little);
   only a full line moves on. "Back" does the same at the top. The
   marker is also a button. (js/about.js: "Pulling past the end") */
.ab-next,
.ab-prev{
  position: absolute;
  left: 50%;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 1.1em;
  padding: .7em 1em;
  translate: -50% 0;
  font-family: var(--font-mono);
  font-size: var(--about-go-size);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--fg);
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s ease;
}
.ab-next{ bottom: .6em; background: none; border: 0; cursor: pointer; }
.ab-prev{ top: .6em; }
.ab-go-label{ color: var(--fg-2); }
.ab-chapter.is-lit.is-end .ab-next{ opacity: .7; pointer-events: auto; transition-delay: .6s; }
.ab-chapter.is-lit .ab-next:hover,
.ab-chapter.is-lit.pull-dn .ab-next{ opacity: 1; transition-delay: 0s; }
.ab-chapter.is-lit.pull-up .ab-prev{ opacity: calc(.35 + var(--pull, 0) * .65); transition: none; }
.ab-pull{
  position: relative;
  width: 7.5em;
  height: 2px;
  background: rgb(var(--fg-rgb) / .3);
}
.ab-pull i{
  position: absolute;
  inset: 0;
  background: var(--fg);
  transform-origin: left center;
  transform: scaleX(0);
}
.pull-dn .ab-next .ab-pull i,
.pull-up .ab-prev .ab-pull i{ transform: scaleX(var(--pull, 0)); }
.ab-arrow{ display: inline-block; font-size: 1.55em; line-height: 1; }
/* a slow nudge on the arrow while it waits */
.ab-chapter.is-end:not(.pull-dn) .ab-next .ab-arrow{ animation: ab-nudge 2s ease-in-out infinite; }
@keyframes ab-nudge{ 0%, 100%{ transform: translateY(-2px); } 50%{ transform: translateY(3px); } }
/* the content gives a little as you pull (the whole scrolling area moves,
   so nothing inside it scrolls) */
.ab-frame{ overflow: hidden; }
.ab-body{ transition: transform .5s cubic-bezier(.16, 1, .3, 1); }
.pull-dn .ab-body{ transform: translateY(calc(var(--pull, 0) * -28px)); transition: none; }
.pull-up .ab-body{ transform: translateY(calc(var(--pull, 0) * 28px)); transition: none; }

/* ---- Paragraphs: split into their lines by js/about.js, then
        brought in line by line. How (data-about-text on <html>):
          focus  (default) each line racks from soft to sharp as it rises
          lines  each line slides up out of its own slot
          scan   a thin light reads across each line, leaving the words
          words  word by word, each settling out of a blur            ---- */
.ab-text{
  margin: 12px 0 0;
  max-width: 62ch;
  font-size: var(--about-text-size);
  line-height: var(--about-text-lh);
  color: rgb(var(--fg-rgb) / .86);
}
.ab-line{ display: block; white-space: nowrap; }
.ab-pb{ display: block; height: 0; }
.ab-line.ab-pstart{ margin-top: .75em; }   /* a new paragraph within a write-up */
.ab-li{ display: inline-block; }
.ab-wd{ display: inline-block; }
.ab-line{
  --d: calc(var(--about-text-delay) + var(--n, 0) * var(--about-text-stagger) + var(--ln, 0) * var(--about-line-step) * var(--step-x, 1));
}

/* focus */
.ab-li{
  opacity: 0;
  filter: blur(var(--about-focus-blur));
  transform: translateY(.45em);
  transition: opacity var(--about-text-dur) ease,
              filter var(--about-text-dur) cubic-bezier(.25, .6, .2, 1),
              transform var(--about-text-dur) cubic-bezier(.16, 1, .3, 1);
}
.ab-chapter.is-lit .ab-li{ opacity: 1; filter: blur(0); transform: none; transition-delay: var(--d); }

/* lines */
[data-about-text="lines"] .ab-line{ overflow: hidden; padding-bottom: .15em; margin-bottom: -.15em; }
[data-about-text="lines"] .ab-li{ opacity: 1; filter: none; transform: translateY(115%);
  transition: transform var(--about-text-dur) cubic-bezier(.16, 1, .3, 1); }
[data-about-text="lines"] .ab-chapter.is-lit .ab-li{ transform: none; }

/* scan */
[data-about-text="scan"] .ab-text{ --step-x: 3.5; }
[data-about-text="scan"] .ab-li{
  position: relative;
  opacity: 1; filter: none; transform: none;
  clip-path: inset(-.3em 100% -.3em 0);
  transition: clip-path var(--about-text-dur) cubic-bezier(.45, .05, .3, 1);
}
[data-about-text="scan"] .ab-chapter.is-lit .ab-li{ clip-path: inset(-.3em -1em -.3em 0); }
[data-about-text="scan"] .ab-li::after{
  content: "";
  position: absolute;
  top: .15em; bottom: .15em;
  left: 0;
  width: 1px;
  background: var(--fg);
  box-shadow: 0 0 10px 1px rgb(var(--fg-rgb) / .7);
  opacity: 0;
}
[data-about-text="scan"] .ab-chapter.is-lit .ab-li::after{
  animation: ab-scan var(--about-text-dur) cubic-bezier(.45, .05, .3, 1) var(--d) both;
}
@keyframes ab-scan{
  0%{ left: 0; opacity: 0; }
  6%{ opacity: 1; }
  88%{ opacity: 1; }
  100%{ left: 100%; opacity: 0; }
}

/* words */
[data-about-text="words"] .ab-li{ opacity: 1; filter: none; transform: none; transition: none; }
[data-about-text="words"] .ab-wd{
  opacity: 0;
  filter: blur(calc(var(--about-focus-blur) * .7));
  transform: translateY(.25em);
  transition: opacity calc(var(--about-text-dur) * .7) ease,
              filter calc(var(--about-text-dur) * .7) ease,
              transform calc(var(--about-text-dur) * .7) cubic-bezier(.16, 1, .3, 1);
}
[data-about-text="words"] .ab-chapter.is-lit .ab-wd{
  opacity: 1; filter: blur(0); transform: none;
  transition-delay: calc(var(--about-text-delay) + var(--n, 0) * var(--about-text-stagger) + var(--wi, 0) * var(--about-word-step));
}

/* coming back to a chapter: everything resets at once, nothing animates out */
.ab-chapter.is-resetting *, .ab-chapter.is-resetting *::before, .ab-chapter.is-resetting *::after{ transition: none !important; }

/* ---- The title card ----
   Centred on the page and sized by js/about.js so its longest line spans
   most of the page (--about-card-fit). Words marked *heavy* in
   js/content.js are set black, the rest hairline thin: the contrast is
   the whole design, so both share one family, one size and one width.
   The cut is placed by js/about.js through a gap between words.
   Styles (data-about-card on <html>):
     contrast (default) hairline and black capitals, same width
     wide     black condensed against hairline expanded
     serif    a serif, the heavy words in italic                        */
.ab-card{
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
  visibility: hidden;
}
.ab-card.is-on{ visibility: visible; }
/* a hidden copy of the first title, only for measuring (js/about.js) */
.ab-card-title.ab-measure{ position: absolute; left: 0; top: 0; visibility: hidden; pointer-events: none; }
/* the chapter line sits above the title, so the title itself is centred */
.ab-card-in{ position: relative; max-width: 100%; }
.ab-kicker{
  position: absolute;
  left: 0; right: 0;
  bottom: 100%;
  display: block;
  margin-bottom: calc(var(--card-fs, 120px) * var(--about-kicker-space));
  font-family: var(--font-mono);
  font-size: max(var(--label-size), calc(var(--card-fs, 120px) * var(--about-kicker-scale)));
  font-weight: var(--about-kicker-weight);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--fg-2);
}
.ab-card-title{
  display: inline-block;
  margin: 0;
  white-space: nowrap;                   /* lines break only where content says */
  font-family: var(--font-display);
  font-size: 120px;                      /* replaced by js/about.js (fit) */
  font-weight: 400;
  font-stretch: 100%;
  line-height: .84;
  text-transform: uppercase;
  font-kerning: normal;
}
/* heavy words want tighter spacing, hairlines a touch more air */
.ab-card .is-heavy{ font-weight: var(--about-card-heavy); letter-spacing: -.028em; }
.ab-card .is-light{ font-weight: var(--about-card-thin); letter-spacing: .012em; }
/* thinner than the font goes: a hairline of background colour laid over
   the outline of each light letter shaves its strokes down */
.ab-card .is-light .wl-c{ -webkit-text-stroke: var(--about-card-shave) var(--bg); }
/* each word's slot: room for the letters without clipping */
.ab-card-title .wl{ padding: .06em .03em .08em; margin: -.06em -.03em -.08em; }

.ab-card .br-w{ display: none; }

[data-about-card="wide"] .ab-card .is-heavy{ font-stretch: 64%; letter-spacing: -.01em; }
[data-about-card="wide"] .ab-card .is-light{ font-stretch: 125%; letter-spacing: .02em; }

[data-about-card="serif"] .ab-card-title{
  font-family: "Instrument Serif", Georgia, "Times New Roman", serif;
  text-transform: none;
  line-height: .95;
  letter-spacing: -.01em;
}
[data-about-card="serif"] .ab-card .is-heavy{ font-weight: 400; font-style: italic; letter-spacing: -.01em; }
[data-about-card="serif"] .ab-card .is-light{ font-weight: 400; letter-spacing: -.01em; }
[data-about-card="serif"] .ab-card-title .wl{ padding-bottom: .18em; margin-bottom: -.18em; }

/* the card's two halves while they part (built by js/about.js) */
.ab-half .ab-card{ visibility: visible; }

/* ---- Between a laptop and a phone: one item per row, the clip or
        portrait on the left and its words beside it ---- */
@media (max-width: 1100px) and (min-width: 761px){
  .ab-services, .ab-people{ grid-template-columns: minmax(0, 1fr); row-gap: clamp(36px, 6vh, 64px); }
  .ab-svc:nth-child(n), .ab-person:nth-child(n){ margin-top: 0; }
  .ab-svc, .ab-person{
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    column-gap: clamp(24px, 3.4vw, 40px);
    align-items: start;
  }
  .ab-svc .ab-num{ grid-column: 1 / -1; }
  .ab-svc .ab-svc-text{ padding-top: 0; }
  .ab-person{ grid-template-columns: minmax(0, .8fr) minmax(0, 1fr); grid-template-rows: auto 1fr; }
  .ab-person .ab-photo{ grid-column: 1; grid-row: 1 / span 2; max-height: none; }
  .ab-person .ab-who{ grid-column: 2; padding-top: 0; }
  .ab-person .ab-text{ grid-column: 2; }
}

/* ---- Phones: one column ---- */
@media (max-width: 760px){
  :root{
    --about-top: 104px;
    --about-bottom: 28px;
    --about-pad: 20px;
    --about-card-fit: 90;
    --about-title-size: 22px;
    --about-text-size: 14px;
    --about-photo-h: 360px;
  }
  .ab-services, .ab-people{ grid-template-columns: minmax(0, 1fr); }
  .ab-svc:nth-child(n), .ab-person:nth-child(n){ margin-top: 0; }
  .ab-card .br-w{ display: inline; }     /* a word per line, set big */
  :root{ --about-go-size: 12px; }
  .ab-next, .ab-prev{ gap: .8em; }
  .ab-pull{ width: 4em; }
}
