/* ============================================================
   GRAPHICXO — ABOUT / STUDIO
   Loaded only by about.php, on top of main.css + pages.css.

   The page is one argument on one line: a gold thread drawn down the
   workflow as you read it, with the particle field (about.js) running down
   it as current. Everything here either hangs off that line or is a place
   the field gathers — the mark at the top, the signature at the end, and a
   knot at every stage of the work.

   Order below follows the page: field · hero · founder · workflow ·
   studio band · creative technology · philosophy · responsive · motion.
   ============================================================ */

/* ------------------------------------------------------------
   THE FIELD
   Fixed and behind the page. z-index:-1 keeps it under .main's in-flow
   content while still painting above the body background; a positioned
   z-index:0 child would paint over the text.
   ------------------------------------------------------------ */
.ab{position:relative}
.ab-field{
  position:fixed;inset:0;z-index:-1;
  width:100%;height:100%;pointer-events:none;
  opacity:0;transition:opacity 1.6s var(--ease);
}
.ab-field.is-live{opacity:1}
@media (prefers-reduced-motion:reduce){ .ab-field{display:none} }

/* ------------------------------------------------------------
   1 · HERO — copy, and the mark the field gathers around
   ------------------------------------------------------------ */
.ab-head{
  position:relative;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,26rem);
  align-items:center;gap:clamp(2rem,6vw,5rem);
  padding-top:clamp(9rem,18vh,13rem);
  padding-bottom:clamp(2.5rem,6vh,4.5rem);
}
.ab-head__eyebrow{display:flex;align-items:center;gap:.9rem;margin-bottom:1.4rem}
.ab-head__eyebrow::before{content:"";width:40px;height:1px;background:var(--gold)}

.ab-head__title{font-family:var(--serif);font-size:clamp(2.6rem,8vw,7rem);line-height:.94;letter-spacing:-.03em}
.ab-head__title em{color:var(--gold);font-style:italic;font-weight:300}
/* Each line rises out of its own mask; the padding stops the overflow
   shaving descenders. */
.ab-head__mask{display:block;overflow:hidden;padding-bottom:.08em}
.ab-head__mask > span{display:block;transform:translateY(115%);transition:transform 1.05s var(--ease)}
.ab-head__title.is-in .ab-head__mask > span{transform:none}
.ab-head__title.is-in .ab-head__mask:nth-child(2) > span{transition-delay:.1s}

.ab-head__desc{
  margin-top:1.9rem;max-width:52ch;
  color:var(--grey);font-size:clamp(1rem,1.5vw,1.2rem);font-weight:300;
  opacity:0;transform:translateY(24px);
  transition:opacity 1s var(--ease) .2s, transform 1s var(--ease) .2s;
}
.ab-head__desc.is-in{opacity:1;transform:none}

/* Three plain facts under the opening claim. Set as a rule of small caps
   rather than as pills, so the hero stays type-led — this is a masthead
   line, not a row of badges. */
.ab-facts{
  list-style:none;
  display:flex;flex-wrap:wrap;align-items:center;
  gap:.7rem clamp(1rem,2.4vw,1.9rem);
  margin-top:2.2rem;padding-top:1.5rem;
  border-top:1px solid var(--line);
  font-size:.7rem;font-weight:600;letter-spacing:.22em;text-transform:uppercase;
  color:var(--grey-dim);
  opacity:0;transform:translateY(20px);
  transition:opacity 1s var(--ease) .34s, transform 1s var(--ease) .34s;
}
.ab-facts.is-in{opacity:1;transform:none}
.ab-facts li{display:flex;align-items:center;gap:clamp(1rem,2.4vw,1.9rem)}
/* The separator is drawn BEFORE each item but the first, so it never trails
   off the end of a wrapped line. */
.ab-facts li + li::before{content:"";width:5px;height:5px;border-radius:50%;background:rgba(212,175,55,.55)}

