/* bookbask design system v1
   Authority: docs/bookbask/bookbask-design-documentation-v1.pdf

   Every color has one job. A color doing a second job is a bug — which is why
   these are named for the job, not the hue. Reach for --bb-trust when you mean
   trust; if you want "the green one", you are about to introduce the bug.

   Separation is done by hairlines, not shadow stacks. There is exactly one
   shadow in this file and it is for hover and the two floating cards. */

/* DM Sans — the UI face, self-hosted from assets/fonts (owner decision,
   2026-08-11). One variable file per subset, weight axis 100-1000. Latin
   coverage only: Lao and Thai stay on the Noto script fallbacks below.
   css/site.css and client-dashboard/dash.css carry copies of these two rules
   because their pages never load this file — keep the three in step. */
@font-face {
  font-family: "DM Sans";
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url("../assets/fonts/DMSans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "DM Sans";
  font-style: normal;
  font-weight: 100 1000;
  font-display: swap;
  src: url("../assets/fonts/DMSans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Surfaces. The 2026-08-25 export walks the warm pair back: white page,
     #FAFAFA card, so the card sits one step DARKER than the page again. This
     is the third position in five days (cream -> white/#FAFAFA -> warm pair ->
     white/#FAFAFA) and it is the export's, counted rather than eyeballed:
     #FAFAFA appears 154 times in it and #FFFDF9 three. */
  --bb-page:        #FFFFFF;  /* Journey Atlas: clean white marketplace canvas */
  --bb-surface:     #FFFFFF;  /* cards and panels */

  /* Ink */
  --bb-ink:         #172033;  /* primary text */
  --bb-ink-mid:     #586174;  /* body copy inside dense panels — one step up
                                 from --bb-ink-soft, new in the 2026-08-25
                                 export (policy bodies, room facts) */
  --bb-ink-soft:    #747C8E;  /* metadata, distances, review counts, sublines */

  /* Jobs. Every one of the three lifted off the v1 doc by the export: the navy
     from #123A63, the jade from #0F6E56, the rust from #9A4A1C. Same three
     hues, same three jobs, each about one stop brighter — enough that the page
     reads as a travel product rather than an institution, and short of the
     #1565C7 / #00875A pair tried on 2026-08-22, which went far enough that the
     blue stopped being navy at all. */
  --bb-primary:     #4655F6;  /* Journey Blue: buttons, selected states, links, wordmark */
  --bb-primary-deep:#3342D7;  /* hover and pressed primary states */
  --bb-papaya:      #FF6846;  /* waypoints and discovery emphasis */
  --bb-lagoon:      #18BFA3;  /* supporting brand accent */
  --bb-sun:         #FFD166;  /* editorial highlights */
  --bb-trust:       #0F9F7D;  /* ratings, verified, live availability. never decoration */
  --bb-urgency:     #D95735;  /* scarcity and heat. never red */

  /* The two greens the bright jade cannot do. Jade at #12886A is a fill colour:
     it carries white text and it draws dots, bars and seals. Written as text on
     paper or on the jade tint it is under AA, so the export writes green words
     in --bb-trust-ink and sets the darkest labels (the pill on a jade-tint
     badge) in --bb-trust-deep. One colour to fill with, two to write with. */
  --bb-trust-ink:   #08785F;  /* green words: ✓ Verified, "paid", link hover */
  --bb-trust-deep:  #07684F;  /* label ink on --bb-tint-jade-strong */

  /* Structure */
  --bb-hairline:    #E2E7F0;  /* cool structure, never cream */
  --bb-tint-blue:   #EEF2FF;  /* time chips, tag pills, info panels */
  --bb-tint-jade:   #DFF8F2;  /* verified pills, positive insets */
  /* The badge tint. One step greener than --bb-tint-jade, and the only
     background --bb-trust-deep is legible on. Travelers' Choice, the score
     chip, "leave a review" — the jade things that sit on photography and have
     to hold their own against it. */
  --bb-tint-jade-strong: #D7F5ED;
  /* The rust counterpart of the tints above. Everything urgent that needs a
     fill rather than just ink: rejected documents, overdue badges, error panels.
     `.bb-disc--rust` predates this and mixes its own rgba() at 11% — that is a
     disc-only value and deliberately lighter than a panel wants. */
  --bb-tint-rust:   #FFE8E1;

  /* On-navy variants */
  --bb-on-navy-trust:   #6FE0C7;
  --bb-on-navy-urgency: #FF9B82;
  /* Cream, and only ever on navy or on photography. The export writes every
     on-dark string in #FBF7F0 — 104 uses against three of #FFFDF9. */
  --bb-on-navy-ink:     #FFFFFF;

  /* Radii. Round is out again. Counted across the 2026-08-25 export: 4px 163
     times, 8px 155, 6px 63, 7px 49 — and 999px six, all of them progress
     tracks and avatars, i.e. things that have to be round. So chips and badges
     are 4, buttons 6, fields 7, containers 8, and --bb-r-pill is reserved for
     the handful of genuinely circular things. */
  --bb-r-chip:      7px;   /* badges, tags, chips */
  --bb-r-btn:       10px;  /* buttons */
  --bb-r-field:     12px;  /* inputs, selects, dropdowns, date tiles */
  --bb-r-card:      16px;  /* consumer cards and containers */
  --bb-r-feature:   16px;  /* floating cards: booking, request form */
  --bb-r-thumb:     12px;  /* photo thumbnails in a strip */
  --bb-r-pill:      999px; /* progress tracks, avatars — round by nature only */

  /* Shadows. Hover is the doc's one shadow and is unchanged. The export adds
     two more, both for things that genuinely float rather than sit: the
     booking/request cards rest at --bb-shadow-card, and the search deck hangs
     off the bottom of the hero photo at --bb-shadow-deck. Nothing else in the
     system may carry a resting shadow — separation is the hairline. */
  --bb-shadow-hover: 0 12px 30px rgba(70, 85, 246, 0.12);
  --bb-shadow-card:  0 8px 24px rgba(23, 32, 51, 0.08);
  --bb-shadow-deck:  0 18px 44px rgba(23, 32, 51, 0.18);

  /* Layout */
  --bb-column:       1280px;
  --bb-booking-card: 352px;
  --bb-row-photo:    264px;

  /* Type. DM Sans throughout — it covers neither Lao nor Thai, so the script
     fallbacks stay part of the stack rather than being an override. */
  --bb-font: "DM Sans", "Noto Sans Lao", "Noto Sans Thai", system-ui, sans-serif;
  --bb-font-logo: "DM Sans", sans-serif;
  /* Script-first stacks, for the times a string is known to be Lao or Thai
     rather than merely possibly-Lao. `--bb-font` reaches the same fonts by
     fallback, but only after DM Sans has already claimed the Latin digits and
     punctuation inside the string, which leaves a Lao name set in two faces. */
  --bb-font-lao: "Noto Sans Lao", "DM Sans", system-ui, sans-serif;
  --bb-font-thai: "Noto Sans Thai", "DM Sans", system-ui, sans-serif;

  /* Weight. The whole system's weight lives here — change it here, nowhere
     else. Every rule in every stylesheet points at one of these four.

     Nothing goes above 700, ever. Noto Sans Lao and Noto Sans Thai are loaded
     at 400-700 only, so a rule asking for 800 gets a synthesised or clamped
     bold for Lao and Thai readers while English gets the real face — the same
     class of bug as the font-family miss in commit 1954cc4, and just as
     invisible if you only check the English page.

     600 is the ceiling in practice. The 2026-08-25 export sets font-weight 600
     757 times and 700 twice, so the display tier the previous export
     introduced is gone again: heroes, headings, titles and prices are all 600,
     and --bb-w-bold goes back to the wordmark and nothing else. DM Sans is a
     geometric sans and runs optically heavier than a neo-grotesque at the same
     number; hierarchy here comes from size, colour and space, not weight. */
  --bb-w-regular:  400;  /* body text, descriptions, secondary information */
  --bb-w-medium:   500;  /* quiet labels — metadata, sublines, nav */
  --bb-w-semibold: 600;  /* all emphasis: headings, titles, prices, buttons, b */
  --bb-w-bold:     700;  /* reserved. The wordmark, and nothing else. */
}

html { background: var(--bb-page); }

body {
  margin: 0;
  background: var(--bb-page);
  color: var(--bb-ink);
  font-family: var(--bb-font);
  -webkit-font-smoothing: antialiased;
}

*, *::before, *::after { box-sizing: border-box; }

/* Unstyled markup inherits the system, not the browser's default bold. Without
   these, a bare <h1> or <b> resolves to 700 — above the emphasis tier and, on
   the pages that carry Lao and Thai, heavier than the loaded faces support.
   Class rules still win, so this only catches what nothing else styles. */
h1, h2, h3, h4, h5, h6,
b, strong { font-weight: var(--bb-w-semibold); }

/* The `hidden` attribute is only `display:none` at user-agent strength, so any
   component rule setting display (every flex pill and chip in this file) beats
   it and the element stays visible while reading as hidden to script. */
[hidden] { display: none !important; }

a { color: var(--bb-primary); text-decoration: none; }
a:hover { text-decoration: underline; }

::selection { background: var(--bb-tint-blue); }


/* ---------- Type ----------
   Roles from the doc, section 2. Hero headlines are a question or an
   invitation, never a value prop. Section headings are always paired with a
   warm-gray subline in a human voice — .bb-h2 without a following .bb-sub is
   an incomplete section. Meta is sentence case; ALL-CAPS eyebrows are banned. */

/* Export: 46px/800/-1.6 on the home hero, 44px on the venue hero, 40.5px on
   the owners page. One clamp covers all three and keeps the tracking tied to
   the size — a -1.6px track on a 30px phone headline closes the letters up. */
.bb-hero {
  font: var(--bb-w-semibold) clamp(31px, 3.9vw, 46px)/1.08 var(--bb-font);
  letter-spacing: -1.6px;
  margin: 0;
}
/* The page titles that open a list rather than a destination — "Spa & massage
   in Ubud", "Almost yours", "My bookings". Export: 26.5-28px/800/-1px. */
.bb-hero--page {
  font: var(--bb-w-semibold) clamp(23px, 2.4vw, 28px)/1.14 var(--bb-font);
  letter-spacing: -1px;
}

.bb-h2 {
  font: var(--bb-w-semibold) 23px/1.2 var(--bb-font);
  letter-spacing: -0.5px;
  margin: 0;
}
/* The heading inside a page rather than opening a band — "Availability",
   "House rules", "What travelers say". Export: 22px/700/-0.6. */
.bb-h2--sec {
  font-size: 22px;
  letter-spacing: -0.6px;
}
/* Export: 19px/700/-0.4, the third level down — "Before you go". */
.bb-h3 {
  font: var(--bb-w-semibold) 19px/1.25 var(--bb-font);
  letter-spacing: -0.4px;
  margin: 0;
}

.bb-sub {
  font: var(--bb-w-regular) 13px/1.5 var(--bb-font);
  color: var(--bb-ink-soft);
  margin: 4px 0 0;
}

/* A section head is a heading and its subline on one baseline row, with
   whatever the section carries on the right — carousel arrows, a "see all"
   link. The doc's rule that .bb-h2 without a subline is an incomplete section
   is what this class encodes. */
.bb-sec-head {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  margin-bottom: 20px;
}
.bb-sec-head__end { margin-left: auto; }
/* The variant where the subline sits beside the heading instead of under it. */
.bb-sec-head--inline { align-items: baseline; gap: 14px; }
.bb-sec-head--inline .bb-sub { margin: 0; }

.bb-card-title {
  font: var(--bb-w-semibold) 14px/1.3 var(--bb-font);
  margin: 0;
}
/* The title on a listing row rather than a grid card — it has a whole row of
   width to fill, so the export sets it two steps up at 16px. */
.bb-card-title--row { font-size: 16px; }

/* Prices. The export never lets a price share the weight of the label beside
   it: "from" and the unit stay soft at 12px, the number is display weight and
   two to five steps larger. Tabular so a changing price does not jitter. */
.bb-price {
  font: var(--bb-w-semibold) 15px/1.2 var(--bb-font);
  color: var(--bb-ink);
  font-variant-numeric: tabular-nums;
}
.bb-price--lg { font-size: 26px; letter-spacing: -0.8px; }
.bb-price__unit {
  font: var(--bb-w-regular) 12px/1.4 var(--bb-font);
  color: var(--bb-ink-soft);
}

.bb-body {
  font: var(--bb-w-regular) 13.5px/1.65 var(--bb-font);
  max-width: 66ch;
  margin: 0;
}

/* Traveler quotes: italic, with the attribution roman and soft. Used on cards,
   postcards, the owner testimonial and the venue's own note. */
.bb-quote {
  font: italic var(--bb-w-regular) 14.5px/1.55 var(--bb-font);
  color: var(--bb-ink);
  margin: 0;
}
.bb-quote--sm { font-size: 12px; line-height: 1.5; }
.bb-quote__by {
  font-style: normal;
  color: var(--bb-ink-soft);
}

.bb-meta {
  font: var(--bb-w-medium) 11.5px/1.45 var(--bb-font);
  color: var(--bb-ink-soft);
}

/* Numerals in prices, counts and times must not jitter as they change. */
.bb-tabular { font-variant-numeric: tabular-nums; }

.bb-wordmark {
  font: var(--bb-w-bold) 21.5px/1 var(--bb-font-logo);
  letter-spacing: 2px;
  color: var(--bb-primary);
  text-transform: lowercase;
}


/* ---------- Cards ----------
   No resting shadow. Separation is the hairline. */

.bb-card {
  background: var(--bb-surface);
  border: 1px solid var(--bb-hairline);
  border-radius: var(--bb-r-card);
  overflow: hidden;
  transition: box-shadow .18s ease-out;
}
.bb-card:hover { box-shadow: var(--bb-shadow-hover); }
.bb-card--feature { border-radius: var(--bb-r-feature); }

.bb-card__photo {
  display: block;
  width: 100%;
  height: 172px;          /* export: 172 on grid cards, 190 on the owner preview */
  object-fit: cover;
  background: var(--bb-tint-blue);
}
/* The two cards the doc allows a resting shadow: the booking card and the
   request form. Also the search deck, which hangs off the hero photo. */
.bb-card--float {
  border-radius: var(--bb-r-feature);
  box-shadow: var(--bb-shadow-card);
}
.bb-card--float:hover { box-shadow: var(--bb-shadow-card); }

.bb-card__body {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 14px 16px 16px;   /* export */
  flex: 1;
}
/* Pushes the price footer to the bottom so a row of cards keeps one baseline
   however long the names and quotes above it run. */
.bb-card__foot {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: auto;
  padding-top: 4px;
}


/* ---------- Rating ----------
   Rebuilt on the 2026-08-24 export, which drops the doc's solid jade seal pill
   for a large jade numeral: score, a hairline rule, then the dots stacked over
   the verdict-and-count line. The count is still mandatory — a rating without
   it is not allowed, so .bb-rating without .bb-count is a bug, not a style
   choice. Dots are real elements, never the bullet character. */

.bb-rating { display: flex; align-items: center; gap: 9px; }

/* The numeral. Display weight, tight tracking, and the one place --bb-trust is
   allowed to be text rather than fill: at 21px it clears AA on paper with room
   to spare, which the same green does not at 12px (that is --bb-trust-ink). */
.bb-score {
  font: var(--bb-w-semibold) 21px/1 var(--bb-font);
  letter-spacing: -0.8px;
  color: var(--bb-trust);
  font-variant-numeric: tabular-nums;
}
/* On the venue hero the score sits on photography, so it goes cream with the
   rest of the line and the rule and dots drop away entirely. */
.bb-score--onphoto { font-size: 23px; color: var(--bb-on-navy-ink); }
/* The reviews panel leads with the score at poster size. Deep green, not the
   fill green: at this size it is unambiguously a headline. */
.bb-score--xl {
  font-size: 44px;
  letter-spacing: -1.5px;
  color: var(--bb-trust-ink);
}

.bb-rating__rule {
  width: 1px;
  height: 22px;
  background: var(--bb-hairline);
  flex: none;
}

.bb-rating__stack {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.bb-dots { display: inline-flex; gap: 2.5px; align-items: center; }

.bb-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--bb-trust);
  flex: none;
}
/* Half fill is a hard-stop gradient, not an opacity — the empty side must read
   as the empty color, not as washed-out jade. */
.bb-dot--half {
  background: linear-gradient(90deg, var(--bb-trust) 0 50%, var(--bb-hairline) 50% 100%);
}
.bb-dot--empty { background: var(--bb-hairline); }
/* The filter rail draws the same dots one step down, inside a checkbox label. */
.bb-dots--sm .bb-dot { width: 7px; height: 7px; }
/* The reviews panel draws them one step up, under the poster-size score. */
.bb-dots--lg { gap: 3px; }
.bb-dots--lg .bb-dot { width: 11px; height: 11px; }

/* "Exceptional · 1,204 travelers". The verdict is ink, the count is soft: the
   word is the venue's, the number is ours. */
.bb-count {
  font: var(--bb-w-regular) 11.5px/1.2 var(--bb-font);
  color: var(--bb-ink-soft);
  font-variant-numeric: tabular-nums;
}
.bb-count b { color: var(--bb-ink); font-weight: var(--bb-w-semibold); }

/* The seal survives for the two places a numeral does not fit: the checkout
   summary line and the dashboard's review tables. The export writes it on the
   badge tint rather than solid jade — solid jade at pill size put white text
   at the AA line, and this reads as the same family as the ✓ Verified pill. */
.bb-seal {
  display: inline-flex;
  align-items: center;
  background: var(--bb-tint-jade-strong);
  color: var(--bb-trust-deep);
  border-radius: var(--bb-r-chip);
  padding: 2px 9px;
  font: var(--bb-w-semibold) 12px/1.5 var(--bb-font);
  font-variant-numeric: tabular-nums;
}

/* The horizontal score bars in the reviews panel — "Therapists 4.9",
   "Excellent 1,096". Track is the hairline, fill is jade. */
.bb-meter {
  flex: 1;
  height: 6px;
  background: var(--bb-hairline);
  border-radius: var(--bb-r-pill);
  overflow: hidden;
  min-width: 0;
}
.bb-meter__fill {
  height: 100%;
  background: var(--bb-trust);
  border-radius: var(--bb-r-pill);
}
.bb-meter-row {
  display: flex;
  align-items: center;
  gap: 12px;
  font: var(--bb-w-regular) 12px/1.4 var(--bb-font);
}
.bb-meter-row__val {
  font-weight: var(--bb-w-semibold);
  font-variant-numeric: tabular-nums;
  text-align: right;
}


/* ---------- Chips and pills ----------
   Urgency is plain rust text at weight 600. It is never a filled badge and
   never red — see the doc's anti-SaaS rule 6. */

/* Time chips. The one chip the export keeps square-ish: 8px, because a row of
   pill-shaped times reads as tags rather than as a clock. */
.bb-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bb-tint-blue);
  color: var(--bb-primary);
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 6px 13px;
  font: var(--bb-w-semibold) 11.5px/1.4 var(--bb-font);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.bb-chip--selected {
  background: var(--bb-primary);
  color: var(--bb-on-navy-ink);
}
.bb-chip--gone {
  background: transparent;
  border: 1px dashed var(--bb-hairline);
  color: var(--bb-ink-soft);
  text-decoration: line-through;
  cursor: default;
}
/* Not a time but the same row: "Day ticket", "Walk-ins welcome". */
.bb-chip--trust {
  background: var(--bb-tint-jade);
  color: var(--bb-trust-ink);
  cursor: default;
}

/* Tag and character pills — "Sunset favorite", "Locals' pick", "Next up ·
   Saturday". Fully round, blue tint, no border. */
.bb-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--bb-tint-blue);
  color: var(--bb-primary);
  border-radius: var(--bb-r-chip);
  padding: 4px 11px;
  font: var(--bb-w-semibold) 12px/1.5 var(--bb-font);
}
/* Trust pills — ✓ Verified, ✓ Confirmed. Jade tint, green ink. */
.bb-pill--trust {
  background: var(--bb-tint-jade);
  color: var(--bb-trust-ink);
}
/* Quiet review tags — not booked / booked but not arrived. Hairline, not rust:
   they are facts, not failures. */
