/* ==========================================================================
   Enevate Engineering — main.css

   Design system in the post-war functionalist tradition (Ulm / NPK):
   typography, a strict 12-column grid, hairline rules and whitespace do the
   work. The layout is deliberately image-optional — every section reads
   correctly with zero photographs, and has a defined slot for one when it
   arrives.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Fonts

   Inter and JetBrains Mono, served from assets/fonts/ instead of from
   fonts.googleapis.com. The remote embed disclosed every visitor's IP address
   and user agent to Google on every page before they clicked anything -- a
   German court found that to breach the GDPR in 2022 -- and it was the last
   third-party request the site made outside the booking calendar.

   Both families ship as variable fonts, which is why one file per family
   covers every weight: the three Inter files Google served for 400, 500 and
   600 were byte-identical. font-weight below is each file's real wght axis
   read off its fvar table, not a guess, so any weight in range interpolates
   rather than being synthesised.

   Subsets are the same two Google served -- latin, and latin-ext for the
   accented characters above U+00FF. unicode-range keeps latin-ext unfetched
   unless a page actually uses one of them, which for Dutch and English is
   almost never: e-acute and friends live in the latin block.

   Updating them: refetch from Google's css2 endpoint with a modern browser
   user agent (an old one gets .ttf), keep the latin and latin-ext blocks, and
   check the fvar axis still matches what is declared here.
   -------------------------------------------------------------------------- */

/* Inter latin */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Inter latin-ext */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* JetBrains Mono latin */
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* JetBrains Mono latin-ext */
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Colour — near-monochrome plus a single signal accent */
  --paper:        #ffffff;
  --paper-2:      #f4f4f2;   /* recessed panels */
  --paper-3:      #ebebe8;
  --ink:          #101010;   /* headings, primary text */
  --ink-2:        #3d3d3b;   /* body text */
  --ink-3:        #757572;   /* labels, meta, captions */
  --line:         #d7d7d3;   /* structural hairlines */
  --line-2:       #e9e9e6;   /* secondary hairlines */
  --accent:       #d93b0a;   /* signal orange — 4.6:1 on paper */
  --accent-ink:   #ffffff;
  --focus:        #0b57d0;

  /* Type */
  --sans: "Inter", "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --t-display: clamp(2.75rem, 7.2vw, 6.25rem);
  --t-h2:      clamp(1.875rem, 3.4vw, 3.125rem);
  --t-h3:      clamp(1.375rem, 1.9vw, 1.75rem);
  --t-lede:    clamp(1.125rem, 1.55vw, 1.4375rem);
  --t-body:    1.0625rem;
  --t-small:   0.9375rem;
  --t-label:   0.75rem;

  /* Space — a single 8px-derived scale */
  --s-1: 0.5rem;
  --s-2: 1rem;
  --s-3: 1.5rem;
  --s-4: 2rem;
  --s-5: 3rem;
  --s-6: 4rem;
  --s-7: 5.5rem;
  --s-8: 8rem;

  /* Grid */
  --header-h: 72px;
  --wrap:   1400px;
  --gutter: clamp(1.25rem, 2.2vw, 2rem);
  --pad:    clamp(1.25rem, 4vw, 4rem);

  --section: clamp(3.5rem, 8vw, 7rem); /* vertical rhythm between sections */
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:      #0e0e0d;
    --paper-2:    #171716;
    --paper-3:    #201f1e;
    --ink:        #f3f3f1;
    --ink-2:      #bcbcb8;
    --ink-3:      #8a8a85;
    --line:       #2e2e2b;
    --line-2:     #1f1f1d;
    --accent:     #ff5a1f;
    --accent-ink: #160700;
    --focus:      #7cacff;
  }
}

/* --------------------------------------------------------------------------
   2. Reset & base
   -------------------------------------------------------------------------- */

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

