/* ═══════════════════════════════════════════════════════════════
   page-about.css (v0.21.0 — Round 4C-A)

   VERBATIM PORT from prototype 02-about.html lines 3393-6565 (v0.21.1 — was 3409, missed the leading #about-hero container rule)
   (stripped of <style>/</style> boundary tags but otherwise byte-
   identical to the prototype). All About-page-only selectors:

     .ah-*       — About hero atmosphere (blobs, grain, veil)
     #about-hero, #about-intro, #about-stats, #vmv, #brand-story,
     #team-culture, #milestones, #key-persons
     .ai-*       — About prose intro
     .as-*       — About stats wrapper (inner .vw-* lives in
                   intro-stats.css, theme-owned, re-enqueued
                   on this page via functions.php)
     .vmv-*      — Vision-Mission-Values section header
     .cards .card .card__* .hero__* .values-* .value-*
                 — VMV tilt-card module (CSS scoped via the
                   inner :root tokens —v-pink / —v-ink / —v-card
                   that don't collide with theme design-system)
     .vb-* .vertwo-branding*
                 — Brand-story 10-chapter accordion
     .kp-* .kp-lb-*
                 — Key persons cards + lightbox
     .tc-* .tc-lb-*
                 — Team & culture full-bleed gallery + lightbox
     .ml-*       — Milestones year-grouped timeline

   What's NOT in this file (theme-owned, do not duplicate):
     - Nav, footer, btn-orange, v-btn — components.css / theme
     - .vw-stats / .vw-card / .vw-grid — intro-stats.css (theme)
     - Reveal-on-scroll `.r → .r.in` transitions — design-system
       owns the base `.r{opacity:0;transform...}` and `.r.in{...}`
       (ensure design-system.css carries those — verified v0.20.x)
     - Fonts, design-system tokens (--orange, --black, --white)

   Filter pattern is the same one used in news-archive.css and
   news-single.css. See handoff §7 "Verbatim-port pattern" for
   the canonical rationale.
   ═══════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════════════════
   ABOUT PAGE — page-specific styles
═══════════════════════════════════════════════════════════════════ */

/* ───── ABOUT HERO — medium height with animated gradient parallax ───── */
#about-hero{
  position:relative;
  min-height:50vh;
  height:auto;
  display:flex;align-items:center;justify-content:center;
  overflow:hidden;
  background:#0a0a0c;
  isolation:isolate;
  padding:120px 24px 70px;
}
.ah-bg{
  position:absolute;inset:-10% -5%;
  z-index:0;
  pointer-events:none;
  filter:blur(70px) saturate(140%);
  opacity:.85;
  will-change:transform;
}
.ah-blob{
  position:absolute;border-radius:50%;
  mix-blend-mode:screen;
}
.ah-blob--a{
  width:55vw;height:55vw;left:-10%;top:-10%;
  background:radial-gradient(circle at 30% 30%, var(--blob-color, #F27A0F) 0%, transparent 60%);
  animation:ahDriftA 22s ease-in-out infinite alternate;
}
.ah-blob--b{
  width:50vw;height:50vw;right:-12%;top:8%;
  background:radial-gradient(circle at 70% 50%, var(--blob-color, #EC2F7A) 0%, transparent 60%);
  animation:ahDriftB 28s ease-in-out infinite alternate;
}
.ah-blob--c{
  width:62vw;height:62vw;left:18%;bottom:-22%;
  background:radial-gradient(circle at 50% 50%, var(--blob-color, #F5A623) 0%, transparent 60%);
  animation:ahDriftC 34s ease-in-out infinite alternate;
}
@keyframes ahDriftA{
  0%{transform:translate3d(0,0,0) scale(1)}
  100%{transform:translate3d(8vw,4vh,0) scale(1.12)}
}
@keyframes ahDriftB{
  0%{transform:translate3d(0,0,0) scale(1.05)}
  100%{transform:translate3d(-6vw,5vh,0) scale(1)}
}
@keyframes ahDriftC{
  0%{transform:translate3d(0,0,0) scale(1)}
  100%{transform:translate3d(-4vw,-6vh,0) scale(1.15)}
}
.ah-grain{
  position:absolute;inset:0;z-index:1;
  pointer-events:none;
  opacity:.10;
  background-image: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='3' /%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:200px 200px;
  mix-blend-mode:overlay;
}
.ah-veil{
  position:absolute;inset:0;z-index:2;pointer-events:none;
  background:
    radial-gradient(ellipse at 50% 80%, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0) 60%),
    linear-gradient(180deg, rgba(10,10,12,0.0) 0%, rgba(10,10,12,0.45) 100%);
}
.ah-inner{
  position:relative;z-index:3;
  max-width:920px;width:100%;
  text-align:center;
  color:#fff;
}
.ah-eyebrow{
  font-size:0.72rem;font-weight:600;letter-spacing:0.2em;
  text-transform:uppercase;color:var(--orange);
  margin-bottom:18px;display:inline-block;
}
.ah-title{
  font-family:var(--font-title);
  font-size:clamp(2.2rem, 4.4vw, 4.4rem);
  font-weight:900;letter-spacing:-0.045em;line-height:1.02;
  color:#fff;
  margin-bottom:22px;
}
.ah-title em{font-style:normal;color:var(--orange)}
.ah-sub{
  font-size:clamp(0.95rem,1.25vw,1.1rem);
  font-weight:300;line-height:1.7;
  color:rgba(255,255,255,0.75);
  max-width:580px;margin:0 auto;
}
@media(max-width:600px){
  #about-hero{min-height:42vh;padding:100px 20px 50px}
}

/* ───── ABOUT PROSE — clean white section before stats ───── */
#about-intro{
  background:var(--white);
  padding:72px 24px 24px;
}
.ai-wrap{max-width:780px;margin:0 auto;text-align:center}
.ai-eyebrow{
  font-size:0.72rem;font-weight:600;letter-spacing:0.2em;
  text-transform:uppercase;color:var(--orange);
  margin-bottom:14px;display:inline-block;
}
.ai-title{
  font-family:var(--font-title);
  font-size:clamp(1.9rem,4vw,2.9rem);
  font-weight:900;letter-spacing:-0.04em;line-height:1.12;
  color:var(--black);margin-bottom:22px;
}
.ai-title em{font-style:normal;color:var(--orange)}
.ai-prose{
  font-size:1.04rem;font-weight:300;color:var(--mid);
  line-height:1.78;
}
.ai-prose p+p{margin-top:18px}
.ai-prose strong{color:var(--black);font-weight:600}

/* ───── STATS WRAPPER on About — keep light bg, give it room ───── */
#about-stats{
  background:var(--white);
  padding:24px 24px 64px;
  border-bottom:1px solid var(--line);
}
/* v0.22.6 — was max-width:1280px which let the stats grid expand to
   1280px on About while the homepage's .intro-wrap caps at var(--max)
   (980px). That made About's stats cards visibly wider/larger than
   the homepage's even though both use the same vertwo_stats_get_data().
   Vic's "just copy verbatim from Homepage" — match the homepage wrapper. */
.as-wrap{max-width:var(--max);margin:0 auto}

/* ───── VMV — own dark canvas with pink+orange ambient glows ─────
   Previously VMV and brand-story shared a single #vmv-brand-bg wrapper so the
   glow blobs would span across both. On tablet/mobile that visual merge made
   brand-story feel "swallowed" by the VMV section. Each section now owns its
   own canvas + glow signature so they read as two distinct chapters. */
#vmv{
  position:relative;
  background:#0a0a0c;
  padding:72px 24px 64px;
  isolation:isolate;
  z-index:1;
  overflow:hidden;
}
#vmv::before,
#vmv::after{
  content:"";
  position:absolute;
  border-radius:50%;
  pointer-events:none;
  z-index:0;
  filter:blur(120px);
  opacity:0.55;
  will-change:transform;
}
#vmv::before{
  /* Pink glow — top-left, drifts down-right */
  width:60vw;height:60vw;
  left:-15%;top:-10%;
  background:radial-gradient(circle, rgba(236,47,122,0.55) 0%, rgba(236,47,122,0) 70%);
  animation:vmvGlowA 24s ease-in-out infinite alternate;
}
#vmv::after{
  /* Orange accent glow — bottom-right of VMV */
  width:50vw;height:50vw;
  right:-10%;bottom:-10%;
  background:radial-gradient(circle, rgba(242,122,15,0.40) 0%, rgba(242,122,15,0) 70%);
  animation:vmvGlowB 30s ease-in-out infinite alternate;
}
@keyframes vmvGlowA{
  0%{transform:translate3d(0,0,0) scale(1)}
  100%{transform:translate3d(6vw,4vh,0) scale(1.15)}
}
@keyframes vmvGlowB{
  0%{transform:translate3d(0,0,0) scale(1.1)}
  100%{transform:translate3d(-5vw,-3vh,0) scale(1)}
}

/* VMV section title (sits above the cards module) */
.vmv-header{
  position:relative;z-index:2;
  max-width:1080px;margin:0 auto 64px;
  text-align:center;color:#fff;
}
.vmv-eyebrow{
  font-size:0.72rem;font-weight:600;letter-spacing:0.2em;
  text-transform:uppercase;color:var(--orange);
  margin-bottom:14px;display:inline-block;
}
.vmv-title{
  font-family:var(--font-title);
  font-size:clamp(1.9rem,4vw,2.9rem);
  font-weight:900;letter-spacing:-0.04em;line-height:1.12;
  color:#fff;margin-bottom:18px;
}
.vmv-title em{font-style:normal;color:var(--orange)}
.vmv-caption{
  font-size:1rem;font-weight:300;color:rgba(255,255,255,0.62);
  line-height:1.7;max-width:580px;margin:0 auto;
}

/* The VMV module itself sits above the glow background */
#vmv > .cards{position:relative;z-index:1}
#vmv .cards{background:transparent}

/* ───── BRAND STORY — own dark canvas with a single warm focal glow ─────
   Now standalone (no shared wrapper). Uses one centred gold/orange glow that
   sits behind the chapter title + featured card, giving brand-story its own
   distinct mood vs VMV's two-glow palette. Keeps the brand-family feel via
   the same dark base, but reads as a fresh chapter on every viewport. */
#brand-story{
  position:relative;
  background:#0a0a0c;
  padding:64px 0 70px;
  z-index:1;
  isolation:isolate;
  overflow:hidden;
  /* content-visibility:auto lets the browser skip rendering work when
     the section is offscreen — including the animated glow above. */
  content-visibility:auto;
  contain-intrinsic-size:auto 900px;
}
#brand-story::before{
  content:"";
  position:absolute;
  width:60vw;height:60vw;
  left:50%;top:-15%;
  transform:translateX(-50%);
  border-radius:50%;
  pointer-events:none;
  z-index:0;
  /* Reduced blur from 140px to 70px — the original was creating a giant
     compositor layer that the GPU had to repaint every frame, causing
     stutter/lag while the page scrolled through this section. The drop
     in blur radius is barely perceptible visually but costs an order of
     magnitude less to paint. `will-change` removed for the same reason —
     keeping a permanent compositor layer is more expensive than letting
     the browser optimize the simple animation transform. The animation
     itself is paused via the parent's content-visibility when offscreen. */
  filter:blur(70px);
  opacity:0.42;
  background:radial-gradient(circle, rgba(245,166,35,0.55) 0%, rgba(245,166,35,0) 70%);
  animation:brandGlowDrift 28s ease-in-out infinite alternate;
}
/* Pause the (constantly-running, GPU-expensive) glow animation while
   the user is actively dragging the mobile accordion. Without this, the
   glow re-composites a blur(70px) layer every frame in parallel with
   the drag's scroll repaints, which Vic was experiencing as drag lag. */
#brand-story:has(.vb-accordion.is-dragging)::before,
#brand-story.is-dragging::before {
  animation-play-state: paused;
}
@keyframes brandGlowDrift{
  0%   { transform: translate3d(calc(-50% - 3vw), 0,    0) scale(1); }
  100% { transform: translate3d(calc(-50% + 3vw), 4vh,  0) scale(1.1); }
}
/* Module's own black bg → transparent so the parent's glow shows through */
#brand-story .vertwo-branding{
  background:transparent;
  position:relative;
  z-index:1;
}

/* On tablet, the brand-story header has its title and arrows separated
   to opposite ends (justify-content:space-between). At narrower widths,
   that big horizontal gap makes the layout feel "broken". Stack them
   vertically so the title sits naturally with the arrows beside/below. */
@media (max-width: 1100px){
  #brand-story .vb-header{
    flex-direction:column;
    align-items:flex-start;
    gap:18px;
  }
  #brand-story .vb-nav{
    align-self:flex-end;
  }
}

/* v0.22.6 — Removed `#about-stats .vw-grid` and `#about-stats .vw-card`
   responsive overrides. They diverged from the homepage's intro-stats
   sizing (clamp 360-500px max-width, custom min-heights) — so the same
   stat cards rendered visibly different on /about/ vs /. Per Vic's
   "just copy verbatim from Homepage": both pages now share the global
   .vw-grid / .vw-card rules from intro-stats.css with no overrides.
   Removed rules previously at this location:
       @media (max-width: 1100px){ #about-stats .vw-grid { ... } }
       @media (max-width: 600px){  #about-stats .vw-grid { ... } } */

/* ═════════════════════════════════════════════════════════════════════════
   VMV CARDS — Lock the desktop card form across every breakpoint.
   ═════════════════════════════════════════════════════════════════════════
   Vic's hard rule: cards never change size or form between viewports.
   The VMV cards module's own responsive CSS (in its scoped <style> block)
   does change form at <960px and <620px:
     - <960px: switches to 2-col grid + Values becomes a 700:360 LANDSCAPE
       card with a 2-col grid of values rows.
     - <620px: 1-col but Values uses 320:560 (slightly different from desktop's
       320:540).
   Both violate "use the desktop version across all other versions".

   Layered breakpoint plan:
     • Desktop (>1100px): 3-col grid, cards at desktop size (~360 wide)
     • Tablet (641–1100px): 3-col grid, cards proportionally scaled down so
       all three fit comfortably in one row. Card-internal sizing (fonts,
       paddings, badge dimensions) scales via clamp(min, vw, max) so content
       fits without clipping while staying readable.
     • Mobile (≤640px): 1-col stacked, cards at desktop form (320:540)
     • Narrow phone (≤430px): values card alone gets aspect-ratio:auto so
       the 6-row list isn't clipped when value-pill descriptions wrap.

   Higher specificity (#vmv .cards / #vmv .card--values) is enough to win
   over the module's lower-specificity .cards / .card--values rules without
   needing !important. */

/* ─── TABLET: 3-col, content proportionally scaled ─── */
@media (min-width: 641px) and (max-width: 1100px){
  #vmv .cards{
    grid-template-columns:repeat(3, 1fr);
    max-width:none;
    gap:clamp(10px, 1.6vw, 22px);
  }
  /* Values stays a portrait 320:540 card — kill the module's landscape override */
  #vmv .card--values{
    grid-column:auto;
    aspect-ratio:320 / 540;
  }
  #vmv .card--values .values-list{
    flex-direction:column;
    flex-wrap:nowrap;
    padding:clamp(2px, 0.35vw, 4px) clamp(10px, 1.5vw, 16px) clamp(12px, 1.8vw, 18px);
    gap:clamp(5px, 0.8vw, 9px);
  }
  #vmv .card--values .value-row{ width:100%; }

  /* Card content — fluid scaling so 3 cards fit and nothing clips.
     Each clamp() floors at a readable phone-sized minimum, scales with
     vw through the tablet range, and ceilings at the desktop value. */
  #vmv .card__title{ font-size:clamp(22px, 4.1vw, 42px); line-height:0.9; margin-bottom:clamp(8px, 1.2vw, 14px); }
  #vmv .values-head .card__title{ font-size:clamp(20px, 3.9vw, 40px); margin-bottom:4px; }
  #vmv .card__text{ font-size:clamp(11px, 1.42vw, 14.5px); line-height:1.5; }
  #vmv .card__eyebrow{ font-size:clamp(7.5px, 1vw, 10px); margin-bottom:clamp(7px, 1vw, 11px); }
  #vmv .card__eyebrow::before{ width:clamp(14px, 1.8vw, 20px); }

  #vmv .bullet{ font-size:clamp(10.5px, 1.35vw, 13.5px); line-height:1.42; }
  #vmv .bullet svg{ width:clamp(11px, 1.4vw, 14px); height:clamp(11px, 1.4vw, 14px); margin-top:2px; }
  #vmv .bullets{ gap:clamp(7px, 1vw, 10px); }

  #vmv .value-name{ font-size:clamp(10.5px, 1.4vw, 14px); line-height:1.15; }
  #vmv .value-desc{ font-size:clamp(8.5px, 1.13vw, 11.5px); line-height:1.28; }
  #vmv .value-divider{ margin:clamp(2px, 0.4vw, 4px) 0; }
  #vmv .value-badge{
    width:clamp(30px, 4.6vw, 48px);
    height:clamp(30px, 4.6vw, 48px);
    font-size:clamp(15px, 2.3vw, 24px);
    margin-right:clamp(-12px, -1.1vw, -8px);
  }
  #vmv .value-pill{
    min-height:clamp(34px, 5vw, 52px);
    padding:clamp(4px, 0.65vw, 7px) clamp(8px, 1.4vw, 16px) clamp(4px, 0.65vw, 7px) clamp(12px, 1.9vw, 20px);
    border-radius:clamp(14px, 2vw, 20px);
  }

  #vmv .card__content{ padding:clamp(12px, 1.85vw, 20px) clamp(12px, 2vw, 22px) clamp(14px, 2.1vw, 22px); }
  #vmv .values-head{ padding:clamp(14px, 2.2vw, 24px) clamp(14px, 2.2vw, 24px) clamp(8px, 1.4vw, 14px); }
  #vmv .card__content-art{
    width:clamp(110px, 16vw, 170px);
    height:clamp(110px, 16vw, 170px);
    bottom:clamp(-22px, -1.8vw, -16px);
    right:clamp(-26px, -2.3vw, -20px);
  }
}

