/* ============================================================================
   Urbanrise Begur Koppa Road — "Canopy"
   First site for Urbanrise, so the theme is authored from scratch.

   The system: light and landscape-led. The page alternates between
   edge-to-edge photographic plates and a narrow 900px reading column — the
   rhythm itself is the signature, and it suits a 20-acre township whose
   selling point is open ground. Soft geometry throughout (18px on imagery,
   pill buttons), no shadows anywhere: depth comes from tinted blocks.

   Colour discipline: the nine canonical brand tokens from
   builders/urbanrise/urbanrise.json plus the two form state tokens.
   ⚠ --brand-secondary (lime #94BB44 — 2.23:1 on white) and --brand-tertiary
   (blue #418FCD — 3.48:1 on white) are DECORATIVE ONLY. Never use either for
   body text or for a control's label. Deep green carries every text role.
   ========================================================================== */

:root {
  /* The nine canonical brand tokens */
  --brand-primary:   #166535;
  --brand-secondary: #94BB44;
  --brand-tertiary:  #418FCD;
  --dark-primary:    #171717;
  --dark-secondary:  #4a4a4a;
  --dark-tertiary:   #d8d8d8;
  --light-primary:   #f8f8f8;
  --light-secondary: #ffffff;
  --light-tertiary:  #eeeeee;

  /* Form state */
  --state-success: #166534;
  --state-error:   #991b1b;

  /* Semantic aliases */
  --ink:        var(--dark-primary);
  --ink-soft:   var(--dark-secondary);
  --bg:         var(--light-secondary);
  --wash:       #f2f7f2;                /* pale green field */
  --wash-deep:  #e6efe6;
  --line:       #dfe7df;
  --green:      var(--brand-primary);
  --green-deep: #0f4826;                /* hover / pressed, 10.6:1 on white */
  --lime:       var(--brand-secondary);  /* decorative marks only */
  --canopy:     #0d2a18;                /* the dark band ground */

  /* Ink tokens for inverted ground. Declared as properties so no later
     context rule can repaint a :hover into invisibility. */
  --on-green:   var(--light-secondary);
  --on-canopy:  var(--light-secondary);
  --on-canopy-soft: #c5d3c9;             /* 8.9:1 on --canopy */

  --shell:   1280px;
  --column:  900px;
  --gutter:  clamp(1.25rem, 5vw, 2.75rem);
  --rhythm:  clamp(3.25rem, 7vw, 6rem);
  --navh:    72px;
  --radius:  18px;
  --pill:    999px;

  --sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* ------------------------------------------------------------------ reset */

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

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

body {
  font-family: var(--sans);
  font-size: 1.02rem;
  line-height: 1.72;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

img, picture, svg, video { display: block; max-width: 100%; }
img { height: auto; background-color: var(--wash); }

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

a { color: var(--green); text-underline-offset: 2px; }
a:hover { color: var(--green-deep); }

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

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--green); color: var(--on-green);
  padding: 0.75rem 1.25rem; border-radius: 0 0 var(--radius) 0; text-decoration: none;
}
.skip:focus { left: 0; }

/* ------------------------------------------------------------------ type */

h1, h2, h3, h4 {
  font-weight: 650;
  line-height: 1.18;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: balance;
}
h1 { font-size: clamp(2.2rem, 5vw, 3.5rem); line-height: 1.1; }
h2 { font-size: clamp(1.7rem, 3.2vw, 2.5rem); font-weight: 600; }
h3 { font-size: clamp(1.12rem, 1.7vw, 1.35rem); font-weight: 650; line-height: 1.35; }
h4 { font-size: 1.02rem; }

.copy > * + *, .prose > * + *, .article-body > * + * { margin-top: 1.25rem; }
.copy h3, .prose h3, .article-body h3 { margin-top: 2.5rem; }
.copy ul, .copy ol, .prose ul, .prose ol, .article-body ul, .article-body ol { padding-left: 1.2rem; }
.copy li + li, .prose li + li, .article-body li + li { margin-top: 0.45rem; }
.copy strong, .prose strong, .article-body strong { font-weight: 650; }