/* The browser's own [hidden] rule lives in the UA stylesheet, so ANY author rule
   setting display beats it -- .label { display: block } would keep a hidden
   element on screen. The booking modal was the scar that taught us this; the
   modal is gone but the rule stays, because booking.js and main.js both drive
   visibility through `el.hidden` and rely on it. Global, so `el.hidden = true`
   can be trusted anywhere. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.6;
  font-feature-settings: "kern" 1, "liga" 1, "cv05" 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  margin: 0;
  color: var(--ink);
  font-weight: 500;
  letter-spacing: -0.022em;
  line-height: 1.08;
  text-wrap: balance;
}

p { margin: 0 0 var(--s-3); max-width: 68ch; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

img, svg, iframe { display: block; max-width: 100%; }

ul, ol { margin: 0; padding: 0; list-style: none; }

hr {
  height: 0;
  margin: 0;
  border: 0;
  border-top: 1px solid var(--line);
}

::selection { background: var(--accent); color: var(--accent-ink); }

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

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: var(--s-2) var(--s-3);
  background: var(--ink);
  color: var(--paper);
}
.skip:focus { left: 0; }

/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */

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

.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
}

.section { padding-block: var(--section); }
.section--tight { padding-block: clamp(2.5rem, 5vw, 4rem); }
.section--ruled { border-top: 1px solid var(--line); }

/* Common column placements on the 12-col grid */
.col-full  { grid-column: 1 / -1; }
.col-head  { grid-column: 1 / 5; }
.col-body  { grid-column: 5 / 13; }
.col-text  { grid-column: 1 / 8; }
.col-aside { grid-column: 9 / 13; }

@media (max-width: 900px) {
  .col-head, .col-body, .col-text, .col-aside { grid-column: 1 / -1; }
  .col-body, .col-aside { margin-top: var(--s-3); }
}

/* --------------------------------------------------------------------------
   4. Type utilities
   -------------------------------------------------------------------------- */

.mono {
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-feature-settings: normal;
}

