@charset "UTF-8";
/* ==========================================================================
   Upadhyay Suraj & Co. — main stylesheet

   ⚠️  THIS MUST BE THE ONLY RENDER-BLOCKING STYLESHEET, AND IT MUST BE FIRST.
   Do not add an external blocking sheet (fonts.googleapis.com, any CDN) above it.
   The reference site documented a recurring unstyled-flash regression traced to
   exactly that: an external blocking sheet that stalls or errors releases Chrome's
   paint-block early and paints raw HTML for a frame. A same-origin, immutably
   cached sheet cannot. See docs/kirtanepandit-teardown.md §5.

   Hand-written rather than Tailwind: a CDN build would be that external blocking
   sheet, and a compiled build would add a Node toolchain to a flat-PHP project for
   one brochure site. Custom properties give us the token layer we need.

   Contents
     1. Tokens
     2. Reset and base
     3. Typography
     4. Layout primitives
     5. Components — buttons, tiles, cards
     6. Chrome — utility strip, nav, mega panel, drawer, footer
     7. Sections — hero, practice areas, method, entities, insights, offices
     8. Forms
     9. Utilities
    10. Responsive
    11. Reduced motion and print
   ========================================================================== */

/* ── 0. Fonts ───────────────────────────────────────────────────────────────
   Self-hosted variable woff2. Two files, 180 KB total, covering every weight.

   ⚠️ NEVER replace these with a fonts.googleapis.com <link>. That is an external
   render-blocking stylesheet, and it is the documented cause of the unstyled-flash
   regression on the reference site (docs/kirtanepandit-teardown.md §5).

   Newsreader is the display face. The choice is deliberate: a warm editorial serif
   reads as established and considered, which is the register a chartered accountancy
   firm actually wants. A geometric sans — the obvious match to the letterhead
   wordmark — reads as a tech startup, and every competitor site in this market
   already uses one. Since ICAI bars the monogram anyway, the site's typographic
   identity is ours to set, so we set it to something with gravitas.
   ------------------------------------------------------------------------- */
@font-face {
  font-family: "Newsreader";
  src: url("../fonts/newsreader-var-latin.woff2") format("woff2-variations");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("../fonts/inter-var-latin.woff2") format("woff2-variations");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* ── 1. Tokens ──────────────────────────────────────────────────────────── */
:root {
  /* Brand — sampled from the supplied logo file, not estimated.
     See docs/client-brief.md §3 for the sampling method and contrast measurements. */
  --green:        #243F2E;   /* primary   — 10.1:1 on cream, AAA */
  --green-deep:   #244530;   /* tiles     —  9.9:1 on cream, AAA */
  --terracotta:   #7F4B36;   /* accent    —  6.3:1 on cream, AA  */
  --cream:        #F4F1EC;   /* page bg */
  --paper:        #FBFAF6;   /* card bg */
  --sage:         #5F6C62;   /* muted text — 5.0:1 on cream, AA.
                                Little headroom above the 4.5:1 floor: do not lighten. */

  /* Derived */
  --green-soft:   #2E5240;
  --green-wash:   #EAE9E2;
  --terra-wash:   #F2E7E1;
  --ink:          #1A1D1A;
  --rule:         rgba(36, 63, 46, 0.14);
  --rule-strong:  rgba(36, 63, 46, 0.28);
  --scrim:        rgba(36, 63, 46, 0.62);   /* hero: measured to hold cream text ≥4.5:1 */
  --shadow-card:  0 1px 2px rgba(36, 63, 46, 0.05), 0 8px 24px rgba(36, 63, 46, 0.06);
  --shadow-nav:   0 1px 2px rgba(36, 63, 46, 0.06), 0 10px 30px rgba(36, 63, 46, 0.08);

  --font-display: "Newsreader", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-body:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* A wider scale than the first pass. Editorial layouts earn their authority from
     the jump between display and body sizes, not from decoration. */
  --step--2: clamp(0.72rem, 0.71rem + 0.06vw, 0.76rem);
  --step--1: clamp(0.83rem, 0.81rem + 0.10vw, 0.89rem);
  --step-0:  clamp(1.00rem, 0.97rem + 0.16vw, 1.10rem);
  --step-1:  clamp(1.20rem, 1.13rem + 0.36vw, 1.42rem);
  --step-2:  clamp(1.44rem, 1.30rem + 0.71vw, 1.85rem);
  --step-3:  clamp(1.73rem, 1.48rem + 1.24vw, 2.40rem);
  --step-4:  clamp(2.07rem, 1.66rem + 2.06vw, 3.11rem);
  --step-5:  clamp(2.49rem, 1.82rem + 3.34vw, 4.05rem);
  --step-6:  clamp(2.99rem, 1.92rem + 5.32vw, 5.26rem);

  /* Space */
  --sp-1: 0.25rem;  --sp-2: 0.5rem;   --sp-3: 0.75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;   --sp-6: 2rem;     --sp-7: 3rem;     --sp-8: 4rem;
  --sp-9: 6rem;     --sp-10: 8rem;

  /* Shape — the letterhead's rounded tile is the brand cue that survives the
     monogram bar (docs/client-brief.md §3). --radius-tile is that geometry. */
  --radius-tile: 18px;
  --radius-card: 14px;
  --radius-pill: 100px;
  --radius-sm:   8px;

  --measure: 66ch;
  --container: 1240px;
  --container-narrow: 780px;

  --ease-butter: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 160ms;
  --dur:      240ms;

  --nav-h: 76px;
}

/* ── 2. Reset and base ──────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + var(--sp-5));
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }

:where(a) { color: var(--green); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
:where(a):hover { color: var(--terracotta); }

/* Visible focus everywhere. Never remove without an equivalent replacement. */
:focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--green); color: var(--cream); }

.skip-link {
  position: absolute; left: var(--sp-4); top: var(--sp-4);
  z-index: 200;
  padding: var(--sp-3) var(--sp-5);
  background: var(--green); color: var(--cream);
  border-radius: var(--radius-sm);
  transform: translateY(-200%);
  transition: transform var(--dur) var(--ease-butter);
}
.skip-link:focus { transform: translateY(0); color: var(--cream); }

/* ── 3. Typography ──────────────────────────────────────────────────────── */
h1, h2, h3, h4 {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.014em;
  color: var(--green);
  text-wrap: balance;
  /* Optical sizing is the reason for choosing a variable serif: at display sizes the
     letterforms thin and open up, at body sizes they thicken for legibility. */
  font-optical-sizing: auto;
}
/* Tracking is optical, so it scales with size rather than being one value for h1-h4.
   A serif at 65px needs the counters closed up; the same tracking at 20px makes the word
   look cramped. Line-height moves the other way — tighter as the type gets larger. */
h1 { font-size: var(--step-5); line-height: 1.04; letter-spacing: -0.022em; }
h2 { font-size: var(--step-4); line-height: 1.07; letter-spacing: -0.018em; }
h3 { font-size: var(--step-2); line-height: 1.18; letter-spacing: -0.008em; font-weight: 500; }
h4 { font-size: var(--step-1); line-height: 1.25; letter-spacing: 0;        font-weight: 600; }