/* ─── MOBILE: 1-col stacked, cards at full desktop form ─── */
@media (max-width: 640px){
  #vmv .cards{
    grid-template-columns:1fr;
    max-width:380px;
    gap:24px;
  }
  /* Override the module's <620px aspect-ratio:320/560 — keep desktop's 320/540 */
  #vmv .card--values{
    grid-column:auto;
    aspect-ratio:320 / 540;
  }
  #vmv .card--values .values-list{
    flex-direction:column;
    flex-wrap:nowrap;
    padding:4px 18px 22px;
    gap:10px;
  }
  #vmv .card--values .value-row{ width:100%; }
  /* Module shrinks .card__title to 36px at <620px — keep desktop's 46px so
     card form stays identical between 1-col-stacked and desktop. */
  #vmv .card__title{ font-size:46px; }
  #vmv .values-head .card__title{ font-size:44px; }
}

/* Narrow-tablet values escape hatch ─ Between 641-960px the 3-col layout
   makes each card narrow enough that the value-pill descriptions wrap to
   2 lines, pushing the 6-row list past the 320:540 height. Same fix as
   the narrow-phone escape hatch: drop aspect-ratio on the Values card so
   it grows content-driven. V & M stay at 320:540. align-items:start on
   the grid keeps V & M anchored to the top of the row instead of being
   stretched to match Values' taller height — so V & M's "form" is
   preserved exactly per Vic's rule. */
@media (min-width: 641px) and (max-width: 960px){
  #vmv .cards{ align-items:start; }
  #vmv .card--values{ aspect-ratio:auto; }
  #vmv .card--values .card__inner{ height:auto; }
}

/* Narrow-phone escape hatch ─ At <430px viewport the cards are forced
   below 360px wide. The value-pill descriptions wrap to 2 lines (e.g.
   "Striving to be the best in everything."), making 4 of the 6 rows
   77px tall instead of 61px. Total content (values-head 110 + 6 rows
   ≈ 506) wants ~616px but aspect-ratio:320/540 caps the card at 577px,
   so the last row (Outstanding) clips. Solution: drop the strict ratio
   on the Values card only, let it grow content-driven. V & M still use
   320:540. The cards are stacked 1-col on phone so a ~40px height delta
   on Values is invisible — visitors see one card at a time. */
@media (max-width: 430px){
  #vmv .card--values{ aspect-ratio:auto; }
  #vmv .card--values .card__inner{ height:auto; }
}

/* ═════════════════════════════════════════════════════════════════════════
   BRAND STORY — Safari/WebKit carousel-mode height fix.
   ═════════════════════════════════════════════════════════════════════════
   In carousel mode (≤1100px), the module sets:
     .vb-accordion { height: auto; overflow-x: auto; display: flex; }
     .vb-panel    { aspect-ratio: 16/9; flex: 0 0 calc(100% - 56px); }

   WebKit (Safari, including iOS) cannot resolve aspect-ratio against a
   percentage-based flex-basis when the parent has height:auto +
   overflow-x:auto. The result on Safari: panels render with 0 height
   and the chapter card area looks empty/missing. (Chromium resolves it
   fine, which is why Vic only saw the bug on Safari.)

   Fix: give the accordion a deterministic height via clamp() that
   approximates 9/16 of the panel's available width, and let panels
   stretch to fill it via height:100%. No more aspect-ratio inside flex,
   so Safari is happy — and Chrome renders identically because the
   computed height matches what aspect-ratio would have given. */
@media (max-width: 1100px){
  #brand-story .vb-accordion{
    height:clamp(220px, calc((100vw - 56px) * 9 / 16), 540px);
  }
  #brand-story .vb-panel,
  #brand-story .vb-panel.is-active{
    aspect-ratio:auto;
    height:100%;
  }
}

/* ───── KEY PERSONS — module handles its own padding ─────
   (no overrides needed) */

/* ───── TEAM & CULTURE — landscape parallax gallery + orange glow + lightbox ─────
   Section has NO horizontal padding so the gallery viewport spans the full
   browser width — slides slide in/out at the literal browser edges, not
   at a max-width container. Head and pills are wrapped in their own
   `.tc-inner` containers with horizontal padding for normal alignment. */
#team-culture{
  background:var(--white);
  padding:40px 0 72px;
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
.tc-inner{
  max-width:1320px;
  margin:0 auto;
  padding:0 24px;
}
.tc-head{
  display:flex;justify-content:space-between;align-items:flex-end;gap:30px;
  margin-bottom:48px;
}
.tc-head-left{max-width:620px}
.tc-eyebrow{
  font-size:0.72rem;font-weight:600;letter-spacing:0.2em;
  text-transform:uppercase;color:var(--orange);
  margin-bottom:14px;display:inline-block;
}
.tc-title{
  font-family:var(--font-title);
  font-size:clamp(1.9rem,4vw,2.9rem);
  font-weight:900;letter-spacing:-0.04em;line-height:1.12;
  color:var(--black);margin-bottom:14px;
}
.tc-title em{font-style:normal;color:var(--orange)}
.tc-caption{
  font-size:1rem;font-weight:300;color:var(--mid);line-height:1.7;
}
.tc-controls{
  display:flex;align-items:center;gap:10px;
  flex-shrink:0;
}
/* Rounded-box arrows (matches brand story aesthetic — border-radius:14px) */
.tc-arrow{
  width:52px;height:52px;border-radius:14px;
  background:var(--white);border:1px solid var(--line);
  cursor:pointer;display:flex;align-items:center;justify-content:center;
  color:var(--black);
  transition:background .25s ease,border-color .25s ease,color .25s ease,
             transform .35s cubic-bezier(.16,1,.3,1),
             box-shadow .35s ease;
}
.tc-arrow:hover{
  background:var(--orange);border-color:var(--orange);color:#fff;
  transform:translateY(-2px);
  box-shadow:0 10px 24px rgba(242,122,15,0.35);
}
.tc-arrow:disabled{
  opacity:0.4;cursor:not-allowed;
  transform:none;box-shadow:none;
}
.tc-arrow svg{width:20px;height:20px}

/* Full-width viewport — slides slide in/out at browser edges */
.tc-viewport{
  position:relative;
  margin:-22px 0 0;
  padding:22px 0 44px;
  overflow:hidden;
}
.tc-track{
  display:flex;gap:20px;
  /* Track padding MUST equal gap (20px) — otherwise the previous slide's
     right edge appears at viewport-x = padding - gap when scrolled, causing
     a visible "peek" on the left. With padding == gap, slide N-1's right
     edge sits exactly at viewport-x = 0 (offscreen). */
  padding-left:20px;
  padding-right:20px;
  transition:transform .9s cubic-bezier(.7,0,.3,1);
  will-change:transform;
}
/* LANDSCAPE slides: wider than tall (~16:10 ratio) */
.tc-slide{
  flex:0 0 auto;
  width:clamp(320px, 44vw, 620px);
  height:clamp(220px, 28vw, 390px);
  border-radius:18px;
  overflow:hidden;
  position:relative;
  background:#0d0d0d;
  box-shadow:0 6px 24px rgba(0,0,0,0.08);
  /* `isolation: isolate` creates a new stacking context so the caption's
     compositing stays stable while the bg's transform updates rapidly via
     the rAF parallax loop. Without this, mobile browsers can briefly
     re-compose the slide's layers, causing the caption to flicker. */
  isolation:isolate;
  transform:translateZ(0);
  cursor:zoom-in;
  transition:transform .5s cubic-bezier(.16,1,.3,1),
             box-shadow .5s cubic-bezier(.16,1,.3,1);
}
/* Tighter, more focused glow that fits within viewport's vertical padding */
.tc-slide:hover{
  transform:translateY(-3px);
  /* v0.21.2 (Vic): bumped from a faint 1px rgba ring to a clearly
     visible 2px solid orange outline so the slide reads as
     interactive (clicks open the lightbox). The existing lift +
     drop shadow stay; the outline is the new affordance. */
  outline: 2px solid var(--orange);
  outline-offset: 2px;
  box-shadow:
    0 10px 28px rgba(242,122,15,0.45),
    0 0 0 1px rgba(242,122,15,0.20);
}
/* Stronger parallax — bigger inset gives bg image room to shift dramatically.
   No CSS transition on bg — the JS rAF loop drives it directly during
   track transitions for perfect sync (avoids first-click jumpiness). */
.tc-slide-bg{
  /* Bigger inset (-25% → -40%) gives the rAF parallax loop dramatically
     more travel room, so cards feel more 3D as they move through the
     viewport. JS PARALLAX_BG_PCT bumped from -11 to -18 to match. */
  position:absolute;inset:-40%;
  background-size:cover;background-position:center;
  will-change:transform;
}
.tc-slide-overlay{
  position:absolute;inset:0;
  background:linear-gradient(180deg, rgba(0,0,0,0) 35%, rgba(0,0,0,0.78) 100%);
  pointer-events:none;
  /* Same layer promotion as caption — the bg's rapid transform updates
     can cause the overlay's gradient to flicker on mobile during slide
     transitions. Promoting it to its own layer isolates it. */
  transform:translate3d(0, 0, 0);
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
  will-change:transform;
}
.tc-slide-caption{
  position:absolute;left:22px;right:22px;bottom:18px;
  color:#fff;
  z-index:2;
  pointer-events:none;
  /* Promote caption to its own composited layer. Without this, the rapid
     bg transform updates (from the rAF parallax loop) can cause mobile
     browsers to flicker the caption text during/after slide transitions.
     Layer promotion isolates the caption's rendering from the bg layer. */
  transform:translate3d(0, 0, 0);
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
  will-change:transform;
}
.tc-slide-tag{
  display:inline-block;
  font-size:0.66rem;font-weight:600;letter-spacing:0.18em;
  text-transform:uppercase;color:var(--orange);
  margin-bottom:6px;
}
.tc-slide-title{
  font-family:var(--font-title);
  font-size:clamp(0.98rem,1.25vw,1.2rem);
  font-weight:900;line-height:1.25;letter-spacing:-0.02em;
  color:#fff;
}

/* Pills + counter row beneath gallery */
.tc-pills-row{
  /* Pills moved to where the counter used to live (right side). Counter
     hidden — chips alone communicate position clearly with the active-pill
     widening animation. Margin reduced from 32 to 14px to tighten the
     visual relationship between the gallery image and its navigation. */
  display:flex;align-items:center;justify-content:flex-end;gap:18px;
  margin-top:14px;
  max-width:100%;
}
.tc-pills{
  display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;
}
.tc-pill{
  width:32px;height:6px;border-radius:980px;
  background:rgba(0,0,0,0.12);
  cursor:pointer;border:none;padding:0;
  transition:background .35s ease, width .45s cubic-bezier(.16,1,.3,1);
}
.tc-pill.active{
  background:var(--orange);
  width:64px;
}
.tc-pill:hover:not(.active){background:rgba(0,0,0,0.28)}
.tc-counter{display:none}

@media(max-width:860px){
  .tc-head{flex-direction:column;align-items:flex-start;gap:24px}
  .tc-controls{align-self:flex-end}
}
@media(max-width:600px){
  #team-culture{padding:32px 0 56px}
  #team-culture .tc-inner{padding:0 18px}
  /* Track padding MUST match gap (20px) to prevent left-edge peek */
  .tc-track{padding-left:20px;padding-right:20px}
  .tc-slide{width:84vw;height:54vw}
  .tc-arrow{width:46px;height:46px;border-radius:12px}
  .tc-arrow svg{width:18px;height:18px}
}

/* ───── TEAM & CULTURE LIGHTBOX (matches Key Persons design) ───── */
.tc-lightbox{
  position:fixed;inset:0;
  background:rgba(10,10,12,0.94);
  backdrop-filter:blur(8px);
  -webkit-backdrop-filter:blur(8px);
  display:flex;align-items:center;justify-content:center;
  z-index:1000;
  opacity:0;
  pointer-events:none;
  transition:opacity 260ms cubic-bezier(.16,1,.3,1);
}
.tc-lightbox.is-open{opacity:1;pointer-events:auto}
.tc-lightbox:not(.is-open),
.tc-lightbox:not(.is-open) *{pointer-events:none !important}

.tc-lb-viewport{
  position:relative;
  width:92vw;height:84vh;
  overflow:hidden;
}
.tc-lb-track{
  position:absolute;top:0;left:0;
  height:100%;
  display:flex;
  will-change:transform;
  transition:transform .55s cubic-bezier(.16,1,.3,1);
}
.tc-lb-slide{
  flex:0 0 92vw;width:92vw;height:84vh;
  display:flex;align-items:center;justify-content:center;
}
.tc-lb-image{
  display:block;
  max-width:92vw;max-height:84vh;
  width:auto;height:auto;
  object-fit:contain;
  user-select:none;
  -webkit-user-drag:none;
  cursor:pointer;
  border-radius:8px;
  box-shadow:0 30px 80px rgba(0,0,0,0.5);
}
.tc-lb-close,.tc-lb-nav{
  position:absolute;
  width:48px;height:48px;border-radius:50%;
  background:transparent;
  border:1px solid rgba(255,255,255,0.24);
  color:#fff;
  display:inline-flex;align-items:center;justify-content:center;
  cursor:pointer;
  z-index:2;
  transition:background .3s ease, border-color .3s ease,
             transform .3s ease, box-shadow .35s ease;
}
.tc-lb-close{top:24px;right:24px}
.tc-lb-close svg{width:20px;height:20px}
.tc-lb-close:hover{
  background:var(--orange);border-color:var(--orange);
  transform:rotate(90deg);
  box-shadow:0 10px 30px -6px rgba(242,122,15,0.6);
}
.tc-lb-nav{top:50%;width:52px;height:52px;border-radius:14px;transform:translateY(-50%)}
.tc-lb-nav svg{width:22px;height:22px}
.tc-lb-prev{left:24px}
.tc-lb-next{right:24px}
.tc-lb-nav:hover{
  background:var(--orange);border-color:var(--orange);
  box-shadow:0 10px 30px -6px rgba(242,122,15,0.6);
}
.tc-lb-prev:hover{transform:translateY(-50%) translateX(-3px)}
.tc-lb-next:hover{transform:translateY(-50%) translateX(3px)}

.tc-lb-footer{
  position:absolute;left:50%;bottom:24px;
  transform:translateX(-50%);
  display:flex;align-items:center;gap:16px;
  z-index:2;
}
.tc-lb-pills{display:flex;gap:6px}
.tc-lb-pill{
  width:28px;height:4px;
  background:rgba(255,255,255,0.22);
  border-radius:2px;
  cursor:pointer;border:none;padding:0;
  transition:background .3s ease, width .3s ease;
}
.tc-lb-pill.is-active{background:var(--orange);width:40px}
.tc-lb-pill:hover{background:rgba(242,122,15,0.75)}
.tc-lb-counter{
  color:rgba(255,255,255,0.7);
  font-size:12px;font-weight:600;letter-spacing:0.06em;
  font-variant-numeric:tabular-nums;
}

/* ───── MILESTONES — light gray bg with subtle pink gradient ───── */
#milestones{
  background:#F4F4F6;
  color:var(--black);
  /* Compact: was 130px → 90px top/bottom — tighter overall section */
  padding:60px 22px 60px;
  position:relative;
  overflow:hidden;
}
#milestones::before,
#milestones::after{
  content:"";
  position:absolute;
  border-radius:50%;
  pointer-events:none;
  filter:blur(140px);
  opacity:0.65;
  z-index:0;
}
/* Wider, larger gradients that cover more of the section */
#milestones::before{
  width:80vw;height:80vw;
  left:-30%;top:-10%;
  background:radial-gradient(circle, rgba(255,180,200,0.7) 0%, rgba(255,180,200,0) 70%);
}
#milestones::after{
  width:85vw;height:85vw;
  right:-30%;bottom:-15%;
  background:radial-gradient(circle, rgba(255,160,190,0.55) 0%, rgba(255,160,190,0) 70%);
}
.ml-inner{
  max-width:1080px;margin:0 auto;position:relative;
  z-index:1;
}
.ml-head{text-align:center;margin-bottom:44px;position:relative;z-index:2}
.ml-eyebrow{
  font-size:0.72rem;font-weight:600;letter-spacing:0.2em;
  text-transform:uppercase;color:var(--orange);
  margin-bottom:14px;display:inline-block;
}
.ml-title{
  font-family:var(--font-title);
  font-size:clamp(2rem,4.4vw,3.2rem);
  font-weight:900;letter-spacing:-0.04em;line-height:1.1;
  color:var(--black);margin-bottom:14px;
}
.ml-title em{font-style:normal;color:var(--orange)}
.ml-caption{
  font-size:1rem;font-weight:300;color:var(--mid);
  line-height:1.7;max-width:560px;margin:0 auto;
}

/* The list contains the line — line starts at the CENTER of the first
   year badge (so the 2020 circle is the visual head of the timeline)
   and ends at the center of the last event dot. */
.ml-list{
  position:relative;
  /* Compact: 60px → 28px between year-blocks */
  display:flex;flex-direction:column;gap:28px;
  z-index:1;
  padding:0;
}
.ml-list::before{
  content:"";
  position:absolute;
  left:50%;
  /* Start at center of first year badge (badge height = 100px → 50px) */
  top:50px;
  /* End at center of last event dot (dot height = 14px → 7px) */
  bottom:7px;
  width:2px;
  transform:translateX(-50%);
  background:linear-gradient(
    180deg,
    rgba(242,122,15,0.55) 0%,
    rgba(242,122,15,0.55) 96%,
    rgba(242,122,15,0) 100%);
  z-index:0;
}

/* YEAR BLOCK — anchor for a year + its sub-events */
.ml-year-block{
  position:relative;
  display:grid;
  grid-template-columns:1fr 100px 1fr;
  gap:24px;
  align-items:center;
  z-index:1;
}
.ml-year-block .ml-events{
  grid-column:1 / -1;
}
.ml-year-block .ml-year-badge{
  width:100px;height:100px;
  border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:#fff;
  border:2px solid var(--orange);
  font-family:var(--font-title);
  font-weight:900;font-size:1.4rem;letter-spacing:-0.02em;
  color:var(--orange);
  position:relative;
  z-index:2;
  grid-column:2;
  justify-self:center;
  box-shadow:0 0 0 6px #F4F4F6, 0 8px 28px rgba(242,122,15,0.28);
  transition:transform .4s cubic-bezier(.16,1,.3,1), box-shadow .4s ease;
}

