/* ==========================================================================
   videoeditor.agency — site stylesheet
   Hand-written. No framework, no preprocessor, no build step.
   What is in this file is what is served.

   Governed by:
     instructions.md §5              (binding design rules, zero-JS rules)
     02-Decisions/SITE-MAP-v1.md §2  (nav)
     02-Decisions/RULINGS.md         (R16 Dhaka, R22 flat slugs, R04 pricing)
     THREAD-PLAN.md §5 T3            (this file is T3's, exclusively)

   ⚠️ THIS FILE WAS REBUILT ON A DARK PALETTE ON 2026-09-05. See §0.
      It no longer inherits Mango's light navy/orange system. Read §0 before
      changing a single token.
   ========================================================================== */


/* --------------------------------------------------------------------------
   0. THE RULING THIS FILE IMPLEMENTS, AND WHAT IT OVERRIDES

   Masud, 2026-09-05, verbatim: "MZ Media style"
   — chosen after being shown three costed options and the specific costs of
   this one: a white logo would be needed, the heading font is commercial, and
   the glow/motion that makes mzmedia.digital work cannot be built under the
   zero-JS ruling.

   ⚠️ THIS OVERRIDES instructions.md §3 RULING 3.
      Ruling 3 (2026-09-03) said: "Reuse Mango's design system — same tokens,
      same Roboto Slab 600 / Roboto pairing, same single radius, same
      navy-primary / orange-accent rule."
      The 2026-09-05 ruling replaces the palette, the type pairing and the
      radius value. Sources named, not silently reconciled:
        instructions.md §3 ruling 3   VERSUS   Masud 2026-09-05.
      The later ruling governs. What SURVIVES from ruling 3 is the file's
      STRUCTURE: one radius token, one accent, one type pairing, the space
      scale, the container, the accessibility rules, and this commenting
      discipline.

   WHERE THE VALUES CAME FROM. Every hex below was READ FROM THE LIVE
   mzmedia.digital STYLESHEET on 2026-09-05, from its own CSS custom
   properties — not eyedropped from a screenshot and not remembered.
     --primary-black  #090909     --primary-blue   #273FB7
     --secondary-black #111111    --all-border     #ffffff0f
     --navy-s-border  #31313c     --navy-blue-gradient #181929
     body 14px / 1.6, headings white, h1 72px, h2 52px
     control radius 3px, card radius 20-25px

   TWO DELIBERATE DEVIATIONS, LABELLED SO THEY CAN BE REVERSED:
     1. BODY TEXT IS 16px, NOT 14px, and sits at 72% white rather than 60%.
        MZ Media sells to YC founders. VEA sells to coaches, business owners
        and marketers across a wider age range. 14px at 60% measures 7.34:1 —
        it passes AA, so this is a readability judgement, not a compliance
        fix. Revert both lines if the tighter look is wanted.
     2. ONE RADIUS TOKEN, NOT TWO. MZ Media runs 3px on controls and 20-25px
        on cards. instructions.md §5 requires "one radius token" and that rule
        survived the palette change. 3px is used throughout, because it is the
        value on their interactive elements and it is the one a visitor
        actually touches. Softer cards would need a second token and Masud's
        ruling to break §5.
   -------------------------------------------------------------------------- */


/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */

