/* GBH Business Discovery — customer-facing flow.
   Brand tokens mirrored from assets/css/gbh-tokens.css (the current, live
   getbusinesshandled.com site's own approved v3 palette — colors/fonts
   only, no shared code/asset pipeline, since gbh-platform is served from
   its own independent docroot).

   2026-09-07 visual redesign: adapts the current PRODUCTION Discovery
   (getbusinesshandled.com/ai-business-discovery-agent.html, inspected
   directly) as the visual/UX quality reference — a calmer, editorial,
   "guided conversation" register instead of a boxed-card admin-form look.
   Architecture/routing/adaptive logic is completely unchanged; this file
   only restyles the same shared classes every Discovery template already
   uses (.gbh-d-card, .gbh-d-eyebrow, .gbh-d-options/.gbh-d-option,
   .gbh-d-back-link, .gbh-d-btn, .gbh-discovery-progress, ...) — so the
   same visual system reaches every page (Stage, Offer, Business Type,
   generic single/multi-select, entry/consent, Snapshot) automatically,
   with zero page-specific CSS and zero template markup changes required
   for the redesign itself. */
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600;9..40,700&family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600;9..144,650&display=swap');

:root{
  --gbh-navy:#173B57;
  --gbh-navy-2:#1F4864;
  --gbh-cream:#F8F5EF;
  --gbh-paper:#FFFFFF;
  --gbh-line:#DCE4E8;
  --gbh-line-strong:#C7D3D8;
  /* GLOBAL ACCENT COLOR CHANGE (2026-09-19, owner-approved): #159BC4 -> #3989C8,
     the single source-of-truth definition — every other rule in this file
     reads the accent via var(--gbh-azure)/var(--gbh-azure-wash), so this one
     line cascades the new accent across every Discovery/Snapshot/booking
     page (buttons, links, progress bars, focus rings, selected-state dots)
     with no other edits needed in this file. */
  --gbh-azure:#3989C8;
  --gbh-azure-wash:#E7F2F6;
  --gbh-text:#667785;
  --gbh-text-2:#8FA0AB;
  --gbh-row-text:#2A5170;    /* production's own answer-row text color — slightly lighter than heading navy */
  --gbh-error:#B3261E;
  --gbh-error-wash:#FBEAE9;
  --ff-heading:'Fraunces', Georgia, serif;
  --ff-body:'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
}

*{ box-sizing: border-box; }
html,body{ margin:0; padding:0; }
/* The browser's own [hidden]{display:none} UA rule is silently defeated by
   ANY author rule that sets `display` on the same element (author rules
   always win over UA ones, regardless of specificity) — several rules
   below (.gbh-d-option, .gbh-d-type-search-results, etc.) do exactly
   that, so `hidden` must be reasserted explicitly here or toggling it via
   JS (Business Type's search results/default rows, the Other detail
   block) silently does nothing. */