blockquote {
  border-left: 3px solid var(--lime);
  padding-left: 1.25rem;
  color: var(--ink-soft);
}

.page-updated { font-size: 0.86rem; color: var(--ink-soft); }
.page-updated time { font-weight: 650; }

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

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

/* The reading column. Everything textual sits inside this measure. */
.column { width: 100%; max-width: var(--column); margin-inline: auto; padding-inline: var(--gutter); }

.scape { padding-block: var(--rhythm); background: var(--bg); }
.scape--wash { background: var(--wash); }
.scape--canopy { background: var(--canopy); color: var(--on-canopy); }
.scape--canopy h2, .scape--canopy h3 { color: var(--on-canopy); }
.scape--canopy p { color: var(--on-canopy-soft); }
/* A plate sits flush against the top of its section, so kill the padding
   above it and let the plate itself provide the break. */
.scape--plated { padding-top: 0; }

/* The plate: an edge-to-edge photographic band. No radius here on purpose —
   the contrast between a bleeding image and a 900px measure is the theme. */
.plate { position: relative; width: 100%; overflow: hidden; background: var(--wash-deep); }
.plate img { width: 100%; height: clamp(220px, 34vw, 420px); object-fit: cover; }
.plate--tall img { height: clamp(280px, 46vw, 560px); }
.plate__cap {
  position: absolute; left: var(--gutter); bottom: var(--gutter);
  background: var(--bg); color: var(--ink);
  border-radius: var(--radius);
  padding: 0.7rem 1.1rem;
  font-size: 0.82rem; font-weight: 600;
  max-width: calc(100% - (var(--gutter) * 2));
}

/* ------------------------------------------------------------------- nav */

