/* IJWestern — the About page. Step 8.
   Prefix: ab-  ·  zero collisions with styles.css, project.css or
   projects.css (pp-, wm-, bh-, px-, nl-, lb-, md- were the ones taken).

   Depends on styles.css for the tokens, .shell, .cta-row, .btn, the
   .reveal system and the whole .story block, which came back into use
   with this page. Nothing already defined there is redefined here, and
   there is not one literal radius, weight or font-size below: step 2's
   rule holds. */

.ab-page {
  padding: calc(var(--topbar-gap) + var(--topbar-h) + clamp(36px, 4.6vw, 72px)) 0 0;
}

/* The one colour this page adds, and it only exists over the map.
   Laterite gold is the site's accent everywhere else, but on the map it
   sits in the same band as Maps' own yellow road shields and the client
   could not pick the markers out (3 Sep). This is the same laterite
   earth an hour later in the day: red enough that nothing on a Google
   basemap competes with it. Scoped here rather than added to the
   palette in styles.css, because nothing off this page should reach
   for it. */
.ab-map {
  --plot-marker: #DE4218;
  --plot-marker-deep: #B33210;
  /* Vermilion on near-black clears AA at 12px only once it is lifted
     toward the parchment. */
  --plot-marker-lift: color-mix(in oklab, var(--plot-marker) 58%, var(--ground-white));
}

/* ─── Hero ───────────────────────────────────────────────────────── */
.ab-hero {
  padding-bottom: clamp(64px, 8vw, 116px);
  background: var(--ground-white);
}
.ab-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  gap: clamp(32px, 4.5vw, 72px);
  align-items: center;
}
.ab-intro { min-width: 0; }

/* The gold rule that sat before the label came out at the client's
   request after step 9. It was the only thing the flex row and the gap
   existed for, so they went with it and the label is plain text again. */
.ab-eyebrow {
  margin: 0 0 clamp(14px, 1.6vw, 22px);
  font-family: var(--font-eyebrow);
  font-size: var(--fs-micro);
  font-weight: var(--fw-strong);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--contour-gray);
}

/* Smaller than the display headline on the other pages, deliberately.
   The client asked for short titles, and at 68px a whole sentence is
   four lines of about fourteen characters — long, whatever its word
   count. At this size it is two. */
.ab-title {
  margin: 0 0 clamp(20px, 2.4vw, 32px);
  font-size: clamp(32px, 3.4vw, 50px);
  font-weight: var(--fw-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
}
.ab-title em {
  font-style: normal;
  font-weight: var(--fw-accent);
  color: var(--survey-ink);
}

.ab-lead {
  margin: 0 0 clamp(16px, 1.8vw, 24px);
  font-size: clamp(17px, 1.25vw, 19px);
  line-height: 1.62;
  font-weight: var(--fw-body);
  color: color-mix(in oklab, var(--survey-ink) 80%, transparent);
  max-width: 54ch;
  text-wrap: pretty;
}
.ab-body {
  margin: 0;
  font-size: var(--fs-body);
  line-height: 1.68;
  font-weight: var(--fw-body);
  color: color-mix(in oklab, var(--survey-ink) 68%, transparent);
  max-width: 54ch;
  text-wrap: pretty;
}
.ab-cta { margin-top: clamp(24px, 3vw, 38px); }

/* ─── The map ────────────────────────────────────────────────────────
   The terrain is the client's own Google Maps view of the district,
   cropped square (site-images/palakkad-map.png). Everything over it is
   ours. The frame carries a wash so a Maps green sits inside a palette
   of parchment and ink rather than on top of it, and the whole thing
   opens on scroll: the frame unclips from 9% in while the photograph
   settles out of a slight zoom. */
.ab-map {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1vw, 14px);
  min-width: 0;
}
.ab-map-stage {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-media-lg);
  overflow: hidden;
  background: var(--stone-surface);
  border: 1px solid color-mix(in oklab, var(--survey-ink) 12%, transparent);
  box-shadow: 0 18px 44px -28px rgba(26, 25, 22, 0.45),
              0 1px 2px rgba(26, 25, 22, 0.05);
  perspective: 1100px;
  /* Tag widths are capped in cqw, so they stay a fixed share of the
     map however wide the column gets. */
  container-type: inline-size;
  clip-path: inset(9% round var(--radius-media-lg));
  transition: clip-path 1s cubic-bezier(0.16, 0.84, 0.28, 1) var(--reveal-delay, 0ms);
}
.ab-map.in .ab-map-stage { clip-path: inset(0 round var(--radius-media-lg)); }

.ab-map-tilt {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform 0.55s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.ab-map-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Maps ships a brighter, greener image than this site owns. */
  filter: saturate(0.7) contrast(1.03) brightness(1.02);
  transform: scale(1.09);
  transition: transform 1.3s cubic-bezier(0.16, 0.84, 0.28, 1) var(--reveal-delay, 0ms);
}
.ab-map.in .ab-map-img { transform: scale(1); }