/* Headings that follow a paragraph need air above them; the first one in a block does not.
   Cheaper and more reliable than adding a class at every call site. */
:is(h2, h3, h4):not(:first-child) { margin-top: var(--sp-6); }
.section-head :is(h1, h2, h3) { margin-top: 0; }

/* Display heading — the hero and section openers. */
.display {
  font-family: var(--font-display);
  font-size: var(--step-6);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.022em;
}

/* An italic phrase inside a serif heading. Used sparingly — once per page at most —
   to give the eye a landing point, the way a magazine deck does. */
.em { font-style: italic; font-weight: 400; color: var(--terracotta); }
.section--green .em { color: #D8A38C; }
.hero .em { color: #E3B7A3; }

p { margin: 0 0 var(--sp-4); max-width: var(--measure); line-height: 1.65; text-wrap: pretty; }

/* Numerals: tabular in tables and figures so columns line up, proportional in prose. */
table.data, .tnum, .counter, .pairs dd { font-variant-numeric: tabular-nums; }
.prose, p, li { font-variant-numeric: proportional-nums; }

/* Stop a stray single word ending a paragraph or heading where it can be avoided. */
h1, h2, h3, h4, .lede { text-wrap: balance; }
p:last-child { margin-bottom: 0; }

.kicker {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
  font-family: var(--font-body);
  font-size: var(--step--2);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sage);
}
/* Hairline that grows out of the kicker. Scales from 0 when revealed. */
.kicker::after {
  content: "";
  flex: 1;
  height: 1px;
  max-width: 5rem;
  background: currentColor;
  opacity: 0.4;
  transform-origin: left center;
}

.lede {
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--green-soft);
  max-width: 58ch;
}
.muted { color: var(--sage); }
.small { font-size: var(--step--1); }
.tnum { font-variant-numeric: tabular-nums; }

/* Section counter — 01 / 06. Editorial device, and it orients the reader. */
.counter {
  font-family: var(--font-body);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--sage);
  font-variant-numeric: tabular-nums;
}
.counter b { color: var(--green); font-weight: 600; }

/* ── 4. Layout primitives ───────────────────────────────────────────────── */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--sp-5);
}
.container--narrow { max-width: var(--container-narrow); }

.section { padding-block: var(--sp-9); }
.section--tight { padding-block: var(--sp-7); }
.section--paper { background: var(--paper); }
.section--green { background: var(--green); color: var(--cream); }
.section--green :is(h1, h2, h3, h4) { color: var(--cream); }
.section--green .kicker { color: rgba(244, 241, 236, 0.72); }
.section--green .lede { color: rgba(244, 241, 236, 0.88); }
/* ⚠️ `:not(.btn)` is load-bearing — do not simplify to `.section--green a`.
   A button carries its own background AND its own foreground. `.btn--onDark` is cream
   background with green text, but `.section--green a` (0,1,1) outranks `.btn--onDark`
   (0,1,0), so inside a green section the label was repainted cream ON the cream button:
   measured 1:1 on /services, /services/{slug} and /about/team. Buttons opt out here. */
.section--green a:not(.btn) { color: var(--cream); }

/* Belt and braces: state the on-dark button's own colours at a specificity that wins
   regardless of what a section rule tries to impose. */
.section--green .btn--onDark { color: var(--green); }
.section--green .btn--primary { color: var(--cream); }

.rule { height: 1px; margin: 0; border: 0; background: var(--rule); }

.section-head { max-width: 60ch; margin-bottom: var(--sp-7); }

.grid { display: grid; gap: var(--sp-5); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
.split { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--sp-8); align-items: start; }

/* ── 5. Components ──────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  padding: 0.78em 1.5em;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  /* Colour and border transitions only — never transform. A scale on hover shifts
     layout and is one of the tells of an unprofessional build. */
  transition: background-color var(--dur) var(--ease-butter),
              border-color var(--dur) var(--ease-butter),
              color var(--dur) var(--ease-butter);
}
.btn--primary { background: var(--green); color: var(--cream); }
.btn--primary:hover { background: var(--green-soft); color: var(--cream); }
.btn--ghost { border-color: var(--rule-strong); color: var(--green); background: transparent; }
.btn--ghost:hover { background: var(--green-wash); color: var(--green); border-color: var(--green); }
.btn--onDark { background: var(--cream); color: var(--green); }
.btn--onDark:hover { background: #fff; color: var(--green); }
.btn__arrow { width: 1em; height: 1em; flex: none; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center; }

/* The tile — letterhead geometry as a layout element, never spelling the initials. */
.tile {
  display: grid; place-items: center;
  width: 2.75rem; aspect-ratio: 1;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-tile);
  background: var(--paper);
  font-family: var(--font-display);
  font-size: var(--step-0);
  font-weight: 700;
  color: var(--green-deep);
  flex: none;
}
.tile--accent { background: var(--terracotta); border-color: var(--terracotta); color: var(--paper); }

.card {
  display: flex; flex-direction: column;
  padding: var(--sp-6);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-tile);
  box-shadow: var(--shadow-card);
  transition: border-color var(--dur) var(--ease-butter),
              background-color var(--dur) var(--ease-butter);
}
.card h3 { font-size: var(--step-1); margin-bottom: var(--sp-3); }
.card p { font-size: var(--step--1); color: var(--sage); }
.card__foot { margin-top: auto; padding-top: var(--sp-5); }

a.card { text-decoration: none; cursor: pointer; }
a.card:hover { border-color: var(--green); }
a.card:hover h3 { color: var(--terracotta); }

.card--accent { border-color: rgba(127, 75, 54, 0.35); background: var(--terra-wash); }
a.card--accent:hover { border-color: var(--terracotta); }

.card__tile { margin-bottom: var(--sp-5); }

/* ⚠️ A component that owns its background MUST own its foreground.
   `.card` sets `background: var(--paper)` but set no colour, so inside `.section--green`
   — which sets cream text on the section, plus cream on every heading and link — a card
   rendered cream text on a near-white card. Measured 1.08:1 on /resources: the official
   links block was effectively invisible. This is not a one-off; it is a class of bug, so
   the reset is stated on the component rather than patched per section. */
.card { color: var(--ink); }
.card h3 { color: var(--green); }
.section--green .card,
.section--green .card p,
.section--green .card address { color: var(--ink); }
.section--green .card :is(h1, h2, h3, h4) { color: var(--green); }
.section--green .card p { color: var(--sage); }
.section--green .card a,
.section--green .card .link-arrow,
.section--green .card .card__foot { color: var(--terracotta); }
.section--green .card .badge { color: var(--green); }

/* Same class of bug on the terracotta-washed variant. */
.card--accent { color: var(--ink); }
.section--green .card--accent :is(h1, h2, h3, h4) { color: var(--green); }

