/**
 * Cross-page UI components: buttons, form fields, property cards, chips,
 * ratings, accordions, carousels and modals.
 * Anything used by two or more pages belongs here; page-specific layout does not.
 */

/* ============================================================
   Icons
   ============================================================ */

/* Figma-exported icons render as a mask filled with currentColor, so one file serves
   the light-on-photo header and the dark-on-white one without a second export. */
.icon {
  display: inline-block;
  flex: none;
  background-color: currentColor;
  -webkit-mask: var(--icon-url) center / contain no-repeat;
  mask: var(--icon-url) center / contain no-repeat;
}

/* ============================================================
   Buttons
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-6);
  border-radius: var(--radius-control);
  /* Buttons are Inter SemiBold in the design, not the Proxima Nova used for nav. */
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

.btn:hover {
  text-decoration: none;
}

.btn:active {
  transform: translateY(1px);
}

.btn--primary {
  background: var(--color-green-primary);
  color: var(--text-inverse);
}

.btn--primary:hover {
  background: #01606c;
}

.btn--rose {
  background: var(--color-rose);
  color: var(--text-inverse);
}

.btn--rose:hover {
  background: #783157;
}

.btn--outline {
  border: 1px solid var(--color-rose);
  color: var(--color-rose);
  background: transparent;
}

.btn--outline:hover {
  background: var(--color-rose);
  color: var(--text-inverse);
}

.btn--ghost {
  border: 1px solid var(--border-field);
  background: var(--color-white);
  color: var(--text-primary);
}

.btn--ghost:hover {
  border-color: var(--color-green-primary);
  color: var(--color-green-primary);
}

.btn--lg {
  min-height: 80px;
  padding-inline: 50px;
  border-radius: var(--radius-control-lg);
  font-size: 20px;
  letter-spacing: 1.4px;
}

.btn--lg.btn--primary {
  box-shadow: var(--shadow-cta);
}

.btn--block {
  width: 100%;
}

/* Underlined text link used for "View All Locations" style calls to action. */
.link-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-green-primary);
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
  text-decoration: underline;
  text-underline-offset: 4px;
}

/* Section-footer variant: the design ships this as a 56px pill-shaped btn whose only
   visible part is the underlined label — Inter Medium 18/24, not the compact 14px link. */
.link-cta--lg {
  height: 56px;
  padding-inline: var(--space-6);
  border-radius: var(--radius-pill);
  font-size: 18px;
  line-height: 24px;
  font-weight: var(--weight-medium);
  text-transform: capitalize;
}

/* Circular icon-only control: carousel arrows, gallery close, map zoom. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-pill);
  color: var(--text-primary);
  background: transparent;
  transition: background var(--duration-fast) var(--ease-out);
}

.icon-btn:hover {
  background: rgba(2, 117, 131, 0.1);
}

.icon-btn--solid {
  background: var(--color-white);
  box-shadow: var(--shadow-card);
}

.icon-btn--solid:hover {
  background: var(--surface-tint);
}

.icon-btn--lg {
  width: 48px;
  height: 48px;
}

.icon-btn--inverse {
  color: var(--text-inverse);
}

.icon-btn--inverse:hover {
  background: rgba(255, 255, 255, 0.18);
}

/* ============================================================
   Form fields
   ============================================================ */

.field {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 0 15px;
  background: var(--color-white);
  border: 1px solid var(--color-grey-light);
  border-radius: var(--radius-control);
  box-shadow: var(--shadow-field);
  color: var(--text-primary);
  transition: border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out);
}

.field:focus-within {
  border-color: var(--color-green-primary);
  box-shadow: 0 0 0 3px rgba(2, 117, 131, 0.12);
}

.field__icon {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--color-rose);
}

.field__input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  background: transparent;
  outline: none;
  font-size: 18px;
  line-height: 1.2;
}

.field__input::placeholder {
  color: var(--color-grey);
}

/* Field captions are capitalised, not uppercase — Inter Medium 18/16 in #6A7282. */
.field-label {
  display: block;
  margin-bottom: 10px;
  font-size: 18px;
  line-height: 16px;
  font-weight: var(--weight-medium);
  text-transform: capitalize;
  color: #6a7282;
}

/* ============================================================
   Property card — browse grid, similar properties, map popup
   ============================================================ */

/* Figma `66:8417`: 417.5x500 — a 315px photo over a 185px white body that carries the
   hairline on three sides only, all inside a 14px radius. */
.property-card {
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  overflow: hidden;
  transition: box-shadow var(--duration-base) var(--ease-out),
    transform var(--duration-base) var(--ease-out);
}

