/* ============================================================================
   MailMorph Media — stylesheet  (v2: reference-site visual language)
   ----------------------------------------------------------------------------
   The user asked on 2026-08-31 for the look of hamiltonemails.co, having first
   been shown the knock-off risk and chosen it anyway. So:

     - acid lime accent on a cool off-white ground, near-black ink
     - oversized geometric-grotesque headings, tight tracking
     - lime pill eyebrows above centred section headings
     - generously rounded white cards (12px small / 24px large)
     - lime tick marks, lime pill buttons, giant lime stat numbers

   NOT taken from them, deliberately: their copy, their photography, their client
   logos, their case-study figures, and Muoto — a licensed commercial typeface we
   have no right to use. Outfit is the closest freely-licensed geometric sans.

   v1 (warm stone + ultramarine, Archivo variable-axis system) is archived beside
   this file as mailmorph-v1-own-identity.css.bak if you ever want it back.
   ========================================================================= */

:root {
  --paper:      #F4F4F6;
  --surface:    #FFFFFF;
  --sunken:     #EAEAEE;
  --ink:        #000000;
  --muted:      #5E5E63;
  --faint:      #8A8A90;
  --line:       #E3E3E8;
  --rule:       #D2D2D9;
  --accent:     #3BEF3B;
  --accent-ink: #2BD62B;
  --accent-soft:#DDFBDD;
  --on-accent:  #000000;
  --dark:       #000000;
  --on-dark:    #F4F4F6;
  --dark-line:  #1E1E1E;
  --dark-muted: #C4C4C8;
  --dark-field: #141414;
  --todo-bg:    #FFE9A8;
  --todo-fg:    #4A3200;
  --todo-line:  #B08900;

  --display: "Outfit", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --body:    "Outfit", "Segoe UI", "Helvetica Neue", Arial, sans-serif;

  --measure: 68ch;
  --shell: 1240px;
  --pad: clamp(20px, 5vw, 40px);
  --r-sm: 12px;
  --r-lg: 24px;
  --r-pill: 999px;

  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:      #0A0A0A;
    --surface:    #141414;
    --sunken:     #1C1C1C;
    --ink:        #F4F4F6;
    --muted:      #A3A3AD;
    --faint:      #7C7C86;
    --line:       #2A2A31;
    --rule:       #3A3A44;
    --accent:     #3BEF3B;
    --accent-ink: #6BF56B;
    --accent-soft:#0E2A0E;
    --on-accent:  #000000;
    --dark:       #000000;
    --on-dark:    #F2F2F5;
    --dark-line:  #24242B;
    --dark-muted: #A3A3AD;
    --dark-field: #16161A;
    --todo-bg:    #4A3A12;
    --todo-fg:    #FFE9A8;
    --todo-line:  #8A6E20;
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --paper:      #0A0A0A;
  --surface:    #141414;
  --sunken:     #1C1C1C;
  --ink:        #F4F4F6;
  --muted:      #A3A3AD;
  --faint:      #7C7C86;
  --line:       #2A2A31;
  --rule:       #3A3A44;
  --accent:     #3BEF3B;
  --accent-ink: #6BF56B;
  --accent-soft:#0E2A0E;
  --on-accent:  #000000;
  --dark:       #000000;
  --on-dark:    #F2F2F5;
  --dark-line:  #24242B;
  --dark-muted: #A3A3AD;
  --dark-field: #16161A;
  --todo-bg:    #4A3A12;
  --todo-fg:    #FFE9A8;
  --todo-line:  #8A6E20;
  color-scheme: dark;
}

/* ---------------------------------------------------------------- reset */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition-duration: .001ms !important; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
@media (min-width: 760px) { body { font-size: 18px; } }

img, svg { max-width: 100%; height: auto; display: block; }
a { color: var(--ink); text-underline-offset: 3px; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

/* ---------------------------------------------------------------- layout */

.shell { max-width: var(--shell); margin-inline: auto; padding-inline: var(--pad); }
.measure { max-width: var(--measure); }
section { padding-block: clamp(56px, 8vw, 104px); }

/* ---------------------------------------------------------------- type */

h1, h2, h3, .display {
  font-family: var(--display);
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.02;
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: clamp(2.5rem, 6.6vw, 4.6rem); }
h2 { font-size: clamp(2rem, 5vw, 3.4rem); }
h3 { font-size: 1.2rem; letter-spacing: -0.018em; line-height: 1.25; }

p { margin: 0 0 18px; }
p:last-child { margin-bottom: 0; }
strong { font-weight: 600; }
.lede { font-size: clamp(1.02rem, 2vw, 1.16rem); color: var(--muted); }

/* the lime pill eyebrow that sits above every section heading */
.eyebrow {
  display: inline-block;
  background: var(--accent); color: var(--on-accent);
  font-size: 12.5px; font-weight: 600;
  padding: 5px 13px; border-radius: var(--r-pill);
  margin: 0 0 22px;
}

.section-head { text-align: center; max-width: 46ch; margin-inline: auto; }
.section-head .lede { margin-top: 18px; }
.section-head.left { text-align: left; margin-inline: 0; max-width: 56ch; }

/* ---------------------------------------------------------------- header */

.masthead { position: sticky; top: 0; z-index: 60; background: var(--paper); }
.masthead .shell { display: flex; align-items: center; gap: 18px; height: 78px; }
.brand {
  display: flex; align-items: center; gap: 9px; text-decoration: none; color: var(--ink);
  font-family: var(--display); font-weight: 600; font-size: 1.35rem; letter-spacing: -0.035em;
}
.brand svg { width: 24px; height: 24px; flex: none; }
.masthead nav { margin-left: auto; display: none; gap: 30px; align-items: center; }
@media (min-width: 1000px) { .masthead nav { display: flex; } }
.masthead nav a { font-size: 16px; color: var(--ink); text-decoration: none; }
.masthead nav a:hover { color: var(--muted); }
.masthead .btn { margin-left: auto; }
@media (min-width: 1000px) { .masthead .btn { margin-left: 26px; } }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--display); font-weight: 600; font-size: 15.5px; line-height: 1;
  text-decoration: none; padding: 15px 24px; border-radius: var(--r-pill);
  border: 1.5px solid transparent; cursor: pointer;
  transition: background-color .16s ease, border-color .16s ease, color .16s ease;
}
.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-ink); color: var(--on-accent); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--rule); }
.btn-ghost:hover { border-color: var(--ink); color: var(--ink); }
.btn-sm { padding: 11px 18px; font-size: 14.5px; }

/* ---------------------------------------------------------------- hero */

.hero { padding-block: clamp(30px, 5vw, 56px) clamp(50px, 7vw, 88px); }
.hero-grid { display: grid; gap: 44px; align-items: center; }
@media (min-width: 1000px) { .hero-grid { grid-template-columns: 1.02fr .98fr; gap: 56px; } }

.badge-pill {
  display: inline-flex; align-items: center; gap: 9px;
  border: 1.5px solid var(--rule); border-radius: var(--r-pill);
  padding: 9px 18px; font-size: 15px; font-weight: 500; margin-bottom: 26px;
}
.badge-pill svg { width: 17px; height: 17px; }

.hero h1 { max-width: 14ch; }
.hero .lede { margin-top: 24px; max-width: 46ch; font-size: clamp(1.05rem, 2.1vw, 1.22rem); }
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 20px; margin-top: 34px; }
.hero-note { font-size: 14.5px; color: var(--faint); margin-top: 20px; }

/* hero visual: three drawn email cards. Wireframes of our own, not client work. */
.hero-visual { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; align-items: end; }
@media (max-width: 999px) { .hero-visual { max-width: 460px; } }
.mailcard {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 14px; aspect-ratio: 9 / 16; display: flex; flex-direction: column; gap: 9px;
  overflow: hidden;
}
.mailcard:nth-child(1) { transform: translateY(16px) rotate(-2deg); }
.mailcard:nth-child(3) { transform: translateY(16px) rotate(2deg); }
.mailcard .label { font-size: 9.5px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase; color: var(--faint); }
.mailcard .bar { height: 7px; border-radius: 4px; background: var(--sunken); }
.mailcard .bar.w85 { width: 85%; }
.mailcard .bar.w60 { width: 60%; }
.mailcard .block { flex: 1; border-radius: var(--r-sm); background: var(--sunken); min-height: 40px; }
.mailcard .block.lime { background: var(--accent); }
.mailcard .block.dark { background: var(--ink); }
.mailcard .cta { height: 24px; border-radius: var(--r-pill); background: var(--ink); }
.mailcard .cta.lime { background: var(--accent); }

/* ---------------------------------------------------------------- proof slots */

