/* ==========================================================================
   MELCOLM — brand stylesheet
   Fonts:  Montserrat (main + captions), Bebas Neue (secondary/display)
   Colors: neon green = wins/money/progress · bright yellow = attention
           neon cyan = brand accents/UI · white = clean text · black = ground
   Rule:   If it is not clear, it is not done.
   ========================================================================== */

/* The brand names below are what the rest of this file paints with. Each one
   now reads the matching value from the Design screen, and falls back to the
   original brand colour if no design has been saved. That fallback is the only
   reason this file can be read on its own; on a real page the tokens are always
   there, set in an inline <style> in the head.

   This indirection is the whole fix. Before it, the Design screen wrote
   --color-* variables that nothing on the website ever read, so every colour
   saved correctly and changed nothing. */

:root {
  --black:  var(--color-background,     #000000);
  --ink:    var(--color-background,     #0a0a0a);
  --panel:  var(--color-surface,        #111111);
  --line:   var(--color-border,         #232323);
  --white:  var(--color-text-primary,   #ffffff);
  --grey:   var(--color-text-secondary, #a5a5a5);
  --green:  var(--color-accent,         #39ff14);
  --yellow: var(--color-highlight,      #ffe800);
  --cyan:   var(--color-link,           #00f0ff);
  --max:    var(--content-width,        1180px);

  --heading-family: var(--font-heading, 'Montserrat'), system-ui, sans-serif;
  --body-family:    var(--font-body,    'Montserrat'), system-ui, -apple-system, 'Segoe UI', sans-serif;
  --radius:         var(--button-radius, 2px);
  --pad-section:    var(--section-spacing, 92px);

  /* One screenful, for the handful of things that are measured in screens: a
     scroll scene, and the canvas an image sequence is drawn into.

     It is a variable rather than 100vh outright because of the editor. There
     the page is drawn inside a frame exactly as tall as its content, which is
     what gives the editor one scrollbar instead of one inside another. Inside
     a frame like that, 100vh means "as tall as everything on this page": a
     scene asking for two screens would make the page taller, which would make
     the frame taller, which would make the scene taller, forever. The editor
     sets this to a fixed number of pixels and the chase never starts. */
  --screen: 100vh;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  background: var(--black);
  color: var(--white);
  font-family: var(--body-family);
  font-weight: 500;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 24px; }

/* ---------- type ---------- */
h1, h2, h3, h4 { font-family: var(--heading-family); font-weight: 900; line-height: 1.05; letter-spacing: -0.02em; }
h1 { font-size: clamp(2.6rem, 7vw, 5.2rem); text-transform: uppercase; }
h2 { font-size: clamp(1.9rem, 4.4vw, 3.2rem); text-transform: uppercase; }
h3 { font-size: clamp(1.15rem, 2.2vw, 1.5rem); }
p  { color: var(--grey); font-size: 1.02rem; }
p strong, li strong { color: var(--white); font-weight: 700; }

.display { font-family: 'Bebas Neue', var(--heading-family); font-weight: 400; letter-spacing: 0.02em; }
.green  { color: var(--green); }
.yellow { color: var(--yellow); }
.cyan   { color: var(--cyan); }

.eyebrow {
  font-size: 0.72rem; font-weight: 800; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--cyan); margin-bottom: 18px;
}
.lead { font-size: clamp(1.05rem, 1.7vw, 1.28rem); color: var(--grey); max-width: 62ch; }

/* ---------- nav ---------- */
header.nav {
  position: sticky; top: 0; z-index: 50;
  background: var(--black); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.nav-inner { display: flex; align-items: center; justify-content: space-between; height: 70px; gap: 20px; }
.logo { font-weight: 900; font-size: 1.5rem; letter-spacing: -0.04em; text-transform: uppercase; }
.logo span { color: var(--green); }
.nav-links { display: flex; gap: 26px; align-items: center; flex-wrap: wrap; }
.nav-links a { font-size: 0.82rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--grey); transition: color .15s; }
.nav-links a:hover, .nav-links a.active { color: var(--white); }
.nav-links a.cta { color: var(--black); background: var(--green); padding: 10px 18px; border-radius: var(--radius); }
.nav-links a.cta:hover { background: var(--yellow); }
.nav-toggle { display: none; background: none; border: 0; padding: 10px; cursor: pointer; }
.nav-toggle span { display: block; width: 24px; height: 2px; background: var(--white); margin: 5px 0; transition: transform .15s, opacity .15s; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 900px) {
  .nav-inner { height: 64px; }
  .nav-toggle { display: block; }
  .nav-links {
    position: absolute; left: 0; right: 0; top: 100%;
    background: var(--black); border-bottom: 1px solid var(--line);
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 8px 24px 20px; display: none;
  }
  .nav-links.open { display: flex; }
  .nav-links a { padding: 14px 0; font-size: 0.9rem; border-bottom: 1px solid var(--line); }
  .nav-links a.cta { text-align: center; margin-top: 14px; padding: 14px 18px; border-bottom: 0; }
}

/* ---------- sections ---------- */
section { padding: var(--pad-section) 0; border-bottom: 1px solid var(--line); }
section.tight { padding: 62px 0; }
.section-head { margin-bottom: 46px; }
.section-head p { margin-top: 16px; }

/* ---------- hero ---------- */
.hero { padding: 120px 0 96px; border-bottom: 1px solid var(--line); }
.hero h1 { margin-bottom: 26px; }
.hero .lead { margin-bottom: 36px; }
.hero-tag {
  display: inline-block; font-size: 0.7rem; font-weight: 800; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--black); background: var(--yellow);
  padding: 7px 14px; margin-bottom: 24px;
}

/* ---------- buttons ---------- */
.btn {
  display: inline-block; font-weight: 800; font-size: 0.86rem; text-transform: uppercase;
  letter-spacing: 0.1em; padding: 16px 30px; border-radius: var(--radius); transition: all .15s;
  border: 2px solid transparent;
  /* A button can carry an email address, and an email address has nowhere to
     break. Without these it is one unbreakable word that pushes a narrow phone
     sideways and gives the whole page a horizontal scrollbar. */
  max-width: 100%; overflow-wrap: anywhere;
}
.btn-primary { background: var(--green); color: var(--black); }
.btn-primary:hover { background: var(--yellow); }
.btn-ghost { border-color: var(--line); color: var(--white); }
.btn-ghost:hover { border-color: var(--cyan); color: var(--cyan); }
.btn-row { display: flex; gap: 14px; flex-wrap: wrap; }

/* ---------- grids ---------- */
.grid { display: grid; gap: 20px; }
.g2 { grid-template-columns: repeat(2, 1fr); }
.g3 { grid-template-columns: repeat(3, 1fr); }
.g4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .g3, .g4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .g2, .g3, .g4 { grid-template-columns: 1fr; } }

/* ---------- cards ---------- */
.card { background: var(--panel); border: 1px solid var(--line); padding: 30px; border-radius: 3px; }
.card h3 { margin-bottom: 12px; }
.card p { font-size: 0.94rem; }
.card .num { font-family: 'Bebas Neue', sans-serif; font-size: 2.4rem; line-height: 1; color: var(--cyan); margin-bottom: 10px; }

/* ---------- pricing ---------- */
.price-card { background: var(--panel); border: 1px solid var(--line); padding: 34px 30px; border-radius: 3px; display: flex; flex-direction: column; }
.price-card.featured { border-color: var(--green); position: relative; }
.price-card.featured::before {
  content: 'MOST POPULAR'; position: absolute; top: -12px; left: 30px;
  background: var(--green); color: var(--black); font-size: 0.62rem; font-weight: 900;
  letter-spacing: 0.16em; padding: 5px 12px;
}
.price-name { font-size: 0.74rem; font-weight: 800; letter-spacing: 0.2em; text-transform: uppercase; color: var(--cyan); margin-bottom: 14px; }
.price-tag { font-family: 'Bebas Neue', sans-serif; font-size: 3.4rem; line-height: 1; color: var(--green); }
.price-tag small { font-family: 'Montserrat'; font-size: 0.8rem; font-weight: 700; color: var(--grey); display: block; margin-top: 6px; letter-spacing: 0.04em; }
.price-for { color: var(--white); font-weight: 700; font-size: 0.95rem; margin: 20px 0 18px; }
.price-card ul { list-style: none; margin-bottom: 26px; }
.price-card li { color: var(--grey); font-size: 0.9rem; padding: 9px 0 9px 24px; position: relative; border-bottom: 1px solid var(--line); }
.price-card li::before { content: '→'; position: absolute; left: 0; color: var(--green); font-weight: 700; }
.price-card .btn { margin-top: auto; text-align: center; }

/* ---------- steps ---------- */
.step { display: grid; grid-template-columns: 84px 1fr; gap: 24px; padding: 26px 0; border-bottom: 1px solid var(--line); align-items: start; }
.step-num { font-family: 'Bebas Neue', sans-serif; font-size: 3rem; line-height: 0.8; color: var(--yellow); }
.step h3 { margin-bottom: 8px; }
.step p { font-size: 0.95rem; }
@media (max-width: 640px) { .step { grid-template-columns: 1fr; gap: 8px; } }

/* ---------- app banner ---------- */
.app-banner {
  background: linear-gradient(120deg, color-mix(in srgb, var(--green) 12%, var(--black)) 0%, var(--ink) 55%, color-mix(in srgb, var(--cyan) 12%, var(--black)) 100%);
  border: 1px solid var(--green); border-radius: 4px; padding: 46px 40px;
  display: flex; align-items: center; justify-content: space-between; gap: 32px; flex-wrap: wrap;
}
.app-banner h2 { font-size: clamp(1.6rem, 3.4vw, 2.4rem); margin-bottom: 12px; }
.app-banner p { max-width: 52ch; }

/* ---------- quote / callout ---------- */
.callout { border-left: 4px solid var(--yellow); background: var(--panel); padding: 26px 30px; }
.callout p { color: var(--white); font-weight: 600; font-size: 1.05rem; }

/* ---------- table ---------- */
.table-scroll { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; min-width: 620px; }
th { background: var(--panel); color: var(--cyan); font-size: 0.72rem; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; text-align: left; padding: 15px 18px; border-bottom: 1px solid var(--line); }
td { padding: 15px 18px; border-bottom: 1px solid var(--line); color: var(--grey); font-size: 0.92rem; vertical-align: top; }
td strong { color: var(--white); }

/* ---------- faq ---------- */
details { border-bottom: 1px solid var(--line); padding: 20px 0; }
summary { cursor: pointer; font-weight: 700; font-size: 1.02rem; list-style: none; display: flex; justify-content: space-between; gap: 20px; }
summary::-webkit-details-marker { display: none; }
summary::after { content: '+'; color: var(--green); font-weight: 900; font-size: 1.3rem; line-height: 1; }
details[open] summary::after { content: '−'; }
details p { margin-top: 14px; }

/* ---------- footer ---------- */
footer { padding: 60px 0 44px; }
.foot-inner { display: flex; justify-content: space-between; gap: 30px; flex-wrap: wrap; align-items: flex-start; }
.foot-links { display: flex; gap: 22px; flex-wrap: wrap; }
.foot-links a { font-size: 0.82rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--grey); }
.foot-links a:hover { color: var(--green); }
.foot-note { color: color-mix(in srgb, var(--grey) 65%, var(--black)); font-size: 0.78rem; margin-top: 30px; }

/* ---------- forms ---------- */
label { display: block; font-size: 0.74rem; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--cyan); margin-bottom: 8px; }
input, select, textarea {
  width: 100%; background: var(--ink); border: 1px solid var(--line); color: var(--white);
  font-family: 'Montserrat', sans-serif; font-size: 0.95rem; padding: 14px 16px; border-radius: 2px; margin-bottom: 22px;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--green); }
textarea { min-height: 140px; resize: vertical; }

/* ==========================================================================
   Pieces added when the site became editable. Same visual language:
   black ground, neon green wins, yellow attention, cyan accents.
   ========================================================================== */

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--green); color: var(--black); padding: 12px 18px;
  font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem;
}
.skip-link:focus { left: 0; }

:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }

