/* ============================================================
   Hybrid Flow — site styles
   Pale spatial environment, ink-purple type, brand accents.
   ============================================================ */

:root {
  --ink: #210438;
  --dark-purple: #510f5e;
  --purple: #611568;
  --deep-magenta: #97066b;
  --magenta: #dd0673;
  --blue: #30428f;
  --grey: #6f6a7b;
  --grey-soft: #a9a4b4;
  --bg: #f5f4f7;
  --bg-deep: #e9e7ee;
  --card: #ffffff;
  --shadow-soft: 0 14px 44px rgba(33, 4, 56, 0.10);
  --shadow-lift: 0 20px 60px rgba(33, 4, 56, 0.16);
  --font-head: "Sora", "Avenir Next", "Segoe UI", sans-serif;
  --font-body: "Inter", "Segoe UI", system-ui, sans-serif;
  --head-h: 76px;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-scroll: cubic-bezier(0.22, 0.72, 0.24, 1);
}

* { box-sizing: border-box; }

/* Author display rules must not resurrect [hidden] elements */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink);
  background:
    radial-gradient(120vmax 120vmax at 62% 30%, #ffffff 0%, var(--bg) 45%, var(--bg-deep) 100%);
  background-attachment: fixed;
  min-height: 100vh;
}

/* Home is a single-screen grid: the hero takes the available space and the
   legal footer remains in-flow at the bottom of the viewport. */
body.home-route {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  height: 100vh;
  height: 100dvh;
  min-height: 0;
}

body.home-route main { min-height: 0; }

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

::selection { background: rgba(221, 6, 115, 0.18); }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: #fff;
  padding: 10px 16px;
  border-radius: 0 0 10px 0;
  z-index: 100;
}
.skip-link:focus { left: 0; }

/* ---------- Header ---------- */

.site-head {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--head-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 clamp(20px, 4vw, 48px);
  z-index: 30;
}

.brand { display: inline-flex; align-items: center; }
.brand img { height: 38px; width: auto; }

.site-nav {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2vw, 28px);
}

.site-nav a:not(.btn) {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.01em;
  color: var(--ink);
  text-decoration: none;
  padding: 6px 2px;
  border-bottom: 2px solid transparent;
  transition: color 0.2s, border-color 0.2s;
}

.site-nav a:not(.btn):hover { color: var(--magenta); }
.site-nav a:not(.btn)[aria-current="page"] {
  color: var(--magenta);
  border-bottom-color: var(--magenta);
}

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  border: 0;
  background: transparent;
  cursor: pointer;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 7px;
  z-index: 40;
}
.nav-toggle span {
  display: block;
  width: 24px;
  height: 2.5px;
  border-radius: 2px;
  background: var(--ink);
  transition: transform 0.3s var(--ease-out), opacity 0.2s;
}
.nav-toggle[aria-expanded="true"] span:first-child { transform: translateY(4.75px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:last-child { transform: translateY(-4.75px) rotate(-45deg); }

/* ---------- Buttons ---------- */

.btn {
  display: inline-block;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 15px;
  text-decoration: none;
  border: 0;
  border-radius: 999px;
  padding: 13px 26px;
  cursor: pointer;
  transition: transform 0.25s var(--ease-out), box-shadow 0.25s, background 0.2s, color 0.2s;
}

.btn-primary {
  background: var(--magenta);
  color: #fff;
  box-shadow: 0 10px 26px rgba(221, 6, 115, 0.32);
}
.btn-primary:hover {
  background: var(--deep-magenta);
  transform: translateY(-2px);
  box-shadow: 0 14px 32px rgba(221, 6, 115, 0.38);
}

.btn-ghost {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 2px rgba(33, 4, 56, 0.22);
}
.btn-ghost:hover {
  box-shadow: inset 0 0 0 2px var(--ink);
  transform: translateY(-2px);
}

.nav-cta { padding: 10px 20px; font-size: 13.5px; }

/* ---------- Stage (3D mark) ---------- */

#stage {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

#mark-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

body:not(.route-open) #mark-canvas { pointer-events: auto; }

#mark-fallback {
  --fallback-mark-x: 71%;
  --fallback-mark-y: 49%;
  --fallback-mark-size: min(46vmin, 460px);
  position: absolute;
  inset: 0;
}

#mark-fallback:not([data-route="home"]) {
  --fallback-mark-y: 50%;
  --fallback-mark-size: min(28vmin, 276px);
}

#mark-fallback:is(
  [data-route="privacy"],
  [data-route="cookies"],
  [data-route="terms"]
) {
  --fallback-mark-size: min(26vmin, 240px);
}

#mark-fallback img {
  position: absolute;
  left: var(--fallback-mark-x);
  top: var(--fallback-mark-y);
  width: var(--fallback-mark-size);
  height: auto;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 40px 50px rgba(33, 4, 56, 0.25));
  transition:
    left 0.56s var(--ease-out),
    top 0.56s var(--ease-out),
    width 0.56s var(--ease-out);
}

@media (max-width: 1100px) {
  #mark-fallback {
    --fallback-mark-x: 50%;
    --fallback-mark-y: 29.5%;
  }

  #mark-fallback:not([data-route="home"]) {
    --fallback-mark-y: 17%;
    --fallback-mark-size: min(32vmin, 320px);
  }

  #mark-fallback:is(
    [data-route="privacy"],
    [data-route="cookies"],
    [data-route="terms"]
  ) {
    /* Legal mode shortens #stage to 40vh; this keeps the static mark in the
       same header-side pocket as the live model within that shorter stage.
       The slight right bias clears the wider brand lockup on 320px phones. */
    --fallback-mark-x: 55%;
    --fallback-mark-y: 24%;
    --fallback-mark-size: min(28vmin, 230px);
  }
}

@media (max-width: 1100px) and (max-height: 719px) {
  #mark-fallback {
    --fallback-mark-y: 28.75%;
    --fallback-mark-size: min(33vmin, 260px);
  }

  #mark-fallback:not([data-route="home"]) {
    --fallback-mark-y: 21%;
    --fallback-mark-size: min(24vmin, 220px);
  }

  #mark-fallback:is(
    [data-route="privacy"],
    [data-route="cookies"],
    [data-route="terms"]
  ) {
    --fallback-mark-y: 28%;
    --fallback-mark-size: min(22vmin, 180px);
  }
}

/* Landscape handhelds reuse the side-by-side 3D composition. Keep this
   query aligned with mark3d.js and the final landscape layout block. */
@media (max-width: 1100px) and (min-aspect-ratio: 5/4) {
  #mark-fallback {
    --fallback-mark-x: 72%;
    --fallback-mark-y: 54%;
    --fallback-mark-size: min(46vmin, 31vw, 460px);
  }

  #mark-fallback:not([data-route="home"]) {
    --fallback-mark-y: 50%;
    --fallback-mark-size: min(28vmin, 19vw, 276px);
  }

  #mark-fallback:is(
    [data-route="privacy"],
    [data-route="cookies"],
    [data-route="terms"]
  ) {
    --fallback-mark-x: 72%;
    --fallback-mark-size: min(26vmin, 16vw, 240px);
  }
}

@media (max-width: 1100px) and (min-aspect-ratio: 5/4) and (max-height: 359px) {
  #mark-fallback { --fallback-mark-y: 50.25%; }
}

