/* ==========================================================================
   The Vasi Verse — Design System
   Locked tokens per docs/01_BRAND (Colors, Typography, Motion) and
   docs/00_PROJECT_BRIEF/Design_Principles.md. Do not introduce new colors,
   fonts, or motion curves without updating the source documents first.
   ========================================================================== */

/* -------------------------------------------------------------------------
   Fonts
   ------------------------------------------------------------------------- */
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&family=Inter:wght@400;500;600;700&display=swap');

/* -------------------------------------------------------------------------
   Tokens
   ------------------------------------------------------------------------- */
:root {
  /* Color */
  --color-bg: #080B12;
  --color-surface: #111827;
  --color-elevated: #1A2233;
  --color-text-primary: #F8FAFC;
  --color-text-secondary: #94A3B8;
  --color-accent: #4A7BA7;
  --color-accent-hover: #6B98C4;
  --color-border: rgba(255, 255, 255, 0.08);
  --color-border-strong: rgba(255, 255, 255, 0.16);
  --color-success: #22C55E;
  --color-warning: #F59E0B;
  --color-error: #EF4444;
  --color-info: #3B82F6;

  /* Accent — restrained light-blue system layered on top of the base palette.
     Used for eyebrows, stat/status surfaces, borders and focus states.
     --accent-blue-strong is a separately-calibrated tone for the primary
     button: it's dark enough to hold WCAG AA contrast under white text,
     which --accent-blue itself (#7FB3FF) is too light to do. */
  --accent-blue: #7FB3FF;
  --accent-blue-soft: #A8CBFF;
  --accent-blue-bg: rgba(127, 179, 255, 0.10);
  --accent-blue-border: rgba(127, 179, 255, 0.28);
  --accent-blue-strong: #2B63D9;
  --accent-blue-strong-hover: #2E68DE;

  /* Shadows — always blue-tinted, never pure black */
  --shadow-sm: 0 8px 24px rgba(0, 0, 0, 0.18);
  --shadow-md: 0 16px 48px rgba(0, 0, 0, 0.24);
  --shadow-lg: 0 24px 64px rgba(0, 0, 0, 0.30);
  --shadow-glow: 0 0 0 1px var(--accent-blue-border);

  /* Type */
  --font-display: 'Geist', 'Inter', -apple-system, sans-serif;
  --font-body: 'Inter', -apple-system, sans-serif;
  --font-mono: 'Geist Mono', 'SFMono-Regular', monospace;

  /* Layout — single fluid inline padding so nav, hero, cards and footer
     always share the same left/right grid line at any viewport width. */
  --content-max: 1200px;
  --page-margin: clamp(24px, 6vw, 120px);
  --radius-sm: 12px;
  --radius-md: 16px;
  --radius-lg: 24px;
  --radius-xl: 28px;

  /* Motion */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --dur-micro: 250ms;
  --dur-card: 450ms;
  --dur-page: 700ms;
  --dur-hero: 900ms;
  --dur-scroll: 600ms;
}

/* -------------------------------------------------------------------------
   Reset
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-weight: 400;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }

a { color: inherit; text-decoration: none; }

button { font-family: inherit; cursor: pointer; }

ul, ol { margin: 0; padding: 0; list-style: none; }

h1, h2, h3, h4, p { margin: 0; overflow-wrap: break-word; }

/* Background atmosphere — subtle accent-blue glow behind the hero, near invisible */
body {
  background-image: radial-gradient(circle at 85% 0%, rgba(127, 179, 255, 0.04), transparent 55%);
  background-repeat: no-repeat;
}

/* -------------------------------------------------------------------------
   Typography scale
   ------------------------------------------------------------------------- */
.display-xl {
  font-family: var(--font-display);
  font-size: clamp(40px, 6vw, 72px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.display-lg {
  font-family: var(--font-display);
  font-size: clamp(32px, 5vw, 56px);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.heading-1 {
  font-family: var(--font-display);
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 700;
  line-height: 1.2;
}

.heading-2 {
  font-family: var(--font-display);
  font-size: clamp(24px, 3vw, 32px);
  font-weight: 600;
  line-height: 1.25;
}

.heading-3 {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  line-height: 1.3;
}

.body-lg {
  font-size: 20px;
  font-weight: 400;
  line-height: 1.7;
  max-width: 620px;
  color: var(--color-text-secondary);
}

.body-base {
  font-size: 18px;
  font-weight: 400;
  line-height: 1.7;
  max-width: 680px;
  color: var(--color-text-secondary);
}

.body-small {
  font-size: 16px;
  font-weight: 400;
  line-height: 1.65;
  color: var(--color-text-secondary);
}

.caption {
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--color-text-secondary);
}

.micro-label {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-blue);
}

.mono { font-family: var(--font-mono); }

/* -------------------------------------------------------------------------
   Layout
   ------------------------------------------------------------------------- */
.container {
  max-width: var(--content-max);
  margin: 0 auto;
  padding-inline: var(--page-margin);
}

.section {
  padding-top: 140px;
}

@media (max-width: 1024px) {
  .section { padding-top: 96px; }
}

@media (max-width: 640px) {
  .section { padding-top: 72px; }
}

/* -------------------------------------------------------------------------
   Navigation
   ------------------------------------------------------------------------- */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: 72px;
  display: flex;
  align-items: center;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background var(--dur-micro) var(--ease-standard),
              border-color var(--dur-micro) var(--ease-standard),
              backdrop-filter var(--dur-micro) var(--ease-standard);
}

