/* ═══════════════════════════════════════════════════════════════════════════
   gf-stack.css — GF Real Estate Website visual system, "The Stack"
   Phase 3C Stage B. Loaded from the shared-shell head region, so it resolves
   after every page-level <style> block and is the site's last word on the
   shared visual system.

   Authority: docs/GF_VISUAL_IDENTITY_SYSTEM_REV4.md (PD-2026-08-01-REV4);
   Stage A concept package approved under the 2026-08-20 CONCEPT_PASS.

   Concept: the site is a stack of quiet, evenly-registered horizontal bands on
   a limestone ground. Midnight navy is structural ink, not page atmosphere.
   At most one navy band per page, never the last one. Separation comes from a
   hairline and proportion, never from decoration.

   Prohibited by REV4 and deliberately absent: gold/brass/bronze/champagne/
   metallic at any scale, decorative gradients, grain or noise texture,
   iconography, and motion without a functional reason.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* REV4 §2 approved palette */
  --gf-navy:        #0E1A2B;
  --gf-ink:         #111827;
  --gf-slate:       #243447;
  --gf-muted:       #5B6675;
  --gf-limestone:   #FAFAF7;
  --gf-white:       #FFFFFF;
  --gf-wash:        #F2F4F7;
  --gf-cool-wash:   #F6F7F8;
  --gf-thesis:      #EEF2FB;
  --gf-border:      #E1E5EA;
  --gf-blue:        #3261C2;
  --gf-blue-navy:   #5A82D6;
  --gf-fog:         #A7B7C7;
  --gf-success:     #2A6E3B;
  --gf-warning:     #B45309;
  --gf-error:       #9B2C2C;

  /* D1 — Website-local semantic colours. Pending cross-system canonicalization
     under GF-P011. brand/gf-design-tokens.json is deliberately unmodified. */
  --gf-on-navy:       #D6DEE7;   /* Website-scoped on-navy body text          */
  --gf-blue-pressed:  #274FA0;   /* Website-scoped GF-blue pressed state      */

  /* Structure */
  --gf-measure:     1240px;
  --gf-gutter:      40px;
  --gf-register:    76px;
  --gf-band-y:      104px;
  --gf-serif:       'Playfair Display', Georgia, 'Times New Roman', serif;
  --gf-sans:        'Montserrat', 'Helvetica Neue', Arial, sans-serif;
}

@media (max-width: 820px) {
  :root { --gf-gutter: 22px; --gf-register: 44px; --gf-band-y: 64px; }
}

