/* ==========================================================================
   Lumora Projects Co — main stylesheet
   Mobile-first. Single stylesheet by design: at seven pages, splitting CSS per
   section costs more requests than it saves bytes.
   Colours and type come from tokens.css. No hex values below this line.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Reset and base
   -------------------------------------------------------------------------- */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Stop the sticky nav covering a section when a jump link lands on it */
  scroll-padding-top: calc(var(--nav-h) + var(--s-4));
}

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

body {
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
svg,
picture {
  display: block;
  max-width: 100%;
  height: auto;
}

button,
input,
textarea,
select {
  font: inherit;
  color: inherit;
}

a { color: var(--forest); }

/* Forest on forest is invisible, so inline links on the dark band switch to
   mist (5.0:1). Buttons set their own colours; the footer sets its own. */
.section--forest a:not(.btn),
.pagehead a,
.entity-card a { color: var(--mist); }

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--ink);
  text-wrap: balance;
}

h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }

/* Playfair is a high-contrast display serif: its thin strokes are hairlines.
   At card-title sizes those hairlines fall under a pixel and the negative
   tracking inherited from the display sizes crowds them further, which is what
   made the small headings hard to read. Normal tracking from h3 down. */
h3 {
  font-size: var(--t-h3);
  line-height: var(--lh-snug);
  letter-spacing: normal;
}

h4 {
  font-size: var(--t-h4);
  line-height: var(--lh-snug);
  letter-spacing: normal;
  font-weight: 600;
}

p { text-wrap: pretty; }

:focus-visible {
  outline: 3px solid var(--forest);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* Visible only to keyboard users, first thing in the tab order */
.skip-link {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -110%);
  z-index: 200;
  padding: var(--s-3) var(--s-5);
  background: var(--forest);
  color: var(--white);
  font-weight: 600;
  text-decoration: none;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  transition: transform 0.15s var(--ease);
}

.skip-link:focus-visible { transform: translate(-50%, 0); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   2. Layout primitives
   -------------------------------------------------------------------------- */

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

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

.section { padding-block: var(--section-y); }
.section--tight { padding-block: var(--section-y-s); }

/* Spacing is a decision, not a constant. The framework and the first step are
   what the page is for, so they breathe; the supporting sections sit closer. */
.section--airy { padding-block: calc(var(--section-y) * 1.35); }
.section--close { padding-block: calc(var(--section-y) * 0.78); }
.section--stone { background: var(--stone); }
.section--white { background: var(--white); }

.section--forest {
  background: var(--forest);
  color: var(--stone);
}

.section--forest h2,
.section--forest h3,
.section--forest h4 { color: var(--white); }

/* The brand's rising-arc graphic element, as a background wash */
.section--forest.has-arc {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.has-arc::after {
  content: '';
  position: absolute;
  z-index: -1;
  inset: auto -20% -60% -20%;
  aspect-ratio: 2 / 1;
  border-radius: 50%;
  border-top: 2px solid var(--forest);
  opacity: 0.5;
  background: radial-gradient(ellipse at 50% 0%, rgba(46, 107, 87, 0.20), transparent 62%);
}

/* --------------------------------------------------------------------------
   3. Section headings
   -------------------------------------------------------------------------- */

/* No eyebrow labels, no decorative rules under headings. A small uppercase
   badge above every section heading is the single most recognisable
   generated-page tell, and the headings here carry themselves. */

.section-head {
  max-width: 46rem;
  margin-bottom: var(--s-8);
}

.section-head p {
  margin-top: var(--s-4);
  font-size: var(--t-lead);
  color: var(--ink-muted);
}

.section--forest .section-head p { color: var(--mist); }/* Hairline between two consecutive white sections, where a background change
   would otherwise be the only separator */

/* --------------------------------------------------------------------------
   4. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 48px;              /* tap target floor */
  padding: var(--s-3) var(--s-6);
  /* Inter, not Playfair. The guide assigns Playfair to headings and Inter to
     body; a display serif set small, uppercase and tracked reads badly. */
  font-family: var(--font-body);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  border: 2px solid transparent;
  border-radius: var(--radius-btn);
  cursor: pointer;
  transition: background-color 0.18s var(--ease),
              border-color 0.18s var(--ease),
              color 0.18s var(--ease),
              transform 0.18s var(--ease);
}

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

.btn--primary {
  background: var(--forest);
  border-color: var(--forest);
  color: var(--white);
}

.btn--primary:hover {
  background: var(--forest-dark);
  border-color: var(--forest-dark);
}

.btn--outline {
  background: transparent;
  border-color: var(--forest);
  color: var(--forest);
}

.btn--outline:hover {
  background: var(--forest);
  color: var(--white);
}

/* On the forest band a forest outline disappears. Mist is 5.0:1 on forest;
   sand gold is only 3.8:1 and cannot carry button text. */
.on-dark .btn--outline,
.entity-card .btn--outline,
.section--forest .btn--outline {
  border-color: var(--mist);
  color: var(--mist);
}

.on-dark .btn--outline:hover,
.entity-card .btn--outline:hover,
.section--forest .btn--outline:hover {
  background: var(--mist);
  color: var(--forest);
}/* A forest-filled primary button on a forest surface is the same colour as
   the surface — it reads as loose text, not a button. Invert it. The photo
   band gets the same treatment: its placeholder ground is forest, and once a
   real photograph lands the white fill still reads against the scrim. */


.section--forest .btn--primary,
.entity-card .btn--primary {
  background: var(--white);
  border-color: var(--white);
  color: var(--forest);
}

.section--forest .btn--primary:hover,
.entity-card .btn--primary:hover {
  background: var(--mist);
  border-color: var(--mist);
  color: var(--forest-dark);
}

.btn--sm {
  min-height: 40px;
  padding: var(--s-2) var(--s-4);
  font-size: 0.8125rem;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-6);
}

