/* ===========================================================
   Infinite Focus — shared stylesheet
   Editorial, full-bleed, monochrome. Inspired by the quiet,
   image-first layout of andyryanphotographer.com.
   =========================================================== */

:root {
  --ink: #141414;
  --paper: #f7f6f3;
  --paper-2: #efeeea;
  --line: rgba(20, 20, 20, 0.12);
  --line-on-dark: rgba(255, 255, 255, 0.18);
  --grey: #8a8880;
  --white: #ffffff;
  --nav-h: 84px;
  --frame: 40px;
  --ease: cubic-bezier(0.65, 0, 0.35, 1);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; background: var(--ink); }

body {
  margin: 0;
  padding: var(--frame);
  background: var(--paper);
  background-clip: content-box;
  color: var(--ink);
  font-family: "Helvetica Neue", Arial, "Segoe UI", sans-serif;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

/* 100vh on mobile browsers is measured against the LARGEST possible
   viewport — as if the address bar and bottom toolbar were fully
   collapsed — not what's actually visible. When Chrome's/Safari's
   toolbar is showing, the real visible area is shorter than 100vh,
   so the bottom of a 100vh-locked page (here: the hero-footer social
   icons + copyright bar) gets sized right under where that toolbar
   sits — and since this page doesn't scroll, it's unreachable, not
   just hidden. 100dvh ("dynamic viewport height") tracks the actual
   visible viewport and updates live as the toolbar shows/hides.
   Browsers without dvh support just keep using the 100vh above. */
body.home { height: 100vh; overflow: hidden; }
body.home { height: 100dvh; }
/* Same --real-vh preference as .hero below, kept in sync so the body's
   own clipping boundary matches the hero's actual height exactly —
   see js/main.js for where --real-vh comes from. */
body.home { height: var(--real-vh, 100dvh); }

/* The dark "frame" border along the top of every page is really
   just the body's own top padding showing the html background
   through it — solid at scroll position 0, but on any page taller
   than the viewport (i.e. every page except the no-scroll homepage)
   that padding scrolls away with the rest of the document, letting
   the page's own paper-colored content show through above the fixed
   nav instead. This pins an actual ink-colored strip to the
   viewport, independent of scroll, so the top border and the gap
   above the nav always stay solid black. */
body::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--frame);
  background: var(--ink);
  z-index: 99;
  pointer-events: none;
}

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

.eyebrow {
  font-size: 11px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--grey);
}

/* ---------------- Nav ---------------- */

.site-nav {
  position: fixed;
  top: var(--frame); left: var(--frame); right: var(--frame);
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 40px;
  background: var(--ink);
  color: var(--white);
  /* Bleeds a couple px of matching black past the nav's own edges so
     any sub-pixel rounding gap between this fixed element and the
     body-padding frame (two separately-computed coordinate systems)
     gets physically covered rather than showing a hairline seam. */
  box-shadow: 0 0 0 2px var(--ink);
}

.site-nav.solid {
  background: var(--paper);
  color: var(--ink);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: inline-flex;
  align-items: center;
}

/* Sized in height, with width following the logo file's own aspect
   ratio automatically — swap in a new file at the same path and it
   scales the same way, no CSS changes needed. */
.brand-logo {
  display: block;
  height: 60px;
  width: auto;
}

.nav-links {
  display: flex;
  gap: 34px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-links a {
  display: block;
  font-size: 19px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding-bottom: 4px;
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease);
}

.nav-links a:hover,
.nav-links a.active {
  border-color: currentColor;
}

/* Hamburger icon — three bars that morph into an X when open. */
.nav-toggle {
  display: none;
  position: relative;
  width: 26px;
  height: 18px;
  padding: 0;
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  flex-shrink: 0;
}

.nav-toggle span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
  transition: transform 0.25s var(--ease), opacity 0.2s var(--ease), top 0.25s var(--ease);
}

.nav-toggle span:nth-child(1) { top: 0; }
.nav-toggle span:nth-child(2) { top: 8px; }
.nav-toggle span:nth-child(3) { top: 16px; }

.nav-toggle.open span:nth-child(1) { top: 8px; transform: rotate(45deg); }
.nav-toggle.open span:nth-child(2) { opacity: 0; }
.nav-toggle.open span:nth-child(3) { top: 8px; transform: rotate(-45deg); }

/* "Mobile" breakpoint — tuned to catch iPad Pro portrait (1024px)
   and everything narrower, so only genuine desktop-width browsers
   get the full nav. Adjust this one number to move the cutoff. */