/* ── Ground (D4) ─────────────────────────────────────────────────────────── */
html { background: var(--gf-limestone); }
body {
  background: var(--gf-limestone);
  color: var(--gf-ink);
  font-family: var(--gf-sans);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Nothing in a band may push the document sideways. */
img, svg, video, canvas, iframe, table { max-width: 100%; }

/* ── Band system ─────────────────────────────────────────────────────────── */
.gf-band { position: relative; }

/* The register: one hairline between consecutive bands, nothing more. */
.gf-band--light + .gf-band--light { border-top: 1px solid var(--gf-border); }

.gf-band--light { background: var(--gf-limestone); color: var(--gf-ink); }
.gf-band--light :is(h1, h2, h3, h4, h5, h6) { color: var(--gf-navy); }

/* The single controlled navy band. A mid-page thesis device, never terminal. */
.gf-band--navy { background: var(--gf-navy); color: var(--gf-on-navy); }
.gf-band--navy :is(h1, h2, h3, h4, h5, h6) { color: var(--gf-white); }
.gf-band--navy a:not([class]) { color: var(--gf-blue-navy); }

/* Photography-led bands keep their on-media ink. */
.gf-band--media :is(h1, h2, h3, h4, h5, h6) { color: var(--gf-white); }

/* ── Typography ──────────────────────────────────────────────────────────── */
:is(h1, h2, h3) { font-family: var(--gf-serif); font-weight: 400; letter-spacing: -0.015em; }
h1 { line-height: 1.08; }
h2 { line-height: 1.14; }
h3 { line-height: 1.22; }
:is(h4, h5, h6) { font-family: var(--gf-sans); font-weight: 600; letter-spacing: 0.02em; }

/* Display heads sit one step quieter than the previous build: composure, not
   scale, carries the premium read. */
.gf-band--light h1 { font-size: clamp(38px, 5.2vw, 66px); }
.gf-band--light h2 { font-size: clamp(27px, 3.1vw, 40px); }

/* Editorial article measure. */
.gf-band--light :is(article, .article-body) :is(p, li) {
  font-size: 17px;
  line-height: 1.75;
  max-width: 68ch;
  color: var(--gf-ink);
}
.gf-band--light figcaption,
.gf-band--light .caption { font-size: 12px; color: var(--gf-muted); letter-spacing: 0.02em; }

/* Section eyebrows / register numerals. */
.gf-register-num {
  font-family: var(--gf-sans);
  font-size: 11px; font-weight: 700; letter-spacing: 0.18em;
  color: var(--gf-blue);
}

/* ── Surfaces ────────────────────────────────────────────────────────────── */
.gf-band--light :is(.card, .lens-card, .faq-item, .framework-item, .listing-card,
                    .review-item, .tower-card, .service-card) {
  background: var(--gf-white);
  border: 1px solid var(--gf-border);
}
.gf-band--light :is(.card, .lens-card, .faq-item, .framework-item, .listing-card,
                    .review-item, .tower-card, .service-card):hover {
  border-color: var(--gf-blue);
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn-primary,
.btn-ghost,
.btn-ghost-dark,
.form-submit,
.mn-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 14px 30px;
  font-family: var(--gf-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: 0;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.btn-primary, .form-submit, .mn-submit {
  background: var(--gf-blue);
  color: var(--gf-white);
  border: 1px solid var(--gf-blue);
}
.btn-primary:hover, .form-submit:hover, .mn-submit:hover {
  background: var(--gf-blue-pressed);
  border-color: var(--gf-blue-pressed);
  color: var(--gf-white);
  transform: none;
}
.btn-primary:active, .form-submit:active, .mn-submit:active {
  background: var(--gf-blue-pressed);
}

.btn-ghost, .btn-ghost-dark {
  background: transparent;
  color: var(--gf-navy);
  border: 1px solid var(--gf-border);
}
.btn-ghost:hover, .btn-ghost-dark:hover {
  background: var(--gf-white);
  border-color: var(--gf-navy);
  color: var(--gf-navy);
}
.gf-band--navy .btn-ghost, .gf-band--media .btn-ghost,
.gf-band--navy .btn-ghost-dark {
  color: var(--gf-white);
  border-color: rgba(214, 222, 231, 0.4);
}
.gf-band--navy .btn-ghost:hover, .gf-band--media .btn-ghost:hover,
.gf-band--navy .btn-ghost-dark:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--gf-white);
  color: var(--gf-white);
}

/* Text links keep a 44px hit area without growing visually. */
.text-link, .gf-band a.text-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  min-width: 44px;
  color: var(--gf-blue);
  text-decoration: none;
  font-weight: 600;
}
.gf-band--light .text-link, .gf-band--light .text-link.light { color: var(--gf-blue); }
.gf-band--navy .text-link, .gf-band--navy .text-link.light,
.gf-band--media .text-link { color: var(--gf-blue-navy); }
.text-link:hover { text-decoration: underline; text-underline-offset: 4px; }

/* ── Target size ─────────────────────────────────────────────────────────────
   WCAG 2.5.5 asks for 44px in both axes. Vertical padding grows a link's hit
   box without altering the line box it sits in, and the matching negative
   margin returns block and flex links to exactly where the page placed them:
   the rule buys hit area and costs no layout. Both halves must land together
   or the negative margin would pull the link into its neighbours, so the pair
   is marked important. Links carrying a component class size their own box,
   and so does the bordered tower chip: its padding is the pill it draws, so
   growing it would inflate a visible shape rather than an invisible one. */
.gf-band a:not([class]):not([style*="border:"]),
.gf-band a.src-link:not([style*="border:"]),
.gf-band a.article-link:not([style*="border:"]) {
  padding-block: 16px !important;
  margin-block: -16px !important;
}

/* The negative margin is a repayment of the padding, not a licence to move the
   element, so a link that set its own block margin has to get it back. The
   eight article back-links ask for twenty pixels of air beneath them; without
   this they collect minus sixteen instead, and the kicker line that follows
   rides up into the link's text. Sixteen of the four below are the repayment;
   the twenty the page asked for sit on top of it. */
.gf-band a[style*="margin-bottom:20px"]:not([class]):not([style*="border:"]) {
  margin-bottom: 4px !important;
}

/* An underline drawn as a border sets a small padding-bottom to hold the rule
   off the baseline. Growing that padding would float the underline away from
   the word, so these links take the whole expansion upward, where nothing is
   painted, and keep the offset the page chose. */
.gf-band a:not([class])[style*="border-bottom:"] {
  padding-top: 28px !important;
  padding-bottom: 3px !important;
  margin-top: -28px !important;
  margin-bottom: 0 !important;
}

.gf-band a:not([class])[style*="padding-bottom:1px"] {
  padding-bottom: 1px !important;
}

/* A bordered link that already reads as a button — an outline CTA, not a chip
   — is two pixels short of the target minimum. Two pixels of padding on each
   edge, returned by the margin, closes it inside a box that already exists. */