.slot {
  border: 2px dashed var(--rule); border-radius: var(--r-lg);
  background: var(--surface); padding: clamp(26px, 4vw, 40px); text-align: center;
}
.slot .tag {
  display: inline-block; background: var(--todo-bg); color: var(--todo-fg);
  border: 1px dashed var(--todo-line); border-radius: var(--r-pill);
  font-size: 12px; font-weight: 600; padding: 4px 12px; margin-bottom: 16px;
}
.slot h3 { margin-bottom: 10px; }
.slot p { color: var(--muted); font-size: 15.5px; max-width: 58ch; margin-inline: auto; }
.slot-grid { display: grid; gap: 14px; margin-top: 28px; }
.slot-grid.cols-6 { grid-template-columns: repeat(2, 1fr); }
.slot-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
.slot-grid.cols-3 { grid-template-columns: 1fr; }
@media (min-width: 720px) {
  .slot-grid.cols-6 { grid-template-columns: repeat(3, 1fr); }
  .slot-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 1000px) {
  .slot-grid.cols-6 { grid-template-columns: repeat(6, 1fr); }
  .slot-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
}
.slot-tile {
  border: 1.5px dashed var(--rule); border-radius: var(--r-sm); background: var(--paper);
  aspect-ratio: 7 / 5; display: grid; place-items: center;
  font-size: 12px; color: var(--faint); font-weight: 500; text-align: center; padding: 6px;
}
.slot-tile.tall { aspect-ratio: 3 / 4; }

/* ---------------------------------------------------------------- capability cards */

.cards { display: grid; gap: 22px; margin-top: 48px; }
@media (min-width: 860px) { .cards { grid-template-columns: 1fr 1fr; } }
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  overflow: hidden; display: flex; flex-direction: column;
}
.card-top {
  background: var(--dark); color: var(--on-dark); padding: 32px 28px 26px;
  min-height: 200px; display: flex; flex-direction: column; justify-content: flex-end;
}
.card-top .stat {
  font-family: var(--display); font-weight: 500; letter-spacing: -0.04em;
  font-size: clamp(2.4rem, 5.4vw, 3.3rem); line-height: .95; color: var(--accent);
}
.card-top .stat-sub { font-size: 15px; font-weight: 600; margin-top: 10px; }
.card-body { padding: 26px 28px 28px; display: flex; flex-direction: column; gap: 14px; flex: 1; }
.card-body .kicker { font-size: 13px; color: var(--muted); font-weight: 500; }
.card-body h3 { font-size: 1.28rem; }
.card-body ul { list-style: none; margin: 0; padding: 0; flex: 1; }
.card-body li { position: relative; padding-left: 30px; margin-bottom: 12px; font-size: 15.5px; color: var(--muted); }
.card-body li::before {
  content: ""; position: absolute; left: 0; top: .18em; width: 19px; height: 19px;
  border-radius: 50%; background: var(--accent);
}
.card-body li::after {
  content: ""; position: absolute; left: 6.5px; top: .42em; width: 5px; height: 9px;
  border-right: 2px solid var(--on-accent); border-bottom: 2px solid var(--on-accent);
  transform: rotate(42deg);
}

/* ---------------------------------------------------------------- problem rows */

.rows { margin-top: 46px; border-top: 1px solid var(--rule); }
.row { border-bottom: 1px solid var(--rule); padding: 26px 0; display: grid; gap: 8px 30px; }
@media (min-width: 820px) { .row { grid-template-columns: 70px 300px 1fr; align-items: start; } }
.row .n { font-size: 15px; color: var(--muted); font-weight: 500; }
.row h3 { font-size: 1.3rem; }
.row p { color: var(--muted); font-size: 16px; margin: 0; }

/* ---------------------------------------------------------------- method */

.steps { display: grid; gap: 16px; margin-top: 46px; }
@media (min-width: 900px) { .steps { grid-template-columns: repeat(2, 1fr); } }
.step {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: clamp(22px, 3vw, 30px); display: flex; flex-direction: column; gap: 12px;
}
.step .when {
  align-self: flex-start; background: var(--accent-soft); color: var(--on-accent);
  border-radius: var(--r-pill); padding: 5px 12px; font-size: 12.5px; font-weight: 600;
}
.step p { color: var(--muted); font-size: 15.5px; margin: 0; }

.cadence {
  margin-top: 28px; background: var(--dark); color: var(--on-dark);
  border-radius: var(--r-lg); padding: clamp(26px, 4vw, 36px);
}
.cadence ul { list-style: none; margin: 18px 0; padding: 0; }
.cadence li { position: relative; padding-left: 26px; margin-bottom: 11px; color: var(--dark-muted); font-size: 16px; }
.cadence li::before { content: ""; position: absolute; left: 0; top: .55em; width: 13px; height: 2px; background: var(--accent); }
.cadence .closing { color: var(--accent); font-weight: 500; margin: 0; }

/* ---------------------------------------------------------------- pricing */

.tiers { display: grid; gap: 20px; margin-top: 48px; }
@media (min-width: 900px) { .tiers { grid-template-columns: repeat(3, 1fr); align-items: stretch; } }
.tier {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: clamp(24px, 3vw, 32px); display: flex; flex-direction: column; gap: 16px;
}
.tier.featured { background: var(--dark); color: var(--on-dark); border-color: var(--dark); }
.tier.featured .who { color: var(--dark-muted); border-color: var(--dark-line); }
.tier.featured li { color: var(--dark-muted); }
.tier .badge {
  align-self: flex-start; background: var(--accent); color: var(--on-accent);
  border-radius: var(--r-pill); padding: 5px 13px; font-size: 12px; font-weight: 600;
}
.tier .price {
  font-family: var(--display); font-weight: 500; letter-spacing: -0.04em;
  font-size: clamp(2rem, 4.4vw, 2.7rem); line-height: 1;
}
.tier .unit { font-size: 14px; color: var(--faint); display: block; margin-top: 8px; }
.tier .who { font-size: 15px; color: var(--muted); border-bottom: 1px solid var(--line); padding-bottom: 16px; margin: 0; }
.tier ul { list-style: none; margin: 0; padding: 0; flex: 1; }
.tier li { position: relative; padding-left: 28px; margin-bottom: 12px; font-size: 15.5px; color: var(--muted); }
.tier li::before {
  content: ""; position: absolute; left: 0; top: .2em; width: 18px; height: 18px;
  border-radius: 50%; background: var(--accent);
}
.tier li::after {
  content: ""; position: absolute; left: 6px; top: .44em; width: 5px; height: 9px;
  border-right: 2px solid var(--on-accent); border-bottom: 2px solid var(--on-accent);
  transform: rotate(42deg);
}
.tier .btn { width: 100%; }
.footnote { font-size: 14px; color: var(--faint); margin-top: 24px; text-align: center; }

/* ---------------------------------------------------------------- fit */

.fit { display: grid; gap: 20px; margin-top: 46px; }
@media (min-width: 860px) { .fit { grid-template-columns: 1fr 1fr; } }
.fit > div {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: clamp(24px, 3vw, 32px);
}
.fit h3 { margin-bottom: 18px; }
.fit ul { list-style: none; margin: 0; padding: 0; }
.fit li { position: relative; padding-left: 28px; margin-bottom: 13px; color: var(--muted); font-size: 16px; }
.fit li:last-child { margin-bottom: 0; }
.fit li::before {
  content: ""; position: absolute; left: 0; top: .22em; width: 18px; height: 18px; border-radius: 50%;
}
.fit .good li::before { background: var(--accent); }
.fit .good li::after {
  content: ""; position: absolute; left: 6px; top: .46em; width: 5px; height: 9px;
  border-right: 2px solid var(--on-accent); border-bottom: 2px solid var(--on-accent);
  transform: rotate(42deg);
}
.fit .bad li::before { background: var(--sunken); }
.fit .bad li::after {
  content: ""; position: absolute; left: 5px; top: .64em; width: 8px; height: 2px; background: var(--faint);
}

/* ---------------------------------------------------------------- who */

.who-block { display: grid; gap: 30px; margin-top: 44px; }
@media (min-width: 900px) { .who-block { grid-template-columns: 1fr 1.3fr; gap: 60px; align-items: start; } }
.who-body p { color: var(--muted); }
.who-credit {
  font-size: 14px; font-weight: 600; color: var(--ink);
  border-top: 1px solid var(--rule); padding-top: 16px; margin-top: 22px;
}

/* ---------------------------------------------------------------- faq */