/* SUB-EVENTS within a year — small dots on the line, mini-cards alternating */
.ml-events{
  position:relative;
  /* Compact: tighter gaps */
  display:flex;flex-direction:column;gap:14px;
  margin-top:14px;
}
.ml-events::before{display:none}
.ml-event{
  position:relative;
  display:grid;
  grid-template-columns:1fr 100px 1fr;
  gap:24px;
  align-items:center;
}
.ml-event-dot{
  grid-column:2;
  justify-self:center;
  width:14px;height:14px;
  border-radius:50%;
  background:var(--orange);
  box-shadow:0 0 0 4px #F4F4F6, 0 0 0 5px rgba(242,122,15,0.4);
  position:relative;z-index:2;
  transition:transform .35s cubic-bezier(.16,1,.3,1);
}

.ml-card{
  background:#fff;
  border:1px solid rgba(0,0,0,0.06);
  border-radius:14px;
  /* Compact: tighter padding */
  padding:14px 18px;
  box-shadow:0 6px 18px rgba(0,0,0,0.04);
  transition:transform .4s cubic-bezier(.16,1,.3,1),
             border-color .35s ease,
             box-shadow .4s ease;
}
.ml-card--major{
  padding:18px 20px;
}
.ml-card-eyebrow{
  font-size:0.64rem;font-weight:700;letter-spacing:0.18em;
  text-transform:uppercase;color:var(--orange);
  margin-bottom:5px;
}
.ml-card-title{
  font-family:var(--font-title);
  font-size:0.98rem;font-weight:900;letter-spacing:-0.02em;line-height:1.22;
  color:var(--black);margin-bottom:5px;
}
.ml-card--major .ml-card-title{
  font-size:1.08rem;
}
.ml-card-text{
  /* Compact: smaller, tighter */
  font-size:0.85rem;font-weight:300;line-height:1.5;
  color:var(--mid);
}

/* Card placement (left or right of line) */
.ml-event--right .ml-card,
.ml-year-block--right .ml-card{grid-column:3}
.ml-event--right .ml-spacer,
.ml-year-block--right .ml-spacer{grid-column:1}
.ml-event--left .ml-card,
.ml-year-block--left .ml-card{grid-column:1;text-align:right}
.ml-event--left .ml-spacer,
.ml-year-block--left .ml-spacer{grid-column:3}

/* HOVER STATES — only on devices with TRUE hover capability AND on
   widths that aren't mobile. Three checks because some Android Chrome
   configurations report `hover:hover` for touch devices, which would
   let mobile taps trigger these transforms and break absolute-positioned
   dots/badges that rely on `transform: translate(-50%, -50%)` for
   centering. The `min-width:761px` is the safety net. */
@media (hover: hover) and (pointer: fine) and (min-width: 761px){
  .ml-year-block:hover .ml-year-badge{
    transform:scale(1.06);
    box-shadow:0 0 0 6px #F4F4F6, 0 12px 36px rgba(242,122,15,0.45);
  }
  .ml-event:hover .ml-event-dot{transform:scale(1.3)}
  .ml-card:hover{
    transform:translateY(-3px);
    border-color:rgba(242,122,15,0.45);
    box-shadow:0 14px 32px -10px rgba(242,122,15,0.30),
               0 4px 12px rgba(0,0,0,0.04);
  }
}

/* Reduce motion */
@media (prefers-reduced-motion:reduce){
  .ml-card,.ml-event-dot,.ml-year-badge{transition:none}
}

/* MOBILE: absolute-position badges + dots so they sit *exactly* on the
   left-side line. The trick: NO padding-left on .ml-year-block or .ml-event.
   Instead, the .ml-card gets margin-left:62 to make room for the dot/badge.
   This way, position:absolute left:24px on dot/badge correctly aligns with
   .ml-list's left edge + 24 = the line position. */
@media(max-width:760px){
  /* Compact mobile padding */
  #milestones{padding:48px 22px 48px}

  /* Mobile pink glow needs to be MORE prominent at small viewport widths.
     Larger gradients (relative to viewport), tighter blur (so blur doesn't
     wash out the color at small dimensions), higher opacity. */
  #milestones::before{
    width:140vw;height:140vw;
    left:-35%;top:-15%;
    opacity:0.85;
    filter:blur(70px);
  }
  #milestones::after{
    width:150vw;height:150vw;
    right:-40%;bottom:-15%;
    opacity:0.75;
    filter:blur(70px);
  }

  .ml-list{gap:30px}
  .ml-list::before{
    left:24px;
    transform:none;
    top:24px;       /* center of first 48px badge */
    bottom:7px;     /* center of last 14px dot */
  }

  .ml-year-block{
    display:block;
    position:relative;
    grid-template-columns:none;
    min-height:48px;  /* ensure space for absolute badge */
    align-items:initial;
  }
  .ml-year-block .ml-year-badge{
    position:absolute;
    left:24px;
    top:0;
    transform:translateX(-50%);
    width:48px;height:48px;
    font-size:0.72rem;
    margin:0;
    grid-column:auto;
    justify-self:auto;
    box-shadow:0 0 0 4px #F4F4F6, 0 4px 16px rgba(242,122,15,0.28);
  }
  .ml-year-block .ml-spacer{display:none}

  .ml-events{
    /* Push down below the absolute year badge, compact gap */
    margin-top:52px;  /* was 64 — compact */
    gap:16px;         /* was 22 — compact */
  }

  .ml-event{
    display:block;
    position:relative;
    grid-template-columns:none;
    align-items:initial;
  }
  .ml-event-dot{
    position:absolute;
    left:24px;
    /* Vertically center the dot with the event card, so it sits beside
       the body of each card rather than at the top edge. */
    top:50%;
    transform:translate(-50%, -50%);
    width:14px;height:14px;
    margin:0;
    grid-column:auto;
    justify-self:auto;
    box-shadow:0 0 0 4px #F4F4F6, 0 0 0 5px rgba(242,122,15,0.4);
  }
  .ml-event .ml-card,
  .ml-event--left .ml-card,
  .ml-event--right .ml-card{
    /* Card offset from line by 62px → leaves room for dot on line */
    margin-left:62px;
    grid-column:auto;
    text-align:left;
    padding:16px 18px;
  }
  .ml-event .ml-card.ml-card--major{padding:20px 22px}
  .ml-spacer{display:none}
}