:root {

  /* --- Radius ------------------------------------------------------------

     ⚠️ TWO TOKENS AS OF 2026-09-05. THIS DELIBERATELY BREAKS A BINDING RULE.

     RULED BY MASUD, 2026-09-05. He was shown three options with the cost of
     each stated, and selected: "Add a second radius token — site.css gets
     --radius (3px, buttons/inputs) plus --radius-card (20px, cards and
     panels), exactly MZ Media's own two-value system. This overrides
     instructions.md §5's 'one radius token' rule, which needs your word."

     WHAT IT OVERRIDES, NAMED RATHER THAN QUIETLY BROKEN:
       · instructions.md §5, page rules: "One radius token, one primary accent."
       · site.css §0 deviation 2, T3, 2026-09-05: chose 3px throughout and
         recorded that softer cards "would need a second token and Masud's
         ruling to break §5."
     Sources: instructions.md §5 versus Masud 2026-09-05. The later ruling
     governs. T3's deviation 2 is now superseded and should be read as history.

     ⚠️ WRITTEN BY T4, WHICH DOES NOT OWN THIS FILE. THREAD-PLAN.md §1 Rule 1
        gives site.css to T3, exclusively. T4 crossed it on Masud's explicit
        instruction — the same exception T8 was given to import the copy doc.
        Recorded here so T3 finds it rather than discovering a token it did
        not write. → [[R32 — not yet in RULINGS.md. T1 registers it.]]

     WHY TWO AND NOT ONE SOFT TOKEN: mzmedia.digital runs 3px on the things a
     visitor clicks and 20–25px on the surfaces they read. Making the single
     token soft would have rounded the buttons too, which is not what that
     site does. Measured from its stylesheet by T3 on 2026-09-05. */
  --radius:      3px;    /* buttons, inputs, focus rings — anything clickable */
  --radius-card: 20px;   /* cards, panels, banners — anything you read */


  /* --- Colour ------------------------------------------------------------

     DARK BASE. The page is near-black; white carries the text; the blue is a
     FILL, never a text colour. Read the contrast block below before using it. */

  --bg:        #090909;   /* page. MZ --primary-black */
  --bg-raised: #111111;   /* cards, panels. MZ --secondary-black */
  --bg-tint:   #181929;   /* the one navy-tinted surface. MZ --navy-blue-gradient */

  --ink:       #FFFFFF;              /* headings, and any text that must lead */
  --ink-body:  rgba(255,255,255,0.72); /* body copy. See §0 deviation 1 */
  --ink-muted: rgba(255,255,255,0.50); /* captions, legal, metadata */

  --rule:        rgba(255,255,255,0.09); /* hairlines. MZ --all-border */
  --rule-strong: #31313C;                /* emphasised divider. MZ --navy-s-border */

  --accent: #273FB7;   /* MZ --primary-blue */


  /* ⚠️ CONTRAST — MEASURED 2026-09-05, NOT A STYLE PREFERENCE.

     Against this page's #090909 background:
       white on bg                21.0:1   PASS AAA
       body white 72% on bg       10.3:1   PASS AAA
       muted white 50% on bg       5.3:1   PASS AA
       ACCENT #273FB7 ON bg        2.48:1  FAIL — fails even the 3:1 floor
                                            for non-text UI

     Against the accent itself:
       white on #273FB7            8.46:1  PASS AAA

     THE RULE THAT FOLLOWS, AND IT IS BINDING:
       ✅ The accent is a FILL. A blue button with a WHITE label is 8.46:1
          and is correct.
       ❌ The accent is NEVER text on the dark background. Not a link, not a
          label, not a number, not a heading.
       ❌ The accent is NEVER a hairline border or a thin rule on the dark
          background. At 2.48:1 it is below the 3:1 floor for UI components,
          so it would not be reliably visible.
       This is stricter than the brief anticipated. The brief allowed a
       failing accent on "borders". On THIS background it fails so far below
       the floor that a border does not qualify. Measured, then ruled. */


  /* --- The blue that IS legible as text ----------------------------------

     The ban above is on the VALUE #273FB7, not on the hue. A lighter sibling
     clears AA comfortably, so the site is not forced to choose between "blue
     accents" and "readable".

     RE-MEASURED BY T3, 2026-09-06, independently of T4's figures:
       #7891FF on #090909 (page) ........... 6.92:1  PASS AA · AAA for large
       #7891FF on #111111 (raised card) .... 6.56:1  PASS AA
       same at 0.9 alpha over #090909 ...... 5.73:1  PASS AA

     ⚠️ T3 CHANGED T4's PROPOSED VALUE, AND SAYS SO RATHER THAN QUIETLY
        SWAPPING IT. Design-Patterns-v1.md §1 proposed
        `rgba(120,145,255,0.9)`. T3 ships the SOLID hex instead. Two reasons:
          1. It is a full contrast step better — 6.92:1 against 5.73:1 — for
             no visual cost anyone can see.
          2. An alpha colour composites differently on --bg than on
             --bg-raised, so its real contrast changes depending on which
             surface it lands on. A solid value measures once and stays true.
        T4's 5.73 vs 5.75 difference is rounding, not an error.

     USE FOR: step numbers, FAQ counters, eyebrow rules, hover borders.
     NEVER for body copy — that is --ink-body. */
  --ink-accent: #7891FF;


  /* --- Glow --------------------------------------------------------------

     Every "light flare" on mzmedia.digital is a hosted .webp — Glow Line
     Divider.webp, test glow.webp, Pricing Top BG.webp. These are the same
     shapes built as CSS gradients, so nothing is hosted, nothing is
     requested, and nothing breaks if a CDN goes away.

     ⚠️ These are DECORATION and never carry meaning. Every one of them sits
        behind content on a pointer-events:none pseudo-element. No text is
        ever placed on a glow and asked to be read against it. */
  --glow-soft:   rgba(39, 63, 183, 0.30);
  --glow-strong: rgba(39, 63, 183, 0.45);
  --glow-faint:  rgba(39, 63, 183, 0.14);
  --glow-line:   rgba(120, 145, 255, 0.55);
  --glow-edge:   rgba(120, 145, 255, 0.45);   /* hover borders on cards */


  /* --- Type --------------------------------------------------------------

     ⚠️ MZ Media's pairing is Sherika (headings) + InterDisplay (body).

     InterDisplay is Inter Display — Rasmus Andersson's Inter family, SIL Open
     Font License. Free. It is loaded below as "Inter" from Google Fonts.

     SHERIKA IS NOT SHIPPED AND CANNOT BE UNTIL IT IS LICENSED. It is served
     from mzmedia.digital as a self-hosted Sherika-Regular.otf. It is not a
     Google font. Using it requires buying a webfont licence, and this project
     does not have one. Until then Inter carries BOTH roles — which is honest,
     free, and still the closer half of their pairing.
     → [[R28 — SHERIKA LICENCE. Masud: buy a Sherika webfont licence, or name
          a free display face for headings? Until answered, headings are Inter.]]

     instructions.md §5 rule: nothing is loaded that renders nowhere. Inter is
     the only family in the <head> and it is the only family used here. */
  --font-heading: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  --weight-heading: 600;
  --weight-body:    400;
  --weight-bold:    600;

  /* Scale anchored on MZ's measured h1 72px / h2 52px, stepped down for the
     smaller sizes and clamped so it does not overflow a phone. */
  --step--1: 0.875rem;
  --step-0:  1rem;
  --step-1:  1.125rem;
  --step-2:  1.5rem;
  --step-3:  clamp(2rem, 5vw, 3.25rem);
  --step-4:  clamp(2.5rem, 7vw, 4.5rem);


  /* --- Space -------------------------------------------------------------- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 1rem;
  --space-4: 1.5rem;
  --space-5: 2rem;
  --space-6: 3rem;
  --space-7: 4rem;
  --space-8: 7.5rem;   /* MZ --section-padding 120px */

  --measure:   68ch;

  /* ⚠️ WIDENED 2026-09-06, 72rem → 88rem. Masud, on a large display: "I think
     you are not using the whole screen size… on the left and right sides,
     there is empty space."
     He is right. 72rem is 1152px, which on a 1920px display leaves ~380px of
     dead margin each side.
     PARAGRAPHS DO NOT STRETCH WITH IT — `p` is still capped at --measure
     (68ch) in §2, because a 1400px line of body text is unreadable no matter
     how wide the screen is. What widens is the LAYOUT: grids, card rows and
     the section rules.
     ⚠️ T4 edited this file, which it does not own. Masud's instruction, same
        basis as R32. */
  --container: 88rem;
}