.bb-pill--quiet {
  background: var(--bb-page);
  color: var(--bb-ink-soft);
  border: 1px solid var(--bb-hairline);
}
/* One step greener and darker: the badge that has to hold on photography, and
   the state chips that lead a row — Travelers' Choice, ✓ Verified venue. */
.bb-pill--award {
  background: var(--bb-tint-jade-strong);
  color: var(--bb-trust-deep);
  font-weight: var(--bb-w-semibold);
}
/* "Confirming with venue" — a pending state, so rust, but a state chip needs a
   fill to sit in a row of filled chips. Mixed at 10%, deliberately lighter
   than --bb-tint-rust, which is a panel value. */
.bb-pill--rust {
  background: rgba(184, 83, 31, 0.10);
  color: var(--bb-urgency);
  font-weight: var(--bb-w-semibold);
}
/* Solid navy: the selected filter chip, the one that says "you are here". */
.bb-pill--on {
  background: var(--bb-primary);
  color: var(--bb-on-navy-ink);
}
/* Outline: the unselected half of that same row, and the quick-picks under the
   search deck. Border darkens to navy on hover, like every secondary control. */
.bb-pill--out {
  background: var(--bb-surface);
  color: var(--bb-ink);
  border: 1px solid var(--bb-hairline);
  cursor: pointer;
  transition: border-color .15s ease-out;
}
.bb-pill--out:hover { border-color: var(--bb-primary); }
/* On photography: a frosted count or label over a destination tile. */
.bb-pill--onphoto {
  background: rgba(252, 250, 246, 0.16);
  border: 1px solid rgba(251, 247, 240, 0.34);
  color: var(--bb-on-navy-ink);
}
/* Sitting on a photo but reading as paper — the venue hero's location tag and
   its "48 photos" control. */
