/* ═══════════════════════════════════════════════════════════════════
   THE INDEX
   ═══════════════════════════════════════════════════════════════════

   Loaded last. Replaces the card grid in two sections, and only those:
   "What I do" and "What I build and run".

   WHY

   Anric, twice: "clunky entry-level HTML text boxes", "that looks
   awful", "not much better". The first attempt at this shrank the type
   and equalised the card heights, which was answering the wrong
   question. A grid of bordered rectangles IS the entry-level answer.
   Every framework starter ships one, every AI-generated page produces
   one, and no amount of tuning the padding makes it read as designed.

   So: no boxes. No borders, no card backgrounds, no rounded corners.
   The structure is an index, the way a well-set annual report or a
   luxury house's service list is an index: a hairline between entries,
   a numeral in the margin, and typographic hierarchy carrying the rest.

   What makes it read as expensive is restraint plus one deliberate
   moment. The restraint is that nothing is enclosed. The moment is that
   the hairline lights up and travels on hover, which is the only
   animation here.

   ONE COMPONENT, TWO CONTENTS

   .b-index is shared. Practice areas use the three-column form with a
   numeral. Ventures use the same rows with the category in the numeral
   slot and the domain pushed right, because a directory of eleven
   things wants to be scanned down the left edge and clicked on the
   right.

   ═══════════════════════════════════════════════════════════════════ */

.b-index {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  border-top: 1px solid var(--b-hairline);
}

/* The row. Grid rather than flex because the three tracks must align
   down the whole list: a numeral column that never moves, a title
   column that takes the slack, and a detail column that stays put so
   the eye can run down it. Flex would let each row size its own
   columns and the list would wander. */
.b-index-row {
  position: relative;
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(14px, 2vw, 34px);
  align-items: start;
  padding: clamp(20px, 2.1vw, 30px) 0;
  border-bottom: 1px solid var(--b-hairline);
}

/* The travelling light. A hairline that brightens and sweeps left to
   right, so hovering an entry feels like it was picked out rather than
   highlighted. transform on a pseudo-element, so it composites and
   costs nothing per frame. */
.b-index-row::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    var(--mv-gold) 18%,
    #ffe0a3 50%,
    var(--mv-gold) 82%,
    transparent
  );
  opacity: 0;
  transform: scaleX(0.25);
  transform-origin: left center;
  transition: opacity 0.3s, transform 0.55s var(--lu-glide);
}

.b-index-row:hover::after,
.b-index-row:focus-within::after {
  opacity: 1;
  transform: scaleX(1);
}

/* Slot 1: the numeral, or the category on a venture row.
   Tabular figures so 01 through 11 occupy identical width and the
   second column starts at the same x on every row. Without this the
   list visibly steps in and out as the digits change. */
.b-index-num {
  font-family: var(--mv-font-display);
  font-size: var(--b-step-micro);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.16em;
  line-height: 1.9;
  color: var(--mv-gold-dark);
  text-transform: uppercase;
  padding-top: 0.15em;
}

/* Slot 2: name and its one line. */
.b-index-name {
  font-family: var(--mv-font-display);
  font-size: clamp(16px, 1.35vw, 21px);
  font-weight: 400;
  line-height: 1.2;
  margin: 0;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--b-text-ivory);
  transition: color 0.25s;
}
.b-index-row:hover .b-index-name,
.b-index-row:focus-within .b-index-name { color: var(--mv-gold); }

.b-index-name a { color: inherit; text-decoration: none; }

.b-index-lede {
  margin: 7px 0 0;
  font-size: var(--b-step-body);
  color: var(--mv-gold-dark);
  max-width: 34ch;
}

.b-index-body {
  margin: 9px 0 0;
  font-size: var(--b-step-body);
  line-height: 1.6;
  color: var(--b-temp-body);
  max-width: 46ch;
}

/* Slot 3: the detail column. Points on a practice row, the link on a
   venture row. */