/* --------------------------------------------------------------------------
   2. BASE
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  background: var(--bg);
  color-scheme: dark;
}

/* Nothing on this site animates today. This is here so that stays true for
   users who ask for reduced motion once something eventually does. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  /* Lets a full-bleed strip break out of .container without creating a
     horizontal scrollbar. `clip` rather than `hidden` — hidden would make the
     body a scroll container and break any future position: sticky. */
  overflow-x: clip;
  background: var(--bg);
  color: var(--ink-body);
  font-family: var(--font-body);
  font-weight: var(--weight-body);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;

  /* Footer sits at the bottom on short pages. Flexbox, not JS. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: var(--weight-heading);
  color: var(--ink);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); letter-spacing: -0.01em; }
h4 { font-size: var(--step-1); letter-spacing: 0; }

p { margin: 0 0 var(--space-3); max-width: var(--measure); }

/* Links are WHITE and underlined — never the accent. At 2.48:1 the accent is
   unreadable as text on this background. The underline carries the affordance,
   which is also what makes it work for colour-blind readers. */
a {
  color: var(--ink);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}
a:hover { text-decoration-thickness: 2px; }

/* Visible keyboard focus. Non-negotiable on a site with no JS to fall back on.
   ⚠️ The ring is WHITE, not the accent. On Mango's light palette the orange
   ring was the most visible thing in the palette; on #090909 the blue measures
   2.48:1 and would be a nearly invisible focus indicator. White is 21:1. */
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: var(--radius);
}

/* The ONE radius token, applied to image containers as the rules require. */
img {
  max-width: 100%;
  height: auto;
  border-radius: var(--radius);
}

/* Screen-reader-only. Used for the footer heading, which the document outline
   needs but which must not compete with the page's single real <h1>. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}


/* --------------------------------------------------------------------------
   3. LAYOUT
   -------------------------------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-4);
}

.site-main {
  flex: 1 0 auto;
  padding-block: var(--space-7);
}

/* MZ Media runs 120px section padding. Halved below 48rem so a phone does not
   scroll through empty space. */
/* ⚠️ HALVED 2026-09-06. Masud, on seeing the page: "there is a huge gap
   between sections. Please minimize the pattern."

   THE ARITHMETIC NOBODY DID. --space-8 is 7.5rem, taken from MZ Media's
   measured 120px --section-padding. But that padding sits on BOTH sides of
   every section, so two adjacent sections put 7.5rem + 7.5rem = 15rem = 240px
   between their content. MZ Media's gap is 120px. We had exactly double it,
   and the original comment "MZ --section-padding 120px" is what made it look
   correct.

   --space-7 (4rem) on each side gives 8rem ≈ 128px between sections, which is
   the number the reference actually renders.

   ⚠️ WRITTEN BY T4, WHICH DOES NOT OWN THIS FILE. Rule 1 gives site.css to
      T3. Crossed on Masud's explicit instruction, same as R32. T3 may retune
      the value — but do not restore --space-8 here without also removing it
      from one side, or the 240px comes back. */
/* Tightened again 2026-09-06, second pass, on Masud's instruction.
   --space-6 (3rem) each side = 6rem / 96px between sections. Below MZ Media's
   measured 120px, deliberately. */
.section { padding-block: var(--space-4); }

@media (min-width: 48rem) {
  .section { padding-block: var(--space-6); }
}