#mark-leaders {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  z-index: 12;
  pointer-events: none;
}
#mark-leaders line {
  stroke: rgba(33, 4, 56, 0.28);
  stroke-width: 1.25;
  transition: stroke 0.25s ease, stroke-width 0.25s ease, filter 0.25s ease;
}

#mark-leaders line.is-selected {
  stroke: var(--magenta);
  stroke-width: 2;
  filter: drop-shadow(0 0 5px rgba(221, 6, 115, 0.5));
}

#mark-labels {
  position: fixed;
  inset: 0;
  z-index: 20;
  pointer-events: none;
}

.mark-label {
  position: absolute;
  transform: translate(-50%, -50%);
  pointer-events: auto;
  appearance: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: blur(6px);
  padding: 9px 16px;
  border-radius: 999px;
  box-shadow: var(--shadow-soft);
  transition: opacity 0.4s, color 0.2s, transform 0.2s, box-shadow 0.2s;
  white-space: nowrap;
}
.mark-label:hover, .mark-label.is-hot {
  color: var(--magenta);
  box-shadow: var(--shadow-lift);
}

.mark-label.is-selected {
  color: #fff;
  background: var(--magenta);
  box-shadow:
    0 8px 24px rgba(221, 6, 115, 0.24),
    0 0 0 4px rgba(221, 6, 115, 0.1);
  transform: translate(-50%, -50%) scale(1.04);
}

body.route-open .mark-label,
body.route-open #mark-leaders,
body.nav-open .mark-label,
body.nav-open #mark-leaders {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s;
}

/* ---------- Views / routing ---------- */

main { position: relative; z-index: 10; }

.view { min-height: 100vh; }

/* Home */

.view-home {
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100%;
  min-height: 0;
  padding: calc(var(--head-h) + 20px) clamp(20px, 4vw, 48px) 24px;
}

.hero-copy { max-width: 840px; }

@media (min-width: 1101px) {
  .hero-copy { transform: translateY(7px); }
}

@media (min-width: 1101px) and (min-height: 800px) {
  .hero-copy { transform: translateY(31px); }
}

.hero-line {
  font-family: var(--font-head);
  font-weight: 800;
  font-size: clamp(44px, 6.2vw, 88px);
  line-height: 1.02;
  letter-spacing: -0.025em;
  max-width: 560px;
  margin: 0;
}

.hero-qualifier {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 400;
  color: var(--grey);
  font-size: clamp(22px, 2.6vw, 36px);
  margin: 10px 0 0 4px;
}

.hero-intro {
  margin: 26px 0 0 4px;
  max-width: 720px;
  color: var(--ink);
}

.hero-intro a {
  color: var(--blue);
  font-weight: 600;
  text-underline-offset: 3px;
}

.hero-actions {
  display: flex;
  gap: 14px;
  margin: 30px 0 0 4px;
  flex-wrap: wrap;
}

/* Panels */

.view-panel {
  padding: calc(var(--head-h) + 34px) clamp(20px, 4vw, 48px) 90px;
  width: min(58%, 760px);
  opacity: 0;
  transform: translateX(-28px);
}

body.route-open .view-panel:not([hidden]) {
  animation: panel-in 0.7s var(--ease-out) 0.18s forwards;
}

@keyframes panel-in {
  to { opacity: 1; transform: translateX(0); }
}

.kicker {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 0 0 14px;
}
.kicker-magenta { color: var(--magenta); }
.kicker-blue { color: var(--blue); }
.kicker-purple { color: var(--purple); }
.kicker-deep { color: var(--deep-magenta); }

.view-panel h1 {
  font-family: var(--font-head);
  font-weight: 800;
  font-size: clamp(30px, 3.4vw, 48px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0 0 18px;
}

.lede {
  font-size: clamp(17px, 1.4vw, 20px);
  color: var(--grey);
  margin: 0 0 34px;
  max-width: 58ch;
}

.section-intro-more {
  display: grid;
  gap: 12px;
  max-width: 64ch;
  margin: -14px 0 38px;
  color: var(--grey);
}

.section-intro-more p { margin: 0; }

.section-intro-more a {
  color: var(--blue);
  font-weight: 600;
  text-underline-offset: 3px;
}

.panel-body { display: grid; gap: 26px; }

.fact-list { display: grid; gap: 18px; }
.fact-list > div {
  background: rgba(255, 255, 255, 0.8);
  border-radius: 14px;
  box-shadow: var(--shadow-soft);
  padding: 18px 22px;
}
.fact-list strong {
  font-family: var(--font-head);
  display: block;
  font-size: 16px;
  margin-bottom: 4px;
}
.fact-list span { color: var(--grey); font-size: 15px; }

.shot {
  margin: 0;
  border-radius: 16px;
  overflow: hidden;
  background: var(--card);
  box-shadow: var(--shadow-lift);
}
.shot img { width: 100%; height: auto; }
.shot figcaption {
  font-size: 13.5px;
  color: var(--grey);
  padding: 12px 18px;
}

.fine-note { font-size: 14px; color: var(--grey); }

.panel-cta {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 44px;
}

/* Embedded portfolio */

.portfolio-list {
  display: grid;
  gap: 32px;
  margin-top: 42px;
}

.portfolio-card {
  min-width: 0;
  overflow: hidden;
  padding: 24px;
  border: 1px solid rgba(33, 4, 56, 0.08);
  border-radius: 22px;
  background: rgba(255, 255, 255, 0.84);
  box-shadow: var(--shadow-soft);
}

.portfolio-card[id] { scroll-margin-top: calc(var(--head-h) + 18px); }

.portfolio-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 22px;
  margin-bottom: 12px;
}

.portfolio-head h2,
.theme-copy h2 {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 28px;
  margin: 0;
}

.project-title {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  column-gap: 9px;
}

.review-score {
  display: inline-flex;
  align-items: center;
  color: var(--blue);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.01em;
  line-height: 1.4;
  text-decoration: none;
  white-space: nowrap;
}

.review-score svg {
  width: 0.9em;
  height: 0.9em;
  margin-left: 0.25em;
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.5;
}

.review-score:hover { text-decoration: underline; }

.project-meta {
  font-size: 13.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--grey-soft);
  font-weight: 500;
  margin: 6px 0 14px;
}

.portfolio-card > p,
.theme-copy > p { color: var(--grey); }

.project-copy {
  display: grid;
  gap: 12px;
  max-width: 67ch;
  color: var(--grey);
}

.project-copy p { margin: 0; }

.project-copy ul {
  margin: 0;
  padding-left: 1.25rem;
}

.project-copy li + li { margin-top: 6px; }

.project-copy.is-collapsible { position: relative; }

.project-copy.is-collapsible:not(.is-expanded) {
  max-height: 16rem;
  overflow: hidden;
}

.project-copy--compact.is-collapsible:not(.is-expanded) {
  max-height: 8rem;
}

.project-copy.is-collapsible:not(.is-expanded)::after {
  content: '';
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 4.5rem;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff 92%);
}

.project-copy-toggle {
  display: inline-flex;
  margin-top: 12px;
  padding: 0;
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--magenta);
  font: 700 14px/1.4 var(--font-head);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.project-copy-toggle:hover { color: var(--deep-magenta); }
.project-copy-toggle[hidden] { display: none; }

.btn-small {
  flex: 0 0 auto;
  padding: 10px 17px;
  font-size: 13px;
  white-space: nowrap;
}