@media (max-width: 1024px) {
  /* Border frame shrinks to 20px in mobile formats. Every layout
     value tied to var(--frame) updates automatically from this one
     override. */
  :root { --frame: 20px; }

  .site-nav { padding: 0 20px; }

  /* Smaller logo on the left so it doesn't crowd the bar next to
     the hamburger. */
  .brand-logo { height: 48px; }

  .nav-links {
    position: fixed;
    top: calc(var(--frame) + var(--nav-h));
    right: var(--frame);
    left: var(--frame);
    /* Matches the top bar instead of going light — besides looking
       intentional, this hides the seam where the panel meets the
       nav/frame at some sizes (dark-on-dark instead of a visible
       edge). */
    background: var(--ink);
    color: var(--white);
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: 10px 24px 30px;
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
    border-bottom: 1px solid var(--line-on-dark);
  }
  .nav-links.open {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  .nav-links a {
    padding: 12px 0;
    width: 100%;
    border-bottom: 1px solid var(--line-on-dark);
  }
  .nav-toggle { display: block; }

  /* Smaller tap targets, tucked closer to the edges. */
  .hero-controls button { width: 42px; height: 42px; font-size: 22px; }
  .hero-prev { left: 8px; }
  .hero-next { right: 8px; }

  /* .hero-kicker is short now ("Architectural Photo / Video") — no
     wrap/stack treatment needed here. Size/position tuning for this
     breakpoint lives in the trailing @media block further down
     (after .hero-kicker's base rule), same reasoning as the note
     near that block: a property set here AND in an unconditional
     rule declared later in the file loses to the later one
     regardless of this @media condition, so anything that actually
     needs to win on mobile has to live after the base rule instead. */

  /* Three stacked lines instead of one wrapped line for the relocated
     tagline text — drop the dot separators (they were joining a
     single line) and break each part onto its own row. Safe to keep
     here (not in the trailing block) since these are display/margin
     tweaks on .hk-part/.hk-sep, a different property than anything
     .hero-tagline's own base rule sets, so there's no cascade
     conflict to worry about. */
  .hero-tagline .hk-sep { display: none; }
  .hero-tagline .hk-part { display: block; }
  .hero-tagline .hk-part + .hk-part { margin-top: 3px; }

  /* .hero-footer-row stacks social links above the copyright line
     and centers everything, since the full copyright text is too
     long to share a row with the social links at this width.
     (.hero-footer itself is already a centered column at every
     size now, per its base rule — this is just the row beneath the
     tagline.) */
  .hero-footer-row {
    flex-direction: column;
    gap: 8px;
  }

  .hero-footer .social { justify-content: center; }

  .hero-footer .copyright { white-space: normal; }
}

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

.site-footer {
  padding: 70px 40px 40px;
  text-align: center;
  border-top: 1px solid var(--line);
  background: var(--paper);
}

.site-footer .social {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 26px;
  margin-bottom: 22px;
}

.site-footer .social a {
  display: inline-flex;
  opacity: 0.85;
  transition: opacity 0.2s var(--ease);
}

.site-footer .social a:hover { opacity: 1; }

.site-footer .social img {
  display: block;
  width: 26px;
  height: 26px;
}

.site-footer .copyright {
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--grey);
}

/* ---------------- Home / Hero slideshow ---------------- */

.hero {
  position: relative;
  width: 100%;
  /* Fills whatever's left of the viewport after the top+bottom
     border frame and the nav bar are accounted for, so the image
     starts flush with the bottom of the nav and ends flush with the
     bottom border. Uses dvh (see body.home above) so this doesn't
     run itself under a mobile browser's toolbar. */
  height: calc(100vh - (var(--frame) * 2) - var(--nav-h));
  height: calc(100dvh - (var(--frame) * 2) - var(--nav-h));
  /* --real-vh is set by js/main.js from window.visualViewport, which
     reports the phone's actual visible area more reliably than 100dvh
     alone — see the comment there for why this was needed. Falls back
     to 100dvh above if JS hasn't run yet or visualViewport isn't
     supported (var() with an unset custom property here just leaves
     this line inert, so the dvh line right above still applies). */
  height: calc(var(--real-vh, 100dvh) - (var(--frame) * 2) - var(--nav-h));
  margin-top: var(--nav-h);
  min-height: 480px;
  overflow: hidden;
  background: var(--ink);
}

/* Wraps the slides + arrows. On desktop this is just a pass-through
   (position:absolute;inset:0, same as the slides sitting directly on
   .hero before). On mobile it becomes the flexed box that gets
   whatever height is left after .hero-footer's own content height is
   subtracted — see the mobile override below. */
.hero-stage {
  position: absolute;
  inset: 0;
}

.hero-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.1s var(--ease);
}

.hero-slide.active { opacity: 1; }

.hero-img {
  width: 100%;
  height: 100%;
  background-color: #201f1c;
  background-image: linear-gradient(160deg, #3c3a35, #201f1c 70%);
  background-size: cover;
  background-position: center;
}

/* Full-bleed invisible wrapper (not a pill anymore) — just gives
   the two arrow buttons something to hide via display:none when
   there's only one surviving slide (see js/main.js). */
.hero-controls {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
}

.hero-controls button {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 52px;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--white);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.85;
  border-radius: 50%;
  pointer-events: auto;
  transition: opacity 0.2s var(--ease), background 0.2s var(--ease);
}