[hidden]{ display: none !important; }
body{
  background: var(--gbh-cream);
  color: var(--gbh-text);
  font-family: var(--ff-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
h1,h2,h3,h4{ font-family: var(--ff-heading); color: var(--gbh-navy); margin: 0 0 0.5em; font-weight: 600; }
a{ color: var(--gbh-azure); }

.gbh-discovery-shell{ min-height: 100vh; display: flex; flex-direction: column; }

/* Lightweight, customer-facing header (production reference: a thin bar —
   GBH mark + wordmark, no heavy Portal/admin chrome) rather than a solid
   navy admin-style bar. */
.gbh-discovery-topbar{
  background: var(--gbh-cream); border-bottom: 1px solid var(--gbh-line);
  padding: 16px 24px;
}
.gbh-discovery-topbar-inner{
  max-width: 640px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between;
}
/* HEADER NAVIGATION FIX (2026-09-24): now a real <a>, not a plain <div>
   — text-decoration:none is the only addition needed to preserve exact
   current appearance; color/font/layout are already fully specified on
   this class regardless of tag, overriding the UA anchor default.
   FINAL GLOBAL HEADER STANDARDIZATION (2026-09-25, owner instruction):
   font-family/weight/size/gap now match the homepage's own .gbh-brand
   exactly (verified live: Fraunces/Georgia/serif, 600, 17px, 14px gap)
   — var(--ff-heading) is the SAME Fraunces token already defined in this
   file, not a new font; color was already identical (both #173B57). No
   more separate, smaller "portal/discovery" text size. */
.gbh-discovery-brand{ font-family: var(--ff-heading); font-weight: 600; font-size: 17px; color: var(--gbh-navy); display: flex; align-items: center; gap: 14px; text-decoration: none; }
/* CANONICAL LOGO RESTORATION (2026-09-19, owner instruction): was a
   CSS-drawn text-in-circle "GBH" placeholder, never migrated to the
   real approved circular mark (assets/images/logos/gbh-mark.svg,
   already circular in the artwork itself) the way the main marketing
   site's .gbh-header already was — see that stylesheet's own img.mark
   rule for the same border:none/object-fit:contain treatment this
   mirrors. */
.gbh-discovery-brand-mark{
  /* GLOBAL LOGO STANDARDIZATION (2026-09-25, owner instruction): matches
     the homepage's own canonical treatment (getbusinesshandled.com's
     .gbh-header .gbh-brand img.mark, verified live) exactly — transparent
     interior, a real 2px azure ring drawn via border (not relying on the
     SVG artwork's own internal ring alone, which is what the superseded
     white-backing fix below was compensating for), and matching padding.
     Replaces two prior, now-superseded fixes:
       - RING VISIBILITY FIX (2026-09-19): added an opaque white circular
         backing because the asset's own internal ring alpha-blended away
         with no backing at all. This external azure border achieves the
         same visibility a different, now-approved way, so the white
         backing is no longer needed anywhere.
       - LEGIBILITY FOLLOW-UP (2026-09-25, earlier today): bumped
         28->34->40px for legibility, as a "portal/discovery-specific"
         size distinct from the homepage's own 50px. FINAL GLOBAL HEADER
         STANDARDIZATION (2026-09-25, later the same day, owner
         instruction) removes that distinction outright: the homepage
         header IS the standard everywhere, full stop — 50px, matching
         its border/padding exactly (already true below).
     var(--gbh-azure) is the same #3989C8 token already used everywhere
     else in this file — no new color introduced. */
  width: 50px; height: 50px; flex-shrink: 0; display: block; object-fit: contain;
  border: 2px solid var(--gbh-azure); padding: 5px; box-sizing: border-box;
  background: transparent; border-radius: 50%;
}
.gbh-discovery-brand span{ font-weight: 400; opacity: 0.75; }
.gbh-discovery-exit{ font-size: 13.5px; color: var(--gbh-text); text-decoration: none; font-weight: 600; }
.gbh-discovery-exit:hover{ color: var(--gbh-navy); }

/* Wider, cardless conversational column (production reference: ~600px, no
   border/shadow/background of its own) — replaces the old narrower,
   boxed-card layout. */
.gbh-discovery-main{ flex: 1; width: 100%; max-width: 640px; margin: 0 auto; padding: 40px 20px 72px; }

.gbh-discovery-footer{
  text-align: center; font-size: 12.5px; color: var(--gbh-text-2); padding: 20px; border-top: 1px solid var(--gbh-line);
}

/* Cardless by default — the "quality reference" is a plain content flow,
   not a bordered/shadowed panel. */
.gbh-d-card{ background: transparent; border: none; border-radius: 0; padding: 0; box-shadow: none; }

.gbh-d-eyebrow{
  font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--gbh-text); margin-bottom: 10px; display: block;
}
h1{ font-size: 26px; line-height: 1.25; }
.gbh-d-lede{ color: var(--gbh-text); font-size: 15.5px; margin: 10px 0 28px; }
/* Acknowledgment microcopy (2026-09-07 correction, matching production's
   own .ack rule): a quiet muted line confirming the customer was heard —
   never a colored success box/alert. The ✓ is written directly into the
   PHP-rendered text (matching production's own convention), not a ::before
   pseudo-element, so it is never duplicated. */
.gbh-d-ack{ color: var(--gbh-text-2); font-size: 13px; font-weight: 600; margin-bottom: 22px; }

.gbh-d-field{ margin-bottom: 20px; }
.gbh-d-field label{ display: block; font-weight: 600; font-size: 14.5px; color: var(--gbh-navy); margin-bottom: 6px; }
.gbh-d-field .gbh-d-hint{ font-size: 13px; color: var(--gbh-text-2); margin-top: 5px; }
/* BOOKING TIMEZONE INDICATION (2026-09-19, live-verification pass): the
   real Google Calendar slots are computed in BookingConfig::GBH_TIMEZONE
   (America/Chicago) but nothing on the page told the customer that --
   confirmed missing during live verification against real availability. */
.gbh-d-timezone-note{ font-size: 12.5px; color: var(--gbh-text-2); margin: -2px 0 12px; }
.gbh-d-hint{ font-size: 13.5px; color: var(--gbh-text-2); margin: -8px 0 16px; }
.gbh-d-field input[type=text], .gbh-d-field input[type=email], .gbh-d-field input[type=tel], .gbh-d-field input[type=url]{
  width: 100%; padding: 12px 14px; border: 1.5px solid var(--gbh-line-strong); border-radius: 8px;
  font-family: var(--ff-body); font-size: 15.5px; color: var(--gbh-navy); background: var(--gbh-paper);
}
.gbh-d-field input:focus{ outline: none; border-color: var(--gbh-azure); box-shadow: 0 0 0 3px var(--gbh-azure-wash); }
/* Multi-line answer support (2026-09-10 design-parity pass) — the same
   field treatment as the single-line inputs above, additive only (no
   existing rule changed); the first Discovery template to need a
   textarea is the AI Lab's fundamentals screen, but this is a shared,
   reusable rule available to any Discovery template. */
.gbh-d-field textarea{
  width: 100%; padding: 12px 14px; border: 1.5px solid var(--gbh-line-strong); border-radius: 8px;
  font-family: var(--ff-body); font-size: 15.5px; color: var(--gbh-navy); background: var(--gbh-paper);
  min-height: 110px; resize: vertical;
}
.gbh-d-field textarea:focus{ outline: none; border-color: var(--gbh-azure); box-shadow: 0 0 0 3px var(--gbh-azure-wash); }

/* Answer rows (2026-09-07 correction, reproduced EXACTLY from the real
   Bexon prototype source — GBH-Bexon-Concept's ai-business-discovery-agent.html,
   its own ".opt"/".opt:hover"/".opt.selected"/".opt .mark" rules — not
   inferred from this file's own prior version and not the legacy live
   DOM. Bexon's row is a flex container with justify-content:space-between
   and exactly two visual children: the label text, and a small fixed-
   width ".mark" pushed to the far right by that space-between — its
   ".opt:hover" changes ONLY text color, never a background, and
   ".opt.selected" is likewise text-color/weight only ("color:var(--ink);
   font-weight:700"), never a background fill. Reproduced here as the
   CUSTOMER-VISIBLE result — text left, indicator far right, no
   background change ever, on hover or on selection — while keeping a
   real <input type=radio|checkbox> (Bexon's own ".mark" is a hidden span
   in a non-semantic div, which this build deliberately does not copy):
   the input is moved to the row's visual end purely via flex `order`,
   never a markup/DOM change, so no template or JS changed for this fix. */
.gbh-d-options{ display: flex; flex-direction: column; }
.gbh-d-option{
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; border: none;
  border-bottom: 1px solid var(--gbh-line); border-radius: 0; padding: 15px 2px; cursor: pointer;
  transition: color .15s; background: none;
  /* BOOKING PRESENTATION FIX (2026-09-19, live-verification pass): the
     date row is a real <a> (see the comment above on .gbh-d-option.is-
     selected), and an anchor's own default color/underline paints
     through its child <span> regardless of the span's own color rule
     below -- text-decoration is not reset by a descendant color change.
     Confirmed live: without this, the date list rendered as raw blue,
     underlined browser links, exactly the "raw HTML form" look this
     restoration was meant to remove. Harmless on the radio <label>
     variant (labels have no default color/underline to begin with). */
  color: inherit; text-decoration: none;
}
.gbh-d-option:visited{ color: inherit; }
.gbh-d-options .gbh-d-option:first-child{ border-top: 1px solid var(--gbh-line); }
.gbh-d-option:hover{ background: none; }
.gbh-d-option:hover span{ color: var(--gbh-navy); }
/* Selected-state text treatment (".opt.selected{color:var(--ink);
   font-weight:700}") — :has() targets the row from its own real input,
   never a JS-added class; a browser without :has() support simply keeps
   the unselected text weight/color, a harmless, non-blocking fallback. */
.gbh-d-option:has(input:checked) span{ color: var(--gbh-navy); font-weight: 700; }
/* BOOKING PRESENTATION RESTORATION (2026-09-19): the date-selection row is
   a plain <a> link (a real GET navigation, not a form input — see
   consultation_booking.php/full-snapshot-platform/booking.php), so there
   is no input for :has(input:checked) to target. Same bold-navy treatment,
   applied via a server-rendered class on the already-selected date instead. */
.gbh-d-option.is-selected span{ color: var(--gbh-navy); font-weight: 700; }
.gbh-d-option input{
  appearance: none; -webkit-appearance: none; margin: 2px 0 0; flex-shrink: 0; order: 1;
  width: 18px; height: 18px; border-radius: 50%; border: none; background: transparent;
  position: relative; cursor: pointer;
}
.gbh-d-option input[type=checkbox]{ border-radius: 4px; }
.gbh-d-option input[type=radio]:checked::after{
  content: "●"; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: var(--gbh-azure); font-size: 10px; line-height: 1;
}
.gbh-d-option input[type=checkbox]:checked::after{
  content: "✓"; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: var(--gbh-azure); font-size: 15px; font-weight: 700; line-height: 1;
}
.gbh-d-option input:focus-visible{ outline: 2px solid var(--gbh-azure); outline-offset: 2px; border-radius: 4px; }
.gbh-d-option span{ font-size: 16px; color: var(--gbh-row-text); transition: color .15s; }
.gbh-d-option span small{ display: block; font-size: 12.5px; color: var(--gbh-text-2); margin-top: 2px; font-weight: 400; }

/* BOOKING — GMH WIZARD RESTORATION (2026-09-24), PREMIUM VISUAL
   REDESIGN (2026-09-25, "BOOKING FLOW — RESTORE APPROVED METHODS +
   PREMIUM VISUAL REDESIGN"): the 2026-09-24 pass's floating-cream-
   card-on-dark-navy full-bleed treatment (modeled on
   GMH-booking-new/book-consultation.html's own standalone-page layout)
   read as a large, out-of-place dark band next to every OTHER
   Discovery page's light cream system. This pass removes the dark
   full-bleed canvas entirely — .gbh-discovery-main now simply falls
   back to the SAME shared 640px cream column every other Discovery
   page already uses (which also means the header's own already-640px
   topbar row aligns with this page's content for free — no new
   alignment rule needed, unlike the wider Snapshot-result page).
   Progress bar/card/method-card component shapes are kept (same
   structure, same class names, same form/analytics behavior) — only
   retinted for a light background, with a much lighter card shadow. */
/* PREMIUM SHELL — PROPAGATED ACROSS ALL 5 STEPS (2026-09-25): Step 1's
   own premium width, approved, is now the ONE shell every booking step
   shares — no width jump between Step 1 and Steps 2-5. .gbh-discovery-main
   needs its own widening (840, border-box, matching its existing
   20px+20px padding) so the 800px card/progress bar actually have room
   to render at that width instead of being clipped by the narrower
   640px shared default every other 640px-column Discovery page uses;
   the topbar is widened to the same 800 the card itself ends up at
   (not the wider 840 main) for the same reason the Snapshot page's
   header matches its inner reading column, not its outer shell. */
.gbh-discovery-main:has(.gbh-book-wizard){ max-width: 840px; }
body:has(.gbh-book-wizard) .gbh-discovery-topbar-inner{ max-width: 800px; }
.gbh-book-progress-wrap{ width: 100%; max-width: 800px; margin: 0 0 22px; }
.gbh-book-progress-track{
  background: var(--gbh-line); height: 6px; border-radius: 999px; overflow: hidden;
}
.gbh-book-progress-fill{ background: var(--gbh-azure); height: 100%; border-radius: 999px; transition: width .3s ease; }
.gbh-book-progress-label{
  margin-top: 8px; color: var(--gbh-text-2); font-size: 12.5px; font-weight: 600; text-align: right;
}

.gbh-book-card{
  background: #fff; border: 1px solid var(--gbh-line); border-radius: 10px; max-width: 800px; width: 100%;
  padding: 48px 56px 44px; box-shadow: 0 1px 3px rgba(23,59,87,.06);
}
@media (max-width: 480px){ .gbh-book-card{ padding: 30px 22px 26px; } }

.gbh-book-eyebrow{
  font-size: 12.5px; font-weight: 700; color: var(--gbh-navy); text-transform: uppercase;
  letter-spacing: .05em; margin-bottom: 10px;
}
.gbh-book-card h1{ font-size: 24px; font-weight: 500; letter-spacing: -.01em; line-height: 1.3; margin-bottom: 0; }
.gbh-book-card p.gbh-d-lede{ margin: 10px 0 0; }

/* Step 1 — Consultation method (PREMIUM REDESIGN, 2026-09-25 — Phone
   Call / Google Meet / Zoom, three real, equally-weighted choices; see
   consultationBookingMethodSubmit()'s own docblock for the backend
   history). Deliberately full-width stacked cards, never narrow
   columns — the wider .gbh-book-card (now shared by all 5 steps) above
   gives each one enough room that a 1-2 line description never wraps
   awkwardly. Equal height
   falls out naturally: every card holds the same shape (title + one
   short description line), no forced min-height needed. */
.gbh-book-method-grid{ margin-top: 28px; display: grid; grid-template-columns: 1fr; gap: 14px; }
.gbh-book-method-card{
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  border: 1.5px solid var(--gbh-line); background: #fff; border-radius: 10px;
  padding: 22px 26px; cursor: pointer; transition: border-color .15s, background .15s;
}
.gbh-book-method-card:hover{ border-color: var(--gbh-azure); }
.gbh-book-method-card:has(input:checked){ border-color: var(--gbh-azure); background: var(--gbh-azure-wash); }
/* IMMEDIATE PROCESSING FEEDBACK (2026-09-25): same convention as
   .gbh-book-opt-grid's own disabled-dimming rule — the chosen card
   keeps its full-strength selected treatment above; every other card
   (now genuinely disabled by the shared single-select JS) steps back. */
.gbh-book-method-card:has(input:disabled):not(:has(input:checked)){ opacity: .45; cursor: default; }
.gbh-book-method-card input[type=radio]{
  flex-shrink: 0; width: 20px; height: 20px; accent-color: var(--gbh-azure); cursor: pointer; margin: 0;
}
.gbh-book-method-card-text{ min-width: 0; }
.gbh-book-method-title{ display: block; font-size: 17px; font-weight: 700; color: var(--gbh-navy); }
.gbh-book-method-desc{ display: block; font-size: 14px; color: var(--gbh-text-2); margin-top: 4px; line-height: 1.5; }

/* Steps 2/3 — Date/Time option pills, and the existing/placeholder
   panels: reuse the shared .gbh-d-option base class already used
   everywhere else in Discovery (hover/selected/focus/aria-checked/
   loading-text plumbing keeps working for free) inside a 2-up grid. */
.gbh-book-opt-grid{ margin-top: 26px; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 480px){ .gbh-book-opt-grid{ grid-template-columns: 1fr; } }
/* GMH BOOKING FLOW RESTORATION (2026-09-25, "DATE + TIME INTERACTION
   STATES"): restores GMH's own real bordered-pill treatment for these
   rows (GMH-booking-new/book-consultation.html's .opt/.opt:hover/
   .opt.selected), which the plain shared .gbh-d-option base (a divider-
   line list row, meant for a different, vertical Discovery-question
   layout) never had here — the border is present at every state so
   hover/selected only ever recolor it, never shift the layout. Time's
   native radio dot is visually hidden (GMH's own .opt is not a real
   form control at all) since the whole pill already carries the
   selected signal via border+background; the label/input still work
   exactly as before for click/keyboard/screen readers. */
.gbh-book-opt-grid .gbh-d-option{
  text-align: center; justify-content: center; padding: 14px 16px;
  border: 1.5px solid var(--gbh-line); background: #fff; border-radius: 8px;
  transition: border-color .15s, background .15s;
}
.gbh-book-opt-grid .gbh-d-option:hover{ border-color: var(--gbh-azure); }
.gbh-book-opt-grid .gbh-d-option:active{ background: var(--gbh-azure-wash); }
.gbh-book-opt-grid .gbh-d-option:has(input:checked),
.gbh-book-opt-grid .gbh-d-option.is-selected{ border-color: var(--gbh-azure); background: var(--gbh-azure-wash); }
.gbh-book-opt-grid .gbh-d-option input[type=radio]{ display: none; }
/* IMMEDIATE PROCESSING FEEDBACK (2026-09-25): a non-selected option that
   is mid-processing (input disabled, or an <a> marked aria-disabled) is
   visually dimmed and inert — the SELECTED one (:has(input:checked) /
   .is-selected, above) deliberately keeps its full-strength azure
   treatment throughout, so it stays the one clearly "active" thing on
   the screen while everything else quietly steps back. */
.gbh-book-opt-grid .gbh-d-option:has(input:disabled):not(:has(input:checked)),
.gbh-book-opt-grid a.gbh-d-option[aria-disabled="true"]{
  opacity: .45; cursor: default; pointer-events: none;
}

/* IMMEDIATE PROCESSING FEEDBACK (2026-09-25): one shared status row for
   both the Step 2/Date and Step 3/Time pickers — always present in the
   DOM at its natural size so activating it (discovery.js adds
   .is-active and fills in the text) never shifts surrounding layout.
   Kept out of the .gbh-book-actions flex row on purpose: it needs its
   own line, not to compete for space with the Back link/Confirm
   fallback button. */
.gbh-book-processing{
  display: flex; align-items: center; gap: 8px; min-height: 20px; margin-top: 14px;
  opacity: 0; transition: opacity .15s;
}
.gbh-book-processing.is-active{ opacity: 1; }
.gbh-book-processing-text{ font-size: 13.5px; font-weight: 600; color: var(--gbh-text-2); }
.gbh-book-spinner{
  width: 16px; height: 16px; flex-shrink: 0; border-radius: 50%;
  border: 2px solid var(--gbh-line); border-top-color: var(--gbh-azure);
  animation: gbh-book-spin .6s linear infinite;
}
@keyframes gbh-book-spin{ to{ transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce){ .gbh-book-spinner{ animation-duration: 1.6s; } }

/* RELEASE GATE FIX (2026-09-24): a negative top margin here collided
   with the Step 3 h1 ("What time works best on <long date>?") whenever
   it wrapped to two lines — common at mobile widths — visibly
   overlapping the note text into the heading's last line. */
.gbh-book-tz-note{ font-size: 12.5px; color: var(--gbh-text-2); margin: 8px 0 4px; }

.gbh-book-actions{ margin-top: 28px; display: flex; justify-content: space-between; align-items: center; gap: 16px; }
/* STEP 3 ACTION-ROW FIX (2026-09-25): pre-existing issue, exposed (not
   caused) by the wider shell — .gbh-d-btn's own shared width:100% rule
   competes for space in this flex row and was squeezing this link down
   far enough to wrap onto two lines. flex-shrink:0 guarantees it keeps
   its natural, single-line width regardless of the button's own width;
   the button (default flex-shrink:1) simply gives up exactly that much
   space, staying just as wide/prominent otherwise. No other rule here
   changed — same colors, same layout, same route/JS. */
.gbh-book-back-link{ color: var(--gbh-text-2); font-weight: 700; font-size: 14px; text-decoration: none; flex-shrink: 0; }
.gbh-book-back-link:hover{ color: var(--gbh-navy); }

/* Step 4 — Details (name/email/phone). Reuses the shared .gbh-d-field
   input styling verbatim — only the surrounding card chrome is new. */
.gbh-book-card .gbh-d-field{ margin-top: 18px; margin-bottom: 0; }

/* Step 5 — Confirmation summary rows. */
.gbh-book-confirm-summary{ margin-top: 8px; border-top: 1px solid var(--gbh-line); padding-top: 18px; }
.gbh-book-confirm-row{
  display: flex; justify-content: space-between; gap: 14px; padding: 10px 0; border-bottom: 1px dashed var(--gbh-line); font-size: 14.5px;
}
.gbh-book-confirm-row:last-child{ border-bottom: none; }
.gbh-book-confirm-label{ color: var(--gbh-text-2); font-weight: 600; }
.gbh-book-confirm-value{ font-weight: 700; text-align: right; }
.gbh-book-confirm-note{
  margin-top: 18px; background: #f0fbf7; border: 1px solid #cdeee0; color: #0f6b4c;
  font-size: 13px; font-weight: 600; padding: 12px 14px; border-radius: 6px;
}

/* Already-booked / manage-booking panel (existing $existing gate). */
.gbh-book-manage-note{ margin-top: 18px; font-size: 13px; color: var(--gbh-text-2); line-height: 1.6; }

/* Supporting value line (2026-09-13) — sits between the Free Snapshot's
   teaser paragraph and its "GET MY FULL SNAPSHOT" button: reassuring,
   deliberately quiet/secondary so the button remains the visual focus. */
.gbh-d-value-line{
  font-size: 13px; font-weight: 600; color: var(--gbh-text-2); margin: 14px 0 0; line-height: 1.5;
}

.gbh-d-btn{
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--gbh-azure); color: #fff; border: none; border-radius: 8px;
  font-family: var(--ff-body); font-weight: 700; font-size: 15.5px; padding: 13px 26px;
  cursor: pointer; width: 100%; transition: background .15s, transform .1s; margin-top: 20px;
}
/* CTA UNDERLINE FIX (2026-09-18, "CUSTOMER SNAPSHOT FLOW CLEANUP") — an
   <a class="gbh-d-btn"> otherwise inherits the browser's default link
   underline in every state; explicit here so it can never regress
   regardless of which container it's placed in. */
.gbh-d-btn,
.gbh-d-btn:link,
.gbh-d-btn:visited,
.gbh-d-btn:hover,
.gbh-d-btn:focus,
.gbh-d-btn:active{ text-decoration: none !important; }
.gbh-d-btn:hover{ background: #0F7E9F; }
.gbh-d-btn:active{ transform: translateY(1px); }
.gbh-d-btn.secondary{ background: transparent; color: var(--gbh-navy); border: 1.5px solid var(--gbh-line-strong); }
.gbh-d-btn.secondary:hover{ background: var(--gbh-cream); }

.gbh-d-error{
  background: var(--gbh-error-wash); color: var(--gbh-error); border: 1px solid rgba(179,38,30,.25);
  border-radius: 8px; padding: 12px 14px; font-size: 14px; margin-bottom: 20px;
}

/* TEST MODE notice (2026-09-13, "PURCHASE CTA" fix) — deliberately
   distinct from .gbh-d-error (this isn't a problem the customer caused)
   and from .gbh-d-hint (this is more load-bearing than a passing aside):
   every order/checkout/confirmation screen that runs against
   FakePaymentProvider (no real payment provider exists yet) carries one
   of these so it is never mistaken for a live charge. Neutral/informational
   tone using the existing azure tokens, not the red error palette. */
.gbh-d-test-mode-notice{
  background: var(--gbh-azure-wash); border: 1px solid var(--gbh-line-strong); border-radius: 8px;
  padding: 12px 14px; margin: 0 0 20px; font-size: 13px; color: var(--gbh-navy);
}
.gbh-d-test-mode-notice strong{ text-transform: uppercase; letter-spacing: .04em; font-size: 11.5px; }

/* Thin, understated progress bar (production reference) — small label,
   never dominant. Underlying completed/total values are unchanged, purely
   the adaptive greenfield calculation already computed server-side. */
.gbh-discovery-progress{ height: 3px; background: var(--gbh-line); border-radius: 2px; margin-bottom: 6px; overflow: hidden; }
.gbh-discovery-progress-bar{ height: 100%; background: var(--gbh-azure); border-radius: 2px; transition: width .4s ease; }
.gbh-d-progress-label{ font-size: 11.5px; font-weight: 600; color: var(--gbh-text); margin: 0 0 28px; text-align: right; }

.gbh-d-loading{ text-align: center; padding: 48px 20px; }
.gbh-d-spinner{
  width: 40px; height: 40px; margin: 0 auto 20px; border-radius: 50%;
  border: 4px solid var(--gbh-line); border-top-color: var(--gbh-azure); animation: gbh-spin 0.8s linear infinite;
}
@keyframes gbh-spin{ to{ transform: rotate(360deg); } }

/* Snapshot-preparation rotating status message (2026-09-11, "DISCOVERY
   UX — PROGRESS + SNAPSHOT PREPARATION TRANSITION") — a smooth fade
   between messages, driven purely by discovery-ai-lab-snapshot.js
   toggling this one element's opacity; no JS-generated markup, no new
   visual system. */
.gbh-d-prep-message{ font-size: 15.5px; color: var(--gbh-text); min-height: 24px; transition: opacity .2s ease; }

.gbh-d-snapshot-section{ border-bottom: 1px solid var(--gbh-line); padding: 18px 0; }
.gbh-d-snapshot-section:last-child{ border-bottom: none; }
.gbh-d-tier{
  display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--gbh-navy); background: var(--gbh-azure-wash); border-radius: 5px; padding: 3px 8px; margin-bottom: 8px;
}
.gbh-d-empty{ color: var(--gbh-text-2); font-style: italic; padding: 20px 0; }
.gbh-d-snapshot-group{ margin-bottom: 28px; }
.gbh-d-snapshot-group > .gbh-d-eyebrow{ margin-bottom: 12px; }
/* Snapshot content redesign (2026-09-07) */
.gbh-d-snapshot-ready{ color: var(--gbh-navy); font-size: 15px; margin-bottom: 8px; }
.gbh-d-why-matters{ color: var(--gbh-text-2); font-size: 14.5px; font-style: italic; margin: 4px 0 24px; }
.gbh-d-priority-preview{ margin-top: 8px; }
.gbh-d-priority-label{
  display: inline-block; font-size: 11.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--gbh-azure); border: 1px solid var(--gbh-azure); border-radius: 5px; padding: 4px 10px;
}