.gallery { margin-top: 22px; }

.gallery-viewport {
  overflow: hidden;
  border: 1px solid rgba(33, 4, 56, 0.09);
  border-radius: 15px;
  background: #f1f0f3;
}

.gallery-track {
  display: flex;
  width: 100%;
  transition: transform 0.62s var(--ease-out);
  will-change: transform;
}

.gallery-slide {
  position: relative;
  flex: 0 0 100%;
  min-width: 0;
  margin: 0;
  background: #eeedf0;
}

.gallery-slide img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: contain;
  object-position: center top;
}

.gallery-slide img[role="button"] { cursor: zoom-in; }

.gallery-slide img[role="button"]:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: -4px;
}

.gallery-slide figcaption {
  position: absolute;
  left: 12px;
  bottom: 12px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 11px;
  border-radius: 999px;
  color: #fff;
  background: rgba(33, 4, 56, 0.82);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: 12.5px;
  line-height: 1.2;
}

.gallery-slide figcaption[role="button"] { cursor: zoom-in; }

.gallery-slide figcaption[role="button"]::after {
  content: "";
  width: 13px;
  height: 13px;
  flex: 0 0 13px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='6.75' cy='6.75' r='4.75' fill='none' stroke='black' stroke-width='1.6'/%3E%3Cpath d='m10.2 10.2 3.8 3.8' fill='none' stroke='black' stroke-linecap='round' stroke-width='1.6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='6.75' cy='6.75' r='4.75' fill='none' stroke='black' stroke-width='1.6'/%3E%3Cpath d='m10.2 10.2 3.8 3.8' fill='none' stroke='black' stroke-linecap='round' stroke-width='1.6'/%3E%3C/svg%3E") center / contain no-repeat;
}

.gallery-slide figcaption[role="button"]:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

.gallery-controls {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 12px;
}

.gallery-controls button {
  width: 40px;
  height: 40px;
  border: 1px solid rgba(33, 4, 56, 0.15);
  border-radius: 50%;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.76);
  font-size: 18px;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s, transform 0.2s var(--ease-out);
}

.gallery-controls button:hover {
  color: var(--magenta);
  border-color: var(--magenta);
  transform: translateY(-1px);
}

.gallery-status {
  min-width: 48px;
  color: var(--grey);
  font-size: 13px;
  text-align: center;
}

/* The mobile-only screenshot viewer is intentionally just a full-bleed black
   canvas and an overlaid close control. */
.screenshot-viewer {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: #000;
}

.screenshot-viewer-close {
  position: absolute;
  top: max(12px, env(safe-area-inset-top));
  right: max(12px, env(safe-area-inset-right));
  z-index: 2;
  display: inline-grid;
  place-items: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  color: #fff;
  background: rgba(0, 0, 0, 0.72);
  font: 400 30px/1 var(--font-head);
  cursor: pointer;
}

.screenshot-viewer-close:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

.screenshot-viewer-canvas {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 0;
  border-radius: 0;
  background: #000;
  touch-action: none;
  overscroll-behavior: contain;
  cursor: grab;
}

.screenshot-viewer-canvas.is-dragging { cursor: grabbing; }

.screenshot-viewer-canvas img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  transform: translate3d(0, 0, 0) scale(1);
  transform-origin: center;
  will-change: transform;
}

.theme-project {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(240px, 0.75fr);
  padding: 0;
}

.theme-shot {
  min-height: 300px;
  margin: 0;
  background: var(--bg-deep);
}

.theme-project.has-expanded-copy {
  grid-template-columns: minmax(0, 1fr);
}

.theme-project.has-expanded-copy .theme-shot {
  min-height: 0;
  aspect-ratio: 16 / 10;
}

.theme-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

.theme-shot img[role="button"] { cursor: zoom-in; }

.theme-shot img[role="button"]:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: -4px;
}

.theme-copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 28px;
}

.theme-copy .project-meta { margin-top: 0; }
.theme-copy > p { margin: 12px 0 0; }
.theme-copy > .project-copy { margin-top: 12px; }

.theme-project.has-expanded-copy .theme-copy {
  justify-content: flex-start;
  padding: 22px clamp(30px, 4vw, 52px) clamp(30px, 4vw, 52px);
}

/* During the staged expansion the card's real height participates in layout,
   while its grid tracks stay anchored to the top. This lets following cards
   move naturally and avoids stretching or snapshot-scaling the text. */
.theme-project.is-layout-animating {
  overflow: hidden;
}

.theme-project.is-layout-reshaping {
  align-content: start;
  overflow: hidden;
}

.theme-project.is-layout-reshaping .theme-shot,
.theme-project.is-layout-reshaping .theme-copy {
  align-self: start;
}

.theme-project.is-layout-reshaping:not(.has-expanded-copy) .theme-shot {
  height: var(--theme-shot-target-height);
  min-height: 0;
}

.project-link {
  align-self: flex-start;
  margin-top: 10px;
  color: var(--blue);
  font-weight: 600;
  text-decoration: none;
}
.project-link:hover { text-decoration: underline; }

/* Integrations and automations */

.integration-board {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  padding: 22px;
  border: 1px solid rgba(48, 66, 143, 0.14);
  border-radius: 20px;
  background:
    radial-gradient(circle at 50% 12%, rgba(221, 6, 115, 0.11), transparent 42%),
    rgba(255, 255, 255, 0.75);
  box-shadow: var(--shadow-soft);
}

.integration-board span {
  display: grid;
  min-height: 76px;
  place-items: center;
  padding: 12px;
  border-radius: 13px;
  color: var(--grey);
  background: #fff;
  box-shadow: 0 7px 20px rgba(33, 4, 56, 0.07);
  font-size: 13px;
  font-weight: 600;
  text-align: center;
}

.integration-board .integration-core {
  grid-column: 1 / -1;
  width: min(190px, 60%);
  min-height: 88px;
  justify-self: center;
  color: #fff;
  background: linear-gradient(135deg, var(--magenta), var(--blue));
  font-family: var(--font-head);
  font-size: 21px;
}

.integration-proof {
  display: grid;
  grid-template-columns: minmax(170px, 0.72fr) minmax(0, 1.6fr);
  align-items: center;
  gap: clamp(26px, 4vw, 52px);
  padding: clamp(26px, 4vw, 44px);
  border: 1px solid rgba(33, 4, 56, 0.10);
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.86);
  box-shadow: var(--shadow-soft);
}

.integration-proof-logo {
  display: grid;
  min-height: 176px;
  place-items: center;
  padding: clamp(26px, 4vw, 42px);
  border-radius: 16px;
  background: #f1ece7;
}

.integration-proof-logo img {
  width: min(100%, 270px);
  height: auto;
}

.bybiehl-proof-logo img {
  aspect-ratio: 1200 / 332;
  object-fit: contain;
}

.integration-proof-copy {
  display: grid;
  gap: 12px;
}

.integration-proof-copy .project-meta { margin: 0 0 2px; }

.integration-proof-copy h2 {
  margin: 0 0 4px;
  font-family: var(--font-head);
  font-size: clamp(26px, 3vw, 40px);
  line-height: 1.08;
  letter-spacing: -0.02em;
}

.integration-proof-copy p:not(.project-meta) {
  max-width: 60ch;
  margin: 0;
  color: var(--grey);
}