.bb-pill--frosted {
  background: rgba(253, 252, 249, 0.92);
  color: var(--bb-ink);
}
/* For pills that sit inside a heading line rather than on their own row. */
.bb-pill--tight { padding: 3px 10px; font-size: 11px; }
/* Roomier: the pills on the venue hero and the quick-picks row. */
.bb-pill--lg { padding: 7px 15px; }

/* The rust dot that marks a place. Never decorative — it means "this is where,
   specifically". */
.bb-dot-here {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--bb-urgency);
  display: inline-block;
  flex: none;
}
/* Its jade twin: live, open, confirmed. */
.bb-dot-live {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--bb-trust);
  display: inline-block;
  flex: none;
}

.bb-urgency {
  color: var(--bb-urgency);
  font: var(--bb-w-semibold) 12.5px/1.45 var(--bb-font);
}
/* Green words. Not the fill green — see --bb-trust-ink. */
.bb-trust-note {
  color: var(--bb-trust-ink);
  font: var(--bb-w-semibold) 12px/1.5 var(--bb-font);
}

/* The jade tick that opens a reassurance line on the booking card. A real
   character rather than a disc, because it sits inline with the sentence. */
.bb-tick {
  display: flex;
  gap: 10px;
  font: var(--bb-w-regular) 12px/1.5 var(--bb-font);
}
.bb-tick::before {
  content: "\2713";
  color: var(--bb-trust);
  font-weight: var(--bb-w-semibold);
  font-size: 13px;
  line-height: 1.35;
  flex: none;
}
.bb-tick b { font-weight: var(--bb-w-semibold); }