header.nav { position: sticky; }
.nav-inner { position: relative; }

/* ---------- video / project cards ---------- */
.vid { background: var(--panel); border: 1px solid var(--line); border-radius: 3px; overflow: hidden; display: flex; flex-direction: column; }
.vid .frame {
  aspect-ratio: 9/16; background: var(--panel); display: flex; align-items: center; justify-content: center;
  color: var(--grey); font-size: 0.78rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  border-bottom: 1px solid var(--line); position: relative; text-align: center; padding: 12px;
}
.vid .frame img, .vid .frame iframe, .vid .frame video { width: 100%; height: 100%; object-fit: cover; border: 0; }
.vid .frame.play { cursor: pointer; }
.vid .frame .play-badge {
  position: absolute; inset: auto; width: 54px; height: 54px; border-radius: 50%;
  background: rgba(0,0,0,0.72); border: 2px solid var(--green); color: var(--green);
  display: grid; place-items: center; font-size: 1.1rem; transition: transform .15s, background .15s;
}
.vid .frame.play:hover .play-badge { transform: scale(1.08); background: var(--green); color: var(--black); }
.vid .meta { padding: 20px; }
.vid .meta h3 { font-size: 1.02rem; margin-bottom: 8px; }
.vid .meta p { font-size: 0.86rem; }
.vid-client { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: var(--cyan); margin-bottom: 10px; }
.vid-result { color: var(--green); font-weight: 700; font-size: 0.86rem; margin-top: 10px; }