.ab-map-wash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(118% 96% at 50% 42%, transparent 50%,
      color-mix(in oklab, var(--survey-ink) 15%, transparent) 100%),
    linear-gradient(180deg,
      color-mix(in oklab, var(--laterite-gold) 8%, transparent),
      color-mix(in oklab, var(--ground-white) 13%, transparent));
}

.ab-map-cap {
  margin: 0;
  padding-left: 2px;
  font-size: var(--fs-meta);
  line-height: 1.5;
  font-weight: var(--fw-body);
  color: color-mix(in oklab, var(--survey-ink) 52%, transparent);
}

/* ─── Markers and name tags ──────────────────────────────────────────
   The pin is a 44px hit area centred on its coordinate; everything
   visible inside it is smaller than that. The marker pulses, and the
   active one pops its name up out of the pin: the tag scales from the
   corner the stem stands in, with a little overshoot going in and a
   quick, unweighted exit going out.

   Only ever one tag is up at a time, so tags cannot collide with each
   other and the only thing to keep them clear of is the edge of the
   frame. Which way each one points is set per marker in about.jsx,
   chosen so the widest tag still has room. */
.ab-pins { position: absolute; inset: 0; transform: translateZ(26px); }

.ab-pin {
  position: absolute;
  width: 44px;
  height: 44px;
  margin: -22px 0 0 -22px;
  display: grid;
  place-items: center;
  border-radius: 50%;
}
.ab-pin:focus-visible {
  outline: 2px solid var(--plot-marker);
  outline-offset: 1px;
}

.ab-pin-dot {
  position: relative;
  width: 18px;
  height: 18px;
  display: block;
}
.ab-pin-core {
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: var(--plot-marker);
  /* A parchment collar and a real shadow: the map is busy, and a flat
     disc on it reads as one more POI dot. */
  box-shadow: 0 0 0 3px var(--ground-white),
              0 2px 6px rgba(26, 25, 22, 0.45);
  transition: inset 0.3s cubic-bezier(0.22, 1.2, 0.4, 1),
              background-color 0.3s ease,
              box-shadow 0.3s ease;
}
.ab-pin-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--plot-marker);
  opacity: 0;
  animation: ab-pulse 2.9s cubic-bezier(0.2, 0.7, 0.2, 1) infinite;
  animation-delay: calc(var(--pin-i) * 0.4s);
}
.ab-pin-ring.is-late { animation-delay: calc(var(--pin-i) * 0.4s + 1.45s); }

@keyframes ab-pulse {
  0%   { transform: scale(0.5); opacity: 0.8; }
  70%  { transform: scale(2.5);  opacity: 0; }
  100% { transform: scale(2.5);  opacity: 0; }
}

.ab-pin.is-on .ab-pin-core {
  inset: 1px;
  background: var(--plot-marker-deep);
  box-shadow: 0 0 0 3.5px var(--ground-white),
              0 3px 11px rgba(26, 25, 22, 0.5);
}

/* The tag */
.ab-flag {
  position: absolute;
  bottom: calc(50% + 7px);
  display: flex;
  flex-direction: column-reverse;
  pointer-events: none;
}
.ab-pin[data-side="right"] .ab-flag { left: 50%;  align-items: flex-start; }
.ab-pin[data-side="left"]  .ab-flag { right: 50%; align-items: flex-end; }

.ab-flag-stem {
  height: clamp(18px, 2.2vw, 26px);
  width: 2px;
  background: linear-gradient(
    to top,
    color-mix(in oklab, var(--plot-marker) 35%, transparent),
    var(--plot-marker));
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.18s cubic-bezier(0.4, 0, 1, 1);
}
.ab-pin.is-on .ab-flag-stem {
  transform: scaleY(1);
  transition: transform 0.3s cubic-bezier(0.22, 1.1, 0.4, 1) 0.04s;
}

.ab-flag-plate {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: max-content;
  max-width: 38cqw;
  padding: 6px 11px 7px;
  border-radius: var(--radius-media-sm);
  /* Ink, not parchment. The map is mostly white and pale green, and a
     near-white plate on it disappeared. */
  background: color-mix(in oklab, var(--survey-ink) 95%, transparent);
  backdrop-filter: blur(8px);
  border: 1px solid color-mix(in oklab, var(--ground-white) 16%, transparent);
  box-shadow: 0 14px 32px -14px rgba(26, 25, 22, 0.75),
              0 2px 6px rgba(26, 25, 22, 0.22);
  opacity: 0;
  transform: translateY(7px) scale(0.9);
  transition: opacity 0.16s ease, transform 0.2s cubic-bezier(0.4, 0, 1, 1);
}
.ab-pin[data-side="right"] .ab-flag-plate { transform-origin: left bottom; }
.ab-pin[data-side="left"]  .ab-flag-plate { transform-origin: right bottom; }
.ab-pin.is-on .ab-flag-plate {
  opacity: 1;
  transform: translateY(0) scale(1);
  transition: opacity 0.2s ease 0.09s,
              transform 0.46s cubic-bezier(0.22, 1.3, 0.4, 1) 0.09s;
}

