/* ===========================================================================
   Luna IT Consulting — stylesheet
   Rebuilt to match the design tokens read off the live Squarespace template:

     h1    Roboto 700, 3em,  letter-spacing -.01em, line-height 1
     h2    Roboto 700, 24px, letter-spacing -.07em, line-height .9, capitalize
     h3    futura-pt 400, 14px, uppercase, letter-spacing .15em, line-height 2
     body  proxima-nova 400, 18px, letter-spacing .01em, line-height 1.8
     chrome  20px white site border, 640px mobile breakpoint

   futura-pt and proxima-nova are licensed Adobe Fonts and cannot be
   self-hosted, so Jost and Inter stand in for them (see assets/fonts.css).
   =========================================================================== */

:root {
  /* Light theme. Every colour below is redefined in the
     prefers-color-scheme: dark block at the end of this file, so add new
     colours here as tokens rather than as literals further down. */
  color-scheme: light dark;

  --surface: #fff;
  --surface-alt: #f5f5f6;
  --ink: #222;
  --ink-strong: #000;
  --muted: #707070;
  --rule: #ddd;
  --rule-soft: #ececec;
  --header-bg: rgba(255, 255, 255, .96);
  --nav-link: rgba(0, 0, 0, .6);
  --shadow: rgba(0, 0, 0, .07);
  --brand: #719cfe;
  --glow: rgba(113, 156, 254, .13);
  --card: #fff;

  --font-head: 'Roboto', 'Helvetica Neue', Arial, sans-serif;
  --font-accent: 'Jost', 'Futura', 'Century Gothic', sans-serif;
  --font-body: 'Inter', 'Helvetica Neue', Arial, sans-serif;

  --border-w: 20px;
  --header-h: 120px;
  --wrap: 1100px;
  --wrap-narrow: 760px;
  --wrap-wide: 1360px;
}

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

html {
  scroll-behavior: smooth;
  /* Keep anchored sections clear of the fixed header. */
  scroll-padding-top: calc(var(--header-h) + var(--border-w));
}

body {
  margin: 0;
  padding: var(--border-w);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 18px;
  font-weight: 400;
  letter-spacing: .01em;
  line-height: 1.8;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* The 20px white frame that rings the viewport. Content scrolls beneath it. */
.site-border {
  position: fixed;
  inset: 0;
  border: var(--border-w) solid var(--surface);
  pointer-events: none;
  z-index: 900;
}

/* --------------------------------------------------------------- typography */

h1, h2, h3 { margin: 0; }

h1 {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: clamp(2.25rem, 6.2vw, 3rem);
  letter-spacing: -.01em;
  line-height: 1;
  color: var(--ink-strong);
}

h2 {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: clamp(1.75rem, 4.4vw, 2.5rem);
  letter-spacing: -.07em;
  line-height: .9;
  color: var(--ink-strong);

  /* The live Squarespace site sets a site-wide `text-transform: capitalize`, so
     every h2 rendered in title case — "for small and medium sized businesses"
     became "For Small And Medium Sized Businesses". Dropped as part of the
     layout change; set this back to `capitalize` to restore the old look. */
  text-transform: none;
}

h3 {
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: .15em;
  line-height: 2;
  color: var(--ink-strong);
}

p { margin: 0 0 1.4em; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

.lede {
  color: var(--muted);
  margin-top: 1.1em;
}

.subhead {
  margin-top: 1.2em;
  color: var(--muted);
}

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

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

.wrap.narrow { max-width: var(--wrap-narrow); }
.wrap.wide { max-width: var(--wrap-wide); }

.section { padding: clamp(64px, 11vw, 130px) 0; }
.section-alt { background: var(--surface-alt); }

.section-head {
  margin-bottom: clamp(40px, 6vw, 68px);
  max-width: 62ch;
}

/* Caps line length without centring the column, so every section shares one
   left edge instead of each being optically centred at its own width. */
.measure { max-width: 68ch; }

/* Small uppercase label above a heading. */
.eyebrow {
  display: block;
  margin-bottom: 14px;
  font-family: var(--font-accent);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .2em;
  line-height: 1;
  color: var(--muted);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink-strong);
  color: var(--surface);
  padding: 12px 20px;
  z-index: 1000;
}
.skip-link:focus { left: var(--border-w); top: var(--border-w); }

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

.header {
  position: fixed;
  top: var(--border-w);
  left: var(--border-w);
  right: var(--border-w);
  height: var(--header-h);
  z-index: 800;
  transition: background-color .25s ease, box-shadow .25s ease;
}

/* Solid once the page has scrolled past the hero (toggled in script.js). */
.header.is-stuck {
  background: var(--header-bg);
  box-shadow: 0 1px 0 var(--rule-soft);
  backdrop-filter: saturate(160%) blur(6px);
}

.header-inner {
  max-width: var(--wrap);
  height: 100%;
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.brand {
  display: flex;
  align-items: center;
  flex: none;
  text-decoration: none;
}

/* Site logo. Squarespace serves this lockup at max-width:150px in a tall
   centred header; here it sits left in a 120px bar, so it is sized by width
   and the header height is set to clear it. */
.brand-logo {
  display: block;
  width: 100px;
  height: auto;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2.4vw, 28px);
}

/* --------------------------------------------------------- theme toggle */

.theme-toggle {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: none;
  padding: 3px;
  border: 1px solid var(--rule-soft);
  border-radius: 999px;
  background: var(--card);
}

.theme-toggle button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: background-color .17s ease-out, color .17s ease-out;
}