/* ---------- Buttons ----------
   Fully round again, per the export. Sentence case labels — "Request a
   listing", never "REQUEST A LISTING". Jade solid is reserved for review
   actions. */

.bb-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border-radius: var(--bb-r-btn);
  padding: 12px 24px;
  font: var(--bb-w-semibold) 12.5px/1.2 var(--bb-font);
  font-family: var(--bb-font);
  cursor: pointer;
  border: 1px solid transparent;
  transition: border-color .15s ease-out, background-color .15s ease-out;
}
.bb-btn--primary {
  background: var(--bb-primary);
  color: var(--bb-on-navy-ink);
}
.bb-btn--primary:hover { background: var(--bb-primary-deep); text-decoration: none; }
.bb-btn--secondary {
  background: transparent;
  color: var(--bb-primary);
  border-color: var(--bb-hairline);
  font-weight: var(--bb-w-semibold);
}
.bb-btn--secondary:hover { border-color: var(--bb-primary); }
/* The secondary that has already been chosen, or that is the page's own second
   action rather than an escape hatch — border in navy from the start. */
.bb-btn--outline {
  background: transparent;
  color: var(--bb-primary);
  border-color: var(--bb-primary);
}
.bb-btn--review {
  background: var(--bb-tint-jade-strong);
  color: var(--bb-trust-deep);
}
/* On navy: the field-guide band and the owners' closing panel. */
.bb-btn--onnavy {
  background: var(--bb-on-navy-ink);
  color: var(--bb-primary);
}
/* Full width inside a card — "Check availability", "Save my bookings". */
.bb-btn--block { width: 100%; padding-inline: 0; }
/* The primary that closes a page: 15px padding, 14.5px label. */
.bb-btn--lg { padding: 15px 32px; font-size: 14.5px; }
/* Dense surfaces — table rows, document slots — where a full-size button would
   set the row height instead of sitting inside it. */