.btn-row--center { justify-content: center; }

/* Full-width buttons on the narrowest phones, side by side above that */
@media (max-width: 27.4375rem) {
  .btn-row .btn { flex: 1 1 100%; }
}

/* --------------------------------------------------------------------------
   5. Navigation
   -------------------------------------------------------------------------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--white);
  border-bottom: 1px solid var(--rule);
}

/* Deepen the shadow once the page has scrolled. main.js sets .is-stuck, and
   like .is-open this class never appears in the built HTML, so a class-usage
   scan will always report it dead. It is not. */
.nav.is-stuck { box-shadow: var(--shadow); }

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: var(--nav-h);
}

/* --- Wordmark --- */
.wordmark {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  text-decoration: none;
  line-height: 1;
}

.wordmark__name {
  display: flex;
  align-items: center;
  font-family: var(--font-heading);
  font-size: 1.375rem;
  font-weight: 500;
  letter-spacing: var(--ls-logo);
  color: var(--ink);
}

/* The O in LUMORA carries the beacon mark from the logo */
.wordmark__mark {
  width: 0.92em;
  height: 0.92em;
  margin-inline: 0.02em;
  flex: none;
}

.wordmark__sub {
  font-family: var(--font-heading);
  font-size: 0.5625rem;
  font-weight: 600;
  letter-spacing: 0.42em;
  text-indent: 0.42em;   /* optical centring against the tracked-out name */
  color: var(--forest);
}

.on-dark .wordmark__name { color: var(--white); }
.on-dark .wordmark__sub { color: var(--mist); }

/* --- Links --- */
.nav__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-right: calc(var(--s-3) * -1);
  background: none;
  border: 0;
  color: var(--ink);
  cursor: pointer;
}

.nav__toggle svg { width: 26px; height: 26px; }
.nav__toggle .icon-close { display: none; }
.nav__toggle[aria-expanded='true'] .icon-close { display: block; }
.nav__toggle[aria-expanded='true'] .icon-open { display: none; }

/* Closed by default below the desktop breakpoint. main.js adds .is-open, and
   the rule below is the only thing that reveals the drawer — without it the
   toggle sets aria-expanded="true" over a menu that never appears, which is
   both a dead mobile nav and a WCAG 4.1.2 failure. Do not remove it because a
   class-usage scan of the HTML reports it unused: it is added at runtime and
   so never appears in the built markup. */
.nav__menu {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  flex-direction: column;
  gap: var(--s-1);
  padding: var(--s-4) var(--gutter) var(--s-6);
  list-style: none;
  background: var(--white);
  border-bottom: 1px solid var(--rule);
  box-shadow: var(--shadow);
}