/* ---------- numbers ---------- */
.stat { text-align: center; }
.stat .n { font-family: 'Bebas Neue', sans-serif; font-size: clamp(2.4rem, 6vw, 3.4rem); line-height: 1; color: var(--green);
  /* Every digit the same width, so a number counting up to itself does not
     shuffle the words underneath it on the way. */
  font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }
.stat p { font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700; margin-top: 8px; color: var(--white); }
.stat .stat-note { text-transform: none; letter-spacing: 0; font-weight: 500; color: var(--grey); font-size: 0.82rem; margin-top: 6px; }

/* ---------- case studies ---------- */
.case-card { display: flex; flex-direction: column; transition: border-color .15s; }
.case-card:hover { border-color: var(--green); }
.case-metrics { display: flex; flex-wrap: wrap; gap: 18px; margin: 20px 0 4px; }
.case-metrics div { display: flex; flex-direction: column; }
.case-metrics strong { font-family: 'Bebas Neue', sans-serif; font-size: 1.7rem; line-height: 1; color: var(--green); font-weight: 400; }
.case-metrics span { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--grey); font-weight: 700; margin-top: 4px; }
.case-more { margin-top: auto; padding-top: 20px; font-size: 0.8rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em; }
.case-hero h1 { font-size: clamp(2.2rem, 5.4vw, 4rem); }
.case-image { width: 100%; border: 1px solid var(--line); border-radius: 3px; }
.case-block p { margin-bottom: 16px; max-width: 72ch; }
.gallery-item { padding: 0; overflow: hidden; }
.gallery-item img { width: 100%; aspect-ratio: 16/10; object-fit: cover; }
.gallery-item figcaption { padding: 14px 18px; font-size: 0.84rem; color: var(--grey); }

