/* Public site v2 — atoms.
   Ported from docs/mockups/PublicDesignSystem/components (Button, Badge,
   RatingBadge, PropertyCard, Avatar, GuestFeedback, HelpfulVote .jsx files).
   Unprefixed (S227-EXEC-1 Seq #13): legacy public/css and this file never
   load on the same page (separate routes/templates), so a defensive ``
   namespace bought nothing — this is the real, final class-name source of
   truth going forward. Requires public-tokens.css loaded first. */

/* Screen-reader-only (S227-EXEC-1 Seq #75) — keeps a real heading in the
   DOM/accessibility tree for correct level order without a redundant
   on-screen duplicate of copy a nearby visible heading already covers. */
.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}

/* S291 EXEC-14 Part 1 (guest-reservation.md Q46): the pending state of a Continue or submit button (static/shared/focus_flow.js): the public family's one spinner. */
.pub-spinner{flex:none;display:inline-block;width:1em;height:1em;border-radius:50%;border:0.125rem solid currentColor;border-top-color:transparent;animation:pub-spin 0.7s linear infinite}
@keyframes pub-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.pub-spinner{animation-duration:2.5s}}
.btn[aria-busy="true"]{cursor:progress}

/* Button */
.btn{font-family:var(--font-sans);font-weight:600;border-radius:var(--radius-pill);border:0.0625rem solid transparent;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;transition:background var(--dur-fast) var(--ease-standard),transform var(--dur-fast) var(--ease-standard);box-sizing:border-box;text-decoration:none;outline:none}
.btn:disabled,.btn[aria-disabled="true"]{opacity:0.5;cursor:not-allowed}
.btn:active:not(:disabled){transform:scale(0.97)}
.btn:focus-visible{box-shadow:var(--shadow-focus)}
.btn--sm{padding:0.5625rem 1rem;font-size:0.8125rem;min-height:2.25rem}
.btn--md{padding:0.8125rem 1.25rem;font-size:0.875rem;min-height:2.75rem}
.btn--lg{padding:0.9375rem 1.625rem;font-size:0.9375rem;min-height:3rem}
.btn--primary{background:var(--action-primary);color:var(--text-on-gold)}
.btn--primary:hover:not(:disabled){background:var(--action-primary-hover)}
.btn--secondary{background:var(--action-secondary);color:var(--white)}
.btn--secondary:hover:not(:disabled){background:var(--action-secondary-hover)}
.btn--outline{background:transparent;color:var(--text-primary);border-color:var(--border-strong)}
.btn--outline:hover:not(:disabled){background:var(--surface-sunken)}
.btn--outline[aria-current="page"]{background:var(--action-primary);color:var(--text-on-gold);border-color:transparent} /* DA275.6: a link to the page you are on */
.btn--ghost{background:transparent;color:var(--text-primary)}
.btn--ghost:hover:not(:disabled){background:var(--surface-sunken)}
.btn--whatsapp{background:var(--action-whatsapp);color:var(--white)}
.btn--whatsapp:hover:not(:disabled){background:oklch(44% 0.13 152)}
/* On-navy variant (hero outline CTA on a dark panel) */
.btn--outline-on-navy{background:transparent;border-color:var(--text-on-navy);color:var(--text-on-navy)}
.btn--outline-on-navy:hover:not(:disabled){background:color-mix(in oklch, var(--text-on-navy) 10%, transparent)}

/* Badge */
.badge{display:inline-flex;align-items:center;padding:0.1875rem 0.625rem;border-radius:var(--radius-pill);font-family:var(--font-sans);font-size:0.75rem;font-weight:600}
.badge--highlight{background:var(--status-highlight-bg);color:var(--status-highlight-fg)}
.badge--success{background:var(--status-success-bg);color:var(--status-success-fg)}
.badge--error{background:var(--status-error-bg);color:var(--status-error-fg)}
.badge--neutral{background:var(--surface-sunken);color:var(--text-secondary)}

/* RatingBadge — static-cosmetic (no Review model backs this, see
   docs/reports/public-website/S227-EXEC-1_home-page-schema-classification.md) */
.rating{display:inline-flex;align-items:center;gap:0.375rem;font-family:var(--font-sans);font-size:0.8125rem;color:var(--text-primary)}
.rating__star{color:var(--gold-500)}
.rating__muted{color:var(--text-muted)}