.link-arrow {
  display: inline-flex; align-items: center; gap: 0.45em;
  font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
  text-decoration: none;
}
.link-arrow svg { width: 0.95em; height: 0.95em; transition: transform var(--dur) var(--ease-butter); }
.link-arrow:hover svg { transform: translateX(3px); }

.badge {
  display: inline-block;
  padding: 0.3em 0.8em;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-pill);
  font-size: var(--step--1);
  color: var(--sage);
}

/* ── 6. Chrome ──────────────────────────────────────────────────────────── */
.utility {
  background: var(--green);
  color: rgba(244, 241, 236, 0.86);
  font-size: var(--step--1);
}
.utility__inner { display: flex; justify-content: space-between; gap: var(--sp-5); align-items: center; min-height: 40px; }
.utility__list { display: flex; gap: var(--sp-5); align-items: center; margin: 0; padding: 0; list-style: none; }
.utility a { color: inherit; text-decoration: none; }
.utility a:hover { color: #fff; text-decoration: underline; }
.utility svg { width: 0.9em; height: 0.9em; opacity: 0.7; }
.utility__item { display: inline-flex; align-items: center; gap: 0.4em; }

/* Floating pill nav — offset from the edges, not flush. */
.nav-wrap { position: sticky; top: 0; z-index: 100; padding: var(--sp-4) 0; transition: padding var(--dur) var(--ease-butter); }
.nav-wrap[data-scrolled="true"] { padding: var(--sp-2) 0; }

/* The nav is a floating pill, so the page scrolls through the gutter either side of it.
   Against a table or a dense block that reads as text colliding with the nav — visible on
   /resources, where calendar rows ran straight through the gap. Once scrolled, lay a
   blurred band behind the whole strip so content passes UNDER something rather than
   through nothing. Sits behind the pill (z-index -1 within the wrap's own stacking
   context) so it never dims the nav itself. */
.nav-wrap::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to bottom,
    rgba(244, 241, 236, 0.92) 0%,
    rgba(244, 241, 236, 0.72) 62%,
    rgba(244, 241, 236, 0) 100%);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-butter);
  pointer-events: none;
}
.nav-wrap[data-scrolled="true"]::before { opacity: 1; }

/* The wrap needs its own stacking context for the -1 above to stay inside it. */
.nav-wrap { isolation: isolate; }

.nav {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-5);
  min-height: var(--nav-h);
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-5);
  background: rgba(251, 250, 246, 0.92);
  backdrop-filter: blur(12px);
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-nav);
}

/* Scroll progress — a hairline of terracotta across the very top of the viewport.
   Driven by Motion's scroll() against scaleX, so it costs one composited transform. */
.progress {
  position: fixed; inset: 0 0 auto 0;
  height: 2px; z-index: 200;
  background: var(--terracotta);
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;
}

/* Brand lock-up.
   With features.brand_mark on, the tile mark leads and the name sits beside it as a
   serif masthead. With it off, the name alone carries the brand — no template change
   required either way. See docs/icai-compliance.md §3. */
.brand {
  display: flex; align-items: center; gap: var(--sp-3);
  text-decoration: none; line-height: 1;
}
.brand__mark { height: 30px; width: auto; flex: none; }
.brand__text { display: flex; flex-direction: column; gap: 3px; }
.brand__name {
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 500;
  letter-spacing: -0.018em;
  color: var(--green);
  white-space: nowrap;
}
.brand__desig {
  font-family: var(--font-body);
  font-size: 0.6rem; font-weight: 500;
  letter-spacing: 0.19em; text-transform: uppercase;
  color: var(--sage);
  white-space: nowrap;
}
.brand:hover .brand__name { color: var(--terracotta); }

.nav__list { display: flex; align-items: center; gap: var(--sp-2); margin: 0; padding: 0; list-style: none; }
.nav__link {
  display: inline-flex; align-items: center; gap: 0.35em;
  padding: 0.6em 0.95em;
  border-radius: var(--radius-pill);
  font-family: var(--font-display); font-size: var(--step--1); font-weight: 600;
  color: var(--green); text-decoration: none;
  background: transparent; border: 0; cursor: pointer;
  transition: background-color var(--dur) var(--ease-butter), color var(--dur) var(--ease-butter);
}
.nav__link:hover { background: var(--green-wash); color: var(--green); }
.nav__link[aria-current="page"] { background: var(--green); color: var(--cream); }
.nav__link[aria-expanded="true"] { background: var(--green-wash); }
.nav__chev { width: 0.7em; height: 0.7em; transition: transform var(--dur) var(--ease-butter); }
.nav__link[aria-expanded="true"] .nav__chev { transform: rotate(180deg); }

.nav__has-panel { position: static; }

/* ── Mega panel ───────────────────────────────────────────────────────────────
   Rebuilt from a 3×2 column grid to a rail + pane.

   The grid version was ragged: six columns of wildly different length (Audit has four
   phase-1 services, Direct Tax has six) left big holes, and the panel grew to 741px
   tall — a white slab dropped over the hero. It was also centred on its trigger, so it
   sat off-axis from the page.

   The rail lists the six practices; hovering or focusing one swaps the pane beside it.
   Height is set by the tallest single practice instead of by two stacked rows, and the
   panel is aligned to the container so it shares the page's axis.
   --------------------------------------------------------------------------- */
.panel {
  position: absolute;
  top: calc(100% + var(--sp-3));
  left: 50%;
  translate: -50% 0;
  width: min(calc(100vw - var(--sp-8)), var(--container));
  padding: var(--sp-6);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-nav);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity var(--dur) var(--ease-butter),
              transform var(--dur) var(--ease-butter),
              visibility var(--dur);
}
.panel[data-open="true"] { opacity: 1; visibility: visible; transform: translateY(0); }

.panel--mega { display: grid; grid-template-columns: minmax(240px, 300px) 1fr; gap: var(--sp-7); }

.megarail { display: grid; gap: 2px; align-content: start; }
.megarail__item {
  display: flex; align-items: baseline; gap: var(--sp-3);
  width: 100%;
  padding: 0.62em 0.75em;
  border: 0; border-radius: var(--radius-sm);
  background: transparent;
  font-family: var(--font-display);
  font-size: var(--step-1); font-weight: 500;
  color: var(--green); text-align: left; text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease-butter), color var(--dur) var(--ease-butter);
}
.megarail__item:hover { background: var(--green-wash); }
.megarail__item[aria-selected="true"] { background: var(--green); color: var(--cream); }
.megarail__num {
  font-family: var(--font-body); font-size: var(--step--2); font-weight: 600;
  letter-spacing: 0.08em; opacity: 0.55; font-variant-numeric: tabular-nums;
}