.gf-band a:not([class])[style*="border:"][style*="padding:12px"] {
  padding-block: 14px !important;
  margin-block: -2px !important;
}

/* Inline prose links. */
.gf-band--light :is(p, li, dd, td) a { color: var(--gf-blue); text-underline-offset: 3px; }
.gf-band--navy :is(p, li, dd, td) a { color: var(--gf-blue-navy); }

/* ── Forms ───────────────────────────────────────────────────────────────── */
.form-field, .mn-field, input[type="text"], input[type="email"],
input[type="tel"], select, textarea {
  min-height: 50px;
  background: var(--gf-white);
  color: var(--gf-ink);
  border: 1px solid var(--gf-border);
  border-radius: 0;
  font-family: var(--gf-sans);
  font-size: 15px;
  padding: 13px 16px;
}
textarea { min-height: 120px; }
.form-field::placeholder, .mn-field::placeholder,
input::placeholder, textarea::placeholder { color: var(--gf-muted); opacity: 1; }
.form-field:focus, .mn-field:focus, input:focus, select:focus, textarea:focus {
  border-color: var(--gf-blue);
  outline: none;
}
.gf-band--navy :is(.form-field, .mn-field, input, select, textarea) {
  background: rgba(255, 255, 255, 0.06);
  color: var(--gf-white);
  border-color: rgba(214, 222, 231, 0.28);
}
.gf-band--navy :is(.form-field, .mn-field, input, textarea)::placeholder { color: var(--gf-fog); }
.form-field option { color: var(--gf-ink); background: var(--gf-white); }

/* ── Focus: one site-wide treatment, on every interactive element ────────── */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--gf-blue);
  outline-offset: 3px;
  border-radius: 0;
}
.gf-band--navy :is(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
.gf-band--media :is(a, button, [tabindex]):focus-visible,
#site-nav :is(a, button):focus-visible,
#mobile-menu a:focus-visible,
footer :is(a, button):focus-visible {
  outline: 3px solid var(--gf-blue-navy);
  outline-offset: 3px;
}

/* ── Minimum interactive target ──────────────────────────────────────────── */
#site-nav .nav-link,
#site-nav .nav-cta,
#site-nav .lang-link,
#mobile-menu a,
footer a {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  min-height: 44px;
  min-width: 44px;
}
#nav-toggle {
  min-width: 44px;
  min-height: 44px;
  display: none;
  align-items: center;
  justify-content: center;
}

/* The language control and Contact are controls, not destinations. They sit in
   their own region, divided from the five canonical paths by a hairline, so the
   content navigation reads as five items rather than seven. */
.nav-inner { justify-content: flex-start; }
.nav-links { margin-left: auto; }
.nav-controls {
  display: flex;
  align-items: center;
  gap: 22px;
  margin-left: 32px;
  padding-left: 26px;
  border-left: 1px solid rgba(214, 222, 231, 0.18);
}
#site-nav .nav-controls a { display: inline-flex; align-items: center; min-height: 44px; }
#mobile-menu .lang-link { margin-top: 6px; border-top: 1px solid rgba(214, 222, 231, 0.18); }
@media (max-width: 820px) {
  .nav-controls { display: none; }
  .nav-links { margin-left: 0; }
}

/* ── Chrome ──────────────────────────────────────────────────────────────── */
#site-nav { background: rgba(14, 26, 43, 0.97); border-bottom: 1px solid rgba(214, 222, 231, 0.14); }
.nav-link { color: var(--gf-on-navy); }
.nav-link:hover, .nav-link-active { color: var(--gf-white); }
/* The language control is a control, not a content destination: it reads
   quieter than the five canonical paths and sits with Contact. Scoped to the
   chrome, because fog is only legal on navy — the same class appears in page
   content, where it has to resolve on the limestone ground instead. */
#site-nav .lang-link, #site-nav .lang-switch,
#mobile-menu .lang-link, #mobile-menu .lang-switch,
footer .lang-link, footer .lang-switch {
  color: var(--gf-fog);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
}
#site-nav .lang-link:hover, #site-nav .lang-switch:hover,
#mobile-menu .lang-link:hover, #mobile-menu .lang-switch:hover,
footer .lang-link:hover, footer .lang-switch:hover { color: var(--gf-white); }

/* A language switch inside page content is a discrete control on limestone. */
.gf-band--light .lang-switch {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--gf-blue);
  font-weight: 600;
  text-decoration: none;
}
#mobile-menu { background: var(--gf-navy); border-top: 1px solid rgba(214, 222, 231, 0.14); }
#mobile-menu a { color: var(--gf-on-navy); border-bottom: 1px solid rgba(214, 222, 231, 0.1); }