.video-embed { position: relative; aspect-ratio: 16/9; border: 1px solid var(--line); border-radius: 3px; overflow: hidden; background: var(--panel); }
.video-embed iframe, .video-embed video { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video-embed video { object-fit: contain; background: #000; display: block; }
/* A few shapes rather than a free number. A video is one of about four things,
   and a box asking for a decimal is a box nobody fills in correctly. */
.video-embed.ratio-4-3 { aspect-ratio: 4/3; }
.video-embed.ratio-1-1 { aspect-ratio: 1/1; }
/* A phone-shaped video is taller than most screens, so it is capped and centred
   rather than being allowed to push everything else off the page. */
.video-embed.ratio-9-16 { aspect-ratio: 9/16; max-width: min(420px, 100%); margin-inline: auto; max-height: 78vh; }
/* Only ever seen in the editor: a video section with nothing in it yet. */
.video-blank {
  display: grid; place-items: center; padding: 24px; text-align: center;
  border-style: dashed; color: var(--grey);
}
.video-blank span { font-size: 0.9rem; max-width: 34ch; }

/* ---------------------------------------------------------- the video wall

   A grid of clips. Inside it the 9:16 cap above is wrong -- that cap exists to
   stop one phone-shaped video swallowing a whole screen, and here the column
   is already doing that job -- so it is lifted and the tile fills its column.

   `object-fit: cover` rather than `contain` is the other difference. On its
   own a video should never be cropped; in a wall, letterbox bars around nine
   tiles read as a broken layout, and every clip here was shot in the shape it
   is being shown in. */
.video-wall {
  display: grid; gap: 26px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.video-wall.vw-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.video-wall.vw-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.vw-item { margin: 0; }
.vw-item .video-embed.ratio-9-16 { max-width: 100%; max-height: none; }
.vw-item .video-embed video { object-fit: cover; }
.vw-item figcaption { margin-top: 12px; display: flex; flex-direction: column; gap: 4px; }
.vw-title {
  font-family: var(--heading-family); font-weight: 700; font-size: 0.9rem;
  color: var(--white); line-height: 1.35;
}
.vw-note { font-size: 0.82rem; color: var(--grey); line-height: 1.45; }

@media (max-width: 900px) {
  .video-wall, .video-wall.vw-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
}
@media (max-width: 560px) {
  /* Two phone-shaped tiles side by side on a phone are two thumbnails nobody
     can see. Below this width the wall becomes a single column. */
  .video-wall, .video-wall.vw-2, .video-wall.vw-4 { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------ client names

   Names, set large, wrapping as a row. `justify-content: center` because an
   uneven last line reads as a mistake when it is flush left and as a deliberate
   arrangement when it is centred. */
.client-row {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 30px 56px; align-items: flex-start; text-align: center;
}
.client { display: flex; flex-direction: column; gap: 5px; max-width: 20ch; }
.client-name {
  font-family: var(--heading-family); font-weight: 800;
  font-size: clamp(1rem, 2vw, 1.4rem); line-height: 1.1;
  letter-spacing: 0.02em; text-transform: uppercase; color: var(--white);
}
.client-note { font-size: 0.78rem; color: var(--grey); letter-spacing: 0.04em; }
@media (max-width: 560px) { .client-row { gap: 22px 30px; } }
.video-caption { margin-top: 12px; }

/* ---------- testimonials ---------- */
.quote-card { display: flex; flex-direction: column; }
.quote-card blockquote { color: var(--white); font-weight: 600; font-size: 1rem; line-height: 1.55; }
.quote-card figcaption { margin-top: 18px; font-size: 0.82rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em; color: var(--cyan); }
.quote-card figcaption span { display: block; color: var(--grey); font-weight: 600; text-transform: none; letter-spacing: 0; margin-top: 5px; font-size: 0.84rem; }

/* ---------- brand logos ---------- */
.brand-logo { display: grid; place-items: center; min-height: 118px; padding: 24px; transition: border-color .15s; }
.brand-logo img { max-height: 62px; width: auto; object-fit: contain; filter: grayscale(1); opacity: 0.82; transition: filter .15s, opacity .15s; }
.brand-logo:hover img { filter: none; opacity: 1; }
.brand-logo h3 { color: var(--grey); text-align: center; }

/* ---------- pricing card highlight ---------- */
.card-featured { border-color: var(--green); }

/* ---------- about hero with a photo ---------- */
.hero-with-photo { display: grid; grid-template-columns: 1.35fr 1fr; gap: 46px; align-items: center; }
.hero-photo img { width: 100%; height: auto; border: 1px solid var(--line); border-radius: 3px; object-fit: cover; }
@media (max-width: 820px) { .hero-with-photo { grid-template-columns: 1fr; gap: 30px; } }

.step-image { margin-top: 30px; border: 1px solid var(--line); border-radius: 3px; }

/* ---------- a hero whose headline arrives word by word ----------
   CSS rather than the scroll runtime: the hero is on screen the moment the page
   opens, and a CSS animation always ends visible, with or without JavaScript.
   Each word carries its own --i, written by the renderer. */
.hl-words .w {
  display: inline-block;
  animation: hl-word 0.75s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--i, 0) * 75ms + 120ms);
}
@keyframes hl-word {
  from { opacity: 0; transform: translateY(0.5em); filter: blur(8px); }
  to   { opacity: 1; transform: none; filter: none; }
}
.hero-motion .hero-tag,
.hero-motion .lead,
.hero-motion .btn-row { animation: hero-up 0.8s cubic-bezier(0.22, 1, 0.36, 1) both; }
.hero-motion .hero-tag { animation-delay: 0s; }
.hero-motion .lead { animation-delay: 0.55s; }
.hero-motion .btn-row { animation-delay: 0.75s; }
@keyframes hero-up {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- a hero with a brand's logo beside it ---------- */
.hero-brand .hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: 56px; align-items: center;
}
.hero-logo { position: relative; display: grid; place-items: center; }
.hero-logo-card {
  position: relative; z-index: 1; overflow: hidden;
  width: min(300px, 64vw); aspect-ratio: 1; padding: 38px;
  display: grid; place-items: center;
  background: #ffffff; border-radius: 36px;
  box-shadow: 0 34px 70px -24px rgba(0, 0, 0, 0.55);
  /* Arrives with a little overshoot, then floats. The float only starts once
     the arrival has finished, so the two never fight over the transform. */
  animation: logo-in 1.1s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s both,
             logo-float 6s ease-in-out 1.4s infinite;
}
.hero-logo-card img { width: 100%; height: 100%; object-fit: contain; }
/* One pass of light across the card, just after it lands. */
.hero-logo-card::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, 0.75) 50%, transparent 65%);
  transform: translateX(-120%);
  animation: logo-shine 1.3s ease-in-out 1.1s both;
}
/* A soft ring that keeps pulsing out from behind the card. */
.hero-logo::before {
  content: ''; position: absolute; width: min(300px, 64vw); aspect-ratio: 1;
  border-radius: 36px; border: 2px solid rgba(255, 255, 255, 0.55);
  animation: logo-ring 3.2s ease-out 1.3s infinite; opacity: 0;
}
@keyframes logo-in {
  from { opacity: 0; transform: scale(0.55) rotate(-12deg); }
  to   { opacity: 1; transform: none; }
}
@keyframes logo-float {
  0%, 100% { transform: translateY(0) rotate(0); }
  50%      { transform: translateY(-12px) rotate(1.5deg); }
}
@keyframes logo-shine { to { transform: translateX(120%); } }
@keyframes logo-ring {
  from { opacity: 0.7; transform: scale(1); }
  to   { opacity: 0; transform: scale(1.4); }
}
@media (max-width: 820px) {
  .hero-brand .hero-grid { grid-template-columns: 1fr; gap: 34px; }
  .hero-brand .hero-logo { order: -1; justify-items: start; }
  .hero-logo-card, .hero-logo::before { width: 150px; padding: 22px; border-radius: 26px; }
}