.megapane { display: none; grid-template-columns: 1fr 1fr; gap: var(--sp-5) var(--sp-6); align-content: start; }
.megapane[data-active="true"] { display: grid; }
.megapane__head { grid-column: 1 / -1; }
.megapane__head p { font-size: var(--step--1); color: var(--sage); max-width: 60ch; margin: 0; }
.megapane__list { margin: 0; padding: 0; list-style: none; display: grid; gap: 1px; align-content: start; }
.megapane__list a {
  display: block; padding: 0.34em 0;
  font-size: var(--step--1); color: var(--green-soft); text-decoration: none;
  border-bottom: 1px solid transparent;
}
.megapane__list a:hover { color: var(--terracotta); border-bottom-color: var(--rule); }
.megapane__foot {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; gap: var(--sp-5); align-items: center;
  padding-top: var(--sp-4); border-top: 1px solid var(--rule);
}
.megapane__note { font-size: var(--step--2); color: var(--sage); margin: 0; }

.panel--links { display: grid; gap: var(--sp-3); width: max-content; max-width: 340px; }
.panel--links a { display: block; text-decoration: none; padding: var(--sp-2) 0; }
.panel--links strong { display: block; font-family: var(--font-display); font-size: var(--step-0); font-weight: 500; color: var(--green); }
.panel--links span { font-size: var(--step--1); color: var(--sage); }
.panel--links a:hover strong { color: var(--terracotta); }

.nav__cta { display: inline-flex; }

/* Mobile drawer — a separate component, not a reflow of the mega panel. */
.drawer {
  position: fixed; inset: 0 0 0 auto; z-index: 150;
  width: min(88vw, 380px);
  padding: var(--sp-6) var(--sp-5) var(--sp-8);
  background: var(--paper);
  border-left: 1px solid var(--rule);
  overflow-y: auto;
  translate: 100% 0;
  transition: translate var(--dur) var(--ease-butter);
}
.drawer[data-open="true"] { translate: 0 0; }
.drawer__head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--sp-6); }
.drawer__group { padding-block: var(--sp-4); border-top: 1px solid var(--rule); }
.drawer__group-title { font-family: var(--font-display); font-size: var(--step--1); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--sage); margin-bottom: var(--sp-3); }
.drawer__list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--sp-1); }
.drawer__list a { display: block; padding: 0.45em 0; font-family: var(--font-display); font-weight: 600; color: var(--green); text-decoration: none; }
.drawer__list a:hover { color: var(--terracotta); }
.drawer__contact { margin-top: var(--sp-6); padding-top: var(--sp-5); border-top: 1px solid var(--rule); font-size: var(--step--1); color: var(--sage); }

.overlay {
  position: fixed; inset: 0; z-index: 140;
  background: rgba(26, 29, 26, 0.4);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease-butter), visibility var(--dur);
}
.overlay[data-open="true"] { opacity: 1; visibility: visible; }

.icon-btn {
  display: grid; place-items: center;
  /* 2.75rem = 44px at a 16px root — the minimum for a reliable touch target. It measured
     2.6rem (42px) before, which is close enough to look right and not close enough to hit. */
  width: 2.75rem; aspect-ratio: 1;
  border: 1px solid var(--rule-strong); border-radius: var(--radius-pill);
  background: transparent; color: var(--green); cursor: pointer;
  transition: background-color var(--dur) var(--ease-butter);
}
.icon-btn:hover { background: var(--green-wash); }
.icon-btn svg { width: 1.15rem; height: 1.15rem; }

/* ⚠️ ORDER MATTERS — DO NOT MOVE ABOVE .icon-btn.
   `.nav__burger` and `.icon-btn` are both single-class selectors, so they tie on
   specificity and the LATER rule wins. Declared before .icon-btn, this `display: none`
   lost to `.icon-btn { display: grid }` and the burger stayed visible on desktop next to
   the Contact button. Same class of bug the reference site documented between Swiper's
   `.swiper-slide` and its own sizing rules — see docs/kirtanepandit-teardown.md §5.
   The 900px query below re-shows it. */
.nav__burger { display: none; }

/* Footer */
.footer { background: var(--green); color: rgba(244, 241, 236, 0.82); padding-block: var(--sp-8) var(--sp-6); }
.footer :is(h2, h3, .footer__brand-name) { color: var(--cream); }
.footer a { color: rgba(244, 241, 236, 0.82); text-decoration: none; }
.footer a:hover { color: #fff; text-decoration: underline; }
.footer__top { display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr)); gap: var(--sp-6); }
.footer__brand-name { font-family: var(--font-display); font-size: var(--step-2); font-weight: 700; letter-spacing: -0.02em; }
.footer__brand-desig { font-size: 0.7rem; letter-spacing: 0.17em; text-transform: uppercase; color: rgba(244, 241, 236, 0.62); margin-bottom: var(--sp-4); }
.footer__col-title { font-family: var(--font-display); font-size: var(--step--1); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(244, 241, 236, 0.62); margin-bottom: var(--sp-4); }
.footer__list { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--sp-2); font-size: var(--step--1); }
.footer__meta { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--sp-4); margin-top: var(--sp-8); padding-top: var(--sp-5); border-top: 1px solid rgba(244, 241, 236, 0.16); font-size: var(--step--1); }
.footer__legal { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin: 0; padding: 0; list-style: none; }
.footer__facts { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-bottom: var(--sp-4); font-size: var(--step--1); color: rgba(244, 241, 236, 0.62); }

/* ── 7. Sections ────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  display: grid; align-items: end;
  min-height: clamp(520px, 76vh, 760px);
  margin: 0 var(--sp-4) var(--sp-8);
  padding: var(--sp-9) 0 var(--sp-8);
  border-radius: var(--radius-card);
  overflow: hidden;
  isolation: isolate;
  /* Designed failure state: if the video never loads, or is deliberately skipped on
     mobile / reduced-motion / save-data, this is what shows. Not a white box. */
  background:
    radial-gradient(120% 90% at 82% 8%, rgba(127, 75, 54, 0.42) 0%, transparent 58%),
    linear-gradient(165deg, var(--green-deep) 0%, var(--green) 46%, #1B3324 100%);
}
/* ⚠️ Compound selector on purpose — do NOT simplify to `.hero__media`.
   `.media` is declared later in this file and sets `position: relative` plus
   `aspect-ratio: 3/2`. Both are single-class selectors, so with equal specificity the
   later one won, the image dropped into flow as a grid item, and page heroes rendered
   1275px tall instead of 414px with a thousand pixels of empty green below the heading.
   Raising specificity here means a template can carry both classes without breaking. */
.hero__media,
.hero .hero__media {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%;
  aspect-ratio: auto;          /* cancels .media's reserved box if both are applied */
  border-radius: 0;
  object-fit: cover;
  scale: 1.07;                 /* headroom so the parallax never exposes an edge */
  will-change: transform;
}

/* ⚠️ REQUIRED, not redundant. `.hero__media` is a <picture>, which is NOT a replaced
   element — `object-fit` on it does nothing at all. Without this rule the inner <img>
   lays out at its own intrinsic size: measured 1284×813 inside a 1393×342 hero, so it
   overflowed the bottom and left a 109px gap down the right-hand side. This was masked
   for a while because the templates also carried `.media`, whose `.media img` rule
   happened to supply the cover. */
