/* Nandivahan Developers — shared stylesheet
   Palette follows the Five Elements generating cycle: Fire (maroon) creates
   Earth (cream), Earth creates Metal (gold). Cream carries roughly two
   thirds of every page; maroon anchors headings, the footer and at most two
   full-width bands; gold stays on hairlines, small caps and figures; jade is
   a small deliberate accent only. No blue, no navy, no pure black. */

:root {
  --maroon:      #5E2020;
  --maroon-deep: #3B0F0D;
  --brown:       #603020;
  /* Gold is split by role. On cream, --gold measures 3.5:1: enough for a
     line, not enough for words. So it keeps the rules, borders, underlines,
     focus rings and the chevron, and every gold glyph — small caps, labels,
     numerals — takes --gold-text, the same hue darkened (5.7:1 on cream,
     4.6:1 on cream-warm). Never color: var(--gold). Neither gold is set as
     text on maroon, where neither has the contrast; the band eyebrows there
     are marigold. */
  --gold:        #A87E27;
  --gold-text:   #7E5E1D;
  --marigold:    #EFC12A;
  --jade:        #47654F;
  --jade-soft:   #6E8F72;
  --cream:       #FDF9F0;
  --cream-warm:  #F0E0D0;
  --offwhite:    #F0F0F0;
  --ink:         #4B3A31;

  --font-display: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --font-body: 'Jost', -apple-system, 'Segoe UI', Arial, sans-serif;

  --container: 1160px;
}

/* ---------- Reset ---------- */

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

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

body {
  margin: 0;
  background-color: var(--cream);
  /* Faint drafting-table grid, echoing the elevation motif's own window
     grid and the compass grid in the Nandi emblem — quiets the flat cream
     ground without adding weight or competing with content. */
  background-image: radial-gradient(rgba(96, 48, 32, 0.05) 1px, transparent 1px);
  background-size: 26px 26px;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

/* ---------- The background veil (CLAUDE.md 10.8) ---------- */
/* The official logo, held still behind the whole site while the content
   scrolls over it. A real fixed element rather than background-attachment:
   fixed, which stutters on iOS Safari and in places fails outright.

   It is the logo rather than the Nandi emblem because the emblem is hairline
   drawing: it dissolves at the opacity this has to run at, and turning it up
   far enough to read puts a second copy of the hero's own bull behind the
   hero. The logo is solid shape, so it survives 0.05 and reads as its own
   object. Measured, the colour costs almost nothing — see below.

   It sits at z-index -1 — above the canvas the body background paints, below
   everything in the page — so every section carrying a ground of its own (the
   maroon bands, the footer, the panels, the stat cells, the header) covers it
   and only bare cream lets it through. It never sits behind a photograph, and
   never under light text on dark.

   0.05 was measured, not guessed: over the darkest pixel of the logo, on a
   dot of the body grid, warm near-black body text still reads 8.50:1 and the
   gold small caps 4.73:1. The ceiling is 0.07, where the small caps fall to
   4.53:1 — the AA floor, and the reason the range stops there. 0.08 fails.

   Decorative: aria-hidden in the markup, no alt, no pointer events, one
   instance, and it does not move. */

.page-veil {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* The plain url() is the fallback a browser without image-set() parses. */
  background-image: url("../img/logo-500.png");
  background-image: image-set(
    url("../img/logo-500.avif") type("image/avif"),
    url("../img/logo-500.webp") type("image/webp"),
    url("../img/logo-500.png") type("image/png")
  );
  background-repeat: no-repeat;
  background-position: center;
  /* Around two thirds of the viewport's height, held inside the logo's own
     500px native size so it is never upscaled, and inside the viewport's width
     so it is never cropped. The artwork is square, so the one length sets
     both sides and nothing is stretched. */
  background-size: min(66vh, 500px, 78vw) auto;
  opacity: 0.05;
}

/* Every image is a picture offering AVIF, then WebP, then the original. The
   wrapper is a block so it sizes exactly like the image it holds, and so the
   scroll reveal can still move a picture that sits directly in a container. */
picture { display: block; }

a { color: inherit; }

/* One focus ring for every link and button, in the site's gold rather than
   whatever the browser draws. Form fields, the guide and the skip link set
   their own. */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

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

figure { margin: 0; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--maroon);
  font-weight: 600;
  line-height: 1.1;
  margin: 0;
}

/* One size for every section heading, set once here so a new context — the
   invitation band was the one that slipped — cannot fall back to the
   browser's smaller default. Rajlaxmi and Riddhi are buildings like the other
   nine, so they are h3s in the outline, but each has a panel of its own and
   keeps this size through .feature-title. */
h2,
.feature-title { font-size: clamp(1.9rem, 5vw, 2.6rem); }

p { margin: 0; }

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 20px;
}

/* ---------- Utility ---------- */

/* Usually a span, but where it is the only heading a block has it is an h2,
   so the outline never skips a level. The line-height is set here rather than
   inherited so both elements render identically. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--font-body);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.6;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold-text);
}

.eyebrow::before {
  content: "";
  display: inline-block;
  width: 1.6em;
  height: 1px;
  background: var(--gold);
}

.rule-gold {
  border: none;
  border-top: 1px solid var(--gold);
  width: 64px;
  margin: 1.25rem 0;
}

/* Read by screen readers, never seen. */
.visually-hidden {
  position: absolute;
  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;
}

.section {
  padding: 3rem 0;
}