.topbar {
  position: sticky; top: 0; z-index: 100;
  height: var(--navh);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.topbar__in { height: 100%; display: flex; align-items: center; gap: 1.25rem; }

.lockup { display: flex; align-items: center; gap: 0.7rem; text-decoration: none; color: inherit; margin-right: auto; }
.lockup__mark { width: 40px; height: 40px; object-fit: contain; background: none; }
.lockup__text { display: flex; flex-direction: column; line-height: 1.15; }
/* Keep these two on separate lines with real whitespace between them so the
   accessible name reads "Urbanrise Begur Koppa Road", not one run-on word. */
.lockup__dev { font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 650; color: var(--green); }
.lockup__proj { font-size: 0.98rem; font-weight: 650; letter-spacing: -0.02em; }

.menu { display: none; list-style: none; padding: 0; margin: 0; gap: 1.35rem; }
.menu a { color: var(--ink); text-decoration: none; font-size: 0.92rem; font-weight: 500; }
.menu a:hover, .menu a.is-active { color: var(--green); }

.topbar__cta {
  display: none;
  background: var(--green); color: var(--on-green);
  border-radius: var(--pill);
  text-decoration: none; font-size: 0.86rem; font-weight: 650;
  padding: 0.55rem 1.2rem;
  transition: background 180ms ease;
}
.topbar__cta:hover { background: var(--green-deep); color: var(--on-green); }

.burger { width: 44px; height: 44px; margin-left: auto; display: grid; place-content: center; gap: 5px; background: none; border: 0; color: var(--ink); }
.burger span { display: block; width: 22px; height: 2px; background: currentColor; transition: transform 200ms ease, opacity 200ms ease; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.sheet {
  position: fixed; inset: var(--navh) 0 auto 0; z-index: 99;
  background: var(--bg); border-bottom: 1px solid var(--line);
  padding: 0.5rem var(--gutter) 1.5rem;
  display: none; flex-direction: column;
}
.sheet.is-open { display: flex; }
.sheet a { color: var(--ink); text-decoration: none; padding: 0.85rem 0; border-bottom: 1px solid var(--line); font-weight: 550; }
.sheet a:hover { color: var(--green); }
.sheet .pill { margin-top: 1.15rem; border-bottom: 0; }

/* --------------------------------------------------------------- buttons */

.pill {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0.8rem 1.6rem; border-radius: var(--pill);
  font-size: 0.92rem; font-weight: 650;
  text-decoration: none; border: 1px solid transparent;
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
}
.pill--solid { background: var(--green); color: var(--on-green); }
.pill--solid:hover { background: var(--green-deep); color: var(--on-green); }

.pill--outline { background: transparent; color: var(--green); border-color: var(--green); }
.pill--outline:hover { background: var(--green); color: var(--on-green); }

/* On the canopy band an outline button in deep green would be green-on-near-
   black. It gets its own ink instead. */
.scape--canopy .pill--outline { color: var(--on-canopy); border-color: var(--on-canopy); }
.scape--canopy .pill--outline:hover { background: var(--on-canopy); color: var(--canopy); }

.pill--light { background: var(--bg); color: var(--green); }
.pill--light:hover { background: var(--wash-deep); color: var(--green-deep); }

.actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 2rem; }
.actions--center { justify-content: center; }

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

/* One composition at every width: the plate fills the section and the card
   sits on it, inset far enough that the photograph reads around it. Only the
   inset changes across breakpoints. */
.hero {
  position: relative;
  background: var(--canopy);
  display: grid;
  align-items: center;
  overflow: hidden;
}
.hero__frame,
.hero__card { grid-area: 1 / 1; }
.hero__frame { position: relative; overflow: hidden; align-self: stretch; }
/* A stretched grid item is not a definite height to resolve a percentage
   against, so `height: 100%` here would fall back to auto and the 1200²
   source would paint at its intrinsic square, setting the row. Out of flow
   instead — the frame is already relative and clipped. */
.hero__frame img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero__veil {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(13, 42, 24, 0.34) 0%, rgba(13, 42, 24, 0.12) 40%, rgba(13, 42, 24, 0.62) 100%);
}
.hero__card {
  position: relative;
  /* Top inset is the photograph's share of the section; phones get the most
     of it, since their card is the tallest relative to the screen. */
  margin: clamp(170px, 30svh, 260px) auto clamp(1.25rem, 3svh, 3rem);
  width: min(var(--column), calc(100% - (var(--gutter) * 2)));
  max-width: none;
  background: var(--bg);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  z-index: 2;
}
.hero__kicker {
  display: block; font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase;
  font-weight: 650; color: var(--green); margin-bottom: 0.9rem;
}
.hero__card h1 em { display: block; font-style: normal; font-weight: 400; font-size: clamp(1rem, 1.8vw, 1.25rem); line-height: 1.45; margin-top: 0.75rem; color: var(--ink-soft); }
.hero__card .page-updated { margin-top: 0.9rem; }
.hero__lead { margin-top: 1.1rem; color: var(--ink-soft); }
.hero__stats { list-style: none; padding: 0; margin: 1.75rem 0 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
.hstat { border-left: 3px solid var(--lime); padding-left: 0.85rem; }
.hstat__n { font-size: clamp(1.2rem, 2.2vw, 1.6rem); font-weight: 650; letter-spacing: -0.02em; line-height: 1.15; }
.hstat__l { font-size: 0.76rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); margin-top: 0.2rem; }

/* Subpage head — same idiom as the hero, one notch quieter. */
.page-plate {
  position: relative;
  background: var(--canopy);
  display: grid;
  align-items: center;
  overflow: hidden;
}
.page-plate__media,
.page-plate__card { grid-area: 1 / 1; }
.page-plate__media { position: relative; overflow: hidden; align-self: stretch; }
.page-plate__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.page-plate__card {
  position: relative;
  margin: clamp(120px, 22svh, 200px) auto clamp(1.25rem, 3svh, 3rem);
  width: min(var(--column), calc(100% - (var(--gutter) * 2)));
  max-width: none;
  background: var(--bg); border-radius: var(--radius);
  padding: clamp(1.35rem, 3.5vw, 2.25rem); z-index: 2;
}
.page-plate__lead { margin-top: 1rem; color: var(--ink-soft); }
.crumb { font-size: 0.84rem; color: var(--ink-soft); margin-bottom: 0.9rem; }
.crumb a { color: var(--ink-soft); }
.crumb a:hover { color: var(--green); }

/* ------------------------------------------------------------- lead-ins */