.bb-btn--sm { padding: 9px 18px; font-size: 11.5px; }
.bb-btn[disabled] { opacity: .45; cursor: not-allowed; }

/* Circular step controls: the hero reel arrows and the carousel arrows. */
.bb-step {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--bb-hairline);
  background: var(--bb-surface);
  color: var(--bb-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  cursor: pointer;
  transition: border-color .15s ease-out;
}
.bb-step:hover { border-color: var(--bb-primary); }
/* The same control on photography: frosted, no paper behind it. */
.bb-step--onphoto {
  width: 32px;
  height: 32px;
  font-size: 14px;
  background: rgba(28, 26, 23, 0.40);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-color: rgba(251, 247, 240, 0.20);
  color: var(--bb-on-navy-ink);
}
.bb-step--onphoto:hover {
  background: rgba(28, 26, 23, 0.65);
  border-color: rgba(251, 247, 240, 0.20);
}


/* ---------- Form fields ----------
   The auth pages style their own inputs (`.auth-field`) because they predate
   this block and carry a peek button and per-field error wiring. These are the
   plain primitives every other surface uses. */

.bb-input,
.bb-select {
  width: 100%;
  border: 1px solid var(--bb-hairline);
  border-radius: var(--bb-r-field);
  background: var(--bb-surface);
  padding: 11px 13px;
  font: var(--bb-w-regular) 13px/1.4 var(--bb-font);
  color: var(--bb-ink);
  outline: none;
}
.bb-textarea {
  min-height: 74px;
  resize: vertical;
}
/* Radios and checkboxes in the filter rail and the consent rows. The export
   leaves them as native controls and only sets the accent — geometry the
   browser already draws correctly is geometry we do not redraw. */