/* PropertyCard */
.property-card{display:block;text-decoration:none;color:inherit;width:100%;border-radius:var(--radius-lg);background:var(--surface-card);box-shadow:var(--shadow-card);overflow:hidden;transition:box-shadow var(--dur-base) var(--ease-standard);font-family:var(--font-sans)}
.property-card:hover{box-shadow:var(--shadow-elevated)}
.property-card__media{position:relative;aspect-ratio:var(--aspect-video);background:var(--gray-300);display:flex;align-items:flex-start;justify-content:flex-end;padding:0.625rem}
.property-card__media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.property-card__badge{padding:0.1875rem 0.625rem;border-radius:var(--radius-pill);background:var(--status-highlight-bg);color:var(--status-highlight-fg);font-size:0.75rem;font-weight:600}
.property-card__body{padding:0.875rem 1rem}
.property-card__head{display:flex;justify-content:space-between;align-items:baseline;gap:0.5rem}
.property-card__title{font-family:var(--font-serif);font-size:1.0625rem;color:var(--text-primary);margin:0}
.property-card__rating{font-size:0.8125rem;color:var(--text-secondary);flex:none}
.property-card__location{font-size:0.8125rem;color:var(--text-muted);margin-top:0.25rem}
.property-card__price{font-size:0.875rem;color:var(--text-primary);font-weight:600;margin-top:0.625rem}
.property-card__price-unit{color:var(--text-muted);font-weight:400}

/* Avatar */
.avatar{border-radius:50%;background:var(--terracotta-100);color:var(--terracotta-600);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-weight:600;flex-shrink:0}

/* GuestFeedback (testimonial card) — static-cosmetic */
.feedback-card{background:var(--surface-card);border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:1.25rem;display:flex;flex-direction:column;gap:0.75rem;width:100%;font-family:var(--font-sans)}
.feedback-card__quote{color:var(--text-secondary);font-size:0.875rem;line-height:var(--lh-loose);margin:0}
.feedback-card__by{display:flex;align-items:center;gap:0.625rem;margin-top:0.25rem}
.feedback-card__name{font-size:0.8125rem;font-weight:600;color:var(--text-primary)}

/* HelpfulVote — static-cosmetic, no vote persists server-side */
.helpful{display:flex;align-items:center;gap:0.625rem;font-family:var(--font-sans)}
.helpful__question{font-size:0.8125rem;color:var(--text-muted)}
.vote-btn{display:flex;align-items:center;gap:0.375rem;padding:0.375rem 0.75rem;border-radius:var(--radius-pill);border:0.0625rem solid var(--border-default);background:var(--surface-card);cursor:pointer;font-family:var(--font-sans);font-size:0.8125rem;color:var(--text-primary)}
.vote-btn:hover{background:var(--surface-sunken)}
.vote-btn[aria-pressed="true"]{border-color:var(--border-strong);background:var(--surface-sunken)}
.vote-btn[aria-pressed="true"] svg{fill:var(--action-primary);stroke:var(--action-primary)}

/* Surface helpers used directly by page layout */
.surface-card{background:var(--surface-card);border:0.0625rem solid var(--border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-card)}
.container{max-width:75rem;margin:0 auto}

/* ListingCard (Listing Grid v2, S227-EXEC-1 Seq #12) — a distinct card
   variant from property-card: ported from Listing Grid.dc.html's own
   card shape (full-bleed photo, spec-chip row, price+CTA footer, no
   locality-badge photo overlay). Deliberately not a modification of
   property-card, which Home's build already depends on. */
.listing-card{background:var(--surface-card);border-radius:var(--radius-lg);box-shadow:var(--shadow-card);overflow:hidden;display:flex;flex-direction:column;font-family:var(--font-sans)}
.listing-card__media{position:relative;aspect-ratio:var(--aspect-video);background:var(--gray-300)}
.listing-card__media img{width:100%;height:100%;object-fit:cover;display:block}
/* BT-272.1: caption on a stand-in image (type master photo / brand placeholder) so it never poses as the unit's own photo. */
.pd-hero__media{position:relative}
.photo-fallback-label{position:absolute;left:0.5rem;bottom:0.5rem;max-width:calc(100% - 1rem);padding:0.1875rem 0.5rem;border-radius:var(--radius-pill);background:color-mix(in oklch,var(--navy-900) 80%,transparent);color:var(--white);font-family:var(--font-sans);font-size:0.6875rem;font-weight:600;line-height:1.3;pointer-events:none}
.listing-card__body{padding:var(--space-4);display:flex;flex-direction:column;gap:var(--space-3);flex:1}
.listing-card__title{font-family:var(--font-serif);font-size:1.0625rem;margin:0 0 var(--space-1)}
.listing-card__location{font-size:var(--text-caption);color:var(--text-muted)}
.listing-card__location--pending{font-style:italic}
.listing-card__specs{display:flex;gap:var(--space-2);flex-wrap:wrap}
.listing-card__footer{margin-top:auto;display:flex;justify-content:space-between;align-items:center;padding-top:var(--space-2)}
.listing-card__price{font-size:var(--text-body);font-weight:600;color:var(--text-primary)}
.listing-card__price-unit{color:var(--text-muted);font-weight:400}
.listing-card__link{font-weight:600;font-size:var(--text-body-sm);white-space:nowrap;text-decoration:none}