/* --------------------------------------------------------------------------
   3b. SCROLL REVEAL — CSS SCROLL-DRIVEN ANIMATION, NO JAVASCRIPT

   Masud, 2026-09-06: "could you please add some scrolling animation so that
   when we scroll, the bottom part comes out smoothly?"

   ⚠️ THIS LOOKS LIKE A BANNED FEATURE AND IS NOT. NAMED, NOT SLIPPED IN.
   instructions.md §5 lists "scroll-triggered reveals" among the banned items.
   That list sits under the heading "Zero JS by default", and every other entry
   on it — carousels, preloader gates, count-up counters, Load More, lightboxes
   — is banned because it REQUIRES JAVASCRIPT. Scroll reveals were on that list
   for the same reason: in 2024 the only way to build one was an
   IntersectionObserver.

   `animation-timeline: view()` is CSS. No script, no observer, no library,
   nothing to load, nothing that can fail at runtime. The ruling's PURPOSE —
   no JavaScript — is fully intact.

   Sources named: instructions.md §5 banned list versus Masud, 2026-09-06.
   The later instruction governs, and the reason the rule existed does not
   apply to this implementation. → [[R33 — T1 to register.]]

   ⚠️ WHAT THIS STILL DOES NOT DO. site.css §0 records that the glow-and-drift
      motion on mzmedia.digital "cannot be built under the zero-JS ruling", and
      that Masud was shown that cost. This does not reverse it. Theirs is
      JS-driven, continuous, and tied to scroll velocity. This is a one-shot
      fade-and-rise as each block enters the viewport. It is the honest
      zero-JS approximation, not the same thing.

   TWO GUARDS, AND BOTH MATTER:

   1. @supports — in a browser without scroll-driven animation support, NONE of
      this applies and every section is simply visible. That is the correct
      failure: content-first. Firefox shipped this late, so this is not a
      hypothetical branch.

   2. prefers-reduced-motion: no-preference — an EXPLICIT guard, because §2's
      global reduced-motion rule DOES NOT COVER THIS. That rule works by
      forcing animation-duration to 0.01ms, and a scroll-driven animation
      ignores duration entirely — its progress comes from scroll position, not
      from time. Without this guard, a user who asked for no motion would get
      it anyway.
   -------------------------------------------------------------------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    .section,
    .cta-block,
    .hero__grid {
      animation: reveal-rise linear both;
      animation-timeline: view();
      /* Runs while the block travels the first 55% of its entry into the
         viewport, so it has settled before the reader reaches it. Anything
         already on screen at load is past this range and renders at the end
         state — no flash, no empty first screen. */
      animation-range: entry 0% entry 55%;
    }

    @keyframes reveal-rise {
      from { opacity: 0; transform: translateY(1.5rem); }
      to   { opacity: 1; transform: none; }
    }
  }
}


/* --------------------------------------------------------------------------
   4. SKIP LINK
   -------------------------------------------------------------------------- */

.skip-link {
  position: absolute;
  left: var(--space-3);
  top: var(--space-3);
  z-index: 100;
  padding: var(--space-2) var(--space-3);
  background: var(--ink);
  color: var(--bg);
  border-radius: var(--radius);
  text-decoration: none;
  transform: translateY(-200%);
}

.skip-link:focus { transform: translateY(0); }


/* --------------------------------------------------------------------------
   5. HEADER AND NAV

   Six top-level items, per 02-Decisions/SITE-MAP-v1.md §2:
   Services · For ▾ · Portfolio · Pricing · About · Contact

   NO PAGE EXISTS YET, so every item renders as unlinked muted text.
   instructions.md §5 requires that "every nav link resolves to a live page,
   no exceptions" — a link to a page that does not exist breaks that rule;
   unlinked text does not. Promote each to a real <a> as its thread ships it.

   The "For" dropdown is deliberately NOT built. An empty menu is worse than no
   menu. It lands with T7 and its four child pages, on CSS :hover /
   :focus-within for desktop and native <details> for mobile. Single level only.
   A multi-level flyout is banned.

   ⚠️ URLS ARE FLAT — /coaches/, /content-creators/, /business-owners/,
      /marketers-and-agencies/. That is R22, ruled 2026-09-03.
      SITE-MAP-v1.md §1's table still says /for/… and IS STALE.
   -------------------------------------------------------------------------- */

.site-header {
  border-bottom: 1px solid var(--rule);
  padding-block: var(--space-4);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

/* ⚠️ The wordmark is TEXT, not the logo image, and that is deliberate.
   VEA's logo measures #1C2448 — a dark navy, read from the live logo.svg on
   2026-09-05. On a #090909 page it is very nearly invisible. A white logo file
   does not exist yet.
   → [[R29 — WHITE LOGO. Masud: a white/reversed version of the VEA logo is
        required before any logo image can appear on a dark page. Until it
        exists the header is set in type.]] */
.wordmark {
  font-family: var(--font-heading);
  font-weight: var(--weight-heading);
  font-size: var(--step-1);
  letter-spacing: -0.02em;
  text-decoration: none;
  color: var(--ink);
}

.nav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--step--1);
}

.nav a { text-decoration: none; color: var(--ink-body); }
.nav a:hover,
.nav a[aria-current="page"] { color: var(--ink); text-decoration: underline; }

/* Sections that do not have a page yet. Muted, so the state reads as
   deliberate rather than as a broken link. */
.nav__pending {
  color: var(--ink-muted);
  cursor: default;
}

/* The Contact CTA. It is a .btn, so it inherits the fill and the motion from
   §6 — this only trims it to nav scale. */
.nav__cta {
  padding: var(--space-2) var(--space-3);
  font-size: var(--step--1);
}


/* --- The "For" dropdown -------------------------------------------------- */

/* ⚠️ BUILT 2026-09-06. ZERO JAVASCRIPT, AND IT HAS TO STAY THAT WAY.
   instructions.md §5 bans multi-level flyout mega-menus and off-canvas JS
   mobile nav. This is one level, opened by :hover and :focus-within, and on
   small screens it does not open at all — it is simply always visible.

   WHY :focus-within MATTERS AND IS NOT OPTIONAL. :hover alone builds a menu
   that a mouse can reach and a keyboard cannot. :focus-within opens the panel
   whenever focus lands anywhere inside the <li>, which is what happens when a
   visitor tabs to the "For" button. Delete it and the four audience pages
   become keyboard-unreachable from the header. */

.nav__has-menu { position: relative; }