.label {
  display: block;
  margin-bottom: var(--s-3);
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.label--accent { color: var(--accent); }

.display { font-size: var(--t-display); letter-spacing: -0.035em; line-height: 0.97; }
.h2      { font-size: var(--t-h2); }
.h3      { font-size: var(--t-h3); letter-spacing: -0.015em; }

.lede {
  font-size: var(--t-lede);
  line-height: 1.45;
  color: var(--ink);
  letter-spacing: -0.012em;
  max-width: 46ch;
}

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

/* --------------------------------------------------------------------------
   5. Buttons & links
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.75em;
  padding: 0.95em 1.5em;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--t-small);
  font-weight: 500;
  letter-spacing: 0.005em;
  text-decoration: none;
  cursor: pointer;
  border-radius: 0;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.btn::after { content: "→"; font-family: var(--mono); font-size: 0.95em; }
.btn:hover { background: var(--ink); color: var(--paper); }

.btn--accent {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.btn--accent:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }

.btn--lg { padding: 1.15em 1.9em; font-size: 1rem; }

.btn--onaccent {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
  color: var(--accent);
}
.btn--onaccent:hover { background: transparent; color: var(--accent-ink); border-color: var(--accent-ink); }

/* Underlined text link with an animated rule */
.tlink {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5em;
  color: var(--ink);
  text-decoration: none;
  padding-bottom: 2px;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 100% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size .22s ease;
}
.tlink::after { content: "→"; font-family: var(--mono); font-size: 0.85em; color: var(--accent); }
.tlink:hover { background-size: 0% 1px; }

/* --------------------------------------------------------------------------
   6. Header / navigation
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}

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

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--ink);
  flex-shrink: 0;
}
.wordmark__name {
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.045em;
  line-height: 1;
}
.wordmark__rule {
  width: 1px;
  height: 18px;
  background: var(--accent);
}
.wordmark__kind {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  line-height: 1;
  padding-top: 2px;
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 2rem);
  margin-left: auto;
}
/*
  :not(.btn) on every one of these, because the Book button is also an <a>
  inside .nav -- and `.nav a` (0,1,1) outranks `.btn--accent` (0,1,0), so an
  unscoped rule here silently repaints the button rather than the links.

  It had, in both palettes. The button took --ink-2 on --accent: 2.37:1 on
  paper, which is what "black text on the red button" was, and 1.64:1 in the
  dark palette. Worse on hover, where `.nav a:hover` set the text to --ink
  while `.btn--accent:hover` set the background to --ink -- the same colour
  on both halves, so the label went to 1.00:1 and vanished into its own
  button. All of it invisible to `.btn--accent`, which was being outranked
  rather than misdefined: the palette is fine, and was not the bug.

  Two narrower patches for the same bleed were already here and stay, because
  both are wanted for their own sake: `.site-header .btn` (0,2,0) restores the
  padding this rule was overriding, and `.nav .btn` centres it in the mobile
  sheet. Anything added to `.nav a` from now on wants the same guard.
*/
.nav a:not(.btn) {
  font-size: var(--t-small);
  text-decoration: none;
  color: var(--ink-2);
  padding: 0.35em 0;
  border-bottom: 1px solid transparent;
  transition: color .16s ease, border-color .16s ease;
}
.nav a:not(.btn):hover { color: var(--ink); border-bottom-color: var(--line); }
.nav a:not(.btn)[aria-current="page"] { color: var(--ink); border-bottom-color: var(--accent); }

.site-header .btn { padding: 0.7em 1.1em; }

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
}
.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  display: block;
  width: 22px;
  height: 1px;
  background: currentColor;
  transition: transform .2s ease, opacity .2s ease;
}
.nav-toggle span { margin-inline: auto; position: relative; }
.nav-toggle span::before { content: ""; position: absolute; top: -6px; }
.nav-toggle span::after  { content: ""; position: absolute; top: 6px; }
.nav-toggle[aria-expanded="true"] span { background: transparent; }
.nav-toggle[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span::after  { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 860px) {
  .nav-toggle { display: block; }
  .nav {
    position: fixed;
    inset: var(--header-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--s-2) var(--pad) var(--s-4);
    background: var(--paper);
    border-bottom: 1px solid var(--line);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .18s ease, transform .18s ease, visibility .18s;
  }
  .nav[data-open="true"] { opacity: 1; visibility: visible; transform: none; }
  .nav a:not(.btn) {
    padding: var(--s-2) 0;
    font-size: 1.125rem;
    border-bottom: 1px solid var(--line-2);
  }
  .nav .btn { margin-top: var(--s-3); justify-content: center; }
}

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */

/*
  The hero owns the first screen: nothing from the following section should
  be visible on landing, at any window size.

  svh, not vh: on mobile, 100vh is the viewport with the browser chrome
  HIDDEN, which is taller than what you actually see on arrival, so the next
  section would peek in under the fold. svh is the chrome-visible height,
  which is the state a page loads in. dvh is wrong here too -- it would
  resize the hero as the chrome slides away mid-scroll.

  min-height, not height: if the copy ever outgrows a short window it must
  push the page taller rather than overflow behind the next section.
*/
.hero {
  display: grid;
  align-content: center;
  min-height: calc(100vh - var(--header-h));   /* fallback */
  min-height: calc(100svh - var(--header-h));
  padding-block: clamp(2.5rem, 5vw, 4rem);
}

.hero__title { grid-column: 1 / 11; margin-bottom: var(--s-5); }
.hero__lede  { grid-column: 1 / 6; }
.hero__cta   { grid-column: 7 / 13; align-self: end; }

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
}

@media (max-width: 900px) {
  .hero__title, .hero__lede, .hero__cta { grid-column: 1 / -1; }
  .hero__cta { margin-top: var(--s-4); }
}

/* --------------------------------------------------------------------------
   8. Index rows — the core content component
   -------------------------------------------------------------------------- */

.rows { border-bottom: 1px solid var(--line); }

.row {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
  border-top: 1px solid var(--line);
}
.row__no    { grid-column: 1 / 2; padding-top: 0.45rem; }
.row__no .mono { color: var(--accent); }
.row__head  { grid-column: 2 / 6; }
.row__body  { grid-column: 7 / 13; }

.row__title { font-size: var(--t-h3); letter-spacing: -0.018em; }
.row__lede  { margin: 0.4rem 0 0; color: var(--ink-3); font-size: var(--t-small); max-width: 30ch; }

/* Rows that link somewhere get a hover wash */
a.row { text-decoration: none; transition: background-color .18s ease; }
a.row:hover { background: var(--paper-2); }
a.row:hover .row__title { color: var(--accent); }

@media (max-width: 900px) {
  .row__no   { grid-column: 1 / -1; padding-top: 0; margin-bottom: var(--s-1); }
  .row__head { grid-column: 1 / -1; }
  .row__body { grid-column: 1 / -1; margin-top: var(--s-2); }
}

