/* ============================================================
   ABOUT

   Three independent layers, in DOM order (back to front):
     1. .about__text       — heading + statement + message bubbles
     2. .about__ornament   — note + polaroid + post-it, one fluid unit
     3. .message-bubble     — the chat bubbles, always on top (z-index
                               set on .about__bubbles in this file, the
                               bubble's own look lives in base.css)

   .about itself is a plain flex layout (text column / ornament column)
   that wraps naturally when space runs out — there is no single
   "mobile breakpoint" for this section. Everything downstream of that
   (the note's size, its type, the ornament's internal layout) scales
   continuously with real available width, not with a viewport jump.
   ============================================================ */

/* container-type here (independent of the .about__ornament one further
   down, which is about the note's own type) is what lets the ornament
   tell whether it's sitting beside the text or stacked under it —
   see the @container rules on .about__ornament. */
.about {
  container-type: inline-size;
  container-name: about;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: clamp(32px, 5vw, 80px);
  padding-block: clamp(24px, 4vw, 56px);
  max-width: var(--content-max);
  margin: 0 auto;
  padding-inline: var(--gutter);
}

.about__text {
  /* flex-basis 0 (not a px value) keeps this column out of the
     wrap/no-wrap decision — that's driven by the ornament's own fixed
     basis below — while flex-grow:1 still lets it fill whatever room
     is actually left, up to max-width. min-width is a hard floor so
     it can't get shrunk into an unreadable sliver instead of wrapping. */
  flex: 1 1 0%;
  min-width: 280px;
  max-width: 560px;
}

.about__heading {
  font-family: var(--font-headline);
  font-style: italic;
  font-weight: 400;
  text-transform: uppercase;
  font-size: var(--fs-title-section);
  line-height: 1.05;
  text-wrap: pretty;
}

/* The name alone gets a little "signature" flourish the first time it
   scrolls into view (main.js, IntersectionObserver) — it leans past
   its resting angle and settles back, as if it had just been written.
   font-style itself can't be animated smoothly (browsers only ever
   snap between italic/normal, no in-between frames), so the lean is
   faked with skewX, which interpolates properly. transform-origin at
   the baseline (bottom left) keeps the letters pivoting from where
   they'd rest on the line, not from the middle of the word.
   The skew is 8deg, not the 14deg it was: back then the heading was
   upright and the skew had to invent the whole lean, but the heading
   is real Instrument Serif italic now and already leans ~12deg on
   its own, so the old value stacked on top of that and the name
   nearly fell over. 8deg reads as an overshoot of the italic it
   settles into, which is the point of the flourish. */
.about__heading-name {
  display: inline-block;
  transform-origin: bottom left;
  opacity: 0;
  transform: translateY(8px) skewX(-8deg);
}