.section-head {
  max-width: 640px;
  margin: 0 0 2.25rem;
}

.section-head h2,
.section-head .feature-title { margin-top: 0.6rem; }

.section-head p {
  margin-top: 1rem;
  font-size: 1.05rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0.85em 1.8em;
  border-radius: 2px;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.btn-primary {
  background: var(--maroon);
  color: var(--cream);
  box-shadow: 0 2px 6px rgba(59, 15, 13, 0.18);
}

.btn-primary:hover { background: var(--maroon-deep); transform: translateY(-1px); box-shadow: 0 6px 14px rgba(59, 15, 13, 0.22); }

.btn:active { transform: translateY(0); }

.btn-ghost {
  background: transparent;
  color: var(--maroon);
  border-color: var(--gold);
}

.btn-ghost:hover {
  background: var(--maroon);
  color: var(--cream);
  border-color: var(--maroon);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-top: 1.75rem;
}

/* The rule sits on the text rather than the box, so the hit area can reach
   44px without the underline drifting away from the words. */
.link-more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 1.25rem;
  font-size: 1rem;
  font-weight: 500;
  color: var(--maroon);
  text-decoration: underline;
  text-decoration-color: var(--gold);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35em;
  transition: color 0.2s ease, text-decoration-color 0.2s ease;
}

.link-more:hover { color: var(--jade); text-decoration-color: var(--jade); }

.caption {
  font-size: 1rem;
  color: var(--brown);
  margin-top: 0.6rem;
  font-style: italic;
}

.tag {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--cream);
  background: var(--jade);
  padding: 0.4em 0.9em;
  border-radius: 999px;
}

/* ---------- Form (contact.html only — no other page needs one) ---------- */
/* Parked: the form is off until send.php exists (see the TODO in contact.html).
   These rules stay so it can return unchanged. */

.form-field { display: block; margin-bottom: 1.5rem; }

/* The "I am a" question is a fieldset, so its radios are announced with it.
   The browser's frame is removed and the legend is dressed as a label. */
fieldset.form-field {
  min-width: 0;
  margin-inline: 0;
  padding: 0;
  border: 0;
}

.form-field label,
.form-field legend {
  display: block;
  /* Never below 16px: these are read by people filling the form on a phone. */
  font-size: 1rem;
  font-weight: 500;
  color: var(--brown);
  margin-bottom: 0.5rem;
}

.form-field legend { padding: 0; }

/* Spelled out rather than an asterisk, which is easy to miss on a phone. The
   inputs carry the required attribute, so screen readers already announce it
   and the visible word is hidden from them. */
.field-required {
  font-weight: 400;
  color: var(--ink);
}

.form-field input,
.form-field select,
.form-field textarea {
  width: 100%;
  min-height: 44px;
  padding: 0.7em 0.9em;
  border: 1px solid var(--cream-warm);
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  border-radius: 2px;
}

.form-field textarea { min-height: 130px; resize: vertical; }

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}

.radio-group { display: flex; flex-wrap: wrap; gap: 0.5rem 2rem; }

.radio-group label {
  display: flex;
  align-items: center;
  gap: 0.6em;
  min-height: 44px;
  font-size: 1rem;
  font-weight: 400;
  color: var(--ink);
  margin-bottom: 0;
}

.radio-group input { width: 18px; height: 18px; accent-color: var(--maroon); }

/* ---------- Scroll reveal (CLAUDE.md 10.4) ---------- */
/* Both classes are added by script. Nothing here hides anything on its own,
   so a page with no JavaScript renders fully visible. Entry only — an element
   that has arrived keeps .is-revealed and never fades out again. */

.will-reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 600ms ease-out, transform 600ms ease-out;
}

.is-revealed {
  opacity: 1;
  transform: none;
}

/* The building rises. An image of a building is not faded in like a card: it
   is uncovered from the ground up, the way a structure goes up. The rule is
   structural — on this site every image inside a figure is a building — so a
   new render needs no wiring. The figure only fades, so the picture is not
   also sliding, and the image reads the stagger delay the script sets. */
figure.will-reveal {
  transform: none;
  transition: opacity 400ms ease-out;
}

.will-reveal figure img,
figure.will-reveal img {
  clip-path: inset(100% 0 0 0);
  transition: clip-path 750ms cubic-bezier(0.16, 1, 0.3, 1);
  transition-delay: var(--reveal-delay, 0ms);
}

.is-revealed figure img,
figure.is-revealed img { clip-path: inset(0); }

/* Prospera is the one building still to be built, and it rises slowest. */
.will-reveal .upcoming-figure img,
.upcoming-figure.will-reveal img { transition-duration: 1000ms; }

/* Inside the phone scroll row a vertical shift fights the scroller, so those
   cards fade without rising. */