.lead-in { margin-bottom: clamp(1.5rem, 3vw, 2.25rem); }
.lead-in__kicker { display: block; font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 650; color: var(--green); margin-bottom: 0.75rem; }
.scape--canopy .lead-in__kicker { color: var(--lime); }
.lead-in__rule { width: 56px; height: 3px; background: var(--lime); border-radius: var(--pill); margin-top: 1rem; }
.lead-in__sub { margin-top: 1.1rem; color: var(--ink-soft); }
.scape--canopy .lead-in__sub { color: var(--on-canopy-soft); }

/* ------------------------------------------------------------ key facts */

.keys { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.75rem; margin-top: 2rem; }
.key { background: var(--wash); border-radius: var(--radius); padding: 1rem 1.15rem; }
.scape--wash .key { background: var(--bg); }
.key__k { font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--green); font-weight: 650; margin-bottom: 0.25rem; }
.key__v { font-weight: 600; }

/* ---------------------------------------------------------------- tiles */

.tiles { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.tile { background: var(--wash); border-radius: var(--radius); padding: clamp(1.25rem, 2.5vw, 1.75rem); }
.scape--wash .tile { background: var(--bg); }
.scape--canopy .tile { background: rgba(255, 255, 255, 0.07); }
.tile h3 { margin-bottom: 0.6rem; }
.tile p { font-size: 0.96rem; color: var(--ink-soft); }
.scape--canopy .tile p { color: var(--on-canopy-soft); }
.tile > * + * { margin-top: 0.85rem; }

/* --------------------------------------------------------------- tables */

.table-wrap { overflow-x: auto; margin-block: 1.5rem; border-radius: var(--radius); border: 1px solid var(--line); }
.ptable { width: 100%; border-collapse: collapse; font-size: 0.94rem; min-width: 34rem; }
.ptable th, .ptable td { padding: 0.8rem 1rem; text-align: left; border-bottom: 1px solid var(--line); vertical-align: top; }
.ptable th { background: var(--wash); color: var(--green); font-size: 0.74rem; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 700; }
.ptable tbody tr:last-child td { border-bottom: 0; }

/* ----------------------------------------------------------- floor plans */

.plan-strip { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.plan-card { background: var(--wash); border-radius: var(--radius); overflow: hidden; }
.scape--wash .plan-card { background: var(--bg); }
.plan-card img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.plan-card__meta { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; padding: 0.9rem 1.15rem 1.2rem; }
.plan-card__name { font-weight: 650; }
.plan-card__area { font-size: 0.86rem; color: var(--ink-soft); }

/* -------------------------------------------------------------- gallery */

.shots { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.shot { margin: 0; background: var(--wash); border-radius: var(--radius); overflow: hidden; }
.scape--wash .shot { background: var(--bg); }
.shot img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.shot figcaption { padding: 0.9rem 1.15rem 1.2rem; font-size: 0.9rem; color: var(--ink-soft); }
.shot figcaption strong { display: block; color: var(--green); font-weight: 700; font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 0.3rem; }

/* ------------------------------------------------------------ amenities */

.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; padding: 0; margin-top: 1.5rem; }
.chip { background: var(--wash); border-radius: var(--pill); padding: 0.5rem 1rem; font-size: 0.88rem; }
.scape--wash .chip { background: var(--bg); }

/* ---------------------------------------------------------------- price */

.price-stack { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.price-card { background: var(--wash); border-radius: var(--radius); padding: 1.5rem 1.4rem; display: flex; flex-direction: column; gap: 0.4rem; }
.scape--wash .price-card { background: var(--bg); }
/* `.scape--wash .price-card` (0,2,0) outranks a bare `.price-card--lead`
   (0,1,0), so on a wash band the featured card kept its white text and lost
   its green fill — white on white, 1.00:1, the entire card invisible. The
   modifier has to be stated at matching specificity for every band it can
   appear on. */
.price-card--lead,
.scape--wash .price-card--lead,
.scape--canopy .price-card--lead { background: var(--green); color: var(--on-green); }
.price-card--lead .price-card__area,
.price-card--lead .price-card__note { color: var(--on-green); opacity: 0.9; }
.price-card--lead .pill--outline { color: var(--on-green); border-color: var(--on-green); }
.price-card--lead .pill--outline:hover { background: var(--on-green); color: var(--green); }
.price-card__cfg { font-size: 1.3rem; font-weight: 650; letter-spacing: -0.02em; }
.price-card__area { font-size: 0.86rem; color: var(--ink-soft); }
.price-card__amt { font-weight: 650; margin-top: 0.3rem; }
.price-card__note { font-size: 0.74rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--green); min-height: 1.1em; }
.price-card .pill { margin-top: auto; align-self: flex-start; }

/* ------------------------------------------------------------------ map */

.mapcard { display: block; position: relative; text-decoration: none; border-radius: var(--radius); overflow: hidden; }
.mapcard img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.mapcard__tag { position: absolute; left: 1rem; bottom: 1rem; background: var(--green); color: var(--on-green); border-radius: var(--pill); font-size: 0.8rem; font-weight: 650; padding: 0.55rem 1.05rem; }
.mapcard:hover .mapcard__tag { background: var(--green-deep); color: var(--on-green); }

.mp-img { width: 100%; border-radius: var(--radius); }

/* ------------------------------------------------------------------ faq */

.faq-list { display: grid; gap: 0.6rem; }
.faq-item { background: var(--wash); border-radius: var(--radius); overflow: hidden; }
.scape--wash .faq-item { background: var(--bg); }
.faq-q {
  width: 100%; display: flex; align-items: flex-start; justify-content: space-between; gap: 1.15rem;
  background: none; border: 0; padding: 1.05rem 1.25rem;
  text-align: left; font-size: 1rem; font-weight: 600; color: var(--ink); line-height: 1.45;
}
.faq-q:hover { color: var(--green); }
.faq-icon { flex: 0 0 auto; font-size: 1.25rem; line-height: 1; color: var(--green); transition: transform 200ms ease; }
.faq-item.is-open .faq-icon { transform: rotate(45deg); }
/* max-height, not grid-template-rows: 0fr -> 1fr — the latter can leave the
   panel pinned shut while the class and aria-expanded both flip correctly. */
.faq-a { max-height: 0; overflow: hidden; transition: max-height 260ms ease; }
.faq-item.is-open .faq-a { max-height: 240rem; }
.faq-a > div { padding: 0 1.25rem 1.25rem; color: var(--ink-soft); }
.faq-a p + p { margin-top: 0.9rem; }

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

.enquiry { background: var(--wash); border-radius: var(--radius); padding: clamp(1.5rem, 3.5vw, 2.5rem); }
.scape--wash .enquiry { background: var(--bg); }
.scape--canopy .enquiry { background: var(--bg); color: var(--ink); }
.scape--canopy .enquiry h2, .scape--canopy .enquiry > p { color: var(--ink); }
.enquiry h2 { font-size: clamp(1.3rem, 2.2vw, 1.7rem); }
.enquiry > p { margin-top: 0.6rem; color: var(--ink-soft); font-size: 0.96rem; }

.form-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.85rem; margin-top: 1.4rem; }
.fg { display: flex; flex-direction: column; gap: 0.3rem; }
.fg--full { grid-column: 1 / -1; }
.form-grid input, .form-grid textarea {
  width: 100%; padding: 0.85rem 1rem;
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: 12px;
}
.form-grid input::placeholder, .form-grid textarea::placeholder { color: var(--ink-soft); opacity: 1; }
.form-grid input:focus, .form-grid textarea:focus { outline: 2px solid var(--green); outline-offset: 0; border-color: var(--green); }
.form-grid button[type="submit"] { grid-column: 1 / -1; justify-content: center; }

.field-error { font-size: 0.82rem; color: var(--state-error); min-height: 1em; }
.form-status { grid-column: 1 / -1; padding: 0.75rem 1rem; font-size: 0.9rem; border-radius: 12px; border: 1px solid var(--line); }
.form-status.is-success { color: var(--state-success); border-color: var(--state-success); }
.form-status.is-error { color: var(--state-error); border-color: var(--state-error); }
.form-note { margin-top: 0.9rem; font-size: 0.82rem; color: var(--ink-soft); }
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

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

.footer { background: var(--canopy); color: var(--on-canopy-soft); padding-block: clamp(3rem, 6vw, 4.5rem) 2rem; }
.footer__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
.footer__brand a { text-decoration: none; color: var(--on-canopy); display: inline-flex; flex-direction: column; line-height: 1.18; }
.footer__dev { font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 650; color: var(--lime); }
.footer__proj { font-size: 1.1rem; font-weight: 650; letter-spacing: -0.02em; }
.footer p { font-size: 0.92rem; margin-top: 1rem; max-width: 46ch; }
.footer__disc { font-size: 0.8rem; opacity: 0.86; }
.footer__disc strong { color: var(--on-canopy); }
.footer__col { min-width: 0; }
.footer h2 { font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--on-canopy); font-weight: 650; }
.footer__links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem 1.5rem; margin-top: 1rem; }
.footer__links a, .footer__bottom a { color: var(--on-canopy-soft); text-decoration: none; font-size: 0.92rem; }
.footer__links a:hover, .footer__bottom a:hover { color: var(--on-canopy); text-decoration: underline; }
.footer p a { color: var(--on-canopy); text-decoration: underline; text-underline-offset: 2px; }
.footer__bottom {
  margin-top: 2.75rem; padding-top: 1.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  display: flex; flex-direction: column; gap: 0.75rem; font-size: 0.84rem;
}
.footer__bottom p { margin-top: 0; }
.footer__bottom-links { display: flex; gap: 1.25rem; }