.nav.is-scrolled {
  background: rgba(8, 11, 18, 0.72);
  border-bottom: 1px solid var(--color-border);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

/* Same box model as .container (max-width, then padding-inline applied
   inside it) so the logo lands on the exact same grid line as hero/card
   content below it. Padding lives here rather than on .nav so the
   translucent scrolled background can still bleed full-width. */
.nav-inner {
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding-inline: var(--page-margin);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.nav-logo {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--color-text-primary);
  transition: color var(--dur-micro) var(--ease-standard);
}

.nav-logo:hover { color: var(--accent-blue); }

/* Brand mark — identity, not navigation. Plain text (no href, no button
   role), so no hover-lift/magnetic/cursor-trail behavior can ever attach to
   it; the only feedback on hover is a slightly brighter border. */
.brand-mark {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-primary);
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent-blue-border);
  background: var(--accent-blue-bg);
  cursor: default;
  user-select: none;
  transition: border-color var(--dur-micro) var(--ease-standard);
}

.brand-mark:hover { border-color: var(--accent-blue); }

.nav-links {
  display: flex;
  align-items: center;
  gap: 36px;
}

.nav-link {
  position: relative;
  font-size: 15px;
  font-weight: 500;
  color: var(--color-text-secondary);
  padding-bottom: 4px;
  transition: color var(--dur-micro) var(--ease-standard),
              opacity var(--dur-micro) var(--ease-standard),
              transform var(--dur-micro) var(--ease-standard);
}

.nav-link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--accent-blue);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-micro) var(--ease-standard);
}

.nav-link:hover { color: var(--color-text-primary); transform: translateY(-1px); }
.nav-link:hover::after { transform: scaleX(1); }

.nav-link.is-active { color: var(--color-text-primary); }
.nav-link.is-active::after {
  transform: scaleX(1);
  height: 2px;
  box-shadow: 0 0 8px 0 var(--accent-blue-border);
}

/* Spotlight hover — desktop only. Hovering the nav dims every link except
   the one under the cursor, which lifts slightly and picks up the accent. */
@media (min-width: 769px) {
  .nav-links:hover .nav-link { opacity: 0.45; }
  .nav-links:hover .nav-link:hover {
    opacity: 1;
    transform: scale(1.06);
    color: var(--accent-blue-soft);
  }
}

.nav-toggle {
  display: none;
  position: relative;
  z-index: 101;
  background: none;
  border: none;
  color: var(--color-text-primary);
  padding: 8px;
}

.nav-toggle svg { width: 24px; height: 24px; overflow: visible; }

.nav-toggle .nav-toggle-line {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform var(--dur-micro) var(--ease-standard),
              opacity var(--dur-micro) var(--ease-standard);
}

/* Hamburger morphs into a close (×) mark when the panel is open */
.nav-toggle[aria-expanded="true"] .nav-toggle-line-top { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-line-mid { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-line-bottom { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 768px) {
  .nav-links {
    position: fixed;
    top: 72px;
    left: 0;
    right: 0;
    bottom: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
    padding: 32px var(--page-margin) 40px;
    background: rgba(8, 11, 18, 0.97);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--color-border);
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-card) var(--ease-standard),
                transform var(--dur-card) var(--ease-standard);
  }

  .nav-links.is-open {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }

  /* Spotlight is a desktop-only affordance; mobile links stay at full opacity */
  .nav-links:hover .nav-link,
  .nav-links .nav-link:hover {
    opacity: 1;
    transform: none;
  }

  .nav-toggle { display: block; }
}