@media (max-width: 767px) {
  .commitment-grid .will-reveal { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .will-reveal,
  .is-revealed {
    opacity: 1;
    transform: none;
    transition: none;
    /* The delay is set inline by the script. */
    transition-delay: 0ms !important;
  }

  .will-reveal figure img,
  figure.will-reveal img {
    clip-path: none;
    transition: none;
  }
}

/* ---------- Page transitions (CLAUDE.md 10.4) ---------- */
/* The one motion that is not an entrance. Moving between pages, the header
   holds still while the page beneath it cross-fades. CSS only: a browser
   without support simply loads the next page, and so does a reader who has
   asked for reduced motion. It needs the site to be served, so it does not
   run on a page opened straight from the folder. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }

  .site-header { view-transition-name: site-header; }
}

/* ---------- Header ---------- */

/* Off-screen until it takes keyboard focus, then it sits over the header's
   left edge, so a keyboard reader passes the navigation in one keystroke.
   Screen readers find it first either way. */
.skip-link {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 100;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 1.1rem;
  background: var(--maroon);
  color: var(--cream);
  font-size: 1rem;
  font-weight: 500;
  text-decoration: none;
  border-radius: 2px;
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: none;
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.site-header {
  background: var(--cream);
  border-bottom: 1px solid var(--cream-warm);
  position: relative;
  z-index: 40;
}

/* The bar is sized by the mark, not the other way round. */
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 96px;
}

/* The mark and the name. The header carries logo-mark — the seated bull inside
   its ring, with the wordmark cut away — rather than the full lockup. In the
   lockup the roundel is only half the file's height, so at a 76px box the bull
   rendered at 37px and its detail turned to mush. Cut free, the same box gives
   the roundel the whole 88px, and the wordmark it replaces was illegible at
   header size anyway.

   "Nandivahan" is set beside it in Cormorant, scaled with the mark, and is now
   the only place the name appears in the header. "Developers" stays off: small
   enough to sit under the name, it would be too small to read. The mark's alt
   text already names the link in full, so the visible name is hidden from
   screen readers rather than announced twice. */
.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
}

/* Height, not width: the mark is 266 x 244, so a width would set the bull's
   size by however far its muzzle happens to stick out past the ring. */
.brand img { height: 68px; width: auto; }

.brand-name {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--maroon);
  line-height: 1.1;
}

/* The three bars stack in a column. The outer two sit 4px out from the middle
   one, and when the menu is open they meet at its centre to form the cross. */
.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: transparent;
  border: 1px solid var(--cream-warm);
  border-radius: 2px;
  cursor: pointer;
}

.nav-toggle span,
.nav-toggle::before,
.nav-toggle::after {
  content: "";
  display: block;
  width: 20px;
  height: 2px;
  background: var(--maroon);
  position: relative;
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.nav-toggle::before { transform: translateY(-4px); }
.nav-toggle::after { transform: translateY(4px); }

.nav-toggle[aria-expanded="true"] span { opacity: 0; }
.nav-toggle[aria-expanded="true"]::before { transform: translateY(2px) rotate(45deg); }
.nav-toggle[aria-expanded="true"]::after { transform: translateY(-2px) rotate(-45deg); }

/* The open menu hangs from the bottom of the header, whatever its height. */
.site-nav {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--cream);
  border-bottom: 1px solid var(--cream-warm);
  display: none;
  box-shadow: 0 12px 24px -18px rgba(59, 15, 13, 0.4);
}

.site-nav.is-open { display: block; }

.site-nav ul {
  display: flex;
  flex-direction: column;
  padding: 0.5rem 20px 1.25rem;
}

.site-nav a {
  display: flex;
  align-items: center;
  min-height: 48px;
  text-decoration: none;
  font-size: 1rem;
  font-weight: 500;
  color: var(--ink);
  border-bottom: 1px solid var(--cream-warm);
}

.site-nav a[aria-current="page"] { color: var(--maroon); }

.site-nav a:hover { color: var(--jade); }

/* ---------- Hero ---------- */
/* No photograph or render above the fold. Every hero is built around the
   firm's own artwork, nandi-emblem.png — the seated Nandi before a skyline
   inside concentric rings. Native size is 500x500 and it is never rendered
   above that: 380-440px on desktop, 260-310px on inner pages, no more than
   260px on a phone. The emblem carries its own rings, so nothing is drawn
   around it. The headline block and the emblem are optically centred against
   each other and the gap between them stays far narrower than the emblem. */

/* Phone: the hero has to clear the fold on an 844px screen with the header
   above it, so the padding is tighter and the emblem sits below its 260px
   ceiling rather than at it. */
.hero { padding: 1.5rem 0 2rem; }

/* The inner-page hero carries a ground of its own, so the veil does not show
   through it. This is not a special case — it is the same rule as the maroon
   bands and the panels in 10.8, applied where it is needed: the veil is the
   official logo, and from 900px down the inner hero shows that same logo,
   centred, at very nearly the same size. Left transparent, the two land on
   top of each other and read as a misprint. Home keeps a transparent hero,
   because its mark is the Nandi emblem and there is nothing to double. */
/* The ground is cream plus the body's own drafting grid, repeated here rather
   than simply painted over, so the only thing the panel hides is the veil.
   The body's grid is measured from the top of the document and this one from
   the top of the hero, so it is pulled back by however far the header pushed
   it — the header's own height, modulo the 26px cell. Header 96.8px on a
   phone leaves 18.8, 120.8px from the tablet breakpoint up leaves 16.8. If
   the header height in section 4 changes, these two numbers change with it. */
.hero--compact {
  background-color: var(--cream);
  background-image: radial-gradient(rgba(96, 48, 32, 0.05) 1px, transparent 1px);
  background-size: 26px 26px;
  background-position: 0 -18.8px;
}

@media (min-width: 768px) {
  .hero--compact { background-position: 0 -16.8px; }
}

.hero-grid {
  max-width: 1060px;
  margin: 0 auto;
  padding: 0 20px;
  display: grid;
  gap: 2rem;
}

.hero-copy h1 {
  font-size: clamp(2.1rem, 8vw, 3rem);
  margin-top: 0.6rem;
}