/* ---------- client names with logos ---------- */
.client-has-logo { align-items: center; gap: 12px; max-width: 24ch; }
.client-logo {
  width: 112px; height: 112px; padding: 18px;
  display: grid; place-items: center;
  background: #ffffff; border-radius: 26px;
  box-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.45);
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.25s;
}
.client-logo img { width: 100%; height: 100%; object-fit: contain; }
a.client:hover .client-logo,
a.client:focus-visible .client-logo { transform: translateY(-6px) scale(1.04); box-shadow: 0 26px 50px -20px rgba(0, 0, 0, 0.5); }
a.client:hover .client-name { text-decoration: underline; text-underline-offset: 4px; }

@media (prefers-reduced-motion: reduce) {
  .hl-words .w, .hero-motion .hero-tag, .hero-motion .lead, .hero-motion .btn-row,
  .hero-logo-card, .hero-logo-card::after, .hero-logo::before { animation: none !important; }
  .hero-logo-card::after, .hero-logo::before { display: none; }
}

/* ---------- forms ---------- */
.form-error {
  border-left: 4px solid #ff4d4d; background: #1a0d0d; color: #ffdede;
  padding: 14px 18px; margin-bottom: 22px; font-size: 0.92rem; font-weight: 600;
}
.form-success { border-left: 4px solid var(--green); background: var(--panel); padding: 26px 30px; }
.form-success h3 { margin-bottom: 10px; }
.form-success p { color: var(--white); }
.form-submit { width: 100%; border: 0; cursor: pointer; font-family: 'Montserrat', sans-serif; }
.form-submit[disabled] { opacity: 0.6; cursor: progress; }
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.booking-line { margin-top: 20px; }