.hero-controls button:hover {
  opacity: 1;
  background: rgba(255, 255, 255, 0.12);
}

.hero-prev { left: 24px; }
.hero-next { right: 24px; }

/* Small "what / where" line sitting in the otherwise-empty photo
   space just under the nav. Doubles as an on-page SEO signal
   (Google reads visible text) without adding a new banner-style
   element to the layout. The gradient behind it mirrors the one on
   .hero-footer below, so it reads as part of the original design. */
.hero::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 140px;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0) 100%);
  z-index: 3;
  pointer-events: none;
}

/* The main brand statement now — bigger and a touch more spaced-out
   than the old SEO kicker line it replaced, since this is meant to
   read as the primary visual, not a quiet utility strip. */
.hero-kicker {
  position: absolute;
  top: 26px;
  left: 40px;
  z-index: 4;
  margin: 0;
  font-size: 16px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.95);
}

/* Slim footer bar overlaid on the very bottom edge of the hero
   image — a quiet keyword line up top, then social links on the
   left / copyright on the right below it. Keeps the homepage
   full-screen/no-scroll, unlike every other page's .site-footer,
   which is a full section you scroll to. */
.hero-footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 40px;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0) 100%);
  color: var(--white);
  text-align: center;
}

/* The old hero-kicker copy, relocated rather than removed — still
   real, visible, indexable text (Real Estate / Videography / Drone /
   Alabama Gulf Coast), just background rather than the headline. */
.hero-tagline {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.75);
}

.hero-tagline .hk-sep { opacity: 0.6; }

/* The row that used to be the whole footer — now just its bottom
   half, below .hero-tagline. */
.hero-footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.hero-footer .social {
  display: flex;
  gap: 18px;
  align-items: center;
  flex-wrap: wrap;
}

.hero-footer .social a {
  display: inline-flex;
  opacity: 0.9;
  transition: opacity 0.2s var(--ease);
}

.hero-footer .social a:hover { opacity: 1; }

.hero-footer .social img {
  display: block;
  width: 22px;
  height: 22px;
  /* The icon files are a black badge + white glyph, built for a
     light background. Inverted here so this overlay (on the dark
     hero photo) gets a white badge / black glyph instead — same
     image file, no separate dark-mode asset needed. Every other
     page's .site-footer sits on the light paper background, so it
     uses the icons unchanged. */
  filter: invert(1);
}

.hero-footer .copyright {
  margin: 0;
  font-size: 10px;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.75);
  white-space: nowrap;
}

/* Deliberately placed AFTER the base .hero/.hero-stage/.hero-footer
   rules above (not inside the earlier mobile breakpoint block with
   the kicker/controls tweaks), so these position/spacing overrides
   actually win the cascade — an identical-specificity rule declared
   earlier in the file loses to one declared later for any property
   both set, @media condition aside. Putting the conflicting
   properties here, after their base rules, is what makes them stick.

   Cover photos are landscape; a phone's tall-narrow screen was
   forcing them to fill the ENTIRE hero height behind an overlaid
   footer, cropping down to a sliver of the actual photo. Switching
   .hero to a column flexbox lets .hero-stage (flex:1) claim exactly
   the space left over once .hero-footer's own content height is
   accounted for, so the photo stops above the footer instead of
   running full-screen underneath it — shows much more of the
   original frame, with no hardcoded pixel guess for the footer's
   height (which varies by 1 vs. 2-line copyright text). */
@media (max-width: 1024px) {
  .hero {
    display: flex;
    flex-direction: column;
  }

  .hero-stage {
    position: relative;
    inset: auto;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
  }

  /* No longer an overlay on top of the photo (the photo stops above
     it now), so it sits in normal flex flow with a solid background
     instead of the gradient meant for legibility over an image.
     Gap and padding tightened and kept symmetric top/bottom, per
     "bring the icons closer to the text, same spacing above the
     icons as below the text." */
  .hero-footer {
    position: relative;
    inset: auto;
    flex-shrink: 0;
    gap: 6px;
    padding: 14px 20px;
    background: var(--ink);
  }

  /* Scaled down for the smaller screen — same reasoning as above,
     placed here (after .hero-kicker's/.hero-tagline's base rules)
     so these values actually win. */
  .hero-kicker {
    left: 20px;
    right: 20px;
    top: 20px;
    font-size: 13px;
    letter-spacing: 0.16em;
    text-align: center;
  }

  .hero-tagline {
    font-size: 9.5px;
    letter-spacing: 0.12em;
  }
}

/* ---------------- Placeholder photo blocks ---------------- */