.to-top {
  position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 90;
  width: 46px; height: 46px; border-radius: var(--pill);
  background: var(--green); color: var(--on-green);
  border: 0; font-size: 1.1rem; line-height: 1;
  opacity: 0; pointer-events: none; transition: opacity 200ms ease;
}
.to-top.is-visible { opacity: 1; pointer-events: auto; }
.to-top:hover { background: var(--green-deep); color: var(--on-green); }

/* ------------------------------------------------------------------ 404 */

.notfound { padding-top: clamp(3rem, 7vw, 5rem); }

/* --------------------------------------------------------- breakpoints */

@media (min-width: 640px) {
  .keys { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .plan-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .shots { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .price-stack { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero__stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .footer__bottom { flex-direction: row; align-items: center; justify-content: space-between; }
}

@media (min-width: 1025px) {
  .menu { display: flex; }
  .topbar__cta { display: inline-flex; }
  .burger { display: none; }
  .sheet { display: none !important; }

  .tiles--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .plan-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .shots { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .price-stack { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .keys { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .footer__grid { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 4rem; }

}

/* Overlay heads — tablet up. Below 641 the plate and the card stack instead;
   there is no width to hold both. */
@media (min-width: 641px) {

  /* Hero: one screen, not two.
     Stacked — a 74vh plate with the card hanging 5.5rem below it — the section
     measured 1,232px against a 980px viewport, so the first thing a visitor
     saw was a photograph with the project name below the fold. Overlay the two
     instead: both children share one grid cell, the plate stretches to the
     section and the card sits in it, left of centre so the tower stays visible.
     min-height, not height, so a short window still gets the whole card. */
  .hero {
    display: grid;
    /* Capped here; desktop below spends the whole window. A tablet held in
       portrait has 950px of viewport and a 580px card — a full-height hero
       there is mostly empty photograph. */
    min-height: min(calc(100svh - var(--navh)), 40rem);
    align-items: center;
  }
  .hero__frame,
  .hero__card { grid-area: 1 / 1; }
  .hero__frame { align-self: stretch; }
  /* A stretched grid item is not a definite height to resolve a percentage
     against, so `height: 100%` on the image fell back to auto and the 1200²
     source painted at its intrinsic square — which then set the row and made
     the hero TALLER than before. Take the image out of flow instead: the
     frame is already position:relative and overflow:hidden. */
  .hero__frame img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }

  .hero__card {
    /* Same inset-band trick as the subpage plate, so the photograph reads
       above and below the card rather than only beside it. Desktop overrides
       this to sit on the shell's left edge, where there is width for it. */
    margin: clamp(1.25rem, 3svh, 3rem) auto;
    width: min(var(--column), calc(100% - (var(--gutter) * 2)));
    max-width: none;
    padding: clamp(1.75rem, 2.4vw, 2.25rem);
  }
  /* The card is now the thing that sets the hero's height, so its internal
     rhythm is what decides whether the section clears a 800px-tall window.
     Every step below is tightened just enough to land under it — nothing is
     hidden, clamped or moved out of the hero. */
  .hero__card h1 { font-size: clamp(2rem, 3.2vw, 2.7rem); }
  .hero__card h1 em { margin-top: 0.5rem; }
  .hero__card .page-updated { margin-top: 0.7rem; }
  .hero__lead { margin-top: 0.9rem; font-size: 0.97rem; line-height: 1.62; }
  .hero__stats { margin-top: 1.35rem; gap: 0.8rem 1rem; }
  .hero .actions { margin-top: 1.35rem; }

  /* Subpage heads take the same treatment, one notch quieter — the card stays
     on the reading column and centred rather than moving to the shell's left
     edge, so a subpage still reads as a subpage. Overlaying is worth more here
     than on the homepage: the plate was adding its full 340px to the card's
     height, which put /reviews and /gallery over the fold before their first
     section. Same absolute-image trick, for the same percentage-height reason. */
  .page-plate {
    display: grid;
    min-height: clamp(340px, 44svh, 460px);
    align-items: center;
  }
  .page-plate__media,
  .page-plate__card { grid-area: 1 / 1; }
  .page-plate__media { align-self: stretch; }
  .page-plate__media img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }
  .page-plate__card {
    /* Vertical margin, not padding on the plate: the media is a stretched grid
       item with no margin of its own, so it fills the whole row while the card
       is inset — the photograph reads above and below it rather than as two
       slivers down the sides. Scaled in svh so a short window spends less of
       itself on the band and the plate still clears the fold. */
    margin: clamp(1.25rem, 3svh, 3rem) auto;
    width: min(var(--column), calc(100% - (var(--gutter) * 2)));
    max-width: none;
  }
  /* Same tightening the hero card got, for the same reason: /reviews opens on
     a full editorial note, and at 1280x720 the band plus that lead was 38px
     over the fold. Set here rather than trimming the paragraph. */
  .page-plate__lead { margin-top: 0.85rem; font-size: 0.97rem; line-height: 1.62; }
}

/* Desktop refinements on top of the shared overlay. Declared after it so the
   two do not fight at equal specificity — the wider layout must win. */
@media (min-width: 1025px) {
  /* The whole window is worth spending on the homepage hero. */
  .hero { min-height: calc(100svh - var(--navh)); }

  /* Sideways now that the card covers the left: keep the right edge readable
     and stop the plate washing out behind the white block. */
  .hero__veil {
    background: linear-gradient(90deg, rgba(13, 42, 24, 0.52) 0%, rgba(13, 42, 24, 0.22) 58%, rgba(13, 42, 24, 0.48) 100%);
  }
  /* Off the centre line and onto the shell's left edge, so the tower reads
     down the right of the screen. Only worth doing where there is width to
     spare: centred below 1025, or the card swallows the photograph. */
  .hero__card {
    margin: 0;
    width: min(42rem, calc(100% - (var(--gutter) * 2)));
    justify-self: start;
    margin-inline-start: max(var(--gutter), calc((100% - var(--shell)) / 2 + var(--gutter)));
  }
  /* Four across in a 42rem card is a 7-character column; two rows read. */
  .hero__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Phone. Same composition as tablet, only tighter: the card is the tallest
   thing on the smallest screen, so it takes more of the section and the
   photograph reads as a band above it plus a margin around it. The type and
   the CTAs tighten so the card does not run away with the page. */
@media (max-width: 640px) {
  .hero__card { padding: 1.4rem; }
  .hero__card h1 { font-size: clamp(1.85rem, 7.5vw, 2.3rem); }
  .hero__lead { margin-top: 0.85rem; font-size: 0.96rem; line-height: 1.6; }
  .hero__stats { margin-top: 1.25rem; gap: 0.85rem; }
  .hero .actions { margin-top: 1.25rem; }
  .hero .actions .pill { flex: 1 1 100%; justify-content: center; }

  .page-plate__card { padding: 1.4rem; }
  .page-plate__lead { margin-top: 0.85rem; font-size: 0.96rem; line-height: 1.6; }
}

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


/* ==== contact-modal (fleet rollout — see tooling/add-contact-modal.mjs) ==== */
.cm-modal {
    /* Re-assert the UA's dialog centering: universal "* { margin: 0 }" resets
       (sattva/purva families and others) strip it, pinning the dialog top-left. */
    margin: auto;
    width: min(100%, 28rem);
    padding: 1rem;
    border: 0;
    background: transparent;
    overscroll-behavior: contain;
    --cm-accent: var(--brand-primary, #166535);
    --cm-ink: #ffffff;
}

/* Browsers without <dialog> ignore [open] and would render the form inline. */
.cm-modal:not([open]) {
    display: none;
}

/* Literal scrim: ::backdrop cannot reliably see page custom properties. */
.cm-modal::backdrop {
    background: rgba(15, 23, 42, 0.6);
}

.cm-modal__panel {
    position: relative;
    padding: 1.5rem;
    border-radius: 0.75rem;
    background: #ffffff;
    color: #1f2937;
    font-family: inherit;
    box-shadow: 0 20px 25px rgba(15, 23, 42, 0.15);
}

.cm-modal__title {
    margin: 0 0 1.25rem;
    padding-right: 2.5rem;
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1.3;
    color: #1f2937;
}

.cm-modal__close {
    position: absolute;
    top: 0.5rem;
    right: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 0;
    border-radius: 0.25rem;
    background: transparent;
    color: #475569;
    cursor: pointer;
    font-size: 1.5rem;
    line-height: 1;
}

.cm-modal__close:hover {
    background: #f1f5f9;
    color: #0f172a;
}

.cm-modal__close:focus-visible {
    outline: 2px solid var(--cm-accent);
    outline-offset: 2px;
}

.cm-form {
    display: grid;
    gap: 1rem;
}

.cm-form__field {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    text-align: left;
}

.cm-form__field label {
    font-size: 0.85rem;
    font-weight: 600;
    color: #1f2937;
}

/* Form controls don't inherit fonts — font: inherit closes the gap. */
.cm-form input,
.cm-form textarea {
    width: 100%;
    min-width: 0;
    font: inherit;
    color: #1f2937;
    background: #ffffff;
    border: 1px solid #cbd5e1;
    border-radius: 6px;
    padding: 0.6rem 0.75rem;
}

.cm-form input:focus-visible,
.cm-form textarea:focus-visible {
    outline: 2px solid var(--cm-accent);
    outline-offset: 1px;
}

.cm-form textarea {
    min-height: 5.5rem;
    resize: vertical;
}

.cm-form__submit {
    border: 0;
    border-radius: 6px;
    background: var(--cm-accent);
    color: var(--cm-ink);
    cursor: pointer;
    font: inherit;
    font-weight: 600;
    padding: 0.75rem 1.5rem;
}

.cm-form__submit:hover {
    opacity: 0.92;
}

.cm-form__submit:focus-visible {
    outline: 2px solid #1f2937;
    outline-offset: 2px;
}

.cm-form__hint {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.55;
    color: #64748b;
}

.cm-form__hint a {
    color: inherit;
    text-decoration: underline;
}

/* Class-based, so it cannot fight any inline body.style.overflow use. */
body.has-modal-open {
    overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
    .cm-modal[open] {
        animation: cm-modal-in 160ms ease-out;
    }

    .cm-modal[open]::backdrop {
        animation: cm-modal-backdrop-in 160ms ease-out;
    }
}

@keyframes cm-modal-in {
    from {
        opacity: 0;
        transform: translateY(0.5rem);
    }
}

@keyframes cm-modal-backdrop-in {
    from {
        opacity: 0;
    }
}