/* -------------------------------------------------------------------------
   Buttons
   ------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 52px;
  padding: 0 28px;
  border-radius: 14px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
  transition: background var(--dur-micro) var(--ease-standard),
              color var(--dur-micro) var(--ease-standard),
              border-color var(--dur-micro) var(--ease-standard),
              transform var(--dur-micro) var(--ease-standard);
}

.btn-primary {
  background: var(--accent-blue-strong);
  color: #ffffff;
}

.btn-primary:hover {
  background: var(--accent-blue-strong-hover);
  transform: translateY(-2px);
  box-shadow: 0 12px 28px rgba(43, 99, 217, 0.35);
}

.btn-ghost {
  background: transparent;
  border-color: var(--accent-blue-border);
  color: var(--accent-blue-soft);
}

.btn-ghost:hover {
  border-color: var(--accent-blue);
  color: var(--accent-blue);
  background: var(--accent-blue-bg);
  transform: translateY(-2px);
}

.btn-link {
  height: auto;
  padding: 0;
  border-radius: 0;
  color: var(--accent-blue-soft);
  font-size: 16px;
  gap: 6px;
}

.btn-link:hover { color: var(--color-text-primary); }

.btn-link .arrow {
  display: inline-block;
  transition: transform var(--dur-micro) var(--ease-standard);
}

.btn-link:hover .arrow { transform: translateX(4px); }

/* -------------------------------------------------------------------------
   Metadata panel (Product Overview)
   ------------------------------------------------------------------------- */
.meta-panel {
  background: var(--accent-blue-bg);
  border: 1px solid var(--accent-blue-border);
  border-radius: var(--radius-lg);
  padding: 40px;
}

/* Photo slot (Product Overview) — square, ~260px on desktop, scales down
   with the panel on smaller screens. Reuses existing surface/border tokens
   so an empty slot (no photo yet) still reads as intentional, not broken.
   The <img> removes itself on error, leaving just this styled square. */
.meta-photo {
  width: 100%;
  max-width: 260px;
  aspect-ratio: 1 / 1;
  margin: 0 auto 28px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-elevated);
  border: 1px solid var(--color-border);
}

.meta-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.meta-row {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  padding: 16px 0;
  border-bottom: 1px solid var(--color-border);
}

.meta-row:last-child { border-bottom: none; padding-bottom: 0; }
.meta-row:first-child { padding-top: 0; }

.meta-label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
  flex-shrink: 0;
}

.meta-value {
  font-size: 16px;
  color: var(--color-text-primary);
  text-align: right;
  min-width: 0;
  overflow-wrap: break-word;
}

.status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-success);
  margin-right: 8px;
}

/* -------------------------------------------------------------------------
   Status chips + pills
   ------------------------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 100px;
  background: var(--accent-blue-bg);
  border: 1px solid var(--accent-blue-border);
  color: var(--accent-blue-soft);
}

/* Success/warning keep their own semantic hue — status meaning (Completed vs.
   In Progress) is carried by color, so it stays distinct from the accent system. */
.chip-success { color: var(--color-success); background: rgba(34, 197, 94, 0.08); border-color: rgba(34, 197, 94, 0.3); }
.chip-warning { color: var(--color-warning); background: rgba(245, 158, 11, 0.08); border-color: rgba(245, 158, 11, 0.3); }
.chip-accent { color: var(--accent-blue-soft); background: var(--accent-blue-bg); border-color: var(--accent-blue-border); }

.pill {
  display: inline-flex;
  align-items: center;
  font-size: 14px;
  color: var(--color-text-secondary);
  padding: 8px 16px;
  border-radius: 100px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}

.pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

/* -------------------------------------------------------------------------
   Cards — shared product/case-study/playground card system
   ------------------------------------------------------------------------- */
.card {
  position: relative;
  overflow: hidden;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: transform var(--dur-card) var(--ease-standard),
              border-color var(--dur-card) var(--ease-standard),
              box-shadow var(--dur-card) var(--ease-standard),
              background var(--dur-card) var(--ease-standard),
              opacity var(--dur-card) var(--ease-standard),
              filter var(--dur-card) var(--ease-standard);
}

/* :not(.flip-card-front):not(.flip-card-back) throughout this rule keeps it
   from fighting the flip system's own transform on cards used as a flip
   face (Home gateway cards, Case Studies) — see the Flip cards section. */
.card:not(.flip-card-front):not(.flip-card-back):hover,
.card:not(.flip-card-front):not(.flip-card-back):focus-visible {
  transform: translateY(-6px) scale(1.02);
  border-color: var(--accent-blue-border);
  background: var(--color-elevated);
  box-shadow: var(--shadow-lg), var(--shadow-glow);
}

/* Tap press feedback — the only motion feedback touch devices get, since
   they have no hover. Quick and gentle, distinct from the desktop lift. */
.card:not(.flip-card-front):not(.flip-card-back):active {
  transform: translateY(-2px) scale(0.99);
  transition-duration: var(--dur-micro);
}

/* Shine sweep — a single soft diagonal highlight passes over the card on
   hover/tap. Only used on cards that aren't flip faces — flip cards already
   have their own physical motion. */