.nav__menu.is-open { display: flex; }

.nav__menu a {
  display: block;
  padding: var(--s-3) 0;
  font-family: var(--font-body);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
}

.nav__menu .btn {
  margin-top: var(--s-4);
  border-bottom: 0;
  color: var(--white);
}

.nav__cta-desktop { display: none; }

@media (min-width: 60rem) {
  .nav__toggle { display: none; }

  .nav__menu {
    display: flex;
    position: static;
    flex-direction: row;
    align-items: center;
    gap: var(--s-6);
    padding: 0;
    background: none;
    border: 0;
    box-shadow: none;
  }

  .nav__menu a {
    padding: var(--s-2) 0;
    border-bottom: 2px solid transparent;
    transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
  }

  .nav__menu a:hover { color: var(--forest); }

  .nav__menu .btn { display: none; }
  .nav__cta-desktop { display: inline-flex; }
}

/* --------------------------------------------------------------------------
   6. Hero
   -------------------------------------------------------------------------- */

/* Light hero, following the brand guide (13 Aug 2026), which is 78% light and
   has no dark neutral at all. Warm stone ground with the guide's soft green
   wave rising from the lower left. Template structure kept: two-size
   headline, check row, dual CTA, cut-out photo bleeding into the strip. */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--stone);
  color: var(--ink);
  padding-block: var(--section-y);
  text-align: center;
}

/* The watercolour wave from the guide's hero panel: soft sage banked into the
   lower left, with a barely-there gold warmth top right. */
.hero::before {
  content: '';
  position: absolute;
  z-index: -2;
  inset: -10% -20%;
  background:
    radial-gradient(ellipse 52% 34% at 12% 96%, rgba(167, 195, 176, 0.85), transparent 70%),
    radial-gradient(ellipse 38% 26% at 30% 104%, rgba(46, 107, 87, 0.22), transparent 72%),
    radial-gradient(ellipse 42% 30% at 86% 4%, rgba(216, 200, 161, 0.30), transparent 74%);
}

/* The brand's rising arc, drawn as the sweep from the logo */
.hero::after {
  content: '';
  position: absolute;
  z-index: -1;
  left: -30%;
  right: -30%;
  bottom: -34%;
  aspect-ratio: 2.2 / 1;
  border-radius: 50%;
  border-top: 1.5px solid var(--forest);
  opacity: 0.35;
}

.hero h1 { color: var(--ink); }

/* Two-part headline. The template drops the first line back and lets the
   second line carry the weight — that size jump is most of its character. */
.hero__title {
  display: block;
  max-width: 60rem;
  margin-inline: auto;
}/* The quiet first line. Optical space beneath it, not line-height, so the two
   lines read as a pair rather than one block of text. */

.hero__title-lg {
  display: block;
  /* Retuned for a longer headline: 32px at 375 and 76px at 1440, so the
     mobile fold gets 3 lines rather than 4 and the CTAs stay in view. */
  font-size: clamp(2rem, 1.03rem + 4.13vw, 4.75rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.025em;
}

/* Never styled until now: no max-width meant a 1200px measure at 17px, and no
   margin meant it sat flush against the headline. */
.hero__lead {
  max-width: 46ch;
  margin: var(--s-6) auto 0;
  font-size: var(--t-lead);
  line-height: 1.6;
  color: var(--ink-muted);
}

/* The hero is centred, and .btn-row defaults to flex-start. Without this the
   CTAs sit hard left under a centred headline. */
.hero .btn-row { justify-content: center; }

/* --- Review strip beneath the hero --- *//* Gold stars would be the convention, but sand gold on the mist strip is
   1.3:1 — invisible. Forest is 5.0:1 on it. */

/* --------------------------------------------------------------------------
   7. Media and placeholders
   -------------------------------------------------------------------------- */

.media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--mist);
}

.media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.media--4x3   { aspect-ratio: 4 / 3; }
.media--3x4   { aspect-ratio: 3 / 4; }
.media--21x9  { aspect-ratio: 21 / 9; }

/* A 3:4 portrait at full phone width is ~500px tall and swallows the screen.
   Crop it rather than let it push the copy off the fold. */