.hero-copy p {
  margin-top: 1.1rem;
  font-size: 1.1rem;
  max-width: 48ch;
  color: var(--ink);
}

.hero-art { display: flex; justify-content: center; }

/* Upcoming is the only hero carrying two paragraphs, and on a phone they push
   everything else past the fold. The emblem goes above the copy there — which
   section 9.1 allows — so the firm and the heading are what a reader meets
   first, rather than the top of a wall of text. */
@media (max-width: 899px) {
  .hero--prose .hero-grid { gap: 1.5rem; }
  .hero--prose .hero-art { order: -1; }
  .hero--prose .hero-art img { width: min(180px, 46vw); }
}

/* Phone: above or below the text rather than beside it, and comfortably under
   the 260px ceiling so the whole hero clears the fold. */
.hero-art img { width: min(210px, 54vw); height: auto; }

/* Home keeps the Nandi emblem; the five inner pages carry the official logo.
   Both files are 500 x 500, but they are not filled the same way: the emblem's
   artwork covers its whole canvas, the logo's covers 84% of the width and only
   68% of the height. Rendered at the same width the logo puts a third less ink
   in the slot and the hero loses the balance section 9.2 asks for. Every width
   below is the emblem's width for that slot divided by 0.68, which lands the
   same ink height in the same place. Nothing reaches the file's own 500px, so
   nothing is upscaled and nothing is stretched. */
.hero-art img.hero-logo { width: min(300px, 76vw); }

@media (max-width: 899px) {
  .hero--prose .hero-art img.hero-logo { width: min(264px, 64vw); }
}

/* ---------- Who we are / What we build ---------- */

.prose { max-width: 62ch; }

.prose p + p { margin-top: 1.1rem; }

.build-list {
  margin-top: 2rem;
  display: grid;
  gap: 1.5rem;
}

.build-list li {
  padding-left: 1.4rem;
  position: relative;
  font-size: 1.02rem;
}

.build-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jade);
}

.build-list h3 {
  font-size: 1.1rem;
  color: var(--brown);
  font-family: var(--font-body);
  font-weight: 600;
  margin-bottom: 0.3rem;
}

/* The emblem already carries the hero. Where the name is explained it returns
   once as a faint watermark — low opacity, generous margin, well under its
   500px native width. */
.name-emblem {
  width: min(300px, 70vw);
  height: auto;
  margin: 1.5rem auto 0;
  opacity: 0.4;
}

/* ---------- Motif divider band ---------- */
/* The one full-width maroon band besides the footer, per the palette's
   "one or at most two bands" rule. No photograph and no drawing — the motto
   carries it on its own. */

.motif-divider {
  position: relative;
  color: var(--cream);
  padding: 3.5rem 0;
  background-color: var(--maroon);
  overflow: hidden;
  isolation: isolate;
}

.motif-divider .container { text-align: center; position: relative; }

.motif-divider p.motto {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 5vw, 2rem);
  color: var(--cream);
  letter-spacing: 0.02em;
}

.motif-divider .caption { color: var(--cream-warm); opacity: 0.85; }

/* ---------- The commitments ---------- */
/* Four by two on desktop, two by four on tablet, a horizontal scroll-snap row
   on phones with a small progress indicator. Never a carousel on desktop — a
   carousel hides seven items to show one, and a committee member on a laptop
   will not hunt for arrows. The numeral sits large and faint behind the title
   rather than as a small label. Cards stretch to equal heights in each row. */

.commitments {
  margin-top: 2rem;
  /* Lets the phone progress bar read the row's scroll position in CSS alone,
     so this needs no JavaScript. */
  timeline-scope: --commitment-row;
}

.commitment-grid {
  display: grid;
  gap: 1.25rem;
}

.commitment-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0.3rem 1.1rem 1.3rem;
  border-left: 2px solid transparent;
  transition: border-left-color 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}

/* Everything but the numeral paints above it. */
.commitment-card > :not(.commitment-num) { position: relative; z-index: 1; }

.commitment-num {
  position: absolute;
  top: -0.35rem;
  left: 0.7rem;
  z-index: 0;
  font-family: var(--font-display);
  font-size: 3.5rem;
  font-weight: 600;
  line-height: 1;
  color: var(--gold-text);
  opacity: 0.24;
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  transition: opacity 0.3s ease;
}

/* Clears the numeral's glyphs, so the hairline reads as its own line rather
   than disappearing into the figure above it. Drawn at 64px and scaled to
   38px at rest, so it can extend without animating its width. */
.commitment-rule {
  border: none;
  border-top: 1px solid var(--gold);
  width: 64px;
  margin: 3.15rem 0 0.9rem;
  transform: scaleX(0.59375);
  transform-origin: left;
  transition: transform 0.3s ease;
}

.commitment-card h3 {
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--maroon);
}

.commitment-card p {
  margin-top: 0.5rem;
  font-size: 1rem;
  color: var(--ink);
}

/* The card answers a pointer or a tap: the jade edge appears, the faint
   numeral warms and the hairline draws out. A phone only treats a tap as
   hover on something that looks clickable, hence the pointer on touch
   screens alone. */
.commitment-card:hover { border-left-color: var(--jade); }

.commitment-card:hover .commitment-num { opacity: 0.7; }

.commitment-card:hover .commitment-rule { transform: none; }

@media (hover: none) {
  .commitment-card { cursor: pointer; }
}

@media (prefers-reduced-motion: reduce) {
  .commitment-num,
  .commitment-rule { transition: none; }
}