.card:not(.flip-card-front):not(.flip-card-back)::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 42%, rgba(127, 179, 255, 0.12) 50%, transparent 58%);
  transform: translateX(-120%);
  pointer-events: none;
  transition: transform var(--dur-card) var(--ease-standard);
}

.card:not(.flip-card-front):not(.flip-card-back):hover::after,
.card:not(.flip-card-front):not(.flip-card-back):active::after {
  transform: translateX(120%);
}

/* Spotlight — hovering the group dims every card except the one under the
   cursor. .flip-card is included since flip cards are the grid's direct
   child now (the .card styling lives one level deeper, on each face). */
.card-grid:hover > .card,
.card-grid:hover > .flip-card,
.small-card-grid:hover > .card,
.small-card-grid:hover > .flip-card {
  opacity: 0.5;
  filter: saturate(0.85);
}

.card-grid:hover > .card:hover,
.card-grid:hover > .flip-card:hover,
.small-card-grid:hover > .card:hover,
.small-card-grid:hover > .flip-card:hover {
  opacity: 1;
  filter: none;
}

.card-media {
  overflow: hidden;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: var(--color-elevated);
}

.card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-card) var(--ease-standard),
              filter var(--dur-card) var(--ease-standard);
}

.card:hover .card-media img {
  transform: scale(1.02);
  filter: brightness(1.05);
}

.card-body {
  padding: 28px 32px 32px;
}

.card-arrow {
  display: inline-block;
  transition: transform var(--dur-micro) var(--ease-standard);
}

.card:hover .card-arrow { transform: translateX(4px); }

/* Home / grid cards */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px;
}

@media (max-width: 1024px) {
  .card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .card-grid { grid-template-columns: 1fr; }
}

.gateway-card {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.gateway-card .card-media { aspect-ratio: 4 / 3; }
.gateway-card .card-body { display: flex; flex-direction: column; gap: 14px; flex: 1; }

/* Whole-card click-through (Builds rows, Case Studies cards) — the actual
   navigation is handled in js/main.js via [data-card-href]; this just
   signals the whole card is clickable, not only its CTA. */
[data-card-href] { cursor: pointer; }

/* Alternating editorial rows (Builds / Case Studies). Each row wraps a
   single .flip-card — the whole thing (logo included) physically turns, so
   the row itself is just padding/border; the 2-column media|content grid
   lives on .flip-card-front (see .flip-card--row below), and .flip-card
   owns the hover lift so the row no longer sets its own transform. */
.editorial-row {
  padding: 96px 40px;
  border-bottom: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  transition: opacity var(--dur-card) var(--ease-standard),
              filter var(--dur-card) var(--ease-standard);
}

.editorial-row:last-child { border-bottom: none; }

/* Spotlight — hovering the list dims every build except the one under the cursor */
.builds-list:hover > .editorial-row { opacity: 0.5; filter: saturate(0.85); }
.builds-list:hover > .editorial-row:hover { opacity: 1; filter: none; }

.editorial-media {
  border-radius: var(--radius-xl);
  overflow: hidden;
  border: 1px solid var(--color-border);
  background: var(--color-elevated);
  aspect-ratio: 4 / 3;
  transition: border-color var(--dur-card) var(--ease-standard);
}

.editorial-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-card) var(--ease-standard),
              filter var(--dur-card) var(--ease-standard);
}

/* Logo lockup variant — the three Builds logos have wildly different native
   aspect ratios (wide/square/tiny), so they sit contained on the same dark
   surface as the other media boxes instead of being cropped/stretched to
   fill the frame. StudioAI.png and DotRyder.png have their own baked-in
   white background (not something CSS can strip), so those two will still
   show a light rectangle — GrowthAlpha.png is transparent and blends in. */
.editorial-media.is-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 56px;
}

.editorial-media.is-logo img {
  width: auto;
  height: auto;
  max-width: 70%;
  max-height: 70%;
  object-fit: contain;
}

.editorial-row:hover .editorial-media { border-color: var(--accent-blue-border); }
.editorial-row:hover .editorial-media img { transform: scale(1.02); filter: brightness(1.05); }

.editorial-content { display: flex; flex-direction: column; gap: 20px; min-width: 0; }

/* The Builds row's flip front holds the media + content side by side —
   this is where the row's old 2-column grid moved to, now that the row
   itself wraps a single .flip-card. The back reuses .editorial-content's
   own flex-column layout at full row width (no media there to pair with). */
.flip-card--row .flip-card-front {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 64px;
  align-items: center;
}

.editorial-row.is-reversed .flip-card-front .editorial-media { order: 2; }
.editorial-row.is-reversed .flip-card-front .editorial-content { order: 1; }

