/* Kanit + JetBrains Mono are enqueued by the plugin (erf-kanit / erf-jetbrains-mono
   handles in erf-studio-widgets.php), not imported here, so they share one
   request with the Kit's font loading instead of double-fetching Kanit. */

:root {
  --erf-white:  #ffffff;
  --erf-dark:   #1d1e18;
  --erf-accent: #ffffff;
  --erf-ease:   cubic-bezier(0.65, 0, 0.35, 1);
  /* Erf System motion — one easing curve, two duration registers (shared with ERF Kit):
     fast for chrome/controls, slow for editorial media/hero reveals. */
  --erf-fast:   0.15s;
  --erf-slow:   0.6s;
  /* the one ratified live-signal accent — data glows, chrome never does */
  --erf-phos:   #38ff70;
  --erf-display: 'Kanit', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  --erf-mono:   'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
}


/* ══════════════════════════════════════════════════════
   1. LIGHTBOX GRID
   ══════════════════════════════════════════════════════ */

.erf-lg-wrap { width: 100%; }
.erf-lg-grid { display: grid; grid-template-columns: repeat(var(--erf-cols, 3), 1fr); gap: 6px; align-items: start; }
/* The cell ratio lives on the IMG, not the cell: an aspect-ratio cell inside
   a stretch-aligned grid track can end up shorter than its own track (the
   track sizes from the image's contribution), exposing page-background bars
   under every row. Sizing the img directly makes cell = track = image. */
.erf-lg-item { position: relative; overflow: hidden; cursor: pointer; border: none; padding: 0; margin: 0; background: #111; display: block; width: 100%; }
.erf-lg-item img { width: 100%; height: auto; aspect-ratio: var(--erf-ratio, 1); object-fit: cover; display: block; -webkit-user-drag: none; user-select: none; transition: transform 0.6s var(--erf-ease); }
.erf-lg-grid[style*="--erf-ratio:0"] .erf-lg-item img { aspect-ratio: auto; }
/* "Auto height" (ratio:0): height:100% has nothing to be a percentage OF once
   aspect-ratio:auto removes the item's own explicit sizing — that circular
   reference resolves to 0 in most engines, collapsing the whole grid. Let the
   image's own intrinsic size drive the box instead. */
.erf-lg-grid[style*="--erf-ratio:0"] .erf-lg-item img { height: auto; }
/* Collage: justified rows. Each item's flex-grow AND flex-basis are
   proportional to its aspect ratio, so every item in a wrapped row resolves
   to the same height while keeping its own ratio: horizontals and verticals
   sit flush, nothing is cropped, the row fills the width exactly. The
   ::after filler soaks up slack on the final row so a short last row stays
   near the target height instead of stretching to fill. */
.erf-clg { display: flex; flex-wrap: wrap; gap: var(--erf-clg-gap, 6px); width: 100%; }
/* longhands on purpose: the flex shorthand drops a calc() basis in some
   engines, collapsing every item to 0 */
.erf-clg .erf-clg-item { flex-grow: calc(var(--r, 1.5) * 100); flex-shrink: 1; flex-basis: calc(var(--r, 1.5) * var(--erf-clg-h, 300px)); aspect-ratio: var(--r, 1.5); width: auto; min-width: 0; }
.erf-clg .erf-clg-item img { width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; }
.erf-clg::after { content: ''; flex: 999999 1 0%; }
/* Narrow screens: the basis must shrink with the viewport or every landscape
   frame demands more than half the row and stacks 1-up. 30vw keeps two
   landscapes (2 x 45vw) or three-plus verticals per row on a phone. */
@media (max-width: 1024px) { .erf-clg .erf-clg-item { flex-basis: calc(var(--r, 1.5) * min(var(--erf-clg-h, 300px), 30vw)); } }
.erf-lg-hover--scale .erf-lg-item:hover img  { transform: scale(1.05); }
.erf-lg-hover--darken .erf-lg-item:hover img { filter: brightness(0.75); }
.erf-lg-hover-veil { position: absolute; inset: 0; pointer-events: none; }
@media (max-width: 900px) { .erf-lg-grid { grid-template-columns: repeat(2, 1fr); } }
#erf-lightbox { position: fixed; inset: 0; z-index: 999999; display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; }
#erf-lightbox.is-open { opacity: 1; pointer-events: all; }
/* zoom controls, shared by every widget that opens a photo */
#erf-lightbox .erf-lb-img { margin: auto; cursor: zoom-in; transition: max-height 0.2s ease, max-width 0.2s ease; }
#erf-lightbox.is-zoomed .erf-lb-stage { overflow: auto; width: 100vw; height: 100vh; }
#erf-lightbox.is-zoomed .erf-lb-img-wrap { display: block; }
#erf-lightbox .erf-lb-zoom { position: absolute; bottom: 1.4rem; right: 1.6rem; z-index: 10;
  display: flex; align-items: center; gap: 2px; font-family: var(--erf-mono,'JetBrains Mono',monospace); }
#erf-lightbox .erf-lb-zoom button { width: 34px; height: 32px; border: 1px solid rgba(255,255,255,0.28);
  background: rgba(0,0,0,0.5); color: #fff; font-size: 14px; line-height: 1; cursor: pointer; transition: 0.15s; }
#erf-lightbox .erf-lb-zoom button:hover { border-color: #fff; }
#erf-lightbox .erf-lb-zlvl { min-width: 52px; text-align: center; font-size: 10px; letter-spacing: 1.5px;
  color: rgba(255,255,255,0.55); font-variant-numeric: tabular-nums; }