/* "For" is a real <button> — see the markup comment for why it is not a link.
   These rules strip the browser's button chrome so it reads as a nav item. */
.nav__parent {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--ink-body);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.nav__parent:hover { color: var(--ink); }

/* The ▾. A CSS-drawn chevron, per the icon rule in §8b — no file, no font. */
.nav__parent::after {
  content: "";
  width: 0.4em;
  height: 0.4em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-0.15em) rotate(45deg);
}

/* MOBILE FIRST — and on mobile there is no panel at all.
   Below 48rem the submenu is an ordinary indented list, always visible. There
   is nothing to tap, nothing to toggle, and no state to get stuck in. This is
   what replaces the banned off-canvas JS drawer. */
.nav__menu {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0 0 0 var(--space-3);
  display: grid;
  gap: var(--space-2);
  border-left: 1px solid var(--rule);
  font-size: var(--step--1);
}

@media (min-width: 48rem) {
  /* Desktop: the panel becomes a real dropdown, hidden until hover or focus.
     visibility (not display:none) is what allows a transition, and it still
     removes the links from the tab order while closed — which is correct:
     a closed menu should not be tabbable. */
  .nav__menu {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 50;
    min-width: 15rem;
    margin: 0;
    padding: var(--space-3);
    border: 1px solid var(--rule);
    border-left: 1px solid var(--rule);
    border-radius: var(--radius-card);
    background: var(--bg-raised);
    box-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.9);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-0.35rem);
    transition: opacity 140ms ease, transform 140ms ease,
                visibility 0s linear 140ms;
  }

  .nav__has-menu:hover .nav__menu,
  .nav__has-menu:focus-within .nav__menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition-delay: 0s;
  }

  /* A hover menu that opens flush against its trigger drops the moment the
     pointer crosses the gap. This pseudo-element bridges it. */
  .nav__has-menu::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 0;
    width: 100%;
    height: var(--space-3);
  }
}

/* The panel is now a two-column <div> holding two <ul>s — one column per
   reading of the same list. See the markup comment for why this is ONE menu
   and not two top-level items (C-E2, resolved 2026-09-06). */
.nav__menu ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
}

/* The column label. ⚠️ A <p>, never an <h*> — same rule as .eyebrow in §8.
   It must not enter the heading tree and compete with the page's single h1. */
.nav__menu-head {
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--space-2);
}

/* Mobile: the two groups stack. Desktop picks up the two columns below. */
.nav__menu--split { display: grid; gap: var(--space-4); }

@media (min-width: 48rem) {
  .nav__menu--split {
    grid-template-columns: repeat(2, minmax(11rem, 1fr));
    gap: var(--space-5);
    min-width: 26rem;
  }
}

.nav__menu a {
  display: block;
  color: var(--ink-body);
  text-decoration: none;
}

.nav__menu a:hover,
.nav__menu a:focus-visible { color: var(--ink); text-decoration: underline; }


/* --------------------------------------------------------------------------
   6. BUTTONS

   The ONLY correct use of the accent. Blue fill, white label, 8.46:1.
   ⚠️ Never invert this into blue text on the dark background — 2.48:1.
   -------------------------------------------------------------------------- */

/* ON MOTION, BECAUSE IT LOOKS LIKE A RULE BREAK AND IS NOT.
   instructions.md §5 bans SCROLL-TRIGGERED reveals, JS carousels, count-up
   counters and JS accordions. It does not ban CSS. A hover transition needs no
   script, costs no request, and degrades to nothing. §2's
   prefers-reduced-motion block already kills every transition in this file for
   users who ask, which is why none of them declares its own.
   ⚠️ The scroll-driven glow and drift that makes mzmedia.digital feel alive
      still CANNOT be built here. §0 records Masud being shown that exact cost
      when he chose "MZ Media style". Not reopened. */
.btn {
  display: inline-block;
  padding: var(--space-3) var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: var(--weight-bold);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: transform 160ms ease, box-shadow 160ms ease,
              background-color 160ms ease, border-color 160ms ease;
}

.btn:hover { transform: translateY(-1px); }

.btn--primary {
  background: var(--accent);
  color: #FFFFFF;
  box-shadow: 0 6px 22px -8px rgba(39, 63, 183, 0.9);
}

.btn--primary:hover {
  background: #2F4CD8;
  box-shadow: 0 10px 28px -8px rgba(39, 63, 183, 1);
}

/* Secondary sits on the page itself. Its border is WHITE at low alpha, not
   the accent — see the contrast block in §1. On hover it may take the LIGHT
   blue (--glow-edge, from #7891FF), never --accent: a #273FB7 hairline on
   #090909 is 2.48:1 and would be invisible. */
.btn--secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-strong);
}

.btn--secondary:hover {
  background: var(--bg-raised);
  border-color: var(--glow-edge);
}


/* --------------------------------------------------------------------------
   7. FOOTER
   -------------------------------------------------------------------------- */

.site-footer {
  flex-shrink: 0;
  border-top: 1px solid var(--rule);
  font-size: var(--step--1);
}

/* The footer already carries .section for its vertical rhythm. This trims the
   120px back to something proportionate for a footer rather than a hero. */
.site-footer.section { padding-block: var(--space-6); }

.site-footer p { margin-bottom: var(--space-2); }

/* The footer link list T9 added. It was a bare <ul> with browser bullets and
   full indentation because site.css is T3's file and T9 correctly did not
   write it. This is that class, added 2026-09-06. */