.b-index-points {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.b-index-points li {
  position: relative;
  padding-left: 17px;
  font-size: var(--b-step-micro);
  letter-spacing: 0.05em;
  line-height: 1.55;
  color: var(--b-temp-body);
}

/* A rule, not a bullet or a tick. Squared, which the brand allows, and
   it borrows no shape from anybody else's icon set. Positioned against
   the line box rather than centred, because a centred mark next to a
   two-line item reads as an accident. */
.b-index-points li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.66em;
  width: 8px;
  height: 1px;
  background: var(--mv-gold);
  opacity: 0.7;
}

.b-index-meta {
  margin: 12px 0 0;
  font-size: var(--b-step-micro);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--mv-gold-dark);
}

/* The venture row's link. Right-aligned on wide screens so eleven
   domains form a clean column to click down. */
.b-index-go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--b-step-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mv-gold);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s, gap 0.25s var(--lu-glide);
}
.b-index-go svg { width: 15px; height: 6px; }
.b-index-row:hover .b-index-go,
.b-index-go:focus-visible { border-bottom-color: var(--mv-gold); gap: 13px; }

.b-index-detail { display: flex; flex-direction: column; align-items: flex-start; }
.b-index--dir .b-index-detail { align-items: flex-end; text-align: right; }

/* A venture with no approved blurb is not a hole. The honesty rule in
   data.js says it renders as name and link only, and in an index that
   reads as a deliberately terse entry rather than as an empty box,
   which is the other reason boxes were the wrong container. */

/* ── Narrow ───────────────────────────────────────────────────────
   Below 900px the third column has nowhere to go, so the row collapses
   to two: the numeral keeps its margin, everything else stacks under
   the title. The numeral column is the one thing that must survive,
   because it is what still makes it read as an index rather than as a
   pile of paragraphs. */