/* ───── VMV CARDS module styles (scoped) ───── */

  /* ============================================================
     VERTWO — VMV TILT CARDS (v3.1)
     Dark cards · animated gradient hero · cursor-tracked 3D tilt
     ============================================================ */

  :root {
    --v-pink:   #EC2F7A;
    --v-ink:    #0E0E12;      /* page */
    --v-card:   #17171B;      /* card surface */

    --v-text:     #FAFAFA;
    --v-text-sub: #B5B5B8;
    --v-text-mut: #7A7A80;

    --v-gradient: linear-gradient(135deg, #EC2F7A 0%, #F27A0F 100%);

    --ease-inertia: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-press:   cubic-bezier(0.4, 0, 0.2, 1);

    --font-display: 'Neue Haas Grotesk Display Pro', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    --font-body:    'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

    /* Per-card dynamic vars (set by JS) — unitless, units appended in CSS */
    --rx: 0;
    --ry: 0;
    --mx: 50%;
    --my: 50%;
  }

  

  

  

  /* ---------- Cards grid ---------- */
  .cards {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 44px;
    justify-items: center;
    align-items: start;
  }
  .cards > .card { width: 100%; }

  /* ---------- Card base ---------- */
  .card {
    position: relative;
    perspective: 1300px;
    aspect-ratio: 320 / 540;
  }

  .card__inner {
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 24px;
    background: var(--v-card);
    transform-style: preserve-3d;
    transform: rotateX(calc(var(--rx) * 1deg)) rotateY(calc(var(--ry) * 1deg)) translateZ(0);
    transition: transform 0.7s var(--ease-inertia);
    /* Subtle inset highlight on top edge, no drop shadow */
    box-shadow: 0 1px 0 rgba(255,255,255,0.06) inset;
    will-change: transform;
    overflow: hidden;
  }

  /* Snappy tilt response during hover (overrides the slower resting transition) */
  .card:hover .card__inner,
  .card.is-hovering .card__inner {
    transition: transform 0.12s ease-out;
  }

  /* ---------- Lighter gradient border (follows cursor) ---------- */
  .card__border {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1.5px;
    background: radial-gradient(circle 340px at var(--mx) var(--my),
      rgba(255, 255, 255, 1) 0%,
      rgba(255, 225, 230, 0.95) 15%,
      rgba(255, 190, 160, 0.85) 32%,
      rgba(236, 47, 122, 0.5) 55%,
      rgba(255, 255, 255, 0.06) 100%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    opacity: 0.3; /* faint resting edge so dark card has definition */
    transition: opacity 0.5s var(--ease-press);
    pointer-events: none;
    z-index: 4;
  }
  .card.is-hovering .card__border { opacity: 1; }

  /* Shine — warm radial highlight under cursor */
  .card__shine {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(circle 300px at var(--mx) var(--my),
      rgba(255, 220, 230, 0.12) 0%,
      rgba(255, 160, 110, 0.06) 30%,
      transparent 60%);
    opacity: 0;
    transition: opacity 0.5s var(--ease-press);
    pointer-events: none;
    z-index: 3;
  }
  .card.is-hovering .card__shine { opacity: 1; }

  /* ============================================================
     HERO — Animated gradient placeholder (top of V/M cards)
     Swap this block with <img> or <video> when asset is ready.
     ============================================================ */
  .card__hero {
    position: relative;
    height: 44%;
    width: 100%;
    overflow: hidden;
    transform: translateZ(24px);
    background: #14141A;
    isolation: isolate;
  }

  .hero__blob {
    position: absolute;
    width: 80%;
    aspect-ratio: 1;
    border-radius: 50%;
    filter: blur(38px);
    mix-blend-mode: screen;
    will-change: transform;
  }

  /* Vision — pink-dominant, dreamy */
  .card--vision .hero__blob--a {
    background: radial-gradient(circle, #FF4488 0%, transparent 65%);
    top: -15%; left: -20%;
    animation: blob-a 14s ease-in-out infinite alternate;
  }
  .card--vision .hero__blob--b {
    background: radial-gradient(circle, #F27A0F 0%, transparent 70%);
    bottom: -20%; right: -15%;
    width: 70%;
    animation: blob-b 17s ease-in-out infinite alternate;
  }
  .card--vision .hero__blob--c {
    background: radial-gradient(circle, #FFB6D5 0%, transparent 75%);
    top: 30%; right: -30%;
    width: 55%;
    animation: blob-c 11s ease-in-out infinite alternate;
  }

  /* Mission — warm orange-gold */
  .card--mission .hero__blob--a {
    background: radial-gradient(circle, #F27A0F 0%, transparent 65%);
    top: -20%; left: -15%;
    animation: blob-a 16s ease-in-out infinite alternate;
  }
  .card--mission .hero__blob--b {
    background: radial-gradient(circle, #EC2F7A 0%, transparent 70%);
    bottom: -25%; right: -10%;
    width: 70%;
    animation: blob-b 13s ease-in-out infinite alternate;
  }
  .card--mission .hero__blob--c {
    background: radial-gradient(circle, #F5A623 0%, transparent 75%);
    top: 20%; right: -20%;
    width: 60%;
    animation: blob-c 19s ease-in-out infinite alternate;
  }

  @keyframes blob-a {
    0%   { transform: translate(-10%, -10%) scale(1); }
    33%  { transform: translate(30%, 20%)  scale(1.2); }
    66%  { transform: translate(10%, 40%)  scale(0.95); }
    100% { transform: translate(-5%, 15%)  scale(1.1); }
  }
  @keyframes blob-b {
    0%   { transform: translate(10%, 10%)   scale(1); }
    50%  { transform: translate(-30%, -20%) scale(1.25); }
    100% { transform: translate(15%, -5%)   scale(1); }
  }
  @keyframes blob-c {
    0%   { transform: translate(0, 0)        scale(1); }
    40%  { transform: translate(-25%, 20%)   scale(1.15); }
    80%  { transform: translate(10%, -30%)   scale(0.9); }
    100% { transform: translate(20%, 5%)     scale(1.05); }
  }

  /* Halftone dot overlay — Vertwo brand texture */
  .hero__noise {
    position: absolute;
    inset: 0;
    background-image: radial-gradient(circle at center, rgba(255,255,255,0.12) 0.6px, transparent 1.2px);
    background-size: 6px 6px;
    opacity: 0.35;
    mix-blend-mode: overlay;
    pointer-events: none;
    z-index: 2;
  }

  /* Smooth transition from hero into content */
  .card__hero::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 40px;
    background: linear-gradient(180deg, transparent 0%, var(--v-card) 100%);
    z-index: 2;
    pointer-events: none;
  }

  /* ---------- Content (lower area) ---------- */
  .card__content {
    position: relative;
    height: 56%;
    padding: 22px 24px 26px;
    transform: translateZ(16px);
    transform-style: preserve-3d;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--v-card);
  }

  /* Animated SVG watermark — now lives in content area (lower) */
  .card__content-art {
    position: absolute;
    bottom: -24px;
    right: -30px;
    width: 180px;
    height: 180px;
    opacity: 0.16;
    pointer-events: none;
    z-index: 0;
    transform: translateZ(6px);
  }
  .card__content-art svg { width: 100%; height: 100%; }

  /* Text sits above the watermark */
  .card__content > :not(.card__content-art) { position: relative; z-index: 1; }

  .card__eyebrow {
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--v-text-mut);
    margin: 0 0 12px;
    display: flex;
    align-items: center;
    gap: 9px;
    transform: translateZ(6px);
  }
  .card__eyebrow::before {
    content: '';
    width: 22px;
    height: 1.5px;
    background: var(--v-gradient);
  }

  .card__title {
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 46px;
    line-height: 0.88;
    letter-spacing: -0.045em;
    margin: 0 0 16px;
    background: var(--v-gradient);
    -webkit-background-clip: text;
            background-clip: text;
    color: transparent;
    transform: translateZ(14px);
  }

  .card__text {
    font-size: 15.5px;
    line-height: 1.55;
    font-weight: 500;
    color: var(--v-text-sub);
    margin: 0;
    transform: translateZ(10px);
  }

  /* Mission-specific bullets */
  .bullets {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 11px;
    transform: translateZ(10px);
  }
  .bullet {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    font-size: 14.5px;
    line-height: 1.45;
    color: var(--v-text-sub);
    font-weight: 500;
  }
  .bullet svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    color: var(--v-pink);
    margin-top: 2.5px;
  }

  /* ============================================================
     VALUES CARD — Bigger content
     ============================================================ */
  .card--values .card__inner {
    display: flex;
    flex-direction: column;
    padding: 0;
  }

  .values-head {
    padding: 26px 26px 16px;
    transform: translateZ(14px);
    position: relative;
    z-index: 2;
  }
  .values-head .card__title { font-size: 44px; margin-bottom: 4px; }
  .values-head .card__eyebrow { margin-bottom: 12px; }

  .values-list {
    flex: 1;
    padding: 4px 18px 22px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    justify-content: space-around;
    transform: translateZ(12px);
    transform-style: preserve-3d;
  }

  .value-row {
    display: flex;
    align-items: center;
    gap: 0;
    transform-style: preserve-3d;
  }

  /* Letter badge — circle with V/E/R/T/W/O on light bg, black text */
  .value-badge {
    width: 54px;
    height: 54px;
    flex-shrink: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(#F5F5F5, #F5F5F5) padding-box,
                var(--v-gradient) border-box;
    border: 2px solid transparent;
    color: #0A0A0A;
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 26px;
    text-transform: lowercase;
    letter-spacing: -0.03em;
    transform: translateZ(10px);
    margin-right: -14px;  /* overlap with pill */
    z-index: 2;
    position: relative;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.45);
  }

  /* Pill — gradient bar with name / separator / description */
  .value-pill {
    flex: 1;
    background: var(--v-gradient);
    color: #fff;
    border-radius: 22px;
    padding: 8px 18px 8px 24px;
    min-height: 58px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    position: relative;
    z-index: 1;
    transform: translateZ(4px);
  }

  .value-name {
    font-weight: 800;
    font-size: 15.5px;
    letter-spacing: -0.005em;
    line-height: 1.15;
  }

  .value-divider {
    border: 0;
    height: 1px;
    background: rgba(255, 255, 255, 0.4);
    margin: 5px 0;
    width: 100%;
  }

  .value-desc {
    font-weight: 500;
    font-size: 12.5px;
    line-height: 1.3;
    opacity: 0.95;
  }

  /* Watermark SVG animations */
  @keyframes spin       { to { transform: rotate(360deg); } }
  @keyframes spin-rev   { to { transform: rotate(-360deg); } }
  @keyframes soft-pulse { 0%,100% { transform: scale(1); opacity: 0.9; } 50% { transform: scale(1.04); opacity: 1; } }
  @keyframes tw         { 0%,100% { opacity: 0.3; } 50% { opacity: 1; } }

  .spin-slow  { transform-origin: center; animation: spin 28s linear infinite; }
  .spin-fast  { transform-origin: center; animation: spin-rev 15s linear infinite; }
  .soft-pulse { transform-origin: center; animation: soft-pulse 3.6s ease-in-out infinite; }
  .tw-1 { animation: tw 2.2s ease-in-out infinite; }
  .tw-2 { animation: tw 2.8s ease-in-out 0.6s infinite; }

  /* ---------- Section header ---------- */
  .section-head {
    position: absolute;
    top: 32px;
    left: 50%;
    transform: translateX(-50%);
    color: #666;
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .section-head::before, .section-head::after {
    content: '';
    width: 36px;
    height: 1px;
    background: linear-gradient(90deg, transparent, #444, transparent);
  }

  /* ---------- Responsive ---------- */
  @media (max-width: 960px) {
    .cards { grid-template-columns: repeat(2, 1fr); max-width: 720px; gap: 32px; }
    .card--values { grid-column: span 2; aspect-ratio: 700 / 360; }
    .card--values .values-list { flex-direction: row; flex-wrap: wrap; padding: 4px 20px 20px; gap: 8px 12px; }
    .card--values .value-row { width: calc(50% - 6px); }
  }

  @media (max-width: 620px) {
    
    .cards { grid-template-columns: 1fr; max-width: 380px; gap: 24px; }
    .card--values { grid-column: span 1; aspect-ratio: 320 / 560; }
    .card--values .values-list { flex-direction: column; flex-wrap: nowrap; }
    .card--values .value-row { width: 100%; }
    .section-head { display: none; }
    .card__title { font-size: 36px; }
  }

  @media (prefers-reduced-motion: reduce) {
    
    .card__inner { transform: none !important; }
  }

/* ───── LOGO / BRAND STORY module styles (scoped) ───── */

/* ============================================================
   VERTWO · "The New Logo, The New Spirit" — 10-Slide Branding Slider
   ------------------------------------------------------------
   Ten chapters of the Vertwo brand story — from the new logo
   reveal through the six virtues — presented as a Stripe-style
   horizontal accordion (1 big active panel + 9 slim thumbs).

   RENDERING MODES

     DESKTOP (> 768px):   Horizontal flex-accordion. One panel
                          is active and expands to dominate the
                          width; the remaining 9 sit as narrow
                          vertical strips. Hover fires a JS-
                          driven flex-grow cascade. Arrow keys
                          and the arrow buttons move through.

     MOBILE (≤ 768px):    Horizontal scroll-snap carousel. One
                          card per view, swipeable, snap points
                          on each. Arrows scroll by one card
                          width. No flex-grow cascade here.

   ARCHITECTURE

   • Single source of truth: the LOGO_SLIDES array below. Swap
     for a Wix CMS dataset bind to make content dynamic.
   • Each slide renders its own inline SVG background — no
     network-loaded images, no fallback chain needed. SVGs are
     center-weighted so slim thumbs always show the key visual.
   • Hover cascade is JS-driven via class toggles so it composes
     cleanly with the is-active state and avoids CSS :has()
     browser-support gaps.
   • For 10 items (9 non-actives), the active-hover cascade splits
     the non-actives into a 5-near / 4-far group. Tuned so total
     flex-grow stays CONSTANT across all active positions:
         9.5 + 5×1.1 + 4×0.75 = 18.0  (matches rest: 9 + 9×1)
     The active panel never shifts when hovered.

   ACCESSIBILITY

   • ARIA tablist/tab roles on the accordion panels.
   • Keyboard: ←/→ arrows move active. Enter/Space activates.
   • prefers-reduced-motion shortens all transitions.
   • aria-labelledby links the section to its heading.
   ============================================================ */
:root {
  --v-orange:    #F27A0F;
  --v-orange-2:  #FF9438;
  --v-gold:      #F5A623;
  --v-crimson:   #C23A5C;
  --v-dark:      #1A1A1A;
  --v-navy:      #0D1F3C;
  --v-cream:     #FAF5EC;
  --v-white:     #FFFFFF;

  --v-gray-50:   #F7F7F7;
  --v-gray-100:  #EFEFEF;
  --v-gray-200:  #E3E3E3;
  --v-gray-300:  #CFCFCF;
  --v-gray-500:  #8A8A8A;
  --v-gray-600:  #666666;

  /* Motion — smooth, non-bouncy easings tuned for a 10-panel slider.
     `inout` = symmetric ease-in-out, used for state changes where we
               want a balanced, slider-like transition (no overshoot)
     `coast` = ease-out, used for resting/exit transitions
     `soft`  = generic ease for shadow/filter/opacity */
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-coast: cubic-bezier(0.25, 1, 0.32, 1);
  --ease-soft:  cubic-bezier(0.4, 0, 0.2, 1);

  --r-md: 16px;
  --r-lg: 24px;

  /* Card shadow tuned for a black page. Dark shadows vanish on black,
     so we combine a faint white hairline rim (depth cue) with a soft
     orange glow (brand-tinted halo) and a deep black shadow for lift. */
  --shadow-active:
    0 0 0 1px rgba(255,255,255,.06),
    0 28px 64px -18px rgba(242,122,15,.22),
    0 18px 44px -14px rgba(0,0,0,.8);

  --font-title: 'Neue Haas Grotesk Display', 'Inter Tight', 'Inter', system-ui, sans-serif;
  --font-body:  'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-jp:    'Noto Serif JP', 'Yu Mincho', 'Hiragino Mincho ProN', serif;
}






button { font-family: inherit; cursor: pointer; border: none; background: none; }

/* =============== SECTION WRAPPER =============== */
.vertwo-branding {
  width: 100%;
  padding: clamp(56px, 7vw, 104px) clamp(20px, 4vw, 64px);
  background: #000;
}
.vertwo-branding__inner {
  max-width: 1440px;
  margin: 0 auto;
}

/* =============== HEADER =============== */
.vb-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 32px;
  margin-bottom: clamp(32px, 4vw, 56px);
}
.vb-title-group h2 {
  font-family: var(--font-title);
  font-weight: 900;
  font-size: clamp(30px, 4.2vw, 54px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  color: var(--v-white);
  margin-bottom: 6px;
}
.vb-title-group p {
  /* v0.32.40 — Vic ask: subtitle was too big + visually different from the
     other About-page section subtitles. The VMV caption + Team & Culture
     caption both sit at flat 1rem / weight 300, so bring this peer
     into the same family for visual rhythm. */
  font-size: 1rem;
  color: rgba(255,255,255,.62);
  font-weight: 300;
  line-height: 1.7;
  letter-spacing: 0;
}

/* Prev / Next arrows — identical to the news accordion's arrow
   buttons so the two sections feel like the same family. */
.vb-nav { display: flex; gap: 10px; flex-shrink: 0; }
.vb-nav-btn {
  width: 52px; height: 52px;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 14px;
  color: var(--v-orange);
  display: flex; align-items: center; justify-content: center;
  transition:
    background .4s var(--ease-soft),
    color .4s var(--ease-soft),
    transform .5s var(--ease-inout),
    box-shadow .4s var(--ease-soft),
    border-color .4s var(--ease-soft);
}
.vb-nav-btn:hover:not(:disabled) {
  background: var(--v-orange);
  border-color: var(--v-orange);
  color: var(--v-white);
  transform: scale(1.06);
  box-shadow: 0 10px 28px -6px rgba(242,122,15,.5);
}
.vb-nav-btn:active:not(:disabled) { transform: scale(.95); }
.vb-nav-btn:disabled { opacity: .3; cursor: not-allowed; }
.vb-nav-btn svg { width: 20px; height: 20px; }

/* =============== ACCORDION =============== */
.vb-accordion {
  display: flex;
  gap: 10px;
  padding: 2px;
  margin: 0 -2px;
  /* Aspect-ratio lives on the CONTAINER, not on .vb-panel.is-active.
     Putting it on the active panel caused the accordion to collapse
     mid-click: when the old active lost .is-active, its aspect-ratio
     disappeared and its intrinsic height dropped to 0; the new
     active's aspect-ratio kicked in but its width was still tiny
     (mid-flex-grow-transition) so its derived height was tiny too —
     and the row height cratered.

     Container aspect-ratio is stable — the container's width is
     parent-driven and doesn't change during the transition, so its
     aspect-ratio-derived height is rock-solid. 22/7 was chosen so
     the active panel (flex-grow 14 of 23 total, minus 9 gaps) lands
     on very close to 16:9 at typical viewport widths. Verified:
       1440: active ≈ 744×417   (1.782, vs target 1.778)
       1024: active ≈ 530×300   (1.767)
        820: active ≈ 421×240   (1.754)
     Close enough — the eye can't detect the delta. */
  aspect-ratio: 22 / 7;
}

/* Track wrapper. On desktop, display:contents makes it transparent
   to flex layout — panels behave as direct children of .vb-accordion,
   preserving the original accordion expansion behaviour. The mobile
   @media block below promotes it to a real flex container that gets
   translated via JS for the carousel. */
.vb-track { display: contents; }

.vb-panel {
  position: relative;
  flex: 1 1 0;
  /* Thumb min-width. Tuned so natural flex proportions give ~16:9
     active panels at every viewport above the mobile breakpoint —
     without this being too narrow to host the vertical "chapter
     number" pill (which needs ~25px). At 44px it was clamping at
     tablet widths and squeezing the active panel out of 16:9. */
  min-width: 30px;
  border-radius: var(--r-lg);
  overflow: hidden;
  /* Dark background so any 1px clip anti-aliasing at the rounded corners
     reads as "slightly darker black" against the page — not as a bright
     white halo bleeding through. (Previously var(--v-gray-100) = #EFEFEF
     which was fine on a white page but caused visible light edges now
     that the page bg is #000.) */
  background: #0A0A0A;
  cursor: pointer;
  z-index: 1;
  isolation: isolate;

  /* flex-grow is the only animated size property; container widens
     via flex-grow while the SVG scales naturally via viewBox. No
     will-change here — flex-grow is a layout property, not a
     compositor-accelerated one, so hinting about it just eats
     compositor resources without speeding anything up. */
  transition:
    flex-grow .55s var(--ease-coast),
    box-shadow .4s var(--ease-soft);
}

/* Active panel — bumped to flex-grow: 14 (from the news version's 9)
   because with 10 items we need the active to dominate more
   proportionally. Total flex grow at rest = 14 + 9 = 23, giving
   active ≈ 61% of available space. */
.vb-panel.is-active {
  flex-grow: 14;
  z-index: 2;
  box-shadow: var(--shadow-active);
  /* The active card isn't clickable — clicking it is a no-op (see the
     `if (idx !== activeIndex)` guard in the panel click handler). So
     drop the pointer cursor that .vb-panel inherits from the thumb
     rule; it was falsely advertising clickability on the featured card. */
  cursor: default;
}

/* Keyboard focus ring — no size change on hover or focus, just a
   visible outline for a11y. Hover now drives only the grayscale →
   color SVG filter (see the .vb-panel__bg svg rules below). */
.vb-panel:focus-visible {
  outline: 2px solid var(--v-orange);
  outline-offset: 3px;
}

/* =============== BACKGROUNDS =============== */
/* Each panel holds an inline SVG that fills it completely.
   The SVGs are center-weighted (key visuals at horizontal
   center) so slim thumbs still read as branded images, not
   cropped edges. */
.vb-panel__bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  /* `isolation: isolate` scopes the SVG grayscale filter without forcing
     a permanent GPU compositor layer. Previously `transform: translateZ(0)`
     was used to fix a 1px filter-halo at rounded corners — but that
     promoted EACH of the 10 panels to its own GPU layer, and Lenis
     re-composited all of them every smooth-scroll frame. The cost was
     the "stuck/laggy" feeling Vic reported. Isolation alone usually
     handles the clip ordering correctly on modern browsers; if a 1px
     halo reappears at panel corners, switch back. */
  isolation: isolate;
}
.vb-panel__bg svg {
  width: 100%;
  height: 100%;
  display: block;
  /* Thumbs are monochrome at rest — the grayscale filter drains all
     color from the SVG so the accordion reads as a muted "wall of
     chapters". Hovering a thumb wakes its color back up; the active
     panel is always in full color (rule below). */
  filter: grayscale(1) contrast(0.95);
  transition: filter .55s var(--ease-inout);
}
/* Color restored on hover (thumbs only) AND always on the active
   panel. The :not(.is-active) guard on the hover selector means
   hovering the active card does nothing — no flicker, no double-
   transition, matches the "opened card has no hover state" rule. */
.vb-panel:hover:not(.is-active) .vb-panel__bg svg,
.vb-panel.is-active .vb-panel__bg svg {
  filter: grayscale(0) contrast(1);
}

/* v0.22.0 — image-driven brand-story panel background.
   Editors can upload an image per chapter (CMS: "About: Page Content"
   → Brand Story); that image replaces the SVG_BUILDERS art for the
   panel. Behavior mirrors .vb-panel__bg svg above: monochrome at rest,
   color on hover (inactive thumbs) and always color on .is-active.
   background-size:cover keeps the image filling the panel regardless
   of aspect ratio; center anchors the focal point through the
   accordion's height transitions. */
.vb-panel__bg-image {
  width: 100%;
  height: 100%;
  display: block;
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  filter: grayscale(1) contrast(0.95);
  transition: filter .55s var(--ease-inout);
}
.vb-panel:hover:not(.is-active) .vb-panel__bg-image,
.vb-panel.is-active .vb-panel__bg-image {
  filter: grayscale(0) contrast(1);
}

/* Subtle darkening layer on INACTIVE panels so the active one
   reads as the "featured" state. Fades out on the active panel. */
.vb-panel:not(.is-active) .vb-panel__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(26,26,26,.06) 0%,
    rgba(26,26,26,0) 40%,
    rgba(26,26,26,.2) 100%
  );
  pointer-events: none;
}

/* Gradient on ACTIVE panel — darkens bottom so the title overlay
   reads clearly against any background (orange, navy, cream). */
.vb-panel__gradient {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(0,0,0,0) 0%,
    rgba(0,0,0,0) 40%,
    rgba(0,0,0,.35) 78%,
    rgba(0,0,0,.7) 100%
  );
  opacity: 0;
  transition: opacity .65s var(--ease-soft);
  pointer-events: none;
}
.vb-panel.is-active .vb-panel__gradient { opacity: 1; }

/* =============== ACTIVE TITLE OVERLAY =============== */
/* Only appears on the active panel. Matches the Stripe reference's
   "Annual letter 2025" placement — bottom-left of the big slide.
   Fades/slides in with a small stagger after the panel expands. */
/* v0.22.5 — `filter: blur()` removed from the transition (and from
   both rest + active states). Reason: on iOS Safari, animating an
   element that has `filter: blur(...)` AT THE SAME TIME as a parent
   panel is animating its `flex-grow` (the .vb-panel becoming active
   triggers a layout-driven flex-grow ramp from 1 → 14 over .55s) was
   causing the title text to jitter and "step" instead of fading
   smoothly. The blur compositor pass and the layout pass were
   competing for the same frame budget. Vic's recording on iPhone
   showed the eyebrow + h3 popping in roughly + the typography
   gradient appearing in jumps. Pure opacity + transform stays
   smooth: opacity is GPU-cheap, transform is compositor-only. */
.vb-panel__title {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 32px 38px 36px;
  color: var(--v-white);
  z-index: 3;
  pointer-events: none;

  opacity: 0;
  transform: translate3d(0, 32px, 0);
  transition:
    opacity .75s var(--ease-soft),
    transform 1.3s var(--ease-coast);
}
.vb-panel.is-active .vb-panel__title {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity .8s .4s var(--ease-soft),
    transform 1.2s .35s var(--ease-inout);
}
.vb-panel__eyebrow {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(255,255,255,.85);
  margin-bottom: 10px;
  text-shadow: 0 2px 10px rgba(0,0,0,.4);
}
.vb-panel__title h3 {
  font-family: var(--font-title);
  font-weight: 800;
  font-size: clamp(24px, 2.6vw, 38px);
  line-height: 1.1;
  letter-spacing: -0.025em;
  max-width: 640px;
  text-shadow: 0 2px 18px rgba(0,0,0,.45);
}

/* =============== FOLDED NUMBER (slim thumbs) =============== */
/* Small chapter number on each slim thumb — vertical, in a subtle
   dark capsule so it stays legible regardless of the thumb's
   background color (white, cream, navy, orange — all need to work).
   Disappears when the thumb becomes the active panel. */
.vb-panel__num {
  position: absolute;
  top: 14px;
  left: 0; right: 0;
  display: flex;
  justify-content: center;
  z-index: 2;
  pointer-events: none;
  /* Simple opacity-only transition. We deliberately do NOT animate
     transform here — earlier the pill had a translate3d(0,-12,0)
     animation on activate/deactivate, which combined with the inner
     span's rotate(180deg) produced a visible "flip" glitch on panels
     whose backdrop was also filter-transitioning (chapter 10 with
     its white SVG bg was the worst offender). Fade-only is stable
     across every chapter. */
  transition: opacity .35s var(--ease-inout);
}
.vb-panel__num span {
  display: inline-block;
  padding: 9px 6px;
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: rgba(255,255,255,.95);
  /* Solid-ish background instead of backdrop-filter:blur. Blur
     was causing repaint jitter during the SVG filter transition
     because the blurred backdrop had to recompute every frame. */
  background: rgba(26,26,26,.72);
  border-radius: 999px;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  box-shadow: 0 1px 4px rgba(0,0,0,.22);
  transition:
    background .3s var(--ease-inout),
    color .3s var(--ease-inout);
}
.vb-panel.is-active .vb-panel__num {
  opacity: 0;
}
/* Hover: the pill warms up to Vertwo orange. Thumbs only — the active
   panel's pill is already hidden so this selector never fires on it. */
.vb-panel:hover:not(.is-active) .vb-panel__num span {
  background: var(--v-orange);
  color: var(--v-white);
  box-shadow: 0 2px 10px rgba(242,122,15,.45);
}

/* =============== RESPONSIVE — CAROUSEL (tablet + mobile) =============== */
/* Below 1025px: ditch the accordion and use a real draggable carousel.
   Previously tablets (769-1024) got the desktop accordion with a
   "flick to advance" touch handler — but that binary flick with no
   visible drag feedback felt stuck on touch devices. Converting
   tablets to carousel gives continuous-drag feedback and matches
   what touch users expect. */

/* =============== CAROUSEL MODE (tablet + mobile) =============== */
/* Below 1025px: the draggable scroll-snap carousel. Each card is one
   full-width (with peek) swipeable unit. On tablet widths this means
   slightly smaller header + nav, and a bigger card; on phone widths
   the whole section tightens up further. */
@media (max-width: 1100px) {
  .vb-accordion {
    /* TRANSFORM-BASED CAROUSEL (TC gallery pattern).
       Switched away from native overflow-x scroll because mouse drag on
       a scroll container is fundamentally main-thread (browsers don't
       accelerate scroll for mouse-driven scrolls — only touch). With
       transform on a track child, drag is a pure GPU translate per
       frame, equivalent to TC gallery's drag which works smoothly. */
    flex-direction: row;
    aspect-ratio: auto;
    height: auto;
    padding: 2px 0 18px;
    margin: 0 -16px;
    overflow: hidden;             /* clip the wider track */
    contain: paint;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: pan-y;          /* let vertical pan bubble; horizontal owned by JS */
  }
  .vb-accordion.is-dragging { cursor: grabbing; }
  .vb-track {
    /* Mobile: real flex container that holds the panels. Transform on
       this is what creates the "scroll" effect. */
    display: flex;
    flex: 0 0 auto;
    gap: 14px;
    will-change: transform;
  }
  .vb-track.is-snapping {
    /* JS adds this class for the snap-on-release animation, removes it
       once the transition ends so live drag is instant again. */
    transition: transform 0.42s cubic-bezier(0.16, 1, 0.3, 1);
  }
  /* The 14px end-spacers come back as track ::before/::after so they
     translate with the track and produce a real visual gutter at both
     ends regardless of scroll position. */
  .vb-track::before,
  .vb-track::after {
    content: '';
    flex: 0 0 14px;
  }
  .vb-accordion::-webkit-scrollbar { display: none; }  /* Chrome/Safari */

  /* Removed .vb-accordion::before/::after spacers — gutters are now on
     .vb-track::before/::after so they translate with the track. */

  .vb-panel,
  .vb-panel.is-active {
    /* Use viewport-derived width via CSS var to break the flex circular
       dependency: track is now `width: max-content` (sums of children)
       and panels were `100% - 56px` of track-width which is undefined
       when track sizes from children. JS keeps --vb-panel-width in sync
       with the actual accordion width on resize. Fallback to 100vw-56
       for first paint before JS runs. */
    flex: 0 0 var(--vb-panel-width, calc(100vw - 56px));
    width: var(--vb-panel-width, calc(100vw - 56px));
    min-width: 0;
    aspect-ratio: 16 / 9;         /* every card is 16:9 in carousel mode too */
    border-radius: 20px;
    /* Inherit the accordion's cursor (grab / grabbing) instead of
       overriding with pointer. Before this, hovering a card showed
       the click hand while hovering the gap between cards showed
       the grab hand — jarring and inconsistent. Now the whole
       draggable area reads as one cohesive surface. */
    cursor: inherit;
    /* Simpler shadow than desktop — heavy 64px-blur shadows on every
       scrolling card were causing visible scroll jank on lower-end
       mobile GPUs. This 2-layer version still feels premium but
       composites dramatically faster. */
    box-shadow:
      0 0 0 1px rgba(255,255,255,.05),
      0 16px 32px -12px rgba(0,0,0,.65);
    /* Kill the will-change from the base .vb-panel rule — flex-grow
       isn't animated in carousel mode, so reserving compositor
       resources for it just wastes them and slows scroll. */
    will-change: auto;
    transition: box-shadow .3s var(--ease-soft);
  }

  /* translateZ(0) on .vb-panel__bg was added for the desktop white-
     edge fix (it forces the grayscale filter into its own composite
     layer before the rounded clip). In carousel mode the filter is
     disabled (rule below), so that fix isn't needed — and 10 extra
     compositing layers during scroll is measurable jank on mid-range
     phones. Dropping it back to auto. */
  .vb-panel__bg { transform: none; }

  /* --- CAROUSEL PARALLAX ---
     Two layers, driven by CSS vars that JS updates on every scroll
     frame (see the scroll listener + RAF loop in the script block):

       --bg-parallax    : background layer, shifts opposite to the
                          panel's distance-from-viewport-center. Gets
                          a pre-applied scale(1.22) so there's enough
                          slack to translate ±11% without exposing
                          the rounded clip edges.
       --title-parallax : foreground layer (eyebrow + title text),
                          shifts in the opposite direction to the bg
                          for a stronger sense of depth.

     Both default to 0 so the effect is inert until JS kicks in, and
     both use translate3d(...) so they stay on the GPU compositor. */
  /* v0.22.7 — Parallax disabled on mobile per Vic's "stick to the
     images, just slide along" request. Previously the SVG bg got an
     opposite-direction translate3d shift driven by --bg-parallax
     (computed from the in-flight track offset) so the bg appeared to
     drift relative to its panel during a snap. That motion was the
     "jumpy gradient" Vic was seeing. Now the bg has no transform —
     it slides 1:1 with its parent panel, identical to how a static
     image would behave inside the carousel. The --bg-parallax /
     --title-parallax CSS vars set by updateParallax() are still
     written but no longer read by these selectors, so the rAF
     parallax loop is effectively a no-op on mobile (left in place
     to keep the snap-tick scaffolding intact for desktop drag, where
     --vb-panel-width is also synced). */
  .vb-panel__bg svg,
  .vb-panel__bg-image {
    transform: none;
  }
  /* On mobile, every card is effectively "active" — show gradient
     + title on all of them, hide the folded number (which assumes
     a narrow thumb width). */
  .vb-panel__gradient { opacity: 1; }
  .vb-panel__num { display: none; }
  .vb-panel__title {
    opacity: 1;
    filter: none;
    padding: 24px 24px 26px;
    transition: none;
    /* v0.22.7 — Title parallax also disabled. Title slides with the
       panel, no opposite-direction drift. */
    transform: none;
  }
  .vb-panel__eyebrow { font-size: 11px; margin-bottom: 8px; }

  /* Carousel cards are always "featured" (one at a time on swipe).
     The desktop grayscale-at-rest rule would make the next/previous
     peek cards look dull, so we override to full color across the
     whole carousel. */
  .vb-panel__bg svg,
  .vb-panel:hover:not(.is-active) .vb-panel__bg svg {
    filter: none;
  }

  /* Active glow: not used in carousel mode, but keep the rule
     harmless so resizing back to desktop doesn't leave a ghost glow. */
  .vb-panel.is-active {
    box-shadow:
      0 0 0 1px rgba(255,255,255,.05),
      0 16px 32px -12px rgba(0,0,0,.65);
  }
}

/* Phone-size tightening. Below 640px we shrink the header + title
   and scale the card title down so everything fits comfortably on a
   phone screen. The carousel mechanic above stays identical. */
@media (max-width: 640px) {
  .vertwo-branding { padding: 56px 16px; }

  .vb-header { margin-bottom: 24px; }
  .vb-title-group h2 { font-size: 30px; line-height: 1.05; }
  .vb-title-group p  { font-size: 15px; }
  .vb-nav-btn { width: 44px; height: 44px; border-radius: 12px; }

  .vb-panel__title h3 { font-size: 22px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .2s !important;
    scroll-behavior: auto !important;
  }
}

/* ───── KEY PERSONS module styles (scoped) ───── */

/* ============================================================
   VERTWO · KEY PERSONS · v14
   -----------------------------------------------------------
   Architecture:
   - Absolute-positioned cards on a stage
   - CSS variables drive position (--x --y --w --h)
   - JS computes positions based on state; CSS transitions animate
   - ONE shared portrait element per card (no cross-fade)
   - Data-driven content (PEOPLE array → DOM)
   - Zero FLIP, zero grid-template animation hacks
   ============================================================ */

:root{
  --v-orange: #F27A0F;
  --v-gold:   #F5A623;
  --v-ink:    #1A1A1A;
  --v-white:  #FFFFFF;

  --surface-0: #FFFFFF;
  --surface-1: #F6F6F7;
  --surface-2: #EEEEF1;
  --line:      rgba(26,26,26,0.08);
  --line-2:    rgba(26,26,26,0.14);
  --muted:     rgba(26,26,26,0.62);

  --v-grad: linear-gradient(135deg, #F27A0F 0%, #F5A623 100%);

  /* Easing */
  --ease:       cubic-bezier(.83,0,.17,1);      /* card movement */
  --ease-out:   cubic-bezier(.22,1,.36,1);      /* micro-interactions */
  --ease-slide: cubic-bezier(.97,0,.03,1);      /* image slides — extremely pronounced ease-in-out */

  --dur-card:  720ms;
  --dur-inner: 420ms;
  --dur-hover: 280ms;
  --dur-glow:  900ms;   /* very slow, lingering glow/shadow transitions */
  --dur-slide: 680ms;   /* image slide transitions (gallery + lightbox).
                            v0.22.20 — restored to canon. The "rapid arrow
                            clicks stutter" issue is solved by the lockout
                            in goToSlide (state.animating + 730ms timeout)
                            which drops extra clicks during animation, NOT
                            by shortening the transition. Same pattern as
                            the Works details gallery's `transitioning`
                            flag. */

  --font-display: "Neue Haas Grotesk Display Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-body:    "Inter", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
}





button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

/* ============================================================
   Section
   ============================================================ */
.kp-section{
  max-width: 1280px;
  margin: 0 auto;
  /* Tightened clamps to bring sections closer together vertically. */
  padding: clamp(32px, 5vw, 64px) clamp(20px, 4vw, 48px) clamp(40px, 6vw, 72px);
}

.kp-head{
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: clamp(28px, 4vw, 48px);
}
.kp-head-title{ max-width: 780px; }

.kp-eyebrow{
  font-size: 12px; font-weight: 600;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--v-orange);
  display: inline-flex; align-items: center; gap: 10px;
  margin: 0 0 18px;
}
.kp-eyebrow::before{
  content: ""; width: 22px; height: 2px;
  background: var(--v-grad); border-radius: 2px;
}

.kp-title{
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(40px, 6vw, 84px);
  line-height: 0.96;
  letter-spacing: -0.035em;
  margin: 0;
  color: var(--v-ink);
}
.kp-title .dot{ color: var(--v-orange); }

.kp-caption{
  max-width: 360px;
  color: var(--muted);
  font-size: 15px; line-height: 1.55;
  margin: 0 0 8px;
  text-align: right;
}

/* ============================================================
   Stage — absolute-positioned card container
   ============================================================ */
.kp-stage{
  position: relative;
  width: 100%;
  /* height is set by JS via --stage-h */
  height: var(--stage-h, 460px);
  opacity: 0;
  transition: height var(--dur-card) var(--ease), opacity 360ms var(--ease-out);
}
.kp-stage.is-ready{ opacity: 1; }

/* Kill all transitions inside stage — used for instant layout
   (initial load + window resize) so things don't animate weirdly. */
.kp-stage.no-transition,
.kp-stage.no-transition *,
.kp-stage.no-transition *::before,
.kp-stage.no-transition *::after{
  transition: none !important;
}

/* ============================================================
   Card — absolute positioned, driven by CSS vars
   ============================================================ */
.kp-card{
  position: absolute;
  left: var(--x, 0px);
  top: var(--y, 0px);
  width: var(--w, 280px);
  height: var(--h, 460px);

  background: var(--surface-1);
  border-radius: 20px;
  overflow: hidden;

  cursor: pointer;
  outline: none;
  -webkit-tap-highlight-color: transparent;

  /* the big one — everything that changes position/size animates */
  transition:
    left        var(--dur-card) var(--ease),
    top         var(--dur-card) var(--ease),
    width       var(--dur-card) var(--ease),
    height      var(--dur-card) var(--ease),
    box-shadow  var(--dur-glow) var(--ease-out),
    background  var(--dur-glow) var(--ease-out);

  /* hover shadow baseline */
  box-shadow:
    0 0 0 1px var(--line),
    0 1px 2px rgba(0,0,0,0.02);
}

/* v0.22.7 — Hover glow gated behind (hover: hover) — iOS sticky-hover
   was leaving the orange ring on the just-tapped card after a chip
   click, contributing to perceived flicker. Keyboard focus-visible
   stays separate (always-on) for a11y. */
@media (hover: hover) {
  .kp-stage:not(.has-expanded) .kp-card:hover{
    box-shadow:
      0 0 0 2px var(--v-orange),
      0 18px 50px -12px rgba(242,122,15,0.38),
      0 4px 12px -2px rgba(242,122,15,0.18);
    background: #FCFCFD;
  }
}
.kp-stage:not(.has-expanded) .kp-card:focus-visible{
  box-shadow:
    0 0 0 2px var(--v-orange),
    0 18px 50px -12px rgba(242,122,15,0.38),
    0 4px 12px -2px rgba(242,122,15,0.18);
  background: #FCFCFD;
}

/* Expanded card baseline */
.kp-card.is-expanded{
  cursor: default;
  background: var(--surface-0);
  box-shadow:
    0 0 0 1px var(--line),
    0 30px 80px -20px rgba(26,26,26,0.18),
    0 10px 24px -10px rgba(26,26,26,0.10);
  z-index: 3;
}

/* Peek (mini) cards — when another card is expanded, these lower-row cards */
.kp-card.is-peek{
  cursor: pointer;
}
/* v0.22.7 — gated behind (hover: hover) for sticky-hover reasons. */
@media (hover: hover) {
  .kp-stage.has-expanded .kp-card.is-peek:hover{
    box-shadow:
      0 0 0 2px var(--v-orange),
      0 12px 30px -10px rgba(242,122,15,0.32);
  }
}

/* ============================================================
   Portrait — SINGLE element, position/size driven by CSS vars
   ============================================================ */
.kp-portrait{
  position: absolute;
  left: var(--pt-l, 16px);
  top: var(--pt-t, 16px);
  width: var(--pt-w, 252px);
  height: var(--pt-h, 290px);
  border-radius: 14px;
  overflow: hidden;
  background: var(--surface-2);

  transition:
    left       var(--dur-card) var(--ease),
    top        var(--dur-card) var(--ease),
    width      var(--dur-card) var(--ease),
    height     var(--dur-card) var(--ease),
    box-shadow var(--dur-glow) var(--ease-out);
}

.kp-portrait .kp-photo{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  user-select: none; -webkit-user-drag: none;
}

/* Fallback monogram behind the image */
.kp-portrait::before{
  content: attr(data-monogram);
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(48px, 8vw, 120px);
  color: rgba(26,26,26,0.08);
  letter-spacing: -0.04em;
}

/* v0.22.2 — Hairline outline drawn AS A TOP-LAYER OVERLAY over the
   portrait. v0.22.1 used `box-shadow: inset` directly on .kp-portrait
   but that paints UNDER .kp-photo (which is position:absolute inset:0
   and fully opaque), so portraits with uploaded photos showed no
   outline. Pseudo `::after` stacks above all real children including
   the photo, so the frame is visible whether the portrait has a photo
   or only the monogram fallback. pointer-events:none keeps the click
   target unaffected; border-radius:inherit follows the 14px corners.
   `inset` opacity .18 matches the team-culture hairline separator. */
.kp-portrait::after{
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(26,26,26,0.18);
}

/* Role tag badge (e.g. FOUNDER · CEO).
   v0.22.1 — switched bg from near-black to brand orange so the role
   pops against both light portraits (skin tones) and dark portraits
   alike. backdrop-filter is preserved as a no-op safety net for any
   future translucent variant; on the solid orange it has no visible
   effect. */
.kp-tag{
  position: absolute;
  left: 12px; bottom: 12px;
  padding: 6px 12px;
  background: var(--orange);
  color: var(--v-white);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-radius: 999px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  white-space: nowrap;
}

/* Hide the badge on peek cards — the small portrait clips it ("CO-FOUNDER · COO"
   becomes "CO-FOUND") and the same role text is already shown next to the
   portrait via .kp-compact, so the badge is redundant in this state. */
.kp-card.is-peek .kp-tag{
  display: none;
}

/* Same reasoning on mobile: portraits are smaller and the role text is shown
   right below in .kp-compact. The badge would clip and is redundant. */
.kp-stage.mode-mobile .kp-tag{
  display: none;
}

/* On tablet the COMPACT cards are 4 in a row, so individually each card is
   narrow (170-225px portraits) — badges clip there too. Keep it visible on
   the EXPANDED tablet card where the portrait is a comfortable 260px. */
.kp-stage.mode-tablet .kp-card:not(.is-expanded) .kp-tag{
  display: none;
}

/* Portrait is decorative in expanded state — not clickable anymore */

/* ============================================================
   Compact content — name, role, CTA (visible in compact state)
   ============================================================ */
.kp-compact{
  position: absolute;
  left: var(--cp-l, 20px);
  top: var(--cp-t, 324px);
  right: var(--cp-r, 20px);
  bottom: var(--cp-b, 16px);

  display: flex;
  flex-direction: column;
  gap: 6px;
  opacity: 1;
  transform: translateY(0);
  /* On collapse: compact fades IN with a delay so card has resized first */
  transition:
    left      var(--dur-card) var(--ease),
    top       var(--dur-card) var(--ease),
    right     var(--dur-card) var(--ease),
    bottom    var(--dur-card) var(--ease),
    opacity   320ms var(--ease-out) 320ms,
    transform 320ms var(--ease-out) 320ms;
}

.kp-name-sm{
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 22px;
  line-height: 1.08;
  letter-spacing: -0.025em;
  margin: 0;
  color: var(--v-ink);
}
.kp-name-sm .dot{ color: var(--v-orange); }

.kp-role-sm{
  font-size: 14px;
  color: var(--muted);
  margin: 0;
}

.kp-cta{
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--v-ink);
  transition: color var(--dur-hover) var(--ease-out), gap var(--dur-hover) var(--ease-out);
}
.kp-cta svg{ width: 14px; height: 14px; transition: transform var(--dur-hover) var(--ease-out); }
/* v0.22.7 — KP CTA hover gated behind (hover: hover). */
@media (hover: hover) {
  .kp-card:hover .kp-cta{ color: var(--v-orange); gap: 12px; }
  .kp-card:hover .kp-cta svg{ transform: translateX(2px); }
}

/* Hide compact content when card is expanded */
.kp-card.is-expanded .kp-compact{
  opacity: 0;
  transform: translateY(14px);
  pointer-events: none;
  /* fade out fast, no delay */
  transition:
    opacity   180ms var(--ease-out),
    transform 180ms var(--ease-out);
}

/* Peek state: compact content becomes landscape layout */
.kp-card.is-peek .kp-compact{
  left: var(--cp-l, 112px);
  top: var(--cp-t, 18px);
  right: var(--cp-r, 14px);
  bottom: var(--cp-b, 18px);
  gap: 3px;
  justify-content: center;
}
.kp-card.is-peek .kp-name-sm{ font-size: 15px; }
.kp-card.is-peek .kp-role-sm{ font-size: 12px; }
.kp-card.is-peek .kp-cta{ display: none; }

/* ============================================================
   Expanded body — middle column (name-lg, bio, chips)
   ============================================================ */
.kp-body{
  position: absolute;
  left: var(--bd-l, 424px);
  top: var(--bd-t, 48px);
  width: var(--bd-w, 300px);
  bottom: var(--bd-b, 48px);

  display: flex;
  flex-direction: column;
  gap: 18px;

  opacity: 0;
  transform: translateY(14px);
  pointer-events: none;
  /* Fast fade OUT on collapse */
  transition:
    opacity   200ms var(--ease-out) 0ms,
    transform 200ms var(--ease-out) 0ms;
}
.kp-card.is-expanded .kp-body{
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
  /* Slow, delayed fade IN on expand — card resizes first */
  transition:
    opacity   var(--dur-inner) var(--ease-out) 300ms,
    transform var(--dur-inner) var(--ease-out) 300ms;
}

.kp-name-group{
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.kp-name-lg{
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin: 0;
  color: var(--v-ink);
}
.kp-name-lg .dot{ color: var(--v-orange); }

.kp-role-lg{
  margin: 0;
  font-style: italic;
  font-size: 15px;
  color: var(--muted);
}

.kp-sep{
  border: 0;
  height: 1px;
  background: var(--line);
  margin: 6px 0;
}

.kp-bio{
  font-size: 15px;
  line-height: 1.6;
  color: var(--v-ink);
  margin: 0;
  opacity: 0.9;
}

/* ============================================================
   Chips block — "Past roles" label + chips, BELOW the portrait
   (its own absolute-positioned column member, not inside body)
   ============================================================ */
.kp-chips-block{
  position: absolute;
  left:  var(--ch-l, 32px);
  top:   var(--ch-t, 492px);
  width: var(--ch-w, 583px);

  display: flex;
  flex-direction: column;
  gap: 10px;

  opacity: 0;
  transform: translateY(14px);
  pointer-events: none;
  /* Fast fade OUT on collapse */
  transition:
    left      var(--dur-card)  var(--ease),
    top       var(--dur-card)  var(--ease),
    width     var(--dur-card)  var(--ease),
    opacity   200ms            var(--ease-out) 0ms,
    transform 200ms            var(--ease-out) 0ms;
}
.kp-card.is-expanded .kp-chips-block{
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
  /* Slow, delayed fade IN on expand */
  transition:
    left      var(--dur-card)  var(--ease),
    top       var(--dur-card)  var(--ease),
    width     var(--dur-card)  var(--ease),
    opacity   var(--dur-inner) var(--ease-out) 280ms,
    transform var(--dur-inner) var(--ease-out) 280ms;
}

.kp-chips-label{
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.kp-chips-label::before{
  content: ""; width: 18px; height: 2px;
  background: var(--v-grad); border-radius: 2px;
}

.kp-chips{
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 14px;
  background: var(--surface-1);
  border-radius: 14px;
  border: 1px solid var(--line);
}

.kp-chip{
  padding: 8px 14px;
  background: rgba(26,26,26,0.92);
  color: var(--v-white);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  border-radius: 999px;
  transition:
    background var(--dur-hover) var(--ease-out),
    box-shadow var(--dur-glow)  var(--ease-out),
    transform  var(--dur-hover) var(--ease-out);
}
/* v0.22.5 — Hover effect gated behind @media (hover: hover) so it
   ONLY applies on devices with a real hovering pointer. iOS Safari
   reports `hover: none` for touch — without this guard, tapping a
   chip on iPhone leaves it in a stuck :hover state (background still
   orange) until the user taps somewhere else, which makes the chip
   look "still active" alongside the actually-active chip. Vic's
   screenshot showed both "ex-CEO · HIVE" (active, slide 9) AND
   "Co-Founder · CONNECTOON" (sticky-hover from a prior tap) lit
   simultaneously. With this media query, .is-active is the only path
   that paints orange on touch devices, so exactly one chip is ever
   highlighted. */
@media (hover: hover) {
  .kp-chip:hover{
    background: var(--v-orange);
    box-shadow: 0 8px 20px -6px rgba(242,122,15,0.5);
    transform: translateY(-1px);
  }
}
.kp-chip.is-active{
  background: var(--v-orange);
  box-shadow: 0 0 0 2px rgba(242,122,15,0.25);
}

/* ============================================================
   Expanded gallery — right column slider
   ============================================================ */
.kp-gallery{
  position: absolute;
  left: var(--gl-l, 760px);
  right: var(--gl-r, 32px);
  top: var(--gl-t, 32px);
  bottom: var(--gl-b, 32px);

  display: flex;
  flex-direction: column;
  gap: 14px;

  opacity: 0;
  transform: translateY(18px);
  pointer-events: none;
  /* Fast fade OUT on collapse */
  transition:
    opacity   200ms var(--ease-out) 0ms,
    transform 200ms var(--ease-out) 0ms;
}
.kp-card.is-expanded .kp-gallery{
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
  /* Slow, delayed fade IN on expand */
  transition:
    opacity   var(--dur-inner) var(--ease-out) 380ms,
    transform var(--dur-inner) var(--ease-out) 380ms;
}

.kp-gallery-head{
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.kp-gallery-head::before{
  content: ""; width: 18px; height: 2px;
  background: var(--v-grad); border-radius: 2px;
}

.kp-gallery-viewport{
  position: relative;
  flex: 1;
  overflow: hidden;
  border-radius: 18px;
  background: var(--surface-2);
  min-height: 0;
  /* v0.22.13 — All GPU layer hints (translateZ, backface-visibility,
     contain) added in v0.22.10 + v0.22.12 REVERTED. Vic's v0.22.12
     debug logs showed the same clean 60fps pattern — the layer
     promotions weren't fixing the flicker, and stacking too many
     compositor hints across nested elements is a known iOS Safari
     anti-pattern that causes "layer thrashing" (the compositor
     re-allocates surfaces every frame). Falling back to the
     minimal set: track-only `will-change: transform`, no parent
     hints. */
}

.kp-gallery-track{
  position: absolute; inset: 0;
  display: flex;
  transition: transform var(--dur-slide) var(--ease-slide);
  will-change: transform;
  /* v0.22.13 — extra hints from v0.22.10 (backface-visibility +
     baseline translate3d(0,0,0)) REVERTED. They didn't fix the
     flicker per Vic's v0.22.12 logs, and on iOS Safari stacking
     multiple compositor hints can cause layer-thrashing artifacts
     that don't show up in frame timing. Back to the minimal
     `will-change: transform`. */
}

/* v0.22.5 — toggled on by setTrackTransformInstant() in page-about.js
   to forcibly disable the transform transition for the duration of an
   "instant snap" (clone-of-last → real-last after a wrap-around chip
   click). The !important is REQUIRED here because the rule above sets
   `transition: transform ...` directly on .kp-gallery-track, which has
   the same specificity (single class) as a hypothetical no-important
   override. Single-class no-important could lose the cascade race
   depending on declaration order, which on iOS Safari resulted in the
   snap visibly animating an 83%-of-viewport jump (Vic's reported
   flicker through v0.22.4). */
.kp-gallery-track.kp-no-anim{
  transition: none !important;
}

/* v0.22.20 — Cross-fade rules removed. Vic prefers slide-transition
   animations consistent across chips/arrows/drag (matches the canon
   prototype + Works details gallery design). */

.kp-slide{
  position: relative;
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  overflow: hidden;
  cursor: zoom-in;
  /* v0.32.87 — Unified GPU layer for the slide on EVERY mode. Was
     previously scoped to .mode-mobile + .mode-tablet via the v0.22.34
     cure; the video Vic shot was on iPad landscape running .mode-desktop
     (12.9"/11" iPad in landscape exceeds the JS isTablet 1100px
     threshold), where the v0.22.33 rule promotes .kp-slide-bg to its
     own GPU layer for the prototype look but leaves .kp-slide-overlay
     un-promoted. iOS Safari's compositor splits them: bg translates
     atomically with the track transform, overlay rides on a separate
     paint cycle and visibly disappears mid-transition. Promoting the
     parent .kp-slide unifies bg + overlay back into one layer so they
     translate as a single unit (same approach v0.22.34 used on phones
     + iPad portrait). Safe on desktop too — there's no JS parallax on
     .kp-slide-bg, so we lose nothing by moving the GPU hint up the
     tree. */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.kp-slide-bg{
  position: absolute; inset: 0;
  background-size: cover;
  background-position: center;
  /* v0.22.30 — Reverted to v0.22.28 state. v0.22.29 attempt to use
     <img> element instead broke iPad portrait without fixing iPad
     landscape, so we're back to inline background-image. */
}

/* Orange ring + warm glow on slide hover */
.kp-slide::after{
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  border-radius: 18px;
  box-shadow: inset 0 0 0 0 transparent;
  transition: box-shadow var(--dur-glow) var(--ease-out);
}
/* v0.22.7 — Gated behind (hover: hover) for the same reason as
   .kp-chip:hover (v0.22.5 fix): iOS Safari's sticky-hover treats a
   tap as :hover until the next tap, then transfers :hover as the
   finger moves over different elements. With the gallery animating
   underneath the user's touch point, the orange ring was flashing
   on/off as different slides passed under the held finger — Vic's
   reported "gallery flicker on chip click" was actually this ring
   transitioning, NOT the clone-snap as I'd been chasing. The
   transition: box-shadow .25s on .kp-slide::after made each touch
   transition visible as a fade-in/out cycle (the flicker). */
@media (hover: hover) {
  .kp-slide:hover::after{
    box-shadow: inset 0 0 0 3px var(--v-orange);
  }
}

.kp-slide-overlay{
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: clamp(20px, 3vw, 36px);
  background: linear-gradient(
    to top,
    rgba(0,0,0,0.78) 0%,
    rgba(0,0,0,0.55) 45%,
    rgba(0,0,0,0.08) 85%,
    transparent 100%
  );
  color: var(--v-white);
  pointer-events: none;
  /* v0.32.88 — Smooth fade for the slide overlay. Several earlier
     rounds (v0.32.82 / .83 / .86 / .87) tried to keep the overlay
     visible mid-transition by forcing bg + overlay onto a unified GPU
     layer; iOS Safari kept splitting them anyway. Vic's suggestion:
     "make the text fade-in more smoothly and slowly". So instead of
     fighting the compositor, we lean in — fade overlay OUT quickly
     when the track starts sliding (300ms) and back IN slowly when
     it settles (600ms + 60ms delay so the slide is visually parked
     before the text re-materializes). The is-sliding class on the
     track is set/cleared by transitionstart/transitionend listeners
     in buildCard. */
  opacity: 1;
  transition: opacity 600ms ease-out 60ms;
}
.kp-gallery-track.is-sliding .kp-slide-overlay{
  opacity: 0;
  transition: opacity 300ms ease-out;
}

.kp-slide-eyebrow{
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* v0.32.82 — was var(--v-gold); Vic's call for the brand orange.
     v0.32.89 — switched to white per Vic; the orange dot pseudo
     stays as the accent. */
  color: var(--v-white);
  margin-bottom: 8px;
}
.kp-slide-eyebrow::before{
  content: "";
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--v-orange);
  box-shadow: 0 0 10px rgba(242,122,15,0.8);
}

.kp-slide-year{
  font-family: var(--font-display);
  font-weight: 900;
  /* v0.32.82 — was clamp(44, 5.6vw, 80); Vic asked for a tick smaller. */
  font-size: clamp(40px, 4.8vw, 68px);
  line-height: 0.92;
  /* v0.32.82 — was var(--v-gold); brand-orange to match the eyebrow. */
  color: var(--v-orange);
  letter-spacing: -0.04em;
  margin: 0 0 6px;
}

.kp-slide-title{
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(18px, 2vw, 24px);
  line-height: 1.15;
  margin: 0 0 8px;
  color: var(--v-white);
}

.kp-slide-desc{
  font-size: 13.5px;
  line-height: 1.55;
  margin: 0;
  color: rgba(255,255,255,0.88);
  max-width: 48ch;
}

/* ============================================================
   Gallery footer — progress pills, counter, arrows
   ============================================================ */
.kp-gallery-foot{
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 16px;
  min-height: 36px;
}

.kp-pills{
  display: flex;
  gap: 6px;
  flex: 1;
  min-width: 0;
}
.kp-pill{
  flex: 1;
  height: 4px;
  background: var(--line-2);
  border-radius: 2px;
  overflow: hidden;
  position: relative;
  cursor: pointer;
  transition: background var(--dur-hover) var(--ease-out);
}
.kp-pill::after{
  content: "";
  position: absolute;
  inset: 0;
  background: var(--v-grad);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 360ms var(--ease-out);
  border-radius: 2px;
}
.kp-pill.is-active::after{ transform: scaleX(1); }
/* v0.22.7 — KP pill hover gated behind (hover: hover). */
@media (hover: hover) { .kp-pill:hover{ background: rgba(242,122,15,0.22); } }

.kp-counter{
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kp-counter .cur{ color: var(--v-ink); }

.kp-arrows{
  display: flex;
  gap: 6px;
}

/* Generic circular icon button — reused across the module */
.kp-icon-btn{
  width: 44px; height: 44px;
  border-radius: 12px;
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--v-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background   var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out),
    color        var(--dur-hover) var(--ease-out),
    box-shadow   var(--dur-glow)  var(--ease-out),
    transform    var(--dur-hover) var(--ease-out);
}
.kp-icon-btn svg{ width: 18px; height: 18px; }
.kp-icon-btn:hover{
  background: var(--v-orange);
  border-color: var(--v-orange);
  color: var(--v-white);
  box-shadow: 0 8px 22px -6px rgba(242,122,15,0.5);
}
.kp-icon-btn:disabled{
  opacity: 0.35;
  cursor: not-allowed;
}
.kp-icon-btn:disabled:hover{
  background: transparent;
  border-color: var(--line-2);
  color: var(--v-ink);
  box-shadow: none;
}

/* ============================================================
   Close button
   ============================================================ */
.kp-close{
  position: absolute;
  top: 16px; right: 16px;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--line-2);
  color: var(--v-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  z-index: 4;
  opacity: 0;
  pointer-events: none;
  transition:
    background   var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out),
    color        var(--dur-hover) var(--ease-out),
    opacity      240ms            var(--ease-out),
    transform    var(--dur-hover) var(--ease-out),
    box-shadow   var(--dur-glow)  var(--ease-out);
}
.kp-close svg{ width: 16px; height: 16px; }
.kp-close:hover{
  background: var(--v-orange);
  border-color: var(--v-orange);
  color: var(--v-white);
  transform: rotate(90deg);
  box-shadow: 0 8px 22px -6px rgba(242,122,15,0.5);
}
/* When card is expanded, reveal X with a short delay — but ONLY on the
   opacity transition, so hover responses stay snappy. */
.kp-card.is-expanded .kp-close{
  opacity: 1;
  pointer-events: auto;
  transition:
    background   var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out),
    color        var(--dur-hover) var(--ease-out),
    opacity      240ms            var(--ease-out) 180ms,
    transform    var(--dur-hover) var(--ease-out),
    box-shadow   var(--dur-glow)  var(--ease-out);
}

/* ============================================================
   Lightbox
   ============================================================ */
.kp-lightbox{
  position: fixed;
  inset: 0;
  background: rgba(10,10,12,0.94);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 260ms var(--ease-out);
}
.kp-lightbox.is-open{
  opacity: 1;
  pointer-events: auto;
}

/* DEFENSIVE: When the lightbox is closed, force pointer-events: none on ALL
   descendants. This protects against any current/future child that might set
   `pointer-events: auto` explicitly (which would otherwise override the
   parent's `none` and leave an invisible click-blocker over the page). */
.kp-lightbox:not(.is-open),
.kp-lightbox:not(.is-open) *{
  pointer-events: none !important;
}

/* Sliding viewport — fixed size so the track can slide 100% per slide */
.kp-lb-viewport{
  position: relative;
  width: 92vw;
  height: 84vh;
  overflow: hidden;
  /* transparent — no bounding box per spec */
}

.kp-lb-track{
  position: absolute;
  top: 0; left: 0;
  height: 100%;
  display: flex;
  will-change: transform;
  transition: transform var(--dur-slide) var(--ease-slide);
}

.kp-lb-slide{
  flex: 0 0 92vw;       /* each slide = viewport width */
  width: 92vw;
  height: 84vh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* click anywhere in the empty area around the image = close */
  /* v0.32.76 — relative anchor for the .kp-lb-overlay caption pill at
     slide bottom. Without this, the overlay (position:absolute) inherits
     its containing block from .kp-lb-track (the long sliding rail),
     which puts it at the rail's center — way off-screen during normal
     navigation. Same pattern used on .nd-lb-slide for the v0.32.61
     tag pill. This was the bug Vic flagged in the v0.32.75 lightbox:
     "still nothing" — the JS was inserting the overlay correctly,
     but CSS was placing it on the wrong containing block. */
  position: relative;
}

.kp-lb-image{
  display: block;
  max-width: 92vw;
  max-height: 84vh;
  width: auto;
  height: auto;
  object-fit: contain;
  user-select: none;
  -webkit-user-drag: none;
  cursor: pointer;        /* click image = advance to next slide (when open) */
  /* v0.32.79 — Rounded corners to match the .nd-lb-image precedent
     (news lightbox, set in v0.32.61). The pre-v0.32.78 overlay had a
     wrapping border-radius:18px that disguised the absence of image
     rounding; v0.32.78 dropped that to match the image edges and
     exposed the missing radius. Now both the image and the overlay's
     bottom corners share the same 8px curve. */
  border-radius: 8px;
  /* NOTE: deliberately NO `pointer-events: auto` here. An explicit `auto`
     would override the parent's `pointer-events: none` (set when lightbox
     is closed), leaving the invisible image as a click-blocking ghost.
     With pointer-events left alone, the image inherits the parent's
     state — clickable when open, completely inert when closed. */
}

/* v0.32.78 — Wrapper that shrink-wraps to the rendered .kp-lb-image's
   display box. The img's own max-w/max-h does the contain-fit math (a
   landscape original lands height-capped to 84vh × ratio-derived width;
   a portrait original lands width-capped to 92vw × ratio-derived height
   OR height-capped depending on the aspect). `display: inline-block`
   then snaps the wrapper to those rendered dimensions. With this in
   place, an absolute-positioned .kp-lb-overlay anchored to the wrapper
   bottom-aligns to the IMAGE bottom and spans only the IMAGE width —
   no more dead band under landscape images, no more pill overflow past
   portrait image edges. */
.kp-lb-img-wrap{
  position: relative;
  display: inline-block;
  max-width: 92vw;
  max-height: 84vh;
  line-height: 0; /* belt-and-suspenders against baseline gap below img */
}

/* v0.32.75 — Caption pill on each lightbox slide. Surfaces the same
   eyebrow / year / title / desc fields shown in the inline .kp-slide-overlay
   so users keep that context inside the lightbox.
   v0.32.77 — Widened to banner proportions, vertical padding tightened,
   and the flat glass background replaced with a bottom-up gradient
   (matches the inline .kp-slide-overlay's `to top` pattern). The top of
   the banner fades to transparent so the image reads through above the
   text band. Border + backdrop-filter dropped — a hard edge or uniform
   blur fights the gradient fade. Top padding is intentionally generous
   so the eyebrow sits inside the opaque band rather than the fading
   gradient tail.
   v0.32.78 — Re-anchored from the slide (.kp-lb-slide) to the image
   wrapper (.kp-lb-img-wrap), so width tracks the image's actual rendered
   width and bottom-edge sits flush against the image bottom. No more
   `width: min(...)` cap or `translateX(-50%)` centering — the wrapper
   already sizes to the image, so left:0/right:0/bottom:0 does the job.
   `border-radius: 0` to match the image edges (image has no radius). */
.kp-lb-overlay{
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: clamp(34px, 4vw, 56px) clamp(24px, 2.6vw, 32px) clamp(14px, 1.6vw, 18px);
  background: linear-gradient(
    to top,
    rgba(0,0,0,0.82) 0%,
    rgba(0,0,0,0.60) 45%,
    rgba(0,0,0,0.18) 85%,
    transparent 100%
  );
  /* v0.32.79 — Round only the bottom corners (8px) to match the image's
     border-radius. Top corners stay square — they're inside the
     gradient's fade-to-transparent band and so are invisible regardless. */
  border-radius: 0 0 8px 8px;
  color: var(--v-white);
  pointer-events: none;
  z-index: 3;
  text-align: left;
  line-height: normal; /* reset wrapper's line-height: 0 for descendants */
}

.kp-lb-eyebrow{
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* v0.32.82 — was var(--v-gold); match brand orange.
     v0.32.89 — switched to white per Vic; orange dot pseudo stays. */
  color: var(--v-white);
  margin-bottom: 4px; /* v0.32.77 — tighter for the wider/shorter banner */
}
.kp-lb-eyebrow::before{
  content: "";
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--v-orange);
  box-shadow: 0 0 10px rgba(242,122,15,0.8);
}

.kp-lb-year{
  font-family: var(--font-display);
  font-weight: 900;
  /* v0.32.77 — shrunk from clamp(40,5vw,72) so the banner stays short.
     v0.32.82 — another step smaller per Vic's call. */
  font-size: clamp(32px, 3.6vw, 52px);
  line-height: 0.92;
  /* v0.32.82 — was var(--v-gold); brand orange. */
  color: var(--v-orange);
  letter-spacing: -0.04em;
  margin: 0 0 2px; /* v0.32.77 — tighter spacing to title */
}

.kp-lb-title{
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(18px, 2vw, 24px);
  line-height: 1.15;
  margin: 0 0 6px; /* v0.32.77 — tighter spacing to desc */
  color: var(--v-white);
}

.kp-lb-desc{
  font-size: 13.5px;
  line-height: 1.5; /* v0.32.77 — slight tighten from 1.55 */
  margin: 0;
  color: rgba(255,255,255,0.88);
}

/* v0.32.75 — Mobile/narrow shrink for the lightbox caption pill so it
   doesn't crowd the image on phones. Mirrors the .mode-mobile shrink
   used on the inline .kp-slide-overlay so type stays visually consistent
   between the inline card and the lightbox at small sizes.
   v0.32.77 — Widened to ~94vw banner; vertical padding asymmetric (more
   top so the eyebrow lands in the opaque part of the gradient fade).
   v0.32.78 — Overlay now spans the image width via .kp-lb-img-wrap, so
   the `width: 94vw` + `bottom: 80px` clear-the-footer overrides are no
   longer needed (footer chrome sits BELOW the image's slide box). Only
   the padding / type-shrink rules remain.
   v0.32.81 — Major restructure for narrow viewports (mobile + iPad
   portrait, ≤1023px). Caption pill moved OUT of the image and into
   the area BELOW it — Vic's call: at phone widths the text was
   blocking too much of the image. Now the wrapper flexes vertically
   (img on top, caption below); the image's max-height drops to 60vh
   so the caption gets ~24vh of breathing room before the footer
   chrome. iPad LANDSCAPE (1024+) and desktop are unaffected — they
   keep the v0.32.78 in-image gradient pill. */
@media (max-width: 1023px){
  .kp-lb-img-wrap{
    /* Stay inline-block so the wrap continues to shrink-wrap to the
       image's rendered width. Relaxing max-height lets the wrap grow
       downward for the in-flow caption underneath. The lb-viewport
       (84vh) still clips anything past it, so img max-h is dropped
       to 60vh below — that leaves ~24vh of slide for the caption. */
    max-height: none;
  }
  .kp-lb-image{
    max-height: 60vh; /* leave room for the caption underneath */
  }
  .kp-lb-overlay{
    /* In-flow below the image as a block child of the inline-block wrap.
       width: auto lets the overlay take the wrap's width (= the image's
       rendered width) so the caption stays as wide as the image, no
       wider, no narrower. */
    position: static;
    display: block;
    width: auto;
    background: none;
    border-radius: 0;
    padding: 14px 14px 8px;
  }
  .kp-lb-eyebrow{
    font-size: 10px;
    margin-bottom: 4px;
  }
  .kp-lb-year{
    /* v0.32.82 — was 34px. */
    font-size: 30px;
    margin-bottom: 2px;
  }
  .kp-lb-title{
    font-size: 16px;
    margin-bottom: 6px;
  }
  .kp-lb-desc{
    font-size: 12.5px;
    line-height: 1.45;
  }
}

.kp-lb-close{
  position: absolute;
  top: 24px; right: 24px;
  width: 48px; height: 48px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.24);
  color: var(--v-white);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background   var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out),
    color        var(--dur-hover) var(--ease-out),
    transform    var(--dur-hover) var(--ease-out),
    box-shadow   var(--dur-glow)  var(--ease-out);
  z-index: 2;
}
.kp-lb-close svg{ width: 20px; height: 20px; }
.kp-lb-close:hover{
  background: var(--v-orange);
  border-color: var(--v-orange);
  transform: rotate(90deg);
  box-shadow: 0 10px 30px -6px rgba(242,122,15,0.6);
}