/* The mark. about.js reads the <img>'s box and forms the swarm into a halo
   just outside it, so the rings below and the particles describe the same
   circle. */
.ab-portrait{
  position:relative;display:grid;place-items:center;
  aspect-ratio:1;
  opacity:0;transform:scale(.92);
  transition:opacity 1.2s var(--ease) .16s, transform 1.2s var(--ease) .16s;
}
.ab-portrait.is-in{opacity:1;transform:none}
.ab-portrait__ring{
  position:absolute;width:82%;aspect-ratio:1;border-radius:50%;
  border:1px solid rgba(212,175,55,.16);
  /* One brighter arc, or the rotation below is invisible on a plain circle. */
  border-top-color:rgba(231,201,107,.75);
  border-right-color:rgba(212,175,55,.34);
  background:radial-gradient(circle,rgba(212,175,55,.1),transparent 66%);
  animation:abRing 16s linear infinite;
}
.ab-portrait__ring--2{
  width:98%;
  border-style:dashed;border-color:rgba(139,92,255,.18);
  background:none;
  animation-duration:26s;animation-direction:reverse;
}
@keyframes abRing{to{transform:rotate(360deg)}}
.ab-portrait__mark{
  position:relative;z-index:1;width:56%;height:auto;
  filter:drop-shadow(0 18px 40px rgba(0,0,0,.6)) drop-shadow(0 0 30px rgba(212,175,55,.22));
}

/* ------------------------------------------------------------
   2 · THE FOUNDER
   One frame and one column of writing. Deliberately asymmetric and
   deliberately singular: a centred card, or a row of equal cells, would
   read as the first entry of a team grid that does not exist.
   ------------------------------------------------------------ */
.founder{
  display:grid;
  grid-template-columns:minmax(0,25rem) minmax(0,1fr);
  gap:clamp(2rem,6vw,5.5rem);
  align-items:start;
}

/* Not sticky. It was, while the frame was a fixed 4:5 crop and always
   shorter than the viewport; an uncropped portrait can be taller than the
   window, and a sticky box that does not fit pins with its own bottom off
   screen and never scrolls the rest into view. The two columns now run to
   roughly the same height anyway, so pinning bought nothing but a gap. */
.founder__figure{
  opacity:0;transform:translateY(28px);
  transition:opacity 1s var(--ease),transform 1s var(--ease);
}
.founder__figure.is-in{opacity:1;transform:none}