.property-card:hover,
.property-card.is-active {
  box-shadow: var(--shadow-card-hover);
  transform: translateY(-2px);
}

.property-card__media {
  position: relative;
  height: 315px;
  flex: none;
  background: var(--color-grey-light);
  overflow: hidden;
}

.property-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Slide strip: each frame is a full-width flex child, translated by the carousel. */
.property-card__slides {
  display: flex;
  height: 100%;
  transition: transform var(--duration-slow) var(--ease-out);
}

.property-card__slides > * {
  flex: 0 0 100%;
  height: 100%;
}

.property-card__nav {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.85);
  color: var(--text-primary);
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease-out);
}

.property-card:hover .property-card__nav {
  opacity: 1;
}

.property-card__nav--prev {
  left: var(--space-3);
}

.property-card__nav--next {
  right: var(--space-3);
}

/* 3D-tour ribbon, Figma component `1:35`: two white bracket vectors rotated -46.87°
   into a scan-frame around the label. The brackets are the real exports; only their
   placement is reconstructed, since the component sits inside an instance and cannot
   be exported whole. */
.property-card__badge {
  position: absolute;
  top: 20px;
  left: 12px;
  width: 55.57px;
  height: 48px;
  filter: drop-shadow(0 2px 2.5px rgba(0, 0, 0, 0.2));
}

.property-card__badge-bracket {
  position: absolute;
  width: 29.15px;
  height: 15.58px;
  background: no-repeat center / 100% 100%;
  transform: rotate(-46.87deg) skewX(0.61deg);
}

/* Each bracket is centred on its own half of the frame before it is rotated. */
.property-card__badge-bracket--a {
  left: -0.29px;
  top: 7.71px;
  background-image: url('../../assets/icons/tour-badge-bracket-a.svg');
}

.property-card__badge-bracket--b {
  left: 26.71px;
  top: 24.71px;
  background-image: url('../../assets/icons/tour-badge-bracket-b.svg');
}

.property-card__badge-label {
  position: absolute;
  left: 7px;
  top: 9px;
  width: 44px;
  font-size: 12px;
  line-height: 11px;
  font-weight: 800;
  text-align: center;
  text-transform: uppercase;
  color: var(--text-inverse);
}

.property-card__body {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  flex: 1 1 auto;
  min-height: 185px;
  padding: var(--space-5);
  background: var(--color-white);
  /* No top border — the photo meets the body edge to edge. */
  border: 1px solid var(--color-grey-light);
  border-top: 0;
  border-radius: 0 0 14px 14px;
}

.property-card__top {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.property-card__topline {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.property-card__neighborhood {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  font-size: 12px;
  line-height: 14px;
  letter-spacing: 0.2px;
  text-transform: uppercase;
  color: var(--color-green-primary);
}

.property-card__heading {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.property-card__name {
  font-family: var(--font-display);
  font-variation-settings: var(--display-axes);
  font-size: 24px;
  line-height: 24px;
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
}

.property-card__address {
  font-size: var(--text-sm);
  line-height: 20px;
  color: var(--color-grey-secondary);
}

.property-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.property-card__sqft {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-display);
  font-variation-settings: var(--display-axes);
  font-size: 16px;
  line-height: 18px;
  font-weight: var(--weight-medium);
  letter-spacing: -0.8px;
  color: var(--color-rose);
}

/* Added for the Razor port: the size line that shares this footer has no data source,
   so the price is usually on its own. `space-between` would then park it on the left,
   away from where the design puts it. */
.property-card__price:only-child,
.property-card__availability:only-child {
  margin-left: auto;
}

.property-card__price {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-size: var(--text-body);
  line-height: 24px;
  color: var(--color-grey-secondary);
}

.property-card__price strong {
  font-family: var(--font-display);
  font-variation-settings: var(--display-axes);
  font-size: 30px;
  line-height: 24px;
  font-weight: var(--weight-bold);
  color: var(--color-green-primary);
}

/* ============================================================
   Chips, pills and ratings
   ============================================================ */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  background: var(--color-white);
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-green-primary);
}

.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 38px;
  padding: 0 var(--space-4);
  border: 1px solid var(--border-field);
  border-radius: var(--radius-pill);
  background: var(--color-white);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  transition: all var(--duration-fast) var(--ease-out);
}

.filter-pill:hover {
  border-color: var(--color-green-primary);
  color: var(--color-green-primary);
}

.filter-pill.is-active {
  background: var(--color-green-primary);
  border-color: var(--color-green-primary);
  color: var(--text-inverse);
}