.gbh-d-back-link{
  display: inline-flex; align-items: center; gap: 6px; font-size: 13.5px; font-weight: 600;
  color: var(--gbh-text); text-decoration: none; margin-bottom: 20px;
}
.gbh-d-back-link:hover{ color: var(--gbh-navy); }

.gbh-d-nav-links{ display: flex; gap: 16px; margin-top: 24px; flex-wrap: wrap; }
.gbh-d-nav-links .gbh-d-btn{ width: auto; flex: 1 1 200px; text-decoration: none; }
.gbh-d-checkbox-list, .gbh-d-radio-list{ display: flex; flex-direction: column; margin-bottom: 4px; }

/* Business Type search (2026-09-07) — reuses the same row styling above;
   only the search input and the "why: Category" subtext are new. */
.gbh-d-type-search-wrap{ margin: 4px 0 8px; }
.gbh-d-type-search{
  width: 100%; padding: 12px 14px; border: none; border-bottom: 1.5px solid var(--gbh-line-strong);
  font-family: var(--ff-body); font-size: 16px; color: var(--gbh-navy); background: transparent;
}
.gbh-d-type-search:focus{ outline: none; border-bottom-color: var(--gbh-azure); }
.gbh-d-type-other-detail{ margin-top: 4px; }
.gbh-d-type-other-detail label{ display: block; font-weight: 600; font-size: 14px; color: var(--gbh-navy); margin: 16px 0 6px; }
.gbh-d-type-other-detail input[type=text]{
  width: 100%; padding: 12px 14px; border: 1.5px solid var(--gbh-line-strong); border-radius: 8px;
  font-family: var(--ff-body); font-size: 15.5px; color: var(--gbh-navy); background: var(--gbh-paper);
}
.gbh-d-type-other-detail input[type=text]:focus{ outline: none; border-color: var(--gbh-azure); box-shadow: 0 0 0 3px var(--gbh-azure-wash); }