.founder__frame{
  position:relative;overflow:hidden;
  border-radius:18px;
  border:1px solid var(--line);
  background:
    radial-gradient(120% 92% at 22% 4%, rgba(109,40,255,.30), transparent 62%),
    linear-gradient(158deg, rgba(212,175,55,.13), #0a0a0b 70%);
  transition:border-color .6s var(--ease);
}
@media (hover:hover){.founder__figure:hover .founder__frame{border-color:rgba(212,175,55,.38)}}

/* A photograph is shown WHOLE. It sits in normal flow at its own aspect
   ratio and the frame takes its height from it, so the portrait is never
   cropped to fit a shape this stylesheet picked — whatever proportions the
   next one arrives in, all of it is on the page.
   (.plate is shared with the portfolio wall and the band below, where it is
   an absolutely-positioned cover fill; these rules undo that here.) */
.founder__frame--photo .plate{
  position:static;display:block;
  width:100%;height:auto;
  color:#fff;
}

/* No photograph yet. An empty frame has no proportions of its own, so the
   monogram gets the 4:5 the band below uses. */
.founder__frame--mono{aspect-ratio:4/5}

/* The slot, waiting for a photograph. A monogram under a slow ring — honest
   about being a placeholder, and the same furniture the hero uses, so the
   page does not have two ideas of what an empty frame looks like. */
.founder__mono{position:absolute;inset:0;display:grid;place-items:center}
.founder__mono-ring{
  position:absolute;width:58%;aspect-ratio:1;border-radius:50%;
  border:1px dashed rgba(212,175,55,.26);
  border-top-color:rgba(231,201,107,.6);
  animation:abRing 24s linear infinite;
}
.founder__initials{
  position:relative;
  font-family:var(--serif);font-size:clamp(3rem,7vw,4.6rem);line-height:1;
  letter-spacing:.04em;color:var(--gold);
  text-shadow:0 0 46px rgba(212,175,55,.35);
}

.founder__caption{padding-top:1.3rem;border-top:1px solid var(--line);margin-top:1.3rem}
.founder__name{font-family:var(--serif);font-size:clamp(1.35rem,2.4vw,1.9rem);line-height:1.15;letter-spacing:-.01em}
.founder__role{
  margin-top:.55rem;
  font-size:.68rem;font-weight:600;letter-spacing:.24em;text-transform:uppercase;
  color:var(--gold);
}

.founder__body{
  opacity:0;transform:translateY(28px);
  transition:opacity 1s var(--ease) .12s,transform 1s var(--ease) .12s;
}
.founder__body.is-in{opacity:1;transform:none}
.founder__lede{
  font-family:var(--serif);font-size:clamp(1.7rem,3.4vw,2.8rem);
  line-height:1.12;letter-spacing:-.02em;max-width:20ch;
}
.founder__lede em{color:var(--gold);font-style:italic;font-weight:300}
.founder__text{
  margin-top:1.5rem;max-width:56ch;
  color:var(--grey);font-weight:300;font-size:1.02rem;line-height:1.78;
}

/* What the single direction actually covers. A rule per line rather than a
   grid of tiles: it is a list of disciplines, not a set of products. */
.founder__caps{
  list-style:none;margin-top:2.6rem;
  border-top:1px solid var(--line);
}
.founder__caps li{
  position:relative;
  padding:.95rem 0 .95rem 1.7rem;
  border-bottom:1px solid var(--line);
  color:var(--grey);font-weight:300;
}
/* Centred on the first line rather than set at a round em: the padding is a
   fixed .95rem and the line box is .8em either side of the centre, so the
   rule lands on the text at every one of the sizes this page renders at. */
.founder__caps li::before{
  content:"";position:absolute;left:0;top:calc(.95rem + .8em);
  width:9px;height:1px;background:var(--gold);opacity:.8;
}

/* ------------------------------------------------------------
   3 · HOW THE STUDIO WORKS — the thread
   One gold line from the first stage to the last, drawn as you scroll
   (app.js writes --thread 0->1). It is the page's spine — and the wire the
   particle field runs down.
   ------------------------------------------------------------ */

/* The shared .stitle carries an 18ch measure, tuned for the four- and
   five-word headlines it sets elsewhere. This page's runs longer and breaks
   over three lines at that width, leaving "file." alone on the last one.
   24ch sets it as the two-line sentence it is. */
.ab .stitle{max-width:24ch}

/* The five stages as one line before they are read one at a time. Scrolls
   on its own axis rather than wrapping: broken over two lines it stops
   reading as a sequence, which is the only thing it is here to do. */
.flow__map{
  display:flex;align-items:center;gap:clamp(.7rem,1.6vw,1.3rem);
  margin:2.4rem 0 3.4rem;
  padding-bottom:.6rem;
  overflow-x:auto;
  font-size:.68rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--grey-dim);
  scrollbar-width:none;
}
.flow__map::-webkit-scrollbar{display:none}
.flow__map span{white-space:nowrap}
.flow__map span:first-child{color:var(--gold)}
.flow__map i{
  flex:0 0 auto;width:clamp(1.4rem,3vw,3rem);height:1px;
  background:linear-gradient(90deg,rgba(212,175,55,.55),var(--line));
}