.ab-flag-num {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: var(--fw-strong);
  letter-spacing: 0.1em;
  color: var(--plot-marker-lift);
  flex: none;
}
.ab-flag-name {
  font-family: var(--font-display);
  font-size: var(--fs-ui);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-card);
  line-height: var(--lh-card);
  color: var(--ground-white);
  white-space: nowrap;
}
.ab-flag-name .pname-phase { white-space: nowrap; }

/* The Story heading, at the same size as this page's own. styles.css
   sets it at up to 80px, which was right under a home page hero and is
   too much here. story.jsx renders on this page and no other, so the
   override lives with the rest of that section's step-8 changes. */
.ab-page .story-title {
  font-size: clamp(30px, 3.4vw, 50px);
  margin-bottom: 0;
}

/* "Meet the founder", under the heading rather than over it, which is
   how the client asked for it. */
.ab-page .story-sub {
  margin: clamp(10px, 1.2vw, 14px) 0 clamp(26px, 3vw, 40px);
  font-family: var(--font-eyebrow);
  font-size: var(--fs-micro);
  font-weight: var(--fw-strong);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--contour-gray);
}

/* Six paragraphs, not two. A two-track grid laid them out across the
   rows, which reads left-right-left-right and leaves ragged gaps when
   one is short; multi-column flows them down one column and then the
   next, which is the order they are written in. */
.ab-page .story-cols {
  display: block;
  columns: 2;
  column-gap: clamp(20px, 2.4vw, 40px);
}
.ab-page .story-cols .story-p {
  break-inside: avoid;
  margin: 0 0 1.15em;
}
.ab-page .story-cols .story-p:last-child { margin-bottom: 0; }

@media (max-width: 860px) {
  .ab-page .story-cols { columns: 1; }
}

/* ─── Two rules the Story section gained in step 8 ───────────────────
   The line under the two columns, carrying what the brand deck calls
   The Shift. It lives here rather than in styles.css because story.jsx
   renders on this page and no other; if the section is ever reused, it
   moves across with the rest of the .story block. */
.ab-page .story-pull {
  margin: clamp(28px, 3.2vw, 44px) 0 0;
  padding-top: clamp(20px, 2.4vw, 28px);
  border-top: var(--rule);
  font-size: clamp(18px, 1.4vw, 22px);
  line-height: 1.55;
  font-weight: var(--fw-strong);
  letter-spacing: -0.012em;
  color: color-mix(in oklab, var(--survey-ink) 88%, transparent);
  max-width: 60ch;
  text-wrap: pretty;
}

/* ─── Responsive ─────────────────────────────────────────────────────
   Two columns only while the map is wide enough for the widest tag to
   stay inside the frame. Below that the hero stacks and the map takes
   the shell, which gives every tag more room than it needs. */
@media (max-width: 1100px) {
  .ab-hero-grid { grid-template-columns: minmax(0, 1fr); }
  .ab-intro { max-width: 62ch; }
  .ab-map { max-width: 660px; }
}

@media (max-width: 640px) {
  .ab-flag-plate { padding: 5px 9px 6px; gap: 6px; }
  .ab-flag-name { font-size: var(--fs-meta); }
  .ab-pin { width: 38px; height: 38px; margin: -19px 0 0 -19px; }
}

/* ─── Reduced motion ─────────────────────────────────────────────────
   Nothing pulses, nothing advances, nothing pops and the frame does not
   open: the map is simply there, with the first name up. about.jsx
   stops the cycle and the tilt at the same time; hover and Tab still
   move the name. styles.css already neutralises .reveal-fade itself,
   but not the two things inside it that this page animates. */
@media (prefers-reduced-motion: reduce) {
  .ab-map-tilt,
  .ab-flag-stem,
  .ab-flag-plate,
  .ab-pin-core { transition: none; }
  .ab-pin-ring { animation: none; opacity: 0; }
  .ab-map-stage {
    clip-path: inset(0 round var(--radius-media-lg));
    transition: none;
  }
  .ab-map-img { transform: none; transition: none; }
}
.ab-map-stage.is-still .ab-pin-ring { animation: none; opacity: 0; }
.ab-map-stage.is-still .ab-map-tilt,
.ab-map-stage.is-still .ab-flag-stem,
.ab-map-stage.is-still .ab-flag-plate,
.ab-map-stage.is-still .ab-pin-core { transition: none; }
