/* About panel, the second on the track. Built from Figma keyan-folio-v2, node 921:21611.
   One --about-width column, --about-top (53px) from the top of the card. The panel scrolls down inside itself. */
.about {
  --about-ink: #111111;
  --about-body: rgba(17, 17, 17, 0.9);
  --about-quiet: rgba(154, 147, 147, 0.9);
  --about-rule: rgba(34, 28, 25, 0.07);
  --about-split: #f7f5f4;
  --about-hover: #f7f8fa;
  --logo-line: rgba(198, 198, 198, 0.1);

  color: var(--about-ink);
}

.about h2,
.about h3,
.about p,
.about ul,
.about figure {
  margin: 0;
  padding: 0;
  font: inherit;
}

/* Panels with no content yet. */
.soon {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
  justify-content: center;
}

.soon h2,
.soon p {
  margin: 0;
}

.soon h2 {
  font-size: 14px;
  font-weight: 350;
}

.soon p {
  color: var(--mute);
}

/* Tidbits: three columns of pieces, after Elissa Martial's design page (elissamartial.com/design; Keyan, 2026-10-14):
   each piece as wide as its column, at its own shape (--r, width over height), --tidbit-gap apart every way, with
   rounded corners where hers are square. Corners are the card's less the 12px gutter, so the two curves keep one
   distance apart; pictures that share a piece take 0.75 of that, as smaller boxes do. Each piece is bare on the card
   with the 1px line every picture has inside its edge. Only the phones and the card that came on their own grey ground
   keep a grey plate (.plate.grey), so the ground runs to the plate's edge; a click on that grey opens the picture
   (image-zoom.js). Pictures that share a piece sit side by side (each grows by its own --r, so they share one height)
   or one above the other (.stack), --tidbit-gap apart. The columns share the width evenly and only the heights vary;
   the pieces are in their columns in index.html already, as Keyan laid them out (2026-10-14). A phone shows one column,
   the pieces in reading order (order). The caption shows only in the big view. */
.tiles {
  display: flex;
  align-items: flex-start;
  gap: var(--tidbit-gap);
  padding: 12px 12px 80px;  /* 80px at the foot, up from 40px (Keyan, 2026-10-15: "add more bottom margin") */
}

.tiles-col {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  gap: var(--tidbit-gap);
  min-width: 0;
}

.tidbit {
  display: flex;
  flex-direction: column;
  gap: var(--tidbit-caption-gap);
  margin: 0;
}

.tidbit .plate {
  display: flex;
  align-items: flex-start;
  gap: var(--tidbit-gap);
}

/* A picture keeps the shape its width and height give it while it loads; only pieces that sit side by side set it. */
.tidbit .plate > * {
  display: block;
  flex: none;
  width: 100%;
  min-width: 0;
  height: auto;
  border-radius: calc(var(--card-radius) - 12px);
  outline: 1px solid #f4f4f4;
  outline-offset: -1px;
}

.tidbit .plate:not(.grey, .stack) > * {
  aspect-ratio: var(--r);
}

.tidbit .plate:not(.grey, .stack) > :not(:only-child) {
  flex: var(--r) 1 0;
  width: auto;
}

.tidbit .plate > :not(:only-child) {
  border-radius: calc((var(--card-radius) - 12px) * 0.75);
}

.tidbit .plate.stack {
  flex-direction: column;
}

/* The grey plate, for a piece that came on its own grey ground: the piece takes --h of its height, in the middle. */
.tidbit .plate.grey {
  align-items: center;
  justify-content: center;
  aspect-ratio: var(--r);
  overflow: clip;
  border-radius: calc(var(--card-radius) - 12px);
  background: var(--tidbit-plate);
}

.tidbit .plate.grey > * {
  width: auto;
  height: var(--h, var(--tidbit-height));
  border-radius: var(--tidbit-radius);
}

.tidbit video {
  object-fit: cover;
}

/* A piece's caption shows only once it opens big, under the picture (image-zoom.js), as the about photo's does (Keyan,
   2026-10-14). */
.tidbit figcaption {
  display: none;
}

@media (max-width: 639px) {
  .tiles {
    flex-direction: column;
    align-items: stretch;
  }

  .tiles-col {
    display: contents;
  }
}

/* Figma sets the column 33.5px left of the card centre. */
.column {
  position: relative;
  left: -33.5px;
  display: flex;
  flex-direction: column;
  gap: 43px;
  width: var(--about-width);
  margin: var(--about-top) auto 0;
  padding-bottom: 53px;
}