.kp-lb-nav{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 52px; height: 52px;
  border-radius: 14px;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.24);
  color: var(--v-white);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background   var(--dur-hover) var(--ease-out),
    border-color var(--dur-hover) var(--ease-out),
    color        var(--dur-hover) var(--ease-out),
    transform    var(--dur-hover) var(--ease-out),
    box-shadow   var(--dur-glow)  var(--ease-out);
  z-index: 2;
}
.kp-lb-nav svg{ width: 22px; height: 22px; }
.kp-lb-prev{ left: 24px; }
.kp-lb-next{ right: 24px; }
.kp-lb-nav:hover{
  background: var(--v-orange);
  border-color: var(--v-orange);
  box-shadow: 0 10px 30px -6px rgba(242,122,15,0.6);
}
.kp-lb-prev:hover{ transform: translateY(-50%) translateX(-3px); }
.kp-lb-next:hover{ transform: translateY(-50%) translateX(3px); }

.kp-lb-footer{
  position: absolute;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 16px;
  z-index: 2;
}

.kp-lb-pills{
  display: flex;
  gap: 6px;
}
.kp-lb-pill{
  width: 28px;
  height: 4px;
  background: rgba(255,255,255,0.22);
  border-radius: 2px;
  cursor: pointer;
  transition: background var(--dur-hover) var(--ease-out), width var(--dur-hover) var(--ease-out);
}
.kp-lb-pill.is-active{
  background: var(--v-orange);
  width: 40px;
}
.kp-lb-pill:hover{
  background: rgba(242,122,15,0.75);
}

