html { -webkit-font-smoothing: antialiased; scroll-behavior: smooth; }
body { margin: 0; background: #fff; }
* { box-sizing: border-box; }
a { color: #000; text-decoration: none; }
a:hover { color: #FF4D1D; text-decoration: none; }
input, textarea { font-family: Sora, sans-serif; }
input::placeholder, textarea::placeholder { color: #b9b9b9; }
input:focus, textarea:focus { outline: none; }
::selection { background: #FF4D1D; color: #fff; }

/* ---- page-load fade-in -------------------------------------------------
 * `extnd-preload` is set on <html> by an inline head script, so it only ever
 * applies when JS is running — no-JS visitors never get a hidden page. Only
 * opacity is animated on <body>: a transform there would create a containing
 * block and break the fixed nav mid-transition. */
html.extnd-preload body { opacity: 0; }
html.extnd-preload *, html.extnd-preload *::before, html.extnd-preload *::after { animation-play-state: paused !important; }
body { opacity: 1; transition: opacity 300ms linear; }

/* ---- homepage loader ---------------------------------------------------
 * White overlay over an already-rendered homepage: the mark fades in, its
 * three layers extend upward, then the whole overlay dissolves.
 *
 * Every beat is a delay off the same t=0 — no JS sequencing, no animationend
 * listeners. The overlay's own animation ends `forwards` on hidden, so a
 * stalled script can never leave the page behind a white screen.
 * Total budget: 3.4s, dissolving over the last 10%. */
.extnd-loader {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Rise lands at 2.5s, the finished mark holds ~2.3s, then dissolves over
     the last 13% — 5.5s door to door. The rise timing is fixed by the
     geometry, so the hold is the knob for total length. */
  animation: extnd-loader-out 5500ms cubic-bezier(.6, 0, .3, 1) forwards;
}
@keyframes extnd-loader-out {
  0%, 87% { opacity: 1; visibility: visible; }
  100%    { opacity: 0; visibility: hidden; }
}

.extnd-loader__mark { width: clamp(58px, 7.5vw, 104px); height: auto; display: block; }

/* The Rise.
 * All three bands start below the frame — the SVG viewBox clips them, so they
 * are genuinely out of sight rather than faded out — and travel up into place.
 *
 * Every band moves at the same 245 user-units/second, so each move is only as
 * long as its distance requires. That constant speed is what makes it read as
 * one gesture instead of three separate moves, and it is why the timing is
 * linear: easing would break the shared velocity.
 *
 *   band   distance   duration   delay    lands
 *   bar      91.72u     374ms      0ms    0.374s
 *   mid     244.34u     997ms    400ms    1.397s
 *   peak    415.61u    1696ms    804ms    2.500s
 *
 * Vertical position is the only value that changes: no scale, rotate or skew,
 * so the mark is never distorted. */
.extnd-loader__band {
  animation-name: extnd-band-rise;
  animation-timing-function: linear;
  animation-fill-mode: both;
}
.extnd-loader__band--bar  { --rise: 91.72px;  animation-duration: 374ms;  animation-delay: 0ms; }
.extnd-loader__band--mid  { --rise: 244.34px; animation-duration: 997ms;  animation-delay: 400ms; }
.extnd-loader__band--peak { --rise: 415.61px; animation-duration: 1696ms; animation-delay: 804ms; }

@keyframes extnd-band-rise {
  from { transform: translate3d(0, var(--rise), 0); }
  to   { transform: translate3d(0, 0, 0); }
}

/* The preload rule pauses every animation on the page while the body is
   hidden. The loader plays over that hold, so it has to be exempt or the
   mark sits frozen for the whole sequence. */
html.extnd-preload .extnd-loader,
html.extnd-preload .extnd-loader * { animation-play-state: running !important; }

/* No animation means nothing would ever hide the overlay, so remove it. */
@media (prefers-reduced-motion: reduce) { .extnd-loader { display: none; } }

/* ---- staggered element reveal -----------------------------------------
 * Blocks start shifted down and transparent, then settle as they enter the
 * viewport. Marked by script.js before the page is un-hidden, so content
 * never flashes at full opacity first. */
.reveal {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition:
    opacity 900ms cubic-bezier(.22,.61,.36,1),
    transform 900ms cubic-bezier(.22,.61,.36,1);
}
.reveal.is-in { opacity: 1; transform: none; }
/* Printing never scrolls, so un-revealed blocks would come out blank. */
@media print { .reveal { opacity: 1 !important; transform: none !important; } }

@keyframes extnd-rise { from { opacity: 0; transform: translate3d(0,22px,0); } to { opacity: 1; transform: none; } }
@keyframes extnd-reveal { from { opacity: 0; transform: scale(1.03); } to { opacity: 1; transform: none; } }
@keyframes extnd-sheen { 0% { background-position: 160% 0; } 100% { background-position: -60% 0; } }
@keyframes efvGrain {
  0%   { transform: translate3d(0,0,0); }
  10%  { transform: translate3d(-2%,-4%,0); }
  20%  { transform: translate3d(-8%,2%,0); }
  30%  { transform: translate3d(4%,-6%,0); }
  40%  { transform: translate3d(-4%,4%,0); }
  50%  { transform: translate3d(-8%,6%,0); }
  60%  { transform: translate3d(6%,0,0); }
  70%  { transform: translate3d(0,6%,0); }
  80%  { transform: translate3d(2%,-4%,0); }
  90%  { transform: translate3d(-6%,-2%,0); }
  100% { transform: translate3d(0,0,0); }
}
[data-grain] > div { background-image: url("data:image/svg+xml,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' width='170' height='170'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='170' height='170' filter='url(%23n)'/%3E%3C/svg%3E"); background-repeat: repeat; }
/* ---- accessibility ----------------------------------------------------- */
.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 999;
  background: #FF4D1D; color: #fff; font-family: Sora, sans-serif;
  font-size: 14px; font-weight: 500; padding: 12px 20px;
  transition: top 200ms ease;
}
.skip-link:focus { top: 12px; color: #fff; }

:focus-visible {
  outline: 2px solid #FF4D1D;
  outline-offset: 3px;
}
/* On black panels the orange ring needs a light halo to stay visible. */
footer :focus-visible,
#services :focus-visible,
#why :focus-visible,
[data-contact-form] button:focus-visible {
  outline-color: #fff;
  box-shadow: 0 0 0 5px rgba(255,77,29,.55);
}

/* ---- contact form fields ----------------------------------------------
 * These are underline fields, so focus thickens and colours the underline
 * rather than boxing the input. The box-shadow paints a second 1px line
 * flush under the border, giving a 2px indicator with no layout shift. */
.form-field {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(255,255,255,.3);
  color: #fff;
  caret-color: #FF4D1D;
  font-size: clamp(19px,2.2vw,34px);
  font-weight: 600;
  letter-spacing: -0.01em;
  padding: 8px 0 14px;
  transition: border-color 250ms ease, box-shadow 250ms ease;
}
.form-field--long {
  font-size: clamp(17px,1.7vw,26px);
  font-weight: 500;
  letter-spacing: normal;
  line-height: 1.4;
  resize: none;
}
.form-field:focus,
.form-field:focus-visible {
  outline: none;
  border-bottom-color: #FF4D1D;
  box-shadow: 0 1px 0 0 #FF4D1D;
}
.form-field[aria-invalid="true"] {
  border-bottom-color: #FF4D1D;
  box-shadow: 0 1px 0 0 #FF4D1D;
}

/* ---- form validation --------------------------------------------------- */
.field-error {
  margin: 0; font-family: Inter, sans-serif; font-size: 13px;
  line-height: 1.5; color: #FF8A6B; min-height: 0;
}

/* ---- reduced motion ---------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  html.extnd-preload body { opacity: 1; }
  body { transition: none; }
  [data-grain] > * { animation: none !important; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .skip-link { transition: none; }
}

@media (max-width: 800px) {
  [data-frow] { grid-template-columns: 1fr 1fr !important; gap: 30px 24px !important; }
  [data-fcol="brand"] { grid-column: 1 / -1; }
  [data-fcol="contact"] { align-items: flex-start !important; text-align: left !important; }
  [data-intro] { position: static !important; }
}

/* ---- hover-state classes (converted from style-hover attributes) ---- */
.nav-a { color: rgba(0,0,0,.7); transition: color 250ms ease; }
.nav-a:hover { color: #FF4D1D; }
.nav-a-active { color: #000; transition: color 250ms ease; }
.nav-a-active:hover { color: #FF4D1D; }

.cta-btn { background: #FF4D1D; color: #fff; transition: background 300ms ease; }
.cta-btn:hover { background: #ff5f34; color: #fff; }

.underline-link { color: #000; border-bottom: 1px solid rgba(0,0,0,.3); transition: color 250ms ease, border-color 250ms ease, gap 250ms ease; }
.underline-link:hover { color: #FF4D1D; border-color: #FF4D1D; gap: 14px; }

.underline-link-lg { color: #fff; border-bottom: 1px solid rgba(255,255,255,.35); transition: color 300ms ease, border-color 300ms ease, gap 300ms ease; }
.underline-link-lg:hover { color: #FF4D1D; border-color: #FF4D1D; gap: 16px; }

.pillar-row { color: #fff; transition: background 450ms cubic-bezier(.2,.7,.2,1), color 450ms ease; }
.pillar-row:hover { background: #FF4D1D; color: #fff; }

.footer-link { color: #fff; transition: color 250ms ease; }
.footer-link:hover { color: #FF4D1D; }

.back-btn { color: rgba(255,255,255,.55); transition: color 250ms ease; }
.back-btn:hover { color: #fff; }

.reset-btn { border: 1px solid rgba(255,255,255,.35); background: none; color: #fff; transition: background 300ms ease, color 300ms ease; }
.reset-btn:hover { background: #fff; color: #000; }

.next-btn { background: #FF4D1D; transition: background 300ms ease; }
.next-btn:hover { background: #ff5f34; }

.work-cta { transition: transform 300ms cubic-bezier(.2,.7,.2,1); text-decoration: none; }
.work-cta:hover { transform: translate3d(0,-3px,0); text-decoration: none; }

.work-nav-a { color: #000; text-decoration: none; opacity: .75; transition: color 250ms ease; }
.work-nav-a:hover { color: #FF4D1D; opacity: 1; }

.service-btn { width: 100%; background: none; border: 0; border-bottom: 1px solid rgba(255,255,255,.14); padding: clamp(16px,1.8vw,22px) 0; display: flex; align-items: baseline; gap: clamp(14px,2vw,26px); cursor: pointer; text-align: left; color: #fff; font-family: Sora, sans-serif; }
.service-num { font-family: Inter, sans-serif; font-size: 12px; letter-spacing: 0.1em; flex: 0 0 auto; transition: color 300ms ease; color: rgba(255,255,255,.35); }
.service-title { flex: 1; font-weight: 500; font-size: clamp(19px,1.9vw,27px); line-height: 1.2; letter-spacing: -0.015em; transition: color 300ms ease, transform 400ms cubic-bezier(.2,.7,.2,1); display: block; color: rgba(255,255,255,.7); transform: none; }
.service-rule { flex: 0 0 auto; height: 1px; transition: background 300ms ease, width 400ms cubic-bezier(.2,.7,.2,1); align-self: center; background: rgba(255,255,255,.25); width: 18px; }
.service-btn.is-active .service-num { color: #FF4D1D; }
.service-btn.is-active .service-title { color: #FF4D1D; transform: translate3d(10px,0,0); }
.service-btn.is-active .service-rule { background: #FF4D1D; width: 40px; }

.step-num { font-family: Sora, sans-serif; font-weight: 700; font-size: clamp(34px,3.6vw,56px); line-height: .9; letter-spacing: -0.03em; color: transparent; -webkit-text-stroke: 1px rgba(0,0,0,.3); transition: color 600ms ease, -webkit-text-stroke-color 600ms ease; }
.step-title { margin: 0; font-family: Sora, sans-serif; font-weight: 500; font-size: clamp(20px,1.9vw,27px); line-height: 1.1; letter-spacing: -0.02em; transition: color 500ms ease; }