/* Lede: the photo, a heading, three paragraphs. Figma node 921:23152. */
.lede {
  display: flex;
  flex-direction: column;
  gap: 19px;
  padding-inline: 6px;
}

/* Text sizes. The title has its own, --about-title-size (18px, as Figma has it), whichever way the rest goes. As now
   (--about-one-size 0): the lede 15px, the rows and their labels 13px, as Figma has them. One size (1): every other line
   in the panel at --about-text, each keeping its own weight and leading. */
.lede h2 {
  font-size: var(--about-title-size);
  font-weight: 350;
}

.lede p {
  color: var(--about-body);
  font-size: calc(15px + (var(--about-text) - 15px) * var(--about-one-size));
  line-height: 1.45;
}

/* The photo: a print in a white frame, tipped 2deg, floating over a flat ground shadow, centred in the column or at its
   left (--photo-align). The frame bobs --photo-bob up and back, --photo-bob-time each way (tokens.css), and the shadow
   shrinks and fades as it rises. Only transform and opacity move, so the loop runs off the main thread. The frame moves
   inside .bob, not on its own, as print.js may put an SVG filter on .print; photo.js tilts .print toward the cursor.
   The photo is --photo-width wide (128px as Figma drew it; Keyan, 2026-10-15) and keeps its 128 by 82 shape.
   The box runs from the top of the print (the photo and its 5px of white, 92px tall at 128) to the foot of the shadow:
   --photo-shadow-gap from the print's foot to the shadow, then the shadow. --photo-heading-gap from the shadow's foot to
   the heading, less the lede's own 19px gap (Keyan, 2026-10-14: 9px and 22px, as it was). */
.lede .snap {
  position: relative;
  align-self: var(--photo-align);
  width: calc(var(--photo-width) + 10px);
  height: calc(var(--photo-width) * 82 / 128 + 10px + var(--photo-shadow-gap) + var(--photo-shadow-height));
  margin-bottom: calc(var(--photo-heading-gap) - 19px);
}

.snap .bob {
  position: absolute;
  inset: 0 0 auto;
  animation: photo-bob var(--photo-bob-time) cubic-bezier(.37, 0, .63, 1) infinite alternate;
}

/* 5px of white round the photo, a hairline edge, and a close shadow cast down and right (light from the top left). */
.snap .print {
  position: relative;
  display: block;
  padding: 5px;
  background: #fff;
  box-shadow: 0 0 0 0.5px rgba(71, 67, 60, 0.14), 1px 2px 4px rgba(50, 45, 42, 0.1);
  rotate: var(--photo-turn);
}

.snap img {
  display: block;
  width: var(--photo-width);
  height: calc(var(--photo-width) * 82 / 128);
}

/* Rachel's grain once more, over the photo only (as body::after and the goodbye photo), at --photo-grain: a printed
   tooth on the photo, in place of the pixel art. */
.snap .print::before {
  content: '';
  position: absolute;
  inset: 5px;
  opacity: var(--photo-grain);
  mix-blend-mode: multiply;
  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E") 0 0 / var(--photo-grain-size) repeat;
  pointer-events: none;
}