.ph {
  background-color: #201f1c;
  background-image:
    linear-gradient(135deg, rgba(255,255,255,0.06), rgba(255,255,255,0) 45%),
    linear-gradient(160deg, #3c3a35, #201f1c 70%);
  background-size: cover;
  background-position: center;
  position: relative;
  display: flex;
  align-items: flex-end;
  color: rgba(255,255,255,0.55);
  overflow: hidden;
}

.ph::after {
  content: attr(data-label);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 14px;
}

.ph {
  aspect-ratio: 4 / 5;
  width: 100%;
}

.ph.wide { aspect-ratio: 3 / 2; }
.ph.square { aspect-ratio: 1 / 1; }
.ph.tall { aspect-ratio: 3 / 4; }

/* ---------------- Page intro ---------------- */

.page-intro {
  padding: calc(var(--frame) + var(--nav-h) + 90px) 40px 60px;
  max-width: 1200px;
  margin: 0 auto;
  /* .page-intro is itself the <p> (see pricing.html) — the ".page-intro p"
     rule below never actually matches anything (no nested <p> exists),
     so the real copy's font-size/line-height/color have to live here. */
  font-size: 19px;
  line-height: 1.8;
  color: #4a4a45;
}

.page-intro h1 {
  font-size: clamp(28px, 4vw, 46px);
  font-weight: 200;
  letter-spacing: 0.04em;
  margin: 16px 0 20px;
}

.page-intro p {
  font-size: 19px;
  line-height: 1.8;
  color: #4a4a45;
  max-width: 620px;
}

/* ---------------- Projects grid ---------------- */

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
  padding: 0 2px 2px;
}

@media (max-width: 900px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .grid { grid-template-columns: 1fr; }
}

/* ---------------- Portfolio "coming soon" ---------------- */

.coming-soon {
  position: relative;
  max-width: 1200px;
  margin: 0 auto;
  padding: 30px 40px 140px;
  overflow: hidden;
}

/* Faint blueprint-style grid lines behind the message — a quiet
   nod to "architectural" without needing real photos here yet. */
.coming-soon::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    repeating-linear-gradient(0deg, var(--line) 0 1px, transparent 1px 80px),
    repeating-linear-gradient(90deg, var(--line) 0 1px, transparent 1px 80px);
  opacity: 0.6;
  pointer-events: none;
}

.coming-soon-frame {
  position: relative;
  z-index: 1;
  max-width: 640px;
  margin: 0 auto;
  padding: 60px 50px;
  background: var(--paper);
  border: 1px solid var(--line);
  text-align: center;
}

.coming-soon-eyebrow { margin: 0 0 16px; }

.coming-soon h2 {
  font-size: clamp(24px, 3.4vw, 34px);
  font-weight: 200;
  letter-spacing: 0.02em;
  line-height: 1.3;
  margin: 0 0 20px;
}

.coming-soon-copy {
  font-size: 17px;
  line-height: 1.8;
  color: #4a4a45;
  margin: 0 0 32px;
}

@media (max-width: 600px) {
  .coming-soon { padding: 10px 20px 90px; }
  .coming-soon-frame { padding: 40px 26px; }
}

.grid-item { display: block; position: relative; overflow: hidden; }

a.grid-item { cursor: pointer; }

.grid-item .ph { aspect-ratio: 4/3; transition: transform 0.6s var(--ease); }

.grid-item:hover .ph { transform: scale(1.04); }

.grid-item .tag {
  position: absolute;
  left: 18px;
  bottom: 16px;
  color: var(--white);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}

.grid-item:hover .tag { opacity: 1; transform: translateY(0); }

.grid-item::before {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(0,0,0,0.45), rgba(0,0,0,0) 45%);
  opacity: 0;
  transition: opacity 0.3s var(--ease);
}

.grid-item:hover::before { opacity: 1; }

/* ---------------- Project detail ---------------- */

.project-meta {
  font-size: 17px;
  letter-spacing: 0.05em;
  color: var(--grey);
  margin: 14px 0 0;
}

.project-gallery {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 60px 2px 2px;
}

.project-gallery .ph { aspect-ratio: 16 / 10; }

.project-gallery .ph.portrait { aspect-ratio: 4 / 5; max-width: 720px; margin: 0 auto; }

.project-video { background: var(--ink); }
.project-video video { width: 100%; display: block; max-height: 90vh; }

.project-footer-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 50px 40px 90px;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.project-footer-nav a { border-bottom: 1px solid transparent; transition: border-color 0.2s; }
.project-footer-nav a:hover { border-color: currentColor; }

/* ---------------- Packages ---------------- */

.packages {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  margin: 0 40px 90px;
  border: 1px solid var(--line);
}

@media (max-width: 900px) {
  .packages { grid-template-columns: 1fr; margin: 0 20px 70px; }
}

.package {
  background: var(--paper);
  padding: 50px 36px;
  display: flex;
  flex-direction: column;
}

.package.featured { background: var(--ink); color: var(--white); }
.package.featured .package-price,
.package.featured .eyebrow { color: rgba(255,255,255,0.7); }
.package.featured ul li { border-color: rgba(255,255,255,0.15); }