.commitment-progress {
  display: none;
  height: 2px;
  margin-top: 1.1rem;
  background: var(--cream-warm);
  overflow: hidden;
}

.commitment-progress span {
  display: block;
  width: 25%;
  height: 100%;
  background: var(--jade-soft);
}

@keyframes commitment-progress {
  from { transform: translateX(0); }
  to   { transform: translateX(300%); }
}

/* Phones: one scroll-snap row, bleeding to both screen edges. Nothing is
   hidden behind arrows — the row is swiped, and the bar shows where you are. */
/* The two Dombivli aerials are the only real photographs on the site and the
   strongest thing on Our Work. Section 10.7 makes them the exception to
   keeping images contained, so on a phone they run to both screen edges and
   gain back the container's padding. */
@media (max-width: 767px) {
  .aerial { margin-left: -20px; margin-right: -20px; }

  .aerial img { width: 100%; }

  .aerial figcaption { padding: 0 20px; }
}

@media (max-width: 767px) {
  .commitment-grid {
    grid-auto-flow: column;
    grid-auto-columns: 78%;
    gap: 1rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-left: 20px;
    margin: 0 -20px;
    padding: 0 20px;
    scrollbar-width: none;
    scroll-timeline: --commitment-row x;
  }

  .commitment-grid::-webkit-scrollbar { display: none; }

  .commitment-card { scroll-snap-align: start; }

  .commitment-progress { display: block; }

  /* Where scroll-driven animation is unsupported the bar simply sits at the
     start rather than breaking. */
  @supports (animation-timeline: scroll()) {
    .commitment-progress span {
      animation: commitment-progress linear both;
      animation-timeline: --commitment-row;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .commitment-progress span { animation: none; }
}

/* ---------- The record ---------- */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--cream-warm);
  border: 1px solid var(--cream-warm);
  margin-bottom: 3rem;
}

.stat {
  background: var(--cream);
  padding: 1.75rem 1.25rem;
  text-align: center;
  transition: background-color 0.2s ease;
}

.stat:hover { background: var(--cream-warm); }

.stat .figure {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2rem, 6vw, 2.8rem);
  color: var(--maroon);
  font-weight: 600;
}

.stat .label {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-text);
  font-weight: 600;
}

.suburb-grid {
  display: grid;
  gap: 1rem;
}

/* Each suburb opens its own group on Our Work. The whole row is the link, and
   the arrow carries the response: it steps forward on hover and focus, and
   further while pressed. Room is kept on the right so it never wraps. */
.suburb-card {
  position: relative;
  border-top: 1px solid var(--gold);
  padding: 1.1rem 2rem 1.1rem 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1rem;
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

.suburb-arrow {
  position: absolute;
  right: 0.25rem;
  top: 50%;
  font-size: 1.1rem;
  color: var(--maroon);
  transform: translateY(-50%);
  transition: transform 0.2s ease, color 0.2s ease;
}

.suburb-card:hover .suburb-arrow,
.suburb-card:focus-visible .suburb-arrow {
  color: var(--jade);
  transform: translate(4px, -50%);
}

.suburb-card:active .suburb-arrow { transform: translate(8px, -50%); }

/* With reduced motion the arrow still answers, but moves at once. */
@media (prefers-reduced-motion: reduce) {
  .suburb-arrow { transition: none; }
}

.suburb-card .name {
  font-family: var(--font-display);
  font-size: 1.3rem;
  color: var(--maroon);
  font-weight: 600;
  flex: 1 1 160px;
}

.suburb-card .metrics {
  font-size: 1rem;
  color: var(--ink);
}

.suburb-card .metrics strong { color: var(--brown); }

/* ---------- Upcoming panel ---------- */

.upcoming-panel {
  background: var(--cream-warm);
  padding: 2.5rem 1.25rem;
  border-radius: 2px;
  box-shadow: 0 10px 30px -12px rgba(59, 15, 13, 0.15);
}

.upcoming-media { margin-top: 1.75rem; }

.upcoming-media img { border-radius: 2px; }

.upcoming-panel .eyebrow { margin-bottom: 0.5rem; }

/* The pill sits on the same line as the heading, never above it, so it flows
   inline with the text rather than being laid out as a separate row. */
.title-with-pill .tag {
  vertical-align: middle;
  margin-left: 0.8rem;
  position: relative;
  top: -0.18em;
  white-space: nowrap;
}

/* The last word and the pill never part. Where a screen is too narrow for the
   whole title, it breaks before "Prospera" and the pill stays beside it — it
   is never left alone on a line under the name. */
.title-tail { white-space: nowrap; }

/* At 390px "Codename Prospera" takes 265 of the 350px available, and the full
   pill needs 115px more. On a phone the pill gets smaller rather than wrapping:
   tracking, padding and the gap give up the width, so the letters themselves
   hold at 11px. */
@media (max-width: 479px) {
  .title-with-pill .tag {
    font-size: 0.6875rem;
    letter-spacing: 0.06em;
    padding: 0.4em 0.45em;
    margin-left: 0.35rem;
  }
}

/* Three facts, side by side once there is room, stacked before that. */
.upcoming-facts {
  margin-top: 2rem;
  display: grid;
  gap: 1.5rem;
  border-top: 1px solid var(--gold);
  padding-top: 1.5rem;
  font-size: 1rem;
}

.upcoming-facts li { display: grid; gap: 0.35rem; }

.upcoming-facts li span:first-child {
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-text);
  font-weight: 600;
}