@media (max-width: 55.9375rem) {
  .media--3x4 { aspect-ratio: 4 / 3; }
  .media--21x9 { aspect-ratio: 3 / 2; }
}

/* Photo placeholder. Deliberately styled, not broken-looking, so the layout
   reads true at the correct aspect ratio before real photography lands.
   Every one of these must be replaced before launch — grep for "ph". */
.ph {
  display: grid;
  place-content: center;
  gap: var(--s-3);
  padding: var(--s-6);
  text-align: center;
  background:
    linear-gradient(150deg, rgba(167, 195, 176, 0.75), rgba(221, 232, 225, 0.55) 62%),
    var(--stone);
  color: var(--ink-muted);
}

.ph::before {
  content: '';
  justify-self: center;
  width: 40px;
  height: 40px;
  border: 2px solid var(--forest);
  border-radius: 50%;
  opacity: 0.45;
}/* Inside a photo tile the label is white over a scrim, so that placeholder
   stays dark — it is standing in for a photograph, not for a panel. */

.ph span {
  font-family: var(--font-body);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   7b. Template components
   Two-tone headings, photo tiles, the repeated CTA pair, dashed process
   cards, the reasons grid, quotes, photo bands and the FAQ.
   -------------------------------------------------------------------------- */

/* Two-tone heading. The template opens each heading with its accent colour and
   finishes in the dark — it does the job an eyebrow label would, without the
   badge. */
.h-accent { color: var(--forest); }
.section--forest .h-accent { color: var(--mist); }

.section-head--center {
  margin-inline: auto;
  text-align: center;
}/* The CTA pair that repeats under every section: solid primary, outlined phone *//* --- Photo service tiles --- *//* Dark scrim so the label stays legible whatever the photograph does */

/* --- Numbered process cards, dashed border alternating forest/sage --- */
.procs {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
  list-style: none;
  padding: 0;
  margin: 0;
}

@media (min-width: 40rem) { .procs { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 66rem) { .procs { grid-template-columns: repeat(5, 1fr); } }

.proc {
  display: flex;
  flex-direction: column;
  padding: var(--s-7) var(--s-6) var(--s-6);
  background: var(--stone);
}

.proc h3 {
  font-size: var(--t-h3);
  margin-bottom: var(--s-3);
}

.proc p {
  font-size: var(--t-body);
  color: var(--ink-muted);
}

/* --- Reasons grid: label left, mark in the top-right corner --- */
.reasons {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
  list-style: none;
  padding: 0;
  margin: 0;
}

@media (min-width: 44rem) { .reasons { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .reasons { grid-template-columns: repeat(3, 1fr); } }

.reason {
  position: relative;
  padding: var(--s-6);
  padding-right: var(--s-8);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.reason__icon {
  width: 54px;
  height: 54px;
  margin-bottom: var(--s-5);
  color: var(--forest);
}

.reason h3 {
  font-size: var(--t-h3);
  margin-bottom: var(--s-3);
  max-width: 18ch;
}

.reason p {
  font-size: var(--t-body);
  color: var(--ink-muted);
}/* The template hangs a coloured square off the top-right of each card *//* --- Client quotes --- *//* --- Full-width photo CTA band --- */

/* --- FAQ accordion --- */
.faq {
  max-width: 52rem;
  margin-inline: auto;
  border-radius: var(--radius);
  overflow: hidden;
}

.faq details {
  background: var(--forest);
  border-bottom: 1px solid var(--rule-dark);
}

.faq details:last-child { border-bottom: 0; }

.faq summary {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  cursor: pointer;
  list-style: none;
  color: var(--white);
  font-weight: 500;
}

.faq summary::-webkit-details-marker { display: none; }

/* Caret rotates on open — the only state change, no height animation */
.faq summary::before {
  content: '';
  flex: none;
  width: 0;
  height: 0;
  border-left: 6px solid var(--mist);
  border-block: 5px solid transparent;
  transition: transform 0.2s var(--ease);
}

.faq details[open] summary::before { transform: rotate(90deg); }

.faq summary:hover { background: var(--forest-dark); }

.faq .faq__answer {
  padding: 0 var(--s-5) var(--s-5) calc(var(--s-5) + var(--s-3) + 6px);
  color: var(--mist);
  font-size: var(--t-body);
}

.faq .faq__answer a { color: var(--mist); }


/* --- Symptom cards: the reader diagnoses herself --------------------------- */
.symptoms {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
  list-style: none;
  padding: 0;
  margin: 0;
}

@media (min-width: 44rem) { .symptoms { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 66rem) { .symptoms { grid-template-columns: repeat(3, 1fr); } }

.symptom {
  padding: var(--s-7);
  background: var(--white);
  border: 1px solid var(--rule);
}

.symptom__icon {
  width: 40px;
  height: 40px;
  margin-bottom: var(--s-4);
  color: var(--forest);
}

.symptom h3 {
  font-size: var(--t-h3);
  margin-bottom: var(--s-3);
}

.symptom p {
  font-size: var(--t-body);
  color: var(--ink-muted);
}

/* --- Getting started: three square cards ---------------------------------- */
.starts {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: start;
}

@media (min-width: 52rem) { .starts { grid-template-columns: repeat(3, 1fr); } }

.start {
  display: flex;
  flex-direction: column;
  padding: var(--s-8) var(--s-7);
  background: var(--white);
  box-shadow: var(--shadow-sm);
}

/* Square, but only where there is room to be square. Forcing a 1:1 box on a
   phone leaves a tall card that is mostly empty. */
@media (min-width: 52rem) {
  .start { aspect-ratio: 1 / 1; justify-content: center; }
}

.start p.start__num,
.proc p.proc__num {
  font-family: var(--font-heading);
  font-size: 2.25rem;
  font-weight: 700;
  line-height: 1;
  color: var(--forest);
  margin-bottom: var(--s-4);
}

.start h3 {
  font-size: var(--t-h3);
  margin-bottom: var(--s-3);
}

.start p {
  font-size: var(--t-body);
  color: var(--ink-muted);
}

/* --- Grid overrides where the item count is not the component default ------ */
@media (min-width: 66rem) {
  .procs--4 { grid-template-columns: repeat(4, 1fr); }
}

@media (min-width: 44rem) {
  .reasons--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64rem) {
  .reasons--4 { grid-template-columns: repeat(2, 1fr); }
}/* --------------------------------------------------------------------------
   8. Services grid
   -------------------------------------------------------------------------- *//* An icon in a tinted circle is the most common generated-page component
   going. The number does the same job typographically and doesn't need a
   lightbulb to stand for "ideas". */

/* --------------------------------------------------------------------------
   9. Split blocks (image beside copy)
   -------------------------------------------------------------------------- */

.split {
  display: grid;
  gap: var(--s-7);
  align-items: center;
  grid-template-columns: 1fr;
}

@media (min-width: 56rem) {
  .split { grid-template-columns: repeat(2, 1fr); gap: var(--s-9); }


  /* Photo on the right, copy on the left */
  .split--reverse .split__media { order: 2; }
}

.split__body h2 { margin-bottom: var(--s-4); }

.split__body p + p { margin-top: var(--s-4); }

.split__body p { color: var(--ink-muted); }

.section--forest .split__body p { color: var(--mist); }

/* Plain list inside split copy. Green ticks on every list is a tell, and a
   thin rule reads calmer against the brand anyway. */
.plainlist {
  margin: var(--s-5) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule);
}

.plainlist li {
  padding: var(--s-3) 0 var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--rule);
  border-left: 2px solid var(--forest);
  font-size: var(--t-small);
}/* --------------------------------------------------------------------------
   10. Process steps
   -------------------------------------------------------------------------- *//* Numbers set as type against a rule, rather than white numerals in green
   circles inside bordered cards. Same information, less template. *//* --------------------------------------------------------------------------
   11. Alternating service detail blocks
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   12. CTA bands
   -------------------------------------------------------------------------- */

.cta-band { text-align: center; }

.cta-band h2 { max-width: 24ch; margin-inline: auto; }

/* The CTA band is used on both the forest band and a light stone section, so
   the paragraph colour cannot be pinned to either. Mist on stone is 1.1:1. */
.cta-band p {
  max-width: 52ch;
  margin: var(--s-4) auto 0;
  color: var(--ink-muted);
}

.section--forest .cta-band p,
.section--forest.cta-band p { color: var(--mist); }

/* --------------------------------------------------------------------------
   13. Contact
   -------------------------------------------------------------------------- */

.contact {
  display: grid;
  gap: var(--s-7);
  grid-template-columns: 1fr;
}

@media (min-width: 56rem) {
  .contact { grid-template-columns: 1.1fr 1fr; gap: var(--s-9); }
}

.contact-list {
  margin: var(--s-6) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--s-5);
}

/* Child combinator, not a descendant selector. The Social row nests its own
   <ul> of marks, and a descendant selector put a divider under each of those
   too — everything except the last one, so two stray rules under the icons. */
.contact-list > li {
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--rule);
}

.contact-list > li:last-child { padding-bottom: 0; border-bottom: 0; }

.contact-list__label {
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: var(--s-1);
}

.contact-list__value {
  font-size: var(--t-h4);
  font-weight: 500;
  line-height: 1.45;
  color: var(--ink);
}

/* No resting underline: the EMAIL label above already says what this is, and a
   rule under a long address is noisy. The affordance comes back on hover and
   focus, so it is still discoverable rather than colour-only. */
.contact-list__value a {
  color: var(--ink);
  text-decoration: none;
  overflow-wrap: anywhere;   /* long email must not overflow on narrow phones */
}

.contact-list__value a:hover,
.contact-list__value a:focus-visible {
  color: var(--forest);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}


/* The prose block below the contact list. Rows inside that list are separated
   by 48px (24 gap + 24 padding), so a 48px margin here read as another row
   rather than a new subject. 64px puts it clearly outside the list. */
.contact-note { margin-top: var(--s-9); }

.contact-note h3 { margin-bottom: var(--s-4); }

.contact-note p {
  color: var(--ink-muted);
  max-width: 60ch;
}

.contact-note p + p { margin-top: var(--s-4); }


/* Card holding the entity details an acquirer and a client both want to see */
.entity-card {
  padding: var(--s-6);
  background: var(--forest);
  color: var(--mist);
  border-radius: var(--radius);
}

.entity-card h3 {
  color: var(--white);
  margin-bottom: var(--s-4);
  font-size: var(--t-h4);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.entity-card dl {
  display: grid;
  gap: var(--s-3);
  margin: 0;
  font-size: var(--t-small);
}

.entity-card dt {
  font-weight: 600;
  color: var(--mist);
}

.entity-card dd {
  margin: var(--s-1) 0 0;
}


/* --------------------------------------------------------------------------
   Offer card: the single deliverables panel, paired with a photograph
   -------------------------------------------------------------------------- */

.offercard {
  padding: var(--s-8) var(--s-7);
  background: var(--white);
  box-shadow: var(--shadow-sm);
}

.offercard h2 { margin-bottom: var(--s-4); }

.offercard__intro {
  font-size: var(--t-body);
  color: var(--ink-muted);
}

/* Ticks appear exactly once on the page. A page where every list has green
   checkmarks reads as generated; one list of concrete deliverables does not. */
.ticks {
  display: grid;
  gap: var(--s-4);
  margin: var(--s-6) 0 0;
  padding: 0;
  list-style: none;
}

.ticks li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: var(--s-3);
  align-items: start;
  font-size: var(--t-body);
  line-height: 1.55;
  color: var(--ink-muted);
}

.ticks strong {
  display: block;
  font-weight: 600;
  color: var(--ink);
}

.ticks svg {
  width: 22px;
  height: 22px;
  margin-top: 1px;
  color: var(--forest);
}

@media (max-width: 55.9375rem) {
  .offercard { padding: var(--s-7) var(--s-6); }
}

/* --------------------------------------------------------------------------
   Contact form
   Lives inside .entity-card, so it sits on forest. Inputs are white with ink
   text; labels are mist (5.0:1 on forest).
   -------------------------------------------------------------------------- */

.formcard__intro {
  margin-bottom: var(--s-6);
  font-size: var(--t-small);
  color: var(--mist);
}

.cform { display: grid; gap: var(--s-5); }

.cform__field { display: grid; gap: var(--s-2); }

.cform__field label {
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--mist);
}