/* NavToggle (S231-EXEC-4) — icon-only hamburger/close button for a collapsing
   nav. Hidden by default; the page stylesheet reveals it at the breakpoint
   where its nav collapses (public.css, header block). On-navy colours: it
   lives on the navy header. Icon swaps on aria-expanded, so the visual state
   can never disagree with the announced state. 2.75rem = 44px touch target. */
.nav-toggle{display:none;align-items:center;justify-content:center;flex:none;width:2.75rem;height:2.75rem;margin:0 calc(-1 * var(--space-2)) 0 0;padding:0;background:transparent;border:0;border-radius:var(--radius-md);color:var(--text-on-navy);cursor:pointer;-webkit-tap-highlight-color:transparent}
.nav-toggle:hover{background:color-mix(in oklch, var(--text-on-navy) 10%, transparent)}
.nav-toggle:focus-visible{outline:none;box-shadow:var(--shadow-focus)}
.nav-toggle svg{width:1.5rem;height:1.5rem;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}
/* display is set ONLY on the two icon classes, never on the bare `svg` rule:
   an earlier `.nav-toggle svg{display:block}` (0,1,1) out-ranked
   `.nav-toggle__close{display:none}` (0,1,0), so both icons rendered while closed. */
.nav-toggle__open{display:block}
.nav-toggle__close{display:none}
.nav-toggle[aria-expanded="true"] .nav-toggle__open{display:none}
.nav-toggle[aria-expanded="true"] .nav-toggle__close{display:block}

/* S251 BT-183: environment banner (shared partial
   static/shared/partials/env-banner.css) mapped to this stack's own tokens.
   The public site is light-only. Contrast --text-primary on --gold-100:
   14.8:1. */
:root{--env-banner-bg:var(--gold-100);--env-banner-fg:var(--text-primary);--env-banner-accent:var(--gold-500)}
/* S294 (DA294.9): the deploy notice, same shared partial as the env banner above -- rendered only
   on the Reserve/booking flow (/reserve/*; public/base.html's own path gate), never on a marketing
   page. Public is light-only (this file's own note above), so there is no dark-mode block to add. */
:root{--deploy-notice-warn-bg:var(--gold-100);--deploy-notice-warn-fg:var(--text-primary);--deploy-notice-warn-accent:var(--gold-500);
--deploy-notice-info-bg:var(--status-highlight-bg);--deploy-notice-info-fg:var(--text-primary);--deploy-notice-info-accent:var(--terracotta-500);
--deploy-notice-muted-bg:var(--gray-300);--deploy-notice-muted-fg:var(--text-secondary);--deploy-notice-muted-accent:var(--gray-500);
--deploy-notice-ok-bg:var(--status-success-bg);--deploy-notice-ok-fg:var(--text-primary);--deploy-notice-ok-accent:var(--status-success-fg);
--deploy-notice-danger-bg:var(--status-error-bg);--deploy-notice-danger-fg:var(--text-primary);--deploy-notice-danger-accent:var(--status-error-fg);
--deploy-notice-btn-bg:var(--status-success-fg);--deploy-notice-btn-fg:var(--white);--deploy-notice-btn-hover-bg:color-mix(in oklch, var(--status-success-fg) 85%, black);
--deploy-notice-danger-btn-bg:var(--status-error-fg);--deploy-notice-danger-btn-fg:var(--white);--deploy-notice-danger-btn-hover-bg:color-mix(in oklch, var(--status-error-fg) 85%, black)}
/* Horizontal scroller (DA275.6): the Calendar family's .h-scroller in public tokens, for the Help chapter strip. */
.h-scroller{display:flex;align-items:center;gap:var(--space-2);min-width:0}
.h-scroller__track{display:flex;flex:1;min-width:0;overflow-x:auto;overflow-y:hidden;scrollbar-width:none}
.h-scroller__track::-webkit-scrollbar{display:none}
.h-scroller__nav{width:2rem;height:2rem;flex-shrink:0;padding:0;display:flex;align-items:center;justify-content:center;border-radius:50%;border:0.0625rem solid var(--border-default);background:var(--surface-card);color:var(--text-muted);font-size:1.125rem;cursor:pointer}
.h-scroller__nav:hover{background:var(--surface-sunken);color:var(--text-primary)}
.h-scroller__nav:focus-visible{outline:none;box-shadow:var(--shadow-focus)}
.h-scroller__nav[hidden]{display:none}