.package h2 {
  font-size: 20px;
  font-weight: 300;
  letter-spacing: 0.06em;
  margin: 14px 0 6px;
  text-transform: uppercase;
}

.package-price {
  font-size: 30px;
  font-weight: 200;
  margin: 6px 0 26px;
}

.package-price span {
  font-size: 12px;
  letter-spacing: 0.1em;
  opacity: 0.6;
  margin-left: 6px;
}

.package ul {
  list-style: none;
  margin: 0 0 34px;
  padding: 0;
  flex-grow: 1;
}

.package ul li {
  font-size: 13px;
  line-height: 1.6;
  padding: 11px 0;
  border-top: 1px solid var(--line);
}

.package ul li:last-child { border-bottom: 1px solid var(--line); }

.package .btn { align-self: flex-start; }

/* ---------------- Pricing calculator ---------------- */

.calc-wrap {
  padding: 0 40px 100px;
  max-width: 1200px;
  margin: 0 auto;
}

.calc-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 60px;
  align-items: start;
}

@media (max-width: 900px) {
  .calc-wrap { padding: 0 20px 70px; }
  .calc-grid { grid-template-columns: 1fr; gap: 40px; }
}

.calc-notice {
  border: 1px solid var(--line);
  background: var(--paper-2);
  padding: 22px 26px;
  margin-bottom: 44px;
  font-size: 17px;
  line-height: 1.8;
  color: #3f3e39;
}

.calc-notice strong { color: var(--ink); }

.calc-field { margin-bottom: 40px; }

.calc-field label.field-label {
  display: block;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 14px;
}

.calc-field .field-note {
  font-size: 16px;
  color: var(--grey);
  margin: -6px 0 14px;
}

.field-min {
  text-transform: none;
  letter-spacing: normal;
  font-size: 11px;
  color: var(--grey);
  opacity: 0.8;
}

.below-min-msg {
  display: none;
  margin: -20px 0 40px;
  padding: 12px 16px;
  font-size: 12px;
  line-height: 1.6;
  color: #8a5a2a;
  background: #fbf1e4;
  border: 1px solid #e8d3ae;
}
.below-min-msg.show { display: block; }

.stepper--sm button { width: 30px; height: 30px; font-size: 15px; }
.stepper--sm .count { font-size: 16px; min-width: 22px; }

.amenity-counter {
  border: 1px solid var(--line);
  padding: 16px 18px;
  margin-top: 10px;
}

.amenity-counter-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.amenity-counter .field-note { margin: 10px 0 0; }

.fn-mark {
  font-size: 0.85em;
  vertical-align: super;
  color: var(--grey);
  margin-left: 1px;
}

/* Square footage slider */
.sqft-value { font-size: 28px; font-weight: 200; margin-bottom: 12px; }
.sqft-value span { font-size: 14px; color: var(--grey); font-weight: 300; }

input[type="range"] {
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
  height: 2px;
  background: var(--line);
  outline: none;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--ink);
  cursor: pointer;
  border: 3px solid var(--paper);
  box-shadow: 0 0 0 1px var(--ink);
}
input[type="range"]::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--ink);
  cursor: pointer;
  border: 3px solid var(--paper);
  box-shadow: 0 0 0 1px var(--ink);
}

/* Bedroom stepper */
.stepper { display: inline-flex; align-items: center; gap: 22px; }
.stepper button {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--ink);
  background: none;
  font-size: 18px;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.stepper button:hover { background: var(--ink); color: var(--white); }
.stepper button:disabled { opacity: 0.3; cursor: default; background: none; color: var(--ink); }
.stepper .count { font-size: 22px; font-weight: 200; min-width: 30px; text-align: center; }

/* Option rows — real checkbox/radio indicators, not just a
   color-shift on the whole row, so it's unambiguous that each row
   is a clickable toggle. */
.opt-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
@media (max-width: 560px) { .opt-grid { grid-template-columns: 1fr; } }

.opt-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border: 1px solid var(--line);
  cursor: pointer;
  transition: border-color 0.2s var(--ease);
  user-select: none;
}
.opt-row:hover { border-color: var(--ink); }
.opt-row input { position: absolute; opacity: 0; width: 0; height: 0; }

.opt-box {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  border: 1px solid var(--ink);
  position: relative;
}
.opt-box.radio { border-radius: 50%; }