/* ------------------------------------------------------------------
   Full Business Snapshot OFFER PAGE (2026-09-13, two-column premium
   redesign) — scoped entirely to templates/discovery-ai-lab/
   full_snapshot_offer_preview.php via the .gbh-d-offer-page marker
   class. Reuses every existing token/class above (h1, .gbh-d-card,
   .gbh-d-lede, .gbh-d-eyebrow, .gbh-d-back-link, .gbh-d-btn, the same
   navy/azure/cream palette and Fraunces/DM Sans fonts — no new colors
   or fonts anywhere below). Nothing here is used by, or changes the
   appearance of, any other Discovery page.

   The one deliberate structural exception: this page alone widens the
   shared .gbh-discovery-main column (640px everywhere else) via :has(),
   the same selector already used elsewhere in this file
   (.gbh-d-option:has(input:checked)) — so no other template, and no
   shared partial, needs to change for this one page to be wider.
   ------------------------------------------------------------------ */
.gbh-discovery-main:has(.gbh-d-offer-page){ max-width: 1040px; }

/* FREE SNAPSHOT — FULL-PAGE-WIDE RESTORATION (2026-09-19, "FREE SNAPSHOT
   MUST MATCH THE ATTACHED SCREENSHOT 1:1"): the approved screenshot's own
   source (business-snapshot.html, --wrap:1040px) reads as a full
   professional business report, not a narrow card — same :has() marker
   pattern as the offer page immediately above, scoped to
   templates/discovery-ai-lab/snapshot.php's .gbh-snap-page wrapper only. */