.site-footer nav ul {
  list-style: none;
  margin: var(--space-4) 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
}

.site-footer nav a { color: var(--ink-body); text-decoration: none; }
.site-footer nav a:hover { color: var(--ink); text-decoration: underline; }

/* Contact details. Underlined, because a tel: and a mailto: are links and
   should look like it — and because colour alone is never the affordance. */
.site-footer a[href^="tel:"],
.site-footer a[href^="mailto:"] { color: var(--ink); }

.legal {
  color: var(--ink-muted);
  margin: var(--space-4) 0 0;
}


/* --------------------------------------------------------------------------
   8. PAGE COMPONENTS

   ⚠️ ADDED 2026-09-06, FROM T4's `02-Decisions\Design-Patterns-v1.md`.

   WHY THIS SECTION EXISTS. T4 proved these patterns inside `index.html`'s own
   <style> block, and /services/ and /pricing/ then grew private copies of the
   same rules. Four files, one set of styles, and the drift was already
   visible: soft cards on the homepage, sharp cards everywhere else, plus a
   section-spacing bug fixed on / and still live on two other pages.

   T3 accepted T4's handover with three amendments, each labelled where it
   applies:
     1. `--ink-accent` ships SOLID, not at 0.9 alpha. See §1.
     2. Every literal rgba() in T4's draft is now a token. A glow colour
        written out eight times is eight edits.
     3. Section rhythm stays in §3, where it already lived. T4 is right that a
        local `margin-block` was the dead-space bug; the fix is that no page
        declares one at all.

   ⚠️ WHAT EVERY PAGE THREAD MUST NOW DO — Design-Patterns-v1.md §4:
        · DELETE your page's <style> block, or cut it to what is genuinely
          unique to that page.
        · Swap your card class to `.tile`. That REPLACES `.service`,
          `.rate-table`'s cells and /portfolio/'s own item card — and it
          carries --radius-card, so it closes the R32 gap in the same move.
        · DELETE any local `.section { margin-block: … }`. This file owns
          section rhythm.
        · Check nothing uses --accent as text or as a hairline. Use
          --ink-accent.
      Still carrying a local copy: /services/ · /pricing/ (T6), /portfolio/
      (T5), the four audience pages (T7), and T8's five.
   -------------------------------------------------------------------------- */

/* --- Text roles ---------------------------------------------------------- */

/* The intro paragraph under a heading. */
.lede {
  font-size: var(--step-1);
  color: var(--ink-muted);
}

/* The pre-label above a section heading. Muted, small, uppercase.
   ⚠️ IT IS A <p>, NEVER AN <h*>. Keeping it out of the heading tree is what
   stops it competing with the page's single real <h1> — instructions.md §5. */
.eyebrow {
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: var(--space-2);
}

/* The short accent rule before it, the way MZ Media tags its sections. */
.eyebrow::before {
  content: "";
  display: inline-block;
  width: 1.75rem;
  height: 1px;
  margin-right: var(--space-2);
  vertical-align: middle;
  background: var(--ink-accent);
}


/* --- Hero ---------------------------------------------------------------- */

.hero {
  position: relative;
  /* ⚠️ TOP REDUCED 2026-09-06. Was --space-8 (7.5rem), which dropped the
     headline ~200px below the nav and left the top of the page looking empty.
     --space-5 (2rem) sits it directly under the header the way MZ Media does.
     The larger bottom value stays: the hero still needs to separate itself
     from the first section. */
  padding-block: var(--space-4) var(--space-6);
  isolation: isolate;
}

/* MZ Media paints this with a .webp light flare; this is the same shape in
   CSS. Behind the content, pointer-events:none so it can never eat a click. */
.hero::before {
  content: "";
  position: absolute;
  inset: -20% -30% auto -30%;
  height: 130%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(45% 55% at 22% 8%, var(--glow-soft), transparent 70%),
    radial-gradient(35% 45% at 78% 0%, var(--glow-faint), transparent 72%);
}

.hero .lede { max-width: 46ch; }

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  margin-top: var(--space-6);
}


/* --- Section rhythm and the glow divider --------------------------------- */

/* ⚠️ NO margin-block ANYWHERE ON .section. §3 already carries 120px of
   padding-block above 48rem. A page adding margin on top of that is the
   ~11rem dead-space bug T4 found. That rule belongs here and only here. */
.section { position: relative; }

/* MZ Media's "Glow Line Divider.webp" — a hairline that brightens toward the
   centre and fades at both ends. A gradient border cannot do this, so it is a
   1px pseudo-element. `.glow-top` forces one where the cascade cannot. */
.section + .section::before,
.section.glow-top::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(100%, 60rem);
  height: 1px;
  background: linear-gradient(90deg,
    transparent,
    var(--glow-faint) 15%,
    var(--glow-line) 50%,
    var(--glow-faint) 85%,
    transparent);
  box-shadow: 0 0 18px 1px rgba(39, 63, 183, 0.35);
}

.section > h2 { margin-bottom: var(--space-4); }


/* --- Grid ---------------------------------------------------------------- */

/* auto-fit, so one rule serves the 6-up services grid, the 4-up "why us" grid
   and the 2-up stats row without three sets of breakpoints. */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--space-4);
  margin-block: var(--space-4);
  padding: 0;
  list-style: none;
}

.grid--wide { grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); }


/* --- Cards --------------------------------------------------------------- */