.theme-toggle button:hover { color: var(--ink-strong); }

.theme-toggle button[aria-pressed="true"] {
  background: var(--surface-alt);
  color: var(--ink-strong);
}

.theme-toggle svg {
  display: block;
  width: 15px;
  height: 15px;
}

.nav-menu {
  display: flex;
  align-items: center;
  gap: 2em;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-menu a {
  font-family: var(--font-accent);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .15em;
  color: var(--nav-link);
  text-decoration: none;
  padding: .618em 0;
  transition: color .17s ease-out;
}

.nav-menu a:hover,
.nav-menu a:focus-visible { color: var(--ink-strong); }

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
}

.nav-toggle-bar {
  display: block;
  width: 24px;
  height: 1.5px;
  margin: 0 auto;
  background: var(--ink-strong);
  transition: transform .25s ease, opacity .25s ease;
}

.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(3.75px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { transform: translateY(-3.75px) rotate(-45deg); }

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

.hero {
  position: relative;
  min-height: 80vh;
  max-height: 900px;
  display: flex;
  align-items: center;
  padding: calc(var(--header-h) + 40px) 0 96px;
  /* Soft brand-blue wash behind the mark. Painted on the element itself
     rather than a ::before, because a negative z-index pseudo would fall
     behind the body background -- .hero creates no stacking context. */
  background: radial-gradient(58% 52% at 74% 44%, var(--glow), transparent 72%);
}

/* Copy left, mark right. The columns collapse to one below 760px. */
.hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  align-items: center;
  gap: clamp(28px, 5vw, 64px);
  text-align: left;
}

.hero h1 {
  font-size: clamp(2.4rem, 6.4vw, 3.9rem);
  letter-spacing: -.035em;
  line-height: 1.02;
}

.hero-mark {
  display: block;
  width: 100%;
  max-width: 290px;
  height: auto;
  margin: 0 0 0 auto;
}

.hero-sub {
  margin-top: .6em;
  font-weight: 400;
  font-size: clamp(1.1rem, 2.6vw, 1.5rem);
  letter-spacing: -.01em;
  line-height: 1.3;
  color: var(--muted);
}

.scroll-cue {
  position: absolute;
  bottom: 34px;
  /* Line up with the left edge of .wrap's content box. */
  left: max(24px, calc((100% - var(--wrap)) / 2 + 24px));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: var(--muted);
}

.scroll-cue-text {
  font-family: var(--font-accent);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .22em;
}

/* Thin vertical rule that pulses downward — the template's scroll indicator. */
.scroll-cue-line {
  width: 1px;
  height: 56px;
  background: var(--rule);
  position: relative;
  overflow: hidden;
}

.scroll-cue-line::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 40%;
  background: var(--ink-strong);
  animation: scroll-cue 2.1s cubic-bezier(.6, .04, .3, 1) infinite;
}

@keyframes scroll-cue {
  0%   { transform: translateY(-100%); }
  100% { transform: translateY(250%); }
}

/* ---------------------------------------------------------------- banners */

.banner {
  height: clamp(300px, 52vh, 560px);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;   /* parallax, per tweak-overlay-parallax-enabled */
}

.banner-chairs { background-image: url("assets/banner-chairs.webp"); }
.banner-desk   { background-image: url("assets/banner-desk.webp"); }

/* --------------------------------------------------------------- services */