.gbh-discovery-main:has(.gbh-snap-page){ max-width: 1040px; }
/* FREE SNAPSHOT RESULT PAGE — HEADER/CONTENT ALIGNMENT RESTORATION
   (2026-09-25, approved design restoration): the shared topbar's inner
   row is capped at the same 640px every OTHER Discovery page uses,
   which never lined up with this one page's own 720px reading column
   (.gbh-snap-col in snapshot.php — the widened :has() rule above only
   widens the outer .gbh-discovery-main shell to 1040px, the topbar is a
   separate sibling element it does not touch). Same :has() page-marker
   pattern as the rule immediately above, scoped to body since the
   topbar and .gbh-discovery-main are siblings — matches .gbh-snap-col's
   own 720px exactly, no other page's header is affected. */
body:has(.gbh-snap-page) .gbh-discovery-topbar-inner{ max-width: 720px; }

/* NOTE (2026-09-18, "FINAL GBH CUSTOMER JOURNEY + SNAPSHOT RESTORATION"):
   a prior pass added a `:has(.gbh-snap-grid)` widening exception here for
   a two-column Snapshot + sidebar layout — that layout is retired (see
   snapshot.php's own docblock); the Snapshot page is deliberately back
   at the shared 640px width, matching the approved narrow, centered
   report/document feel, so no exception is declared for it. */