/* Capability lists */
.caps {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--gutter);
  margin-top: var(--s-3);
  border-top: 1px solid var(--line-2);
}
.caps li {
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--line-2);
  font-size: var(--t-small);
  color: var(--ink-2);
}
@media (max-width: 620px) { .caps { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------------------
   9. Cards, panels, image slots
   -------------------------------------------------------------------------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: var(--gutter);
}

.card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-4);
  border: 1px solid var(--line);
  text-decoration: none;
  background: var(--paper);
  transition: border-color .18s ease, background-color .18s ease;
}
.card:hover { border-color: var(--ink); background: var(--paper-2); }
.card__no { color: var(--accent); }
.card h3 { font-size: var(--t-h3); }
.card p { font-size: var(--t-small); }

.panel {
  padding: clamp(1.5rem, 3vw, var(--s-5));
  background: var(--paper-2);
  border: 1px solid var(--line);
}

/* Checklist used for the consultation promise */
.checks li {
  position: relative;
  padding: 0.65rem 0 0.65rem 1.75rem;
  border-bottom: 1px solid var(--line-2);
  font-size: var(--t-small);
}
.checks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.15rem;
  width: 10px;
  height: 1px;
  background: var(--accent);
}
.checks li:last-child { border-bottom: 0; }

/*
  Image slot — a deliberate, labelled placeholder. Drop a real photograph in
  by replacing the whole .imgslot element with <img class="fig" ...>.
*/
.imgslot {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  background:
    repeating-linear-gradient(
      -45deg,
      transparent 0 9px,
      var(--line-2) 9px 10px
    );
  border: 1px solid var(--line);
}
.imgslot span {
  padding: 0.4rem 0.7rem;
  background: var(--paper);
  border: 1px solid var(--line);
}
.imgslot--wide { aspect-ratio: 16 / 9; }
.imgslot--tall { aspect-ratio: 3 / 4; }

.fig {
  display: block;
  width: 100%;
  /* height:auto is required — the width/height attributes on <img> are
     presentational hints, and an explicit height would beat aspect-ratio. */
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--line);
  background: var(--paper-2);
}
.fig--wide { aspect-ratio: 16 / 9; }
.fig--tall { aspect-ratio: 3 / 4; }
.fig--free { aspect-ratio: auto; }

figure { margin: 0; }
figcaption { margin-top: var(--s-2); font-size: var(--t-label); font-family: var(--mono); color: var(--ink-3); letter-spacing: 0.05em; }

/* --------------------------------------------------------------------------
   10. Process / phases
   -------------------------------------------------------------------------- */

.phase { align-items: start; }
.phase__no { grid-column: 1 / 2; }
.phase__no .mono { color: var(--accent); }
.phase__title { grid-column: 2 / 6; }
.phase__body { grid-column: 7 / 13; }

@media (max-width: 900px) {
  .phase__no, .phase__title, .phase__body { grid-column: 1 / -1; }
  .phase__body { margin-top: var(--s-2); }
}

/* --------------------------------------------------------------------------
   11. CTA band — the primary conversion surface
   -------------------------------------------------------------------------- */

.cta-band {
  background: var(--accent);
  color: var(--accent-ink);
}
.cta-band h2 { color: var(--accent-ink); }
.cta-band p  { color: color-mix(in srgb, var(--accent-ink) 82%, transparent); }
.cta-band .label { color: color-mix(in srgb, var(--accent-ink) 72%, transparent); }
.cta-band__inner { padding-block: clamp(3rem, 7vw, 5.5rem); }
.cta-band__text { grid-column: 1 / 8; }
.cta-band__side { grid-column: 9 / 13; align-self: end; }
.cta-band .checks li { border-bottom-color: color-mix(in srgb, var(--accent-ink) 25%, transparent); color: var(--accent-ink); }
.cta-band .checks li::before { background: var(--accent-ink); }

@media (max-width: 900px) {
  .cta-band__text, .cta-band__side { grid-column: 1 / -1; }
  .cta-band__side { margin-top: var(--s-4); }
}