.bb-check { accent-color: var(--bb-primary); }
.bb-check-row {
  display: flex;
  gap: 8px;
  align-items: center;
  cursor: pointer;
  font: var(--bb-w-regular) 12.5px/1.4 var(--bb-font);
}
.bb-input::placeholder { color: var(--bb-ink-soft); }
.bb-input:focus,
.bb-select:focus,
.bb-textarea:focus {
  border-color: var(--bb-primary);
  box-shadow: 0 0 0 3px rgba(26, 87, 147, .12);
}
/* Export: the field label is ink, not soft. A form the traveler has to fill in
   reads its own labels first; the soft grey is for the hint underneath. */
.bb-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}
.bb-field__label {
  display: block;
  font: var(--bb-w-semibold) 11.5px/1.45 var(--bb-font);
  color: var(--bb-ink);
}
.bb-field__hint {
  display: block;
  font: var(--bb-w-regular) 11px/1.5 var(--bb-font);
  color: var(--bb-ink-soft);
}
.bb-field__err {
  display: block;
  font: var(--bb-w-semibold) 11px/1.5 var(--bb-font);
  color: var(--bb-urgency);
}


/* ---------- List page title ----------
   Smaller than the marketing `h1`. A console screen is read at a glance and
   repeatedly, so the title identifies the screen rather than opening it. */

.bb-h1--list {
  font: var(--bb-w-semibold) 27px/1.15 var(--bb-font);
  letter-spacing: -1px;
  color: var(--bb-ink);
  margin: 0;
}


/* ---------- Icon discs ----------
   Pure geometry only — circles, lines, arcs. No icon fonts, no illustration
   packs, no emoji. If a concept needs more than three simple shapes, use words. */

.bb-disc {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--bb-tint-blue);
  color: var(--bb-primary);
  flex: none;
}
.bb-disc--jade { background: var(--bb-tint-jade); color: var(--bb-trust); }
.bb-disc--rust { background: rgba(184, 83, 31, 0.12); color: var(--bb-urgency); }
/* Numbered step discs — the four steps on the owners page, the 1/2/3 on the
   reserve form. Solid, because a step number is the thing itself, not a hint. */
.bb-disc--num {
  background: var(--bb-primary);
  color: var(--bb-on-navy-ink);
  font: var(--bb-w-semibold) 12.5px/1 var(--bb-font);
}
.bb-disc--num-sm { width: 22px; height: 22px; font-size: 11.5px; }
.bb-disc--done { background: var(--bb-tint-jade-strong); color: var(--bb-trust-deep); }

/* The square counterpart: house rules, "before you go", the checklist rows. A
   30-32px rounded square holding nothing but its tint — the shape is the
   colour-coding, and the words beside it carry the meaning. */
.bb-tile-icon {
  width: 30px;
  height: 30px;
  border-radius: 7px;
  background: var(--bb-tint-blue);
  flex: none;
}
.bb-tile-icon--jade { background: var(--bb-tint-jade); }
.bb-tile-icon--rust { background: rgba(184, 83, 31, 0.12); }
.bb-tile-icon--lg { width: 32px; height: 32px; border-radius: 8px; }


/* ---------- Dividers ----------
   Hairlines separate list rows, not boxes. Do not wrap a group of rows in a
   border as well — that is the box the doc is trying to avoid. */

.bb-divider { height: 1px; background: var(--bb-hairline); border: 0; margin: 0; }

.bb-list { list-style: none; margin: 0; padding: 0; }
.bb-list__item { padding: 14px 0; border-top: 1px solid var(--bb-hairline); }
.bb-list__item:first-child { border-top: 0; }


/* ---------- Photography ----------
   Photo heroes, never gradient heroes. The scrim is warm — built from
   rgba(28,26,23,...) with navy at the top. Never gray, never purple. */

.bb-photo { position: relative; overflow: hidden; }
.bb-photo > img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Scrims. Warm dark, built from rgba(28,26,23,...) with the navy carrying the
   coloured end. Never grey, never purple. The export uses a different one per
   job, so they are separate classes rather than one compromise gradient.

   --hero: raked across from the left, so the headline sits on the dark side and
   the photo keeps its light side. */