/* FREE SNAPSHOT — FINAL LOGO STYLE FIX (2026-09-19): superseded by the
   GLOBAL LOGO STANDARDIZATION (2026-09-25) above, which now gives every
   page (not just this one) the same transparent/azure-ring treatment
   this override used to carve out as a Snapshot-only exception. Removed
   rather than left in place, since border-radius:0 here would now
   conflict with (force a square instead of) the new shared circular
   treatment. */

.gbh-d-offer-grid{
  display: grid; grid-template-columns: 1.15fr 1fr; gap: 12px 56px; align-items: start;
}
.gbh-d-offer-main{ min-width: 0; }

.gbh-d-offer-price-row{ display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; margin: 4px 0 22px; }
.gbh-d-offer-price{ font-family: var(--ff-heading); font-size: 38px; font-weight: 600; color: var(--gbh-navy); line-height: 1; }
.gbh-d-offer-delivery{
  font-size: 13px; font-weight: 700; color: var(--gbh-navy); background: var(--gbh-azure-wash);
  border-radius: 6px; padding: 5px 10px; white-space: nowrap;
}

.gbh-d-offer-note{
  background: var(--gbh-cream); border: 1px solid var(--gbh-line); border-radius: 10px;
  padding: 14px 16px; font-size: 13.5px; color: var(--gbh-text); margin: 20px 0 24px;
}
.gbh-d-offer-note strong{ color: var(--gbh-navy); }