/* --------------------------------------------------------------------------
   12. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--line);
  padding-block: var(--s-6) var(--s-4);
  font-size: var(--t-small);
}
.site-footer__brand { grid-column: 1 / 5; }
.site-footer__col   { grid-column: span 2; }
.site-footer h4 {
  margin-bottom: var(--s-2);
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 400;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.site-footer li { margin-bottom: 0.5rem; }
.site-footer a { text-decoration: none; color: var(--ink-2); }
.site-footer a:hover { color: var(--accent); }
.site-footer__base {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s-2);
  margin-top: var(--s-6);
  padding-top: var(--s-3);
  border-top: 1px solid var(--line);
}

@media (max-width: 900px) {
  .site-footer__brand { grid-column: 1 / -1; margin-bottom: var(--s-4); }
  .site-footer__col   { grid-column: span 6; margin-bottom: var(--s-3); }
}
@media (max-width: 560px) {
  .site-footer__col { grid-column: 1 / -1; }
}

/* --------------------------------------------------------------------------
   13. Booking: the inline scheduler

   There was a modal here: a dialog that covered the page, with our own
   "Open the scheduler" panel inside it. Every Book button opened it, and its
   one button then opened Google's booking page in a new tab -- so a reader
   met two dialogs to reach one calendar. Book buttons are now plain links to
   contact.html#book, where the calendar actually lives, and the modal and its
   focus trap are gone from main.js with it.
   -------------------------------------------------------------------------- */

/* Shown when no scheduler URL is configured yet */
.setup { padding: clamp(1.5rem, 4vw, var(--s-5)); }
.setup ol { list-style: decimal; padding-left: 1.25rem; margin: var(--s-3) 0; }
.setup li { margin-bottom: 0.6rem; font-size: var(--t-small); }
.setup code {
  font-family: var(--mono);
  font-size: 0.85em;
  padding: 0.15em 0.4em;
  background: var(--paper-2);
  border: 1px solid var(--line);
}

/* Mobile sticky booking bar */
.stickycta {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 55;
  display: none;
  padding: 0.75rem var(--pad) calc(0.75rem + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--line);
  transform: translateY(110%);
  transition: transform .25s ease;
}
.stickycta[data-show="true"] { transform: none; }
.stickycta .btn { width: 100%; justify-content: center; }

@media (max-width: 860px) { .stickycta { display: block; } body { padding-bottom: 0; } }

/* --------------------------------------------------------------------------
   14. Forms
   -------------------------------------------------------------------------- */

.field { margin-bottom: var(--s-3); }
.field label {
  display: block;
  margin-bottom: 0.4rem;
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.field input,
.field textarea,
.field select {
  width: 100%;
  padding: 0.8em 0.9em;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 0;
  color: var(--ink);
  font: inherit;
  font-size: var(--t-small);
}
.field input:focus,
.field textarea:focus,
.field select:focus { border-color: var(--ink); }
.field textarea { min-height: 8rem; resize: vertical; }

/* --------------------------------------------------------------------------
   15. Motion — restrained by design
   -------------------------------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .55s cubic-bezier(.22,.61,.36,1), transform .55s cubic-bezier(.22,.61,.36,1);
}
.reveal[data-seen="true"] { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* --------------------------------------------------------------------------
   16. Interior page headers & long-form discipline blocks
   -------------------------------------------------------------------------- */

.pagehead { padding-block: clamp(3rem, 7vw, 6rem) clamp(2rem, 4vw, 3.5rem); }
.pagehead__title {
  grid-column: 1 / 10;
  font-size: clamp(2.25rem, 5.2vw, 4.5rem);
  letter-spacing: -0.032em;
  line-height: 1.02;
}
.pagehead__lede { grid-column: 1 / 7; margin-top: var(--s-4); }
.pagehead__aside { grid-column: 9 / 13; margin-top: var(--s-4); align-self: end; }

@media (max-width: 900px) {
  .pagehead__title, .pagehead__lede, .pagehead__aside { grid-column: 1 / -1; }
}

/* A .disc block reuses the .row grid with more air around it. */
.disc { padding-block: clamp(2.5rem, 5.5vw, 4.5rem); scroll-margin-top: 90px; }
.disc .row__title { font-size: var(--t-h2); }
.disc .row__lede { font-size: 1.0625rem; color: var(--accent); margin-top: var(--s-2); }
.disc figure { margin-top: var(--s-4); }

/* Two-up definition rows, used for facts/FAQ */
.deflist { border-top: 1px solid var(--line); }
.deflist > div {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  padding-block: var(--s-3);
  border-bottom: 1px solid var(--line-2);
}
.deflist dt { grid-column: 1 / 5; color: var(--ink); font-weight: 500; }
.deflist dd { grid-column: 6 / 13; margin: 0; }
@media (max-width: 900px) {
  .deflist dt, .deflist dd { grid-column: 1 / -1; }
  .deflist dd { margin-top: 0.35rem; }
}

/* --------------------------------------------------------------------------
   17. Booking page & team grid
   -------------------------------------------------------------------------- */

.book { padding-block: clamp(2rem, 4vw, 3.5rem) var(--section); scroll-margin-top: 80px; }
.book__intro { grid-column: 1 / 5; }
.book__embed { grid-column: 5 / 13; }
@media (max-width: 1000px) {
  .book__intro, .book__embed { grid-column: 1 / -1; }
  .book__embed { margin-top: var(--s-4); }
}


/* Work teaser cards — the figure is the whole target. */
.workcard { text-decoration: none; display: block; }
.workcard .imgslot { transition: border-color .18s ease; }
.workcard figcaption { transition: color .18s ease; }
.workcard:hover .imgslot { border-color: var(--ink); }
.workcard:hover figcaption { color: var(--accent); }

/* Four-up card row (approach principles) — avoids a lone orphan card. */
.cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) { .cards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .cards--4 { grid-template-columns: 1fr; } }