.opt-row input:checked + .opt-box { background: var(--ink); }
.opt-row input:checked + .opt-box::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 1px;
  width: 5px;
  height: 10px;
  border: solid var(--white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.opt-row input:checked + .opt-box.radio::after {
  left: 4px;
  top: 4px;
  width: 8px;
  height: 8px;
  border: none;
  border-radius: 50%;
  background: var(--white);
  transform: none;
}
.opt-row input:focus-visible + .opt-box { outline: 2px solid var(--ink); outline-offset: 3px; }

.opt-row.disabled { opacity: 0.45; cursor: not-allowed; }
.opt-row.disabled .opt-box { cursor: not-allowed; }

.opt-label { flex: 1; font-size: 17px; }
.opt-price { font-size: 12px; color: var(--grey); white-space: nowrap; }

/* 3D tour sub-panel — only meaningful once the main toggle is on */
.tour-sub {
  margin-top: 10px;
  padding: 18px 20px;
  border: 1px dashed var(--line);
  display: none;
}
.tour-sub.open { display: block; }
.tour-sub .opt-grid { margin-bottom: 14px; }
.tour-sub p {
  margin: 0;
  font-size: 16px;
  line-height: 1.7;
  color: var(--grey);
}

/* Quote / estimate summary card */
.quote-card {
  position: sticky;
  top: calc(var(--frame) + var(--nav-h) + 24px);
  border: 1px solid var(--line);
  padding: 34px 30px;
  background: var(--paper);
}

.quote-card h3 {
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey);
  margin: 0 0 20px;
  font-weight: 400;
}

.quote-line {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: 17px;
  padding: 9px 0;
  border-top: 1px solid var(--line);
}
.quote-line:first-of-type { border-top: none; }
.quote-line .qty { color: var(--grey); }

.quote-stats {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 20px;
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--ink);
}

.quote-stat .label { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--grey); }
.quote-stat .label .fn-mark { text-transform: none; letter-spacing: normal; }
.quote-stat.price .amount { font-size: 40px; font-weight: 200; display: block; }
.quote-stat.time .amount { font-size: 22px; font-weight: 300; display: block; }
.quote-stat.time { text-align: right; }

/* Stacked variant — Total, then Session Time, then Photos
   Delivered, each on their own row (rather than the price/time
   side-by-side layout above). */
.quote-stats--stacked {
  flex-direction: column;
  align-items: stretch;
  gap: 14px;
}
.quote-stats--stacked .quote-stat { display: flex; justify-content: space-between; align-items: baseline; }
.quote-stats--stacked .quote-stat.sub .amount { font-size: 16px; font-weight: 300; }

.quote-disclaimer {
  margin: 18px 0 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--grey);
}

/* Mobile sticky running-total bar — see .calc-grid mobile breakpoint
   below for why the real quote card ends up out of view while
   scrolling through the calculator on phones. Hidden entirely on
   wider screens; toggled with .show via JS on phones/tablets. */
.mobile-price-bar {
  display: none;
}
@media (max-width: 1024px) {
  .mobile-price-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 80;
    padding: 14px 20px calc(14px + env(safe-area-inset-bottom, 0px)) 20px;
    background: var(--paper);
    border-top: 1px solid var(--line);
    box-shadow: 0 -6px 24px rgba(0,0,0,0.1);
    transform: translateY(100%);
    transition: transform 0.3s ease;
  }
  .mobile-price-bar.show { transform: translateY(0); }
}
.mpb-info { display: flex; flex-direction: column; gap: 2px; line-height: 1.2; }
.mpb-label { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--grey); }
.mpb-amount { font-size: 22px; font-weight: 300; color: var(--ink); }
.mpb-book-btn {
  flex-shrink: 0;
  background: var(--ink);
  color: var(--paper);
  border: none;
  padding: 12px 20px;
  font-size: 13px;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.mpb-book-btn:hover { opacity: 0.85; }

/* ---------------- Residential / Commercial toggle ---------------- */

.service-toggle {
  display: flex;
  max-width: 1200px;
  margin: 0 auto 40px;
  padding: 0 40px;
  width: 100%;
  gap: 0;
}

.service-toggle-btn {
  flex: 1;
  padding: 14px 20px;
  background: transparent;
  border: 1px solid var(--ink);
  color: var(--ink);
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.service-toggle-btn + .service-toggle-btn { border-left: none; }
.service-toggle-btn.active { background: var(--ink); color: var(--paper); }
.service-toggle-btn:not(.active):hover { background: var(--paper-2); }

@media (max-width: 900px) { .service-toggle { padding: 0 20px; } }

/* ---------------- Commercial pricing (proof of concept — draft numbers) ---------------- */

.opt-grid--4 { grid-template-columns: repeat(4, 1fr); }
.opt-grid--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 700px) {
  .opt-grid--4 { grid-template-columns: repeat(2, 1fr); }
  .opt-grid--3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .opt-grid--4, .opt-grid--3 { grid-template-columns: 1fr; }
}

.commercial-packages {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin: 44px 0 8px;
}
@media (max-width: 900px) { .commercial-packages { grid-template-columns: 1fr; } }

.commercial-package {
  position: relative;
  border: 1px solid var(--line);
  background: var(--paper);
  padding: 30px 26px;
  transition: border-color 0.2s var(--ease);
}
.commercial-package.recommended { border-color: var(--ink); }

.commercial-package h3 {
  margin: 0 0 10px;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey);
  font-weight: 400;
}