.about__heading-name.is-visible {
  animation: heading-name-settle 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes heading-name-settle {
  0% { opacity: 0; transform: translateY(8px) skewX(-8deg); }
  60% { opacity: 1; transform: translateY(-2px) skewX(2deg); }
  100% { opacity: 1; transform: translateY(0) skewX(0deg); }
}

.about__statement {
  margin-top: clamp(12px, 2vw, 20px);
  font-family: var(--font-headline);
  text-transform: uppercase;
  font-size: clamp(1rem, 1.8vw, 26px);
  line-height: 1.35;
  text-wrap: pretty;
}

.about__bubbles {
  margin-top: clamp(20px, 3vw, 32px);
  /* Always above the ornament (z-index 0-2 below) — a floating chat
     overlay that never ends up tucked behind another element. */
  position: relative;
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}

/* ============================================================
   ORNAMENT — note + polaroid + post-it, one fluid unit

   Width is the only thing set explicitly (a continuous clamp(), not a
   breakpoint switch) — height is 100% content-driven: the note sizes
   itself to its own text, .about__ornament sizes itself to the note,
   and the polaroid/post-it are positioned as percentages of this same
   box. That's what keeps all three in the same relative arrangement
   (photo overlapping the note's left edge, post-it peeking at its
   bottom-left corner) at every width, from a tall narrow phone layout
   to a short wide desktop one — never a separate "mobile version".

   container-type: inline-size turns on container query units (cqw)
   for the note's type below, so its font-size reflows against this
   box's real rendered width — not the viewport's.
   ============================================================ */
.about__ornament {
  position: relative;
  /* flex-shrink:0 — this column's own clamp() already handles fitting
     smaller viewports; letting flexbox ALSO shrink it on top of that
     would fight the clamp and distort its proportions. */
  flex: 0 0 clamp(300px, 46vw, 620px);
  container-type: inline-size;
  /* Named, so the rules below can ask how wide the NOTE actually is,
     independently of the `about` container the section asks about. The
     two answers come apart badly in the middle of the range: the
     section can be wide enough to seat the note beside the text while
     the note itself is barely half the width it has on a desktop. */
  container-name: ornament;
  /* Stacked (mobile/tablet) default: centered on its own line below
     the text/bubbles (.about's justify-content:center already does
     this — no extra margin needed), with the normal .about `gap` as
     breathing room, no overlap. Overridden below once there's room to
     sit beside the text. */
}

/* Side-by-side (desktop): its top edge lands level with the
   statement's third line, not the heading — heading's own line-height
   + the statement's top margin + two of the statement's own lines,
   all pulled from the exact same clamp()s that size that type, so
   this tracks them if those ever change. */
@container about (min-width: 640px) {
  .about__ornament {
    margin-top: calc(
      clamp(1.5rem, 2.7vw, 39px) * 1.1
      + clamp(12px, 2vw, 20px)
      + clamp(1rem, 1.8vw, 26px) * 1.35 * 2
    );
  }
}

/* Note (info-card) — a plain paper box, not a fixed Figma shape.
   Height is auto: exactly as tall as its info-list content needs at
   whatever width the ornament currently has. */
/* Carries the note's shadow (moved off .about__info-card — see the
   HTML comment for why) so it isn't swallowed by that element's own
   mask-image. Same border-radius as the note so the shadow follows
   its rounded corners correctly. */
.about__note-shadow {
  position: relative;
  z-index: 1;
  border-radius: var(--radius-sm);
  /* Matches the crisp, close drop-shadow baked into the post-it and
     polaroid SVGs (small offset, tight blur, more opaque) instead of
     the soft/spread one this had before, so all three read as the
     same kind of "lifted paper" rather than the note looking flatter. */
  box-shadow: -4px 6px 10px rgba(0,0,0,0.22);
}

.about__info-card {
  position: relative;
  width: 100%;
  background: var(--color-paper);
  border-radius: var(--radius-sm);
  overflow: hidden;
  /* No interactive purpose of its own — let clicks/hovers reach the
     post-it underneath (see the file header). */
  pointer-events: none;
  /* The spiral/punch-hole column ("troquel") along the note's left
     edge is a real cut-out, not a faked circle of page-colored paint:
     mask-image makes those pixels of the card itself transparent, so
     whatever is truly behind the note (page, photo strip, anything)
     shows through. The hole sits a fixed 13px from the left edge and
     the tile is a fixed 26px tall — both in real px, not %, so the
     strip never stretches or deforms as the note's own width/height
     change; it just repeats more or fewer times. */
  -webkit-mask-image: radial-gradient(circle at 13px center, transparent 0 7px, black 7.5px 100%);
  mask-image: radial-gradient(circle at 13px center, transparent 0 7px, black 7.5px 100%);
  -webkit-mask-size: 100% 26px;
  mask-size: 100% 26px;
  -webkit-mask-repeat: repeat-y;
  mask-repeat: repeat-y;
  -webkit-mask-position: left top;
  mask-position: left top;
}

.about__info-card-content {
  position: relative;
  /* Left padding clears both the punch-hole column AND the photo strip
     sitting in front of the note's left edge. Computed from the exact
     same expression as the photo strip's own left+width (about's
     `left: -15%` + `width: max(112px, 58cqi)`, plus a small gap)
     rather than a flat value, because the photo's own floor for
     legibility on narrow notes can otherwise exceed a plain percentage
     reservation and spill over the edge into this padding — matching
     the formula keeps this margin correct (and only as wide as the
     photo actually needs) at every note size. */
  padding: 1.5em 1.6em 1.4em calc(-15% + max(112px, 58cqi) + 10px);
}

.about__info-list {
  display: grid;
  /* minmax(0, 1fr), not a bare 1fr: without the explicit 0 minimum, an
     implicit grid track sizes to its content's max-content (the full,
     unwrapped line) and only THEN lets the item overflow it — the
     classic "grid child ignores the parent and overflows" trap. This
     is what was pushing text like "GRAPHIC & PRODUCT DESIGNER" or
     "(OR INFARO.LAB)" as one unbroken line past the note's edge, for
     .about__info-card's overflow:hidden to silently clip, instead of
     wrapping inside the reserved width like the rest of the text. */
  grid-template-columns: minmax(0, 1fr);
  gap: 0.55em;
  font-family: var(--font-mono-label);
  /* Sized against the ornament's own rendered width (container query
     units), not the viewport — this is what makes the type genuinely
     reflow to whatever room the note actually has at any given width,
     rather than jumping between fixed sizes at a breakpoint. */
  font-size: clamp(10px, 3.4cqw, 14px);
  line-height: 2em;
  text-wrap: pretty;
  /* Safety net for the narrowest notes: a long word (e.g. a longer
     e-mail-style string) that still doesn't fit at the type's own
     floor size breaks mid-word instead of silently disappearing past
     .about__info-card's overflow:hidden. */
  overflow-wrap: break-word;
  /* Ruled lines live here (not on the card) so "em" resolves against
     this element's own font-size — the same basis as line-height —
     and each rule lands exactly under one text line. */
  background-image: repeating-linear-gradient(
    to bottom,
    transparent 0,
    transparent 2em,
    var(--color-paper-lines) 2em,
    var(--color-paper-lines) calc(2em + 1px)
  );
}

.about__info-row {
  display: flex;
  gap: var(--space-3);
  text-transform: uppercase;
  /* Same min-width:auto overflow trap as the grid track above, one
     level down: without this, the value span refuses to shrink/wrap
     below its own unbroken max-content width inside this flex row. */
  min-width: 0;
}

.about__info-value {
  min-width: 0;
}

.about__info-label {
  opacity: 0.45;
  flex: 0 0 5em;
}

/* Photo strip — sits in front of the note's left edge, over the
   punch-hole column. Sized with cqi (container-query width units, %
   of .about__ornament's own rendered width) wrapped in max() against
   a fixed floor — cqi alone keeps the same VISUAL RATIO to the note
   at every size, but on the narrowest notes that ratio alone shrinks
   it into an illegible sliver, so the floor guarantees it stays a
   readable size there. It's allowed to overflow the ornament's own
   left edge and the page gutter on the narrowest layouts (no
   containing clip anywhere in this chain) — the only hard rule is it
   must never cover the note's text, guaranteed by the note's own
   reserved left padding (see .about__info-card-content) rather than
   by constraining the photo's size.

   max-height caps it at the note's own real rendered height: the
   strip's 3-photo aspect ratio would otherwise make it taller than a
   short, wide note once its width scales up, and that excess
   spilling below the note is exactly the space the post-it needs for
   its own corner peek — without this cap the two collide and an icon
   peeks out alongside the post-it's yellow corner instead of just the
   corner. cqb (container query block-size units) can't do this cap:
   they need container-type:size, which would force the ornament to a
   fixed height and break the note's own content-driven auto height —
   so main.js watches the note with a ResizeObserver instead and
   writes its live height into --note-height on .about__ornament. The
   browser re-derives this element's width from the height cap to
   keep its real aspect ratio, so it isn't stretched. */
.about__photo-strip {
  position: absolute;
  left: -15%;
  top: 2%;
  width: max(112px, 58cqi);
  max-height: var(--note-height, 320px);
  height: auto;
  z-index: 2;
  pointer-events: none;
}

/* Post-it — lives behind the note, positioned so that at rest only its
   bottom-left corner peeks past the note's own bottom-left corner.
   Anchored with left/bottom (not top) specifically: that pins it to
   the bottom-left corner directly, regardless of how tall the note
   gets at any given width — a top-based offset would drift away from
   the corner whenever the note's height changes relative to the
   post-it's own height, since it's a fixed height ratio measured from
   the top. min()/max() below give it a floor so it stays legible on
   the narrowest notes while still scaling up with bigger ones — see
   the sizing comment further down for why cqi alone isn't enough.

   A <button> so it's natively focusable/clickable: hovering it
   (desktop) or tapping it (touch, via the JS toggle below) reveals it
   in full. Because the note and polaroid have pointer-events:none,
   this button receives hover/click across its ENTIRE box, including
   the part visually covered by them — not just the visible corner. */
.about__postit {
  position: absolute;
  left: -3%;
  bottom: -5%;
  width: max(130px, 36cqi);
  z-index: 0;
  border: 0;
  margin: 0;
  padding: 0;
  background: none;
  display: block;
  cursor: pointer;
  transition: transform var(--dur-medium) var(--ease-out);
}

.about__tech-icons {
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
}

/* The reveal direction follows available LAYOUT SPACE (the same
   about-container width the rest of the ornament reacts to), not
   input capability — a hover-capable device on a narrow/stacked
   layout still needs it to slide down, since sideways is exactly
   where the stacked column has no room and it used to slide off-
   screen out of view. Both triggers (:hover for a real pointer,
   .is-open toggled by main.js on tap) share the same transform per
   layout mode, so whichever fires first is consistent.

   :hover is gated to (hover: hover) devices specifically — on touch,
   :hover doesn't just fail to help, it actively fights the tap-to-
   toggle: many mobile browsers apply :hover on tap and leave it
   "stuck" until something else is tapped, so a second tap removing
   .is-open (closing it) didn't actually close anything visually,
   since the stuck :hover kept the open transform applied regardless.
   Touch devices now rely on .is-open alone. */
@media (hover: hover) {
  .about__postit:hover {
    transform: translate(-4%, 55%) rotate(3deg);
    z-index: 3;
  }
}

.about__postit:focus-visible,
.about__postit.is-open {
  transform: translate(-4%, 55%) rotate(3deg);
  z-index: 3;
}

@container about (min-width: 640px) {
  /* A bit more of it peeking out at rest on desktop, per Clara. */
  .about__postit {
    left: -6%;
    bottom: -9%;
  }

  /* Same (hover: hover) gating as the base rule above — this
     container query is about available WIDTH, not input type, so a
     wide/landscape touch device (a tablet, say) can still land here
     while having no real hover to speak of. */
  @media (hover: hover) {
    .about__postit:hover {
      transform: translate(-38%, -6%) rotate(-4deg);
    }
  }

  .about__postit:focus-visible,
  .about__postit.is-open {
    transform: translate(-38%, -6%) rotate(-4deg);
  }

  /* Desktop, per Clara: the note's own text gets more of the freed-up
     width back — tightened past the photo's own bounding-box edge
     (which the base padding matches exactly) since the photo is
     rotated and its real visible pixels fall well short of that box
     on this corner, leaving reserved space that wasn't actually
     needed. Unlike the base (mobile/stacked) rule, `left` here is
     POSITIVE, not negative: on desktop the photo sits entirely inside
     the note now (still overlapping its text-free top-left corner,
     still in front via z-index), rather than hanging part-way off the
     note's own left edge into the page gutter. padding-left is sized
     to clear the photo's new right edge plus a small gap, so it still
     marks exactly the note's own text-free margin, just measured from
     this different footprint. */
  /* top shifted up 80px from the base rule's 2% (40px, then another
     40px), desktop only, per Clara — plain subtraction works here
     despite the base value being a %, since that % has already
     resolved to a real px figure by the time an absolutely-positioned
     box like this is placed. */
  .about__photo-strip {
    left: 4%;
    top: calc(2% - 80px);
    width: max(96px, 54cqi);
  }

  .about__info-card-content {
    padding-left: calc(4% + max(96px, 54cqi) + 16px);
  }
}

/* Wider still (a big monitor, browser maximized): .about__ornament's
   own width caps out at 620px (its flex-basis clamp), so past that
   point the photo — sized in cqi, relative to the ornament — had
   already stopped growing too, while everything else on the page kept
   getting more room.

   Controlled by HEIGHT here, not width: this asset's own shape (3
   stacked photos, viewBox 199×558 — much taller than wide) means
   sizing it up via width made it grow height at 2.8x that rate, so
   the same "just widen it" approach that worked fine elsewhere blew
   this past a thousand px tall the moment max-height (the note's own
   height, which is what kept it in check before) was let go of.
   Setting height directly, with width:auto to follow it, is the
   dimension that actually maps to "how big does this look" for a
   strip shaped like this. `left`/padding-left here are fixed px, not
   %/cqi — at this tier the ornament's width is already pinned near
   its 620px cap, so a fixed footprint is simpler than carrying the
   percentage math over for no real benefit. Per Clara, the photo's
   width must stay inside the note (unlike its height, which is fine
   running past the note's own bottom on a screen this wide — that's
   the one dimension this tier doesn't constrain). `top` isn't
   redeclared here — it just carries over the 40px-up shift set at the
   640px tier above. */
@container about (min-width: 900px) {
  .about__photo-strip {
    left: 20px;
    width: auto;
    height: 460px;
    max-height: none;
  }

  .about__info-card-content {
    padding-left: 200px;
  }
}

/* ============================================================
   NARROW NOTE — every width where the note is not near its full size

   Keyed on the note's OWN width, not the section's, because the
   squeeze is the note's alone. The section reaches the 640px that
   seats the ornament beside the text at around a 700px window, where
   the ornament is only 322px wide — and the desktop treatment above
   spends 4% + 54cqi + 16px of that on the photograph, leaving about
   110px for the text. That is what set "CLARA (ALSO INFARO)" as
   "CLAR / A (ALS / O / INFA / RO)": not wrapping, but a column too
   narrow for a single word, breaking mid-word to fit.

   540px is where the desktop treatment stops leaving a readable
   measure (0.42 of the note's width, once the photo and its margins
   are taken out — about 200px there, and falling fast below it).
   Above it nothing here applies and the desktop note is untouched.

   Two things give way, in the order that costs least:

   1. The photograph moves fully inside the note and takes a smaller
      share of it. It loses the overhang past the note's left edge that
      the stacked layout gave it — which was only ever safe while the
      note was alone on its own line, and reaches into the text column
      the moment the section is wide enough to seat the two side by
      side. Inside the note is also what the desktop does.
   2. The label sits ABOVE its value rather than beside it. A 5em
      label out of a 150px column leaves nothing for the value; once
      the label has its own line, the value gets the whole measure.
      The ruled lines are drawn per line of text, so they follow.
   ============================================================ */
@container ornament (max-width: 540px) {
  .about__photo-strip {
    left: 0;
    top: 2%;
    width: max(100px, 40cqi);
  }

  .about__info-card-content {
    padding-left: calc(max(100px, 40cqi) + 12px);
  }

  .about__info-row {
    flex-direction: column;
    gap: 0;
  }

  .about__info-label {
    flex: none;
  }
}

/* Touch only: no reliable hover to signal it's interactive, so a
   periodic wiggle hints at it instead, without revealing the icons. */
@media (hover: none) {
  .about__postit:not(.is-open) {
    animation: postit-wiggle 4.5s ease-in-out infinite;
  }
}

@keyframes postit-wiggle {
  0%, 82%, 100% { transform: rotate(0deg); }
  88% { transform: rotate(-4deg); }
  94% { transform: rotate(3deg); }
}