/* S290 PREUAT Seq #17: the live password checklist takes the Public family's tokens (shared/partials/password-policy.css). */
.pwp { --password-policy-ok: var(--status-success-fg); --password-policy-bad: var(--status-error-fg); --password-policy-muted: var(--text-secondary); --password-policy-line: var(--border-default); --password-policy-bg: var(--surface-sunken); --password-policy-font: var(--font-sans); }
/* Guest sign-in pages already list the same rules as help text under the field: the live checklist replaces that list. */
.gla-form-wrap:has(.pwp) .gla-help ul { display: none; }

/* S291 EXEC-2 (login-auth-onboarding.md Q156, DA291.1): the Public family's alert atom. Same class names and variants as the
   Desktop family's .alert (atoms-desktop.css), drawn from this family's own tokens, so a notice reads the same on the guest
   sign-in and on the internal sign-in. Markup: templates/shared/_alert.html. The Public site is light-only. Each variant is a
   tinted fill, a matching border and an icon plus text, so meaning never rests on colour alone. */
.alert{display:flex;align-items:flex-start;gap:var(--space-2);margin:0 0 var(--space-4);padding:var(--space-3) var(--space-4);border:0.0625rem solid transparent;border-radius:var(--radius-md);font-family:var(--font-sans);font-size:var(--text-body-sm);line-height:var(--lh-body)}
.alert[hidden]{display:none}
.alert:focus-visible{outline:0.125rem solid currentColor;outline-offset:0.125rem}
.alert__icon{flex:none;width:1.125rem;height:1.125rem;margin-top:0.0625rem}
.alert__body{display:flex;flex-direction:column;gap:var(--space-1);min-width:0}
.alert__body a{color:inherit;font-weight:600}
.alert-danger{background:color-mix(in oklch,var(--status-error-fg) 12%,var(--surface-page));color:var(--status-error-fg);border-color:color-mix(in oklch,var(--status-error-fg) 30%,transparent)}
.alert-success,.alert-ok{background:color-mix(in oklch,var(--status-success-fg) 12%,var(--surface-page));color:color-mix(in oklch,var(--status-success-fg) 70%,var(--text-primary));border-color:color-mix(in oklch,var(--status-success-fg) 30%,transparent)}
.alert-info{background:var(--surface-sunken);color:var(--text-primary);border-color:var(--border-default)}
.alert-warn{background:var(--status-highlight-bg);color:var(--status-highlight-fg);border-color:color-mix(in oklch,var(--status-highlight-fg) 30%,transparent)}

/* S291 EXEC-2 (DA291.2): two-tab switch between sibling pages (Sign in / Create account). Navigation, not a panel switcher: the
   current page is a link marked aria-current="page"; a tab that is not available yet is a button marked aria-disabled (it
   stays in the tab order, announces as unavailable and goes nowhere). The Desktop family's twin is .atom-tabstrip. */
.tabstrip{display:flex;gap:var(--space-1);margin:0 0 var(--space-5);padding:var(--space-1);background:var(--surface-sunken);border:0.0625rem solid var(--border-default);border-radius:var(--radius-pill)}
.tabstrip__tab{flex:1 1 0;display:inline-flex;align-items:center;justify-content:center;min-height:2.75rem;padding:var(--space-2) var(--space-4);border:0;border-radius:var(--radius-pill);background:transparent;font-family:var(--font-sans);font-size:var(--text-body-sm);font-weight:600;color:var(--text-secondary);text-decoration:none;cursor:pointer;transition:background var(--dur-fast) var(--ease-standard),color var(--dur-fast) var(--ease-standard)}
.tabstrip__tab:hover{color:var(--text-primary)}
.tabstrip__tab[aria-current="page"],.tabstrip__tab[aria-selected="true"]{background:var(--surface-card);color:var(--text-primary);box-shadow:var(--shadow-card);cursor:default}
.tabstrip__tab[aria-disabled="true"]{opacity:0.5;cursor:not-allowed}
.tabstrip__tab:focus-visible{outline:none;box-shadow:var(--shadow-focus)}

/* S333 OCT21-UX Seq #11 (Q361): the mobile-number control (shared partial mobile-field.css) mapped to the public site's tokens (light-only). The input itself is the .br-input atom. */
:root{--mobile-field-radius:var(--radius-md);--mobile-field-border:var(--border-default);--mobile-field-cc-bg:var(--surface-sunken);--mobile-field-cc-fg:var(--text-secondary);--mobile-field-link:var(--text-secondary);--mobile-field-muted:var(--text-secondary);--mobile-field-focus:var(--text-primary)}