.faq { max-width: 900px; margin: 46px auto 0; display: grid; gap: 12px; }
.faq details { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm); }
.faq summary {
  cursor: pointer; list-style: none; padding: 22px 60px 22px 24px; position: relative;
  font-size: 1.04rem; font-weight: 500; letter-spacing: -0.012em; line-height: 1.35;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::before,
.faq summary::after {
  content: ""; position: absolute; right: 24px; top: 50%; background: var(--ink);
  transition: opacity .18s ease, transform .18s ease;
}
.faq summary::before { width: 14px; height: 2px; margin-top: -1px; }
.faq summary::after  { width: 2px; height: 14px; margin: -7px 6px 0 0; }
.faq details[open] summary::after { opacity: 0; transform: rotate(90deg); }
.faq .answer { padding: 0 24px 24px; color: var(--muted); font-size: 16px; }

/* ---------------------------------------------------------------- final cta */

.cta-block { display: grid; gap: 34px; margin-top: 44px; }
@media (min-width: 940px) { .cta-block { grid-template-columns: 1fr 400px; gap: 60px; align-items: start; } }
.cta-block ul { list-style: none; margin: 28px 0 0; padding: 0; }
.cta-block li { position: relative; padding-left: 30px; margin-bottom: 14px; color: var(--muted); }
.cta-block li::before {
  content: ""; position: absolute; left: 0; top: .2em; width: 19px; height: 19px;
  border-radius: 50%; background: var(--accent);
}
.cta-block li::after {
  content: ""; position: absolute; left: 6.5px; top: .44em; width: 5px; height: 9px;
  border-right: 2px solid var(--on-accent); border-bottom: 2px solid var(--on-accent);
  transform: rotate(42deg);
}
.cta-card { background: var(--dark); color: var(--on-dark); border-radius: var(--r-lg); padding: clamp(26px, 3.6vw, 34px); }
.cta-card h3 { margin-bottom: 12px; }
.cta-card p { color: var(--dark-muted); font-size: 15.5px; }
.cta-card .btn { width: 100%; margin-top: 6px; }
.cta-card .fallback { font-size: 13.5px; color: var(--faint); margin: 16px 0 0; text-align: center; }

/* ---------------------------------------------------------------- legal pages */

.doc { padding-block: clamp(40px, 6vw, 72px); }
.doc h1 { font-size: clamp(2.2rem, 5vw, 3.2rem); margin-bottom: 12px; }
.doc .updated { font-size: 14px; color: var(--faint); margin-bottom: 32px; }
.doc h2 { font-size: 1.3rem; margin: 42px 0 12px; }
.doc p { color: var(--muted); max-width: var(--measure); }
.doc .intro { color: var(--ink); font-size: 1.06rem; }

/* ---------------------------------------------------------------- footer */

.sitefoot { background: var(--dark); color: var(--on-dark); padding-block: 56px 32px; }
.sitefoot .brand { color: var(--on-dark); }
.sitefoot .cols { display: grid; gap: 36px; }
@media (min-width: 860px) { .sitefoot .cols { grid-template-columns: 1.5fr 1fr 1fr; gap: 48px; } }
.sitefoot h2 { font-size: 13px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); margin: 0 0 16px; }
.sitefoot ul { list-style: none; margin: 0; padding: 0; }
.sitefoot li { margin-bottom: 10px; }
.sitefoot a { color: var(--dark-muted); text-decoration: none; font-size: 15.5px; }
.sitefoot a:hover { color: var(--accent); }
.sitefoot .blurb { color: var(--dark-muted); font-size: 15.5px; max-width: 38ch; margin: 16px 0 0; }
.sitefoot .base {
  margin-top: 42px; padding-top: 22px; border-top: 1px solid var(--dark-line);
  display: flex; flex-wrap: wrap; gap: 10px 24px; font-size: 13.5px; color: var(--faint);
}

.newsletter { margin-top: 22px; }
.newsletter label { display: block; font-size: 13px; color: var(--faint); margin-bottom: 9px; }
.newsletter .field { display: flex; gap: 8px; flex-wrap: wrap; }
.newsletter input {
  flex: 1 1 190px; background: var(--dark-field); border: 1px solid var(--dark-line);
  color: var(--on-dark); border-radius: var(--r-pill); padding: 13px 18px;
  font-family: var(--body); font-size: 15px;
}
.newsletter input::placeholder { color: var(--faint); }

/* ---------------------------------------------------------------- utility */

.skip {
  position: absolute; left: -9999px; top: 0; background: var(--accent); color: var(--on-accent);
  padding: 12px 18px; z-index: 100; font-weight: 600;
}
.skip:focus { left: 0; }

.todo {
  background: var(--todo-bg); color: var(--todo-fg); padding: 0 5px; border-radius: 3px;
  border: 1px dashed var(--todo-line); font-size: .92em; font-weight: 500;
}

/* ---------------------------------------------------------------- categories */

.cats { display: grid; gap: 16px; margin-top: 48px; grid-template-columns: repeat(2, 1fr); }
@media (min-width: 720px)  { .cats { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1060px) { .cats { grid-template-columns: repeat(6, 1fr); } }
.cat { margin: 0; }
.cat img {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: var(--r-sm); background: var(--sunken);
}
.cat figcaption { margin-top: 12px; display: flex; flex-direction: column; gap: 3px; }
.cat strong { font-size: 15px; font-weight: 600; letter-spacing: -0.012em; }
.cat span { font-size: 13px; color: var(--faint); line-height: 1.4; }

/* ---------------------------------------------------------------- concept gallery */

.gallery { display: grid; gap: 22px; margin-top: 48px; grid-template-columns: 1fr; }
@media (min-width: 660px)  { .gallery { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1020px) { .gallery { grid-template-columns: repeat(3, 1fr); } }
.shot { margin: 0; }
.shot img {
  width: 100%; aspect-ratio: 2 / 3; object-fit: cover; object-position: top;
  border-radius: var(--r-lg); border: 1px solid var(--line); background: var(--surface);
}
.shot figcaption { margin-top: 14px; display: flex; flex-direction: column; gap: 4px; }
.shot strong {
  align-self: flex-start; background: var(--accent); color: var(--on-accent);
  border-radius: var(--r-pill); padding: 4px 11px; font-size: 12px; font-weight: 600;
}
.shot span { font-size: 14.5px; color: var(--muted); line-height: 1.45; }

/* photo behind the big-number card tops */
.card-top { position: relative; isolation: isolate; }
.card-top .card-bg {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  z-index: -1; opacity: .38; filter: grayscale(1) contrast(1.05);
}
.card-top::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(0,0,0,.30) 0%, rgba(0,0,0,.90) 78%);
}

/* ============================================================================
   MailMorph Media — hero
   ----------------------------------------------------------------------------
   Concatenated between mailmorph.css and motion.css by the build.

   Composition follows the reference site's hero: a ghosted wordmark field with a
   soft accent wash behind it, an outlined stat pill, an oversized headline, and
   overlapping tilted phone frames on the right.

   Two substitutions, deliberate:
     - the ghost field spells OUR FLOW NAMES, not a competitor's client list
     - the phones show OUR OWN concept email renders, not anyone's client work
   ========================================================================= */

.hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(34px, 5vw, 64px) clamp(56px, 8vw, 100px);
}

/* ---------------------------------------------------------------- backdrop */

.hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

/* accent wash bleeding in from the upper right, exactly as the reference does */
.hero-bg .wash {
  position: absolute;
  top: -28%;
  right: -14%;
  width: 78%;
  height: 132%;
  background:
    radial-gradient(44% 40% at 78% 16%, color-mix(in srgb, var(--accent) 34%, transparent) 0%, transparent 70%),
    radial-gradient(34% 34% at 97% 2%, color-mix(in srgb, var(--accent) 26%, transparent) 0%, transparent 74%);
  filter: blur(8px);
}
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .hero-bg .wash {
    background:
      radial-gradient(44% 40% at 78% 16%, rgba(59,239,59,.28) 0%, transparent 70%),
      radial-gradient(34% 34% at 97% 2%, rgba(59,239,59,.20) 0%, transparent 74%);
  }
}

/* the ghosted wordmark field — a tilted lattice of the flows we build */
.ghosts {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 158%;
  transform: translate(-50%, -50%) rotate(-7deg);
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2.6vw, 34px);
  /* Fade the lattice out across the text column so it never competes with the
     headline — it is texture behind the phones, not a layer over the copy. */
  -webkit-mask-image: linear-gradient(96deg, transparent 6%, rgba(0,0,0,.35) 30%, #000 58%);
          mask-image: linear-gradient(96deg, transparent 6%, rgba(0,0,0,.35) 30%, #000 58%);
}
.ghosts .line {
  display: flex;
  gap: clamp(30px, 4.2vw, 62px);
  justify-content: center;
  white-space: nowrap;
}
.ghosts span {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(22px, 3.6vw, 48px);
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--ink);
  opacity: .05;
  user-select: none;
}
.ghosts .line:nth-child(even) { transform: translateX(-7%); }
.ghosts .line:nth-child(3n) span { opacity: .034; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ghosts span { opacity: .1; }
  :root:not([data-theme="light"]) .hero-bg .wash { opacity: .5; }
}
:root[data-theme="dark"] .ghosts span { opacity: .1; }
:root[data-theme="dark"] .hero-bg .wash { opacity: .5; }

/* ---------------------------------------------------------------- foreground */

.hero .shell { position: relative; z-index: 1; }
.hero-grid { display: grid; gap: 44px; align-items: center; }
@media (min-width: 1000px) { .hero-grid { grid-template-columns: 1fr 1.04fr; gap: 40px; } }

/* 11ch keeps the headline clear of the phone group. At 13ch it ran the full
   width of its grid column and the first phone — which bleeds left because
   rotation widens its bounding box — sat on top of the last two lines. */
.hero h1 { max-width: 11ch; }
.hero .lede { margin-top: 22px; max-width: 44ch; font-size: clamp(1.05rem, 2.1vw, 1.22rem); }
.hero .lede em { font-style: italic; }

.badge-pill {
  display: inline-flex; align-items: center; gap: 10px;
  border: 1.5px solid var(--rule); border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--surface) 72%, transparent);
  padding: 10px 20px; font-size: 15px; font-weight: 500; margin-bottom: 26px;
}
.badge-pill svg { width: 17px; height: 17px; }

/* CTA row: primary button, then a flag badge and a one-line trust statement */
.hero-actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 16px 22px; margin-top: 34px;
}

.flagmark {
  display: inline-flex; align-items: center; gap: 10px;
}
.flagmark .flag {
  position: relative;
  background: var(--ink); color: var(--paper);
  padding: 9px 22px 9px 14px;
  font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  line-height: 1.15; text-align: left;
  clip-path: polygon(0 0, 100% 0, calc(100% - 11px) 50%, 100% 100%, 0 100%);
}
.flagmark .flag b { display: block; font-weight: 700; }
.flagmark .flag i {
  display: block; font-style: normal; font-weight: 500;
  font-size: 9.5px; letter-spacing: .14em; opacity: .72;
}
.flagmark .flag::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--accent);
}
.flagmark .note { font-size: 15px; font-weight: 500; color: var(--muted); max-width: 22ch; }