.integration-proof-copy .project-link { margin-top: 2px; }

.shelter-proof-brand {
  display: grid;
  align-self: stretch;
  align-content: center;
  gap: 10px;
}

.shelter-proof-logo {
  padding: 18px;
  background: #fff;
}

.shelter-proof-logo img {
  width: min(100%, 150px);
}

.shelter-brand-legal {
  margin: 0;
  color: var(--grey-soft);
  font-size: 9px;
  line-height: 1.35;
  text-align: center;
}

/* Contact */

.contact-form { display: grid; gap: 18px; max-width: 520px; }
.contact-form label { display: grid; gap: 7px; }
.contact-form label span {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 14px;
}
.contact-form input,
.contact-form textarea {
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.9);
  border: 1.5px solid rgba(33, 4, 56, 0.14);
  border-radius: 12px;
  padding: 13px 16px;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.contact-form input:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: var(--magenta);
  box-shadow: 0 0 0 4px rgba(221, 6, 115, 0.12);
}
.contact-form button { justify-self: start; }
.contact-form button:disabled {
  cursor: wait;
  opacity: 0.62;
}

.form-trap {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.captcha-row { display: grid; gap: 7px; }
.captcha-label {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 14px;
}

altcha-widget {
  display: block;
  width: 100%;
  --altcha-color-base: #ffffff;
  --altcha-color-base-content: var(--ink);
  --altcha-color-primary: var(--magenta);
  --altcha-color-primary-content: #ffffff;
  --altcha-color-neutral: var(--bg);
  --altcha-color-neutral-content: var(--grey);
  --altcha-color-success: var(--blue);
  --altcha-color-success-content: #ffffff;
  --altcha-color-error: #a51d48;
  --altcha-border-color: rgba(33, 4, 56, 0.14);
  --altcha-border-radius: 12px;
  --altcha-max-width: 100%;
  --altcha-font-family: var(--font-body);
}

.form-note,
.form-status { margin: 0; }
.form-note a { color: var(--blue); font-weight: 600; }
.form-status { min-height: 1.6em; }
.form-status.is-success { color: var(--blue); font-weight: 600; }
.form-status.is-error { color: #a51d48; font-weight: 600; }

/* Legal pages */

.view-legal { width: min(62%, 780px); }

.legal-body {
  display: grid;
  gap: 30px;
  max-width: 64ch;
}

.legal-body > p { margin: 0; }

.legal-body section h2 {
  font-family: var(--font-head);
  font-size: 20px;
  line-height: 1.25;
  margin: 0 0 8px;
}

.legal-body section p { margin: 0 0 12px; }
.legal-body section p:last-child { margin-bottom: 0; }
.legal-body a { color: var(--blue); font-weight: 600; }

/* Shown only when the site is opened from file:// (see inline guard) */
.serve-note {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 90;
  background: var(--ink);
  color: #fff;
  font-size: 14px;
  line-height: 1.5;
  padding: 14px clamp(20px, 4vw, 48px);
}

/* ---------- Footer ---------- */

.site-foot {
  position: relative;
  z-index: 10;
  display: grid;
  justify-items: end;
  gap: 2px;
  padding: 26px clamp(20px, 4vw, 48px) 34px;
  font-size: 12.5px;
  line-height: 1.45;
  text-align: right;
  color: var(--grey-soft);
}
.site-foot p { margin: 2px 0; }

.legal-links {
  display: flex;
  justify-content: flex-end;
  gap: 18px;
  margin-bottom: 4px;
}

.legal-links a {
  color: var(--grey);
  font-weight: 600;
  text-decoration: none;
}

.legal-links a:hover { color: var(--magenta); }

/* ---------- Focus visibility ---------- */

a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible {
  outline: 3px solid rgba(48, 66, 143, 0.6);
  outline-offset: 2px;
}

/* Headings receive programmatic focus on route change for screen readers;
   they are not interactive, so no visible ring. */
.view h1:focus { outline: none; }

/* ---------- Mobile ---------- */

@media (max-width: 1100px) {
  .nav-toggle { display: flex; }

  .site-nav {
    position: fixed;
    inset: 0;
    flex-direction: column;
    justify-content: center;
    gap: 26px;
    background: rgba(245, 244, 247, 0.985);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    transform: translateY(-102%);
    transition: transform 0.45s var(--ease-out);
    z-index: 35;
  }
  body.nav-open .site-nav { transform: translateY(0); }
  .site-nav a:not(.btn) { font-size: 22px; }
  .nav-cta { font-size: 16px; padding: 14px 28px; }

  #stage {
    position: absolute;
    inset: 0 0 auto 0;
    height: 44vh;
  }
  body.route-open #stage { opacity: 0.15; height: 40vh; }
  /* Keep the stage's measurable box so route transitions can continue to
     resolve their coordinates, but remove both WebGL and fallback artwork. */
  body.legal-mode #stage { visibility: hidden; }

  .view-home {
    justify-content: flex-start;
    padding-top: 34vh;
    padding-bottom: 20px;
  }
  .hero-copy { max-width: none; }
  .hero-line { font-size: clamp(38px, 11vw, 56px); }
  .hero-qualifier { font-size: clamp(20px, 5.4vw, 26px); }
  .hero-intro {
    color: var(--grey);
    font-family: var(--font-body);
    font-size: 17px;
    font-style: normal;
    font-weight: 400;
    line-height: 1.6;
    letter-spacing: normal;
  }

  .view-panel, .view-work, .view-legal { width: auto; }

  .shot-grid { grid-template-columns: 1fr; }
  .shot-grid .shot-wide { grid-column: auto; }

  .mark-label {
    padding: 7px 11px;
    font-size: 10.5px;
    letter-spacing: 0.075em;
    box-shadow: 0 7px 20px rgba(33, 4, 56, 0.12);
  }

  #mark-leaders line { stroke-width: 1; }
  #mark-leaders line.is-selected { stroke-width: 1.75; }
}

@media (max-width: 700px) {
  .portfolio-head { flex-direction: column; gap: 0; }
  .portfolio-head .btn-small { align-self: flex-start; }

  .theme-project { grid-template-columns: 1fr; }
  .theme-shot { min-height: 0; aspect-ratio: 16 / 10; }

  .integration-board { grid-template-columns: 1fr 1fr; }
  .integration-board .integration-core { grid-column: 1 / -1; }
  .integration-proof { grid-template-columns: 1fr; }
  .bybiehl-proof-logo {
    grid-template-columns: minmax(0, 1fr);
    width: 100%;
    overflow: hidden;
  }
  .bybiehl-proof-logo img {
    width: 100%;
    max-width: 270px;
    justify-self: center;
  }
  .integration-proof-logo { min-height: 142px; }
}

@media (max-width: 520px) {
  .brand img { height: 32px; }

  #stage { height: 43vh; }

  .view-home { padding-top: 36vh; }
  .hero-qualifier { margin-top: 6px; }
  .hero-intro { margin-top: 16px; }
  .hero-intro + .hero-intro { margin-top: 12px; }
  .hero-actions {
    flex-wrap: nowrap;
    gap: 10px;
    margin-top: 16px;
  }
  .hero-actions .btn { padding: 12px 18px; font-size: 14px; }

  .portfolio-list { gap: 22px; margin-top: 30px; }
  .portfolio-card { padding: 16px; border-radius: 17px; }
  .theme-project { padding: 0; }
  .theme-copy { padding: 22px 18px; }
  .gallery-slide figcaption { left: 8px; bottom: 8px; }
  .integration-board { gap: 9px; padding: 14px; }
  .integration-board span { min-height: 64px; padding: 9px; font-size: 12px; }
  .integration-proof { gap: 22px; padding: 20px; }
  .integration-proof-logo { min-height: 116px; padding: 26px; }

  body.home-route .site-foot {
    padding-top: 10px;
    padding-bottom: 14px;
    font-size: 10.5px;
    line-height: 1.35;
  }

  body.home-route .legal-links { gap: 14px; margin-bottom: 3px; }
}

@media (max-width: 520px) and (max-height: 720px) {
  #stage { height: 29vh; }

  .view-home { padding-top: 25vh; padding-bottom: 10px; }
  .hero-intro { margin-top: 14px; }

  .site-foot {
    padding-top: 8px;
    padding-bottom: 10px;
    font-size: 10.5px;
    line-height: 1.35;
  }
}

@media (max-width: 360px) {
  #stage { height: 23vh; }

  .view-home { padding-top: 20vh; }
  .hero-line { font-size: 34px; }
  .hero-qualifier { font-size: 18px; }
  .hero-intro { margin-top: 12px; }
  .hero-actions { gap: 8px; margin-top: 14px; }
  .hero-actions .btn {
    padding: 11px;
    font-size: 13px;
    white-space: nowrap;
  }
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    transition-duration: 0.001s !important;
  }
  body.route-open .view-panel:not([hidden]) {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ============================================================
   One-page flow
   Marketing destinations are continuous chapters. Each chapter ends in a
   scroll gate which drives both the mark transition and the liquid chevron.
   ============================================================ */

.sr-only {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

body.flow-mode {
  display: block;
  height: auto;
  min-height: 100vh;
  overflow-x: clip;
}

body.flow-mode .site-head {
  background: linear-gradient(180deg, rgba(245, 244, 247, 0.92), rgba(245, 244, 247, 0.72) 72%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

body.flow-mode main { min-height: 0; }

body.flow-mode .flow-view {
  position: relative;
  display: block;
  width: 100%;
  min-height: 0;
  padding: 0;
  opacity: 1;
  transform: none;
  scroll-margin-top: 0;
}

body.flow-mode .flow-view + .flow-view::before {
  content: "";
  position: absolute;
  top: 0;
  left: clamp(20px, 4vw, 48px);
  right: clamp(20px, 4vw, 48px);
  height: 1px;
  background: linear-gradient(90deg, rgba(33, 4, 56, 0.10), rgba(33, 4, 56, 0));
}

body.flow-mode .section-content {
  position: relative;
  z-index: 2;
  box-sizing: border-box;
  width: 54vw;
  min-height: 100vh;
  min-height: 100svh;
  padding: calc(var(--head-h) + 52px) clamp(20px, 4vw, 48px) 100px;
  will-change: opacity;
}

body.flow-mode .view-home .section-content {
  display: flex;
  align-items: center;
  width: 50%;
  padding: calc(var(--head-h) + 28px) 0 54px clamp(20px, 4vw, 48px);
}

body.flow-mode .view-work .section-content {
  width: 54vw;
}

body.flow-mode .section-gate {
  position: relative;
  z-index: 0;
  height: clamp(360px, 58vh, 620px);
  pointer-events: none;
}

body.flow-mode .section-gate::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(44% 65% at 75% 50%, rgba(221, 6, 115, 0.045), transparent 70%),
    linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.24) 50%, transparent);
}

.flow-cue {
  --fill: 0;
  --unfilled: 100%;
  position: fixed;
  left: 50%;
  bottom: clamp(22px, 4vh, 44px);
  z-index: 26;
  width: 116px;
  height: 78px;
  padding: 0;
  border: 0;
  appearance: none;
  background: transparent;
  transform: translateX(-50%);
  cursor: pointer;
  animation: flow-cue-arrive 0.5s var(--ease-out) both;
}

.flow-chevron {
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.12);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 116 78' preserveAspectRatio='none'%3E%3Cpath d='M13 19 L58 62 L103 19' fill='none' stroke='%23000' stroke-width='13' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 116 78' preserveAspectRatio='none'%3E%3Cpath d='M13 19 L58 62 L103 19' fill='none' stroke='%23000' stroke-width='13' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

.flow-chevron-base {
  background: rgba(48, 66, 143, 0.035);
  backdrop-filter: invert(0.13) contrast(1.10) saturate(0.72);
  -webkit-backdrop-filter: invert(0.13) contrast(1.10) saturate(0.72);
  box-shadow: inset 0 0 20px rgba(33, 4, 56, 0.08);
}

.flow-chevron-liquid {
  overflow: hidden;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.flow-liquid-level {
  position: absolute;
  inset: 0;
  clip-path: polygon(
    0 calc(var(--unfilled) + 3px),
    18% calc(var(--unfilled) - 2px),
    38% calc(var(--unfilled) + 2px),
    60% calc(var(--unfilled) - 3px),
    80% calc(var(--unfilled) + 1px),
    100% calc(var(--unfilled) - 2px),
    100% 100%,
    0 100%
  );
  background: rgba(221, 6, 115, 0.11);
  backdrop-filter: invert(0.22) hue-rotate(18deg) saturate(1.5) contrast(1.14);
  -webkit-backdrop-filter: invert(0.22) hue-rotate(18deg) saturate(1.5) contrast(1.14);
  transition: clip-path 40ms linear;
}

.flow-cue.is-full {
  filter: drop-shadow(0 8px 18px rgba(151, 6, 107, 0.16));
}

@keyframes flow-cue-arrive {
  from { opacity: 0; transform: translate(-50%, 10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

@media (max-width: 1100px) {
  body.flow-mode .site-nav {
    height: 100vh;
    height: 100dvh;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
  }

  body.flow-mode.nav-open .site-nav {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
  }

  body.flow-mode #stage {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100vh;
    height: 100svh;
    opacity: 1;
  }

  body.flow-mode .section-content,
  body.flow-mode .view-work .section-content {
    width: 100%;
    min-height: 100vh;
    min-height: 100svh;
    padding: 34vh clamp(20px, 4.5vw, 44px) 82px;
  }

  body.flow-mode .view-home .section-content {
    align-items: flex-start;
    width: 100%;
    padding: 38vh clamp(20px, 4.5vw, 44px) 48px;
  }

  body.flow-mode .section-content > :not(.hero-copy) {
    position: relative;
    z-index: 2;
  }

  body.flow-mode .section-gate {
    height: clamp(310px, 50vh, 500px);
  }

  .flow-cue {
    bottom: max(18px, env(safe-area-inset-bottom));
    width: 98px;
    height: 66px;
  }
}

@media (max-width: 520px) {
  body.flow-mode #stage { height: 100svh; }

  body.flow-mode .view-home .section-content {
    padding-top: 34vh;
    padding-bottom: 38px;
  }

  body.flow-mode .section-content,
  body.flow-mode .view-work .section-content {
    padding-top: 30vh;
    padding-bottom: 70px;
  }

  body.flow-mode .site-foot {
    padding-top: 22px;
    padding-bottom: 24px;
    font-size: 10.5px;
    line-height: 1.4;
  }
}

@media (prefers-reduced-motion: reduce) {
  .flow-cue { animation: none; }
  .flow-liquid-level { transition: none; }
}

/* ============================================================
   Locked viewport chapters
   The document never scrolls in marketing mode. Only an overflowing active
   chapter can scroll; at its end, input is diverted into the liquid gate.
   ============================================================ */

body.flow-mode {
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  overscroll-behavior: none;
}

body.flow-mode main {
  position: fixed;
  inset: 0;
  z-index: 10;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

body.flow-mode > .site-foot { display: none; }

body.flow-mode .flow-view {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  min-height: 0;
  padding: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

body.flow-mode .flow-view::before { display: none; }

body.flow-mode .view-home {
  overflow: hidden;
  scrollbar-gutter: auto;
}

body.flow-mode .section-content {
  width: 54vw;
  min-height: 100vh;
  min-height: 100dvh;
  padding: calc(var(--head-h) + 52px) clamp(20px, 4vw, 48px) 92px;
  opacity: 1 !important;
  will-change: auto;
}

/* The marketing copy belongs to the same rail as its cards and supporting
   content. Older character-based reading-width caps left these blocks visibly
   narrower as the desktop rail grew on larger screens. */
body.flow-mode .flow-view:not(.view-home) .lede,
body.flow-mode .flow-view:not(.view-home) .section-intro-more,
body.flow-mode .flow-view:not(.view-home) .project-copy {
  width: 100%;
  max-width: none;
}

body.flow-mode .view-home .section-content {
  width: 50%;
  height: 100vh;
  height: 100dvh;
  min-height: 0;
  overflow: hidden;
  padding: calc(var(--head-h) + 28px) 0 54px clamp(20px, 4vw, 48px);
}

@media (min-width: 1101px) {
  body.flow-mode .view-home .hero-copy {
    width: 100%;
    max-width: none;
  }

  body.flow-mode .view-home .hero-line {
    max-width: 100%;
    white-space: nowrap;
    font-size: clamp(44px, calc(5vw - 5px), 88px);
  }

  body.flow-mode .view-home .hero-qualifier {
    margin-top: clamp(6px, 0.7vw, 10px);
    font-size: clamp(21px, 2.1vw, 36px);
  }

  body.flow-mode .view-home .hero-intro {
    max-width: none;
    margin-top: clamp(18px, 1.8vw, 26px);
    font-size: clamp(15px, 1.18vw, 17px);
    line-height: 1.55;
  }

  body.flow-mode .view-home .hero-intro + .hero-intro {
    margin-top: clamp(10px, 1vw, 14px);
  }

  body.flow-mode .view-home .hero-actions {
    gap: clamp(10px, 1vw, 14px);
    margin-top: clamp(20px, 2.1vw, 30px);
  }

  body.flow-mode .view-home .hero-actions .btn {
    padding: clamp(11px, 0.9vw, 13px) clamp(18px, 1.8vw, 26px);
    font-size: clamp(13px, 1.05vw, 15px);
  }
}

body.flow-mode .view-work .section-content { width: 54vw; }

body.flow-mode .flow-foot {
  position: relative;
  min-height: 0;
  padding-top: 26px;
  background: linear-gradient(180deg, transparent, rgba(245, 244, 247, 0.86));
}

body.flow-mode .flow-view.is-active { z-index: 2; }
body.flow-mode .flow-view.is-entering-down,
body.flow-mode .flow-view.is-entering-up { z-index: 4; }
body.flow-mode .flow-view.is-leaving-down,
body.flow-mode .flow-view.is-leaving-up {
  z-index: 3;
  pointer-events: none;
}

body.flow-mode .flow-view.is-leaving-down {
  animation: chapter-leave-up 0.72s var(--ease-out) both;
}
body.flow-mode .flow-view.is-entering-down {
  animation: chapter-enter-up 0.72s var(--ease-out) both;
}
body.flow-mode .flow-view.is-leaving-up {
  animation: chapter-leave-down 0.72s var(--ease-out) both;
}
body.flow-mode .flow-view.is-entering-up {
  animation: chapter-enter-down 0.72s var(--ease-out) both;
}

@keyframes chapter-leave-up {
  to { opacity: 0; transform: translateY(-7vh) scale(0.985); }
}
@keyframes chapter-enter-up {
  from { opacity: 0; transform: translateY(9vh) scale(0.985); }
  to { opacity: 1; transform: none; }
}
@keyframes chapter-leave-down {
  to { opacity: 0; transform: translateY(7vh) scale(0.985); }
}
@keyframes chapter-enter-down {
  from { opacity: 0; transform: translateY(-9vh) scale(0.985); }
  to { opacity: 1; transform: none; }
}

/* Clicking a control attached to the model creates one coordinated 560ms
   event. The whole left field changes directionally while its content peels
   away and returns in a short hierarchy-led stagger. */
body.flow-mode .flow-view.is-mark-driven.is-leaving-down {
  animation: mark-chapter-leave-up var(--mark-navigation-duration, 560ms) var(--ease-out) both;
}
body.flow-mode .flow-view.is-mark-driven.is-entering-down {
  animation: mark-chapter-enter-up var(--mark-navigation-duration, 560ms) var(--ease-out) both;
}
body.flow-mode .flow-view.is-mark-driven.is-leaving-up {
  animation: mark-chapter-leave-down var(--mark-navigation-duration, 560ms) var(--ease-out) both;
}
body.flow-mode .flow-view.is-mark-driven.is-entering-up {
  animation: mark-chapter-enter-down var(--mark-navigation-duration, 560ms) var(--ease-out) both;
}

@keyframes mark-chapter-leave-up {
  0% { opacity: 1; transform: none; }
  30%, 100% { opacity: 0; transform: translateY(-12px); }
}
@keyframes mark-chapter-enter-up {
  0%, 30% { opacity: 0; transform: translateY(14px); }
  100% { opacity: 1; transform: none; }
}
@keyframes mark-chapter-leave-down {
  0% { opacity: 1; transform: none; }
  30%, 100% { opacity: 0; transform: translateY(12px); }
}
@keyframes mark-chapter-enter-down {
  0%, 30% { opacity: 0; transform: translateY(-14px); }
  100% { opacity: 1; transform: none; }
}

body.flow-mode .flow-view.is-mark-driven.is-leaving-down .section-content > *,
body.flow-mode .flow-view.is-mark-driven.is-leaving-up .section-content > * {
  animation: mark-content-leave calc(var(--mark-selection-delay, 168ms) - 42ms) cubic-bezier(0.4, 0, 0.2, 1) both;
  will-change: opacity, translate;
}

body.flow-mode .flow-view.is-mark-driven.is-entering-down .section-content > *,
body.flow-mode .flow-view.is-mark-driven.is-entering-up .section-content > * {
  animation: mark-content-enter calc(var(--mark-selection-duration, 291.2ms) - 42ms) var(--ease-out) var(--mark-selection-delay, 168ms) both;
  will-change: opacity, translate;
}

body.flow-mode .flow-view.is-mark-driven .section-content > :nth-child(2) { animation-delay: calc(var(--mark-selection-delay, 168ms) + 14ms); }
body.flow-mode .flow-view.is-mark-driven .section-content > :nth-child(3) { animation-delay: calc(var(--mark-selection-delay, 168ms) + 28ms); }
body.flow-mode .flow-view.is-mark-driven .section-content > :nth-child(n + 4) { animation-delay: calc(var(--mark-selection-delay, 168ms) + 42ms); }
body.flow-mode .flow-view.is-mark-driven.is-leaving-down .section-content > :nth-child(2),
body.flow-mode .flow-view.is-mark-driven.is-leaving-up .section-content > :nth-child(2) { animation-delay: 14ms; }
body.flow-mode .flow-view.is-mark-driven.is-leaving-down .section-content > :nth-child(3),
body.flow-mode .flow-view.is-mark-driven.is-leaving-up .section-content > :nth-child(3) { animation-delay: 28ms; }
body.flow-mode .flow-view.is-mark-driven.is-leaving-down .section-content > :nth-child(n + 4),
body.flow-mode .flow-view.is-mark-driven.is-leaving-up .section-content > :nth-child(n + 4) { animation-delay: 42ms; }

@keyframes mark-content-leave {
  from { opacity: 1; translate: 0 0; }
  to { opacity: 0; translate: -10px 0; }
}

@keyframes mark-content-enter {
  from { opacity: 0; translate: -12px 0; }
  72% { opacity: 1; }
  to { opacity: 1; translate: 0 0; }
}

/* Scroll-driven chapter changes use one reversible layered motion. Moving
   forwards draws the next chapter up from below; moving backwards lowers the
   current chapter to reveal the previous one. Direct navigation keeps the
   shorter cross-motion above. */
body.flow-mode .flow-view.is-scroll-driven.is-leaving-down {
  z-index: 3;
  animation: scroll-chapter-underlay-hide 0.94s var(--ease-scroll) both;
  will-change: opacity, transform;
}

body.flow-mode .flow-view.is-scroll-driven.is-entering-down {
  z-index: 4;
  animation: scroll-chapter-slide-in 0.94s var(--ease-scroll) both;
  will-change: transform;
}

body.flow-mode .flow-view.is-scroll-driven.is-leaving-up {
  z-index: 4;
  animation: scroll-chapter-slide-out 0.94s var(--ease-scroll) both;
  will-change: transform;
}

body.flow-mode .flow-view.is-scroll-driven.is-entering-up {
  z-index: 3;
  animation: scroll-chapter-underlay-show 0.94s var(--ease-scroll) both;
  will-change: opacity, transform;
}

@keyframes scroll-chapter-slide-in {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

@keyframes scroll-chapter-slide-out {
  from { transform: translateY(0); }
  to { transform: translateY(100%); }
}

@keyframes scroll-chapter-underlay-hide {
  from { opacity: 1; transform: scale(1); }
  32%, to { opacity: 0; transform: scale(0.992); }
}

@keyframes scroll-chapter-underlay-show {
  from { opacity: 0; transform: scale(0.992); }
  32% { opacity: 0.78; }
  to { opacity: 1; transform: scale(1); }
}

/* Approximately half the previous height: the SVG mask is deliberately
   stretched to 100% × 100% rather than aspect-fit, compressing the V. */
.flow-cue {
  width: 116px;
  height: 39px;
  bottom: clamp(22px, 3.2vh, 34px);
}

.flow-chevron {
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

.flow-liquid-level {
  clip-path: inset(100% 0 0 0);
  transition: none;
  background:
    radial-gradient(circle at 18% 78%, rgba(255, 255, 255, 0.34) 0 2px, transparent 3px),
    radial-gradient(circle at 73% 54%, rgba(255, 255, 255, 0.26) 0 1.5px, transparent 3px),
    linear-gradient(112deg, rgba(221, 6, 115, 0.15), rgba(48, 66, 143, 0.13));
  background-size: 38px 31px, 51px 37px, 100% 100%;
  backdrop-filter: invert(0.23) hue-rotate(18deg) saturate(1.58) contrast(1.16);
  -webkit-backdrop-filter: invert(0.23) hue-rotate(18deg) saturate(1.58) contrast(1.16);
  filter: drop-shadow(0 -1px 1.5px rgba(221, 6, 115, 0.34));
  animation: liquid-current 2.8s linear infinite;
}

@keyframes liquid-current {
  to { background-position: 38px -31px, -51px -37px, 0 0; }
}

@media (max-width: 1100px) {
  body.flow-mode {
    /* Portrait chapters keep the sculpture in a permanent top band. The
       chapter itself starts below that boundary, so its independently
       scrolling copy can never pass behind the mark. */
    --mobile-mark-band: calc(clamp(300px, 39svh, 400px) + 5svh);
  }

  body.flow-mode .flow-view:not(.view-home) {
    inset: var(--mobile-mark-band) 0 0;
    height: auto;
  }

  body.flow-mode .section-content,
  body.flow-mode .view-work .section-content {
    width: 100%;
    min-height: 100vh;
    min-height: 100dvh;
    padding: 34vh clamp(20px, 4.5vw, 44px) 78px;
  }

  body.flow-mode .flow-view:not(.view-home) .section-content {
    min-height: calc(100svh - var(--mobile-mark-band));
    min-height: calc(100dvh - var(--mobile-mark-band));
    padding: 6px clamp(20px, 4.5vw, 44px) 78px;
  }

  body.flow-mode .view-home .section-content {
    width: 100%;
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: visible;
    padding: 46vh clamp(20px, 4.5vw, 44px) 42px;
  }

  /* Mobile uses the same readable body typography as the other chapter
     blurbs, so let the hero scroll when that copy exceeds a short viewport. */
  body.flow-mode .view-home {
    overflow-y: auto;
    scrollbar-gutter: stable;
  }

  /* Stacked tablets are wide enough for very long lines; cap the reading
     measure that the desktop rail rules above deliberately uncapped. */
  body.flow-mode .flow-view:not(.view-home) .lede,
  body.flow-mode .flow-view:not(.view-home) .section-intro-more {
    max-width: 62ch;
  }

  body.flow-mode .flow-view:not(.view-home) .project-copy {
    max-width: 67ch;
  }

  .flow-cue {
    width: 98px;
    height: 33px;
    bottom: max(16px, env(safe-area-inset-bottom));
  }
}

@media (max-width: 1100px) and (max-aspect-ratio: 5/4) {
  /* Once the independent copy viewport moves, soften its top edge so text
     and cards recede into the reserved model band instead of being clipped
     by a hard horizontal boundary. The class is scroll-position driven, so
     the chapter heading remains completely crisp at scrollTop 0. */
  body.flow-mode .flow-view:not(.view-home).has-top-scroll-fade::before {
    content: "";
    position: sticky;
    top: 0;
    z-index: 5;
    display: block;
    height: 38px;
    margin-bottom: -38px;
    background: linear-gradient(
      to bottom,
      rgba(249, 248, 251, 0.98) 0,
      rgba(249, 248, 251, 0.72) 42%,
      rgba(249, 248, 251, 0) 100%
    );
    backdrop-filter: blur(1.5px);
    -webkit-backdrop-filter: blur(1.5px);
    pointer-events: none;
  }
}

@media (max-width: 520px) {
  body.flow-mode {
    --mobile-mark-band: calc(clamp(275px, 37svh, 320px) + 5svh);
  }

  body.flow-mode .section-content,
  body.flow-mode .view-work .section-content {
    padding: 30vh 20px 66px;
  }

  body.flow-mode .view-home .section-content {
    padding: 43vh 20px 34px;
  }

  body.flow-mode .flow-foot {
    padding-top: 18px;
    padding-bottom: 20px;
  }
}

@media (max-width: 520px) and (max-height: 720px) {
  body.flow-mode .view-home .section-content { padding: 45vh 20px 22px; }
  body.flow-mode .view-home .hero-line { font-size: 34px; }
  body.flow-mode .view-home .hero-qualifier { font-size: 18px; }
  body.flow-mode .view-home .hero-intro {
    margin-top: 12px;
  }
  body.flow-mode .view-home .hero-actions { margin-top: 14px; }
}

@media (max-width: 360px) and (max-height: 720px) {
  body.flow-mode .view-home .section-content { padding: 45vh 16px 22px; }
}

@media (prefers-reduced-motion: reduce) {
  body.flow-mode .flow-view.is-leaving-down,
  body.flow-mode .flow-view.is-entering-down,
  body.flow-mode .flow-view.is-leaving-up,
  body.flow-mode .flow-view.is-entering-up {
    animation-duration: 0.001s;
  }
  body.flow-mode .flow-view.is-mark-driven .section-content > * {
    animation: none !important;
    opacity: 1;
    translate: none;
  }
  .flow-liquid-level { animation: none; }
}

/* ============================================================
   Landscape handhelds (phones sideways, sub-1100px landscape tablets).
   The stacked top-mark composition has no vertical room here, so reuse the
   desktop side-by-side one: content rail left, mark in the right field.
   mark3d.js watches the same query to switch its layout tables.
   ============================================================ */

@media (max-width: 1100px) and (min-aspect-ratio: 5/4) {
  /* The portrait menu's tall type and gaps overflow a landscape viewport. */
  .site-nav {
    gap: 14px;
    overflow-y: auto;
    padding: 12px 0;
  }
  .site-nav a:not(.btn) { font-size: 18px; }
  .site-nav .nav-cta { font-size: 14px; padding: 11px 22px; }

  body.flow-mode .section-content,
  body.flow-mode .view-work .section-content {
    width: 54vw;
    min-height: 100vh;
    min-height: 100svh;
    padding: calc(var(--head-h) + 22px) clamp(16px, 2.5vw, 28px) 64px clamp(20px, 4vw, 48px);
  }

  body.flow-mode .flow-view:not(.view-home) {
    inset: 0;
    height: 100vh;
    height: 100dvh;
  }

  body.flow-mode .flow-view:not(.view-home) .section-content {
    min-height: 100vh;
    min-height: 100svh;
    padding: calc(var(--head-h) + 22px) clamp(16px, 2.5vw, 28px) 64px clamp(20px, 4vw, 48px);
  }

  /* The hero rarely fits a landscape phone's height; let home scroll. */
  body.flow-mode .view-home {
    overflow-y: auto;
    scrollbar-gutter: stable;
  }

  body.flow-mode .view-home .section-content {
    width: 54vw;
    height: auto;
    min-height: 100vh;
    min-height: 100svh;
    padding: calc(var(--head-h) + 14px) 0 44px clamp(20px, 4vw, 48px);
  }

  .hero-line { font-size: clamp(32px, 5.6vw, 52px); }
  .hero-qualifier { font-size: clamp(17px, 2.4vw, 24px); }
  .hero-intro { margin-top: 16px; }
  .hero-actions { margin-top: 18px; gap: 10px; }
  .hero-actions .btn { padding: 11px 18px; font-size: 13.5px; white-space: nowrap; }

  /* The 54vw rail is narrower than the 700px breakpoint assumes wide
     viewports to be; stack the wide card internals just like small screens. */
  .portfolio-card { padding: 18px; }
  .portfolio-head { flex-direction: column; gap: 0; }
  .portfolio-head .btn-small { align-self: flex-start; }

  .theme-project { grid-template-columns: 1fr; padding: 0; }
  .theme-shot { min-height: 0; aspect-ratio: 16 / 10; }
  .theme-copy { padding: 22px 18px; }

  .integration-board { grid-template-columns: 1fr 1fr; }
  .integration-board .integration-core { grid-column: 1 / -1; }
  .integration-proof { grid-template-columns: 1fr; gap: 22px; padding: 20px; }
  .integration-proof-logo { min-height: 132px; }
}

/* ============================================================
   Measured mobile hero
   Mobile deliberately uses one focused paragraph. main.js measures that
   reduced composition and scales it only on unusually constrained screens.
   These rules come last so stacked and landscape-handheld modes share the
   same one-viewport contract and open 1.6 body rhythm.
   ============================================================ */

@media (max-width: 1100px) {
  body.flow-mode .view-home {
    overflow: hidden;
    scrollbar-gutter: auto;
  }

  body.flow-mode .view-home .section-content {
    width: 100%;
    height: 100vh;
    height: 100svh;
    min-height: 0;
    overflow: hidden;
    padding: var(--hero-model-band, 56.5svh) clamp(20px, 4.5vw, 44px) 22px;
  }

  body.flow-mode .view-home .hero-copy {
    width: 100%;
    max-width: none;
  }

  body.flow-mode .view-home .hero-line {
    max-width: none;
    margin: 0;
    overflow: visible;
    font-size: var(--hero-heading-size, clamp(31px, 9.5vw, 52px));
    line-height: 1.02;
    white-space: nowrap;
  }

  body.flow-mode .view-home .hero-qualifier {
    margin: 8px 0 0 2px;
    font-size: var(--hero-qualifier-size, clamp(18px, 4.8vw, 25px));
    line-height: 1.25;
  }

  body.flow-mode .view-home .hero-intro {
    max-width: none;
    margin: var(--hero-primary-gap, 19px) 0 0 2px;
    color: var(--grey);
    font-size: var(--hero-body-size, 16px);
    /* Match the normal site blurb rhythm at every fit state. Text may become
       smaller as the final fallback, but its leading is never compressed. */
    line-height: 1.6;
  }

  /* The supporting credibility paragraph remains part of the desktop hero,
     but mobile gets one focused blurb with room to breathe. */
  body.flow-mode .view-home .hero-intro-secondary { display: none; }

  body.flow-mode .view-home .hero-actions {
    flex-wrap: nowrap;
    gap: var(--hero-actions-gap, 11px);
    margin: var(--hero-actions-top, 21px) 0 0 2px;
  }

  body.flow-mode .view-home .hero-actions .btn {
    padding: var(--hero-button-y, 11.5px) var(--hero-button-x, 18px);
    font-size: var(--hero-button-font, 14px);
    line-height: 1.2;
    white-space: nowrap;
  }

}

@media (max-width: 1100px) and (min-width: 521px) and (max-aspect-ratio: 5/4) {
  body.flow-mode .view-home .section-content {
    padding-top: var(--hero-model-band, 58svh);
  }
}

@media (max-width: 1100px) and (min-aspect-ratio: 5/4) {
  body.flow-mode .view-home .section-content {
    width: 54vw;
    height: 100vh;
    height: 100svh;
    min-height: 0;
    padding: calc(var(--head-h) + 12px + 10svh) 0 20px clamp(20px, 4vw, 48px);
  }
}

@media (max-width: 1100px) and (min-aspect-ratio: 5/4) and (max-height: 359px) {
  body.flow-mode .view-home .section-content {
    padding-top: calc(var(--head-h) + 12px + 2.5svh);
  }
}