.thread{position:relative;padding-left:clamp(0px,4vw,5.5rem)}
.thread::before{
  content:"";
  position:absolute;
  left:0;top:0;bottom:0;
  width:1px;
  background:var(--line);
}
/* The drawn half. scaleY from the top, so it reads as being drawn
   downward rather than growing from the middle. */
.thread::after{
  content:"";
  position:absolute;
  left:0;top:0;
  width:1px;
  height:100%;
  transform-origin:top center;
  scale:1 var(--thread,0);
  background:linear-gradient(180deg,var(--gold),var(--gold-soft) 60%,rgba(212,175,55,0));
  box-shadow:0 0 12px rgba(212,175,55,.5);
}
@media (max-width:720px){
  .thread{padding-left:1.6rem}
}

.step{
  position:relative;
  display:grid;
  grid-template-columns:5.5rem 1fr;
  gap:clamp(1rem,3vw,2.5rem);
  padding:clamp(1.8rem,4vw,3rem) 0;
  border-bottom:1px solid var(--line);
}
.step:last-child{border-bottom:0}
/* The node on the thread. Sits ON the line, not beside it.
   A real element rather than a ::before, because about.js has to measure it
   to knot the field around it — a pseudo-element has no box to read. */
.step__node{
  position:absolute;
  left:calc(clamp(0px,4vw,5.5rem) * -1 - 3px);
  top:calc(clamp(1.8rem,4vw,3rem) + .55em);
  width:7px;height:7px;
  border-radius:50%;
  background:var(--gold);
  box-shadow:0 0 10px rgba(212,175,55,.8);
  opacity:.35;
  transition:opacity .5s var(--ease),scale .5s var(--ease);
}
/* .in is the class app.js puts on a revealed .reveal element. */
.step.in .step__node{opacity:1;scale:1.25}
.step__no{font-family:var(--serif);font-size:clamp(1.6rem,3vw,2.4rem);color:var(--grey-dim);line-height:1;transition:color .5s}
@media (hover:hover){.step:hover .step__no{color:var(--gold)}}
.step__title{font-family:var(--serif);font-size:clamp(1.4rem,2.8vw,2.2rem);line-height:1.1;letter-spacing:-.01em}
.step__text{margin-top:.9rem;color:var(--grey);font-weight:300;line-height:1.7;max-width:56ch}

/* Who is on this stage. The same gold-disc / purple-square language as the
   roster below, so the two sections read as one system: by the time the
   roster names the crew, the reader has already met them on the work. */
.step__crew{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.3rem}
.crew{
  display:inline-flex;align-items:center;gap:.55rem;
  padding:.36rem .8rem;
  border:1px solid var(--line);border-radius:100px;
  font-size:.62rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--grey-dim);
}
.crew::before{content:"";flex:0 0 auto;width:6px;height:6px}
.crew--human{border-color:rgba(212,175,55,.34);color:var(--gold)}
.crew--human::before{border-radius:50%;background:var(--gold)}
.crew--ai{border-color:rgba(139,92,255,.32);color:var(--purple-soft)}
.crew--ai::before{border-radius:2px;background:var(--purple-soft)}
@media (max-width:720px){
  .step{grid-template-columns:1fr;gap:.6rem}
  .step__node{left:-1.6rem}
}

/* Read, not seen. The chips carry rank in colour and shape, which a screen
   reader gets neither of — so each one also carries the word. */