.hero-note { font-size: 14.5px; color: var(--faint); margin-top: 20px; }
/* keep the label and its arrow together — the arrow was orphaning onto its own line */
.hero-note a { white-space: nowrap; display: inline-flex; align-items: center; gap: 6px; }
.hero-note a svg { flex: none; }

/* ---------------------------------------------------------------- phones */

/* Large and tightly overlapping, so the email creative inside is actually
   legible — small separated phones read as thumbnails, not as the work. */
/* Rotation widens each phone's bounding box by roughly 26px per side, so the
   group's VISUAL width exceeds its layout width. Sizing to ~86% of the column
   and nudging the whole group right keeps that bleed off the headline. */
/* The group is anchored flex-end, so making the phones WIDER grows it leftward
   into the headline — the nudge right has to grow with it, not stay put. The
   right-hand gap is what pays for both, and that gap is much smaller at 1280
   than at 1440, so the nudge steps up with the viewport rather than being one
   percentage that is either too timid wide or overflowing narrow. */
.phones {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  max-width: 100%;
  /* NOT `transform` — the entrance animation is `both`-filled and its end state
     would outrank it. motion.css reads this property inside the keyframe so the
     phones come to rest here instead of at centre. */
  --mm-rest: translateX(6%);
}
.phone {
  flex: 0 0 auto;
  width: 33%;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 30px;
  padding: 8px;
  box-shadow: 0 26px 60px rgba(0,0,0,.16), 0 3px 10px rgba(0,0,0,.06);
}
/* A phone shows an email at FULL WIDTH with the bottom running off the screen —
   never side-cropped. The previous rule forced the 4:5 render into a 9:18 box
   with object-fit: cover, which sliced the left and right edges off every design
   ("SERUM CO." became "UM CO."). The screen clips; the image is never cropped. */
.phone .screen {
  display: block;
  aspect-ratio: 9 / 15;
  overflow: hidden;
  border-radius: 23px;
  background: var(--sunken);
}
.phone .screen img {
  width: 100%; height: auto; display: block; border-radius: 0;
}
/* outer two sit lower, tilt away and tuck behind; the middle one leads */
.phone:nth-child(1) { transform: translateY(34px) rotate(-3.5deg); z-index: 1; margin-right: -6%; }
.phone:nth-child(2) { transform: translateY(-10px); z-index: 3; width: 35%; }
.phone:nth-child(3) { transform: translateY(34px) rotate(3.5deg); z-index: 2; margin-left: -6%; }

/* Below ~1360 the group already fills its column, so there is nothing to spend:
   growing or nudging it there only pushes it against the viewport edge. The
   larger, further-right treatment starts where the room actually exists. */
@media (min-width: 1360px) {
  .phones { --mm-rest: translateX(17%); }
  .phone { width: 36%; }
  .phone:nth-child(2) { width: 38%; }
}
@media (min-width: 1560px) { .phones { --mm-rest: translateX(20%); } }

@media (max-width: 999px) {
  /* The group is centred here, so the desktop nudge must be cancelled — before
     the keyframe fix it was inert everywhere and this was not needed. */
  .phones { max-width: 560px; margin-inline: auto; justify-content: center; --mm-rest: translateX(0); }
  .phone { border-radius: 24px; padding: 6px; }
  .phone .screen { border-radius: 18px; }
}
@media (max-width: 520px) {
  .phone { border-radius: 18px; padding: 5px; }
  .phone .screen { border-radius: 13px; }
  .phone:nth-child(1) { transform: translateY(22px) rotate(-3.5deg); }
  .phone:nth-child(3) { transform: translateY(22px) rotate(3.5deg); }
}

/* ============================================================================
   MailMorph Media — counter-scrolling marquee
   ----------------------------------------------------------------------------
   Two rows travelling in opposite directions, directly under the hero.

   The track is rendered TWICE in the markup and animated to -50%, which is what
   makes the loop seamless — at -50% the second copy sits exactly where the first
   started, so the reset is invisible. The duplicate is aria-hidden so screen
   readers hear each item once.

   Under prefers-reduced-motion the whole thing stops being a marquee: the track
   wraps into a centred static grid and the duplicate is removed from flow.
   ========================================================================= */

/* No section heading: this reads as a strip under the hero, not a section of its
   own, so the top padding is tighter than a standard section. */
.marquee-section { padding-block: clamp(10px, 2vw, 24px) clamp(40px, 6vw, 72px); overflow: hidden; }

.mq-row { margin-bottom: 26px; }
.mq-row:last-of-type { margin-bottom: 0; }

.mq-label {
  font-size: 12.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 14px; padding-inline: var(--pad);
}

.marquee {
  position: relative;
  overflow: hidden;
  /* soften both ends so tiles enter and leave rather than being chopped */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 5%, #000 95%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 5%, #000 95%, transparent 100%);
}

.mq-track {
  display: flex;
  width: max-content;
  gap: 14px;
  will-change: transform;
}
.mq-track.rtl { animation: mq-rtl 44s linear infinite; }
.mq-track.ltr { animation: mq-ltr 50s linear infinite; }

@keyframes mq-rtl { from { transform: translate3d(0, 0, 0); }      to { transform: translate3d(-50%, 0, 0); } }
@keyframes mq-ltr { from { transform: translate3d(-50%, 0, 0); }   to { transform: translate3d(0, 0, 0); } }

/* let people read a tile they are pointing at */
.marquee:hover .mq-track,
.marquee:focus-within .mq-track { animation-play-state: paused; }

.mq-tile {
  flex: 0 0 auto;
  width: clamp(150px, 15vw, 196px);
  height: clamp(84px, 8vw, 108px);
  border-radius: 14px;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 10px 14px;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(14px, 1.35vw, 17px);
  letter-spacing: -0.018em;
  line-height: 1.2;
  border: 1px solid transparent;
  transition: transform .25s cubic-bezier(.22,.61,.36,1), box-shadow .25s ease;
}
.mq-tile:hover { transform: translateY(-3px); box-shadow: 0 12px 26px rgba(0,0,0,.12); }

/* A restrained rotation drawn from the site's own three colours, rather than a
   rainbow of other companies' brand palettes. */
.mq-tile.t-1 { background: var(--ink);     color: var(--paper); }
.mq-tile.t-2 { background: var(--accent);  color: var(--on-accent); }
.mq-tile.t-3 { background: var(--surface); color: var(--ink); border-color: var(--line); }
.mq-tile.t-4 { background: var(--sunken);  color: var(--ink); }
.mq-tile.t-5 { background: var(--accent-soft); color: var(--on-accent); }

.mq-note {
  font-size: 13px; color: var(--faint); max-width: 68ch;
  margin: 30px auto 0; text-align: center; padding-inline: var(--pad);
}

@media (prefers-reduced-motion: reduce) {
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .mq-track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
    padding-inline: var(--pad);
  }
  /* the duplicate exists only to make the loop seamless; with no loop it is noise */
  .mq-track [aria-hidden="true"] { display: none; }
}

/* ============================================================================
   MailMorph Media — email creative wall
   ----------------------------------------------------------------------------
   A staggered, captionless grid of email designs, tightly packed.

   CSS multi-column rather than grid: columns naturally interlock items of
   differing heights, which is what produces the offset look. Grid would align
   every row and lose it. `break-inside: avoid` keeps each design whole.

   Source renders are all 2:3 portrait, so the varied heights come from per-tile
   aspect ratios with `object-position: top` — the crop takes from the bottom and
   keeps the masthead, hero image and headline, which is the recognisable part.
   ========================================================================= */

.wall-section { padding-block: clamp(48px, 7vw, 90px); }

.wall {
  columns: 2;
  column-gap: 14px;
  margin-top: 40px;
}
@media (min-width: 900px) { .wall { columns: 3; } }

.wall figure {
  margin: 0 0 14px;
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
}
/* Natural height, no crop. Each design is now authored at its own height
   (660–940px at 560 wide), so the columns interlock on their own. The previous
   version forced six different aspect ratios onto identically-sized renders,
   which is what was slicing the CTAs in half. */
.wall img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--sunken);
  transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease;
}
.wall figure:hover img {
  transform: translateY(-4px);
  box-shadow: 0 16px 36px rgba(0,0,0,.16);
}

.wall-note {
  font-size: 13.5px; color: var(--faint); text-align: center;
  max-width: 62ch; margin: 26px auto 0;
}
.wall-more { text-align: center; margin-top: 28px; }

/* The captioned gallery on /work shares these renders. mailmorph.css forces
   .shot img to aspect-ratio 2/3 with object-fit: cover, which was cropping the
   SIDES off the 4:5 and 3:4 designs — that is what cut the D off DAILY DOSE.
   Each design now has its own authored height, so show it whole. */
.gallery .shot img {
  aspect-ratio: auto;
  height: auto;
  object-fit: fill;
}