.cform__opt {
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  opacity: 0.75;
}

.cform input,
.cform textarea {
  width: 100%;
  min-height: 48px;
  padding: var(--s-3) var(--s-4);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--ink);
  background: var(--white);
  border: 2px solid transparent;
  border-radius: var(--radius-btn);
}

.cform textarea { min-height: 8rem; resize: vertical; }

.cform input:focus-visible,
.cform textarea:focus-visible {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(216, 200, 161, 0.45);
}

/* Server-side validation failures come back with this attribute set */
.cform input[aria-invalid='true'],
.cform textarea[aria-invalid='true'] { border-color: #C4553F; }

/* The spam trap. Off-screen rather than display:none, because some bots skip
   hidden fields but not positioned ones. */
.cform__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.cform__submit { width: 100%; margin-top: var(--s-2); }

.cform__legal {
  font-size: var(--t-small);
  color: var(--mist);
}

/* --- Submission result banner --------------------------------------------- */
.formnote {
  margin-bottom: var(--s-7);
  padding: var(--s-5) var(--s-6);
  background: var(--mist);
  border-left: 4px solid var(--forest);
  font-size: var(--t-lead);
}

.formnote[data-state='error'] {
  background: #F7E4DF;
  border-left-color: #C4553F;
}

/* --------------------------------------------------------------------------
   14. Footer
   -------------------------------------------------------------------------- */

.footer {
  background: var(--forest);
  color: var(--mist);
  padding-block: var(--section-y-s) 0;
}

.footer__grid {
  display: grid;
  gap: var(--s-7);
  grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
  .footer__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64rem) {
  .footer__grid { grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: var(--s-8); }
}

.footer__about p {
  margin-top: var(--s-5);
  font-size: var(--t-small);
  max-width: 34ch;
}

.footer .footer__contact {
  margin-top: var(--s-5);
  padding-top: var(--s-5);
  border-top: 1px solid var(--rule-dark);
}

/* Contact details in the footer, as the template does */
.footer__contact {
  margin-top: var(--s-5);
  display: grid;
  gap: var(--s-2);
  font-size: var(--t-small);
}

.footer__contact a { border-bottom: 1px solid transparent; }
.footer__contact a:hover { border-bottom-color: var(--mist); text-decoration: none; }

.footer h3 {
  color: var(--white);
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  margin-bottom: var(--s-4);
}

.footer ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--s-3);
  font-size: var(--t-small);
}