.alt {
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
}
.alt .label { margin-bottom: var(--s-2); }

/* --------------------------------------------------------------------------
   18. Google Calendar scheduling button

   Google's script injects its own <button> with inline colour styles, so the
   overrides below need !important. Selectors target the mount rather than
   Google's obfuscated class name, which is not a stable API.
   -------------------------------------------------------------------------- */

/*
  There was a clipped mount here, so pages other than the contact page could
  hold an invisible copy of Google's button and forward their own clicks to
  it. Click-to-load ended that: the visitor has to see and press a button
  before Google is contacted at all, and a button nobody can see cannot be
  pressed. Those pages now link to contact.html#book instead.

  Deleted rather than left dormant, unlike the image rules waiting on the
  work page -- this one cannot come back while consent is a click.
*/

/* The mount on the contact page. Restyled to match .btn--accent, and it
   catches our consent button and Google's replacement alike. */
.gcal-mount { margin-top: var(--s-4); }
.gcal-mount button {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex !important;
  align-items: center;
  padding: 1.15em 1.9em !important;
  border: 1px solid var(--accent) !important;
  border-radius: 0 !important;
  background: var(--accent) !important;
  color: var(--accent-ink) !important;
  font-family: var(--sans) !important;
  font-size: 1rem !important;
  font-weight: 500 !important;
  line-height: 1 !important;
  letter-spacing: 0.005em !important;
  text-transform: none !important;
  box-shadow: none !important;
  cursor: pointer;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}
.gcal-mount button:hover {
  background: var(--ink) !important;
  border-color: var(--ink) !important;
  color: var(--paper) !important;
}
.gcal-mount button:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }

/*
  Two controls in the mount, one shown. Google's overlay is a fixed-width panel
  inside Google's own frame, so it cannot be restyled from here at all, and
  below this breakpoint it is too narrow to use -- so the narrow control leaves
  for Google's own booking page instead of embedding it.

  CSS picks the control rather than JavaScript: a resize then switches
  instantly with no listener to keep in step, and display:none takes the other
  one out of the tab order and the accessibility tree, so a keyboard or screen
  reader user never meets two booking controls. main.js reads back whichever
  one is rendered, via offsetParent.

  900px is the site's own breakpoint -- where the grid collapses to one column
  and the nav becomes a sheet -- rather than a number invented for Google.

  inline-flex, not block: that is what .btn uses.

  !important on the consent button alone, and not for emphasis: the rule above
  sets `display: inline-flex !important` on every button in this mount, to beat
  the inline styles Google's script arrives with. A plain `display: none` here
  loses to it and shows both controls at once -- measured, at 500px wide. The
  link needs no such thing, being an <a> that rule never matches.
*/
.gcal-mount [data-gcal-newtab] { display: none; }

@media (max-width: 900px) {
  .gcal-mount [data-gcal-consent] { display: none !important; }
  .gcal-mount [data-gcal-newtab]  { display: inline-flex; }
}