.kp-lb-counter{
  color: rgba(255,255,255,0.7);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   Focus styles
   ============================================================ */
.kp-card:focus-visible{
  box-shadow:
    0 0 0 3px var(--v-orange),
    0 18px 50px -12px rgba(242,122,15,0.42);
}
button:focus-visible,
.kp-pill:focus-visible,
.kp-chip:focus-visible{
  outline: 2px solid var(--v-orange);
  outline-offset: 3px;
  border-radius: 999px;
}

/* ============================================================
   Responsive — mobile
   ============================================================ */
@media (max-width: 860px){
  .kp-head{
    flex-direction: column;
    align-items: flex-start;
  }
  .kp-caption{
    text-align: left;
    max-width: 100%;
  }
}

/* Mobile cosmetic tweaks. Layout itself (positions/sizes) is fully driven by
   JS now via the absolute-positioning model — see computeMobileLayout +
   computeExpandedLayout's mobile branch. This keeps transitions smooth
   (no position: absolute ↔ relative jump on expand/collapse). */
.kp-stage.mode-mobile .kp-card.is-expanded .kp-close{
  top: 10px; right: 10px;
  width: 36px; height: 36px;
}

/* v0.22.10 — Slide overlay content was overflowing the slide on mobile.
   Vic's screenshots: eyebrow text clipped at top of every slide card.

   Why: the gallery viewport on mobile is 300px (galleryH constant in
   computeMobileExpandedHeight) minus head (~18px) minus foot (~36px)
   minus 2×14px gaps = ~218px. With clamp(44px) year + 13.5px desc
   wrapping to 5+ lines + clamp(20px) padding top+bottom + margins
   between, the overlay needed ~245-280px — which exceeded the
   viewport, so the overlay's TOP (where the eyebrow lives) was being
   clipped by the slide's `overflow: hidden`.

   Fix: tighten everything inside the overlay on narrow viewports.
   Smaller year font, smaller padding, smaller desc + line-height. */
/* v0.22.28 — Mobile-cure scoped to NARROW viewports only (≤1023px).
   This covers iPhone (any orientation) and iPad PORTRAIT (~768px).
   iPad landscape (1024+) and desktop fall outside this query so they
   keep the prototype look with bg images visible. Vic's preference:
   cure applies where the gallery viewport is small enough that
   prototype font sizes overflow + the rasterization-during-transform
   flicker showed up on touch devices. */
/* v0.22.33 — Cure applies to mobile + ALL tablet (portrait AND
   landscape). Switched from `@media (max-width: 1023px)` to class
   selectors (.mode-mobile / .mode-tablet) so iPad landscape (which
   gets .mode-tablet at stageWidth 1024-1099) also receives the
   top-aligned text + top-down gradient. Vic noted iPad landscape
   felt laggy with the prototype's bottom-aligned bottom-up gradient
   on transforms; using the same simpler gradient as mobile evens
   things out. Desktop (.mode-desktop, stageWidth ≥1100) keeps the
   prototype look. */
/* v0.32.85 — Reverted v0.32.83 (combined bg+overlay) and v0.32.84 (flex
   column / text below image). Back to the v0.22.33 cure: overlay covers
   the whole slide with a top-down gradient, image visible behind via
   .kp-slide-bg sibling div. Vic's call: "make the text stick on top
   of each image. copy the effect from tablet portrait version which
   work well" — meaning keep the on-image overlay look that tablet
   portrait was running smoothly with. The drift cause we kept chasing
   may have been a perception artifact on certain tablet sizes; the
   v0.32.82 isolation+contain hints stay in place defensively. */
.kp-stage.mode-mobile .kp-slide-overlay,
.kp-stage.mode-tablet .kp-slide-overlay{
  /* Fill the slide so the gradient covers the entire bg image. */
  top: 0;
  bottom: 0;
  padding: 12px 14px;
  /* Top-down dark gradient for text readability over bg image. */
  background: linear-gradient(
    to bottom,
    rgba(0,0,0,0.78) 0%,
    rgba(0,0,0,0.55) 40%,
    rgba(0,0,0,0.20) 75%,
    rgba(0,0,0,0.05) 100%
  );
  display: block;
}

/* v0.22.34 — Unify .kp-slide as a single GPU compositor layer on
   mobile + tablet. iPad landscape was showing the bg-image lagging
   behind the overlay (text + gradient) during slide transitions —
   classic iOS Safari symptom of composite layers updating at
   different rates. By promoting .kp-slide itself to a layer (via
   translateZ(0) + will-change), the entire slide content (bg-image
   AND overlay) composites as ONE unit and translates atomically with
   the parent track transform. Result: title + gradient "stick to
   the image" exactly as Vic described mobile feeling. Mobile already
   worked because of perf headroom on iPhone — applying here too
   for consistency, harmless. */
.kp-stage.mode-mobile .kp-slide,
.kp-stage.mode-tablet .kp-slide{
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* v0.32.86 — Removed `isolation: isolate` + `contain: layout paint`
     (added in v0.32.82 to "strengthen" the unified-layer guarantee).
     Video frames from Vic's screen recording show the overlay text +
     gradient vanish for ~4 frames during slide transitions on iPad
     portrait then re-materialize at the destination, while the bg
     image translates smoothly throughout. That's a classic iOS
     Safari symptom of the overlay element being promoted to its OWN
     compositor layer despite the parent's translateZ. The likely
     cause was the v0.32.82 hints OVER-constraining rendering: with
     `contain: paint` the slide becomes a self-contained paint region
     and `isolation: isolate` creates a new stacking context — the
     combination can push iOS Safari to split off the absolute-
     positioned children into their own composite layers as an
     optimization, which is exactly what v0.22.34's translateZ was
     trying to prevent. Going back to v0.22.34's minimal set of
     hints. */
}
/* v0.22.33 — Slide content shrinks now apply to mobile + ALL tablet
   (extended to iPad landscape). Class-based, no @media. */
.kp-stage.mode-mobile .kp-slide-eyebrow,
.kp-stage.mode-tablet .kp-slide-eyebrow{
  font-size: 10px;
  margin-bottom: 4px;
}
.kp-stage.mode-mobile .kp-slide-year,
.kp-stage.mode-tablet .kp-slide-year{
  /* v0.32.82 — was 32px; matches the desktop tick-smaller bump. */
  font-size: 28px;
  margin-bottom: 2px;
}
.kp-stage.mode-mobile .kp-slide-title,
.kp-stage.mode-tablet .kp-slide-title{
  font-size: 16px;
  margin-bottom: 5px;
}
.kp-stage.mode-mobile .kp-slide-desc,
.kp-stage.mode-tablet .kp-slide-desc{
  font-size: 12.5px;
  line-height: 1.45;
}

/* v0.22.33 — GPU layer hints scoped to .mode-desktop only (was
   `@media (min-width: 1024px)` which covered iPad landscape too).
   Now iPad landscape gets the cure (no GPU hints needed there since
   it uses the same simpler overlay as mobile). Desktop keeps the
   GPU hints since it shows bg images via the prototype layout. */
.kp-stage.mode-desktop .kp-slide-bg {
  will-change: transform;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* Reduce motion */
@media (prefers-reduced-motion: reduce){
  
}

/* ───── SECTION TITLE STANDARDIZATION ─────
   Module titles (key-persons, brand-story) ship with their own font sizes
   and metrics that don't match our standardized section title style. This
   block runs LAST so it wins the cascade, unifying every section title
   to the same look: same font family (var(--font-title) = NHG), same size
   range, same weight, same letter-spacing, same line-height. Also applies
   text-transform:lowercase as a safety net for any title text that wasn't
   manually lowercased in source markup. */
#key-persons .kp-title,
#brand-story .vb-title-group h2{
  font-family: var(--font-title);
  font-size: clamp(1.9rem, 4vw, 2.9rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 1.12;
  text-transform: lowercase;
}


/* ═══════════════════════════════════════════════════════════════════
   v0.21.3 — WP-context patches (Vic feedback round 3)
   --------------------------------------------------------------------
   These rules sit AT THE END so they win the cascade. Each patch is
   commented with the problem and the why.
═══════════════════════════════════════════════════════════════════ */

/* PATCH 1 — #key-persons section bg.

   Problem: theme's design-system.css sets `body { background: #1d1d1f }`
   (a dark near-black) so editors see the dark footer canvas in the
   overscroll area. The prototype expects body bg = white, so its
   #key-persons section (which has no explicit bg rule) inherits white.
   In WP, the same #key-persons inherits the dark body bg, painting
   the section header on dark and clashing with the white founder
   cards inside.

   Fix: explicit white bg on #key-persons. Mirrors the same pattern
   already applied to #about-intro / #about-stats / #team-culture. */
#key-persons {
  background: var(--white);
}


/* PATCH 2 — heading color inheritance for dark sections.

   v0.21.3 originally added a broad `#vmv h*, #brand-story h* {
   color: inherit }` rule. v0.21.6 reverts that approach because
   it broke the VMV cards' gradient text effect (the .card__title
   class sets color:transparent + background-clip:text but the
   broad ID-prefixed h2 rule won on specificity) AND left the
   brand-story title color-less (inherited body's black instead
   of the .vb-title-group h2 white).

   v0.21.6 surgical replacement: target ONLY the elements that
   actually need an override away from design-system's
   `h{1..6} { color: var(--black) }` default. Use higher-specificity
   selectors so each rule wins cleanly without `!important`. */

/* VMV: re-establish .card__title's gradient text effect.
   The VMV scoped CSS already defines .card__title with
   color:transparent + background-clip:text gradient. Use the
   #vmv parent prefix to bump specificity above design-system's
   `h2 { color: var(--black) }` (0,0,0,1) → (1,0,1,0). */
#vmv .card__title {
  background: var(--v-gradient);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}