/* ============================================================================
   MailMorph Media — scheduling panel
   ----------------------------------------------------------------------------
   Two-column: argument and agenda on the left, the booking card on the right.

   The card has two modes (see the `book` block in site.js). When a real booking
   URL exists it holds an iframe of the live scheduler. Until then it holds a
   two-step request form that composes a mailto. There is no decorative calendar
   grid in either mode.

   The steps are progressive enhancement: with JS off both panels are visible and
   the form still submits, so nobody is trapped on step one.
   ========================================================================= */

.bk-section { padding-block: clamp(56px, 8vw, 100px); }

.bk-grid { display: grid; gap: 40px; }
@media (min-width: 1000px) {
  .bk-grid { grid-template-columns: 1fr 440px; gap: 64px; align-items: start; }
}

/* ---------------------------------------------------------------- left column */

.bk-points { list-style: none; margin: 28px 0 0; padding: 0; }
.bk-points li { position: relative; padding-left: 30px; margin-bottom: 14px; color: var(--muted); }
.bk-points li::before {
  content: ""; position: absolute; left: 0; top: .2em; width: 19px; height: 19px;
  border-radius: 50%; background: var(--accent);
}
.bk-points li::after {
  content: ""; position: absolute; left: 6.5px; top: .44em; width: 5px; height: 9px;
  border-right: 2px solid var(--on-accent); border-bottom: 2px solid var(--on-accent);
  transform: rotate(42deg);
}

.bk-qualifier {
  margin-top: 30px; padding: 20px 22px;
  border-left: 3px solid var(--accent); background: var(--surface);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.bk-qualifier h3 { font-size: 1rem; margin-bottom: 8px; }
.bk-qualifier p { font-size: 15px; color: var(--muted); margin: 0; }

.bk-agenda { margin-top: 32px; }
.bk-agenda h3 { font-size: 1.05rem; margin-bottom: 18px; }
.bk-agenda ol { list-style: none; margin: 0; padding: 0; }
.bk-agenda li {
  display: grid; grid-template-columns: 34px 1fr; gap: 4px 14px;
  padding: 14px 0; border-top: 1px solid var(--line);
}
.bk-agenda li:last-child { border-bottom: 1px solid var(--line); }
.bk-agenda .n { grid-row: span 2; font-size: 13px; font-weight: 600; color: var(--accent-ink); padding-top: 2px; }
.bk-agenda .t { font-weight: 600; font-size: 15.5px; }
.bk-agenda .d { font-size: 14.5px; color: var(--muted); }

/* ---------------------------------------------------------------- the card */

.bk-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 18px 44px rgba(0,0,0,.08);
}

.bk-head { padding: 22px 24px 20px; border-bottom: 1px solid var(--line); }
.bk-brand {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--display); font-weight: 600; font-size: 1.05rem;
  letter-spacing: -0.03em; color: var(--ink); margin-bottom: 12px;
}
.bk-brand svg { width: 20px; height: 20px; flex: none; }
.bk-head strong {
  display: block; font-family: var(--display); font-weight: 500;
  font-size: 1.32rem; letter-spacing: -0.028em; line-height: 1.1;
}
.bk-meta { display: block; font-size: 13.5px; color: var(--faint); margin-top: 7px; }

/* live scheduler */
.bk-embed { min-height: 620px; }
.bk-embed iframe { width: 100%; height: 620px; border: 0; display: block; }

/* ---------------------------------------------------------------- request form */

.bk-form { padding: 22px 24px 26px; }

.bk-steps { display: flex; gap: 6px; margin-bottom: 22px; }
.bk-step {
  flex: 1; font-family: var(--body); font-size: 13.5px; font-weight: 600;
  padding: 10px 12px; border-radius: var(--r-pill); cursor: pointer;
  background: var(--sunken); color: var(--muted); border: 1.5px solid transparent;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.bk-step[aria-selected="true"] { background: var(--accent); color: var(--on-accent); }
.bk-step:hover { border-color: var(--rule); }
/* With JS off there are no steps to switch between, so hide the control and
   show both panels — see .no-js rules below. */
.no-js .bk-steps { display: none; }

.bk-field { margin-bottom: 16px; }
.bk-field label, .bk-legend {
  display: block; font-size: 13px; font-weight: 600; margin-bottom: 7px; color: var(--ink);
}
.bk-field input[type="text"],
.bk-field input[type="email"],
.bk-field input[type="url"],
.bk-field input[type="date"] {
  width: 100%; font-family: var(--body); font-size: 15.5px; color: var(--ink);
  background: var(--paper); border: 1.5px solid var(--line); border-radius: var(--r-sm);
  padding: 12px 14px; transition: border-color .18s ease, box-shadow .18s ease;
}
.bk-field input:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}

.bk-windows { display: grid; gap: 8px; }
.bk-chip { position: relative; display: block; cursor: pointer; }
.bk-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.bk-chip span {
  display: block; padding: 11px 14px; font-size: 14.5px;
  border: 1.5px solid var(--line); border-radius: var(--r-sm);
  background: var(--paper); transition: border-color .18s ease, background-color .18s ease;
}
.bk-chip input:checked + span {
  border-color: var(--accent); background: var(--accent-soft); font-weight: 600;
}
.bk-chip input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 2px; }

.bk-submit { width: 100%; margin-top: 6px; }
.bk-note { font-size: 13px; color: var(--faint); text-align: center; margin: 14px 0 0; }
.bk-fallback {
  font-size: 12.5px; margin: 14px 0 0; padding: 10px 12px; border-radius: var(--r-sm);
  background: var(--todo-bg); color: var(--todo-fg); border: 1px dashed var(--todo-line);
}

/* JS turns the two panels into steps; without it, both stay open. */
.bk-panel[hidden] { display: none; }

/* ============================================================================
   MailMorph Media — split FAQ
   ----------------------------------------------------------------------------
   Heading and contact line on the left, accordion column on the right.

   The accordions are <details>, so every answer sits in the served HTML whether
   or not it is open. That is deliberate and load-bearing: the reference site we
   audited shipped its questions without its answers, because its accordion only
   rendered the body once opened. Closing these by default is purely visual —
   the text is still there for a crawler and for anyone with JS disabled.
   ========================================================================= */

.faq-section { padding-block: clamp(56px, 8vw, 100px); }

.faq-split { display: grid; gap: 34px; align-items: start; }
@media (min-width: 1000px) {
  .faq-split { grid-template-columns: 1fr 1.25fr; gap: 64px; }
  .faq-split > .faq-intro { position: sticky; top: 108px; }
}

.faq-intro h2 { margin-bottom: 20px; }
.faq-intro .lede { max-width: 34ch; }
.faq-intro .more { margin-top: 26px; }

/* the accordion column — overrides the centred default in mailmorph.css */
.faq-split .faq { max-width: none; margin: 0; display: grid; gap: 12px; }

/* When the split layout IS the page header, it needs the pagehead's top spacing
   and a slightly tighter gap between the two ledes. */
.faq-section.is-page { padding-block: clamp(44px, 6vw, 76px) clamp(56px, 8vw, 100px); }
.faq-section.is-page .faq-intro h1 { max-width: 15ch; margin-bottom: 20px; }
.faq-section.is-page .faq-intro .contactline { margin-top: 14px; font-size: 15.5px; }

/* ============================================================================
   MailMorph Media — motion, mobile nav, contact + teaser components
   ----------------------------------------------------------------------------
   Concatenated after mailmorph.css by the build. Kept separate because it is the
   one layer that must degrade cleanly: with JS off, `.no-js` reveals everything;
   with prefers-reduced-motion, every transition collapses to nothing.
   ========================================================================= */

/* ---------------------------------------------------------------- scroll reveal */

[data-anim] {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition: opacity .62s cubic-bezier(.22,.61,.36,1), transform .62s cubic-bezier(.22,.61,.36,1);
}
[data-anim="fade"]  { transform: none; }
[data-anim="left"]  { transform: translate3d(-26px, 0, 0); }
[data-anim="right"] { transform: translate3d(26px, 0, 0); }
[data-anim="scale"] { transform: scale(.965); }
[data-anim].in { opacity: 1; transform: none; }

/* If JS never runs, nothing may stay invisible. */
.no-js [data-anim] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-anim] { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ---------------------------------------------------------------- page entry */

@keyframes mm-rise {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}
.mm-enter   { animation: mm-rise .7s cubic-bezier(.22,.61,.36,1) both; }

/* An element that RESTS off-centre cannot use mm-rise. That keyframe ends at
   `transform: none`, and because the animation is `both`-filled its end state
   persists and outranks any normal `transform` declaration — which is why
   `.phones { transform: translateX(...) }` in hero.css silently did nothing for
   as long as both rules existed. The nudge only looked absent; it was cancelled.

   This variant ends at the element's resting transform instead, read from a
   custom property so hero.css still owns the actual number. Elements that don't
   set --mm-rest are unaffected and keep using mm-rise. */
@keyframes mm-rise-nudged {
  from { opacity: 0; transform: var(--mm-rest, translateX(0)) translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: var(--mm-rest, translateX(0)); }
}
.phones.mm-enter { animation-name: mm-rise-nudged; }
.mm-enter-1 { animation-delay: .05s; }
.mm-enter-2 { animation-delay: .13s; }
.mm-enter-3 { animation-delay: .21s; }
.mm-enter-4 { animation-delay: .29s; }
@media (prefers-reduced-motion: reduce) {
  .mm-enter { animation: none; }
  /* With the animation gone there is no fill state to carry the resting nudge,
     so it has to be declared outright or the phones jump back to centre. */
  .phones { transform: var(--mm-rest, none); }
}

/* ---------------------------------------------------------------- masthead */

.masthead { transition: box-shadow .25s ease; }
.masthead .shell { transition: height .25s ease; }
.masthead.scrolled { box-shadow: 0 1px 0 var(--line), 0 8px 28px rgba(0,0,0,.05); }
.masthead.scrolled .shell { height: 62px; }

/* the morph mark reacts on hover: two squares tilt, the circle picks up the accent */
.brand svg rect, .brand svg circle {
  transition: stroke .3s ease, transform .45s cubic-bezier(.22,.61,.36,1);
  transform-origin: center;
}
.brand:hover svg rect:nth-of-type(1) { transform: rotate(-8deg); }
.brand:hover svg rect:nth-of-type(2) { transform: rotate(8deg); }
.brand:hover svg circle { stroke: var(--accent); }

.masthead nav a { position: relative; padding-block: 5px; }
.masthead nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform .24s cubic-bezier(.22,.61,.36,1);
}
.masthead nav a:hover::after,
.masthead nav a[aria-current="page"]::after { transform: scaleX(1); }
.masthead nav a[aria-current="page"] { font-weight: 600; }