.upcoming-facts li span:last-child {
  font-family: var(--font-display);
  font-size: 1.3rem;
  color: var(--maroon);
  font-weight: 600;
  line-height: 1.2;
}

.upcoming-figure { margin-top: 2.5rem; }

.upcoming-figure img { border-radius: 2px; }

/* Paragraph two of the Upcoming copy sits beside the emblem on a wide screen
   and below the render on a phone. On upcoming.html the two positions are in
   different sections, so the paragraph is written twice and only one copy is
   ever rendered. In the home panel every item is a sibling, so `order` moves
   it and no second copy is needed. */
.prose-narrow { display: block; }

.prose-wide { display: none; }

.prose-narrow {
  margin-top: 1.75rem;
  font-size: 1.1rem;
  color: var(--ink);
}

@media (max-width: 899px) {
  .upcoming-panel--flow { display: flex; flex-direction: column; }
  .upcoming-panel--flow > .upcoming-figure { order: 1; }
  .upcoming-panel--flow > p:last-of-type { order: 2; }
  .upcoming-panel--flow > .upcoming-facts { order: 3; }
  .upcoming-panel--flow > .link-more { order: 4; }
}

@media (min-width: 900px) {
  .prose-narrow { display: none; }
  .prose-wide { display: block; }
}

/* ---------- The bungalow scheme (CLAUDE.md 10.7) ---------- */
/* Closes Our Work quietly: one line, two small views side by side, no heading
   and no area figure. Each view keeps its own aspect ratio rather than being
   forced into a matching box — the two sources are not the same shape. */

.bungalow-line { text-align: center; font-size: 1rem; }

.bungalow { max-width: 560px; margin: 2rem auto 0; }

.bungalow-views {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  align-items: start;
}

.bungalow-views img { width: 100%; height: auto; border-radius: 2px; }

.bungalow figcaption { text-align: center; }

/* ---------- Tap to enlarge ---------- */
/* Building images open at their own full size, so a reader on a phone can
   pinch in. Each is a plain link to the image file: no script, and the back
   button returns. On a touch screen the cue always shows; with a mouse it
   appears on hover and focus, and the pointer becomes a magnifier. The cue
   follows the image in the markup so it paints above it, and sits top right:
   the aerials carry building names printed along their lower edge. */
.enlarge {
  position: relative;
  display: block;
  width: fit-content;
  max-width: 100%;
  cursor: zoom-in;
  -webkit-tap-highlight-color: transparent;
}

/* Where the picture is set to fill its box — the aerials, the two bungalow
   views — the link fills the box too. Shrink-wrapped around an image whose
   width is a percentage of the link itself, it collapses to nothing. */
.aerial .enlarge,
.bungalow-views .enlarge { width: auto; }

.enlarge-cue {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 1;
  padding: 0.3em 0.8em;
  border-radius: 999px;
  background: var(--cream);
  color: var(--maroon);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  box-shadow: 0 2px 8px rgba(59, 15, 13, 0.25);
}

/* The two bungalow views are the smallest images on the site — 167px wide on
   a phone — so their cue is tighter and sits closer to the corner. */
.bungalow-views .enlarge-cue {
  top: 0.35rem;
  right: 0.35rem;
  padding: 0.2em 0.55em;
  letter-spacing: 0.08em;
}

@media (hover: hover) {
  .enlarge-cue {
    opacity: 0;
    transition: opacity 0.2s ease;
  }

  .enlarge:hover .enlarge-cue,
  .enlarge:focus-visible .enlarge-cue { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .enlarge-cue { transition: none; }
}

/* ---------- Directors ---------- */

.directors-intro {
  max-width: 60ch;
  margin-bottom: 2.5rem;
}

.director-grid {
  display: grid;
  gap: 2.5rem;
  grid-template-columns: 1fr;
}

.director-card { text-align: center; }

.roundel {
  width: 128px;
  height: 128px;
  border-radius: 50%;
  border: 1px solid var(--gold);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 1.1rem;
  background: var(--cream);
  box-shadow: 0 4px 14px rgba(59, 15, 13, 0.1);
  position: relative;
}

.roundel::before {
  content: "";
  position: absolute;
  inset: 6px;
  border: 1px solid var(--cream-warm);
  border-radius: 50%;
}

.roundel span {
  font-family: var(--font-display);
  font-size: 2.1rem;
  color: var(--maroon);
  font-weight: 600;
  letter-spacing: 0.04em;
}

.director-card .name {
  font-family: var(--font-display);
  font-size: 1.35rem;
  color: var(--maroon);
  font-weight: 600;
}

.director-card .title {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-text);
  font-weight: 600;
}

/* ---------- The guide for committees (CLAUDE.md 7.1) ---------- */
/* An accordion of seven topics, never a bulleted list. Built on <details> so
   it opens, closes and takes keyboard focus with no JavaScript at all. */

.guide { max-width: 760px; }

.guide-item { border-top: 1px solid var(--gold); }

.guide-item:first-of-type { border-top: none; }

.guide-item:last-of-type { border-bottom: 1px solid var(--gold); }

.guide-item > summary {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 44px;
  padding: 1.4rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 600;
  color: var(--maroon);
  transition: color 0.2s ease;
}

/* The default disclosure triangle, removed in favour of the chevron below. */
.guide-item > summary::-webkit-details-marker { display: none; }
.guide-item > summary::marker { content: ""; }

.guide-item > summary:hover { color: var(--brown); }