/* Section title stays solid white — bumped specificity. */
#vmv .vmv-title { color: #fff; }

/* Brand-story: title is solid white, panel-title h3 is also white.
   Bumped specificity via #brand-story prefix so design-system's
   `h2 { color: var(--black) }` doesn't win for the section title,
   and `h3 { color: var(--black) }` doesn't win for the active
   panel's chapter title. */
#brand-story .vb-title-group h2 { color: var(--v-white); }
#brand-story .vb-panel__title h3 { color: rgba(255,255,255,.95); }


/* PATCH 3 — tighter section padding.

   Problem: hero feels too tall and brand-story has too much breathing
   room top + bottom (Vic feedback). Prototype renders these tighter.

   Fix: reduce vertical padding so the rhythm matches Vic's review
   pass. Hero loses 30px top, 20px bottom. Brand-story loses 18px top
   and 22px bottom. Other sections' rhythm stays intact. */
#about-hero {
  padding: 90px 24px 50px;
}
#brand-story {
  padding: 46px 0 48px;
}


/* PATCH 4 — tc-slide hover outline gap.

   Problem: v0.21.2 added `outline-offset: 2px` so the orange ring
   sat 2px outside the slide edge. That 2px gap revealed the section
   bg (white) between the slide and the outline — Vic noted "white
   gap before the outline".

   Fix: outline-offset 0 puts the orange ring flush against the
   slide edge, no gap. Visual weight is unchanged otherwise. */