.meta-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 32px;
}

.meta-grid-item { display: flex; flex-direction: column; gap: 4px; }

.editorial-ctas { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 8px; }

@media (max-width: 900px) {
  .editorial-row { padding: 64px 24px; }
  .flip-card--row .flip-card-front { grid-template-columns: 1fr; gap: 32px; }
  .editorial-row.is-reversed .flip-card-front .editorial-media { order: 1; }
  .editorial-row.is-reversed .flip-card-front .editorial-content { order: 2; }
}

/* Small grid cards (Case Studies grid, Playground cards, Connect cards) */
.small-card-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32px;
}

@media (max-width: 768px) {
  .small-card-grid { grid-template-columns: 1fr; }
}

.small-card {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.small-card .card-media { aspect-ratio: 16 / 10; }
.small-card .card-body { display: flex; flex-direction: column; gap: 14px; flex: 1; }

/* -------------------------------------------------------------------------
   Flip cards — the 3D card turn (Builds content pane, Playground timeline
   card). Front/back are stacked in the same CSS Grid cell so the container
   height always matches the taller face, with no JS measurement needed.
   Desktop: hover or keyboard focus turns the card. Touch: the .flip-trigger
   button (always present, works for mouse/keyboard/touch alike) toggles a
   persistent .is-flipped class via js/main.js.
   ------------------------------------------------------------------------- */
.flip-card {
  perspective: 2000px;
  transition: transform var(--dur-hero) var(--ease-out);
}

/* Builds rows are much wider than the compact cards elsewhere, so a larger
   perspective keeps the turn from skewing too sharply at the edges. */
.flip-card--row {
  perspective: 3400px;
}

.flip-card:hover,
.flip-card:focus-within,
.flip-card.is-flipped {
  transform: translateY(-3px);
}

.flip-card-inner {
  position: relative;
  display: grid;
  transform-style: preserve-3d;
  transition: transform var(--dur-hero) var(--ease-out);
}

.flip-card:hover .flip-card-inner,
.flip-card:focus-within .flip-card-inner,
.flip-card.is-flipped .flip-card-inner {
  transform: rotateY(180deg);
}

.flip-card-front,
.flip-card-back {
  grid-area: 1 / 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.flip-card-back {
  transform: rotateY(180deg);
}

/* Faces reuse .editorial-content / .timeline-card / .card for their existing
   visual styling (padding, background, borders). Each of those components'
   own :hover rules is written with :not(.flip-card-front):not(.flip-card-back)
   so it never fires here — .flip-card owns the hover motion instead. This
   just fills the shared grid cell to the taller face's height. */
.flip-card-front.timeline-card,
.flip-card-back.timeline-card,
.flip-card-front.card,
.flip-card-back.card {
  cursor: default;
  height: 100%;
}

.flip-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-top: 4px;
  border-radius: 50%;
  border: 1px solid var(--accent-blue-border);
  background: var(--accent-blue-bg);
  color: var(--accent-blue-soft);
  font-size: 16px;
  line-height: 1;
  opacity: 0.75;
  transition: opacity var(--dur-micro) var(--ease-standard),
              background var(--dur-micro) var(--ease-standard),
              color var(--dur-micro) var(--ease-standard),
              transform var(--dur-micro) var(--ease-standard);
}

.flip-trigger:hover,
.flip-trigger:focus-visible {
  opacity: 1;
  background: var(--accent-blue-border);
  color: var(--color-text-primary);
}

.flip-trigger:active { transform: scale(0.92); }

/* Desktop already reveals the back on hover, so the trigger is a quiet
   keyboard-accessible affordance there; on touch it's the primary control. */
@media (hover: hover) and (pointer: fine) {
  .flip-trigger { opacity: 0.45; }
  .flip-trigger:hover, .flip-trigger:focus-visible { opacity: 1; }
}

/* -------------------------------------------------------------------------
   Contact cards (Connect page)
   ------------------------------------------------------------------------- */
.contact-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}

@media (max-width: 640px) {
  .contact-grid { grid-template-columns: 1fr; }
}

.contact-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 28px 32px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  cursor: pointer;
  transition: transform var(--dur-card) var(--ease-standard),
              border-color var(--dur-card) var(--ease-standard),
              background var(--dur-card) var(--ease-standard),
              box-shadow var(--dur-card) var(--ease-standard);
}

.contact-card:hover,
.contact-card:focus-visible {
  transform: translateY(-6px) scale(1.01);
  border-color: var(--accent-blue-border);
  background: var(--color-elevated);
  box-shadow: var(--shadow-lg), var(--shadow-glow);
}

.contact-card-icon {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: var(--color-elevated);
  color: var(--accent-blue);
  flex-shrink: 0;
}