.guide-item > summary:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 4px;
}

.guide-item summary span:first-child { flex: 1; }

.guide-sign {
  flex: none;
  width: 10px;
  height: 10px;
  border-right: 1px solid var(--gold);
  border-bottom: 1px solid var(--gold);
  transform: rotate(45deg);
  transform-origin: 60% 60%;
  transition: transform 300ms ease;
}

.guide-item[open] .guide-sign { transform: rotate(-135deg); }

.guide-body { padding-bottom: 1.6rem; }

.guide-body p { font-size: 1.05rem; color: var(--ink); }

.guide-body p + p { margin-top: 1rem; }

.guide-note {
  margin-top: 1.75rem;
  max-width: 760px;
  font-size: 1rem;
  font-style: italic;
  color: var(--brown);
}

/* The smooth open, where the browser can interpolate to a keyword height.
   Elsewhere the panel simply opens at once — functional either way. */
@supports (interpolate-size: allow-keywords) {
  :root { interpolate-size: allow-keywords; }

  .guide-item::details-content {
    height: 0;
    overflow: hidden;
    transition: height 320ms ease-out, content-visibility 320ms allow-discrete;
  }

  .guide-item[open]::details-content { height: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .guide-sign { transition: none; }
  .guide-item::details-content { transition: none; }
}

/* ---------- How the work runs (CLAUDE.md 7.2) ---------- */
/* Numbered stages, generous spacing, a hairline gold rule between each, large
   gold numerals in Cormorant. Not bullets. The measure is held narrow: this is
   the passage a committee actually reads. */

.stages {
  max-width: 700px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.stage {
  padding: 2rem 0;
  border-top: 1px solid var(--gold);
}

.stage:first-child { border-top: none; padding-top: 0.25rem; }

.stage-num {
  display: block;
  font-family: var(--font-display);
  font-size: 2.6rem;
  font-weight: 600;
  line-height: 1;
  color: var(--gold-text);
  margin-bottom: 0.5rem;
}

.stage h3 {
  font-family: var(--font-display);
  font-size: 1.55rem;
  font-weight: 600;
  color: var(--maroon);
}

.stage p {
  margin-top: 0.9rem;
  font-size: 1.05rem;
  color: var(--ink);
}

/* ---------- Invitation band ---------- */

.invite {
  background: var(--maroon);
  color: var(--cream);
  padding: 3.5rem 0;
}

.invite h2 { color: var(--cream); }

.invite p {
  margin-top: 1rem;
  max-width: 52ch;
  font-size: 1.05rem;
  color: var(--cream-warm);
}

.invite-details {
  margin-top: 2rem;
  display: grid;
  gap: 0.6rem;
  font-size: 1rem;
}

/* The phone, WhatsApp and email links matter most to this audience and were
   the smallest targets on the site. They carry the full 44px. */
.invite-details a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--cream);
  text-decoration: underline;
  text-decoration-color: var(--gold);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
}

.invite-details a:hover { color: var(--marigold); text-decoration-color: var(--marigold); }

.invite .btn-row { margin-top: 2rem; }

.invite .btn-primary { background: var(--cream); color: var(--maroon); }
.invite .btn-primary:hover { background: var(--marigold); color: var(--maroon-deep); }
.invite .btn-ghost { color: var(--cream); border-color: var(--gold); }
.invite .btn-ghost:hover { background: var(--cream); color: var(--maroon); }

/* ---------- Footer ---------- */

/* Slim — under 200px on desktop. No navigation column, and no address, phone
   or email: those live on the contact page. Only the mark, one short line,
   one link and the copyright. The mark is the logo without the tagline
   (logo-180), on a plain cream circle that sits just outside it — no border,
   no square box, no shadow. It is the only brand element down here and it
   reads at 96px; the padding gives up what that costs, so the bar still
   measures under 200px on desktop. */

.site-footer {
  background: var(--maroon-deep);
  color: var(--cream-warm);
  padding: 1.75rem 0 1.5rem;
}

.footer-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 1rem;
}

/* No disc. The mark is logo-mark, which carries its own ring, so the cream
   circle behind it read as a white badge stuck onto the maroon rather than as
   part of the mark. Dropping it costs the ring, which measures 1.56:1 against
   the footer and effectively disappears; what survives is the white bull at
   16:1 and the gold at 9.8:1, which is the readable part of the mark anyway
   and is why it can run this large without the bar growing. */
.footer-mark { flex: none; display: flex; }

.footer-mark img { height: 96px; width: auto; }

.footer-line {
  font-size: 1rem;
  color: var(--cream-warm);
}

.footer-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 1rem;
  font-weight: 500;
  color: var(--cream);
  text-decoration: underline;
  text-decoration-color: var(--gold);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35em;
  transition: color 0.2s ease, text-decoration-color 0.2s ease;
}

.footer-link:hover { color: var(--marigold); text-decoration-color: var(--marigold); }

.footer-copyright {
  width: 100%;
  padding-top: 1rem;
  border-top: 1px solid rgba(240, 224, 208, 0.15);
  font-size: 1rem;
  color: var(--cream-warm);
  opacity: 0.75;
}

/* The tagline, once on the whole site, on the contact page. It is set as live
   text under the plain mark rather than drawn: the lockup artwork reads only
   "what you truly desire", which is not the tagline, so logo-tagline.png is
   used nowhere until it is redrawn. Live text also means the six words can
   never drift from the ones the client fixed. Nothing is drawn around the
   mark. */