.commercial-package .cp-price {
  font-size: 26px;
  margin-bottom: 14px;
}
.commercial-package .cp-price strong { font-weight: 500; }

.commercial-package p {
  font-size: 15px;
  line-height: 1.7;
  color: #4a4a45;
  margin: 0;
}

.cp-recommended {
  display: none;
  position: absolute;
  top: -11px;
  left: 26px;
  padding: 3px 10px;
  background: var(--ink);
  color: var(--paper);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.commercial-package.recommended .cp-recommended { display: inline-block; }

.cp-drone-note {
  margin-top: 12px !important;
  font-size: 13px !important;
  letter-spacing: 0.05em;
  color: var(--grey) !important;
  opacity: 0;
  height: 0;
  overflow: hidden;
  transition: opacity 0.2s var(--ease);
}
.cp-drone-note.show { opacity: 1; height: auto; }
.cp-drone-note--included { opacity: 1; height: auto; }

.book-now-link {
  text-decoration: none;
  text-align: center;
}

/* ---------------- Book Now bottom sheet (preview / dummy — not wired up yet) ---------------- */

.book-now-btn {
  display: block;
  width: 100%;
  margin-top: 18px;
  padding: 14px 20px;
  background: var(--ink);
  color: var(--paper);
  border: none;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.book-now-btn:hover { opacity: 0.85; }

.sheet-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 15, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  z-index: 90;
}
.sheet-overlay.open { opacity: 1; pointer-events: auto; }

.book-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 88vh;
  overflow-y: auto;
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -10px 40px rgba(0,0,0,0.15);
  padding: 14px 40px 40px;
  transform: translateY(100%);
  transition: transform 0.35s cubic-bezier(.32,.72,.35,1);
  z-index: 95;
}
.book-sheet.open { transform: translateY(0); }

.book-sheet-handle {
  width: 40px;
  height: 4px;
  background: var(--line);
  border-radius: 2px;
  margin: 0 auto 18px;
}

.book-sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}
.book-sheet-head h3 {
  font-size: 20px;
  font-weight: 300;
  letter-spacing: 0.02em;
  margin: 0;
}
.book-sheet-close {
  background: none;
  border: none;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  color: var(--ink);
  padding: 4px 8px;
}

.book-sheet-summary {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  padding: 16px 0;
  margin-bottom: 24px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}
.book-sheet-summary div { display: flex; flex-direction: column; gap: 4px; }
.book-sheet-summary span {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #8a8a82;
}
.book-sheet-summary strong { font-size: 18px; font-weight: 400; }

.book-sheet-form { max-width: 640px; margin: 0 auto; }
.bsf-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  margin-bottom: 18px;
}
.book-sheet-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #6a6a62;
}
.bsf-full { display: flex; flex-direction: column; gap: 6px; margin-bottom: 18px; font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; color: #6a6a62; }

/* Helper line under a .bsf-full label (e.g. clarifying "Preferred
   Name" isn't asking for a legal name) — normal case/spacing so it
   reads as a sentence, not shouted like the label above it. */
.bsf-hint {
  font-size: 13px;
  letter-spacing: normal;
  text-transform: none;
  color: #9a9a90;
  margin-top: -2px;
}
.book-sheet-form input {
  font-family: inherit;
  font-size: 19px;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink);
  padding: 10px 12px;
  border: 1px solid var(--line);
  background: var(--paper-2);
}
.book-sheet-form input:focus {
  outline: none;
  border-color: var(--ink);
}

.book-sheet-submit {
  display: block;
  width: 100%;
  padding: 14px 20px;
  background: var(--ink);
  color: var(--paper);
  border: none;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  margin-top: 6px;
}
.book-sheet-submit:hover { opacity: 0.85; }

.book-sheet-note {
  font-size: 16px;
  line-height: 1.6;
  color: #8a8a82;
  margin-top: 14px;
  text-align: center;
}

/* AM/PM session picker on the Book Now sheet — buttons reflect live
   Google Calendar availability once a date is chosen (see pricing.html). */