/* ---------------------------------------------------------------- hover states */

.btn { transition: background-color .16s ease, border-color .16s ease, color .16s ease, transform .16s ease; }
.btn:hover  { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.card, .tier, .step, .fit > div, .cat img, .shot img {
  transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease, border-color .3s ease;
}
.card:hover, .tier:hover, .step:hover, .fit > div:hover {
  transform: translateY(-4px); box-shadow: 0 14px 34px rgba(0,0,0,.07);
}
.cat:hover img, .shot:hover img {
  transform: translateY(-5px) scale(1.014); box-shadow: 0 16px 36px rgba(0,0,0,.12);
}

/* counted figures need tabular digits or the odometer jitters mid-count */
.stat { font-variant-numeric: tabular-nums; }

.row { transition: background-color .25s ease, padding-left .25s ease; }
.row:hover { background: var(--accent-soft); padding-left: 12px; }

.faq details { transition: border-color .2s ease, box-shadow .2s ease; }
.faq details[open] { border-color: var(--rule); box-shadow: 0 8px 26px rgba(0,0,0,.05); }
.faq .answer { animation: mm-rise .34s cubic-bezier(.22,.61,.36,1) both; }
@media (prefers-reduced-motion: reduce) { .faq .answer { animation: none; } }

/* ---------------------------------------------------------------- mobile nav */

.navtoggle {
  margin-left: auto; display: inline-flex; flex-direction: column; justify-content: center;
  gap: 5px; width: 46px; height: 44px; padding: 0 11px; background: none;
  border: 1.5px solid var(--rule); border-radius: var(--r-pill); cursor: pointer;
}
@media (min-width: 1000px) { .navtoggle { display: none; } }
.navtoggle i { display: block; height: 2px; background: var(--ink); transition: transform .26s ease, opacity .2s ease; }
.navtoggle[aria-expanded="true"] i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.navtoggle[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
.navtoggle[aria-expanded="true"] i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.drawer {
  position: fixed; inset: 0; z-index: 55; background: var(--paper);
  padding: 100px var(--pad) 40px; display: flex; flex-direction: column; gap: 2px;
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity .26s ease, transform .26s ease, visibility .26s;
  overflow-y: auto;
}
.drawer.open { opacity: 1; visibility: visible; transform: none; }
@media (min-width: 1000px) { .drawer { display: none; } }
.drawer a {
  font-family: var(--display); font-size: clamp(1.5rem, 7vw, 2rem); font-weight: 500;
  letter-spacing: -0.035em; text-decoration: none; color: var(--ink);
  padding: 13px 0; border-bottom: 1px solid var(--line);
}
.drawer a[aria-current="page"] { color: var(--accent-ink); }
.drawer .btn { margin-top: 26px; align-self: flex-start; font-size: 17px; border-bottom: 0; }
body.nav-open { overflow: hidden; }

/* ---------------------------------------------------------------- contact page */

.contact-grid { display: grid; gap: 40px; margin-top: 44px; }
@media (min-width: 940px) { .contact-grid { grid-template-columns: 1fr 1.1fr; gap: 64px; align-items: start; } }
.contact-grid ul { list-style: none; margin: 26px 0 0; padding: 0; }
.contact-grid li { position: relative; padding-left: 30px; margin-bottom: 14px; color: var(--muted); }
.contact-grid li::before {
  content: ""; position: absolute; left: 0; top: .2em; width: 19px; height: 19px;
  border-radius: 50%; background: var(--accent);
}
.contact-grid li::after {
  content: ""; position: absolute; left: 6.5px; top: .44em; width: 5px; height: 9px;
  border-right: 2px solid var(--on-accent); border-bottom: 2px solid var(--on-accent);
  transform: rotate(42deg);
}

.formcard {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--r-lg); padding: clamp(24px, 3.6vw, 36px);
}
.formcard h2 { font-size: 1.5rem; margin-bottom: 8px; }
.formcard .note { font-size: 14.5px; color: var(--faint); margin-bottom: 24px; }
.field-row { display: grid; gap: 16px; margin-bottom: 16px; }
@media (min-width: 560px) { .field-row.two { grid-template-columns: 1fr 1fr; } }
.formcard label { display: block; font-size: 13.5px; font-weight: 600; margin-bottom: 7px; }
.formcard input, .formcard textarea {
  width: 100%; font-family: var(--body); font-size: 15.5px; color: var(--ink);
  background: var(--paper); border: 1.5px solid var(--line); border-radius: var(--r-sm);
  padding: 13px 15px; transition: border-color .18s ease, box-shadow .18s ease;
}
.formcard textarea { min-height: 118px; resize: vertical; }
.formcard input:focus, .formcard textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.formcard .btn { width: 100%; margin-top: 6px; }

.direct {
  margin-top: 26px; border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 24px; background: var(--surface);
}
.direct h2 { font-size: 1.1rem; margin-bottom: 8px; }
.direct p { color: var(--muted); font-size: 15.5px; }
.direct a { font-weight: 600; color: var(--ink); }

/* ---------------------------------------------------------------- page head + teasers */

.pagehead { padding-block: clamp(44px, 6vw, 76px) clamp(8px, 2vw, 20px); }
.pagehead .crumbs { font-size: 13.5px; color: var(--faint); margin-bottom: 20px; }
.pagehead .crumbs a { color: var(--muted); text-decoration: none; }
.pagehead .crumbs a:hover { color: var(--accent-ink); }
.pagehead h1 { max-width: 18ch; }
.pagehead .lede { margin-top: 22px; max-width: 56ch; }

.teaser { display: grid; gap: 18px; margin-top: 44px; }
@media (min-width: 860px) { .teaser { grid-template-columns: repeat(2, 1fr); } }
.teaser a {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: clamp(24px, 3.2vw, 32px); text-decoration: none; color: var(--ink);
  display: flex; flex-direction: column; gap: 10px;
  transition: transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s ease, border-color .3s ease;
}
.teaser a:hover { transform: translateY(-4px); box-shadow: 0 14px 34px rgba(0,0,0,.07); border-color: var(--accent); }
.teaser .k { font-size: 12.5px; font-weight: 600; color: var(--accent-ink); }
.teaser h3 { font-size: 1.35rem; }
.teaser p { color: var(--muted); font-size: 15.5px; margin: 0; }
.teaser .go {
  margin-top: auto; font-weight: 600; font-size: 15px;
  display: inline-flex; gap: 8px; align-items: center; transition: gap .2s ease;
}
.teaser a:hover .go { gap: 14px; }

/* ============================================================================
   MailMorph Media — category strip  (restyle)
   ----------------------------------------------------------------------------
   Loaded after mailmorph.css and motion.css, and deliberately overrides the
   first-pass rules there.

   What was wrong with the first pass:
     - six unrelated stock photographs, each with its own background colour, read
       as a stock grid rather than a designed set
     - captions sat under the image and wrapped to one, two or three lines, so
       the bottom edge of the row was ragged
     - the section heading ran at hero scale for what is supporting content

   The fixes:
     - a shared treatment (desaturated at rest, full colour on hover) is what
       turns six unrelated photographs into one system
     - the label is overlaid on a scrim inside a fixed-ratio card, so wrapping
       can never disturb the row
     - the heading is left-aligned and capped well below hero scale
   ========================================================================= */

.cats-section { padding-block: clamp(48px, 7vw, 88px); }

.cats-head { max-width: 52ch; margin-bottom: 36px; }
.cats-head h2 {
  font-size: clamp(1.7rem, 3.4vw, 2.35rem);   /* well under the hero scale */
  max-width: 20ch;
}
.cats-head .lede { margin-top: 16px; max-width: 54ch; }

.cats {
  display: grid;
  gap: 12px;
  margin-top: 0;
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 640px)  { .cats { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1060px) { .cats { grid-template-columns: repeat(6, 1fr); } }

.cat {
  position: relative;
  margin: 0;
  border-radius: var(--r-sm);
  overflow: hidden;
  isolation: isolate;
  background: var(--sunken);
}

.cat img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: 0;
  display: block;
  /* the unifier — six different photographs, one treatment */
  filter: grayscale(.7) contrast(1.04) brightness(1.02);
  transition: filter .4s ease, transform .5s cubic-bezier(.22,.61,.36,1);
}

/* scrim, so the overlaid label stays legible over any photograph */
.cat::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0) 38%, rgba(0,0,0,.52) 72%, rgba(0,0,0,.82) 100%);
  transition: opacity .4s ease;
}