footer { background: var(--gf-navy); color: var(--gf-on-navy); }
footer a { color: var(--gf-on-navy); text-decoration: none; }
footer a:hover { color: var(--gf-white); }
footer :is(h2, h3, h4, .footer-head) { color: var(--gf-white); }

/* ── Search ──────────────────────────────────────────────────────────────────
   The site already carries a real search control (js/site-search.js, V6.6I)
   which states in its own copy that it searches site and advisory content and
   not live listings. It is left looking exactly as it does: this phase was
   not scoped to restyle it, and drawing a second, non-functional box beside
   it would be worse than either — a search that looks operable and returns
   nothing. The place for live inventory is held open by the section anchors
   the navigation already points at.

   Its hit box is the one thing that does change. The component injects its
   own stylesheet at runtime, after this file, so the pair below is marked
   important for the same reason the band links are: padding buys the height,
   the negative margin gives back the layout, and neither may land alone. */
#site-nav .gf-search-trigger {
  padding-block: 15px !important;
  margin-block: -13px !important;
}
#mobile-menu .gf-search-trigger-mobile {
  padding-block: 15px !important;
  margin-block: -1px !important;
}

/* ── Tables ──────────────────────────────────────────────────────────────── */
.gf-band--light table { border-collapse: collapse; width: 100%; }
.gf-band--light :is(th, td) { border-bottom: 1px solid var(--gf-border); }
.gf-band--light th { color: var(--gf-muted); }

/* Wide content scrolls inside itself rather than widening the page. */
.gf-band .table-scroll, .gf-band .overflow-x { overflow-x: auto; max-width: 100%; }

/* ── Mobile ──────────────────────────────────────────────────────────────── */
@media (max-width: 820px) {
  #nav-toggle { display: inline-flex; }
  .gf-band--light h1 { font-size: clamp(30px, 8vw, 40px); }
  .gf-band--light h2 { font-size: clamp(23px, 6vw, 30px); }
  .btn-primary, .btn-ghost, .btn-ghost-dark, .form-submit, .mn-submit {
    width: 100%;
    box-sizing: border-box;
  }
  .gf-band :is(section, div, article, figure, table, pre) { max-width: 100%; }

  /* An editorial two-track grid written inline carries an 80px gutter and no
     media query of its own. At 390px that gutter alone eats a quarter of the
     content box, so the columns overflow the band. The gutter is the signature
     of the pattern, so it is also the safest thing to key the collapse on:
     the 2px and 12px inline grids — stat pairs, form rows — are left alone. */
  .gf-band [style*="grid-template-columns"][style*="gap:80px"],
  .gf-band [style*="grid-template-columns"][style*="gap: 80px"] {
    grid-template-columns: 1fr !important;
    gap: 40px !important;
  }
}

/* ── Motion ──────────────────────────────────────────────────────────────────
   Motion must have a functional or narrative reason. Where the reader has
   asked for less, there is none. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Fog is legal on navy and unreadable on limestone. Label and meta classes that
   the band resolver saw in both contexts keep fog where it belongs and resolve
   to muted on the light ground. The stylesheet loads after every page's inline
   <style>, so this settles the case without touching page bytes. */
.gf-band--light :is(.section-label, .kicker, .eyebrow, .brief-num, .advisory-note,
  .form-note, .src-link, .meta, .caption, .figure-note, .stat-label) {
  color: var(--gf-muted);
}
.gf-band--light :is(h1, h2, h3, h4, h5, h6) .section-label { color: inherit; }

/* The nav CTA is a filled control on the navy shell and always carries white
   ink, whatever a page's own inline colour used to say. */
#site-nav .nav-cta, #mobile-menu .nav-cta { color: var(--gf-white); }

/* ── Painted-surface ink context ─────────────────────────────────────────────
   A card, panel or CTA can paint its own surface inside a band of the opposite
   ground. The restyle pass marks those elements, so class-driven colour — which
   has no inline declaration to rewrite — resolves correctly here. These follow
   the band rules in source order and win at equal specificity. */
.gf-on-dark { color: var(--gf-on-navy); }
.gf-on-dark :is(h1, h2, h3, h4, h5, h6) { color: var(--gf-white); }
.gf-on-dark :is(.text-link, .text-link.light, a:not([class])) { color: var(--gf-blue-navy); }
.gf-on-dark :is(.section-label, .kicker, .eyebrow, .brief-num, .advisory-note,
  .form-note, .src-link, .meta, .caption, .figure-note, .stat-label) {
  color: var(--gf-fog);
}
.gf-on-blue, .gf-on-blue :is(h1, h2, h3, h4, h5, h6),
.gf-on-blue :is(.text-link, .text-link.light, .section-label, .kicker, a:not([class])) {
  color: var(--gf-white);
}