/* --------------------------------------------------------------------------
   19. Pooled scheduler

   The widget booking.js renders when bookingMode is "pooled": days, then
   times, then a short form. Everything is a real <button> so the keyboard and
   a screen reader get the same thing the mouse does; selection is carried on
   aria-pressed, which doubles as the styling hook.
   -------------------------------------------------------------------------- */

/* The pooled markup is hidden until main.js confirms the mode, so a visitor
   with JavaScript off sees the Google block (the shipped default) rather than
   both blocks or neither. main.js clears this inline. */
[data-mode="pooled"] { display: none; }

/* The site header is sticky, so a plain scroll-to-top would tuck the panel's
   first line underneath it. */
.book__embed .panel { scroll-margin-top: calc(var(--header-h) + var(--s-3)); }

.booker { margin-top: var(--s-4); }

.booker__step + .booker__step { margin-top: var(--s-5); }
.booker__step > .label { margin-bottom: var(--s-2); }

.booker__status {
  margin: 0 0 var(--s-3);
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.booker__status[data-kind="warn"] {
  color: var(--accent);
  text-transform: none;
  font-family: var(--sans);
  font-size: var(--t-small);
  letter-spacing: 0;
}

/* -- days ------------------------------------------------------------------

   A wrapping grid rather than a horizontal scroll rail: the whole bookable
   horizon is legible at once, and nothing is hidden past a clipped edge.

   Cell separation is a border on each cell, with the container supplying only
   the top and left. The obvious alternative -- a 1px grid gap over a coloured
   container background -- paints leftover background as phantom cells wherever
   the last row does not fill, which reads as a rendering fault.
   -------------------------------------------------------------------------- */

.booker__days,
.booker__times {
  display: grid;
  border-top: 1px solid var(--line);
  border-left: 1px solid var(--line);
  background: transparent;   /* unfilled cells read as the panel, not a white box */
}

/* Wide enough for "Wed 16 Sep" on one line -- a wrapped label makes the row
   ragged and costs more space than the extra width does. */
.booker__days { grid-template-columns: repeat(auto-fill, minmax(8.75rem, 1fr)); }

.booker__day {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.9rem 1.1rem;
  border: 0;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink-2);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease;
}
/* --paper-3, not --paper-2: inside a .panel, --paper-2 is the surrounding
   colour, so hovering to it would read as the cell disappearing. */
.booker__day:hover { background: var(--paper-3); }
.booker__day[aria-pressed="true"] {
  background: var(--ink);
  color: var(--paper);
}
.booker__day:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

.booker__day-label {
  font-family: var(--mono);
  font-size: var(--t-small);
  letter-spacing: 0.02em;
}
.booker__day-count {
  font-family: var(--mono);
  font-size: var(--t-label);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.booker__day[aria-pressed="true"] .booker__day-count { color: var(--paper-3); }

/* -- times: a plain grid, sized so a thumb can hit one -------------------- */

.booker__zone { margin: 0 0 var(--s-2); }

.booker__times { grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr)); }

.booker__time {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.9rem 0.5rem;
  border: 0;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--t-small);
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease;
}
.booker__time:hover { background: var(--paper-3); }
.booker__time[aria-pressed="true"] {
  background: var(--accent);
  color: var(--accent-ink);
}
.booker__time:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

.booker__time-alt { font-size: var(--t-label); color: var(--ink-3); }
.booker__time[aria-pressed="true"] .booker__time-alt { color: var(--accent-ink); opacity: 0.8; }

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

.booker__chosen {
  margin: 0 0 var(--s-3);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.65rem;
}
.booker__chosen strong { font-family: var(--mono); letter-spacing: -0.01em; }

.field__req { color: var(--accent); }
.field__hint {
  display: block;
  margin-bottom: 0.45rem;
  font-size: var(--t-small);
  color: var(--ink-3);
}

.booker__note { margin-top: var(--s-3); }

/* The honeypot. Positioned off-screen rather than display:none -- a bot that
   skips hidden inputs would sail straight past a display:none trap. */
.booker__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* -- confirmation --------------------------------------------------------- */

.booker__when {
  margin: 0 0 var(--s-3);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.65rem;
}
.booker__when strong {
  font-family: var(--mono);
  font-size: var(--t-h3);
  letter-spacing: -0.02em;
}

@media (prefers-reduced-motion: reduce) {
  .booker__day,
  .booker__time { transition: none; }
}