.hero__media img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center;
}
.hero__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
/* Two-stop scrim: heavy where the text sits, light at the top so the photograph still
   reads as a photograph. Measured to hold cream text above 4.5:1 against the brightest
   frame of the plate — never rely on the image being dark. */
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to top, rgba(22, 36, 27, 0.90) 0%, rgba(28, 47, 35, 0.62) 44%, rgba(36, 63, 46, 0.28) 100%),
    linear-gradient(102deg, rgba(36, 63, 46, 0.40) 0%, transparent 64%);
}
.hero__content { position: relative; }
.hero__name { font-size: var(--step-6); font-weight: 400; letter-spacing: -0.024em; color: var(--cream); margin-bottom: var(--sp-3); }
.hero__desig { display: block; font-family: var(--font-body); font-size: var(--step--2); font-weight: 500; letter-spacing: 0.22em; text-transform: uppercase; color: rgba(244, 241, 236, 0.74); margin-bottom: var(--sp-6); }
.hero__lede { max-width: 52ch; font-size: var(--step-1); line-height: 1.5; color: rgba(244, 241, 236, 0.93); margin-bottom: var(--sp-6); }
.hero__toggle { position: absolute; right: var(--sp-5); bottom: var(--sp-5); z-index: 2; border-color: rgba(244, 241, 236, 0.4); color: var(--cream); }
.hero__toggle:hover { background: rgba(244, 241, 236, 0.14); }
.hero__credit {
  position: absolute; right: var(--sp-5); top: var(--sp-5); z-index: 2;
  font-size: 0.62rem; letter-spacing: 0.04em;
  color: rgba(244, 241, 236, 0.45);
}
.hero__credit a { color: inherit; text-decoration: none; }
.hero__credit a:hover { color: rgba(244, 241, 236, 0.9); text-decoration: underline; }

/* Interior page hero — same treatment, shorter. */
/* A page hero carries a label, a heading and one line of standfirst — roughly 200–270px
   of content. It does not need the homepage's 76vh stage. Kept as its own scale rather
   than a fraction of the home value so the two can move independently. */
.hero--page { min-height: clamp(300px, 38vh, 400px); padding-block: var(--sp-8) var(--sp-6); }
.hero--page .hero__name { font-size: var(--step-5); }
.hero--page .hero__lede { margin-bottom: 0; }

/* The full hero's scrim is tuned for 684px of height with a long heading over the lower
   third. Reused unchanged on a 342px band it covered almost the whole photograph and
   turned India Gate on /contact into a silhouette, so this variant is lighter.

   MEASURED, not assumed — sampled from a render of /contact with the hero text hidden,
   taking the BRIGHTEST background pixel under the text (cream #F4F1EC on top):
       heading band     4.54:1  (large text needs 3:1)
       standfirst band  6.51:1  (body text needs 4.5:1)
   A first attempt at this gradient measured 3.16:1 on the heading — legal for large text
   but far too thin, given one rule serves several different photographs. If you lighten
   it again, re-measure with the text hidden; sampling a normal screenshot picks up the
   glyphs themselves and reports a meaningless ratio. */
.hero--page .hero__scrim {
  background:
    linear-gradient(to top, rgba(22, 36, 27, 0.86) 0%, rgba(28, 47, 35, 0.60) 52%, rgba(36, 63, 46, 0.34) 100%),
    linear-gradient(102deg, rgba(36, 63, 46, 0.52) 0%, transparent 62%);
}

/* Page heroes sit closer to the content they head — the full hero's bottom margin is
   sized for a homepage stage, and doubled up with the next section's padding it left a
   conspicuous hole. */
.hero--page { margin-bottom: var(--sp-6); }

.facts { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.facts__item { padding: 0.35em 0.9em; border: 1px solid rgba(244, 241, 236, 0.28); border-radius: var(--radius-pill); font-size: var(--step--1); color: rgba(244, 241, 236, 0.86); }

/* ── Media ──────────────────────────────────────────────────────────────── */
.media {
  position: relative; overflow: hidden;
  border-radius: var(--radius-tile);
  background: var(--green-wash);
  aspect-ratio: 3 / 2;          /* reserves the box so nothing shifts on load */
}
.media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.media--tall { aspect-ratio: 4 / 5; }
.media--wide { aspect-ratio: 16 / 9; }
.media--square { aspect-ratio: 1; }
.media--bleed { border-radius: 0; }

figure { margin: 0; }
figcaption { margin-top: var(--sp-3); font-size: var(--step--2); color: var(--sage); }

/* Caption plate floated over an image corner. */
.media__plate {
  position: absolute; left: var(--sp-4); bottom: var(--sp-4);
  max-width: calc(100% - var(--sp-8));
  padding: var(--sp-3) var(--sp-4);
  background: rgba(251, 250, 246, 0.94);
  border-radius: var(--radius-sm);
  font-size: var(--step--2); color: var(--sage);
}
.media__plate strong { display: block; font-family: var(--font-display); font-size: var(--step-0); font-weight: 500; color: var(--green); }

/* ── Reveals ────────────────────────────────────────────────────────────────
   Base states for the Motion-driven entrances in main.js.

   Note the `.motion-ready` ancestor: JS adds that class to <html> only after it has
   confirmed the Motion bundle loaded AND that motion is permitted. Until then — and
   forever, if the vendor file 404s or the visitor prefers reduced motion — these rules
   never match and every element is simply visible.

   The reference site inverts this: its hero heading is hidden in CSS and revealed by
   GSAP SplitText, so one failed vendor request leaves the headline invisible.
   --------------------------------------------------------------------------- */
.motion-ready .reveal { opacity: 0; }
.motion-ready .reveal--up { transform: translateY(20px); }
.reveal-line { display: block; overflow: hidden; }
.motion-ready .reveal-line > span { display: block; transform: translateY(105%); }

/* ── Editorial list — used for service lists and the resources table ────── */
.rows { border-top: 1px solid var(--rule); }
.rows__item {
  display: grid; grid-template-columns: 3rem 1fr auto; gap: var(--sp-4);
  align-items: baseline;
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  transition: background-color var(--dur) var(--ease-butter);
}
a.rows__item:hover { background: var(--green-wash); }
.rows__num { font-size: var(--step--2); font-weight: 600; letter-spacing: 0.08em; color: var(--sage); font-variant-numeric: tabular-nums; }
.rows__body h3 { font-size: var(--step-1); margin-bottom: var(--sp-2); }
.rows__body p { font-size: var(--step--1); color: var(--sage); margin: 0; }
.rows__meta { font-size: var(--step--2); color: var(--sage); text-align: right; white-space: nowrap; }
a.rows__item:hover .rows__body h3 { color: var(--terracotta); }

/* ── Prose — service pages, legal pages, articles ───────────────────────── */
.prose { max-width: var(--measure); }
.prose > * + * { margin-top: var(--sp-5); }
.prose h2 { font-size: var(--step-2); margin: var(--sp-8) 0 var(--sp-4); }
.prose h2:first-child { margin-top: 0; }
.prose h3 { font-size: var(--step-1); margin: var(--sp-6) 0 var(--sp-3); }
.prose ul, .prose ol { margin: 0; padding-left: 1.15em; }
.prose li { margin-bottom: var(--sp-3); }
.prose li::marker { color: var(--terracotta); }
.prose strong { font-weight: 600; color: var(--green); }
.prose a { color: var(--terracotta); }
.prose blockquote {
  margin: var(--sp-6) 0; padding-left: var(--sp-5);
  border-left: 2px solid var(--terracotta);
  font-family: var(--font-display); font-size: var(--step-1); font-style: italic;
  color: var(--green-soft);
}

/* Definition-style pairs — "what you receive", key dates. */
.pairs { display: grid; gap: 0; margin: 0; border-top: 1px solid var(--rule); }
.pairs > div { display: grid; grid-template-columns: minmax(140px, 30%) 1fr; gap: var(--sp-4); padding: var(--sp-4) 0; border-bottom: 1px solid var(--rule); }
.pairs dt { font-family: var(--font-body); font-size: var(--step--1); font-weight: 600; color: var(--green); margin: 0; }
.pairs dd { margin: 0; font-size: var(--step--1); color: var(--sage); }

/* Table — compliance calendar. */
.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: var(--step--1); }
table.data caption { text-align: left; padding-bottom: var(--sp-3); color: var(--sage); font-size: var(--step--2); }
table.data th, table.data td { text-align: left; padding: var(--sp-3) var(--sp-4) var(--sp-3) 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
table.data th { font-family: var(--font-body); font-weight: 600; color: var(--green); white-space: nowrap; }
table.data td:first-child { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--green); font-weight: 500; }