.vh{
  position:absolute;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ------------------------------------------------------------
   THE STUDIO BAND
   Three plates, staggered, closing the workflow section. gx_plate() draws
   them until real photographs are dropped into assets/images/about/ — the
   frame is sized for both.
   ------------------------------------------------------------ */
.ab-band{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(1.4rem,3vw,2.6rem);align-items:start;
  margin-top:clamp(3.5rem,8vw,6rem);
}
.ab-card{
  opacity:0;transform:translateY(30px);
  transition:opacity .9s var(--ease) calc(var(--k) * .1s), transform .9s var(--ease) calc(var(--k) * .1s);
}
.ab-card.is-in{opacity:1;transform:none}
/* The middle plate hangs lower, so the row reads as hung rather than ruled. */
.ab-card:nth-child(2){margin-top:clamp(1.2rem,4vw,3.2rem)}

.ab-card__frame{
  position:relative;overflow:hidden;
  aspect-ratio:4/5;border-radius:16px;
  border:1px solid var(--line);
  background:
    radial-gradient(120% 92% at 20% 6%, rgba(109,40,255,.34), transparent 64%),
    linear-gradient(158deg, rgba(212,175,55,.14), #0a0a0b 72%);
  transition:border-color .6s var(--ease), transform .8s var(--ease);
}
@media (hover:hover){.ab-card:hover .ab-card__frame{border-color:rgba(212,175,55,.4);transform:translateY(-8px)}}
.ab-card__frame .plate{
  position:absolute;inset:0;width:100%;height:100%;display:block;
  color:#fff;transition:transform 1.3s var(--ease);
}
@media (hover:hover){.ab-card:hover .ab-card__frame .plate{transform:scale(1.05)}}
.ab-card__frame .plate--photo{object-fit:cover}

.ab-card__cap{padding-top:1.1rem}
.ab-card__label{font-size:.64rem;font-weight:600;letter-spacing:.28em;text-transform:uppercase;color:var(--gold)}
.ab-card__text{margin-top:.6rem;color:var(--grey);font-size:.92rem;font-weight:300;line-height:1.66}

/* ------------------------------------------------------------
   4 · THE STUDIO TEAM
   The claim, then a key, then the roster: one human rank and one digital
   rank, set as a credit block rather than a card grid.

   A grid of equal tiles would say the two ranks are the same kind of thing,
   which is the one claim this section exists to deny. Rows can be unequal —
   the human row is framed and lit, the digital rows are a plain ruled list
   under it — and that hierarchy carries the meaning before a word is read.
   ------------------------------------------------------------ */
.team{position:relative;overflow-x:clip}
.team__glow{
  position:absolute;right:-12%;top:8%;
  width:52vw;height:52vw;max-width:720px;max-height:720px;
  background:radial-gradient(circle,rgba(109,40,255,.15),transparent 62%);
  pointer-events:none;
}

.team__head{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(2rem,5vw,4.5rem);align-items:start;
}
.team__claim{
  font-family:var(--serif);font-size:clamp(2rem,4.6vw,3.6rem);
  line-height:1.06;letter-spacing:-.02em;
}
.team__claim em{color:var(--gold);font-style:italic;font-weight:300}
.team__intro{color:var(--grey);font-weight:300;line-height:1.8;padding-top:.4rem}
.team__intro p + p{margin-top:1.1rem}
.team__intro p:last-child{color:var(--white)}

/* ---- The rank marks ----
   A GOLD DISC is a person, a PURPLE SQUARE is a system. Two channels, not
   one: the colours carry it at a glance and the shapes carry it for a
   colour-blind reader, in greyscale, and in print. Colour alone deciding
   who is human would be the wrong thing to get wrong.

   Purple for the machine and gold for the hand is the site's own scale —
   main.css opens on "purple energy -> gold reward" — so the section borrows
   a distinction the rest of the studio already makes rather than inventing
   a private one for this page. */
.mark{
  flex:0 0 auto;display:inline-block;
  width:8px;height:8px;
}
.mark--human{
  border-radius:50%;
  background:var(--gold);
  box-shadow:0 0 10px rgba(212,175,55,.75);
}
.mark--ai{
  border-radius:2px;
  background:var(--purple-soft);
  box-shadow:0 0 10px rgba(109,40,255,.6);
}

/* The key. Reads as a caption, sits above the roster it explains. */
.team__legend{
  display:flex;flex-wrap:wrap;
  gap:.7rem clamp(1.4rem,3.4vw,2.8rem);
  margin-top:clamp(2.6rem,6vw,4rem);
  padding-bottom:1.4rem;
  border-bottom:1px solid var(--line);
  font-size:.82rem;font-weight:300;color:var(--grey-dim);
}
.legend{display:inline-flex;align-items:center;gap:.65rem}

/* ---- The roster ---- */
.roster{margin-top:clamp(1.6rem,4vw,2.6rem)}

/* The rank heading. Coloured to its rank, so the eye has the answer before
   it reaches the rows. */
.roster__rank{
  display:flex;align-items:center;gap:1rem;
  margin:clamp(2rem,4.5vw,3rem) 0 .4rem;
  font-size:.66rem;font-weight:600;letter-spacing:.28em;text-transform:uppercase;
}
.roster__rank::after{content:"";flex:1;height:1px;background:var(--line)}
.roster__rank--human{color:var(--gold)}
.roster__rank--ai{color:var(--purple-soft)}
.roster__rank:first-child{margin-top:0}

.roster__row{
  display:grid;
  grid-template-columns:minmax(0,17rem) minmax(0,1fr) 7.5rem;
  gap:clamp(1rem,3vw,2.6rem);
  align-items:start;
  padding:clamp(1.5rem,3.2vw,2.1rem) clamp(1rem,2.4vw,1.6rem);
  border-bottom:1px solid var(--line);
  border-left:2px solid transparent;
  opacity:0;transform:translateY(24px);
  transition:opacity .85s var(--ease) calc(var(--k,0) * .08s),
             transform .85s var(--ease) calc(var(--k,0) * .08s),
             border-color .5s var(--ease), background .5s var(--ease);
}
.roster__row.is-in{opacity:1;transform:none}

/* The human row is the only framed one. The digital rows are a list under
   it — which is the org chart, drawn. */
.roster__row--human{
  border-left-color:var(--gold);
  border-radius:0 14px 14px 0;
  background:linear-gradient(100deg,rgba(212,175,55,.07),rgba(17,17,17,.3) 58%);
}
@media (hover:hover){
  .roster__row--ai:hover{
    border-left-color:rgba(139,92,255,.55);
    background:linear-gradient(100deg,rgba(109,40,255,.07),transparent 56%);
  }
}

/* Kind ABOVE name, not below it: on a digital row the words "AI agent" are
   then the first thing read, before the name they qualify. */
.roster__kind{
  display:flex;align-items:center;gap:.6rem;
  font-size:.64rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--grey-dim);
}
.roster__row--human .roster__kind{color:var(--gold)}
.roster__row--ai    .roster__kind{color:var(--purple-soft)}
.roster__name{
  margin-top:.7rem;
  font-family:var(--serif);font-size:clamp(1.25rem,2.2vw,1.7rem);
  line-height:1.14;letter-spacing:-.01em;
}
.roster__does{color:var(--grey);font-size:.95rem;font-weight:300;line-height:1.72;max-width:56ch}

/* One word for what this rank does with the work. It is the distinction the
   whole section turns on, so it gets a column of its own. */
.roster__verb{
  text-align:right;
  font-size:.64rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--grey-dim);
}
.roster__row--human .roster__verb{color:var(--gold)}
.roster__row--ai    .roster__verb{color:var(--purple-soft)}