/* Explicit column counts, NOT auto-fit. There are eight cards, so the grid has
   to resolve to 4, 2 or 1 columns and never 3 -- eight cards in three columns
   is 3+3+2, which leaves a hole in the last row and breaks the equal-proportions
   requirement. auto-fit picks its own column count from the available width and
   would land on 3 somewhere in the middle of the range, so the breakpoints are
   spelled out instead. If the card count changes, these numbers change with it.

   The section uses .wrap.wide (1360px) rather than the standard 1100px: four
   cards in the narrower container would be 245px each, too cramped for a
   paragraph, four bullets, a price and a button.

   align-items must stay stretch, NOT start. With start, each card is only as
   tall as its copy, so a row of cards with different-length paragraphs comes
   out visibly ragged -- and .service-price's `margin-top: auto` has no slack to
   work with, so prices and CTAs do not bottom-align either. */
.services {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(18px, 2.2vw, 26px);
  align-items: stretch;
}

@media (min-width: 640px) {
  .services { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1280px) {
  .services { grid-template-columns: repeat(4, 1fr); }
}

.service {
  padding: clamp(26px, 3vw, 34px);
  border: 1px solid var(--rule-soft);
  border-radius: 14px;
  background: var(--card);
  font-size: 16px;
  line-height: 1.7;
}

/* Card titles read as headings rather than the site's uppercase h3 label. */
.service h3 {
  margin-bottom: .5em;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.15rem;
  text-transform: none;
  letter-spacing: -.015em;
  line-height: 1.3;
}

.service-lede {
  margin-bottom: 1em;
  color: var(--ink-strong);
  font-size: 16px;
  line-height: 1.5;
}

.service-points {
  list-style: none;
  margin: 1.3em 0 0;
  padding: 0;
  border-top: 1px solid var(--rule-soft);
  padding-top: 1.2em;
  font-size: 15px;
}

.service-points li {
  position: relative;
  margin-bottom: .65em;
  padding-left: 18px;
  line-height: 1.55;
  color: var(--muted);
}

.service-points li:last-child { margin-bottom: 0; }

.service-points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .55em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--brand);
}

/* ------------------------------------------------------------------ proof */
/* Live ahead of the markup: the proof section in index.html is commented out
   until Salvatore writes the copy, so uncommenting is the only step left. */

.credibility {
  max-width: 62ch;
  margin: 0 0 clamp(48px, 7vw, 80px);
  padding-left: 20px;
  border-left: 3px solid var(--brand);
  font-size: clamp(1.05rem, 2.2vw, 1.25rem);
  line-height: 1.6;
  color: var(--ink-strong);
}

/* .credibility was written to lead the proof section: no space above, a lot
   below. Closing the Mission block instead it needs the reverse, or its bottom
   margin doubles up with the section's own padding. Declared after the base
   rule so source order wins -- both are one class deep, so !important would
   only be papering over ordering. */
.credibility-inline {
  margin-top: clamp(40px, 5vw, 56px);
  margin-bottom: 0;
}

/* Equal-height cards. align-items must stay stretch, never start: these are
   bordered boxes side by side, and with start each one shrinks to its own copy
   so a row of them comes out visibly ragged. Same rule as .services. */
/* Employment wordmarks. Text, not logo images -- see the note in index.html.
   Muted at rest so they read as a quiet credential rather than a client roster,
   which is the distinction spec 3A draws. */
.wordmarks {
  margin: 0 0 clamp(40px, 5vw, 60px);
  padding-bottom: clamp(28px, 4vw, 40px);
  border-bottom: 1px solid var(--rule-soft);
}

.wordmarks-label {
  margin-bottom: 1.1em;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--muted);
}

.wordmark-list {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: clamp(20px, 3.5vw, 44px);
  list-style: none;
  margin: 0;
  padding: 0;
}

.wordmark-list li {
  font-family: var(--font-head);
  font-size: clamp(1.05rem, 2.4vw, 1.4rem);
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--ink-strong);
  opacity: .55;
  transition: opacity .2s ease-out;
}

.wordmark-list li:hover { opacity: 1; }

/* Availability badge. The dot is a CSS pseudo-element rather than an emoji --
   emoji render inconsistently across platforms and nothing else here uses one. */
.availability-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 1em;
  padding: 6px 14px;
  border: 1px solid var(--rule-soft);
  border-radius: 999px;
  background: var(--surface-alt);
  font-size: 13px;
  color: var(--muted);
}

.availability-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #3fa66a;
  flex: 0 0 auto;
}