/* Scoped to the link lists, not to every anchor in the footer. A bare
   `.footer a` also caught the wordmark, and because text-decoration inherits
   into descendants and cannot be cancelled by a child rule, hovering the logo
   struck a line through LUM(mark)RA and "Projects Co" with no way to undo it
   from .wordmark__name. Same species as the .contact-list li bug. */
.footer li a {
  color: var(--mist);
  text-decoration: none;
  transition: color 0.15s var(--ease);
}

.footer li a:hover { color: var(--white); text-decoration: underline; }

/* The wordmark keeps the footer's light-on-dark colour but never an underline */
.footer .wordmark { color: var(--mist); text-decoration: none; }

.footer__bar {
  margin-top: var(--section-y-s);
  padding-block: var(--s-5);
  border-top: 1px solid var(--rule-dark);
  font-size: var(--t-small);
}

.footer__bar-inner {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  align-items: center;
  text-align: center;
}

@media (min-width: 48rem) {
  .footer__bar-inner { flex-direction: row; justify-content: space-between; text-align: left; }
}

/* --------------------------------------------------------------------------
   14b. Interior page header (About, Contact)
   -------------------------------------------------------------------------- */

/* Deliberately not a hero. Interior pages open with a compact forest band so
   they read as part of the site without competing with the home page. */