.cat figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 1;
  margin: 0;
  padding: 14px 14px 15px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.cat strong {
  font-family: var(--display);
  font-size: 15px; font-weight: 600; letter-spacing: -0.018em; line-height: 1.2;
  color: #fff;
}
/* Reserve two lines whatever the note says. Anchoring the caption to the bottom
   and letting it grow upward put the NAMES at two different heights across the
   row — the same ragged edge as before, just moved. A fixed note height puts
   every name on one baseline. */
.cat span {
  font-size: 12.5px; line-height: 1.35;
  color: rgba(255,255,255,.78);
  min-height: 2.7em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* hover restores the photograph's own colour — the card comes alive one at a time */
.cat:hover img {
  filter: grayscale(0) contrast(1) brightness(1);
  transform: scale(1.05);
  box-shadow: none;
}
.cat:hover::after { opacity: .88; }

/* a hairline accent that draws in on hover, tying the row to the brand */
.cat::before {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  background: var(--accent);
  z-index: 2;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .34s cubic-bezier(.22,.61,.36,1);
}
.cat:hover::before { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .cat img, .cat::after, .cat::before { transition: none; }
  .cat:hover img { transform: none; }
}

/* ============================================================================
   MailMorph Media — the four-number cards  (restyle)
   ----------------------------------------------------------------------------
   Loaded after mailmorph.css and motion.css, and deliberately overrides them.

   What was wrong with the first pass: the photograph WAS there, but sat at 38%
   opacity, fully desaturated, beneath a scrim running to 90% black — and both it
   and the scrim used z-index: -1 inside an isolated stacking context, so the
   image was effectively invisible. All four cards read as flat black panels.

   Now: the photograph carries the panel, a top-light gradient keeps the figure
   and its label legible where they actually sit, and a slow drift plus a hover
   reveal give the row some life.
   ========================================================================= */

.cards { display: grid; gap: 22px; margin-top: 48px; }
@media (min-width: 860px) { .cards { grid-template-columns: 1fr 1fr; } }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* ---------------------------------------------------------------- the panel */

.card-top {
  position: relative;
  isolation: isolate;
  min-height: 264px;
  padding: 32px 28px 26px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  background: var(--dark);
  overflow: hidden;
}

.card-top .card-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;                      /* was -1, which buried it */
  opacity: .68;
  filter: grayscale(.4) contrast(1.08) brightness(.86);
  transform: scale(1.06);
  transform-origin: center;
  animation: card-drift 26s ease-in-out infinite alternate;
  transition: transform .7s cubic-bezier(.22,.61,.36,1),
              opacity .45s ease, filter .45s ease;
}

/* Light at the top, dark only where the figure and its label actually sit —
   so the photograph stays visible instead of being flooded out. */
.card-top::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    180deg,
    rgba(0,0,0,.10) 0%,
    rgba(0,0,0,.28) 42%,
    rgba(0,0,0,.74) 78%,
    rgba(0,0,0,.90) 100%
  );
  transition: opacity .45s ease;
}

.card-top .stat,
.card-top .stat-sub { position: relative; z-index: 2; }

.card-top .stat {
  font-family: var(--display); font-weight: 500; letter-spacing: -0.045em;
  font-size: clamp(2.6rem, 6vw, 3.7rem); line-height: .92;
  color: var(--accent);
  text-shadow: 0 2px 20px rgba(0,0,0,.45);
}
.card-top .stat-sub {
  font-size: 15px; font-weight: 600; margin-top: 12px; color: #fff;
  text-shadow: 0 1px 12px rgba(0,0,0,.5);
  max-width: 30ch;
}

/* a hairline of accent along the top edge, drawn in on reveal */
.card-top::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--accent);
  z-index: 3;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .6s cubic-bezier(.22,.61,.36,1);
}
.card.in .card-top::before,
.card:hover .card-top::before { transform: scaleX(1); }

/* hover: the photograph comes forward and finds its colour */
.card:hover .card-bg {
  transform: scale(1.14);
  opacity: .82;
  filter: grayscale(0) contrast(1.04) brightness(.95);
}
.card:hover .card-top::after { opacity: .82; }

/* slow ambient drift, so the row is never completely still */
@keyframes card-drift {
  from { transform: scale(1.06) translate3d(0, 0, 0); }
  to   { transform: scale(1.13) translate3d(-2%, -2%, 0); }
}
/* stagger the four so they never move in lockstep */
.cards .card:nth-child(2) .card-bg { animation-duration: 31s; animation-direction: alternate-reverse; }
.cards .card:nth-child(3) .card-bg { animation-duration: 37s; }
.cards .card:nth-child(4) .card-bg { animation-duration: 43s; animation-direction: alternate-reverse; }

@media (prefers-reduced-motion: reduce) {
  .card-top .card-bg { animation: none; transform: scale(1.04); transition: none; }
  .card:hover .card-bg { transform: scale(1.04); }
  .card-top::before { transition: none; transform: scaleX(1); }
}

/* ---------------------------------------------------------------- the body */

.card-body {
  padding: 26px 28px 30px;
  display: flex; flex-direction: column; gap: 14px; flex: 1;
}
.card-body .kicker {
  font-size: 12px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent-ink);
}
.card-body h3 { font-size: 1.3rem; }
.card-body ul { list-style: none; margin: 0; padding: 0; flex: 1; }
.card-body li {
  position: relative; padding-left: 30px; margin-bottom: 12px;
  font-size: 15.5px; color: var(--muted);
}
.card-body li:last-child { margin-bottom: 0; }
.card-body li::before {
  content: ""; position: absolute; left: 0; top: .18em; width: 19px; height: 19px;
  border-radius: 50%; background: var(--accent);
}
.card-body li::after {
  content: ""; position: absolute; left: 6.5px; top: .42em; width: 5px; height: 9px;
  border-right: 2px solid var(--on-accent); border-bottom: 2px solid var(--on-accent);
  transform: rotate(42deg);
}

/* ============================================================================
   MailMorph Media — client video carousel
   ----------------------------------------------------------------------------
   A horizontally scrolling rail of portrait video cards with a play affordance
   and prev/next controls.

   The component is complete; the CONTENT is empty on purpose. See the note in
   content.js — stock footage of a person under a testimonial heading is a
   fabricated endorsement, so the slots stay labelled until there is real client
   video to put in them.

   Scrolling is native overflow with scroll-snap, so it works with a trackpad,
   a touchscreen, the arrow controls and the keyboard, and needs no JS to be
   usable — the buttons only add click-to-advance.
   ========================================================================= */

.vt-section { padding-block: clamp(56px, 8vw, 100px); }

.vt-rail-wrap { position: relative; margin-top: 44px; }

.vt-rail {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding: 4px 0 18px;
  /* full-bleed edges so cards run off both sides of the shell */
  margin-inline: calc(var(--pad) * -1);
  padding-inline: var(--pad);
  scroll-padding-inline: var(--pad);
  scrollbar-width: none;
}
.vt-rail::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) { .vt-rail { scroll-behavior: auto; } }

.vt-card {
  flex: 0 0 auto;
  width: clamp(150px, 17vw, 208px);
  aspect-ratio: 3 / 4.4;
  scroll-snap-align: start;
  position: relative;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--sunken);
  text-decoration: none;
  color: inherit;
  display: block;
}

/* a filled card: poster image plus a play affordance */
.vt-card img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .5s cubic-bezier(.22,.61,.36,1), filter .4s ease;
}
.vt-card:hover img { transform: scale(1.06); }

.vt-play {
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
}
.vt-play span {
  width: 54px; height: 54px; border-radius: 50%;
  background: rgba(0,0,0,.52);
  backdrop-filter: blur(3px);
  display: grid; place-items: center;
  transition: transform .3s cubic-bezier(.22,.61,.36,1), background-color .3s ease;
}
.vt-card:hover .vt-play span { transform: scale(1.12); background: rgba(0,0,0,.68); }
.vt-play svg { width: 20px; height: 20px; fill: var(--accent); margin-left: 3px; }