.proof-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(18px, 2.2vw, 26px);
  align-items: stretch;
}

/* Column layout so the context line can be pushed to the bottom -- equal boxes
   with the "Context:" rules floating at three different heights is the same
   raggedness one level down. */
.proof-item {
  display: flex;
  flex-direction: column;
  padding: clamp(24px, 2.8vw, 32px);
  border: 1px solid var(--rule-soft);
  border-radius: 14px;
  background: var(--card);
  font-size: 16px;
  line-height: 1.7;
}

.proof-item h3 {
  margin-bottom: .7em;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.05rem;
  text-transform: none;
  letter-spacing: -.015em;
  line-height: 1.35;
}

.proof-context {
  /* auto top margin pushes this to the card's bottom edge, so the Context rules
     line up across a row regardless of how long each paragraph runs.
     padding-top keeps the rule clear of the text when a card is full enough
     that there is no free space left to absorb. */
  margin: auto 0 0;
  padding-top: 1em;
  border-top: 1px solid var(--rule-soft);
  font-size: 14px;
  font-style: italic;
  color: var(--muted);
}

/* ------------------------------------------------------------------ offer */

/* Priced cards. The shell is .service (see above) -- these rules only add the
   price block and the bits a card needs that a plain service pillar does not.
   The old single .offer block, a 720px feature card holding the one price on
   the page, was removed when the Health Check became one of five equal cards.

   .services is reused for the grid as-is: repeat(auto-fit, minmax(290px, 1fr))
   gives three across then two on a wide viewport, and stacks on mobile. */

/* Cards carry a CTA, so the list needs to stop short of it rather than run to
   the card's bottom edge. */
.service .service-points {
  margin-bottom: 1.4em;
}

/* Push the price and CTA to the bottom so a row of cards lines up despite
   different copy lengths. */
.service {
  display: flex;
  flex-direction: column;
}

.service .service-price {
  margin-top: auto;
}

/* Always two lines: price, then qualifier beneath it. This was flex-wrap:wrap
   with a baseline alignment, which only broke the line when the qualifier did
   not fit -- so "per month, up to 4 hours" stayed alongside $1,200 while
   "within one week of repository access" dropped below $1,500. That made the
   price blocks different heights, which pushed the rows out of line with each
   other even though the buttons below them were aligned. A column never wraps
   inconsistently, because it never relies on the text's length. */
.service-price {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  margin: 0 0 1.3em;
  padding-top: 1.2em;
  border-top: 1px solid var(--rule-soft);
}

/* Smaller than the old .offer-price: it sits in a 290px-wide card, not a
   720px feature block. */
.service-price strong {
  font-family: var(--font-head);
  font-size: 1.45rem;
  font-weight: 700;
  letter-spacing: -.03em;
  line-height: 1;
  color: var(--ink-strong);
}

.service-price span {
  font-size: 14px;
  color: var(--muted);
}

/* CTAs span the full card width, which is the only way to make them genuinely
   equal. Shrink-wrapping to the label cannot: the font is proportional, so even
   labels with an identical character count render at different widths, and a
   long one ("START A HEALTH CHECK") wraps to two lines, growing that button's
   height and pushing its price row out of line with the rest of the row.
   Stretching removes all of that -- every card is the same width, so every
   button is too, and none of them can wrap. */
.service .btn {
  align-self: stretch;
  text-align: center;
}

/* ------------------------------------------------------------------- team */

.profile {
  display: grid;
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 64px);
  align-items: start;
  max-width: 980px;
}

.profile-photo img {
  display: block;
  width: 100%;
  height: auto;
  filter: grayscale(100%);
  transition: filter .4s ease;
}

.profile-photo img:hover { filter: grayscale(0%); }

.profile-name { margin-bottom: .1em; }

/* The name links to LinkedIn but must not look like a link: it keeps the
   heading's colour, weight and size exactly. Underline on hover and a visible
   focus ring are the only affordances, so the resting appearance is unchanged
   while the link is still discoverable by mouse and reachable by keyboard. */
.profile-name a {
  color: inherit;
  text-decoration: none;
}

.profile-name a:hover { text-decoration: underline; }

.profile-name a:focus-visible,
.profile-photo a:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}

/* The photo already reveals its colour on hover (see .profile-photo img:hover),
   which doubles as the affordance -- the link wrapper needs no styling of its
   own beyond being a block so it does not add inline descender space. */
.profile-photo a { display: block; }