.filter-pill__count {
  font-size: var(--text-xs);
  opacity: 0.7;
}

.rating {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-xs);
}

.rating__stars {
  display: inline-flex;
  gap: 1px;
  color: var(--color-star);
  letter-spacing: 1px;
}

/* `stars()` marks the stars past the rating with `is-empty`; without this they inherit
   the gold and every rating reads as five. */
.rating__stars .is-empty {
  color: var(--color-grey-light);
}

.rating__count {
  font-size: var(--text-sm);
  line-height: 16px;
  color: var(--color-grey-secondary);
}

.rating__count u {
  text-underline-offset: 2px;
}

/* ============================================================
   Accordion (FAQ)
   ============================================================ */

.accordion {
  display: flex;
  flex-direction: column;
}

.accordion__item {
  border-top: 1px solid var(--border-hairline);
  padding-right: var(--space-5);
}

.accordion__item:last-child {
  border-bottom: 1px solid var(--border-hairline);
}

.accordion__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  padding: var(--space-5) 0;
  text-align: left;
  font-family: var(--font-display);
  font-variation-settings: var(--display-axes);
  font-size: 20px;
  line-height: 28px;
  font-weight: var(--weight-medium);
  color: var(--text-primary);
}

/* The Figma export named caret-down actually draws an *up* caret, so the resting
   state is the rotated one and an open row un-rotates back to the source vector. */
.accordion__chevron {
  flex: none;
  width: 20px;
  height: 20px;
  rotate: 180deg;
  color: var(--color-green-primary);
  transition: rotate var(--duration-base) var(--ease-out);
}

.accordion__trigger[aria-expanded="true"] .accordion__chevron {
  rotate: 0deg;
}

/* Grid-rows 0fr → 1fr animates height without needing a measured pixel value. */
.accordion__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--duration-base) var(--ease-out);
}

.accordion__panel[data-open="true"] {
  grid-template-rows: 1fr;
}

.accordion__panel > div {
  overflow: hidden;
}

/* 14px sits between the question row and the answer, then 20px closes the row. */
.accordion__body {
  padding-top: 14px;
  padding-bottom: var(--space-5);
  font-size: var(--text-body);
  line-height: var(--text-body-lh);
  color: var(--color-grey-secondary);
}

/* ============================================================
   Carousel scaffolding (testimonials, amenities, galleries)
   ============================================================ */

.carousel {
  position: relative;
  overflow: hidden;
}

.carousel__track {
  display: flex;
  gap: var(--space-5);
  transition: transform var(--duration-slow) var(--ease-out);
  will-change: transform;
}

.carousel__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-10);
}

.carousel__dots {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.carousel__dot {
  width: 8px;
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--color-grey-light);
  transition: width var(--duration-base) var(--ease-out),
    background var(--duration-base) var(--ease-out);
}

.carousel__dot.is-active {
  width: 22px;
  background: var(--color-green-primary);
}

/* ============================================================
   Modal / lightbox
   ============================================================ */

.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  /* The implicit `auto` column is sized by the dialog's contents, so a wide child could
     push the column past the container and take the dialog off the right of a phone
     screen. minmax(0, 1fr) caps the column at the modal's own width. */
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  padding: var(--space-6);
  background: var(--surface-scrim);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-base) var(--ease-out);
}

.modal.is-open {
  opacity: 1;
  pointer-events: auto;
}

.modal__dialog {
  position: relative;
  width: min(100%, 1280px);
  max-height: 92vh;
  overflow: auto;
  background: var(--color-white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-popup);
}

.modal__dialog--bare {
  background: transparent;
  box-shadow: none;
  overflow: visible;
}

.modal__close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  z-index: 2;
}

/* ============================================================
   Photography
   ============================================================ */

/* Every photo slot owns its own aspect ratio; the image just fills it. Listed
   explicitly rather than as a blanket `img` rule so logos and icons keep their
   intrinsic sizing. */