/* People on /about/team.
   CoE 2026 §3.3.9 permits a photograph of a person associated with the firm, but only a
   passport-style one — so every frame here is a fixed 4:5 head-and-shoulders crop, never a
   wide or candid one, and object-position is pinned to the top so a tall crop trims the
   chest rather than the forehead. tools/make-portraits.py produces the files to match.

   Everyone sits in one roster, partner first, so the three portraits read as a set. A card
   carries the name and the designation only — `areas` is held in app/data/people.php but
   not published, at the client's instruction. Three columns hold down to 40rem rather than
   dropping to two, because with exactly three people a 2-up grid orphans the third. */
.roster {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-8) var(--sp-6);
  margin: 0; padding: 0; list-style: none;
}
.roster__item { display: flex; flex-direction: column; }
.roster__photo { display: block; width: 100%; margin-bottom: var(--sp-5); }
.roster__img {
  display: block; width: 100%; height: auto; aspect-ratio: 4 / 5;
  object-fit: cover; object-position: center top;
  border-radius: var(--radius-card); background: var(--rule);
}
.roster__name { font-size: var(--step-1); margin: 0 0 var(--sp-2); }
.roster__desig { font-size: var(--step--1); color: var(--sage); margin: 0; }

/* The partner's own permitted particulars (§3.3.7(viii)) — below the grid, because they do
   not apply to the employee cards beside him. Renders only once one is confirmed. */
.particulars { margin-top: var(--sp-9); max-width: 34rem; }
.particulars .pairs { margin-top: var(--sp-4); }

@media (max-width: 40rem) {
  .roster { grid-template-columns: minmax(0, 1fr); gap: var(--sp-7); }
  .roster__item { max-width: 280px; }
}

/* Disclosure — phase-two services inside a pillar page. */
details.disclose { border-bottom: 1px solid var(--rule); }
details.disclose summary {
  display: flex; justify-content: space-between; align-items: center; gap: var(--sp-4);
  padding: var(--sp-5) 0; cursor: pointer;
  font-family: var(--font-display); font-size: var(--step-1); color: var(--green);
  list-style: none;
}
details.disclose summary::-webkit-details-marker { display: none; }
details.disclose summary::after { content: "+"; font-family: var(--font-body); font-size: var(--step-2); color: var(--terracotta); line-height: 1; }
details.disclose[open] summary::after { content: "−"; }
details.disclose summary:hover { color: var(--terracotta); }
details.disclose > div { padding-bottom: var(--sp-5); }

/* Pull-only marker on exclusive services. */
.pill-note {
  display: inline-flex; align-items: center; gap: 0.45em;
  padding: 0.28em 0.7em;
  border: 1px solid var(--rule-strong); border-radius: var(--radius-pill);
  font-size: var(--step--2); color: var(--sage);
}
.pill-note::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--terracotta); }


.method { display: grid; gap: var(--sp-6); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.method__item { display: flex; gap: var(--sp-5); }
.method__body h3 { font-size: var(--step-1); margin-bottom: var(--sp-2); }
.method__body p { font-size: var(--step--1); color: var(--sage); }
.section--green .method__body p { color: rgba(244, 241, 236, 0.78); }
.section--green .tile { background: transparent; border-color: rgba(244, 241, 236, 0.34); color: var(--cream); }
.section--green .tile--accent { background: var(--terracotta); border-color: var(--terracotta); }

/* ⚠️ `column-gap` is not optional here.
   With gap: 0 the two columns sat flush — the left column's note ran to within 3px of the
   right column's first character (measured on the home page: note ended at x=749, right
   column started at 752). Row gap stays 0 so the rules stack tightly; the column gap is
   what separates the two reading columns. */
.entity-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* Proportional, because this list appears both in a half-width column on the home page
     (~500px, where a fixed 48px gutter squeezes the notes to three lines) and in a full
     container on /about and the pillar pages (~1200px, where 24px would look mean).
     Floor is 24px — comfortably above the ~20px at which two columns start to read as
     one — and the ceiling stops the gutter dominating a wide layout. */
  column-gap: clamp(var(--sp-5), 5%, var(--sp-7));
  row-gap: 0;
  margin: 0; padding: 0; list-style: none;
}
.entity-list li { padding: var(--sp-4) 0; border-top: 1px solid var(--rule); }
.entity-list strong { display: block; font-family: var(--font-display); font-size: var(--step-0); color: var(--green); }
.entity-list span { font-size: var(--step--1); color: var(--sage); }

.office { padding-top: var(--sp-5); border-top: 2px solid var(--green); }
.office__label { font-family: var(--font-display); font-size: var(--step--1); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--terracotta); margin-bottom: var(--sp-3); }
/* ⚠️ Terracotta is an on-CREAM accent (6.3:1). On the green section it measured 1.62:1.
   Use the established on-green accent instead — the same one `.section--green .em` uses. */
.section--green .office__label { color: #D8A38C; }
.section--green .office address,
.section--green .office dd { color: rgba(244, 241, 236, 0.92); }
.section--green .office dt { color: rgba(244, 241, 236, 0.70); }

.office address { font-style: normal; line-height: 1.7; }
.office dl { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-2) var(--sp-4); margin: var(--sp-4) 0 0; font-size: var(--step--1); }
.office dt { color: var(--sage); }
.office dd { margin: 0; }