.profile-role {
  color: var(--muted);
  margin-bottom: 1.6em;
}

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

/* Calendly and the form are equal peers, side by side -- the form must not
   read as a fallback for people unwilling to book a call. */
.contact-split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: clamp(24px, 3vw, 40px);
  align-items: start;
  margin-top: 8px;
}

.contact-option h3 {
  margin-bottom: .8em;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 1.05rem;
  text-transform: none;
  letter-spacing: -.01em;
  line-height: 1.35;
}

.contact-option > p {
  margin-bottom: 1.4em;
  font-size: 16px;
  color: var(--muted);
}

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

.contact-form { margin: 0; }

.field { margin-bottom: 18px; }

.field label {
  display: block;
  margin-bottom: 7px;
  font-family: var(--font-accent);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .15em;
  color: var(--muted);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--card);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  transition: border-color .17s ease-out, box-shadow .17s ease-out;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--glow);
}

.field textarea { resize: vertical; }

.field input.is-invalid,
.field select.is-invalid,
.field textarea.is-invalid { border-color: #b3261e; }

/* Honeypot -- hidden from people, catches bots. */
.hp-field {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.form-note {
  min-height: 1.6em;
  margin: 14px 0 0;
  font-size: 15px;
  color: var(--muted);
}

.form-note.is-error { color: #b3261e; }
.form-note.is-success { color: #1e7d32; }

.contact-direct {
  margin: 24px 0 0;
  font-size: 15px;
  color: var(--muted);
}

.contact-direct a,
.btn-email-inline {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.contact-direct a:hover,
.contact-direct a:focus-visible { color: var(--ink-strong); }

.contact-direct { margin-top: clamp(28px, 4vw, 40px); }


.btn {
  display: inline-block;
  padding: 15px 44px;
  border: 1px solid var(--ink-strong);
  background: var(--ink-strong);
  color: var(--surface);
  font-family: var(--font-accent);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .18em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .17s ease-out, color .17s ease-out;
}

.btn:hover:not(:disabled),
.btn:focus-visible:not(:disabled) {
  background: var(--surface);
  color: var(--ink-strong);
}

/* Outline variant, paired with the filled .btn in the contact CTA row. */
.btn-secondary {
  background: transparent;
  color: var(--ink-strong);
}

.btn-secondary:hover,
.btn-secondary:focus-visible {
  background: var(--ink-strong);
  color: var(--surface);
}

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

.footer {
  border-top: 1px solid var(--rule-soft);
  padding: clamp(56px, 8vw, 88px) 0 40px;
}

.footer-inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: clamp(32px, 5vw, 56px);
}

.footer-col h3 { margin-bottom: 1.2em; }

.footer address {
  font-style: normal;
  font-size: 16px;
  line-height: 1.9;
  color: var(--muted);
}

.footer a {
  color: var(--muted);
  text-decoration: none;
  transition: color .17s ease-out;
}

.footer a:hover,
.footer a:focus-visible { color: var(--ink-strong); }

.footer-nav {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 16px;
  color: var(--muted);
}

/* Replaced the footer's Mon-Sat "All Day" table, which invited weekday phone
   calls that cannot be answered. A sentence needs prose styling, not a row. */
.availability {
  margin: 0 0 1em;
  max-width: 26ch;
  font-size: 16px;
  line-height: 1.7;
  color: var(--muted);
}

.availability:last-child { margin-bottom: 0; }

.footer-nav li { line-height: 1.9; }

.copyright {
  max-width: var(--wrap);
  margin: clamp(48px, 7vw, 72px) auto 0;
  padding: 0 24px;
  font-size: 14px;
  color: var(--muted);
  text-align: center;
}

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

.legal { padding-top: calc(var(--header-h) + 72px); }

.back-link {
  display: inline-block;
  margin-bottom: 40px;
  font-family: var(--font-accent);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .15em;
  color: var(--muted);
  text-decoration: none;
}

.back-link:hover,
.back-link:focus-visible { color: var(--ink-strong); }

.legal h1 { margin-bottom: .3em; }

.legal h2 {
  margin: 2em 0 .7em;
  font-size: clamp(1.25rem, 2.8vw, 1.6rem);
  letter-spacing: -.04em;
  line-height: 1.15;
}

.legal .updated {
  color: var(--muted);
  font-size: 15px;
  margin-bottom: 2.4em;
}

.legal ul {
  margin: 0 0 1.4em;
  padding-left: 1.2em;
}

.legal li { margin-bottom: .8em; }

.legal a { text-decoration: underline; }

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

.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s ease, transform .7s ease;
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* ------------------------------------------------------------- responsive */

@media (max-width: 900px) {
  .profile { grid-template-columns: 1fr; }
  .profile-photo { max-width: 320px; }
}

/* tweak-mobile-breakpoint = 640px */
@media (max-width: 640px) {
  :root { --border-w: 12px; --header-h: 96px; }

  body { font-size: 17px; }

  .brand-logo { width: 78px; }

  .hero-inner { grid-template-columns: 1fr; gap: 24px; }
  .hero-mark { max-width: 190px; margin: 0 0 8px; }
  .theme-toggle button { width: 28px; height: 28px; }

  .nav-toggle { display: flex; }

  .nav-menu {
    position: fixed;
    top: calc(var(--border-w) + var(--header-h));
    left: var(--border-w);
    right: var(--border-w);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 8px 0 20px;
    background: var(--surface);
    border-top: 1px solid var(--rule-soft);
    box-shadow: 0 18px 30px var(--shadow);
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .22s ease, transform .22s ease, visibility .22s;
  }

  .nav-menu.is-open {
    transform: none;
    opacity: 1;
    visibility: visible;
  }

  .nav-menu a {
    display: block;
    padding: 14px 24px;
    font-size: 14px;
  }

  /* Fixed backgrounds are unreliable on mobile Safari. */
  .banner { background-attachment: scroll; }

  /* .service .btn is already full-width at every breakpoint -- see the rule in
     the offer section. Nothing to override here. */

  .contact-option .btn { display: block; text-align: center; }

  .availability { max-width: none; }
}

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

  .reveal,
  .profile-photo img {
    transition: none;
    opacity: 1;
    transform: none;
  }

  .scroll-cue-line::after { animation: none; }
}

/* Printing: drop the chrome, keep the words. */
@media print {
  .site-border,
  .header,
  .scroll-cue,
  .banner,
  .contact-split { display: none; }

  body { padding: 0; font-size: 12pt; }
  .section { padding: 18pt 0; }
}

/* -------------------------------------------------------------- dark theme */
/* Three states. With no override, prefers-color-scheme decides; an explicit
   choice sets data-theme on <html> and wins in both directions. The token
   block is duplicated rather than shared because plain CSS has no way to
   assign one declaration list to two selectors -- keep the two copies in sync.
   assets/theme-init.js applies a saved choice before first paint. */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --surface: #1c1d1f;
    --surface-alt: #1f2023;
    --ink: #d7d7d4;
    --ink-strong: #f5f5f3;
    --muted: #9b9b98;
    --rule: #3b3c3f;
    --rule-soft: #2c2d30;
    --header-bg: rgba(28, 29, 31, .96);
    --nav-link: rgba(255, 255, 255, .66);
    --shadow: rgba(0, 0, 0, .5);
    --brand: #719cfe;
    --glow: rgba(113, 156, 254, .16);
    --card: #26272b;
  }

  :root:not([data-theme="light"]) .banner { filter: brightness(.78) saturate(.95); }
}

:root[data-theme="dark"] {
    --surface: #1c1d1f;
    --surface-alt: #1f2023;
    --ink: #d7d7d4;
    --ink-strong: #f5f5f3;
    --muted: #9b9b98;
    --rule: #3b3c3f;
    --rule-soft: #2c2d30;
    --header-bg: rgba(28, 29, 31, .96);
    --nav-link: rgba(255, 255, 255, .66);
    --shadow: rgba(0, 0, 0, .5);
    --brand: #719cfe;
    --glow: rgba(113, 156, 254, .16);
    --card: #26272b;
}

:root[data-theme="dark"] .banner { filter: brightness(.78) saturate(.95); }

/* Keep native controls and scrollbars in step with an explicit choice. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* The header wordmark is black artwork, so each theme needs its own file.
   A <picture> media source cannot see data-theme, so both images ship and
   CSS picks one -- ~10KB each, and it avoids a JS-driven swap that would
   flash on load. */
.brand-logo-dark { display: none; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-logo-light { display: none; }
  :root:not([data-theme="light"]) .brand-logo-dark { display: block; }
}

:root[data-theme="dark"] .brand-logo-light { display: none; }
:root[data-theme="dark"] .brand-logo-dark { display: block; }
:root[data-theme="light"] .brand-logo-light { display: block; }
:root[data-theme="light"] .brand-logo-dark { display: none; }