.pagehead {
  background: var(--forest);
  color: var(--mist);
  padding-block: var(--section-y-s);
}

.pagehead h1 { color: var(--white); }

.pagehead p {
  max-width: 48ch;
  margin-top: var(--s-4);
  font-size: var(--t-lead);
}

/* Principles list on the About page — a definition list, not a card grid */
.principles {
  margin-top: var(--s-7);
  display: grid;
  gap: 0;
}

.principles > div {
  display: grid;
  gap: var(--s-2);
  padding-block: var(--s-5);
  border-top: 1px solid var(--rule);
}

.principles > div:last-child { border-bottom: 1px solid var(--rule); }

.principles dt {
  font-family: var(--font-heading);
  font-size: var(--t-h4);
  font-weight: 600;
  color: var(--ink);
}

.principles dd {
  margin: 0;
  color: var(--ink-muted);
}

@media (min-width: 48rem) {
  .principles > div {
    grid-template-columns: 15rem 1fr;
    gap: var(--s-6);
    align-items: baseline;
  }
}


/* --- Footer social marks --------------------------------------------------
   Not links yet: there are no accounts. Rendered as plain marks so nothing
   looks clickable when it is not.
   -------------------------------------------------------------------------- */
.contact-list .social {
  display: flex;
  gap: var(--s-4);
  margin-top: var(--s-2);
  padding: 0;
  list-style: none;
}