.contact-card-icon svg { width: 22px; height: 22px; }

.contact-card-text { flex: 1; }

.contact-card-arrow {
  color: var(--color-text-secondary);
  transition: transform var(--dur-micro) var(--ease-standard), color var(--dur-micro) var(--ease-standard);
}

.contact-card:hover .contact-card-arrow {
  transform: translateX(4px);
  color: var(--accent-blue);
}

/* -------------------------------------------------------------------------
   Timeline (Playground)
   ------------------------------------------------------------------------- */
.timeline { position: relative; padding-left: 40px; }

.timeline::before {
  content: '';
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: var(--color-border);
}

.timeline-item {
  position: relative;
  padding-bottom: 96px;
}

.timeline-item:last-child { padding-bottom: 0; }

.timeline-item::before {
  content: '';
  position: absolute;
  left: -40px;
  top: 6px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--accent-blue);
  border: 2px solid var(--color-bg);
  box-shadow: 0 0 0 1px var(--color-border);
}

.timeline-year {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--accent-blue);
  margin-bottom: 12px;
  display: block;
}

.timeline-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 32px 36px;
  cursor: pointer;
  transition: border-color var(--dur-card) var(--ease-standard),
              background var(--dur-card) var(--ease-standard),
              transform var(--dur-card) var(--ease-standard),
              box-shadow var(--dur-card) var(--ease-standard);
}

.timeline-card:not(.flip-card-front):not(.flip-card-back):hover {
  border-color: var(--accent-blue-border);
  background: var(--color-elevated);
  transform: translateY(-6px) scale(1.01);
  box-shadow: var(--shadow-lg), var(--shadow-glow);
}

/* Spotlight — hovering the timeline dims every experiment except the one under the cursor */
.timeline:hover > .timeline-item { opacity: 0.5; filter: saturate(0.85); transition: opacity var(--dur-card) var(--ease-standard), filter var(--dur-card) var(--ease-standard); }
.timeline:hover > .timeline-item:hover { opacity: 1; filter: none; }

.timeline-header { display: flex; align-items: center; gap: 16px; margin-bottom: 12px; flex-wrap: wrap; }

.timeline-diagram {
  width: 56px;
  height: 56px;
  border-radius: 12px;
  background: var(--color-elevated);
  border: 1px solid var(--color-border);
  padding: 10px;
  flex-shrink: 0;
}

.timeline-learnings { margin-top: 20px; display: flex; flex-direction: column; gap: 10px; }

.timeline-learnings li {
  position: relative;
  padding-left: 20px;
  font-size: 15px;
  color: var(--color-text-secondary);
  line-height: 1.6;
}

.timeline-learnings li::before {
  content: '→';
  position: absolute;
  left: 0;
  color: var(--accent-blue);
}

/* -------------------------------------------------------------------------
   Checklist (Playground — What's Next)
   ------------------------------------------------------------------------- */
.checklist { display: flex; flex-direction: column; gap: 16px; max-width: 480px; }

.checklist-item {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 17px;
  color: var(--color-text-secondary);
  padding: 4px 0;
}

.checklist-box {
  width: 18px;
  height: 18px;
  border: 1px solid var(--color-border-strong);
  border-radius: 4px;
  flex-shrink: 0;
}

/* -------------------------------------------------------------------------
   Resume page
   ------------------------------------------------------------------------- */
.resume-preview-card {
  max-width: 900px;
  margin: 0 auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 48px;
  text-align: center;
}

.resume-thumb {
  width: 100%;
  max-width: 420px;
  margin: 0 auto 32px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  overflow: hidden;
  background: var(--color-elevated);
}

.resume-cta-group { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }

.quick-facts-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px 48px;
  max-width: 900px;
  margin: 0 auto;
}

@media (max-width: 640px) {
  .quick-facts-grid { grid-template-columns: 1fr; }
}

.fact-item { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }

/* -------------------------------------------------------------------------
   Contact form
   ------------------------------------------------------------------------- */
.form-group { display: flex; flex-direction: column; gap: 8px; margin-bottom: 24px; }

.form-label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
}

.form-input,
.form-textarea {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 14px 18px;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--color-text-primary);
  transition: border-color var(--dur-micro) var(--ease-standard);
}

.form-input:focus,
.form-textarea:focus {
  outline: none;
  border-color: var(--accent-blue);
}

.form-textarea { resize: vertical; min-height: 140px; }

.form-note { font-size: 14px; color: var(--color-text-secondary); margin-top: 12px; }

/* -------------------------------------------------------------------------
   Footer
   ------------------------------------------------------------------------- */
.footer {
  padding-block: 160px 64px;
  text-align: center;
}