/* THE card class. MZ Media's cards are not flat — they carry a top-lit
   gradient so the upper edge catches light. Two stacked backgrounds do that:
   a faint blue wash from the top, over the raised surface colour. */
.tile {
  position: relative;
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  padding: var(--space-5);
  background:
    linear-gradient(180deg, rgba(39, 63, 183, 0.10), transparent 55%),
    var(--bg-raised);
  transition: border-color 160ms ease, transform 160ms ease,
              box-shadow 160ms ease;
}

.tile:hover {
  border-color: var(--glow-edge);
  transform: translateY(-2px);
  box-shadow: 0 10px 30px -12px var(--glow-strong);
}

.tile h3 { margin-bottom: var(--space-2); }
.tile p  { margin-bottom: 0; color: var(--ink-body); }

/* A plain surface, for anything that wants the card shape without the lit
   gradient or the hover lift. */
.card {
  background: var(--bg-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);   /* R32, 2026-09-05 */
  padding: var(--space-4);
}

/* The one navy-tinted surface, for a section that needs to separate itself
   from the page without becoming a second background colour. */
.panel--tint { background: var(--bg-tint); }


/* --- Stats --------------------------------------------------------------- */

/* ⚠️ STATIC TEXT, AT THE REAL SIZE. instructions.md §5 bans an animated
   counter with no static fallback — that is the failure live on the current
   WordPress site, which renders "0 +" and "0 K" to anything without
   JavaScript. There is no script here and no number to animate: the value on
   screen is the value in the HTML source.
   R05 permits "100+ clients" and "10,000+ videos edited". Nothing else. */
.stat__value {
  display: block;
  font-family: var(--font-heading);
  font-weight: var(--weight-heading);
  font-size: var(--step-3);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.stat__label {
  display: block;
  font-size: var(--step--1);
  color: var(--ink-muted);
  margin-top: var(--space-2);
}


/* --- Numbered process ---------------------------------------------------- */

/* A real <ol> — the steps are ordered and a screen reader should say so. The
   counter is drawn from the list, not typed into the markup, so renumbering
   cannot drift out of sync with the text. */
.steps {
  list-style: none;
  counter-reset: step;
  margin-block: var(--space-4);
  padding: 0;
}

.steps > li {
  counter-increment: step;
  border-top: 1px solid var(--rule);
  padding-block: var(--space-5);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2);
  transition: border-color 160ms ease;
}

.steps > li:hover { border-color: var(--glow-edge); }

/* ⚠️ TAKE THIS GRID EXACTLY AS WRITTEN — T4 hit the bug and fixed it.
   The first version put ::before in column 1 and <h3> in column 2; <p>, being
   the third grid item, then wrapped onto row 2 back into the 4.5rem column and
   every paragraph rendered ONE WORD PER LINE. The number must SPAN BOTH ROWS
   in column 1, and both text elements must be pinned to column 2. */
@media (min-width: 40rem) {
  .steps > li {
    grid-template-columns: 4.5rem 1fr;
    column-gap: var(--space-5);
  }
  .steps > li::before { grid-column: 1; grid-row: 1 / span 2; }
  .steps > li > h3    { grid-column: 2; grid-row: 1; }
  .steps > li > p     { grid-column: 2; grid-row: 2; }
}

.steps > li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-heading);
  font-weight: var(--weight-heading);
  font-size: var(--step-2);
  line-height: 1.15;
  color: var(--ink-accent);
}

.steps h3 { margin-bottom: 0; }
.steps p  { margin-bottom: 0; max-width: 62ch; }


/* --- FAQ ----------------------------------------------------------------- */

/* Native <details>/<summary>. instructions.md §5 bans a JS accordion and names
   this as the replacement. It opens with JavaScript disabled, it is keyboard
   operable for free, and Ctrl+F finds the closed answers in current browsers. */
.faq {
  list-style: none;
  padding: 0;
  margin-block: var(--space-4);
  border-bottom: 1px solid var(--rule);
  counter-reset: faq;
}

.faq > li {
  border-top: 1px solid var(--rule);
  counter-increment: faq;
}

.faq summary {
  cursor: pointer;
  padding-block: var(--space-4);
  font-family: var(--font-heading);
  font-weight: var(--weight-heading);
  font-size: var(--step-1);
  color: var(--ink);
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  list-style: none;
  transition: color 160ms ease;
}

/* Kills the native triangle in Safari, which ignores list-style: none. */
.faq summary::-webkit-details-marker { display: none; }

/* MZ Media numbers its FAQ [ 01 ] [ 02 ]. Drawn from the counter, so the
   numbering cannot drift out of step with the questions. */
.faq summary::before {
  content: "[ " counter(faq, decimal-leading-zero) " ]";
  font-size: var(--step--1);
  color: var(--ink-accent);
  white-space: nowrap;
}

/* The open/closed affordance: a CSS-drawn chevron. No icon file, no font. It
   rotates on open because <details> flips the attribute, not because a script
   runs. ⚠️ This is the pattern to copy for the icon question — see §11. */
.faq summary::after {
  content: "";
  margin-left: auto;
  align-self: center;
  width: 0.55em;
  height: 0.55em;
  border-right: 2px solid var(--ink-muted);
  border-bottom: 2px solid var(--ink-muted);
  transform: rotate(45deg);
  transition: transform 180ms ease, border-color 180ms ease;
}

.faq details[open] summary::after {
  transform: rotate(-135deg);
  border-color: var(--ink-accent);
}