/* On a light surface the marks take the brand green, not the footer's mist. */
.social--light .social__mark { color: var(--forest); opacity: 1; }

.footer .social {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--s-4);
  margin-top: var(--s-6);
  padding: 0;
  list-style: none;
}

.social__mark {
  display: grid;
  place-content: center;
  width: 24px;
  height: 24px;
  color: var(--mist);
  opacity: 0.85;
}

.social__mark svg { width: 22px; height: 22px; }

/* When these become links, they need a hover and a 44px hit area */
.social a.social__mark {
  width: 44px;
  height: 44px;
  margin: -10px;
  opacity: 1;
  transition: color 0.15s var(--ease);
}

.social a.social__mark:hover { color: var(--white); }

/* --------------------------------------------------------------------------
   15. Legal pages
   -------------------------------------------------------------------------- */

.legal { padding-block: var(--section-y); }

.legal__head { margin-bottom: var(--s-8); }

.legal__updated {
  margin-top: var(--s-3);
  font-size: var(--t-small);
  color: var(--ink-muted);
}

.prose h2 {
  font-size: var(--t-h3);
  margin-top: var(--s-9);
  margin-bottom: var(--s-5);
}

.prose h2:first-child { margin-top: 0; }

.prose h3 {
  font-size: var(--t-h4);
  margin-top: var(--s-6);
  margin-bottom: var(--s-3);
}

.prose p,
.prose ul,
.prose ol { margin-top: var(--s-4); }

.prose ul,
.prose ol { padding-left: var(--s-5); }

.prose li + li { margin-top: var(--s-2); }

.prose a { color: var(--forest); }

/* Numbered legal clauses: the number sits in its own column so the text keeps
   a straight left edge down the page. */
.clause {
  display: grid;
  grid-template-columns: 3.5rem 1fr;
  gap: var(--s-2);
  margin-top: var(--s-4);
}

.clause__n {
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}

.subclauses {
  margin: var(--s-3) 0 0 3.5rem;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--s-3);
}

.subclauses li {
  display: grid;
  grid-template-columns: 3.5rem 1fr;
  gap: var(--s-2);
}

@media (max-width: 34rem) {
  .clause, .subclauses li { grid-template-columns: 2.75rem 1fr; }
  .subclauses { margin-left: 2.75rem; }
}

/* These three declarations used to be inline style attributes. The CSP sets
   style-src 'self' with no 'unsafe-inline', which blocks style *attributes*
   outright, so the browser dropped them and the paragraphs rendered with no
   top margin in full-strength ink. Keep styling in this file; inline style
   attributes do not work on this site. */
.sprite { position: absolute; }

.note-muted {
  margin-top: var(--s-5);
  color: var(--ink-muted);
}


/* --------------------------------------------------------------------------
   16. Error page
   -------------------------------------------------------------------------- */

.error-page {
  display: grid;
  place-content: center;
  min-height: 60vh;
  padding-block: var(--section-y);
  text-align: center;
}

.error-page__code {
  font-family: var(--font-heading);
  font-size: clamp(4rem, 3rem + 5vw, 7rem);
  font-weight: 700;
  line-height: 1;
  color: var(--forest);
}

/* --------------------------------------------------------------------------
   17. Print
   -------------------------------------------------------------------------- */

@media print {
  .nav,
.cta-band,
.btn-row,
.skip-link { display: none !important; }
  body { color: #000; background: #fff; }
  .section { padding-block: 1rem; }
}