.session-options {
  display: flex;
  gap: 12px;
  margin-top: 2px;
}
.session-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 14px 10px;
  border: 1px solid var(--line);
  background: var(--paper-2);
  cursor: pointer;
  font-family: inherit;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink);
}
.session-btn .session-label { font-size: 15px; font-weight: 600; }
.session-btn .session-range { font-size: 12px; color: #8a8a82; }
.session-btn:hover:not(:disabled) { border-color: var(--ink); }
.session-btn.selected { background: var(--ink); border-color: var(--ink); }
.session-btn.selected .session-label,
.session-btn.selected .session-range { color: var(--paper); }
.session-btn:disabled { opacity: 0.55; cursor: not-allowed; }
/* Booked sessions get an actual strikethrough through the label and
   time range, not just dimming — the "(Booked)" text stays too, so
   the state doesn't rely on color/decoration alone to read clearly. */
.session-btn.unavailable .session-label,
.session-btn.unavailable .session-range {
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}
.session-btn.unavailable .session-label::after { content: " (Booked)"; font-weight: 400; text-decoration: none; }

.session-legend {
  font-size: 12px;
  color: #9a9a90;
  margin-top: 8px;
  text-transform: none;
  letter-spacing: normal;
}

/* Small red-asterisk convention for required fields on the Book Now
   form — Email and Phone currently. */
.required-mark { color: #b3413a; margin-left: 3px; }
.bsf-required-note {
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #9a9a90;
  margin: 0 0 10px;
  text-align: right;
}

@media (max-width: 640px) {
  .book-sheet { padding: 14px 20px 30px; }
  .bsf-row { grid-template-columns: 1fr; gap: 14px; margin-bottom: 14px; }
  .book-sheet-summary { grid-template-columns: 1fr; gap: 10px; padding: 14px 0; }
  .session-options { flex-direction: column; }
}

.fn-legend {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.fn-legend p {
  margin: 0 0 6px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--grey);
}
.fn-legend p:last-child { margin-bottom: 0; }

/* ---------------- Buttons ---------------- */

.btn {
  display: inline-block;
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 15px 30px;
  border: 1px solid currentColor;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}

.btn:hover { background: var(--ink); color: var(--white); }

.package.featured .btn:hover { background: var(--white); color: var(--ink); }

/* ---------------- About ---------------- */

.about-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: center;
  padding: 0 40px 100px;
  max-width: 1200px;
  margin: 0 auto;
}

@media (max-width: 860px) {
  .about-wrap { grid-template-columns: 1fr; padding: 0 20px 70px; }
}

.about-wrap .ph { aspect-ratio: 3/4; }

.about-photo {
  width: 100%;
  aspect-ratio: 3/4;
  object-fit: cover;
  object-position: center 20%;
  background-color: #201f1c;
}

.about-copy p {
  font-size: 19px;
  line-height: 1.85;
  color: #3f3e39;
  margin: 0 0 20px;
}

.about-stats {
  display: flex;
  gap: 40px;
  margin-top: 34px;
  padding-top: 30px;
  border-top: 1px solid var(--line);
}

.about-stats div { font-size: 12px; letter-spacing: 0.06em; color: var(--grey); }
.about-stats strong {
  display: block;
  font-size: 24px;
  font-weight: 200;
  color: var(--ink);
  margin-bottom: 4px;
}

/* ---------------- Contact ---------------- */

.contact-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 70px;
  padding: 0 40px 110px;
  max-width: 1200px;
  margin: 0 auto;
}

@media (max-width: 860px) {
  .contact-wrap { grid-template-columns: 1fr; padding: 0 20px 80px; }
}

.contact-info dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 14px 24px;
  margin: 30px 0 40px;
}

.contact-info dt {
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey);
}

.contact-info dd {
  margin: 0;
  font-size: 19px;
}

.reveal-btn {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
  cursor: pointer;
}

.reveal-btn:hover { color: var(--grey); border-color: var(--grey); }

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

.contact-form label {
  display: block;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 8px;
}

.contact-form .field { margin-bottom: 26px; }

.contact-form input,
.contact-form select,
.contact-form textarea {
  width: 100%;
  border: none;
  border-bottom: 1px solid var(--line);
  background: transparent;
  font-family: inherit;
  font-size: 19px;
  color: var(--ink);
  padding: 10px 2px;
  outline: none;
  transition: border-color 0.2s;
}

.contact-form input:focus,
.contact-form select:focus,
.contact-form textarea:focus {
  border-color: var(--ink);
}

.contact-form textarea { resize: vertical; min-height: 100px; }

.contact-form button { border: 1px solid var(--ink); background: none; cursor: pointer; }

.form-note {
  font-size: 15px;
  line-height: 1.6;
  color: var(--grey);
  margin-top: 14px;
}

/* Inline submit feedback for the Contact form and the Book Now sheet
   (Web3Forms submissions) — shares .form-note's / .book-sheet-note's
   sizing, just recolored per outcome. */
.form-status--ok {
  color: #2f7d4f;
  font-weight: 600;
}

.form-status--error {
  color: #b3413a;
  font-weight: 600;
}

/* ---------------- Section heading helper ---------------- */

.section-head {
  padding: calc(var(--frame) + var(--nav-h) + 70px) 40px 40px;
  max-width: 1200px;
  margin: 0 auto;
}

.section-head h1 {
  font-size: clamp(26px, 4vw, 42px);
  font-weight: 200;
  letter-spacing: 0.04em;
  margin: 14px 0 0;
}

/* On phones, the fixed 70px buffer above wastes scarce vertical space
   — cut it down so page content starts sooner. --frame and --nav-h
   already shrink on their own at this breakpoint (see above). */
@media (max-width: 640px) {
  .section-head { padding-top: calc(var(--frame) + var(--nav-h) + 24px); }
}