/* ---------- footer social ---------- */
.foot-social { display: flex; gap: 20px; flex-wrap: wrap; margin-top: 26px; }
.foot-social a { font-size: 0.8rem; font-weight: 700; letter-spacing: 0.06em; color: var(--grey); }
.foot-social a:hover { color: var(--cyan); }

/* ---------- preview banner ---------- */
.preview-bar {
  position: sticky; top: 0; z-index: 90; display: flex; gap: 16px; flex-wrap: wrap;
  align-items: center; justify-content: center; background: var(--yellow); color: var(--black);
  padding: 10px 20px; font-size: 0.84rem; font-weight: 600; text-align: center;
}
.preview-bar a { text-decoration: underline; font-weight: 800; }
.preview-bar + .skip-link + header.nav { top: 0; }

/* ---------- wide screens ---------- */
@media (min-width: 1800px) { :root { --max: 1320px; } }

/* ---------- small screens ---------- */
@media (max-width: 480px) {
  section { padding: 64px 0; }
  .hero { padding: 74px 0 62px; }
  .wrap { padding: 0 18px; }
  .card { padding: 24px; }
  .price-card { padding: 28px 22px; }
  .app-banner { padding: 32px 24px; }
  .btn { display: block; text-align: center; }
  .btn-row { flex-direction: column; align-items: stretch; }
}

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

/* The way in to the website editor. Deliberately quiet: it is for the owner,
   not for visitors, so it must never compete with anything on the page. */
.foot-admin {
  margin-left: 14px;
  color: var(--grey);
  text-decoration: none;
  opacity: 0.55;
  transition: opacity 0.18s ease, color 0.18s ease;
}
.foot-admin:hover,
.foot-admin:focus-visible { opacity: 1; color: var(--green); }

/* ==========================================================================
   SCROLL ANIMATION
   The starting position of every animated element is written by the runtime
   in anim-js.js, never here. That is the whole reason this page still reads
   perfectly with JavaScript switched off or broken: no stylesheet rule ever
   hides anything, so if the runtime does not run, nothing is hidden.
   ========================================================================== */

/* Only while an element is still waiting its turn. Removed the moment it has
   arrived, so the browser is not asked to hold layers it no longer needs. */
[data-anim-waiting] {
  will-change: transform, opacity;
  backface-visibility: hidden;
}

/* ---------- a section that plays out while it is scrolled through ---------- */

[data-anim-scene] {
  /* Tall enough to scroll through. The runtime turns that distance into
     --scene-progress, from 0 at the top to 1 at the bottom. */
  min-height: calc(var(--scene-screens, 2) * var(--screen));
  position: relative;
}
[data-anim-scene] > .scene-stick {
  position: sticky;
  top: 0;
  min-height: var(--screen);
  display: grid;
  align-content: center;
  overflow: hidden;
}