.notice {
  padding: var(--sp-5);
  border-left: 3px solid var(--terracotta);
  background: var(--terra-wash);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: var(--step--1);
}
.notice p { color: var(--green-soft); }

/* ── 8. Forms ───────────────────────────────────────────────────────────── */
.form { display: grid; gap: var(--sp-5); }
.form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5); }
.field { display: grid; gap: var(--sp-2); }
.field > label { font-family: var(--font-display); font-size: var(--step--1); font-weight: 600; color: var(--green); }
.field .req { color: var(--terracotta); }
.field .hint { font-size: var(--step--1); color: var(--sage); }

.field input, .field select, .field textarea {
  width: 100%;
  padding: 0.7em 0.9em;
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur) var(--ease-butter), box-shadow var(--dur) var(--ease-butter);
}
.field textarea { min-height: 9rem; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--green);
  box-shadow: 0 0 0 3px rgba(36, 63, 46, 0.12);
}
.field[data-invalid="true"] :is(input, select, textarea) { border-color: #9B2C1E; }
/* Error text carries an icon glyph as well as colour, so colour is never the only
   indicator of state. */
.field__error { font-size: var(--step--1); color: #9B2C1E; }
.field__error::before { content: "▲ "; font-size: 0.75em; }

.field--check { grid-template-columns: auto 1fr; align-items: start; gap: var(--sp-3); }
.field--check input { width: 1.1rem; height: 1.1rem; margin-top: 0.35em; }
.field--check label { font-family: var(--font-body); font-weight: 400; font-size: var(--step--1); color: var(--sage); }

/* Honeypot. Off-screen rather than display:none — some bots skip hidden fields. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.alert { padding: var(--sp-5); border-radius: var(--radius-card); font-size: var(--step-0); }
.alert--ok { background: var(--green-wash); border: 1px solid var(--green); }
.alert--bad { background: var(--terra-wash); border: 1px solid var(--terracotta); }
.alert h3 { margin-bottom: var(--sp-2); }

/* ── 9. Utilities ───────────────────────────────────────────────────────── */
/* These exist so that no template ever needs a style="" attribute. The CSP is
   style-src 'self' with no 'unsafe-inline', which blocks style attributes outright —
   deliberately, since that is what makes the policy worth having. Add a class here
   rather than weakening the header. */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.flow > * + * { margin-top: var(--sp-4); }
.flow-lg > * + * { margin-top: var(--sp-6); }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mt-4 { margin-top: var(--sp-4); }
.mt-6 { margin-top: var(--sp-6); }
.mt-7 { margin-top: var(--sp-7); }
.mt-8 { margin-top: var(--sp-8); }
.mb-0 { margin-bottom: 0; }
.gap-5 { gap: var(--sp-5); }
.on-sage { color: var(--sage); }
/* Ghost button sitting on the hero's dark scrim. */
.btn--ghostLight { border-color: rgba(244, 241, 236, 0.45); color: var(--cream); background: transparent; }
.btn--ghostLight:hover { background: rgba(244, 241, 236, 0.14); color: var(--cream); border-color: var(--cream); }
[hidden] { display: none !important; }

/* htmx indicator styles.
   Defined here rather than letting htmx inject them: it appends a <style> element at boot,
   which style-src 'self' blocks. Set includeIndicatorStyles:false in the htmx-config meta
   tag (app/partials/head.php) and these take over. */
.htmx-indicator { opacity: 0; transition: opacity 200ms var(--ease-butter); }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { opacity: 1; }

/* While a boosted navigation is in flight the progress bar fills to a holding position,
   so a slow response still reads as something happening rather than a dead click. */
body.htmx-request .progress { transform: scaleX(0.75); transition: transform 900ms var(--ease-butter); }

/* ── 10. View transitions ───────────────────────────────────────────────────
   Cross-document page transitions, opted in on both the outgoing and incoming
   document. This is a pure progressive enhancement: MDN currently lists
   @view-transition as "Limited availability" — not Baseline, because it does not work
   in some of the most widely used browsers. Where it is unsupported the navigation is
   an ordinary one, and nothing is lost.

   The masthead and the nav carry stable view-transition-names, so they hold still while
   the page content crossfades under them. That continuity is the whole effect: it makes
   a 24-page server-rendered site feel like one application.
   --------------------------------------------------------------------------- */
@view-transition { navigation: auto; }

.nav-wrap  { view-transition-name: site-nav; }
.brand     { view-transition-name: site-brand; }
.progress  { view-transition-name: site-progress; }
.footer    { view-transition-name: site-footer; }

::view-transition-old(root) { animation: vt-out 220ms var(--ease-butter) both; }
::view-transition-new(root) { animation: vt-in 320ms var(--ease-butter) both; }

/* Pinned elements must not be animated by the root group, or they judder. */
::view-transition-group(site-nav),
::view-transition-group(site-brand),
::view-transition-group(site-progress) { animation-duration: 0ms; }

@keyframes vt-out { to { opacity: 0; transform: translateY(-8px); } }
@keyframes vt-in { from { opacity: 0; transform: translateY(10px); } }

/* ── 10b. Floating dock — WhatsApp and back to top ──────────────────────────
   Bottom-right, stacked, clear of the viewport edge. Both buttons are anchors that
   work without JS; JS only reveals the back-to-top one once there is somewhere to
   go back to.

   Deliberately quiet: no pulse, no bounce, no "Chat with us!" bubble. Hover and focus
   change colour and border only — never transform, which would shift the layout of a
   fixed element and fight the scroll. */
.dock {
  position: fixed;
  right: clamp(0.9rem, 2vw, 1.5rem);
  bottom: clamp(0.9rem, 2vw, 1.5rem);
  z-index: 60;                      /* above content, below the drawer (80) and its veil */
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  align-items: flex-end;
}

.dock__btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid rgb(36 63 46 / 0.16);
  box-shadow: 0 2px 6px rgb(20 32 24 / 0.08), 0 10px 24px rgb(20 32 24 / 0.10);
  color: var(--green);
  cursor: pointer;
  transition: background-color 200ms ease, border-color 200ms ease, color 200ms ease;
}

.dock__icon { width: 22px; height: 22px; }

/* The label is for assistive tech and wide screens; the icon carries it visually. */
.dock__label {
  position: absolute;
  right: calc(100% + 0.55rem);
  padding: 0.3rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--green);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease;
}

.dock__btn:hover .dock__label,
.dock__btn:focus-visible .dock__label { opacity: 1; }

/* WhatsApp keeps its own brand green as the glyph colour — their guidelines do not permit
   recolouring the mark, and it is the fastest thing on the page for a user to recognise. */