.tagline-block { margin-top: 2.5rem; }

.tagline-block img { width: min(112px, 32vw); height: auto; }

.tagline-text {
  margin-top: 0.9rem;
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--maroon);
}

/* ---------- Breakpoints ---------- */

@media (min-width: 768px) {
  .site-header .container { height: 120px; }
  .brand img { height: 88px; }
  .brand-name { font-size: 1.75rem; }

  .section { padding: 4.25rem 0; }

  /* The numeral moves beside the stage rather than above it. */
  .stage {
    display: grid;
    grid-template-columns: 4.5rem minmax(0, 1fr);
    gap: 0 2rem;
    padding: 2.5rem 0;
  }

  .stage-num { font-size: 3.1rem; margin-bottom: 0; }

  /* Tablet: two by four. */
  .commitment-grid { grid-template-columns: repeat(2, 1fr); gap: 1.5rem 1.75rem; }

  /* Five never tiles into two columns without a ragged last row, so the last
     card takes the full width instead. */
  .commitment-grid--five > :last-child { grid-column: span 2; }

  .stat-grid { grid-template-columns: repeat(4, 1fr); }

  .who-what-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 3rem;
    align-items: start;
  }

  .director-grid {
    grid-template-columns: repeat(2, minmax(0, 220px));
    justify-content: center;
  }

  .upcoming-panel { padding: 3.5rem; }

  .upcoming-media { margin-top: 0; }

  .upcoming-facts { grid-template-columns: repeat(3, 1fr); gap: 2rem; }

  /* The 96px mark spends most of the bar's height, so the padding gives way
     to keep it under the 200px in 10.5. Measured: 192px at 1440. */
  .site-footer { padding: 1.25rem 0 1rem; }

  .footer-inner {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    text-align: left;
    gap: 1.25rem 1.5rem;
  }

  .footer-line { flex: 1; }

  .footer-copyright { flex-basis: 100%; padding-top: 0.9rem; }
}

/* The menu button stays until 900px. A tablet gets the taller bar and larger
   mark from 768px, but at that width the name and six links sat 14px apart,
   and larger text would have run them together. */
@media (min-width: 900px) {
  .nav-toggle { display: none; }

  .site-nav {
    position: static;
    display: block;
    background: none;
    border-bottom: none;
    box-shadow: none;
  }

  .site-nav ul {
    flex-direction: row;
    padding: 0;
    gap: 2rem;
  }

  .site-nav a {
    position: relative;
    min-height: auto;
    font-size: 0.95rem;
    padding-bottom: 0.2rem;
    border-bottom: 2px solid transparent;
  }

  /* The links read at their natural height, so the current-page rule sits just
     under the word, but each takes taps across a full 44px: a transparent layer
     centred on the link, clear of its neighbours in the 2rem gaps. */
  .site-nav a::after {
    content: "";
    position: absolute;
    left: -0.5rem;
    right: -0.5rem;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  .site-nav a[aria-current="page"] { border-color: var(--gold); }
}

/* The emblem only moves beside the headline once there is room for both at
   full weight. Below this it sits under the text, which is the phone rule. */
@media (min-width: 900px) {
  .hero { padding: 3rem 0 3.5rem; }

  .hero-grid {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 3.5rem;
  }

  .hero-copy h1 { font-size: clamp(2.4rem, 4vw, 3.5rem); }

  .hero-art img { width: clamp(380px, 29vw, 415px); }

  /* Inner pages: the same balance, less vertical padding, smaller emblem. */
  .hero--compact { padding: 2.25rem 0 2.75rem; }

  .hero--compact .hero-grid { max-width: 960px; gap: 3rem; }

  .hero--compact .hero-copy h1 { font-size: clamp(2.1rem, 3.4vw, 2.9rem); }

  .hero--compact .hero-art img { width: clamp(260px, 22vw, 310px); }

  .hero--compact .hero-art img.hero-logo { width: clamp(382px, 32vw, 455px); }

  /* Contact carries the shortest headline block on the site — an eyebrow, a
     three-word heading and one line. At the 260px floor in section 9.2 the
     emblem outweighed it badly, so it sits below that floor here rather than
     the copy being padded out to meet it. */
  .hero--slim .hero-art img { width: 200px; }

  /* 200px was measured on the emblem. The logo needs 290px to put the same
     amount of ink in that slot, so the exception holds at the size it always
     meant rather than at the number it was written as. */
  .hero--slim .hero-art img.hero-logo { width: 290px; }

  /* Upcoming is the one hero carrying two paragraphs. Held to the narrow
     measure the column runs far taller than the emblem, so it takes the full
     column and the emblem goes to the top of the inner-page range. */
  .hero--prose .hero-copy p { max-width: none; }

  .hero--prose .hero-art img { width: clamp(280px, 24vw, 320px); }

  .hero--prose .hero-art img.hero-logo { width: clamp(410px, 35vw, 469px); }
}

/* Desktop: four by two. The eight fill both rows exactly. */
@media (min-width: 1024px) {
  .commitment-grid { grid-template-columns: repeat(4, 1fr); }

  /* Five in four columns would leave a ragged row, and five narrow columns
     leave the short cards mostly empty. The fifth takes the full width
     instead — it carries the longest line, which needs the room. */
  .commitment-grid--five > :last-child { grid-column: span 4; }
}

@media (min-width: 1100px) {
  .suburb-card { padding-top: 1.4rem; padding-bottom: 1.4rem; }
}