/* ---------- image sequences ---------- */

.sequence { position: relative; }
.sequence canvas {
  display: block;
  width: 100%;
  height: min(calc(var(--screen) * 0.7), 620px);
  /* Reserving the height up front is what stops the page jumping when the
     first frame finally arrives. */
}
.sequence-fallback { display: none; }

/* ---------- when someone has asked for less movement ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* Nothing moves, nothing is hidden, and nothing has to be scrolled through
     to be read. A sticky scene collapses into an ordinary section. */
  [data-anim] {
    transform: none !important;
    opacity: 1 !important;
    filter: none !important;
    transition: none !important;
    will-change: auto !important;
  }
  [data-anim-scene] {
    min-height: 0 !important;
  }
  [data-anim-scene] > .scene-stick {
    position: static;
    min-height: 0;
  }
  /* A still picture instead of a scroll-driven sequence. */
  .sequence canvas { display: none; }
  .sequence-fallback { display: block; }
}

/* ---------- the rest of the section types ----------
   Writing, a quote, a picture, a picture beside some words, and a gap. These
   were all offered in the section picker long before they were in this file,
   which is a particular kind of broken: the section saved, the words really
   were in the database, and the page showed them run together with no spacing
   and no shape at all. Everything a section can render now has a rule. */

/* The closing nudge. It had no spacing of its own at all, so the heading, the
   sentence under it and the button arrived stacked flat against each other. */
.cta .lead { margin-top: 22px; margin-bottom: 32px; }

.prose p + p { margin-top: 18px; }
.prose p { line-height: 1.7; max-width: 68ch; }
.prose strong { color: var(--white); }

blockquote.quote { border-left: 4px solid var(--green); padding: 4px 0 4px 26px; max-width: 74ch; }
blockquote.quote p {
  color: var(--white); font-size: clamp(1.08rem, 2vw, 1.4rem);
  font-weight: 700; line-height: 1.5;
}
blockquote.quote cite {
  display: block; margin-top: 16px; font-style: normal; font-size: 0.8rem;
  font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: var(--cyan);
}
blockquote.quote cite span { color: var(--grey); letter-spacing: 0.04em; }

.figure { margin: 0; }
.figure img { width: 100%; border-radius: 3px; }
.figure figcaption { margin-top: 12px; font-size: 0.84rem; color: var(--grey); }
/* How wide a picture is, and where it sits. Four sizes, because a box asking
   for a number of pixels is a box that gets the wrong number in it. */
.figure-wide { max-width: 74%; }
.figure-medium { max-width: 52%; }
.figure-small { max-width: 32%; }
.figure-wide, .figure-medium, .figure-small { margin-inline: auto; }
.figure-left { margin-inline: 0 auto; }
.figure-right { margin-inline: auto 0; }
/* Only ever seen in the editor. */
.figure-blank {
  display: grid; place-items: center; min-height: 180px; padding: 24px;
  border: 1px dashed var(--line); border-radius: 3px; color: var(--grey);
  text-align: center; font-size: 0.9rem;
}
/* On a phone every one of them is the full width. A picture a third of the way
   across a 390px screen is a postage stamp. */
@media (max-width: 700px) {
  .figure-wide, .figure-medium, .figure-small { max-width: 100%; }
}

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 44px; align-items: center; }
.split-media img { width: 100%; border-radius: 3px; }
.split-reverse .split-media { order: 2; }
.split-body .section-head { margin-bottom: 22px; }
@media (max-width: 820px) {
  .split { grid-template-columns: 1fr; gap: 26px; }
  /* The picture goes back above the words. Two columns swapped left-to-right
     mean nothing once there is only one of them. */
  .split-reverse .split-media { order: 0; }
}

.spacer-small  { height: 40px; }
.spacer-medium { height: 80px; }
.spacer-large  { height: 140px; }

.embed iframe, .embed video { max-width: 100%; border: 0; }

/* A picture whose file has gone. The wrapper keeps its shape rather than
   collapsing and dragging everything under it up the page. */
.img-missing { min-height: 160px; border: 1px dashed var(--line); border-radius: 3px; }

/* ---------- a section with its own colours ---------- */
/* Emitted only when a section has actually been painted, so an untouched page
   is exactly the markup it always was. The --color-* properties are set inline
   on this wrapper by the renderer.

   The block below looks like a pointless copy of the one at the top of this
   file, and it is the only thing that makes any of this work.

   A custom property whose value contains var() is resolved where it is
   declared, not where it is read. --black is declared once, on :root, so it is
   resolved there against the website's --color-background and every element on
   the page inherits that finished colour. Setting --color-background further
   down the tree changes nothing at all: --black has already been decided.

   Which meant that for as long as per-section colours have existed, they did
   not do anything. The inline styles were on the element, correct and
   complete, and the section stayed exactly the colour of the rest of the site.

   Declaring the aliases again here resolves them again, on this element,
   against the colours this element carries. Anything the section did not set
   falls back to the website's value, inherited, so painting a background
   without naming a text colour still follows the design for the text. */