.gbh-d-offer-card{
  background: var(--gbh-paper); border: 1px solid var(--gbh-line-strong); border-radius: 16px;
  padding: 28px 26px; box-shadow: 0 1px 2px rgba(23,59,87,.04), 0 8px 28px rgba(23,59,87,.06);
}
.gbh-d-offer-card-title{
  font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--gbh-text); display: block; margin-bottom: 18px;
}
.gbh-d-offer-list{ list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 18px; }
.gbh-d-offer-list li{
  position: relative; padding-left: 28px; padding-top: 4px; padding-bottom: 4px; padding-right: 4px;
  margin: 0 -4px; border-radius: 8px;
  /* Premium, calm easing (2026-09-13 feature showcase) — every property
     that changes between the quiet and active states animates through
     this one curve, never a bounce/spring. Reduced to instant below
     under prefers-reduced-motion. */
  transition: background-color .5s cubic-bezier(.4,0,.2,1), opacity .5s cubic-bezier(.4,0,.2,1), transform .5s cubic-bezier(.4,0,.2,1);
}
.gbh-d-offer-list li::before{
  content: "✓"; position: absolute; left: 4px; top: 5px; color: var(--gbh-azure); font-weight: 700; font-size: 14px;
  transition: color .5s cubic-bezier(.4,0,.2,1);
}
.gbh-d-offer-list li strong{ display: block; font-family: var(--ff-heading); font-size: 15.5px; font-weight: 600; color: var(--gbh-navy); line-height: 1.3; }
.gbh-d-offer-list li span{ display: block; font-size: 13.5px; color: var(--gbh-text-2); margin-top: 2px; line-height: 1.4; }