@media (max-width: 900px) {
  .b-index-row { grid-template-columns: 2.5rem minmax(0, 1fr); }
  .b-index-detail,
  .b-index--dir .b-index-detail {
    grid-column: 2;
    align-items: flex-start;
    text-align: left;
    margin-top: 14px;
  }
  .b-index-lede, .b-index-body { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  .b-index-row::after { transition: none; }
  .b-index-row:hover::after,
  .b-index-row:focus-within::after { transform: none; }
  .b-index-go { transition: border-color 0.2s; }
  .b-index-row:hover .b-index-go { gap: 8px; }
}

/* ═══════════════════════════════════════════════════════════════════
   THE SHELF AND THE RACK
   ═══════════════════════════════════════════════════════════════════

   Anric: "you have built a very elementary, basic website that an intern
   could have built in an afternoon" and "we have so much material".

   Both sections below exist because the material was already in the repo
   and the page was ignoring it. Nine book covers sat in books-site while
   the books section rendered as a list of titles. Six magazine covers sat
   in magazine-site with no magazine section on the page at all.

   A book sells on its cover. A list of nine titles set in a display face
   sells nothing, and it is the single clearest reason the page read as
   thin: it had a bibliography where it should have had a shelf.
   ═══════════════════════════════════════════════════════════════════ */

.b-shelf {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(22px, 2.6vw, 38px);
  border-top: 1px solid var(--b-hairline);
  padding-top: clamp(22px, 2.6vw, 34px);
}
@media (min-width: 720px)  { .b-shelf { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1120px) { .b-shelf { grid-template-columns: repeat(3, 1fr); } }

/* Cover beside text, not above it. A cover stacked over its own blurb
   makes every card tall and turns nine books into a very long scroll;
   side by side keeps three across on a desktop and reads like a
   catalogue entry. */
.b-book {
  display: grid;
  grid-template-columns: minmax(88px, 116px) minmax(0, 1fr);
  gap: clamp(14px, 1.5vw, 20px);
  align-items: start;
}

.b-book-cover {
  display: block;
  position: relative;
  border-radius: 4px;
  overflow: hidden;
  /* The three-part object recipe from lustre.css, at book scale: ambient,
     contact, and a lip along the top edge. A cover with no shadow reads as
     a picture of a book; with one it reads as a book. */
  box-shadow:
    0 16px 30px -18px rgba(0,0,0,0.95),
    0 4px 10px -6px rgba(0,0,0,0.85),
    inset 0 1px 0 rgba(255,255,255,0.08);
  transition: transform 0.45s var(--lu-glide), box-shadow 0.45s var(--lu-glide);
}
.b-book-cover img { width: 100%; height: auto; display: block; }

/* A real book has a spine. This is one hairline of gold at the binding
   edge, which is what stops the cover looking like a flat rectangle. */
.b-book-cover::after {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: linear-gradient(180deg,
    rgba(255,224,163,0.30), rgba(250,189,89,0.12) 40%, rgba(0,0,0,0.5));
  pointer-events: none;
}

.b-book:hover .b-book-cover,
.b-book:focus-within .b-book-cover {
  transform: translateY(-4px);
  box-shadow:
    0 26px 44px -18px rgba(0,0,0,0.95),
    0 6px 14px -6px rgba(0,0,0,0.85),
    inset 0 1px 0 rgba(255,224,163,0.20);
}

/* No cover on file yet: hold the same footprint rather than collapsing and
   knocking the row out of alignment. */
.b-book-nocover {
  display: block;
  aspect-ratio: 2 / 3;
  background: linear-gradient(148deg, rgba(255,255,255,0.05), rgba(0,0,0,0.4));
  border: 1px solid var(--b-hairline);
}

.b-book-text { display: flex; flex-direction: column; }
.b-book-kind {
  font-family: var(--mv-font-display);
  font-size: var(--b-step-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mv-gold-dark);
  margin: 0 0 6px;
}
.b-book-title {
  font-size: clamp(14px, 1.05vw, 16px);
  line-height: 1.25;
  margin: 0 0 8px;
  text-transform: uppercase;
}
.b-book-title a { color: var(--b-text-ivory); text-decoration: none; transition: color 0.25s; }
.b-book:hover .b-book-title a { color: var(--mv-gold); }
.b-book-blurb {
  font-size: var(--b-step-micro);
  line-height: 1.6;
  color: var(--b-temp-body);
  margin: 0;
  /* Blurbs run from 120 to 400 characters. Clamping to five lines keeps
     the shelf even without editing anybody's copy; the full text is on the
     book's own page, which is where the link goes. */
  display: -webkit-box;
  -webkit-line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.b-book-go { margin: 12px 0 0; }

/* ── The magazine rack ────────────────────────────────────────────
   Six covers, presented as forthcoming. The status line is not
   decoration: MAGAZINE.status says "First issue, Fall 2026", and showing
   six covers without it would read as six issues somebody could buy. */

.b-rack {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(14px, 1.8vw, 26px);
  border-top: 1px solid var(--b-hairline);
  padding-top: clamp(22px, 2.6vw, 34px);
}
@media (min-width: 720px)  { .b-rack { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1120px) { .b-rack { grid-template-columns: repeat(6, 1fr); } }

.b-rack-item { margin: 0; }
.b-rack-item img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 3px;
  box-shadow:
    0 14px 26px -16px rgba(0,0,0,0.95),
    inset 0 1px 0 rgba(255,255,255,0.07);
  transition: transform 0.45s var(--lu-glide);
}
.b-rack-item:hover img { transform: translateY(-4px); }

.b-rack-item figcaption {
  margin-top: 10px;
  font-size: var(--b-step-micro);
  line-height: 1.45;
  color: var(--b-temp-body);
}
.b-rack-n {
  display: block;
  font-family: var(--mv-font-display);
  color: var(--mv-gold-dark);
  letter-spacing: 0.16em;
  margin-bottom: 3px;
  font-variant-numeric: tabular-nums;
}

.b-rack-note {
  margin: clamp(20px, 2.2vw, 30px) 0 0;
  font-size: var(--b-step-body);
  color: var(--b-temp-body);
  max-width: 56ch;
}
.b-rack-status {
  margin: 10px 0 0;
  font-family: var(--mv-font-display);
  font-size: var(--b-step-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mv-gold);
}

@media (prefers-reduced-motion: reduce) {
  .b-book:hover .b-book-cover,
  .b-book:focus-within .b-book-cover,
  .b-rack-item:hover img { transform: none; }
}

/* ── Press kit ────────────────────────────────────────────────────
   Approved wording, laid out to be copied rather than admired.

   The two blockquotes are the product here, so they get the strongest
   treatment on the page after the hero: a gold rule down the left edge,
   generous line height, and a measure that stops at 68 characters, which
   is where prose starts being hard to scan. Someone lands here to take
   something away, and everything else on the page is subordinate to
   making that easy. */

.b-kit { display: grid; gap: clamp(22px, 2.6vw, 34px); }
.b-kit-part { display: grid; gap: 8px; }

.b-kit h3 {
  font-family: var(--mv-font-display);
  font-size: 12px;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  text-transform: uppercase;
  color: var(--mv-gold);
  margin: 0;
}

.b-kit-dim {
  margin: 0;
  font-size: var(--b-step-micro);
  color: #8f887c;
}

/* user-select is set explicitly rather than left to default. The whole
   point of this block is that the text leaves the page, and a stray
   user-select:none anywhere up the tree would silently defeat it. */
.b-kit-copy {
  margin: 4px 0 0;
  padding: clamp(14px, 1.5vw, 20px) clamp(16px, 1.8vw, 24px);
  border-left: 2px solid var(--mv-gold);
  border-radius: 0 8px 8px 0;
  background: linear-gradient(90deg, rgba(250, 189, 89, 0.06), rgba(0, 0, 0, 0.28));
  color: #e4dccd;
  font-size: var(--b-step-body);
  line-height: 1.72;
  max-width: 68ch;
  -webkit-user-select: text;
          user-select: text;
}
.b-kit-copy span { display: block; }
.b-kit-copy span + span { margin-top: 0.9em; }

.b-kit-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(18px, 2vw, 30px);
}
@media (max-width: 700px) { .b-kit-grid { grid-template-columns: 1fr; } }

.b-kit-list { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 8px; }
.b-kit-list li {
  position: relative;
  padding-left: 16px;
  font-size: var(--b-step-body);
  line-height: 1.5;
  color: var(--b-temp-body, #b9b2a5);
}
.b-kit-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 7px;
  height: 2px;
  background: rgba(250, 189, 89, 0.72);
}
.b-kit-list .b-kit-dim { display: block; margin-top: 2px; }

/* ── The Right Fit filter line ────────────────────────────────────
 *
 * The sentence at the foot of "Who I work with" that tells a reader
 * they are NOT one of the four. It is not a fifth row, so it must not
 * look like one: no numeral, no three-column grid, no rule above it
 * that would read as another entry in the list.
 *
 * Set apart by the gold left edge and the indent instead. That marks it
 * as a remark on the list rather than a member of it, which is what it
 * is, and it borrows the gold the numerals already use so it arrives as
 * part of the same section rather than a callout bolted on.
 *
 * Left border rather than a full box, because a box here would be the
 * bordered-rectangle pattern the index exists to avoid.
 *
 * max-width is in ch, not px: this is one long sentence and the measure
 * has to hold at roughly 70 characters for it to stay readable, whatever
 * the surrounding column happens to be doing. */
.b-index-filter {
  margin: 34px 0 0;
  padding: 4px 0 4px 22px;
  border-left: 2px solid var(--mv-gold);
  max-width: 70ch;
  font-size: var(--b-step-0);
  line-height: 1.62;
  color: var(--mv-text-dim, #b9b4ab);
}

@media (max-width: 700px) {
  .b-index-filter {
    margin-top: 26px;
    padding-left: 16px;
  }
}