.erf-lb-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.93); cursor: pointer; }
.erf-lb-stage { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; max-width: 90vw; max-height: 90vh; user-select: none; -webkit-user-select: none; }
.erf-lb-img-wrap { position: relative; line-height: 0; }
.erf-lb-img-wrap::after { content: ''; position: absolute; inset: 0; z-index: 1; }
.erf-lb-img { display: block; max-width: 90vw; max-height: 85vh; object-fit: contain; -webkit-user-drag: none; user-select: none; pointer-events: none; }
.erf-lb-caption { margin-top: 0.7rem; color: rgba(255,255,255,0.5); font-size: 0.6875rem; letter-spacing: 0.1em; text-transform: uppercase; font-family: var(--erf-mono); text-align: center; }
.erf-lb-counter { position: fixed; bottom: 1.4rem; left: 50%; transform: translateX(-50%); color: rgba(255,255,255,0.35); font-size: 0.6875rem; font-family: var(--erf-mono); letter-spacing: 0.15em; pointer-events: none; }
.erf-lb-close { position: fixed; top: 1.4rem; right: 1.6rem; z-index: 2; width: 2.2rem; height: 2.2rem; background: transparent; border: 1px solid rgba(255,255,255,0.3); color: rgba(255,255,255,0.7); cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 0.9rem; transition: background 0.25s; }
.erf-lb-close:hover { background: rgba(255,255,255,0.08); border-color: #fff; color: #fff; }
.erf-lb-nav { position: fixed; top: 50%; transform: translateY(-50%); z-index: 2; background: transparent; border: none; color: rgba(255,255,255,0.6); font-size: 2.4rem; cursor: pointer; padding: 0.5rem 1.2rem; transition: color 0.25s; line-height: 1; }
.erf-lb-nav:hover { color: #fff; }
.erf-lb-prev { left: 0.6rem; }
.erf-lb-next { right: 0.6rem; }
.erf-lb-nav:disabled { opacity: 0.2; cursor: default; }


/* ══════════════════════════════════════════════════════
   2. CLEAN SLIDESHOW
   ══════════════════════════════════════════════════════ */

.erf-cs-wrap { position: relative; width: 100%; height: 55vh; overflow: hidden; background: #0a0a0a; }
/* Each link needs an EXPLICIT height, not just inset:0 — a box positioned
   purely via top/bottom:0 renders at the right size itself, but per spec
   doesn't reliably count as a definite-height containing block for ITS OWN
   absolutely-positioned children. Two inset-only links in a row (track,
   slide) broke percentage resolution one level further down at the media
   image, collapsing it to 0 despite every ancestor rendering correctly. */
.erf-cs-track { position: absolute; inset: 0; height: 100%; }
.erf-cs-slide { position: absolute; inset: 0; height: 100%; opacity: 0; transition: opacity var(--erf-trans, 900ms) ease; will-change: opacity; }
.erf-cs-slide.erf-cs-active { opacity: 1; }
.erf-cs-media { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; -webkit-user-drag: none; }
.erf-cs-empty { background: #111; }
.erf-cs-btn { position: absolute; top: 50%; transform: translateY(-50%); z-index: 10; background: transparent; border: none; color: #ffffff; font-size: 22px; cursor: pointer; padding: 1.2rem 1rem; line-height: 1; opacity: 0.6; transition: opacity 0.25s; }
.erf-cs-btn:hover { opacity: 1; }
.erf-cs-prev { left: 0.8rem; }
.erf-cs-next { right: 0.8rem; }
@media (max-width: 600px) { .erf-cs-wrap { height: 38vh; } .erf-cs-btn { font-size: 1.4rem; padding: 0.8rem 0.6rem; } }


/* ══════════════════════════════════════════════════════
   3. PORTFOLIO BANNERS
   CSS Grid (not flex) for reliable equal columns in Elementor.
   White gap. Text BOTTOM LEFT on hover.
   ══════════════════════════════════════════════════════ */

/* Outer column grid — white gap shows between rows */
.erf-pb-wrap {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  background: #000000;
  width: 100%;
}

/* Side-by-side row — two equal columns */
.erf-pb-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  background: #000000;
}

/* Every panel — same height regardless of full/half */
.erf-pb-item {
  display: block;
  width: 100%;
  height: 50vh;
  position: relative;
  overflow: hidden;
  background: #000;
}

/* Inner <a> pinned to all four edges of the panel */
.erf-pb-inner {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  text-decoration: none;
  overflow: hidden;
}

/* Cover image */
.erf-pb-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-size: cover;
  background-position: center;
  z-index: 1;
  transition: transform 0.9s var(--erf-ease);
}
.erf-pb-item:hover .erf-pb-bg { transform: scale(1.03); }

/* Hover video */
.erf-pb-video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 2;
  opacity: 0;
  transition: opacity 0.4s ease;
}
/* video no longer plays on the card; it plays inside the project on click */
.erf-pb-video { display: none; }
.erf-pb-sub { display: block; font-family: var(--erf-mono,'JetBrains Mono',monospace); font-size: 0.625rem; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(255,255,255,0.6); margin-top: 0.5rem; }

/* ── Text: BOTTOM LEFT ── */
/* A scrim only where the type sits. A pale cover (the Blackmail newsprint grey)
   left white text unreadable and the mono label invisible, but veiling the whole
   image to fix it dulls every frame. This grounds the bottom third and leaves
   the picture alone. */
.erf-pb-inner::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 62%;
  background: linear-gradient(to top, rgba(0,0,0,.78) 0%, rgba(0,0,0,.42) 34%, rgba(0,0,0,0) 100%);
  pointer-events: none; z-index: 1;
}
/* the filter row: plain words, no boxes, active one underlined */
/* The reel is the first widget on /work/ and the site header is fixed, so the
   filter row landed underneath it and the tags collided with the logo. Clear
   the measured header height, and carry a solid ground so nothing shows
   through behind it. */
.erf-pb-filter {
  display: flex; flex-wrap: wrap; gap: 26px;
  padding: calc(var(--erf-hdr-h, 72px) + 1.5rem) 4vw 1.5rem;
  background: #000;
}
/* When the page masthead sits above the reel, the masthead clears the fixed
   header, so the filter's own clearance would stack into dead air. */
.elementor-element:has(.erf-pm) ~ .elementor-element .erf-pb-filter {
  padding-top: 1.5rem;
}
.erf-pb-filter button {
  background: none; border: 0; padding: 0 0 4px; cursor: pointer;
  font-family: var(--erf-mono); font-size: 11px; letter-spacing: 0.19em;
  text-transform: uppercase; color: rgba(255,255,255,0.5);
  border-bottom: 1px solid transparent;
  transition: color 0.22s ease, border-color 0.22s ease;
}
.erf-pb-filter button:hover { color: #fff; }
/* how many matched, so pressing a filter always reads as an event even when
   the top project carries every discipline and never moves */
.erf-pb-count {
  margin-left: auto; align-self: center;
  font-family: var(--erf-mono); font-size: 10px; font-weight: 300;
  letter-spacing: 0.2em; color: rgba(237,237,234,0.35);
  font-variant-numeric: tabular-nums;
}
@keyframes erfPbIn {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .erf-pb-item { animation: none !important; }
}
.erf-pb-filter button.is-on { color: #fff; border-bottom-color: #fff; }
.erf-pb-item[hidden], .erf-pb-row[hidden] { display: none !important; }
@media (max-width: 640px) {
  .erf-pb-filter { gap: 18px; padding-bottom: 1.1rem; }
  .erf-pb-filter button { font-size: 10px; }
}

.erf-pb-content {
  position: absolute;
  top: auto;
  right: auto;
  bottom: 4vw;
  left: 4vw;
  z-index: 10;
  pointer-events: none;
}

/* ═══════════════════════════════════════════════════════
   FULL-BLEED ALL ERF CONTENT WIDGETS
   Every ERF widget breaks out to true viewport width at the
   .elementor-widget- level (which always exists — no :has()
   needed). This guarantees every widget's internal 4vw padding
   is measured from the SAME reference: the true viewport edge.
   Result: hero title, portfolio title, about hero, services,
   content block, and contact form all align at exactly 4vw.
   ═══════════════════════════════════════════════════════ */
.elementor-widget-erf_hero,
.elementor-widget-erf_portfolio_reel,
.elementor-widget-erf_contact_form,
.elementor-widget-erf_about_hero,
.elementor-widget-erf_services_grid,
.elementor-widget-erf_content_block,
.elementor-widget-erf_split_section,
.elementor-widget-erf_page_hero,
.elementor-widget-erf_photo_fade,
.elementor-widget-erf_contact_links {
  width: 100vw !important;
  max-width: 100vw !important;
  position: relative !important;
  top: auto !important;
  left: 50% !important;
  right: 50% !important;
  margin-left: -50vw !important;
  margin-right: -50vw !important;
  padding: 0 !important;
}

/* Prevent split section's parent from creating a stacking context that causes overlap */
.elementor-section:has(.elementor-widget-erf_split_section),
.e-con:has(.elementor-widget-erf_split_section) {
  overflow: visible !important;
  position: static !important;
}
.elementor-widget-erf_hero > .elementor-widget-container,
.elementor-widget-erf_portfolio_reel > .elementor-widget-container,
.elementor-widget-erf_contact_form > .elementor-widget-container,
.elementor-widget-erf_about_hero > .elementor-widget-container,
.elementor-widget-erf_services_grid > .elementor-widget-container,
.elementor-widget-erf_content_block > .elementor-widget-container,
.elementor-widget-erf_split_section > .elementor-widget-container,
.elementor-widget-erf_page_hero > .elementor-widget-container,
.elementor-widget-erf_photo_fade > .elementor-widget-container,
.elementor-widget-erf_contact_links > .elementor-widget-container {
  padding: 0 !important;
  margin: 0 !important;
  width: 100% !important;
}

/* Footer: container-safe. No viewport breakout (it can be nested
   in containers/columns where -50vw would throw it off-screen).
   It fills its parent and uses its own 4vw internal padding. */
.elementor-widget-erf_footer {
  width: 100% !important;
  max-width: 100% !important;
}
.elementor-widget-erf_footer > .elementor-widget-container {
  padding: 0 !important;
  margin: 0 !important;
  width: 100% !important;
}

.erf-pb-type {
  display: block;
  font-family: var(--erf-mono);
  font-size: 0.625rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  margin-bottom: 6px;
  opacity: 0;
  transition: opacity var(--erf-fast) ease;
}

.erf-pb-title {
  display: block;
  font-family: 'Kanit', sans-serif;
  font-weight: 200;
  letter-spacing: -0.01em;
  line-height: 1;
  color: #ffffff;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.erf-pb-title { font-size: clamp(1.4rem, 2.6vw, 3.8rem); }

.erf-pb-item:hover .erf-pb-title,
.erf-pb-item:hover .erf-pb-type { opacity: 1; }

@media (hover: none) {
  .erf-pb-title, .erf-pb-type { opacity: 1; }
}

@media (max-width: 767px) {
  /* Stack side-by-side rows into single column */
  .erf-pb-row { grid-template-columns: 1fr !important; gap: 4px; }

  /* 16:9 aspect ratio — matches altcinc mobile exactly */
  .erf-pb-item { height: 56.25vw !important; min-height: 180px; }

  /* Title always visible on mobile (no hover on touch) */
  .erf-pb-title { font-size: 5.5vw !important; opacity: 1 !important; }
  .erf-pb-type  { font-size: 10px !important; opacity: 1 !important; letter-spacing: 0.15em; }
  .erf-pb-content { left: 1.5rem; bottom: 1.5rem; }

  /* Remove gap to be edge-to-edge */
  .erf-pb-wrap { gap: 4px; }
}


/* ══════════════════════════════════════════════════════
   4. HERO WIDGET
   ══════════════════════════════════════════════════════ */

.erf-hero-wrap {
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  background: #000;
  display: flex;
  align-items: flex-end;
}

.erf-hero-video {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 1;
}

.erf-hero-bg {
  /* sits BEHIND the video (fallback only) — equal z-index with later DOM
     order previously put this permanently on top, hiding the video entirely
     whenever a fallback image was set */
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background-size: cover;
  background-position: center;
  z-index: 0;
}

.erf-hero-overlay {
  /* Darken only enough for the overlay header (logo/nav) to stay legible,
     then fade out — a flat tint across the whole hero reads as a solid dark
     band on pale/overcast footage, especially right where the header sits. */
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background: linear-gradient(to bottom, #000 0%, transparent 220px);
  opacity: 0.45;
  z-index: 1;
}

/* Logo mark + studio name — top left */
.erf-hero-brand {
  position: absolute;
  top: 1.8rem;
  left: 2.5rem;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 12px;
}
/* When instrument chrome is present, drop the brand mark below the top rail. */
.erf-hero-wrap:has(.erf-inst) .erf-hero-brand { top: 3.6rem; }

.erf-hero-brand-name {
  font-family: var(--erf-mono);
  font-size: 0.625rem;
  font-weight: 300;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.38);
}

/* Main content — bottom left */
.erf-hero-content {
  position: relative;
  z-index: 10;
  padding: 0 4vw 4vw;
  max-width: 860px;
}

.erf-hero-eyebrow {
  display: block;
  font-family: var(--erf-mono);
  font-size: 0.625rem;
  font-weight: 300;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #ffffff;
  margin-bottom: 1rem;
}

.erf-hero-title {
  font-family: 'Kanit', sans-serif;
  font-size: clamp(2.8rem, 8vw, 9rem);
  font-weight: 500;
  color: #ffffff;
  line-height: 1;
  letter-spacing: -0.025em;
  margin: 0 0 1.2rem;
}

.erf-hero-accent {
  font-style: normal;
  color: #ffffff;
}

.erf-hero-sub {
  font-family: var(--erf-mono);
  font-size: 0.75rem;
  font-weight: 300;
  color: rgba(255,255,255,0.38);
  letter-spacing: 0.05em;
  margin-bottom: 1.8rem;
}

.erf-hero-cta-row {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  flex-wrap: wrap;
}

.erf-hero-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--erf-mono);
  /* Reads the widget's own "CTA Size" Elementor control, which now writes
     --erf-cta-size on the wrapper (see hero.php) instead of font-size
     directly. A custom property inherits down to here regardless of which
     ancestor sets it, so there's no specificity fight and no !important
     needed anywhere in this file. 0.68rem is the fallback if the control is
     ever absent, matching this rule's own long-standing default. */
  font-size: var(--erf-cta-size, 0.6875rem);
  font-weight: 300;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: #ffffff;
  text-decoration: none;
  border: 1px solid rgba(255,255,255,0.45);
  padding: 0.85rem 2.5rem;
  transition: border-color 0.25s, background 0.25s, color 0.25s;
}
.erf-hero-cta:hover {
  border-color: #ffffff;
  background: #ffffff;
  color: #1d1e18;
}
.erf-hero-cta:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 3px;
}
/* Two buttons together read wider than one. Scaled down from whatever the
   CTA Size control is actually set to (not a hardcoded absolute value), so
   changing that control still affects the "both visible" state, just
   proportionally: 65% reproduces the size that was actually confirmed
   correct on this page's real saved value (1rem -> 0.65rem). */
.erf-hero-cta-row-both .erf-hero-cta {
  padding: 0.8rem 2rem;
  font-size: calc(var(--erf-cta-size, 0.6875rem) * 0.65);
}

/* Scroll indicator — bottom right */
.erf-hero-scroll {
  position: absolute;
  right: 2.5rem;
  bottom: 2.2rem;
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.erf-hero-scroll-label {
  font-family: var(--erf-mono);
  font-size: 0.625rem;
  font-weight: 300;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.2);
  writing-mode: vertical-rl;
}

.erf-hero-scroll-track {
  display: block;
  width: 1px;
  height: 44px;
  background: rgba(255,255,255,0.1);
  position: relative;
  overflow: hidden;
}

.erf-hero-scroll-fill {
  display: block;
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 40%;
  background: #ffffff;
  animation: erfHeroScroll 2s ease-in-out infinite;
}

@keyframes erfHeroScroll {
  0%   { transform: translateY(-100%); }
  100% { transform: translateY(350%); }
}

@media (max-width: 600px) {
  .erf-hero-title { font-size: clamp(2rem, 12vw, 4rem); }
  .erf-hero-content { padding: 0 1.5rem 3rem; }
  .erf-hero-scroll  { display: none; }
}


/* ══════════════════════════════════════════════════════
   5. CONTACT FORM WIDGET
   ══════════════════════════════════════════════════════ */

.erf-cf-wrap {
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}

.erf-cf-intro {
  font-family: 'Kanit', sans-serif;
  font-size: clamp(1.4rem, 3vw, 2.4rem);
  font-weight: 200;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin-bottom: 3rem;
}

/* Dark scheme */
.erf-cf--dark .erf-cf-intro { color: #ffffff; }
.erf-cf--dark .erf-cf-label { color: rgba(255,255,255,0.4); }
.erf-cf--dark .erf-cf-input { color: #ffffff; border-bottom-color: rgba(255,255,255,0.15); }
.erf-cf--dark .erf-cf-input::placeholder { color: rgba(255,255,255,0.18); }
.erf-cf--dark .erf-cf-select option { background: #000; color: #fff; }

/* Light scheme */
.erf-cf--light .erf-cf-intro { color: #1d1e18; }
.erf-cf--light .erf-cf-label { color: rgba(0,0,0,0.4); }
.erf-cf--light .erf-cf-input { color: #1d1e18; border-bottom-color: rgba(0,0,0,0.15); }
.erf-cf--light .erf-cf-input::placeholder { color: rgba(0,0,0,0.2); }

/* Form layout */
.erf-cf-form  { display: flex; flex-direction: column; gap: 2rem; }

.erf-cf-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
}

.erf-cf-field { display: flex; flex-direction: column; gap: 0.5rem; }

.erf-cf-label {
  font-family: 'Kanit', sans-serif;
  font-size: 0.625rem;
  font-weight: 300;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.erf-cf-req { font-size: 0.6875rem; }

.erf-cf-input {
  background: transparent;
  border: none;
  border-bottom: 1px solid;
  padding: 0.6rem 0;
  font-family: 'Kanit', sans-serif;
  font-size: 1rem;
  font-weight: 300;
  outline: none;
  width: 100%;
  transition: border-bottom-color 0.2s;
  border-radius: 0;
  appearance: none;
  -webkit-appearance: none;
}

.erf-cf-select {
  cursor: pointer;
  padding-right: 1.2rem;
}

.erf-cf-textarea { resize: vertical; min-height: 130px; }

.erf-cf-footer {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.erf-cf-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  background: transparent;
  border: 1px solid #ffffff;
  color: #ffffff;
  font-family: 'Kanit', sans-serif;
  font-size: 0.6875rem;
  font-weight: 300;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.75rem 1.6rem;
  cursor: pointer;
  transition: background 0.25s, color 0.25s;
}
.erf-cf-btn:hover { background: #ffffff; color: #1d1e18; }
.erf-cf-btn:disabled { opacity: 0.5; cursor: default; }

.erf-cf-btn-arrow { transition: transform 0.25s; }
.erf-cf-btn:hover .erf-cf-btn-arrow { transform: translateX(4px); }

.erf-cf-status {
  font-family: 'Kanit', sans-serif;
  font-size: 0.75rem;
  font-weight: 300;
  min-height: 1.2em;
}
.erf-cf-status--ok  { color: rgba(255,255,255,0.9); letter-spacing: 0.08em; }
.erf-cf-status--err { color: #e74c3c; }

@media (max-width: 600px) {
  .erf-cf-row { grid-template-columns: 1fr; }
}


/* ══════════════════════════════════════════════════════
   Smooth scroll (all anchor links)
   ══════════════════════════════════════════════════════ */
html { scroll-behavior: smooth; }




/* ══════════════════════════════════════════════════════
   6. SPLIT SECTION
   ══════════════════════════════════════════════════════ */

.erf-sps-heading {
  /* Fallback only — the widget's own "Color" control (default #ffffff)
     normally overrides this per-instance. #1d1e18 here read as near-invisible
     dark text on this widget's black background whenever that per-instance
     rule was momentarily missing (e.g. a stale Elementor CSS cache). */
  font-family: 'Kanit', sans-serif !important;
  font-size: 4vw;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: #ffffff;
  margin: 0;
}

.erf-sps-body {
  font-family: 'Kanit', sans-serif !important;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.75;
  color: #b8b8b0;
  margin: 0 0 2rem;
}

.erf-sps-link {
  font-family: 'Kanit', sans-serif !important;
  font-size: 0.8125rem;
  font-weight: 300;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #1d1e18;
  text-decoration: none !important;
  border-bottom: 1px solid transparent !important;
  padding-bottom: 2px;
  display: inline-block;
  transition: border-color 0.25s ease !important;
}

.erf-sps-link:hover {
  border-bottom-color: currentColor !important;
}

/* Fade image into page background at top and bottom edges */
.erf-sps-image-block {
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    black 22%,
    black 78%,
    transparent 100%
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    black 22%,
    black 78%,
    transparent 100%
  );
}

@media (max-width: 960px) {
  .erf-sps-heading { font-size: 9vw; }
}


/* ══════════════════════════════════════════════════════
   Portfolio CTA button
   ══════════════════════════════════════════════════════ */
.erf-pb-cta-wrap {
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 4vw;
  border-top: 1px solid rgba(255,255,255,0.08);
}

.erf-pb-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  font-family: var(--erf-mono);
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #ffffff;
  text-decoration: none;
  border: 1px solid rgba(255,255,255,0.4);
  padding: 0.85rem 2.5rem;
  transition: border-color var(--erf-fast) var(--erf-ease), background var(--erf-fast) var(--erf-ease), color var(--erf-fast) var(--erf-ease);
}

.erf-pb-cta:hover {
  border-color: #ffffff;
  background: #ffffff;
  color: #1d1e18;
}

.erf-pb-cta-arrow {
  transition: transform 0.25s;
}
.erf-pb-cta:hover .erf-pb-cta-arrow {
  transform: translateX(4px);
}


/* ══════════════════════════════════════════════════════
   Footer Widget
   ══════════════════════════════════════════════════════ */
.erf-fw-wrap {
  padding: 2.5rem 4vw 2rem;
  background-color: #f5f5f0;
  font-family: 'Kanit', sans-serif;
}

.erf-fw-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 2rem;
}

.erf-fw-label {
  font-family: 'Kanit', sans-serif;
  font-size: 0.625rem;
  font-weight: 300;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(0,0,0,0.35);
  margin: 0 0 0.7rem;
}

.erf-fw-rule {
  height: 1px;
  background: rgba(0,0,0,0.12);
  margin-bottom: 1.2rem;
}

.erf-fw-copy {
  font-family: 'Kanit', sans-serif;
  font-size: 0.8125rem;
  font-weight: 500;
  color: #1d1e18;
  margin: 0;
  letter-spacing: 0.04em;
}

.erf-fw-link {
  font-family: 'Kanit', sans-serif;
  font-size: 0.8125rem;
  font-weight: 500;
  color: #1d1e18;
  text-decoration: none;
  letter-spacing: 0.04em;
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  transition: border-color 0.2s;
}
.erf-fw-link:hover { border-bottom-color: currentColor; }

.erf-fw-social {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.erf-fw-social-link {
  font-family: 'Kanit', sans-serif;
  font-size: 0.8125rem;
  font-weight: 500;
  color: #1d1e18;
  text-decoration: none;
  letter-spacing: 0.04em;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s;
  align-self: flex-start;
}
.erf-fw-social-link:hover { border-bottom-color: currentColor; }

@media (max-width: 600px) {
  .erf-fw-grid { grid-template-columns: 1fr; gap: 1.5rem; }
}


/* ══════════════════════════════════════════════════════
   Hero title — glitch hover effect
   ══════════════════════════════════════════════════════ */

.erf-hero-title { cursor: default; }

.erf-hero-title:hover {
  animation: erf-glitch 2.5s infinite;
}

@keyframes erf-glitch {
  0%, 84%, 94%, 100% {
    transform: none;
    text-shadow: none;
    filter: none;
  }

  /* Burst 1 */
  85% {
    transform: translateX(-4px);
    text-shadow: 3px 0 rgba(255, 255, 255, 0.75), -2px 0 rgba(255, 255, 255, 0.55);
    filter: brightness(1.12);
  }
  86% {
    transform: translateX(4px) skewX(-1.5deg);
    text-shadow: -3px 0 rgba(255, 255, 255, 0.6), 2px 0 rgba(255, 255, 255, 0.45);
    filter: contrast(1.15);
  }
  87% {
    transform: translateX(-2px) skewX(0.8deg);
    text-shadow: 1px 0 rgba(255, 255, 255, 0.4);
    filter: none;
  }
  88% {
    transform: none;
    text-shadow: none;
  }

  /* Burst 2 — shorter, offset */
  90% {
    transform: translateX(3px);
    text-shadow: -2px 0 rgba(255, 255, 255, 0.5), 2px 0 rgba(255, 255, 255, 0.35);
    filter: brightness(1.08) saturate(1.4);
  }
  91% {
    transform: translateX(-1px) skewX(1deg);
    filter: none;
  }
  92% {
    transform: none;
    text-shadow: none;
  }
}


/* ══════════════════════════════════════════════════════
   MOBILE FIXES
   ══════════════════════════════════════════════════════ */

/* Hero title — much larger on mobile */
@media (max-width: 767px) {
  .erf-hero-title {
    font-size: 11vw !important;
    line-height: 1.05 !important;
  }
  .erf-hero-content {
    padding: 0 1.5rem 3rem !important;
  }
  /* Ensure hero starts at very top on mobile */
  .erf-hero-wrap {
    min-height: 100svh;
  }
}

/* Video player — prevent parent clipping on mobile */
.elementor-widget-erf_video_player,
.elementor-widget-erf_video_player > .elementor-widget-container {
  overflow: visible !important;
  height: auto !important;
}

/* Split section — prevent image bleeding out on mobile */
@media (max-width: 768px) {
  .erf-sps-wrap {
    overflow: hidden !important;
  }
  .erf-sps-center {
    overflow: hidden !important;
  }
}


/* ══════════════════════════════════════════════════════
   ELEMENTOR WIDGET CONTAINER RESETS
   Zero out default padding Elementor adds inside widgets,
   so each widget controls its own spacing consistently.
   ══════════════════════════════════════════════════════ */
.elementor-widget-erf_contact_form > .elementor-widget-container,
.elementor-widget-erf_about_hero > .elementor-widget-container,
.elementor-widget-erf_services_grid > .elementor-widget-container,
.elementor-widget-erf_content_block > .elementor-widget-container,
.elementor-widget-erf_split_section > .elementor-widget-container,
.elementor-widget-erf_portfolio_reel > .elementor-widget-container,
.elementor-widget-erf_photo_fade > .elementor-widget-container,
.elementor-widget-erf_page_hero > .elementor-widget-container,
.elementor-widget-erf_contact_links > .elementor-widget-container,
.elementor-widget-erf_footer > .elementor-widget-container {
  padding: 0 !important;
  margin: 0 !important;
}


/* ══════════════════════════════════════════════════════
   GLOBAL SCROLL REVEAL SYSTEM — 2026
   ══════════════════════════════════════════════════════ */

/* Clip-path wipe: elements that reveal upward */
[data-erf-clip]{
  clip-path: inset(0 0 100% 0);
  will-change: clip-path;
}
[data-erf-clip].erf-in{
  clip-path: inset(0 0 0% 0);
  transition: clip-path 0.85s cubic-bezier(.16,1,.3,1);
}

/* Fade + rise: body text, subtitles */
[data-erf-up]{
  opacity:0;
  transform:translateY(22px);
  will-change:opacity,transform;
}
[data-erf-up].erf-in{
  opacity:1;
  transform:translateY(0);
  transition:opacity 0.7s ease, transform 0.7s cubic-bezier(.16,1,.3,1);
}

/* Horizontal rule scale-in */
[data-erf-rule]{
  transform:scaleX(0);
  transform-origin:left center;
  will-change:transform;
}
[data-erf-rule].erf-in{
  transform:scaleX(1);
  transition:transform 0.9s cubic-bezier(.16,1,.3,1);
}

/* Stagger delays (applied via data-erf-delay attribute in JS) */
.erf-d1{ transition-delay:0.08s !important; }
.erf-d2{ transition-delay:0.18s !important; }
.erf-d3{ transition-delay:0.28s !important; }
.erf-d4{ transition-delay:0.4s  !important; }


/* ══════════════════════════════════════════════════════
   BUTTON GLITCH — 2026
   Applied to all ERF CTAs on hover via a data attr
   ══════════════════════════════════════════════════════ */
@keyframes erf-glitch-1{
  0%  { clip-path:inset(30% 0 60% 0); transform:translateX(-3px); }
  20% { clip-path:inset(70% 0 5%  0); transform:translateX(3px);  }
  40% { clip-path:inset(5%  0 80% 0); transform:translateX(-2px); }
  60% { clip-path:inset(50% 0 30% 0); transform:translateX(2px);  }
  80% { clip-path:inset(15% 0 50% 0); transform:translateX(-1px); }
  100%{ clip-path:inset(0 0 0 0);     transform:translateX(0);     }
}
/* Short glitch burst on entry, then settle — applied via JS */
.erf-btn-glitch::before{
  content:attr(data-text);
  position:absolute;inset:0;
  display:flex;align-items:center;justify-content:center;
  pointer-events:none;
  opacity:0;
}
.erf-btn-glitch:hover::before{
  opacity:1;
  color:inherit;
  animation:erf-glitch-1 0.28s steps(1) forwards;
  mix-blend-mode:difference;
}


/* ═══════════════════════════════════════════════════════
   ELEMENTOR PADDING NULLIFIER
   Zeroes all Elementor section/container/column padding
   for any section containing an ERF widget.
   Ensures all widget text starts at exactly 4vw from 
   the true viewport edge — not 4vw + Elementor padding.
   ═══════════════════════════════════════════════════════ */

/* Old Elementor (section > container > row > column > widget-wrap) */
.elementor-section:has([class*="elementor-widget-erf_"]),
.elementor-top-section:has([class*="elementor-widget-erf_"]) {
    padding-left: 0 !important;
    padding-right: 0 !important;
}
.elementor-section:has([class*="elementor-widget-erf_"]) > .elementor-container {
    max-width: 100% !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
}
.elementor-section:has([class*="elementor-widget-erf_"]) .elementor-column {
    padding-left: 0 !important;
    padding-right: 0 !important;
}
.elementor-section:has([class*="elementor-widget-erf_"]) .elementor-widget-wrap {
    padding: 0 !important;
}
/* New Elementor flex containers */
.e-con:has([class*="elementor-widget-erf_"]),
.e-con-inner:has([class*="elementor-widget-erf_"]) {
    padding-left: 0 !important;
    padding-right: 0 !important;
    max-width: 100% !important;
    --padding-inline-start: 0px !important;
    --padding-inline-end: 0px !important;
}


/* ══════════════════════════════════════════════════════
   PORTFOLIO GRAYSCALE-SIBLINGS FEATURE
   When .erf-pb-wrap has [data-erf-gs="1"], hovering any
   item fades all OTHER items to black & white.
   Toggle via Elementor custom attribute: data-erf-gs = 1
   ══════════════════════════════════════════════════════ */

/* The blur RADIUS itself is animated (blur(0) -> blur(4px)), so the image
   genuinely softens over the transition — a real progressive blur, not an
   opacity crossfade of a pre-blurred copy (that reads as a blurry ghost
   dissolving in over the sharp image, never as "going soft").

   Two supporting pieces:
   - Static inset:-10px oversize: filter:blur() blurs the element's own alpha,
     so its edges go semi-transparent over ~blur-radius and the tile's black
     background shows through as a dark fringe. The bg extends 10px past the
     overflow:hidden crop on every side (> the blur spread), so that fringe is
     clipped away. It's static — present at rest and while blurred — so it
     never reads as a zoom.
   - will-change:filter promotes each dimmed tile to its own layer so an
     animating blur doesn't force siblings to re-rasterize. !important +
     higher specificity is needed to beat the nuclear will-change:auto block
     further down. */
.erf-pb-wrap[data-erf-gs="1"] .erf-pb-bg {
  inset: -10px;
  transition: filter 0.9s var(--erf-ease), transform 0.9s var(--erf-ease);
  will-change: filter !important;
}
.erf-pb-wrap[data-erf-gs="1"]:has(.erf-pb-item:hover) .erf-pb-item:not(:hover) .erf-pb-bg {
  filter: blur(4px) brightness(0.82);
}

/* No dimming on touch devices (no hover state) */
@media (hover: none) {
  .erf-pb-wrap[data-erf-gs="1"]:has(.erf-pb-item:hover) .erf-pb-item:not(:hover) .erf-pb-bg {
    filter: none;
  }
}

/* ══════════════════════════════════════════════════════
   CH.02 PAGE — clear the fixed header
   The CH.02 content mounts flush at the top (its own padding-top is 0) with a
   large title in the top-left, so it slid under the fixed header and the white
   ERF logo collided with the white "CH.02" title. Give the header a solid
   background on this page (not just after scroll) and drop the content below
   the 62px header so the title clears the logo. Scoped via :has(.ch02) so it
   only touches this page and needs no hardcoded page id.
   ══════════════════════════════════════════════════════ */
body:has(.ch02) header[id^="erfhdr"] { background: #000; }
.ch02 { padding-top: 86px; }


/* ══════════════════════════════════════════════════════
   MOBILE IMPROVEMENTS — 2026 PASS
   ══════════════════════════════════════════════════════ */

/* Hero — tighten eyebrow + sub on mobile */
@media (max-width: 600px) {
  .erf-hero-eyebrow { font-size: 0.625rem; letter-spacing: 0.18em; margin-bottom: 0.7rem; }
  .erf-hero-sub { font-size: 0.6875rem; }
  .erf-hero-cta { padding: 0.75rem 1.6rem; font-size: 0.625rem; }
  .erf-hero-cta-row { flex-direction: column; align-items: stretch; gap: 0.9rem; }
  .erf-hero-cta-row .erf-hero-cta { justify-content: center; }
  .erf-hero-brand { top: 1.2rem; left: 1.5rem; }
}

/* Contact form — full-width btn on mobile */
@media (max-width: 600px) {
  .erf-cf-wrap { padding: 0 1.5rem; }
  .erf-cf-btn { width: 100%; justify-content: center; padding: 1rem 1.6rem; }
  .erf-cf-footer { flex-direction: column; align-items: flex-start; gap: 1rem; }
  .erf-cf-status { font-size: 0.6875rem; }
}

/* Footer — already stacks on mobile, improve spacing */
@media (max-width: 600px) {
  .erf-fw-wrap { padding: 2rem 1.5rem 1.5rem; }
  .erf-fw-grid { gap: 2rem; }
}

/* Portfolio CTA — full width on mobile */
@media (max-width: 600px) {
  .erf-pb-cta-wrap { padding: 2rem 1.5rem; }
  .erf-pb-cta { width: 100%; justify-content: center; }
}

/* Split section heading — tighter on mobile */
@media (max-width: 600px) {
  .erf-sps-heading { font-size: 10vw !important; }
  .erf-sps-body { font-size: 0.95rem; }
}

/* About hero, page hero — ensure safe viewport units on mobile */
@media (max-width: 767px) {
  .erf-ph-wrap { min-height: 50svh; }
}

/* Lightbox — better touch targets on mobile */
@media (max-width: 600px) {
  .erf-lb-close { width: 2.8rem; height: 2.8rem; top: 0.8rem; right: 0.8rem; }
  .erf-lb-nav { font-size: 2rem; padding: 0.8rem 0.7rem; }
  .erf-lb-stage { max-width: 96vw; }
  .erf-lb-img { max-height: 78vh; }
}

/* Services grid — single column on small screens */
@media (max-width: 480px) {
  .erf-sg-grid { grid-template-columns: 1fr !important; }
}

/* Contact links — stack vertically, reduce font size on mobile */
@media (max-width: 600px) {
  .erf-cl-email { font-size: clamp(2rem, 12vw, 4rem) !important; }
}

/* Prevent horizontal scroll from full-bleed widgets on iOS */
body { overflow-x: hidden; }

/* Safe area padding for notched phones */
@supports (padding-bottom: env(safe-area-inset-bottom)) {
  .erf-hero-content { padding-bottom: calc(4vw + env(safe-area-inset-bottom)); }
  .erf-fw-wrap { padding-bottom: calc(2rem + env(safe-area-inset-bottom)); }
}

/* ══════════════════════════════════════════════════════
   CRITICAL MOBILE HEADER FIXES — v2
   ══════════════════════════════════════════════════════ */

/*
   The ERF header is position:fixed. On mobile the body needs
   padding-top so content doesn't hide behind it.
   JS sets --erf-hdr-h on <html> after measuring the header height.
   If JS hasn't run yet, 72px is a safe fallback.
*/
:root { --erf-hdr-h: 72px; }

/* Push page content below the fixed header — but NOT when the first section is the hero */
body > .elementor > .elementor-section:first-child:not(:has(.elementor-widget-erf_hero)),
body > div > .elementor > .elementor-section:first-child:not(:has(.elementor-widget-erf_hero)),
#page,
#content,
.site-main {
  padding-top: var(--erf-hdr-h, 72px) !important;
}

/* Exception: the header widget itself must NOT be pushed */
.elementor-widget-erf_header,
.elementor-widget-erf_header > .elementor-widget-container {
  padding-top: 0 !important;
  margin-top: 0 !important;
}

/* The header's visible bar is position:fixed, so its widget wrapper is a
   zero-height box. Inside an Elementor flex container that box still counts
   as a flex ITEM, so the container's 20px gap opened a blank strip between
   it and whatever comes next (the strip above every case-study hero).
   Absolute takes the wrapper out of flow; the fixed bar inside never cared
   where its wrapper sat. */
.e-con > .elementor-widget-erf_header,
.e-con-inner > .elementor-widget-erf_header {
  position: absolute;
}

/* Hero sits flush under the transparent fixed header — no offset needed */

/* On mobile, clamp the title size so it never bleeds into the header */
@media (max-width: 767px) {
  .erf-hero-title {
    font-size: clamp(2rem, 10vw, 3.5rem) !important;
    line-height: 1.08 !important;
  }
  .erf-hero-content {
    padding: 0 1.5rem 3.5rem !important;
    max-width: 100% !important;
  }
  /* Scroll indicator off on mobile (saves space) */
  .erf-hero-scroll { display: none !important; }
}

/* Tablet */
@media (max-width: 1024px) and (min-width: 768px) {
  .erf-hero-title {
    font-size: clamp(2.5rem, 7vw, 5rem) !important;
  }
}



/* ══════════════════════════════════════════════════════
   MOBILE SMOOTH SCROLL WRAPPER OVERRIDE
   When ScrollSmoother loads on mobile despite PHP dequeue,
   this CSS forces normal layout. Uses !important on ALL
   properties the JS sets via inline style.
   ══════════════════════════════════════════════════════ */
/* Fix ScrollSmoother on ALL screen sizes — it was clipping the page to one viewport height */
#smooth-wrapper {
  position: static !important;
  overflow: visible !important;
  height: auto !important;
  width: 100% !important;
  inset: auto !important;
  top: auto !important;
  left: auto !important;
  right: auto !important;
  bottom: auto !important;
}
#smooth-content {
  transform: none !important;
  will-change: auto !important;
  position: static !important;
  overflow: visible !important;
}
html, body {
  overflow: auto !important;
  height: auto !important;
}

/* ══════════════════════════════════════════════════════
   NUCLEAR Z-INDEX — HEADER ALWAYS ON TOP
   Elementor sections, Slider Revolution, and portfolio
   items can all create stacking contexts. This block
   forces the ERF header and mobile menu above all of them.
   ══════════════════════════════════════════════════════ */

/* Force ALL Elementor sections/containers below header */
.elementor-section,
.elementor-top-section,
.e-con,
.e-con-inner,
.elementor-widget-wrap,
.elementor-widget-container {
  /* Do NOT set z-index here — that would create stacking contexts.
     Instead, ensure nothing creates an elevated stacking context
     that could override a fixed positioned element. */
  isolation: auto !important;
}

/* Portfolio items: remove will-change so they don't form stacking contexts.
   (The grayscale-siblings rule re-adds will-change:filter on gs-portfolio
   backgrounds at higher specificity so their animated blur stays on its own
   layer — that's intentional and scoped.) */
.erf-pb-item,
.erf-pb-inner,
.erf-pb-bg,
.erf-pb-video {
  will-change: auto !important;
  /* Keep transform for scale effect but don't let it elevate z */
}
/* Re-apply transforms without will-change */
.erf-pb-item:hover .erf-pb-bg { transform: scale(1.03); }

/* Slider Revolution: ensure it sits below header */
.rev_slider_wrapper,
.rev-slider,
#rev_slider_wrapper,
.tp-banner-container {
  z-index: 1 !important;
}

/* Mobile: explicit rule so nothing from the page bleeds through */
@media (max-width: 1024px) {
  [id^="erfhdr_"] {
    z-index: 99999 !important;
    background: #000000 !important;
  }
  [id$="-menu"] {
    z-index: 99998 !important;
  }
}

/* ═══════════════════════════════════════════════════════
   ERF SYSTEM — INSTRUMENT CHROME (shared: heroes + section seams)
   Teenage-Engineering / KIT-plate faceplate detailing: corner
   screws, top+bottom serial rails, knob/toggle/plus cluster,
   edge ruler, scroll gauge. Overlays the media in the margins
   only (pointer-events:none) — never covers hero content.
   ═══════════════════════════════════════════════════════ */
.erf-inst {
  /* Above the case-study hero content (z-index 8), which otherwise paints over
     the knob, toggle and plus and swallows every click. The overlay itself is
     pointer-events:none, so raising it costs nothing: only .erf-inst-cluster
     takes the pointer back. On the landing page there is no content layer,
     which is why the cluster worked there and nowhere else. */
  position: absolute; inset: 0; z-index: 9; pointer-events: none;
  font-family: var(--erf-mono); color: rgba(237,237,234,0.6);
}
.erf-inst-railB {
  position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center;
  justify-content: space-between; gap: 16px; padding: 0 4vw; height: 44px;
  font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; box-sizing: border-box;
  text-shadow: 0 1px 3px rgba(0,0,0,0.5), 0 1px 10px rgba(0,0,0,0.35);
}
/* No background scrim on the rails — a flat gradient band reads as a hard seam
   across photo content. Legibility comes from the text-shadow above instead. */

/* Channel label sits centered in the SAME band the fixed site header occupies
   (top:0, height:--erf-hdr-h), so it reads on the same line as the logo + burger
   rather than in its own rail below. The header itself is transparent, so this
   shows through the gap between logo and nav. */
.erf-inst-channel {
  position: absolute; top: 0; left: 0; right: 0; height: var(--erf-hdr-h, 72px);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase;
  text-shadow: 0 1px 3px rgba(0,0,0,0.5), 0 1px 10px rgba(0,0,0,0.35);
}

/* Coordinates + EST grouped on the right edge, rotated 90deg clockwise
   (vertical-rl) instead of sitting in the top rail. */
.erf-inst-vert-right {
  position: absolute; top: calc(var(--erf-hdr-h, 72px) + 60px); bottom: 120px; right: 22px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 58px;
}
.erf-inst-vert-right span {
  writing-mode: vertical-rl; text-orientation: mixed;
  font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase;
  text-shadow: 0 1px 3px rgba(0,0,0,0.5), 0 1px 10px rgba(0,0,0,0.35);
}

.erf-inst-screw { position: absolute; width: 19px; height: 19px; color: rgba(237,237,234,0.7); }
.erf-inst-screw svg { width: 100%; height: 100%; display: block; }
.erf-inst-screw.tl { top: calc(var(--erf-hdr-h, 72px) + 52px); left: 22px; }
.erf-inst-screw.tr { top: calc(var(--erf-hdr-h, 72px) + 52px); right: 22px; }
.erf-inst-screw.bl { bottom: 52px; left: 22px; } .erf-inst-screw.br { bottom: 52px; right: 22px; }
.erf-inst-ruler { position: absolute; top: calc(var(--erf-hdr-h, 72px) + 60px); bottom: 120px; left: 24px; width: 14px;
  display: flex; flex-direction: column; justify-content: space-between; }
.erf-inst-ruler i { display: block; width: 8px; height: 1px; background: rgba(237,237,234,0.3); }
.erf-inst-ruler i:nth-child(5n+1) { width: 14px; background: rgba(237,237,234,0.5); }
.erf-inst-cluster { display: flex; align-items: center; gap: 16px; color: rgba(237,237,234,0.78);
  pointer-events: auto; /* the .erf-inst overlay is pointer-events:none; this re-enables just the cluster */ }
.erf-inst-cluster svg { display: block; }
.erf-inst-btn { background: none; border: none; padding: 0; margin: 0; line-height: 0;
  color: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.erf-inst-knob-needle { transition: transform var(--erf-fast) var(--erf-ease); transform-box: view-box; transform-origin: 12px 12px; }
.erf-inst-toggle-thumb { transition: transform var(--erf-fast) var(--erf-ease); transform-box: fill-box; transform-origin: center; }
.erf-inst-toggle.is-on .erf-inst-toggle-thumb { transform: translateY(10px); }
.erf-inst-plus { transition: transform var(--erf-fast) var(--erf-ease); transform-origin: center; }
.erf-inst-plus.is-x { transform: rotate(45deg); }
.erf-inst-scroll { display: flex; align-items: center; gap: 9px; }
.erf-inst-scroll .trk { width: 34px; height: 2px; background: rgba(237,237,234,0.22);
  position: relative; overflow: hidden; }
.erf-inst-scroll .trk i { position: absolute; left: 0; top: 0; height: 100%; width: 40%;
  background: #ededea; animation: erfInstScroll 2s var(--erf-ease) infinite; }
@keyframes erfInstScroll { 0% { transform: translateX(-100%); } 100% { transform: translateX(250%); } }

/* Light-ground variant (for any hero/section over a light background) */
.erf-inst.is-light { color: rgba(20,20,18,0.55); }
.erf-inst.is-light .erf-inst-railB,
.erf-inst.is-light .erf-inst-channel,
.erf-inst.is-light .erf-inst-vert-right span {
  text-shadow: 0 1px 3px rgba(255,255,255,0.6), 0 1px 10px rgba(255,255,255,0.4);
}
.erf-inst.is-light .erf-inst-scroll .trk i { background: #141412; }
.erf-inst.is-light .erf-inst-screw { color: rgba(20,20,18,0.5); }
.erf-inst.is-light .erf-inst-cluster { color: rgba(20,20,18,0.7); }
.erf-inst.is-light .erf-inst-ruler i { background: rgba(20,20,18,0.3); }
.erf-inst.is-light .erf-inst-ruler i:nth-child(5n+1) { background: rgba(20,20,18,0.5); }

/* Thin standalone spec-rail (section seams — a single telemetry strip) */
.erf-specrail { position: relative; width: 100%; box-sizing: border-box; display: flex;
  align-items: center; justify-content: space-between; gap: 16px; padding: 12px 4vw;
  border-top: 1px solid rgba(237,237,234,0.14); border-bottom: 1px solid rgba(237,237,234,0.14);
  font-family: var(--erf-mono); font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase;
  color: rgba(237,237,234,0.55); background: #0e0e0d; }
.erf-specrail.is-light { border-color: rgba(20,20,18,0.14); color: rgba(20,20,18,0.55); background: #f7f7f5; }
.erf-specrail .erf-inst-cluster { color: inherit; opacity: 0.8; }

@media (max-width: 767px) {
  .erf-inst-ruler { display: none; }
  .erf-inst-vert-right { display: none; }
  .erf-specrail .erf-inst-mid { display: none; }
  .erf-inst-screw.tl, .erf-inst-screw.tr { top: 50px; }
  .erf-inst-screw.bl, .erf-inst-screw.br { bottom: 50px; }
}


/* The photo-fade widget reveals from `transform: scale(1.04)`, which paints 4% of
   the viewport past each edge. An element cannot clip its OWN transformed box, so
   the outer div's `overflow:hidden` never helped: /info/ scrolled sideways by 4%
   of the window at every width. The CONTAINER clips it. Measured: page scrollWidth
   1762 -> 1728 at a 1728px viewport. Vertical stays visible, nothing is cropped. */
.elementor-widget-erf_photo_fade > .elementor-widget-container {
  overflow-x: clip;
}


/* ---- Process Console family (erf-pc): the erf.studio skin, NOT the Kit skin.
   Monochrome. The only motion is a grey/white displacement on image hover, no
   RGB split anywhere, and reduced-motion turns even that off. */
.erf-pc { color: #f2f2f0; font-family: 'Kanit', system-ui, sans-serif; }
.erf-pc-framed { border: none; border-top: 1px solid rgba(255,255,255,0.14); border-bottom: 1px solid rgba(255,255,255,0.14); padding: 40px 4vw; }
.erf-pc-head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
    flex-wrap: wrap; margin-bottom: 22px; border-bottom: 1px solid rgba(255,255,255,0.14); padding-bottom: 14px; }
.erf-pc-title { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; }
.erf-pc-meta { font-family: var(--erf-mono, ui-monospace, monospace); font-size: 11px;
    letter-spacing: 0.14em; text-transform: uppercase; color: #8a8a84; }
.erf-pc-tl { display: grid; gap: 0; }
.erf-pc-tl-phase, .erf-pc-tl-live { display: grid; grid-template-columns: 44px 180px 1fr; gap: 14px;
    align-items: baseline; padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,0.10); }
.erf-pc-tl-num { font-family: var(--erf-mono, ui-monospace, monospace); font-size: 11px; color: #8a8a84; }
.erf-pc-tl-label { font-weight: 500; }
.erf-pc-tl-win { font-family: var(--erf-mono, ui-monospace, monospace); font-size: 11px;
    letter-spacing: 0.1em; text-transform: uppercase; color: #8a8a84; }
.erf-pc-tl-note { grid-column: 2 / -1; font-weight: 300; font-size: 13px; color: #b8b8b2; }
.erf-pc-dot { width: 8px; height: 8px; background: #38ff70; align-self: center;
    animation: erfpcblink 2.4s steps(1) infinite; }
@keyframes erfpcblink { 0%, 70% { opacity: 1; } 71%, 100% { opacity: 0.25; } }
.erf-pc-sheet { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; margin-top: 26px; }
.erf-pc-cell { margin: 0; }
.erf-pc-open { display: block; width: 100%; padding: 0; border: 1px solid rgba(255,255,255,0.14);
    background: none; cursor: pointer; position: relative; overflow: hidden; }
.erf-pc-open img { display: block; width: 100%; height: auto; filter: grayscale(1); transition: filter 0.3s ease; }
.erf-pc-open:hover img, .erf-pc-open:focus-visible img { filter: grayscale(0); }
/* the displacement: two grey/white ghost copies via clipped pseudo-shift on hover */
.erf-pc-open::after { content: ''; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(180deg, rgba(255,255,255,0.0) 46%, rgba(255,255,255,0.18) 50%, rgba(255,255,255,0.0) 54%);
    transform: translateY(-101%); transition: transform 0.45s cubic-bezier(0.65, 0, 0.35, 1); }
.erf-pc-open:hover::after { transform: translateY(101%); }
.erf-pc-cap { font-family: var(--erf-mono, ui-monospace, monospace); font-size: 10px;
    letter-spacing: 0.1em; text-transform: uppercase; color: #8a8a84; padding: 7px 2px 0; }
.erf-pc-rack { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; margin: 26px 0 0; }
.erf-pc-tool { border: 1px solid rgba(255,255,255,0.14); padding: 12px 14px; }
.erf-pc-tool dt { font-family: var(--erf-mono, ui-monospace, monospace); font-size: 10px;
    letter-spacing: 0.14em; text-transform: uppercase; color: #8a8a84; margin: 0 0 4px; }
.erf-pc-tool dd { margin: 0; font-weight: 400; }
.erf-pc-lb { position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,0.92);
    display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 14px; padding: 4vh 4vw; }
.erf-pc-lb img { max-width: 92vw; max-height: 82vh; border: 1px solid rgba(255,255,255,0.2); }
.erf-pc-lb-x { position: absolute; top: 18px; right: 22px; background: none; border: 1px solid rgba(255,255,255,0.3);
    color: #f2f2f0; font-size: 22px; line-height: 1; padding: 6px 12px; cursor: pointer; }
.erf-pc-lb-cap { font-family: var(--erf-mono, ui-monospace, monospace); font-size: 11px;
    letter-spacing: 0.12em; text-transform: uppercase; color: #b8b8b2; }
@media (max-width: 680px) { .erf-pc-tl-phase, .erf-pc-tl-live { grid-template-columns: 34px 1fr; }
    .erf-pc-tl-win { grid-column: 2; } }
@media (prefers-reduced-motion: reduce) {
    .erf-pc-open::after { display: none; }
    .erf-pc-open img { transition: none; }
    .erf-pc-dot { animation: none; }
}

/* ---- Testimonial (erf-tm): same erf.studio skin as Process Console, same
   file even, deliberately. No circles, no avatars, no cards, no radius, no
   shadows, no star ratings. The only "graphic" is the mono "//" marker. */
.erf-tm { color: #f2f2f0; font-family: 'Kanit', system-ui, sans-serif; }
.erf-tm-framed { border-top: 1px solid rgba(255,255,255,0.14); padding: 40px 4vw; }
.erf-tm-label { font-family: var(--erf-mono, ui-monospace, monospace); font-size: 11px;
    letter-spacing: 0.14em; text-transform: uppercase; color: #8a8a84; margin-bottom: 22px; }
.erf-tm-fig { margin: 0; max-width: 68ch; }
.erf-tm-quote { margin: 0 0 18px; }
.erf-tm-mark { display: block; font-family: var(--erf-mono, ui-monospace, monospace);
    font-size: 11px; letter-spacing: 0.14em; color: #8a8a84; margin-bottom: 10px; }
.erf-tm-text { display: block; font-weight: 700; letter-spacing: -0.01em;
    font-size: clamp(24px, 3vw, 40px); line-height: 1.25; }
.erf-tm-attr { font-family: var(--erf-mono, ui-monospace, monospace); font-size: 11px;
    letter-spacing: 0.1em; text-transform: uppercase; color: #8a8a84; }

/* ══════════════════════════════════════════════════════
   IMAGE GRID — optional filter bar / in-grid caption / Load More.
   Only rendered when the Image Grid widget's "Enable Artist Filter" toggle
   is on; the base .erf-lg-wrap / .erf-lg-grid / .erf-lg-item styling above
   is untouched either way.
   ══════════════════════════════════════════════════════ */
.erf-fg-wrap { width: 100%; }
/* 4vw matches the header and the case-study hero. The grid itself is
   full-bleed on purpose, but the tags are type, and type sitting hard
   against the viewport edge reads as a mistake. */
/* One line, always. Fourteen artists must not become a second row: the rail
   scrolls sideways and the arrows both drive it and say "there is more".
   The rail carries the 4vw gutter so the first tag sits exactly on the
   header logo's left edge; the scroller inside is free to clip. */
/* Both arrows sit exactly ON the 4vw margin line, like the header logo and
   hamburger. The tags run between them. An arrow tucked into the gutter reads
   as a box violating the margin, which is worse than tags starting one arrow
   further in. */
.erf-fg-rail { display: flex; align-items: center; gap: 0.7rem; margin: 0 0 1.4rem; padding: 0 4vw; }
.erf-fg-rail.is-sticky {
    position: sticky;
    top: var(--erf-hdr-h, 72px);
    z-index: 30;
    background: rgba(10, 10, 10, 0.85);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    padding-top: 0.85rem;
    padding-bottom: 0.85rem;
}
.erf-fg-filters {
    display: flex; flex: 1 1 auto; min-width: 0;
    flex-wrap: nowrap; gap: 0.6rem;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    /* The theme globally sets touch-action: pan-y, which tells the browser to
       IGNORE horizontal swipes. This bar is the one place they're the point.
       Must also cover the tags: a swipe starting on a child is governed by the
       child's own touch-action, not the scroller's. */
    touch-action: pan-x pan-y pinch-zoom;
}
.erf-fg-filters * { touch-action: pan-x pan-y pinch-zoom; }
.erf-fg-filters::-webkit-scrollbar { display: none; }
.erf-fg-filters .erf-fg-tag { flex: 0 0 auto; white-space: nowrap; }
.erf-fg-arrow {
    flex: 0 0 auto; width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    background: none; border: 1px solid rgba(255,255,255,0.38);
    color: rgba(255,255,255,0.85); cursor: pointer;
    transition: color 0.25s, border-color 0.25s, opacity 0.25s;
}
.erf-fg-arrow:hover { color: #fff; border-color: #fff; }
.erf-fg-arrow svg { width: 15px; height: 15px; }
.erf-fg-arrow[hidden] { display: none; }
/* The dead end reads as unavailable, not as absent. 0.22 was invisible on a
   black ground; this still separates clearly from the live arrow. */
.erf-fg-arrow.is-end { opacity: 0.45; pointer-events: none; }
/* Kept on touch as well. Native swipe works when the page's touch-action
   permits it, but that is exactly what the theme's global rule fights, and a
   locked filter bar is unusable. A button cannot be overridden by a
   touch-action anywhere up the tree. */
@media (max-width: 640px) {
    .erf-fg-arrow { width: 28px; height: 28px; }
    .erf-fg-arrow svg { width: 13px; height: 13px; }
    .erf-fg-rail { gap: 0.5rem; }
}
.erf-fg-tag {
    font-family: var(--erf-mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase;
    font-weight: 500; color: rgba(255,255,255,0.55); background: none;
    border: 1px solid rgba(255,255,255,0.18); padding: 0.5em 1em; cursor: pointer;
    transition: color 0.25s, border-color 0.25s, background 0.25s;
}
.erf-fg-tag:hover { color: #fff; border-color: rgba(255,255,255,0.4); }
.erf-fg-tag.is-active { color: #111; background: #fff; border-color: #fff; }
.erf-fg-item { position: relative; }
.erf-fg-cap {
    position: absolute; left: 0; right: 0; bottom: 0; padding: 0.6em 0.7em;
    font-family: var(--erf-mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500;
    color: #fff; text-align: left; background: linear-gradient(0deg, rgba(0,0,0,0.72), rgba(0,0,0,0));
    opacity: 0; transform: translateY(6px); transition: opacity 0.3s var(--erf-ease), transform 0.3s var(--erf-ease);
    pointer-events: none;
}
.erf-fg-item:hover .erf-fg-cap, .erf-fg-item:focus-visible .erf-fg-cap { opacity: 1; transform: translateY(0); }
.erf-fg-item.erf-fg-hidden { display: none; }
.erf-fg-loadmore {
    display: block; margin: 1.6rem auto 0; font-family: var(--erf-mono); font-size: 11px;
    letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500; color: rgba(255,255,255,0.7);
    background: none; border: 1px solid rgba(255,255,255,0.25); padding: 0.7em 1.6em; cursor: pointer;
    transition: color 0.25s, border-color 0.25s;
}
.erf-fg-loadmore:hover { color: #fff; border-color: #fff; }
@media (max-width: 600px) {
    .erf-fg-filters { gap: 0.4rem; }
    .erf-fg-tag { font-size: 10px; padding: 0.5em 0.85em; }
}
@media (prefers-reduced-motion: reduce) {
    .erf-fg-cap { transition: none; }
}

/* ══════════════════════════════════════════════════════
   BREADCRUMBS (erf_breadcrumbs) — mono trail, inherits color
   ══════════════════════════════════════════════════════ */
.erf-crumbs ol { list-style: none; display: flex; flex-wrap: wrap; align-items: center; gap: 0; margin: 0; padding: 0; }
.erf-crumbs .erf-crumbs-item { display: inline-flex; align-items: center; font-family: var(--erf-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; }
.erf-crumbs a { color: rgba(255,255,255,0.55); text-decoration: none; transition: color 0.2s var(--erf-ease); }
.erf-crumbs a:hover { color: #fff; }
.erf-crumbs span[aria-current] { color: #fff; }
.erf-crumbs .erf-crumbs-sep { color: rgba(255,255,255,0.3); margin: 0 0.55em; }

/* grab cursors while a zoomed photo can be dragged around */
#erf-lightbox.is-zoomed .erf-lb-img { cursor: grab; }
#erf-lightbox.is-panning .erf-lb-img,
#erf-lightbox.is-panning .erf-lb-stage { cursor: grabbing; user-select: none; }

/* ══════════════════════════════════════════════════════
   VIDEO PLAYER OVERLAY
   A 72px play circle centred on a photograph reads as decoration: people
   scroll past it. The affordance is now stated three ways instead of once,
   in the mono furniture the rest of the site already uses.
      - a corner tag that says the word
      - a ring that expands, so the target behaves like a control
      - a footline carrying the caption and the runtime, over a scrim
   Scrims sit at top and bottom only, so the middle of the frame is never
   darkened just to make small type legible.
   ══════════════════════════════════════════════════════ */
.erf-vp-outer .erf-vp-scrim {
    position: absolute; inset: 0; pointer-events: none;
    background:
      linear-gradient(to bottom, rgba(0,0,0,0.55), transparent 22%),
      linear-gradient(to top,    rgba(0,0,0,0.65), transparent 28%);
}
.erf-vp-badge {
    /* 4vw is the site gutter: header logo, hero meta, filter rail. A fixed rem
       here put the tag 22px in while the logo above it sat at 80px. */
    position: absolute; top: 1.1rem; left: 4vw; z-index: 2;
    display: flex; align-items: center; gap: 0.55em;
    font-family: var(--erf-mono); font-size: 0.625rem; font-weight: 500;
    letter-spacing: 0.22em; text-transform: uppercase; color: #fff;
    pointer-events: none;
}
.erf-vp-badge svg { width: 8px; height: 10px; fill: #fff; opacity: 0.85; }
.erf-vp-outer .erf-vp-play {
    position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 72px; height: 72px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    border: 1.5px solid rgba(255,255,255,0.55);
    transition: transform 0.25s ease, background 0.25s ease, border-color 0.25s ease;
}
.erf-vp-ring {
    position: absolute; inset: -1.5px; border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.35);
    transition: transform 0.4s cubic-bezier(0.2,0.8,0.2,1), opacity 0.4s ease;
}
.erf-vp-outer.is-hover .erf-vp-play {
    transform: translate(-50%, -50%) scale(1.08);
    border-color: #fff;
}
.erf-vp-outer.is-hover .erf-vp-ring { transform: scale(1.35); opacity: 0; }
.erf-vp-footline {
    position: absolute; left: 4vw; right: 4vw; bottom: 1.2rem; z-index: 2;
    display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
    font-family: var(--erf-mono); font-size: 0.6875rem; font-weight: 300;
    letter-spacing: 0.15em; text-transform: uppercase; pointer-events: none;
}
.erf-vp-runtime { flex: 0 0 auto; font-variant-numeric: tabular-nums; opacity: 0.75; }
@media (max-width: 640px) {
    .erf-vp-badge { top: 0.8rem; font-size: 0.5625rem; }
    .erf-vp-footline { bottom: 0.9rem; font-size: 0.5625rem; }
    .erf-vp-outer .erf-vp-play { width: 60px; height: 60px; }
}
@media (prefers-reduced-motion: reduce) {
    .erf-vp-outer .erf-vp-play, .erf-vp-ring { transition: none; }
}

/* ── Hero reel ──────────────────────────────────────────────────────
   The reel lives in the CTA row, first slot. It was briefly a ring floating on
   the right edge, which Erf read as weirdly positioned, and it crowded the
   vertical rail. A <button> needs the resets an <a> does not. */
.erf-hero-cta-reel {
  background: none;
  cursor: pointer;
  line-height: 1;
}
.erf-hero-cta-play {
  display: inline-block;
  width: 9px;
  height: 11px;
  color: currentColor;
}
.erf-hero-cta-play svg { width: 100%; height: 100%; display: block; }

/* the reel player */
.erf-reel-modal {
  position: fixed;
  inset: 0;
  /* above the fixed header (99999): the reel is the whole screen while it
     plays, and leaving the header on top put the nav under the close X. */
  z-index: 100001;
  background: rgba(0, 0, 0, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6vh 4vw;
  opacity: 0;
  pointer-events: none;
  transition: opacity .35s cubic-bezier(.22, 1, .36, 1);
}
.erf-reel-modal.is-open { opacity: 1; pointer-events: auto; }
.erf-reel-modal .erf-reel-frame {
  position: relative;
  width: min(1400px, 100%);
  aspect-ratio: 16 / 9;
  background: #000;
}
.erf-reel-modal iframe,
.erf-reel-modal video { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* The close X sits EXACTLY where the header's hamburger sits, so opening the
   reel reads as the same control changing its glyph rather than a second X
   appearing next to the first. The header row is `padding: 28px 4vw` with a
   26px button, so these three values have to stay in step with
   header.php's $h_pad, .erf-h-row padding and .erf-h-burger size. */
.erf-reel-close {
  position: absolute;
  top: 28px;
  right: 4vw;
  width: 26px;
  height: 26px;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0;
}
.erf-reel-close::before,
.erf-reel-close::after {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 100%;
  height: 1.5px;
  background: #fff;
}
.erf-reel-close::before { transform: rotate(45deg); }
.erf-reel-close::after  { transform: rotate(-45deg); }


/* ── Scroll sequence ─────────────────────────────────────────────────
   The section is tall; the frame sticks inside it and the scroll through
   that height is the playhead. Sticky, not fixed, so the piece releases
   the page cleanly at both ends with no scroll hijacking anywhere. */
.erf-seq { position: relative; }
.erf-seq-track { height: var(--erf-seq-len, 320vh); }
.erf-seq-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.erf-seq-canvas {
  display: block;
  width: 92vw;
  max-width: 1400px;
  aspect-ratio: var(--erf-seq-ratio, 16/9);
  height: auto;
  max-height: 84vh;
  background: #000;
}
/* the readout: which frame, how far through. Data, so it may glow. */
.erf-seq-rail {
  position: absolute;
  left: 4vw; right: 4vw; bottom: 5vh;
  display: flex; align-items: center; gap: 14px;
  font-family: var(--erf-mono, 'JetBrains Mono', monospace);
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  color: rgba(237,237,234,.62);
  pointer-events: none;
}
.erf-seq-pos { flex: 1 1 auto; height: 1px; background: rgba(237,237,234,.18); position: relative; }
.erf-seq-bar {
  position: absolute; left: 0; top: 0; height: 100%; width: 0;
  /* white, not phosphor: Erf's ruling 2026-07-29. A playhead is chrome,
     not a live signal, and it does not get to glow. */
  background: rgba(237, 237, 234, 0.9);
}
.erf-seq-num { font-variant-numeric: tabular-nums; }
.erf-seq-cap {
  margin: 0; padding: 26px 4vw 0;
  font-family: var(--erf-mono, 'JetBrains Mono', monospace);
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: rgba(237,237,234,.62);
}
/* A visitor who cannot scroll-scrub still gets the piece: the track collapses
   and the canvas simply holds the frame it has. */
@media (prefers-reduced-motion: reduce) {
  .erf-seq-track { height: auto; }
  .erf-seq-stage { position: static; height: auto; }
  .erf-seq-rail { display: none; }
}

/* Phones do not get the sequence at all (Erf's call, 2026-07-29): the page
   opens on the case-study hero instead. display:none also means the observer
   never sees it intersect, so not one frame is downloaded on mobile. */
@media (max-width: 900px) {
  .erf-seq { display: none; }
}

/* Full screen: the piece IS the screen. It breaks out of whatever container
   Elementor put it in (100vw pulled back to the viewport edge), fills the
   height, and crops rather than letterboxes, so nothing shares the frame with
   it except the header. The ordinary case-study hero arrives after the track
   ends, which is why the track releases cleanly instead of pinning. */
.erf-seq.is-full {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}
.erf-seq.is-full .erf-seq-stage { height: 100svh; }
.erf-seq.is-full .erf-seq-canvas {
  width: 100vw;
  max-width: none;
  height: 100svh;
  max-height: none;
  aspect-ratio: auto;
}
.erf-seq.is-full .erf-seq-cap { padding-left: 4vw; padding-right: 4vw; }
@supports not (height: 100svh) {
  .erf-seq.is-full .erf-seq-stage,
  .erf-seq.is-full .erf-seq-canvas { height: 100vh; }
}