/* Quiet/active states — ONLY applied once JS has enhanced the list
   (.gbh-d-offer-list.is-enhanced); with no JS, every item keeps its
   normal, equally-weighted static appearance (see the template's own
   progressive-enhancement comment). Deliberately no scaling, no
   bounce, no flashing — only a soft background tint, a small,
   deliberate upward shift, and a slightly quieter (never illegible)
   inactive opacity. */
.gbh-d-offer-list.is-enhanced li{ opacity: .6; }
.gbh-d-offer-list.is-enhanced li.is-active{
  opacity: 1; background-color: var(--gbh-azure-wash); transform: translateY(-2px);
}
.gbh-d-offer-list li:focus-visible{ outline: 2px solid var(--gbh-azure); outline-offset: 2px; }

.gbh-d-offer-progress{ display: flex; gap: 8px; margin-top: 20px; }
.gbh-d-offer-progress-dot{
  width: 8px; height: 8px; padding: 0; border-radius: 50%; border: none; cursor: pointer;
  background: var(--gbh-line-strong); transition: background-color .5s cubic-bezier(.4,0,.2,1), transform .3s cubic-bezier(.4,0,.2,1);
}
.gbh-d-offer-progress-dot.is-active{ background: var(--gbh-azure); transform: scale(1.15); }
.gbh-d-offer-progress-dot:focus-visible{ outline: 2px solid var(--gbh-azure); outline-offset: 2px; }

/* Reduced motion (2026-09-13): the JS itself also checks this and never
   starts the automatic cycle at all — this CSS layer is a second,
   independent guarantee that even a manual/keyboard-triggered state
   change never animates, and covers a no-JS-timing-yet paint. */
@media (prefers-reduced-motion: reduce){
  .gbh-d-offer-list li, .gbh-d-offer-list li::before, .gbh-d-offer-progress-dot{ transition: none !important; }
  .gbh-d-offer-list.is-enhanced li.is-active{ transform: none; }
}

@media (max-width: 600px){
  .gbh-discovery-main{ padding: 28px 16px 56px; }
  .gbh-discovery-topbar{ padding: 14px 16px; }
  .gbh-d-btn{ padding: 14px 20px; }
  h1{ font-size: 22px; }
}

@media (max-width: 860px){
  .gbh-d-offer-grid{ grid-template-columns: 1fr; gap: 32px; }
  .gbh-d-offer-price{ font-size: 32px; }
}

/* Customer Platform progress checklist (2026-09-16) — isolated, additive
   rules under their own gbh-fsp- prefix; never reuses or redefines any
   existing Discovery class above. */
.gbh-fsp-progress{ list-style: none; margin: 16px 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.gbh-fsp-progress li{ font-size: 14.5px; color: var(--gbh-text-2); padding-left: 22px; position: relative; }
.gbh-fsp-progress li::before{ content: ''; position: absolute; left: 0; top: 6px; width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid var(--gbh-line); }
.gbh-fsp-progress li.gbh-fsp-progress-done{ color: var(--gbh-navy); font-weight: 600; }
.gbh-fsp-progress li.gbh-fsp-progress-done::before{ background: var(--gbh-azure); border-color: var(--gbh-azure); }
.gbh-fsp-progress li.gbh-fsp-progress-active{ color: var(--gbh-navy); font-weight: 600; }
.gbh-fsp-progress li.gbh-fsp-progress-active::before{ border-color: var(--gbh-azure); }