.bb-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    rgba(26, 87, 147, 0.60) 0%,
    rgba(28, 26, 23, 0.40) 48%,
    rgba(28, 26, 23, 0.10) 100%
  );
}
/* A rust wash rising off the bottom edge of the home hero — the warmth that
   keeps the fold from reading blue. Sits over .bb-scrim, under the content. */
.bb-scrim--warm {
  background: linear-gradient(
    0deg,
    rgba(154, 74, 28, 0.30) 0%,
    rgba(154, 74, 28, 0.10) 16%,
    rgba(154, 74, 28, 0) 34%
  );
}
/* Tiles and cards, where a name and a count sit on the bottom edge. */
.bb-scrim--tile {
  background: linear-gradient(
    0deg,
    rgba(28, 26, 23, 0.78) 0%,
    rgba(28, 26, 23, 0.18) 46%,
    rgba(28, 26, 23, 0) 72%
  );
}
/* Destination tiles and the almanac panel, where the dark end goes navy so the
   photo grades into the brand rather than into black. */
.bb-scrim--deep {
  background: linear-gradient(
    0deg,
    rgba(26, 87, 147, 0.82) 0%,
    rgba(28, 26, 23, 0.22) 44%,
    rgba(28, 26, 23, 0) 70%
  );
}
/* The venue hero: nothing at the top, a heavy foot, because the whole title
   block sits on the bottom quarter. */
.bb-scrim--venue {
  background: linear-gradient(
    180deg,
    rgba(28, 26, 23, 0) 30%,
    rgba(28, 26, 23, 0.30) 58%,
    rgba(28, 26, 23, 0.72) 78%,
    rgba(28, 26, 23, 0.92) 100%
  );
}

/* Every hero photo carries a location tag, because photos are rotated
   editorially and the traveler needs to know where they are looking. */
/* Where the photo was taken. The export moves this out of a frosted pill and
   onto the reel row as plain cream text — the arrows and dots are already a
   control cluster, and a second pill beside them read as a button. */
.bb-photo-tag {
  font: var(--bb-w-regular) 11.5px/1.4 var(--bb-font);
  color: rgba(251, 247, 240, 0.80);
}

/* Travelers' Choice, ✓ Verified venue — the award pill sitting on a card
   photo. Clipped rather than wrapped: it must never push the save-heart. */
.bb-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  max-width: calc(100% - 62px);
  background: var(--bb-tint-jade-strong);
  color: var(--bb-trust-deep);
  border-radius: var(--bb-r-chip);
  padding: 5px 12px;
  font: var(--bb-w-semibold) 11.5px/1.4 var(--bb-font);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

.bb-save {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--bb-hairline);
  background: var(--bb-page);
  color: var(--bb-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  cursor: pointer;
}
.bb-save[aria-pressed="true"] { color: var(--bb-urgency); }
.bb-save[aria-pressed="true"] svg path { fill: currentColor; }


/* ---------- Site footer ----------
   Rebuilt on the 2026-08-24 export: a full navy footer with five columns, not
   the hairline strip it replaced. Every page carries this one — it is the last
   thing a traveler sees on every screen, and the navy is what makes the warm
   page above it read as paper.

   It lives in the system stylesheet rather than in css/home.css because it is
   site-wide chrome and the legal, status and 404 pages load nothing but this
   file. Colour behaviour comes from .bb-onnavy above; this is the geometry. */

.site-foot { margin-top: 56px; }

.site-foot__in {
  display: grid;
  grid-template-columns: 268px repeat(4, minmax(0, 1fr));
  gap: 40px;
  padding-block: 48px 28px;
}

.site-foot__mark {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 12px;
}
.site-foot__mark:hover { text-decoration: none; }
.site-foot__arc { display: none; }
.site-foot__lockup { display: block; width: 154px; height: auto; }
.site-foot__word {
  font: var(--bb-w-bold) 19px/1 var(--bb-font-logo);
  letter-spacing: 1px;
  color: var(--bb-primary);
  text-transform: lowercase;
}

.site-foot__tag {
  margin: 0 0 16px;
  max-width: 30ch;
  font: var(--bb-w-regular) 12.5px/1.6 var(--bb-font);
  color: rgba(251, 247, 240, 0.72);
}

.site-foot__prefs { display: flex; gap: 8px; flex-wrap: wrap; }

/* The language switcher is the footer's one control. i18n.js ships its own
   light styling, so it is restated here for navy rather than inherited. */
.site-foot__prefs .ji-sw__btn {
  border: 1px solid rgba(251, 247, 240, 0.28);
  border-radius: var(--bb-r-btn);
  background: transparent;
  padding: 7px 14px;
  font: var(--bb-w-medium) 12px/1 var(--bb-font);
  color: var(--bb-on-navy-ink);
}
.site-foot__prefs .ji-sw__btn:hover {
  border-color: var(--bb-on-navy-ink);
  color: var(--bb-on-navy-ink);
}

.site-foot__h {
  margin: 0 0 12px;
  font: var(--bb-w-semibold) 12px/1.4 var(--bb-font);
  color: var(--bb-on-navy-ink);
}