.hero__media > img,
.rooms__media > img,
.amenities__media > img,
.amenities__thumb > img,
.tour__media > img,
.detail-tour__media > img,
.corporate-card__media > img,
.testimonial__media > img,
.award__art > img,
.gallery__panel > img,
.lightbox__thumb > img,
.pocket-guide__collage > img,
.property-card__slides > img,
.map-popup-card__media > img,
.location-tile__photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Badges and client marks must not be cropped. */
.trust__badge > img,
.lightbox__photo {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ============================================================
   Skeleton placeholder — stands in for a photo until the Figma
   export for that slot has been committed to /assets.
   ============================================================ */

/* The artwork itself, held as a property so a host can either mount .img-placeholder as
   its own element or paint this behind a real photograph. A custom property resolves the
   vars inside it where it is *used*, so each host still supplies its own hue. */
:root {
  --placeholder-art: linear-gradient(
    135deg,
    hsl(var(--placeholder-hue, 190) 32% 62%),
    hsl(calc(var(--placeholder-hue, 190) + 40) 28% 44%)
  );
}

.img-placeholder {
  /* Declared block because several hosts mount the placeholder as a <span>, where an
     inline box would ignore the height and collapse the slot to nothing. */
  display: block;
  width: 100%;
  height: 100%;
  /* Each slot passes its own --placeholder-hue so a grid of stand-ins still reads as
     distinct images rather than one grey wall. */
  background: var(--placeholder-art);
}

/* ============================================================
   Cross-page sections
   ============================================================ */

/* "Don't see what you're looking for?" — Figma `98:11037`: a 397px band with 120px of
   air above and below the 50/64 heading and its 318x78 button. */
.contact-cta {
  padding-block: 120px;
  background: var(--surface-tint);
  text-align: center;
}

.contact-cta h2 {
  margin-bottom: 15px;
  line-height: 64px;
}

.contact-cta .btn {
  min-width: 318px;
  min-height: 78px;
  font-size: 20px;
  letter-spacing: 1.4px;
}

/* The band is a shared component, so its mobile sizing belongs here rather than in
   whichever page stylesheet happens to be loaded — the 318px button minimum overflows
   a 390 viewport once the gutter is taken off. */
@media (max-width: 900px) {
  .contact-cta {
    padding-block: var(--space-16);
  }

  /* The 50/64 desktop heading leaves a two-line gap at 390. */
  .contact-cta h2 {
    font-size: var(--text-h3);
    line-height: 36px;
  }

  .contact-cta .btn {
    min-width: 0;
    width: 100%;
    min-height: 56px;
    font-size: 18px;
  }

  .contact-cta__reach {
    font-size: var(--text-lead);
    line-height: 30px;
  }

  .contact-cta__reach strong {
    font-size: var(--text-h3);
  }
}

/* Details uses the same 397px band on solid teal, with the phone number in place of the
   button — Figma `87:6961`, an override of the same `1:2150` component. */
.contact-cta--teal {
  background:
    linear-gradient(180deg, rgba(0, 0, 0, 0) 52.42%, rgba(0, 0, 0, 0.2) 100%),
    var(--color-green-primary);
}

/* base.css colours every heading explicitly, so a heading on a dark band must restate it. */
.contact-cta--teal h2 {
  color: var(--text-inverse);
}

.contact-cta__reach {
  display: block;
  font-size: var(--text-h3);
  line-height: 40px;
  color: var(--text-inverse);
}

.contact-cta__reach strong {
  display: block;
  font-size: 30px;
  font-weight: var(--weight-medium);
}

/* Only "chat" is underlined in the design; the number reads as plain text. */
.contact-cta__reach a {
  color: inherit;
  text-decoration: none;
}

.contact-cta__reach a[href^='#'] {
  text-decoration: underline;
}

/* Two columns of 760 on a 60px gutter, rows 40px apart — Figma `98:11046`. */
.faq-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-10) 60px;
  align-items: start;
}

/* ============================================================
   Open Q&A block — Figma `1:5198`
   ============================================================ */

.qa {
  display: flex;
  align-items: flex-start;
  gap: 5px;
}

/* The two markers stack against the left edge, aligned to their own paragraphs. */
.qa__markers {
  display: flex;
  flex: none;
  flex-direction: column;
  gap: 16px;
  width: 24px;
  font-family: var(--font-body);
  font-size: 20px;
  font-weight: var(--weight-bold);
  text-align: center;
}

.qa__q {
  line-height: 24px;
  color: var(--color-rose);
}

.qa__a {
  line-height: 22px;
  color: #14b8a6;
}

.qa__body {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  gap: 10px;
}

.qa__question {
  font-size: var(--text-h3);
  line-height: 24px;
  font-weight: var(--weight-semibold);
  color: var(--color-grey-dark);
}

.qa__answer {
  font-size: 18px;
  line-height: 32px;
  color: var(--color-grey-dark);
}

@media (max-width: 900px) {
  .qa__question {
    font-size: var(--text-h4);
    line-height: 26px;
  }

  .qa__answer {
    font-size: var(--text-body);
    line-height: 28px;
  }
}