.vt-meta {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  padding: 14px 14px 15px;
  background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.82) 62%);
  display: flex; flex-direction: column; gap: 2px;
}
.vt-meta strong { font-size: 14px; font-weight: 600; color: #fff; letter-spacing: -.015em; }
.vt-meta span { font-size: 12px; color: rgba(255,255,255,.76); }

/* an empty slot: dashed, labelled, unmistakably not a testimonial */
.vt-card.is-slot {
  border: 2px dashed var(--rule);
  background: var(--surface);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; text-align: center; padding: 14px;
}
.vt-card.is-slot .ring {
  width: 46px; height: 46px; border-radius: 50%;
  border: 2px dashed var(--rule);
  display: grid; place-items: center;
}
.vt-card.is-slot .ring svg { width: 16px; height: 16px; fill: var(--faint); margin-left: 2px; }
.vt-card.is-slot em {
  font-style: normal; font-size: 11.5px; font-weight: 600; color: var(--faint);
  letter-spacing: .06em; text-transform: uppercase;
}

/* ---------------------------------------------------------------- controls */

.vt-controls { display: flex; gap: 10px; justify-content: flex-end; margin-top: 6px; }
.vt-btn {
  width: 46px; height: 46px; border-radius: 50%;
  border: 1.5px solid var(--rule);
  background: var(--surface);
  display: grid; place-items: center;
  cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease, transform .2s ease, opacity .2s ease;
}
.vt-btn svg { width: 18px; height: 18px; stroke: var(--ink); fill: none; stroke-width: 2.2; }
.vt-btn:hover { background: var(--accent); border-color: var(--accent); transform: translateY(-2px); }
.vt-btn:hover svg { stroke: var(--on-accent); }
.vt-btn[disabled] { opacity: .34; cursor: default; transform: none; }
.vt-btn[disabled]:hover { background: var(--surface); border-color: var(--rule); }
.vt-btn[disabled]:hover svg { stroke: var(--ink); }

.vt-howto {
  margin-top: 26px;
  border-left: 3px solid var(--accent);
  background: var(--surface);
  padding: 18px 22px;
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 15px; color: var(--muted); max-width: 74ch;
}

/* ============================================================================
   MailMorph Media — b-roll rail
   ----------------------------------------------------------------------------
   A scrolling rail of short looping clips. Real stock video, captioned as stock.

   Loading: every <video> ships with NO src. mailmorph.js sets it from data-src
   only when the card scrolls into view, and pauses it again on the way out. The
   clips total several megabytes, so eagerly loading them would be the single
   heaviest thing on the page — this way an initial load costs nothing.

   The poster colour keeps each card from flashing empty before its clip decodes.
   ========================================================================= */

.broll-section { padding-block: clamp(48px, 7vw, 88px); }

.broll-rail {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  margin-inline: calc(var(--pad) * -1);
  padding-inline: var(--pad);
  scroll-padding-inline: var(--pad);
  padding-block: 4px 18px;
  margin-top: 40px;
  scrollbar-width: none;
}
.broll-rail::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) { .broll-rail { scroll-behavior: auto; } }

.broll-card {
  flex: 0 0 auto;
  width: clamp(228px, 26vw, 336px);
  aspect-ratio: 16 / 10;
  scroll-snap-align: start;
  position: relative;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--sunken);
  isolation: isolate;
}

.broll-card video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  /* these are preview-resolution files; a touch of scale hides the soft edges */
  transform: scale(1.02);
  filter: saturate(.92) contrast(1.04);
  transition: transform .5s cubic-bezier(.22,.61,.36,1), filter .4s ease;
}
.broll-card:hover video { transform: scale(1.07); filter: saturate(1) contrast(1); }

.broll-card::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(0,0,0,0) 44%, rgba(0,0,0,.72) 100%);
}

.broll-meta {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 14px 16px 15px;
  display: flex; flex-direction: column; gap: 2px;
}
.broll-meta strong {
  font-family: var(--display);
  font-size: 15.5px; font-weight: 600; letter-spacing: -.018em; color: #fff;
}
.broll-meta span { font-size: 12.5px; color: rgba(255,255,255,.76); }

/* a small marker so nobody mistakes ambient footage for client work */
.broll-tag {
  position: absolute; top: 12px; left: 12px; z-index: 2;
  font-size: 10px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: #fff; background: rgba(0,0,0,.46);
  backdrop-filter: blur(3px);
  padding: 5px 9px; border-radius: var(--r-pill);
}

.broll-note {
  font-size: 13px; color: var(--faint);
  max-width: 66ch; margin: 8px auto 0; text-align: center;
}

/* ============================================================================
   MailMorph Media — brand lockup
   ----------------------------------------------------------------------------
   Loaded late, so it overrides the earlier square-icon assumptions.

   The first mark was square, so mailmorph.css pinned `.brand svg` to 24x24 and
   book.css to 20x20. The supplied ribbon mark is wider than it is tall (roughly
   1.29:1), and a fixed square box squashes it. Height is fixed instead and the
   width follows the aspect ratio.
   ========================================================================= */

.brand svg,
.bk-brand svg {
  width: auto;
  height: 24px;
  flex: none;
  overflow: visible;    /* the stroke sits proud of the path's own box */
}
.bk-brand svg { height: 20px; }
.sitefoot .brand svg { height: 26px; }

/* the wordmark sits closer to a mark this wide */
.brand { gap: 11px; }

/* the mark's ribbon picks up the accent on hover, in place of the old
   three-shape animation, which no longer has three shapes to animate */
.brand svg path {
  transition: stroke .3s ease;
}
.brand:hover svg path { stroke: var(--accent-ink); }

@media (prefers-reduced-motion: reduce) {
  .brand svg path { transition: none; }
}

/* ============================================================================
   MailMorph Media — ambient background
   ----------------------------------------------------------------------------
   A fixed layer of slowly drifting accent blooms plus a fine dot grid, sitting
   behind everything on every page.

   Performance notes, because an ambient background is an easy place to wreck a
   site's scrolling:
     - the blooms are plain radial-gradients, NOT blurred elements. A large
       `filter: blur()` is repainted every frame and is genuinely expensive; a
       radial-gradient is soft for free.
     - the layer is `position: fixed`, so scrolling never repaints it.
     - only `transform` is animated, which stays on the compositor.
     - three blooms, with prime-ish durations so they never visibly re-sync.

   Legibility comes first: the blooms sit at low alpha and the dot grid is
   barely-there. Under prefers-reduced-motion the drift stops entirely and the
   composition holds as a still image.
   ========================================================================= */

.ambient {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  background: var(--paper);
}

/* fine dot grid — static texture, costs one tiled paint */
.ambient::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 1px 1px, var(--ink) 1px, transparent 0);
  background-size: 26px 26px;
  opacity: .028;
}

.bloom {
  position: absolute;
  border-radius: 50%;
  will-change: transform;
}

.bloom-1 {
  width: 62vw; height: 62vw;
  top: -18vw; right: -14vw;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 30%, transparent) 0%, transparent 68%);
  animation: drift-1 34s ease-in-out infinite alternate;
}
.bloom-2 {
  width: 54vw; height: 54vw;
  bottom: -20vw; left: -16vw;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 22%, transparent) 0%, transparent 70%);
  animation: drift-2 47s ease-in-out infinite alternate;
}
.bloom-3 {
  width: 44vw; height: 44vw;
  top: 34%; left: 46%;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 15%, transparent) 0%, transparent 72%);
  animation: drift-3 59s ease-in-out infinite alternate;
}

/* Older engines without color-mix still get a background, just a fixed tint. */
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .bloom-1 { background: radial-gradient(circle, rgba(59,239,59,.24) 0%, transparent 68%); }
  .bloom-2 { background: radial-gradient(circle, rgba(59,239,59,.18) 0%, transparent 70%); }
  .bloom-3 { background: radial-gradient(circle, rgba(59,239,59,.12) 0%, transparent 72%); }
}

@keyframes drift-1 {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-9vw, 7vh, 0) scale(1.12); }
}
@keyframes drift-2 {
  from { transform: translate3d(0, 0, 0) scale(1.06); }
  to   { transform: translate3d(11vw, -6vh, 0) scale(1); }
}
@keyframes drift-3 {
  from { transform: translate3d(0, 0, 0) scale(.94); }
  to   { transform: translate3d(-13vw, -9vh, 0) scale(1.1); }
}

@media (prefers-reduced-motion: reduce) {
  .bloom { animation: none !important; }
}

/* The blooms are behind the page, so opaque section backgrounds would hide them.
   Letting a little through keeps the ambient continuous down the whole page. */
body { background: transparent; }
.band { background: color-mix(in srgb, var(--surface) 72%, transparent); }
@supports not (background: color-mix(in srgb, red 50%, transparent)) {
  .band { background: var(--surface); }
}

/* Cards and the masthead stay opaque — text has to sit on a solid ground. */
.masthead { background: color-mix(in srgb, var(--paper) 86%, transparent); backdrop-filter: saturate(150%) blur(12px); }
@supports not (backdrop-filter: blur(4px)) { .masthead { background: var(--paper); } }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ambient::after { opacity: .05; }
  :root:not([data-theme="light"]) .bloom-1 { background: radial-gradient(circle, color-mix(in srgb, var(--accent) 16%, transparent) 0%, transparent 68%); }
  :root:not([data-theme="light"]) .bloom-2 { background: radial-gradient(circle, color-mix(in srgb, var(--accent) 12%, transparent) 0%, transparent 70%); }
  :root:not([data-theme="light"]) .bloom-3 { background: radial-gradient(circle, color-mix(in srgb, var(--accent) 9%, transparent) 0%, transparent 72%); }
}
:root[data-theme="dark"] .ambient::after { opacity: .05; }
:root[data-theme="dark"] .bloom-1 { background: radial-gradient(circle, color-mix(in srgb, var(--accent) 16%, transparent) 0%, transparent 68%); }
:root[data-theme="dark"] .bloom-2 { background: radial-gradient(circle, color-mix(in srgb, var(--accent) 12%, transparent) 0%, transparent 70%); }
:root[data-theme="dark"] .bloom-3 { background: radial-gradient(circle, color-mix(in srgb, var(--accent) 9%, transparent) 0%, transparent 72%); }