.site-foot__links { display: flex; flex-direction: column; gap: 8px; }
.site-foot__links a {
  font: var(--bb-w-regular) 12.5px/1.4 var(--bb-font);
  color: rgba(251, 247, 240, 0.72);
}
.site-foot__links a:hover { color: var(--bb-on-navy-ink); text-decoration: none; }

.site-foot__bar { border-top: 1px solid rgba(251, 247, 240, 0.18); }
.site-foot__bar-in {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
  padding-block: 18px;
  font: var(--bb-w-regular) 12px/1.4 var(--bb-font);
  color: rgba(251, 247, 240, 0.62);
}
.site-foot__bar-in a { color: rgba(251, 247, 240, 0.62); }
.site-foot__bar-in a:hover { color: var(--bb-on-navy-ink); text-decoration: none; }
.site-foot__made { margin-left: auto; }

/* Holipass closes on a bright paper tint rather than an institutional dark
   slab. The brand lockup stays full colour and the Papaya rule carries the
   journey motif into the final edge of the page. */
.site-foot.bb-onnavy {
  position: relative;
  background: #EEF0FF;
  color: var(--bb-ink);
}
.site-foot.bb-onnavy::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 4px;
  background: var(--bb-papaya);
}
.site-foot.bb-onnavy a,
.site-foot.bb-onnavy .site-foot__h { color: var(--bb-ink); }
.site-foot.bb-onnavy .site-foot__tag,
.site-foot.bb-onnavy .site-foot__links a,
.site-foot.bb-onnavy .site-foot__bar-in,
.site-foot.bb-onnavy .site-foot__bar-in a { color: var(--bb-ink-mid); }
.site-foot.bb-onnavy .site-foot__links a:hover,
.site-foot.bb-onnavy .site-foot__bar-in a:hover { color: var(--bb-primary); }
.site-foot.bb-onnavy .site-foot__bar { border-top-color: #D8DBF2; }
.site-foot.bb-onnavy .site-foot__prefs .ji-sw__btn {
  border-color: #C9CEF9;
  color: var(--bb-primary);
}
.site-foot.bb-onnavy .site-foot__prefs .ji-sw__btn:hover {
  border-color: var(--bb-primary);
  color: var(--bb-primary);
}


@media (max-width: 1040px) {
  .site-foot__in { grid-template-columns: 200px repeat(2, minmax(0, 1fr)); gap: 32px; }
}
@media (max-width: 860px) {
  .site-foot__in { grid-template-columns: 1fr 1fr; gap: 30px 24px; }
  .site-foot__brand { grid-column: 1 / -1; }
  .site-foot__made { margin-left: 0; flex: 1 0 100%; }
}


/* ---------- Layout ---------- */

.bb-column {
  max-width: var(--bb-column);
  margin: 0 auto;
  padding-inline: 24px;
}

.bb-grid-4 {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
}
.bb-grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}
.bb-grid-6 {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 12px;
}
/* Content beside a sticky rail. The export runs this at 44px on the venue,
   reserve and confirmed pages and 32px on search results. */
.bb-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--bb-booking-card);
  gap: 44px;
  align-items: start;
}

.bb-row-listing {
  display: grid;
  grid-template-columns: var(--bb-row-photo) 1fr;
  gap: 20px;
  align-items: start;
}

.bb-booking-card {
  position: sticky;
  top: 24px;
  background: var(--bb-surface);
  border: 1px solid var(--bb-hairline);
  border-radius: var(--bb-r-feature);
  padding: 22px;
  box-shadow: var(--bb-shadow-card);  /* one of the two floating cards */
}
/* The rail itself, when it holds more than the one card. */
.bb-rail {
  position: sticky;
  top: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-self: start;
}


/* ---------- Navy surfaces ----------
   The export puts three things on solid navy: the field-guide band, the
   owners' closing panel, and the footer. On navy the ink goes cream, the
   secondary ink goes cream at 72%, and jade and rust step up to the bright
   variants — the paper values go muddy against it. Anything inside a
   .bb-onnavy inherits that, so a component does not need a navy twin. */

.bb-onnavy {
  background: var(--bb-primary);
  color: var(--bb-on-navy-ink);
}
.bb-onnavy a { color: var(--bb-on-navy-ink); }
.bb-onnavy .bb-sub,
.bb-onnavy .bb-meta,
.bb-onnavy .bb-count { color: rgba(251, 247, 240, 0.72); }
.bb-onnavy .bb-body { color: rgba(251, 247, 240, 0.86); }
.bb-onnavy .bb-dot-live { background: var(--bb-on-navy-trust); }
.bb-onnavy .bb-dot-here { background: var(--bb-on-navy-urgency); }
.bb-onnavy .bb-divider { background: rgba(251, 247, 240, 0.18); }

/* The export is a fixed 1140px prototype with no breakpoints at all. Everything
   below is an addition, not a port: the 6-, 4- and 3-up grids and the two
   sticky rails all have to give before the column does. */
@media (max-width: 1040px) {
  .bb-grid-6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .bb-split  { grid-template-columns: 1fr; gap: 28px; }
  .bb-booking-card,
  .bb-rail { position: static; }
}
@media (max-width: 900px) {
  .bb-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bb-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bb-row-listing { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .bb-grid-4,
  .bb-grid-3 { grid-template-columns: 1fr; }
  .bb-grid-6 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bb-column { padding-inline: 18px; }
  .bb-sec-head { flex-wrap: wrap; }
}