.footer-statement {
  font-family: var(--font-display);
  font-size: clamp(28px, 4vw, 48px);
  font-weight: 700;
  max-width: 720px;
  margin: 0 auto 40px;
}

.footer-links {
  display: flex;
  justify-content: center;
  gap: 32px;
  margin-bottom: 48px;
  flex-wrap: wrap;
}

.footer-link {
  font-size: 15px;
  color: var(--color-text-secondary);
  text-underline-offset: 4px;
  text-decoration: none;
  transition: color var(--dur-micro) var(--ease-standard),
              text-decoration-color var(--dur-micro) var(--ease-standard);
}

.footer-link:hover {
  color: var(--accent-blue-soft);
  text-decoration: underline;
  text-decoration-color: var(--accent-blue-border);
}

.footer-tagline {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
  margin-bottom: 12px;
}

.footer-copyright {
  font-size: 13px;
  color: var(--color-text-secondary);
  opacity: 0.6;
}

/* -------------------------------------------------------------------------
   Scroll indicator (Home hero)
   ------------------------------------------------------------------------- */
.scroll-indicator {
  position: absolute;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 13px;
  color: var(--color-text-secondary);
  opacity: 0.6;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  animation: scroll-bob 3s ease-in-out infinite;
}

@keyframes scroll-bob {
  0%, 100% { transform: translate(-50%, 0); }
  50% { transform: translate(-50%, 6px); }
}

/* -------------------------------------------------------------------------
   404 page
   ------------------------------------------------------------------------- */
.error-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding-inline: var(--page-margin);
}

.error-code {
  font-family: var(--font-mono);
  font-size: 15px;
  letter-spacing: 0.1em;
  color: var(--accent-blue);
  margin-bottom: 24px;
}

.error-heading {
  font-family: var(--font-display);
  font-size: clamp(32px, 5vw, 56px);
  font-weight: 700;
  margin-bottom: 20px;
}

.error-copy {
  font-size: 18px;
  color: var(--color-text-secondary);
  max-width: 480px;
  margin: 0 auto 40px;
}

/* -------------------------------------------------------------------------
   Scroll reveal
   ------------------------------------------------------------------------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-scroll) var(--ease-out),
              transform var(--dur-scroll) var(--ease-out);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Stronger editorial reveal for major section headings — horizontal travel
   + a soft clip mask instead of the quiet vertical fade used everywhere
   else. Reuses .gateway-heading, the shared heading wrapper across pages. */
[data-reveal="heading"] {
  transform: translateX(-24px);
  clip-path: inset(0 0 0 8%);
  transition: opacity var(--dur-scroll) var(--ease-out),
              transform var(--dur-scroll) var(--ease-out),
              clip-path var(--dur-scroll) var(--ease-out);
}

[data-reveal="heading"].is-visible {
  transform: translateX(0);
  clip-path: inset(0 0 0 0);
}

/* Hero entrance — staggered via inline delay custom property.
   Default items fade + move up 8px. Items marked data-hero-dir="left|right"
   additionally travel horizontally and reveal from under a soft clip mask —
   used only for the headline (left) and Product Overview (right) per the
   editorial entrance sequence. */
[data-hero-item] {
  opacity: 0;
  transform: translate3d(var(--hero-x, 0), var(--hero-y, 8px), 0);
  clip-path: var(--hero-clip, inset(0 0 0 0));
}

[data-hero-item][data-hero-dir="left"] {
  --hero-x: -28px;
  --hero-y: 0px;
  --hero-clip: inset(0 0 0 10%);
}

[data-hero-item][data-hero-dir="right"] {
  --hero-x: 28px;
  --hero-y: 0px;
  --hero-clip: inset(0 10% 0 0);
}

/* Below 640px the hero stacks to a single column and --page-margin shrinks,
   so the full 28px horizontal travel can briefly exceed the available edge
   space before the stagger delay starts. Motion.md calls for ~30% less
   movement on mobile anyway — this satisfies both at once. */
@media (max-width: 640px) {
  [data-hero-item][data-hero-dir="left"] { --hero-x: -16px; --hero-clip: inset(0 0 0 6%); }
  [data-hero-item][data-hero-dir="right"] { --hero-x: 16px; --hero-clip: inset(0 6% 0 0); }
}

.hero-ready [data-hero-item] {
  animation: hero-fade-up var(--dur-hero) var(--ease-out) forwards;
  animation-delay: var(--hero-delay, 0ms);
}

@keyframes hero-fade-up {
  to { opacity: 1; transform: translate3d(0, 0, 0); clip-path: inset(0 0 0 0); }
}

/* Hero scroll-out — driven by a scroll-linked custom property (--hero-scroll,
   0 to 1) set in js/main.js via a passive, rAF-batched scroll listener. Pure
   function of scroll position, no animation/transition timing, so it never
   fights native scrolling and always tracks 1:1 with the user's gesture. */