/* ------------------------------------------------------------
   5 · STUDIO PHILOSOPHY
   The manifesto type comes from main.css; this is the paragraph under it
   and the signature the field closes around.
   ------------------------------------------------------------ */
/* .manifesto's type comes from main.css, which gives it no entrance of its
   own — it is the homepage's furniture, and there it arrives inside a
   pinned scene. Here it is a section opener that scrolls into view like
   everything else on the page, so it gets the same rise. */
.manifesto[data-rise]{
  opacity:0;transform:translateY(26px);
  transition:opacity 1s var(--ease),transform 1s var(--ease);
}
.manifesto[data-rise].is-in{opacity:1;transform:none}

.philosophy__text{
  margin-top:clamp(2rem,4vw,3rem);
  max-width:58ch;
  color:var(--grey);font-weight:300;
  font-size:clamp(1.02rem,1.5vw,1.2rem);line-height:1.8;
}

/* THE SIGNATURE — the field's second gather point: the swarm closes into a
   halo around the mark as the page ends. */
.signature{
  display:grid;place-items:center;
  padding-block:clamp(3rem,9vh,7rem);
  text-align:center;
  opacity:0;transform:translateY(26px);
  transition:opacity 1s var(--ease),transform 1s var(--ease);
}
.signature.is-in{opacity:1;transform:none}
/* The .sig* rules live in main.css — the footer carries a miniature of the
   same mark on every page, so they are shared furniture, not this page. */