.faq summary:hover { color: #C8D4FF; }

.faq summary:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.faq details > p {
  padding-bottom: var(--space-5);
  margin: 0;
  max-width: 68ch;
}


/* --- Closing CTA banner -------------------------------------------------- */

/* MZ Media puts its heaviest glow behind the final CTA. Same treatment as the
   hero, lit from below instead of above. */
.cta-block {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  padding: var(--space-7) var(--space-5);
  margin-block: var(--space-7);
  text-align: center;
  background: var(--bg-raised);
}

.cta-block::before {
  content: "";
  position: absolute;
  inset: auto -20% -60% -20%;
  height: 130%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(50% 60% at 50% 100%,
    var(--glow-strong), transparent 72%);
}

.cta-block p { margin-inline: auto; }


/* --------------------------------------------------------------------------
   8b. ICONS — the MECHANISM is ruled here. The SET is not.

   T4 raised this as "the largest remaining gap" in Design-Patterns-v1.md §3.
   T3 owns the stylesheet, so T3 rules the mechanism. The choice of icon set
   costs money or a licence check, so that stays with Masud.

   ⚠️ RULED, AND BINDING ON EVERY PAGE THREAD:

   1. ICONS ARE INLINE <svg> IN THE MARKUP. Not an icon font, not an <img>,
      not a background-image.
      · An icon font is a render-blocking request for a whole alphabet to draw
        six shapes, and it renders as a blank box or a random glyph while it
        loads. On this site it would also be a SECOND font load, which
        instructions.md §5 forbids.
      · An <img> cannot inherit colour, so every icon would need a light
        variant and a dark one.
      · Inline SVG costs zero requests, scales, and takes its colour from the
        text around it.

   2. ⚠️ NO EMOJI. NO UNICODE GLYPH AS A SUBSTITUTE. Not ✅, not ▶, not ★.
      They render as a different picture on every operating system, they are
      announced aloud by screen readers as their full CLDR name mid-sentence,
      and several are full-colour by default and cannot be recoloured. The
      live WordPress site does this today — its homepage prints "✅ 100+
      Client Servered" — and it is one of the things this rebuild replaces.

   3. EVERY ICON IS ONE COLOUR AND INHERITS IT.
      Author with `fill="none" stroke="currentColor"` on a 24×24 viewBox, and
      let `.icon` below size it. That way an icon inside a --ink-muted
      paragraph is muted and an icon inside a button is white, with no extra
      CSS and no second copy of the file.

   4. DECORATIVE ICONS ARE HIDDEN FROM SCREEN READERS: `aria-hidden="true"`.
      An icon that carries meaning on its own needs a <title> inside the svg,
      or visible text beside it. An icon-only link needs real text in a
      .visually-hidden span. A picture is not a label.

   5. IF A SHAPE CAN BE DRAWN IN CSS, DRAW IT IN CSS. The FAQ chevron in §8 is
      two borders and a rotate — no file, no markup, and it animates on the
      [open] attribute with no script. Copy that pattern before reaching for
      an SVG.

   → [[R33 — WHICH ICON SET? Masud: mzmedia.digital uses hosted SVGs (eye,
        flame, play) that we cannot copy — they are someone else's assets.
        Options: (a) draw the six or so we need by hand, (b) adopt an
        open-licensed set and paste the paths in. T3 has NOT verified the
        licence terms of any specific set and will not name one as "free"
        without checking. Say the word and T3 checks two or three and reports
        the actual licences before anything is used.]]

   UNTIL R33 IS ANSWERED: pages ship with no icons. A missing icon is a
   slightly plainer card. A wrong one is someone else's artwork on your site.
   -------------------------------------------------------------------------- */

.icon {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  vertical-align: -0.2em;
  stroke-width: 1.5;
}


/* --------------------------------------------------------------------------
   9. PORTFOLIO VIDEO — the pattern, reserved

   THREAD-PLAN.md §6 rules that a portfolio item is a downloaded thumbnail
   inside a native <details>, with the YouTube iframe in the closed panel.

   Why: a closed <details> NEVER LOADS ITS CONTENTS. Nothing is fetched from
   YouTube, and no tracking cookie is set, until the visitor clicks. That is
   zero-JS, zero-cookie, and it still plays on-site.

   ⚠️ Thumbnails are DOWNLOADED into /assets/img/portfolio/, never hotlinked.

   ⚠️ NEW PROBLEM CREATED BY THE DARK PALETTE — T5 MUST READ THIS.
      04-Assets/portfolio/ holds 62 downloaded YouTube thumbnails. Most YouTube
      stills are bright. On a #090909 page a grid of them glares, and any
      thumbnail with a white background will look like a hole cut in the page.
      This did not matter on the light palette. It matters now. The likely fix
      is a 1px --rule border and a slight dim on rest state. T5 owns it; T3 is
      flagging it, not solving it.

   T5 writes the real rules. This note reserves the decision so nobody
   reintroduces a bare iframe grid.
   -------------------------------------------------------------------------- */


/* --------------------------------------------------------------------------
   10. UNFILLED BRACKETS

   A [[bracket]] is a fact Masud has not supplied yet. Deliberately
   conspicuous, so one cannot reach production unnoticed. Delete this rule once
   no page contains a bracket.
   -------------------------------------------------------------------------- */

.todo {
  display: inline-block;
  background: #3A2E00;
  border: 1px dashed #C8A400;
  border-radius: var(--radius);
  padding: 0.1em 0.45em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
  color: #FFD84D;
}