.tc-slide:hover {
  outline-offset: 0;
}


/* ═══════════════════════════════════════════════════════════════════
   v0.21.4/0.21.5 — Font token override (Vic feedback rounds 4-5)
   --------------------------------------------------------------------
   Root cause for "all titles look wrong / not NHG Black":

   page-about.css contains THREE prototype-extracted :root / scoped
   blocks that locally redeclare font tokens. None of these font NAMES
   match what the theme's design-system.css @font-face's load. Result:
   no NHG webfont request fires (verified via DevTools Network tab in
   v0.21.4 — only DM Sans was loaded), and titles silently fall through
   to Inter → system-ui → sans-serif rendering.

   The three offending overrides:

     line 1124-1125 (VMV scope):
       --font-display: 'Neue Haas Grotesk Display Pro', 'Inter', ...
       --font-body:    'Inter', -apple-system, ...

     line 1661-1663 (brand-story scope):
       --font-title:   'Neue Haas Grotesk Display', 'Inter Tight', ...
       --font-body:    'Inter', system-ui, ...
       --font-jp:      'Noto Serif JP', ...

     line 2217-2218 (KP scope):
       --font-display: "Neue Haas Grotesk Display Pro", "Helvetica Neue", ...
       --font-body:    "Inter", system-ui, ...

   The font NAMES 'Neue Haas Grotesk Display' and 'Neue Haas Grotesk
   Display Pro' exist only as locally-installed fonts on Vic's Mac
   (where the prototype was authored). The theme @font-face's load
   the same files under the names 'NHG' and 'NeueHaasGrotesk'. None
   of the prototype's overridden chains include 'NHG' or
   'NeueHaasGrotesk', so the browser never even tries to load them.

   Fix: alias all three tokens back to the theme's design-system
   tokens at :root. Since cascade order puts this AFTER all three
   prototype overrides, it wins. */
:root {
  --font-title:   'NHG', 'NeueHaasGrotesk', 'Helvetica Neue', 'Arial Black', 'Arial', 'Noto Sans JP', sans-serif;
  --font-display: 'NHG', 'NeueHaasGrotesk', 'Helvetica Neue', 'Arial Black', 'Arial', 'Noto Sans JP', sans-serif;
  --font-body:    'DM Sans', 'Inter', 'Noto Sans JP', system-ui, -apple-system, sans-serif;
}

/* Belt-and-braces: redeclare on the modules where the prototype
   originally re-scoped the token, so any cascaded variable lookup
   from a child element also resolves to the theme's NHG chain. */
.cards,
.card,
.kp-section,
.kp-stage,
.kp-card,
.kp-lightbox,
.vertwo-branding,
#brand-story,
#brand-story * {
  --font-title:   'NHG', 'NeueHaasGrotesk', 'Helvetica Neue', 'Arial Black', 'Arial', sans-serif;
  --font-display: 'NHG', 'NeueHaasGrotesk', 'Helvetica Neue', 'Arial Black', 'Arial', sans-serif;
  --font-body:    'DM Sans', 'Inter', system-ui, -apple-system, sans-serif;
}


/* PATCH 6 — additional brand-story upper gap reduction.

   v0.21.3 trimmed brand-story padding 64/70 → 46/48. v0.21.4 trimmed
   to 24/40. v0.21.6 trims to 8/32. v0.21.12 trims further: 0/24.
   Vic round 11 still flags top gap; pull the title essentially
   flush against the section top. */
#brand-story {
  padding: 0 0 24px;
}


/* PATCH 11 (v0.21.15) — horizontal separator: VERBATIM port from
   04-works.html lines 6300-6320 (the "[3] Hairline separators
   (3/4 width, centered) at the boundaries: portfolio→clients
   and clients→testimonials" rule that Vic referenced).

   The works prototype implements section boundary lines as
   pseudo-elements (::before, position:absolute, top:0) on the
   SECOND section of each pair. Specs (verbatim):

     width: 75%
     max-width: 1100px
     height: 1px
     background: rgba(26, 26, 26, 0.10)
     centered via left:50% + translateX(-50%)
     pointer-events: none
     z-index: 1
     parent gets position: relative

   Apply same style to the boundary between #key-persons and
   #team-culture on the About page (since that's the only
   currently-flagged about-page boundary). The line sits at
   the top of #team-culture, centered, ~75% of viewport width
   capped at 1100px. */
#team-culture {
  border-top: none;
  position: relative;
}
#team-culture::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 75%;
  max-width: 1100px;
  height: 1px;
  background: rgba(26, 26, 26, 0.10);
  pointer-events: none;
  z-index: 1;
}


/* PATCH 12 (v0.21.19) — uniform section padding across the About page.

   Vic round 17: "use the uniform sizing like in the Homepage,
   make them all uniform". Going from per-section bespoke values
   (v0.21.15) to a single uniform 80px top/bottom on every section.

   Reference: the homepage's news section uses .vertwo-news with
   `padding: clamp(56px, 6vw, 80px) clamp(20px, 4vw, 64px)` —
   80px is the desktop ceiling. Apply this same value uniformly
   to every About-page section so the rhythm matches the news
   section's clean repeated cadence.

   #about-hero is excluded — heroes are special (have parallax,
   centered content, etc.) and use prototype values verbatim.

   For #brand-story specifically: outer wrapper has padding 0 0 80
   (no extra top — the visual top padding is supplied by the
   inner .vertwo-branding section). Inner .vertwo-branding gets
   padding-top: 80px to match every other section's top rhythm. */
#about-intro,
#about-stats,
#vmv,
#team-culture,
#milestones {
  padding-top: 80px;
  padding-bottom: 80px;
}

/* Re-apply original horizontal padding (which the simple top/bottom
   rule above clobbered for sections that had non-24px sides). */
#about-intro    { padding-left: 24px; padding-right: 24px; }
#about-stats    { padding-left: 24px; padding-right: 24px; }
#vmv            { padding-left: 24px; padding-right: 24px; }
#team-culture   { padding-left: 0;    padding-right: 0;    }
#milestones     { padding-left: 22px; padding-right: 22px; }

/* v0.22.8 — Tighten the boundary between #about-intro and #about-stats
   specifically. Both sections share a white background; the visitor
   reads them as one continuous block, so the doubled 80px+80px = 160px
   gap between the intro paragraph and the stats grid felt like dead
   space (Vic feedback: "stats gap still there, on all versions" — his
   red ellipse circled the empty band between the prose and the cards).
   Reduce intro's bottom-pad to 32 and stats' top-pad to 32 for a total
   64px breathing room. Other adjacent boundaries (vmv→brand-story,
   team-culture→milestones, etc.) keep the full 80px because they cross
   bg-color changes that earn the larger rhythm. */
#about-intro { padding-bottom: 32px; }
#about-stats { padding-top: 32px; }

/* Brand-story: outer has no top padding; inner section provides it. */
#brand-story {
  padding: 0 0 80px;
}
#brand-story .vertwo-branding {
  /* v0.21.19: align brand-story's title-top breathing room with
     the rest of the page (uniform 80px). Was clamp(56px, 7vw, 104px)
     in the prototype which produced the giant gap Vic flagged in
     round 14, and was 40px in v0.21.18 which Vic flagged as too
     tight in round 16. 80px is the uniform value. */
  padding-top: 80px;
}


/* PATCH 7 — match homepage stats responsive treatment.

   Vic feedback round 5: stats cards on About should mirror the
   homepage stats responsive behavior verbatim, not have their own
   tablet 2x2 / mobile gap rules.

   Theme's intro-stats.css (loaded on both home + about) already has:
     @media (max-width: 860px) { .vw-grid: 2-col, gap: 10px }
     @media (max-width: 420px) { .vw-grid: gap: 8px }

   The page-about.css overrides at lines 322 and 332 (`#about-stats
   .vw-grid` at <=1100px and <=600px) PRE-EMPT the homepage rules.
   Override them back to the homepage default by re-applying
   `unset` on the constraint. Specificity of `#about-stats .vw-grid`
   (1,0,1,0) is what we need to beat with same specificity from
   later in cascade. */
@media (max-width: 1100px) {
  #about-stats .vw-grid {
    /* Defer to intro-stats.css default (4-col until 860px). */
    grid-template-columns: repeat(4, 1fr);
    max-width: 1280px;
    gap: clamp(10px, 1.2vw, 16px);
  }
  #about-stats .vw-card {
    min-height: auto;
  }
}
@media (max-width: 860px) {
  #about-stats .vw-grid {
    /* Match intro-stats.css's 860px breakpoint (2-col, 10px gap). */
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
  }
}
@media (max-width: 420px) {
  #about-stats .vw-grid {
    gap: 8px;
  }
}


/* PATCH 8 — VMV cards stack vertically below 1280px (v0.21.7 bump
   from 1100px so mid-tablet/laptop viewports also stack instead of
   shrinking). All three cards locked to portrait 320:540 aspect
   ratio at every viewport ≥ 430px (narrow-phone escape hatch
   below 430px keeps content-driven height).

   Vic feedback round 6: "maintain all cards' ratio on all responsive
   sizing" — the values card was rendering landscape (700:360) on
   tablet because the prototype's @media (max-width: 960px) rule
   forced grid-column:span 2 + landscape aspect. Plus body fonts
   inside the stacked cards were using vw-clamp scaling from the
   tablet 3-col rules, making them feel small. Both fixed below.

   Specificity: #vmv .cards (1,0,1,0) beats the prototype's inner-
   scoped .cards (0,0,1,0) cleanly. */
@media (max-width: 960px) {
  /* Lock body fonts to desktop sizes when stacking at portrait
     tablet / phone — no vw-clamp scaling. This overrides the
     prototype tablet rules' clamp() font-sizes that made body
     text feel cramped at narrower card widths. */
  #vmv .card__title { font-size: 46px; line-height: 0.88; margin-bottom: 16px; }
  #vmv .values-head .card__title { font-size: 44px; margin-bottom: 4px; }
  #vmv .card__text { font-size: 15.5px; line-height: 1.55; }
  #vmv .card__eyebrow { font-size: 11.5px; margin-bottom: 14px; }
  #vmv .card__eyebrow::before { width: 24px; }

  #vmv .bullet { font-size: 14.5px; line-height: 1.45; }
  #vmv .bullet svg { width: 16px; height: 16px; margin-top: 2px; }
  #vmv .bullets { gap: 12px; }

  #vmv .value-name { font-size: 15.5px; line-height: 1.15; }
  #vmv .value-desc { font-size: 12.5px; line-height: 1.3; }
  #vmv .value-divider { margin: 4px 0; }
  #vmv .value-badge {
    width: 48px; height: 48px;
    font-size: 24px;
    margin-right: -10px;
  }
  #vmv .value-pill {
    padding: 14px 20px 14px 32px;
  }
}


/* PATCH 10 (v0.21.11) — values card content scaling at intermediate
   desktop widths.

   Round 10 feedback: at viewport ~1094px (Vic's landscape tablet),
   the 3-col desktop layout fits each card at ~330px wide. With
   aspect-ratio 320:540, card height = 557px. The 6 V-E-R-T-W-O
   rows + header at desktop sizing total ~620px → "O" (Outstanding)
   row clips.

   Vic doesn't want stacking on landscape tablet (he wants desktop
   3-col) AND doesn't want different card heights. So the solution
   is to shrink the values card's content slightly at this
   intermediate range so all 6 rows fit within the 320:540 ratio.
   Vision/Mission cards have plenty of room (1 paragraph or 3
   bullets) so they're untouched.

   The squeeze is ~15-20% on vertical metrics. Visual: pills become
   a bit more compact, but readability is preserved. */
@media (min-width: 961px) and (max-width: 1280px) {
  #vmv .card--values .values-head { margin-bottom: clamp(6px, 0.7vw, 10px); }
  #vmv .card--values .values-list {
    gap: clamp(5px, 0.6vw, 8px);
    padding: clamp(2px, 0.3vw, 4px) clamp(10px, 1.4vw, 16px) clamp(8px, 1.1vw, 14px);
  }
  #vmv .card--values .value-pill {
    padding: clamp(8px, 1vw, 12px) clamp(12px, 1.6vw, 18px) clamp(8px, 1vw, 12px) clamp(20px, 2.5vw, 28px);
    min-height: clamp(46px, 5.4vw, 60px);
  }
  #vmv .card--values .value-badge {
    width: clamp(34px, 3.8vw, 44px);
    height: clamp(34px, 3.8vw, 44px);
    font-size: clamp(16px, 1.8vw, 22px);
  }
  #vmv .card--values .value-name {
    font-size: clamp(11.5px, 1.3vw, 14.5px);
    line-height: 1.15;
  }
  #vmv .card--values .value-desc {
    font-size: clamp(9.5px, 1.05vw, 12px);
    line-height: 1.25;
  }
  #vmv .card--values .value-divider {
    margin: clamp(2px, 0.25vw, 3px) 0;
  }
}

/* Below 430px (narrow phone) — escape hatch for the values card,
   since the 6-row VERTW O list at desktop sizes is taller than
   the 320:540 ratio at small widths. Drop the strict ratio so
   content drives height; vision/mission keep portrait. */
@media (max-width: 430px) {
  #vmv .card--values {
    aspect-ratio: auto;
  }
  #vmv .card--values .card__inner {
    height: auto;
  }
}


/* PATCH 9 (v0.21.9) — stack only at portrait-tablet and below.

   Round 7 + 8 feedback consolidation:
     - Round 7 (v0.21.7): stack at 1280px → fonts cramped, dimensions
       inconsistent at certain widths
     - Round 8 (v0.21.8): forced equal dimensions at 1280px → values
       card content overflowed the locked 810px height because the
       6-row VERTW O list with desktop pill sizing needs more vertical
       space than 320:540 ratio gives
     - Round 8 part 2: Vic flag: "landscape tablet sizing, i prefer
       same layout like desktop" → keep 3-col on laptops/landscape
       tablets, only stack on portrait tablet / phone

   Final answer: pull the stack breakpoint back to 960px. Above
   960px (laptops, landscape tablets, desktops) the cards render
   3-col at desktop default. Below 960px (portrait tablet, phone)
   they stack 1-col with locked dimensions and desktop fonts.

   This matches the prototype's own breakpoint (lines 1556-1571
   show the prototype's 2-col at 960px, 1-col at 620px). The
   values card landscape override at the prototype's <=960px
   media is overridden by my higher-specificity #vmv .card--values
   rules. */

/* Below 960px: copy mobile (≤640px) settings VERBATIM up to 960px.
   Vic round 9: "copy the exact settings from mobile to the portrait
   tablet". The existing mobile rule at @media (max-width: 640px)
   (line 427) renders correctly. The 641-960px escape hatch removed
   aspect-ratio (making values card content-driven), causing the
   "squeezed/stretched" behavior. Replace that escape hatch with
   the mobile settings so portrait tablet gets the same locked
   320:540 cards at 380px max-width that mobile already gets. */
@media (min-width: 431px) and (max-width: 960px) {
  /* Container: same as mobile @640px */
  #vmv .cards {
    grid-template-columns: 1fr !important;
    max-width: 380px !important;
    margin: 0 auto !important;
    gap: 24px !important;
    align-items: start !important;
  }

  /* All three cards locked to the same dimensions. The values card
     specifically needs aspect-ratio:320/540 with !important to win
     over the prototype's 641-960px escape hatch (line 461) which
     sets aspect-ratio:auto. */
  #vmv .card,
  #vmv .card--vision,
  #vmv .card--mission,
  #vmv .card--values {
    width: 100% !important;
    grid-column: auto !important;
    aspect-ratio: 320 / 540 !important;
  }
  #vmv .card--values .card__inner {
    /* Override line 462's height:auto so the inner respects the
       outer card's locked aspect ratio. */
    height: 100% !important;
  }

  /* Values list inner — same padding/gap as mobile. */
  #vmv .card--values .values-list {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    padding: 4px 18px 22px !important;
    gap: 10px !important;
  }
  #vmv .card--values .value-row {
    width: 100% !important;
  }
}