.section-skin {
  --black:  var(--color-background,     #000000);
  --ink:    var(--color-background,     #0a0a0a);
  --panel:  var(--color-surface,        #111111);
  --line:   var(--color-border,         #232323);
  --white:  var(--color-text-primary,   #ffffff);
  --grey:   var(--color-text-secondary, #a5a5a5);
  --green:  var(--color-accent,         #39ff14);
  --yellow: var(--color-highlight,      #ffe800);
  --cyan:   var(--color-link,           #00f0ff);
  --pad-section: var(--section-spacing, 92px);

  background: var(--black); color: var(--white);
}
.section-skin > section:last-child,
.section-skin > .section-anim > section:last-child { border-bottom: 0; }
.section-skin.no-divider section,
.section-skin.no-divider .hero { border-bottom: 0; }
.section-skin.align-center .wrap,
.section-skin.align-center .section-head { text-align: center; }
.section-skin.align-center .lead { margin-left: auto; margin-right: auto; }
.section-skin.align-center .btn-row { justify-content: center; }
.section-skin.align-right .wrap,
.section-skin.align-right .section-head { text-align: right; }
.section-skin.align-right .btn-row { justify-content: flex-end; }

/* ---------- results, drawn ---------- */
/* Two ways of showing a figure without a paragraph around it. Both are plain
   HTML rather than SVG, so the text inside them wraps at 320px, scales with the
   reader's font size, and is read out in order by a screen reader. Both take
   their colours from the band they sit in through the --green/--white/--grey
   aliases, so the same section is legible on white, navy and charcoal. */

.result-bars { display: flex; flex-direction: column; gap: 30px; }
.rb-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  margin-bottom: 10px;
}
.rb-label {
  font-size: 0.82rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--white);
}
.rb-value {
  font-family: 'Bebas Neue', sans-serif; font-size: clamp(1.9rem, 5vw, 2.9rem);
  line-height: 1; color: var(--green);
  /* Tabular figures for the same reason the stats have them: a number counting
     up to itself must not shift the label beside it on every frame. */
  font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1;
  white-space: nowrap;
}
.rb-track { height: 10px; background: var(--panel); border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.rb-fill {
  display: block; height: 100%; border-radius: 999px; background: var(--green);
  /* --rb is the share of the track this bar fills, written inline by the
     renderer. transform rather than width, so growing it is one composited
     property and never a layout pass on the whole section. */
  transform: scaleX(var(--rb, 1)); transform-origin: left center;
}
.rb-note { font-size: 0.86rem; color: var(--grey); margin-top: 10px; max-width: 60ch; }

/* The growth. It is opt-in: the bar is drawn at its full length by the server,
   and only a browser that has run the script and been told the reader is happy
   with movement pulls it back to nothing first. So no JavaScript, reduced
   motion, and the editor canvas all show the finished bar immediately. */
.rb-fill.rb-armed { transform: scaleX(0); }
.rb-fill.rb-grow { transition: transform 900ms cubic-bezier(0.22, 1, 0.36, 1); transform: scaleX(var(--rb, 1)); }

.before-after { display: flex; flex-direction: column; gap: 2px; }
.ba-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center;
  gap: 8px 24px; padding: 22px 0; border-top: 1px solid var(--line);
}
.ba-row:last-child { border-bottom: 1px solid var(--line); }
.ba-label { font-size: 1.02rem; font-weight: 700; color: var(--white); }
.ba-pair {
  display: flex; align-items: baseline; gap: 14px; justify-self: end;
  font-family: 'Bebas Neue', sans-serif; line-height: 1; white-space: nowrap;
  font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1;
}
.ba-from { font-size: clamp(1.3rem, 3.4vw, 1.8rem); color: var(--grey); }
.ba-arrow { font-family: inherit; color: var(--grey); font-size: 1.1rem; }
.ba-to { font-size: clamp(1.9rem, 5vw, 2.9rem); color: var(--green); }
.ba-note { grid-column: 1 / -1; font-size: 0.84rem; color: var(--grey); }

/* On a phone the pair drops under the label rather than being squeezed beside
   it. A before-and-after whose "after" has been shrunk to fit is the one thing
   on the row that must not be small. */
@media (max-width: 620px) {
  .ba-row { grid-template-columns: 1fr; gap: 10px; }
  .ba-pair { justify-self: start; }
}