/* The frame's own shadow, falling on the photo along its top and left edges, multiplied into it. */
.snap .print::after {
  content: '';
  position: absolute;
  inset: 5px;
  box-shadow: inset 1px 1.5px 3px rgba(50, 45, 42, 0.35);
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* A flat ellipse, no blur, as in Figma: #d9d9d9 at 30%. It sits on the box's foot. */
.snap .shadow {
  position: absolute;
  bottom: 0;
  left: calc(50% - var(--photo-shadow-width) / 2);
  width: var(--photo-shadow-width);
  height: var(--photo-shadow-height);
  border-radius: 50%;
  background: rgba(217, 217, 217, 0.3);
  animation: photo-shadow var(--photo-bob-time) cubic-bezier(.37, 0, .63, 1) infinite alternate;
}

/* As an asset (about-art.js, --photo-art): the print is a canvas of pixel art, tipped and framed in its own pixels, so
   the CSS frame, its shadows and the turn step aside, and the photo stays in place, unseen, to hold the size. The
   ground shadow is a stepped ellipse of the same art pixels, its box sized to whole ones. Both are drawn nearest. */
.snap.art-on .print {
  background: none;
  box-shadow: none;
  rotate: none;
}

.snap.art-on .print::before,
.snap.art-on .print::after {
  display: none;
}

.snap.art-on .print img {
  visibility: hidden;
}

.snap .snap-art {
  position: absolute;
  image-rendering: pixelated;
}

/* Outline (--photo-art 2): only the print's edge is pixel art. The canvas draws the frame alone, its photo's place left
   white, and the plain photo sits on it, smooth, tipped by --photo-turn as the canvas's frame is, under its grain and
   the frame's soft shadow. Their own stacking, so the canvas stays under the photo. */
.snap.art-outline .print {
  isolation: isolate;
}

.snap.art-outline .print img {
  position: relative;
  z-index: 1;
  visibility: visible;
  rotate: var(--photo-turn);
}

.snap.art-outline .print::before,
.snap.art-outline .print::after {
  display: block;
  z-index: 2;
  rotate: var(--photo-turn);
}

.snap.art-on .shadow {
  bottom: calc(var(--photo-shadow-height) / 2 - var(--ground-h) / 2);
  left: calc(50% - var(--ground-w) / 2);
  width: var(--ground-w);
  height: var(--ground-h);
  border-radius: 0;
  background: none;
}

.snap .snap-ground {
  display: block;
  image-rendering: pixelated;
}

@keyframes photo-bob {
  to { transform: translateY(calc(-1 * var(--photo-bob))); }
}

@keyframes photo-shadow {
  to { transform: scale(0.88); opacity: 0.65; }
}

@media (prefers-reduced-motion: reduce) {
  .snap :is(.bob, .shadow) {
    animation: none;
  }
}

/* Experience and Q&A: a label, then 60px rows split by pale rules. */
.rows {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.rows h3 {
  padding-inline: 8px;
  color: var(--about-body);
  font-size: calc(var(--text-size) + (var(--about-text) - var(--text-size)) * var(--about-one-size));
}

.rows ul {
  display: flex;
  flex-direction: column;
  list-style: none;
}

.rows li {
  position: relative;
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 16px 8px;
  border-radius: 14px;
  font-size: calc(13px + (var(--about-text) - 13px) * var(--about-one-size));
  /* --about-row-time (tokens.css) on the sheet curve the home projects' hover uses, quicker than their 500ms. The
     rules and the greys below take the same --row-in, so the whole hover moves as one. */
  --row-in: var(--about-row-time) var(--motion-ease-sheet);
  transition: background-color var(--row-in);
}

/* Each rule sits on the seam between two rows and runs 8px in from either end. */
.rows li + li::before {
  content: '';
  position: absolute;
  top: -0.5px;
  right: 8px;
  left: 8px;
  height: 1px;
  background: var(--about-split);
  transition: opacity var(--row-in);
}

/* A row under the pointer fills, the rules on either side of it drop out, and its greys (the role, the slash, the
   year) darken to --project-date-hover, as a home project's date does under its hover grey. */
@media (hover: hover) {
  .rows li:hover {
    --about-quiet: var(--project-date-hover);
    background: var(--about-hover);
  }

  .rows li:hover::before,
  .rows li:hover + li::before {
    opacity: 0;
  }
}

.rows li p:first-of-type {
  flex: 1;
  min-width: 0;
  color: var(--about-body);
}

.rows b {
  font-weight: 350;
}

/* Each company's name links to its site, in a new tab, and the link reaches over its whole row (li is relative), so the
   row clicks anywhere. Its focus ring goes round the row, not the name. */
.rows .row-link {
  color: inherit;
  text-decoration: none;
}

.rows .row-link::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.rows .row-link:focus-visible {
  outline: none;
}

.rows .row-link:focus-visible::after {
  outline: 1px solid var(--mute);
  outline-offset: 2px;
}

html.pointing .rows .row-link:focus-visible::after {
  outline: none;
}

.rows span,
.rows .year {
  color: var(--about-quiet);
  transition: color var(--row-in);
}

/* Grey like the role, or the black of the company: --slash-dim in tokens.css. */
.rows .slash {
  color: color-mix(in srgb, var(--about-quiet) calc(var(--slash-dim) * 100%), var(--about-body));
}

.rows .year {
  flex: none;
  white-space: nowrap;
}

/* Logos are 28px tiles with a faint line drawn over the edge. */
.logo {
  flex: none;
  border-radius: 7px;
  outline: 0.438px solid var(--logo-line);
  outline-offset: -0.438px;
}

/* Q&A rows end in a 16px chevron where Experience has a year. Figma node 922:23418. */
.chevron {
  flex: none;
}

/* Q&A ends with one darker rule, 4px under the last row. */
.qa ul::after {
  content: '';
  height: 1px;
  margin: 4px 8px 0;
  background: var(--about-rule);
}

/* The design covers desktop only. Below 900px the column fills the card. */
@media (max-width: 899px) {
  .column {
    left: 0;
    width: auto;
    margin: 32px 16px 0;
    padding-bottom: 32px;
  }
}