.signature__mark{
  display:flex;flex-direction:column;align-items:center;gap:.6rem;
  width:min(100%,36rem);
}
/* The printed name under the written one, the way a signature block sets it. */
.signature__name{
  font-family:var(--sans);
  font-size:.62rem;font-weight:600;letter-spacing:.44em;text-indent:.44em;
  text-transform:uppercase;color:var(--grey-dim);
}
.signature__line{margin-top:1.2rem;color:var(--grey);font-weight:300;max-width:44ch}

/* ------------------------------------------------------------
   RESPONSIVE
   ------------------------------------------------------------ */
@media (max-width:1080px){
  /* The verb column loses its own track and sits under the name, where it
     still reads as this row's standing. Dropping the word instead would
     take out the one thing that states the rank. */
  .roster__row{grid-template-columns:minmax(0,15rem) minmax(0,1fr);gap:1rem 2rem}
  .roster__verb{grid-row:1;grid-column:2;text-align:right}
  .roster__does{grid-column:1 / -1}
}
@media (max-width:980px){
  .ab-head{grid-template-columns:1fr;gap:2.5rem}
  /* The mark leads on a narrow screen rather than being squeezed into a
     column beside the headline. */
  .ab-portrait{order:-1;width:min(58vw,17rem);justify-self:start}

  .founder{grid-template-columns:1fr;gap:clamp(2rem,6vw,3rem)}
  /* Capped once the frame is above the writing rather than beside it: a
     full-width 9:16 portrait on a tablet is most of a screen of face. */
  .founder__figure{max-width:22rem}

  .team__head{grid-template-columns:1fr;gap:1.8rem}
}
@media (max-width:760px){
  .ab-band{grid-template-columns:1fr}
  .ab-card:nth-child(2){margin-top:0}
  .ab-card__frame{aspect-ratio:16/10}

  /* One column, with the verb kept on the kind line — the rank and its
     standing stay together at the top of the row where they are read
     first, and the description follows underneath. */
  .roster__row{grid-template-columns:minmax(0,1fr) auto;gap:.9rem 1rem}
  .roster__id{grid-column:1}
  .roster__verb{grid-column:2;grid-row:1;align-self:start}
  .roster__does{grid-column:1 / -1}
  .roster__name{margin-top:.5rem}
}
@media (max-width:560px){
  .founder__figure{max-width:none}
}

/* ------------------------------------------------------------
   REDUCED MOTION
   ------------------------------------------------------------ */
@media (prefers-reduced-motion:reduce){
  .ab-head__mask > span,.ab-head__desc,.ab-facts,.ab-portrait,
  .founder__figure,.founder__body,.ab-card,.roster__row,
  .manifesto[data-rise],.signature{
    opacity:1;transform:none;transition:none;
  }
  .ab-portrait__ring,.founder__mono-ring{animation:none}
  .ab-card__frame,.ab-card__frame .plate,.founder__frame{transition:none}
  @media (hover:hover){
    .ab-card:hover .ab-card__frame{transform:none}
    .ab-card:hover .ab-card__frame .plate{transform:none}
  }
}