.home-hero { --hero-scroll: 0; }

[data-hero-scroll-target] {
  transform: translateY(calc(var(--hero-scroll, 0) * -36px));
  opacity: calc(1 - (var(--hero-scroll, 0) * 0.85));
  will-change: transform, opacity;
}

/* -------------------------------------------------------------------------
   Electric cursor trail — desktop only, created lazily by js/main.js only
   when (hover: hover) and (pointer: fine) and no reduced-motion preference.
   A handful of small dots lerp toward the pointer and fade quickly.
   ------------------------------------------------------------------------- */
.cursor-trail {
  position: fixed;
  top: 0;
  left: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-blue-soft);
  box-shadow: 0 0 6px 1px rgba(127, 179, 255, 0.35);
  opacity: 0;
  pointer-events: none;
  z-index: 9999;
  transform: translate3d(-50%, -50%, 0);
  transition: opacity 250ms var(--ease-standard);
  will-change: transform, opacity;
}

/* -------------------------------------------------------------------------
   Focus states
   ------------------------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--accent-blue);
  outline-offset: 3px;
  transition: outline-offset 150ms var(--ease-standard);
}

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

  [data-reveal] { opacity: 1; transform: none; clip-path: none; }
  [data-hero-item] { opacity: 1; transform: none; clip-path: none; }
  [data-hero-scroll-target] { transform: none; opacity: 1; }
  .scroll-indicator { animation: none; }

  /* Large 3D rotation and cursor-tracking effects are motion for its own
     sake — remove them entirely rather than just speeding them up. The flip
     becomes an instant content swap (front/back) instead of a rotation. */
  .flip-card-inner { transform: none !important; }
  .flip-card:hover, .flip-card:focus-within, .flip-card.is-flipped { transform: none; }

  /* !important is required here: .flip-card-front/back.card and
     .timeline-card carry their own height:100% (specificity 0,2,0) so the
     content swap can fill the shared grid cell in normal motion — without
     !important that rule would beat this block's plain-class height:0/auto
     swap (0,1,0) and leave the back face permanently full-height (and, via
     hit-testing, blocking clicks on the front face's own controls). */
  .flip-card-front { position: static; }
  .flip-card-back { position: static; visibility: hidden !important; height: 0 !important; overflow: hidden !important; }

  .flip-card:hover .flip-card-front,
  .flip-card:focus-within .flip-card-front,
  .flip-card.is-flipped .flip-card-front {
    visibility: hidden !important;
    height: 0 !important;
    overflow: hidden !important;
  }

  .flip-card:hover .flip-card-back,
  .flip-card:focus-within .flip-card-back,
  .flip-card.is-flipped .flip-card-back {
    visibility: visible !important;
    height: auto !important;
    overflow: visible !important;
  }

  .cursor-trail { display: none !important; }
}

/* -------------------------------------------------------------------------
   Hero (shared page hero used by Builds / Case Studies / Playground / Resume / Connect)
   ------------------------------------------------------------------------- */
.page-hero {
  padding-block: 180px 80px;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 64px;
  align-items: start;
}

.page-hero-copy { display: flex; flex-direction: column; gap: 24px; min-width: 0; }

.page-hero-meta { padding-top: 8px; min-width: 0; }

.page-hero-meta .meta-panel { padding: 32px; }

@media (max-width: 900px) {
  .page-hero { grid-template-columns: 1fr; padding-block: 140px 56px; gap: 40px; }
}

/* Hero variant for pages with no metadata panel */
.page-hero.is-full { grid-template-columns: 1fr; }

/* Makes an entire card/row clickable via one CTA link, without nesting anchors.
   Add position:relative to the clickable container and .stretched-link to its CTA. */
.editorial-row, .timeline-card { position: relative; }
.stretched-link::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* Home hero */
.home-hero {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 64px;
  align-items: center;
  padding-block: 140px 80px;
  position: relative;
}

@media (max-width: 900px) {
  .home-hero { grid-template-columns: 1fr; min-height: auto; padding-block: 140px 96px; gap: 48px; }
}

.home-hero-copy { display: flex; flex-direction: column; gap: 24px; min-width: 0; }
.home-hero-identity { display: flex; flex-direction: column; gap: 4px; }
.home-hero-ctas { display: flex; gap: 16px; margin-top: 16px; flex-wrap: wrap; }

@media (max-width: 480px) {
  .home-hero-ctas { flex-direction: column; }
  .home-hero-ctas .btn { width: 100%; }
}

/* Gateway section */
.gateway-heading { text-align: left; margin-bottom: 56px; max-width: 620px; }
.gateway-heading .heading-1 { margin-bottom: 12px; }