.dock__btn--wa { color: #25D366; }
.dock__btn--wa:hover,
.dock__btn--wa:focus-visible {
  background: #25D366;
  border-color: #25D366;
  color: #fff;
}

.dock__btn--top:hover,
.dock__btn--top:focus-visible {
  background: var(--green);
  border-color: var(--green);
  color: var(--cream);
}

.dock__btn:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }

/* [hidden] on an element we also set to display:grid needs the explicit override. */
.dock__btn[hidden] { display: none; }

/* Printing a floating button is meaningless. */
@media print { .dock { display: none; } }

/* Consent checkbox: the input measured 18x18, and the row it sits in was only as tall as
   the text. Enlarge the control and make the label share the hit area, since that is where
   people actually tap. */
.field--check { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-3); align-items: start; }
.field--check input[type="checkbox"] {
  width: 1.5rem; height: 1.5rem;   /* 24px */
  margin-top: 0.1rem;
  accent-color: var(--green);
  cursor: pointer;
  flex: none;
}
.field--check label {
  min-height: 2.75rem;             /* 44px row, so the label is a real target */
  display: flex; align-items: center; flex-wrap: wrap;
  cursor: pointer;
}

/* A container nested inside another container must not re-apply the inline padding —
   otherwise its content sits inset from every sibling block. Measured on /careers, where a
   narrow container inside a wide one started 16px further in than the rest of the page. */
.container .container,
.container .container--narrow { padding-inline: 0; }

/* The brand link measured 124x30 on a phone, under the 44px comfortable-tap height. Give
   it the height without moving anything: the mark and text stay vertically centred. */
@media (max-width: 900px) {
  .brand { min-height: 2.75rem; }
}

/* A standalone link is a control, not prose, so it needs a real target. These measured
   14px tall on a phone against the 24px minimum in WCAG 2.5.8. Inline links inside a
   paragraph are exempt from that rule and are deliberately left alone. */
.link-arrow,
.footer__legal a,
.card__foot {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 1.5rem;   /* 24px */
}

/* A measure-constrained text column for use INSIDE an existing .container. Nesting a
   second .container there re-centres it in the parent's content box, which put it 24px left
   of an unnested narrow container on the same page (measured on /careers). */
.measure { max-width: var(--container-narrow); }

/* Hero inset compensation.
   The hero is inset by --sp-4 while sections are flush, so its container's text starts
   --sp-4 further right than every section below it: measured 40px vs 24px at 1024px.
   Above --container the container reaches its max-width and centres INSIDE the hero, so the
   symmetric inset cancels itself and no compensation is wanted — hence the upper bound.
   Below 900px the hero is already full-bleed, hence the lower bound. */
@media (min-width: 901px) and (max-width: 1279px) {
  .hero > .container { padding-inline: calc(var(--sp-5) - var(--sp-4)); }
}

/* The breadcrumb link in a hero designation measured 79x15 — a standalone navigation
   control under the 24px minimum in WCAG 2.5.8. */
.hero__desig a { display: inline-flex; align-items: center; min-height: 1.5rem; }

/* ── 10c. Section rhythm ────────────────────────────────────────────────────
   A tonal change earns a double gap. Two plain sections, or two paper sections, in
   sequence do not — the reader sees one block with a hole in it. Drop the second one's
   top padding so the join is the first one's bottom padding alone. */
.section:not(.section--paper):not(.section--green):not(.hero)
  + .section:not(.section--paper):not(.section--green):not(.hero) { padding-top: 0; }
.section--paper + .section--paper { padding-top: 0; }

/* A trailing margin on the last element inside a section adds to the section's own
   padding, so the gap below is bigger than the gap above by whatever that margin is.
   Measured on /about and /services/company-incorporation (16px and 12px on the h1). */
.section > .container > :last-child,
.section > .container--narrow > :last-child,
.hero__content > :last-child { margin-bottom: 0; }

/* ── 11. Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 1080px) {
  .footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .panel--mega { grid-template-columns: 1fr; gap: var(--sp-5); }
  .megarail { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 900px) {
  :root { --nav-h: 64px; }
  .utility { display: none; }
  .nav__list, .nav__cta { display: none; }
  .nav__burger { display: grid; }
  .split, .method, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  .grid--2 { grid-template-columns: 1fr; }
  .section { padding-block: var(--sp-7); }
  /* Full-bleed from here down: containers are full-width below 900px, so an inset hero
     shifts its own text 12px right of every section below it. Measured at 768px. */
  .hero { margin-inline: 0; border-radius: 0; min-height: 66vh; padding-block: var(--sp-8) var(--sp-7); }
  /* …but not the page variant, which would otherwise inherit 66vh from the line above
     purely because that line comes later in the file. */
  .hero--page { min-height: clamp(260px, 34vh, 340px); padding-block: var(--sp-7) var(--sp-5); }
  .megapane { grid-template-columns: 1fr; }
  .brand__name { font-size: var(--step-0); }
}

@media (max-width: 720px) {
  .entity-list { grid-template-columns: 1fr; }
  .form__row { grid-template-columns: 1fr; }
  .footer__top { grid-template-columns: 1fr; }
  .footer__meta { flex-direction: column; }
  .rows__item { grid-template-columns: 2.2rem 1fr; }
  .rows__meta { grid-column: 2; text-align: left; }
  .pairs > div { grid-template-columns: 1fr; gap: var(--sp-2); }
}

@media (max-width: 600px) {
  .container { padding-inline: var(--sp-4); }
  /* (Hero is already full-bleed from the 900px breakpoint — kept for clarity.) */
  .btn { width: 100%; justify-content: center; }
  .btn-row { flex-direction: column; align-items: stretch; }
  .brand__text { display: none; }     /* the mark carries it at this width */
  .hero__credit { display: none; }
}

/* Short-landscape case carried over from the reference — a laptop in a shallow window. */
@media (min-width: 821px) and (max-height: 700px) {
  .hero { min-height: 480px; padding-block: var(--sp-7) var(--sp-6); }
  .hero--page { min-height: 300px; padding-block: var(--sp-6) var(--sp-5); }
}

/* Dock: slightly smaller, and labels suppressed — there is no room, and touch has no
   hover state to reveal them with. */
@media (max-width: 600px) {
  .dock { gap: 0.5rem; }
  .dock__btn { width: 44px; height: 44px; }
  .dock__label { display: none; }
}

/* ── 12. Reduced motion and print ───────────────────────────────────────── */
@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;
  }
  /* The video is never attached by JS under this preference either — belt and braces. */
  .hero__video { display: none; }
  .hero__media { scale: 1; }
  /* Suppress page transitions outright rather than shortening them. */
  @view-transition { navigation: none; }
}

@media print {
  .utility, .nav-wrap, .drawer, .overlay, .progress,
  .hero__video, .hero__media, .hero__scrim, .hero__toggle, .hero__credit { display: none !important; }
  body { background: #fff; color: #000; }
  .hero { background: none; min-height: auto; margin: 0; padding-block: 0 var(--sp-5); }
  .hero__name, .hero__lede, .hero__desig { color: #000; }
  .media { display: none; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.85em; }
}
