/* ==========================================================================
   Ballyhass checkout
   --------------------------------------------------------------------------
   Tokens follow the client brand document — see docs/brand-guidelines.md.
   Names match the guide's own names so the two can be diffed by eye.

   Two deliberate departures from the guide, both for WCAG 2.2 AA on a
   transactional page (measured ratios are in the brand doc):
     · Never white-on-blue (2.42:1) or white-on-pink (3.11:1), which the
       guide's own examples use — navy text is used on both instead.
     · --bh-blue-text is a darkened blue for text/links on white, because
       full-strength Ballyhass Blue on white is 2.42:1.
   ========================================================================== */

/* Poppins, served from this site (phone speed, 31 October 2026, FSD REQ-NF001).

   It came from Google Fonts: a render-blocking stylesheet on one more origin, then the
   files from a second, so a phone opened two extra connections before any text could
   be drawn in the brand face. The files are Google's own woff2 subsets, latin and
   latin-ext, under the SIL Open Font License (fonts/poppins/OFL.txt). A browser fetches
   only the weights and subsets a page uses; the layouts preload the two the first
   screen needs (500 for body text, 900 for the heading). swap keeps text visible while
   a file arrives. */
@font-face { font-family: Poppins; font-style: normal; font-weight: 400; font-display: swap;
    src: url('/fonts/poppins/poppins-400-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: Poppins; font-style: normal; font-weight: 400; font-display: swap;
    src: url('/fonts/poppins/poppins-400-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: Poppins; font-style: normal; font-weight: 500; font-display: swap;
    src: url('/fonts/poppins/poppins-500-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: Poppins; font-style: normal; font-weight: 500; font-display: swap;
    src: url('/fonts/poppins/poppins-500-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: Poppins; font-style: normal; font-weight: 600; font-display: swap;
    src: url('/fonts/poppins/poppins-600-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: Poppins; font-style: normal; font-weight: 600; font-display: swap;
    src: url('/fonts/poppins/poppins-600-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: Poppins; font-style: normal; font-weight: 700; font-display: swap;
    src: url('/fonts/poppins/poppins-700-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: Poppins; font-style: normal; font-weight: 700; font-display: swap;
    src: url('/fonts/poppins/poppins-700-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: Poppins; font-style: normal; font-weight: 800; font-display: swap;
    src: url('/fonts/poppins/poppins-800-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: Poppins; font-style: normal; font-weight: 800; font-display: swap;
    src: url('/fonts/poppins/poppins-800-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: Poppins; font-style: normal; font-weight: 900; font-display: swap;
    src: url('/fonts/poppins/poppins-900-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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: Poppins; font-style: normal; font-weight: 900; font-display: swap;
    src: url('/fonts/poppins/poppins-900-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; }

/* The hidden attribute means hidden, whatever the element's own display. The browser's
   [hidden] rule loses to any author display (.bh-grid-2 is a grid, an inline display:flex),
   which is how "Myself" on the waiver form still showed the authority line and asked for the
   signer's name a second time (Eoghan, comment 11929142). */
[hidden] { display: none !important; }

:root {
    /* ── Brand palette (Ballyhass Adventure Group, p9) ────────────────────── */
    --bh-blue:       #00B6D9; /* 01 Primary    — Ballyhass Blue      */
    --bh-white:      #FFFFFF; /* 02 Secondary  — White               */
    --bh-ink:        #21272F; /* 03 Tertiary   — Ballyhass Navy Blue */
    --bh-yellow:     #E4FF1A; /* 04 Quaternary — Activities Yellow   */
    --bh-pink:       #FF4F8E; /* 05 Quinary    — Ballyhass Pink      */

    /* Derived. Not brand colours — tints and accessible substitutes. */
    --bh-blue-text:  #0B7A8E; /* 5.01:1 on white, for blue text and links   */
    --bh-blue-banner:#05BDD9; /* the banner image's own painted blue, measured from its pixels, so
                                 the fill behind the header's text meets the picture with no seam.
                                 Navy text on it is 6.65:1. */
    --bh-blue-dark:  #009BB8; /* hover fill only, never behind white text   */
    --bh-pink-dark:  #F03A7B;
    --bh-yellow-dark:#C8E000;
    --bh-ink-70:     #5C6570;
    --bh-ink-45:     #8A9099; /* lines and borders, and a disabled button: 3.21:1, never text */

    /* Focus (WCAG 2.2 1.4.11, 2.4.7, 2.4.13; 31 October 2026): a navy ring 3px wide, 2px out,
       with white either side of it. Navy and white are 15.04:1 apart, so one of them is 3:1 or
       more against anything a control sits on (technique C40): white, Ballyhass Blue (navy
       6.23:1), the navy header (white 15.04:1), yellow or a photograph. The website uses the
       same ring (its tokens.css, "Focus"). */
    --bh-focus-ring:  var(--bh-ink);
    --bh-focus-halo:  #FFFFFF;
    --bh-focus-width: 3px;
    --bh-focus-offset: 2px;
    --bh-focus-shadow: 0 0 0 calc(var(--bh-focus-offset) + var(--bh-focus-width) + 2px) var(--bh-focus-halo);

    --bh-field:      #EDEDED;
    /* The edge of a field (WCAG 1.4.11, 3:1 for what identifies it; accessibility assessment,
       3 November 2026). The grey fill alone was 1.17:1 on white. This is 4.06:1 on white and
       3.47:1 on the fill itself, the same edge as the website's (its tokens.css). */
    --bh-field-edge: #767F89;
    --bh-field-hi:   #E3E3E3;
    --bh-line:       #DFE2E5;
    --bh-panel:      #FFFFFF;
    --bh-wash:       #F6F7F8;
    --bh-danger:     #C62828;
    --bh-success:    #1B7F4B;

    /* "Buttons are designed with a rounded square shape, whereas highlighted
       texts feature a straight square shape." (p11) */
    --bh-r-field:    4px;
    --bh-r-btn:      8px;
    --bh-r-card:     8px;
    --bh-r-highlight: 0px;

    --bh-shadow:     0 1px 2px rgba(33, 39, 47, .06), 0 8px 24px rgba(33, 39, 47, .07);
    --bh-shadow-sm:  0 1px 2px rgba(33, 39, 47, .08);

    --bh-gutter:     clamp(16px, 4vw, 40px);
    --bh-max:        1200px;
}

/* --------------------------------------------------------------- reset ---- */

*, *::before, *::after { box-sizing: border-box; }

body {
    margin: 0;
    font-family: Poppins, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    font-size: 16px;
    /* "Use a medium weight for body text" (p11). */
    font-weight: 500;
    line-height: 1.55;
    color: var(--bh-ink);
    background: var(--bh-panel);
    -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3, h4 { margin: 0; line-height: 1.15; }

a { color: var(--bh-blue-text); }

/* One focus indicator for every control, keyboard only (the tokens above). It was Ballyhass
   Blue, 2.42:1 on white, which fails WCAG 1.4.11, with white in the header and hero and other
   colours on single components. Written once, here, with !important so a component's own
   box-shadow cannot take the white away. A control drawn as a card around a hidden input (a
   time slot, a choice) shows it on the card instead. A field you type in takes it however it
   was focused, as browsers do: Chrome does not count a date field reached by Tab on a phone as
   :focus-visible, nor even :focus (its inner field has it), hence :focus-within. */
:focus-visible,
:is(input, textarea):focus-within:not([type=checkbox], [type=radio], [type=button], [type=submit], [type=reset], [type=range], [type=file], [type=color], [type=image]),
.bh-slot input:focus-visible + .bh-slot__body {
    outline: var(--bh-focus-width) solid var(--bh-focus-ring) !important;
    outline-offset: var(--bh-focus-offset) !important;
    box-shadow: var(--bh-focus-shadow) !important;
}
.bh-slot input:focus-visible {
    outline: none !important;
    box-shadow: none !important;
}
@supports selector(:has(*)) {
    .bh-choice:has(:focus-visible),
    .bh-yg-choice:has(:focus-visible) {
        outline: var(--bh-focus-width) solid var(--bh-focus-ring) !important;
        outline-offset: var(--bh-focus-offset) !important;
        box-shadow: var(--bh-focus-shadow) !important;
    }
    .bh-choice :focus-visible,
    .bh-yg-choice :focus-visible {
        outline: none !important;
        box-shadow: none !important;
    }
}

.bh-visually-hidden {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.bh-skip {
    position: absolute; left: 8px; top: -60px; z-index: 100;
    background: var(--bh-ink); color: #fff; padding: 12px 20px;
    border-radius: var(--bh-r-field); font-weight: 600; text-decoration: none;
    transition: top .15s ease;
}
.bh-skip:focus { top: 8px; }

/* -------------------------------------------------------------- header ---- */

.bh-header {
    background: var(--bh-ink);
    color: #fff;
}
.bh-header__in {
    max-width: var(--bh-max);
    margin: 0 auto;
    padding: 14px var(--bh-gutter);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}
.bh-header__logo img { height: 38px; width: auto; }
.bh-header__right { display: flex; align-items: center; gap: 12px; font-size: 14px; }
.bh-header__hi { color: rgba(255,255,255,.8); }

.bh-header__link {
    color: #fff;
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    padding: 9px 16px;
    border: 1.5px solid rgba(255,255,255,.45);
    border-radius: 999px;
    background: none;
    cursor: pointer;
    font-family: inherit;
    white-space: nowrap;
    transition: background .15s ease, border-color .15s ease;
}
.bh-header__link:hover { background: rgba(255,255,255,.12); border-color: #fff; }

/* ---------------------------------------------------------------- hero ---- */

/* The header: the heading and its description on painted blue, with the brush strokes under them.

   Eoghan, 3 November 2026 (comment 11932022, point 1): on My family the description ran into the
   turquoise-to-yellow paint stroke and was hard to read. The banner is 1920x450 and reads top to
   bottom as blue to 47%, a torn blue-to-yellow edge to 57%, Activities Yellow to 90% and a torn
   white foot. It was drawn to the size of the header itself (cover here, 100% 100% on the
   account's slim header), so the torn edge always sat about halfway down the header, wherever the
   text happened to be: on every account page, the checkout, the waiver pages and the sign-in
   pages, at every width, and more so when the text wrapped at 200% zoom or under the visitor's own
   text spacing.

   Now the strokes have a height of their own (--bh-hero-paint), drawn at the foot of the header,
   and the header keeps that height plus a gap free below its text (padding-bottom). The
   picture's blue half sits above the strokes and the header's own fill, the same painted blue,
   behind the rest, so the text is always on flat blue, however many lines it takes. Nothing
   fixes the header's height: it grows with its text, and the strokes move down with it.
   HeaderPaintStrokesTest keeps it that way. */
.bh-hero {
    --bh-hero-paint: clamp(26px, 5.5vw, 84px);
    --bh-hero-paint-gap: clamp(14px, 2vw, 24px);
    position: relative;
    /* The bottom 54% of the picture is the strokes, so it is drawn at the strokes' height / 0.54
       (a few pixels of its blue fall inside --bh-hero-paint, never a stroke above it). */
    background: var(--bh-blue-banner) url('/img/banner--checkout.jpg') center bottom / 100% calc(var(--bh-hero-paint) / 0.54) no-repeat;
    /* The banner is flat painted colour, so the WebP is 14 KB against the JPEG's 165 KB and
       looks the same. It is the largest thing on most pages' first screen, which makes it
       what a phone's load time is measured to, so the layouts preload this exact file
       (phone speed, 31 October 2026). A browser that cannot read image-set() keeps the
       JPEG from the line above. */
    background-image: image-set(url('/img/banner--checkout.webp') type('image/webp'), url('/img/banner--checkout.jpg') type('image/jpeg'));
    padding: clamp(24px, 5vw, 44px) 0 calc(var(--bh-hero-paint) + var(--bh-hero-paint-gap));
}
.bh-hero__in {
    max-width: var(--bh-max);
    margin: 0 auto;
    padding: 0 var(--bh-gutter);
}
.bh-hero__title {
    font-size: clamp(38px, 7vw, 62px);
    font-weight: 900;
    letter-spacing: -.02em;
    margin-top: 14px;
}
.bh-hero__sub {
    margin: 6px 0 0;
    font-weight: 500;
    max-width: 46ch;
    color: var(--bh-ink);
}

/* ------------------------------------------------------------- pathway ---- */

.bh-pathway {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0 4px;
    font-size: 15px;
}
/* A step still to come was navy at 45% (2.23:1 on the header's blue) and its number navy at 60%
   in a pale circle (2.66:1), below the 4.5:1 its words need (WCAG 1.4.3; found retesting the
   header, 4 November 2026, finding B7). Every step's words are full navy now (6.65:1), and the
   state is in the circle's shape rather than a faded colour: an outline still to come, a tick in
   a filled circle when done, and the current step filled and bold. */
.bh-pathway__item {
    display: flex;
    align-items: center;
    gap: 9px;
    color: var(--bh-ink);
    font-weight: 500;
}
.bh-pathway__num {
    flex: 0 0 auto;
    width: 30px; height: 30px;
    border-radius: 50%;
    display: grid; place-items: center;
    background: transparent;
    box-shadow: inset 0 0 0 2px var(--bh-ink);
    color: var(--bh-ink);
    font-size: 14px; font-weight: 700;
    line-height: 1;
}
.bh-pathway__rule {
    width: clamp(14px, 3vw, 40px);
    height: 2px;
    background: rgba(33, 39, 47, .2);
    margin: 0 6px;
}
.bh-pathway__item--done { color: var(--bh-ink); }
.bh-pathway__item--done .bh-pathway__num { background: rgba(33, 39, 47, .8); color: #fff; }
.bh-pathway__item--now  { color: var(--bh-ink); font-weight: 700; }
.bh-pathway__item--now  .bh-pathway__num { background: var(--bh-ink); color: #fff; }

/* Steps already completed are links back; keep them looking like steps. */
a.bh-pathway__item { text-decoration: none; }
a.bh-pathway__item:hover { text-decoration: underline; }

/* On a phone only the current step shows its name. The others are hidden from sight only: with
   display: none a completed step's link back had no name at all (axe link-name, 390px,
   31 October 2026). */
@media (max-width: 640px) {
    .bh-pathway__item:not(.bh-pathway__item--now) > span:not(.bh-pathway__num) {
        position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
        clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
    }
    .bh-pathway__rule { width: 14px; margin: 0 2px; }
}

/* --------------------------------------------------------------- shell ---- */

.bh-shell {
    max-width: var(--bh-max);
    margin: 0 auto;
    padding: clamp(24px, 4vw, 44px) var(--bh-gutter) 80px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 372px;
    align-items: start;
    gap: clamp(20px, 3vw, 40px);
}
.bh-shell--narrow { grid-template-columns: minmax(0, 1fr); max-width: 760px; }

/* One column at the full page width. --narrow is right for a form, where a
   long measure hurts; it is wrong for a six-column table, which it squeezed
   into 760px until the activity name wrapped over four lines and the row's
   buttons were pushed out of sight. */
.bh-shell--single { grid-template-columns: minmax(0, 1fr); }

@media (max-width: 960px) {
    .bh-shell { grid-template-columns: minmax(0, 1fr); }
}

/* --------------------------------------------------------------- panel ---- */

.bh-panel {
    background: var(--bh-panel);
    border: 1px solid var(--bh-line);
    border-radius: var(--bh-r-card);
    box-shadow: var(--bh-shadow-sm);
    padding: clamp(20px, 3vw, 30px);
}
.bh-panel + .bh-panel { margin-top: 20px; }
.bh-panel__title {
    font-size: 20px;
    font-weight: 700;
    margin-bottom: 4px;
}
.bh-panel__hint {
    color: var(--bh-ink-70);
    font-size: 14.5px;
    margin: 0 0 22px;
}

/* The guide's "subtitle": bold, all caps, in Ballyhass Blue. Uses the darkened
   blue token — full-strength blue on white is 2.42:1. */
.bh-step {
    display: block;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--bh-blue-text);
    margin-bottom: 6px;
}

/* ----------------------------------------------------- panel weight ------- */

/* NOT EVERY CARD MATTERS EQUALLY.
   Eoghan, 26 September 2026: "Almost every section is: white card + border +
   heading with roughly equal visual weight. So when I first arrive, my eye has to
   work quite hard to understand: What matters right now?"
   Three weights, not a colour scheme: the next real-world action leads, anything
   with a deadline is flagged, and discovery and history recede. */

/* The next visit, and only that. A left edge in Ballyhass Blue plus a little more
   presence, without a second background colour competing with the status tones. */
.bh-panel--lead {
    border-left: 4px solid var(--bh-blue);
    box-shadow: 0 6px 20px rgba(33, 39, 47, .10);
}

/* Something with a deadline. Amber rather than red: a membership in its grace
   period is a prompt, not a failure. */
.bh-panel--act {
    border-left: 4px solid #B26A00;
    background: #FFFBF4;
}

/* Discovery and history. Present, scannable, and clearly behind the rest. */
.bh-panel--quiet {
    background: transparent;
    box-shadow: none;
    border-color: var(--bh-line);
}
.bh-panel--quiet .bh-panel__title { font-size: 17px; }

/* ----------------------------------------------------- status pills ------- */

/* "I would use status colour / labels more deliberately. Not lots of colour
   everywhere, but enough to establish hierarchy."
   Every tone is checked against its own background for WCAG 2.2 AA, because the
   brand's own white-on-blue and white-on-pink examples fail it. */
.bh-status {
    display: inline-block;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: 4px;
    white-space: nowrap;
    border: 1px solid transparent;
}

/* Active and nothing to do. Deliberately the quietest of the three: Eoghan asked
   that a healthy pass "be visually quieter than a membership in grace or something
   requiring payment", so hierarchy comes from the absence of urgency. */
.bh-status--ok {
    color: #17603A;
    background: #EAF6EF;
    border-color: #CBE6D7;
}

/* Grace, expiring soon, or a balance owing. The one that should catch the eye.
   #8A4B00 on #FFF4E5 is 6.3:1. */
.bh-status--warn {
    color: #8A4B00;
    background: #FFF4E5;
    border-color: #F2D9B3;
}

/* Ended. Attention without alarm: nothing is wrong, it is simply over. */
.bh-status--off {
    color: #4A4F57;
    background: #F1F2F4;
    border-color: #DDE0E4;
}

/* A date or figure that has to be read first: the grace deadline, the credit
   balance. Used inside a row's meta line, never as the whole line. */
.bh-emphasis { font-weight: 700; color: var(--bh-navy); }

/* A membership row: name, status pill, then its own meta underneath. Keeps the
   memberships in ONE section rather than one card each, which is what he asked
   for: "the membership area could carry more of the hierarchy within one section
   rather than each membership feeling like another full card." */
.bh-list__head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

/* --------------------------------------------------- group portal -------- */

/* Erica's group booking header, 24 September 2026. The group's own name first, because a
   leader arriving here wants to see their school before they see ours. Navy ground with
   yellow for the countdown, which is the brand's own highlight pairing and the one that
   passes AA. */
.bh-group-header {
    background: var(--bh-navy);
    color: #fff;
    border-radius: var(--bh-r-card);
    padding: clamp(20px, 3vw, 30px);
    margin-bottom: 16px;
}
.bh-group-header__eyebrow {
    display: block;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--bh-yellow);
    margin-bottom: 6px;
}
.bh-group-header__name { font-size: clamp(22px, 3vw, 30px); font-weight: 700; margin: 0 0 6px; }
.bh-group-header__meta { color: rgba(255, 255, 255, .82); font-size: 14.5px; margin: 0 0 18px; }

.bh-group-header__visit {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    background: rgba(255, 255, 255, .07);
    border-left: 3px solid var(--bh-yellow);
    border-radius: 6px;
    padding: 14px 18px;
}
.bh-group-header__label {
    display: block;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .6);
    margin-top: 8px;
}
.bh-group-header__label:first-child { margin-top: 0; }
.bh-group-header__countdown { text-align: right; }
.bh-group-header__days {
    display: block;
    font-size: clamp(30px, 5vw, 44px);
    font-weight: 700;
    line-height: 1;
    color: var(--bh-yellow);
}

/* The five tabs. Real links, so each is an address a leader can send to a colleague. */
.bh-tabs--five { display: flex; flex-wrap: wrap; gap: 4px; }
.bh-tabs--five .bh-tab { flex: 0 1 auto; }

/* A figure and its label: the readiness counts, the age split, the booking finances. */
.bh-stat {
    background: var(--bh-panel);
    border: 1px solid var(--bh-line);
    border-radius: var(--bh-r-card);
    padding: 16px 18px;
}
.bh-stat__label {
    display: block;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--bh-ink-70);
    margin-bottom: 4px;
}
.bh-stat__value { display: block; font-size: 24px; font-weight: 700; color: var(--bh-navy); }
.bh-stat__note { display: block; font-size: 13px; color: var(--bh-ink-70); margin-top: 4px; }

/* -------------------------------------------------------------- fields ---- */

.bh-field { margin-bottom: 20px; }
.bh-field:last-child { margin-bottom: 0; }

.bh-label {
    display: block;
    font-weight: 600;
    font-size: 14.5px;
    margin-bottom: 8px;
}
.bh-label__opt { color: var(--bh-ink-70); font-weight: 500; }

.bh-input,
.bh-select {
    width: 100%;
    height: 60px;
    padding: 0 20px;
    font: inherit;
    color: var(--bh-ink);
    background: var(--bh-field);
    border: 1px solid var(--bh-field-edge);
    border-radius: var(--bh-r-field);
    appearance: none;
    transition: background .15s ease, border-color .15s ease;
}
.bh-input::placeholder { color: var(--bh-ink-70); }
.bh-input:hover:not(:disabled), .bh-select:hover:not(:disabled) { background: var(--bh-field-hi); }
.bh-input:disabled, .bh-select:disabled { opacity: .55; cursor: not-allowed; }

.bh-select {
    padding-right: 48px;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9' fill='none'%3E%3Cpath d='M1 1l6 6 6-6' stroke='%2321272F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 20px center;
}

/* Icon-prefixed field (location pin, calendar) */
.bh-field--icon { position: relative; }
.bh-field--icon .bh-input,
.bh-field--icon .bh-select { padding-left: 48px; }
.bh-field__icon {
    position: absolute;
    left: 18px;
    bottom: 20px;
    width: 20px; height: 20px;
    color: var(--bh-ink-70);
    pointer-events: none;
}

.bh-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 620px) { .bh-grid-2 { grid-template-columns: 1fr; } }

.bh-error {
    display: block;
    color: var(--bh-danger);
    font-size: 13.5px;
    font-weight: 500;
    margin-top: 7px;
}

/* --------------------------------------------------------------- slots ---- */

.bh-slots {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
    margin: 0;
    padding: 0;
    border: 0;
}
.bh-slot { position: relative; }
.bh-slot input {
    position: absolute;
    opacity: 0;
    width: 100%; height: 100%;
    margin: 0;
    cursor: pointer;
}
.bh-slot__body {
    display: block;
    padding: 14px 16px;
    background: var(--bh-field);
    border: 2px solid transparent;
    border-radius: var(--bh-r-field);
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, transform .1s ease;
}
.bh-slot input:hover + .bh-slot__body { background: var(--bh-field-hi); }
/* Selection is Ballyhass Blue with Navy copy (6.23:1). Keeping it off Navy
   stops the chosen slot reading as another primary button, and puts the brand's
   primary colour to work on the one thing the customer is choosing. */
.bh-slot input:checked + .bh-slot__body {
    background: var(--bh-blue);
    border-color: var(--bh-ink);
    color: var(--bh-ink);
}
.bh-slot input:disabled + .bh-slot__body {
    opacity: .5;
    cursor: not-allowed;
    background: var(--bh-field);
}
.bh-slot__time { display: block; font-weight: 700; font-size: 17px; }
.bh-slot__meta { display: block; font-size: 12.5px; color: var(--bh-ink-70); margin-top: 2px; }

/* Duration and arrival, deliberately quieter than the time above them. Eoghan,
   24 September 2026: "The time itself should remain the strongest element. I
   would not overload every session with too much explanatory text." So this sits
   below .bh-slot__time at a smaller size, and the scarcity line below it only
   appears when there is genuinely something to say. */
.bh-slot__detail { display: block; font-size: 12.5px; color: var(--bh-ink-70); margin-top: 2px; }

/* Scarcity reads as a warning rather than as more grey text, because it is the
   one line on the card that should change a customer's mind. */
.bh-slot__meta { font-weight: 600; }
/* Navy at 75% on Ballyhass Blue was 3.95:1 at 12.5px ("Continue at standard prices" on step 3,
   axe, 31 October 2026). Navy itself is 6.23:1. */
.bh-slot input:checked + .bh-slot__body .bh-slot__meta { color: var(--bh-ink); }
/* On the chosen slot the quieter line is Navy, as the time is: Navy-70 on Ballyhass Blue is
   2.4:1 and fails AA, and for a stay this line is its drop-off and collection (31 October 2026). */
.bh-slot input:checked + .bh-slot__body .bh-slot__detail { color: var(--bh-ink); }
/* A stay (a camp week) reads as its dates, nights, drop-off and collection, not a start time,
   so it takes the whole row rather than a time-sized tile. */
.bh-slot--stay { grid-column: 1 / -1; }

/* ------------------------------------------------------------- stepper ---- */

.bh-tiers { display: grid; gap: 4px; }
.bh-tier {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 0;
    border-bottom: 1px solid var(--bh-line);
}
.bh-tier:last-child { border-bottom: 0; }
.bh-tier__name { font-weight: 600; }
.bh-tier__price { display: block; font-size: 13px; font-weight: 500; color: var(--bh-ink-70); }

.bh-stepper { display: flex; align-items: center; gap: 6px; }
.bh-stepper__btn {
    width: 40px; height: 40px;
    display: grid; place-items: center;
    border: 1.5px solid var(--bh-blue);
    background: #fff;
    color: var(--bh-blue-text);
    border-radius: 50%;
    font-size: 20px; font-weight: 600; line-height: 1;
    cursor: pointer;
    font-family: inherit;
    transition: background .15s ease, color .15s ease;
}
/* Navy on Blue (6.23:1), not white on Blue (2.42:1). */
.bh-stepper__btn:hover:not(:disabled) { background: var(--bh-blue); color: var(--bh-ink); }
.bh-stepper__btn:disabled { opacity: .35; cursor: not-allowed; }
.bh-stepper__val {
    min-width: 46px;
    text-align: center;
    font-weight: 700;
    font-size: 17px;
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- buttons ---- */

/* "Subtitles and buttons should be in all capital letters and always in bold
   weight" and "buttons are designed with a rounded square shape" (p11). */
.bh-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 58px;
    padding: 0 30px;
    font: inherit;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: 15px;
    text-decoration: none;
    border: 2px solid transparent;
    border-radius: var(--bh-r-btn);
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, color .15s ease, transform .08s ease;
}
.bh-btn:active { transform: translateY(1px); }
.bh-btn--block { display: flex; width: 100%; }

/* Primary is Navy, as the guide's worked examples show. Activities Yellow is a
   highlight colour there, never a button fill. */
.bh-btn--primary { background: var(--bh-ink); border-color: var(--bh-ink); color: #fff; }
.bh-btn--primary:hover:not(:disabled) { background: #000; border-color: #000; }

/* Ballyhass Pink. Navy label, not white: white on pink is 3.11:1. */
.bh-btn--pink { background: var(--bh-pink); border-color: var(--bh-pink); color: var(--bh-ink); }
.bh-btn--pink:hover:not(:disabled) { background: var(--bh-pink-dark); border-color: var(--bh-pink-dark); }

/* Ballyhass Blue. Navy label, not white: white on blue is 2.42:1. */
.bh-btn--blue { background: var(--bh-blue); border-color: var(--bh-blue); color: var(--bh-ink); }
.bh-btn--blue:hover:not(:disabled) { background: var(--bh-blue-dark); border-color: var(--bh-blue-dark); }

.bh-btn--ghost { background: #fff; border-color: var(--bh-ink); color: var(--bh-ink); }
.bh-btn--ghost:hover:not(:disabled) { background: var(--bh-ink); color: #fff; }

.bh-btn--sm { min-height: 44px; padding: 0 18px; font-size: 13px; }

.bh-btn--muted,
.bh-btn:disabled,
.bh-btn[aria-disabled="true"] {
    background: var(--bh-field);
    border-color: var(--bh-field);
    color: var(--bh-ink-45);
    cursor: not-allowed;
    transform: none;
}

.bh-back {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 14.5px; font-weight: 600;
    color: var(--bh-ink-70);
    text-decoration: none;
    margin-bottom: 14px;
}
.bh-back:hover { color: var(--bh-ink); }

/* ------------------------------------------------------------- summary ---- */

.bh-summary {
    background: var(--bh-wash);
    border: 1px solid var(--bh-line);
    border-radius: var(--bh-r-card);
    padding: 24px;
    position: sticky;
    top: 20px;
}
.bh-summary__title { font-size: 22px; font-weight: 700; margin-bottom: 16px; }

.bh-summary__card {
    background: #fff;
    border-radius: var(--bh-r-field);
    padding: 16px;
    box-shadow: var(--bh-shadow-sm);
}
.bh-summary__head { display: flex; gap: 14px; align-items: flex-start; }
/* No per-category imagery is exposed by the API, so this is a branded mark
   rather than a grey void waiting for a photo that never arrives. */
.bh-summary__thumb {
    flex: 0 0 74px; width: 74px; height: 74px;
    border-radius: var(--bh-r-field);
    background: var(--bh-blue);
    color: #fff;
    display: grid;
    place-items: center;
}
.bh-summary__thumb svg { width: 34px; height: 34px; }
.bh-summary__act { font-size: 19px; font-weight: 700; line-height: 1.2; }
.bh-summary__venue {
    display: inline-flex; align-items: center; gap: 5px;
    margin-top: 4px;
    font-size: 12px; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bh-ink-70);
}

.bh-summary__rule { border: 0; border-top: 1px solid var(--bh-line); margin: 16px 0; }

.bh-summary__lbl { font-size: 15px; font-weight: 700; margin-bottom: 3px; }
.bh-summary__val { font-size: 14.5px; color: var(--bh-ink-70); margin: 0 0 14px; }
.bh-summary__val:last-child { margin-bottom: 0; }
.bh-summary__val--empty { color: var(--bh-ink-70); font-style: italic; }
/* Aquapark: the length chosen, under the date and as strong as it (comment 11930380, point 7). */
.bh-summary__val + .bh-summary__duration { margin-top: -10px; }
.bh-summary__duration strong { color: var(--bh-ink); font-weight: 700; }

.bh-summary__line {
    display: flex; justify-content: space-between; gap: 12px;
    font-size: 14.5px;
    padding: 5px 0;
}
.bh-summary__line--save { color: var(--bh-success); font-weight: 600; }
.bh-summary__total {
    display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
    font-size: 20px; font-weight: 800;
    padding-top: 12px;
    margin-top: 8px;
    border-top: 2px solid var(--bh-ink);
}

/* The guide's "highlighted text": Activities Yellow block carrying Navy copy,
   with square corners — "highlighted texts feature a straight square shape",
   as opposed to the rounded square used for buttons (p11). */
.bh-upsell {
    display: flex; gap: 14px; align-items: flex-start;
    margin-top: 18px;
    padding: 16px;
    background: var(--bh-yellow);
    color: var(--bh-ink);
    border-radius: var(--bh-r-highlight);
    font-size: 14px;
    font-weight: 500;
}
.bh-upsell strong { font-weight: 800; }
.bh-upsell a { color: var(--bh-ink); }
.bh-upsell__badge {
    flex: 0 0 auto;
    background: var(--bh-ink); color: var(--bh-yellow);
    font-size: 10px; font-weight: 800; letter-spacing: .08em;
    padding: 5px 9px;
    border-radius: var(--bh-r-highlight);
    text-transform: uppercase;
}

/* Mobile: the summary is more useful pinned to the bottom than 2000px down. */
@media (max-width: 960px) {
    .bh-summary { position: static; }
    .bh-aside { order: 2; }
}

/* -------------------------------------------------------- states/alerts --- */

.bh-alert {
    border-radius: var(--bh-r-field);
    padding: 14px 18px;
    margin-bottom: 22px;
    font-size: 14.5px;
    font-weight: 500;
    border-left: 4px solid;
}
.bh-alert--error   { background: #FDECEC; border-color: var(--bh-danger); color: #8E1F1F; }
.bh-alert--info    { background: #E6F8FB; border-color: var(--bh-blue);   color: #0A5A68; }
.bh-alert--success { background: #E8F5EE; border-color: var(--bh-success); color: #14603A; }
/* Two views already asked for this variant and got the bare .bh-alert, so an
   expiring pass and an overdue deadline read exactly like a neutral note. Amber
   on #7A4300 is 7.4:1, well inside AA. */
.bh-alert--warning { background: #FFF6E5; border-color: #E0A106; color: #7A4300; }

/* A booking conversation, not a chat feed. Ballyhass asked that this read as
   correspondence attached to a visit rather than as a messenger window. */
/* What the cart already holds, shown on step 1 where the summary is otherwise
   client-side and only reflects the selection in progress. */
.bh-held {
    margin-bottom: 18px;
    padding: 12px 14px;
    background: var(--bh-field);
    border-radius: var(--bh-r-field);
}
.bh-held__title {
    margin: 0 0 8px;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--bh-ink-70);
}
.bh-held__count {
    display: inline-block;
    margin-left: 6px;
    padding: 0 6px;
    border-radius: 999px;
    background: rgba(33, 39, 47, .10);
    font-size: 11px;
    line-height: 18px;
}
.bh-held__item { margin-bottom: 8px; }
.bh-held__act { display: block; font-size: 14px; font-weight: 600; color: var(--bh-ink); }
.bh-held__meta { display: block; font-size: 12.5px; color: var(--bh-ink-70); }
.bh-held__note { margin: 10px 0 0; font-size: 12px; color: var(--bh-ink-70); }

/* Minus, the number, plus. Each is a plain submit carrying the quantity it
   would set, so the control needs no JavaScript and the cart that comes back is
   the real one rather than a form somebody forgot to submit. */
.bh-qty { display: flex; align-items: center; gap: 6px; margin: 2px 0 12px; }
.bh-qty__lbl { font-size: 12px; color: var(--bh-ink-70); margin-right: 2px; }
.bh-qty__step {
    width: 30px;
    height: 30px;
    font: inherit;
    font-size: 16px;
    line-height: 1;
    color: var(--bh-ink);
    background: var(--bh-field);
    border: 1px solid var(--bh-line);
    border-radius: 4px;
    cursor: pointer;
}
.bh-qty__step:hover:not(:disabled) { background: var(--bh-field-hi); }
.bh-qty__step:disabled { opacity: .4; cursor: default; }
/* At a quantity of one the minus control is a link into the removal
   confirmation rather than a disabled button, so it needs the same box. */
a.bh-qty__step {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}
.bh-qty__now {
    min-width: 26px;
    text-align: center;
    font-size: 14.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--bh-ink);
}

.bh-thread { display: flex; flex-direction: column; gap: 14px; margin-bottom: 4px; }
.bh-thread__item {
    padding: 12px 14px;
    border-radius: var(--bh-r-field);
    background: var(--bh-field);
    border-left: 3px solid var(--bh-line);
}
.bh-thread__item--mine { background: #E6F8FB; border-left-color: var(--bh-blue); }
.bh-thread__who {
    margin: 0 0 6px;
    font-size: 13px;
    font-weight: 700;
    color: var(--bh-ink);
}
.bh-thread__topic,
.bh-thread__when { font-weight: 500; color: var(--bh-ink-70); margin-left: 8px; }
.bh-thread__body { margin: 0; font-size: 14.5px; line-height: 1.55; white-space: pre-line; }
.bh-alert ul { margin: 0; padding-left: 18px; }

.bh-empty {
    text-align: center;
    padding: 28px 20px;
    background: var(--bh-wash);
    border: 1px dashed var(--bh-line);
    border-radius: var(--bh-r-field);
    color: var(--bh-ink-70);
    font-size: 14.5px;
}

.bh-loading {
    display: flex; align-items: center; gap: 10px;
    color: var(--bh-ink-70);
    font-size: 14.5px;
    padding: 18px 0;
}
.bh-spinner {
    width: 20px; height: 20px;
    border: 2.5px solid var(--bh-field-hi);
    border-top-color: var(--bh-blue);
    border-radius: 50%;
    animation: bh-spin .7s linear infinite;
}
@keyframes bh-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
}

/* -------------------------------------------------------------- footer ---- */

.bh-footer {
    background: var(--bh-ink);
    color: rgba(255,255,255,.7);
    font-size: 13.5px;
    padding: 26px 0;
    margin-top: auto;
}
.bh-footer__in {
    max-width: var(--bh-max);
    margin: 0 auto;
    padding: 0 var(--bh-gutter);
    display: flex; flex-wrap: wrap; gap: 8px 22px;
    align-items: center; justify-content: space-between;
}
.bh-footer a { color: #fff; text-decoration: none; }
.bh-footer a:hover { text-decoration: underline; }
.bh-secure { display: inline-flex; align-items: center; gap: 7px; }

html, body { min-height: 100%; }
body { display: flex; flex-direction: column; }
.bh-main { flex: 1 0 auto; }

/* Alpine: hide templated markup until the component boots. */
[x-cloak] { display: none !important; }

/* --------------------------------------------------------------- modal ---- */

.bh-modal {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: grid;
    place-items: center;
    padding: var(--bh-gutter);
    overflow-y: auto;
}
.bh-modal[hidden] { display: none; }

.bh-modal__backdrop {
    position: fixed;
    inset: 0;
    background: rgba(33, 39, 47, .6);
}
.bh-modal__panel {
    position: relative;
    width: 100%;
    max-width: 460px;
    background: #fff;
    border-radius: var(--bh-r-card);
    box-shadow: var(--bh-shadow);
    padding: clamp(22px, 4vw, 32px);
    margin: auto;
}
.bh-modal__close {
    position: absolute;
    top: 14px; right: 14px;
    width: 36px; height: 36px;
    display: grid; place-items: center;
    background: var(--bh-field);
    color: var(--bh-ink);
    border: 0;
    border-radius: 50%;
    cursor: pointer;
}
.bh-modal__close:hover { background: var(--bh-field-hi); }

.bh-modal__title { font-size: 24px; font-weight: 800; }
.bh-modal__hint  { margin: 6px 0 20px; font-size: 14.5px; color: var(--bh-ink-70); }

.bh-tabs {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px;
    background: var(--bh-field);
    border-radius: var(--bh-r-field);
    padding: 4px;
    margin-bottom: 22px;
}
.bh-tab {
    padding: 11px 8px;
    font: inherit;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--bh-ink-70);
    background: none;
    border: 0;
    border-radius: 4px;
    cursor: pointer;
}
.bh-tab.is-active { background: #fff; color: var(--bh-ink); box-shadow: var(--bh-shadow-sm); }

/* The same control as a set of links rather than buttons, for a tab set that
   changes the page rather than the state of one. Three across for Upcoming,
   Past and Cancelled; it collapses to one column on a phone, where three
   uppercase labels in a row do not fit. */
.bh-tabs--three { grid-template-columns: repeat(3, 1fr); }
a.bh-tab { display: block; text-align: center; text-decoration: none; }
a.bh-tab:hover { color: var(--bh-ink); }
/* Navy on the count's tint: the tab's grey was 4.19:1 on it at 11px (axe, 31 October 2026). */
.bh-tab__count {
    color: var(--bh-ink);
    display: inline-block;
    margin-left: 6px;
    padding: 0 6px;
    border-radius: 999px;
    /* No --bh-ink-10 token exists; a fallback nobody can see is worse than
       a literal that matches the navy it is derived from. */
    background: rgba(33, 39, 47, .10);
    font-size: 11px;
    line-height: 18px;
    vertical-align: 1px;
}
@media (max-width: 520px) {
    .bh-tabs--three { grid-template-columns: 1fr; }
}

/* Provider buttons carry Navy labels on light surfaces — brand-neutral chrome
   so no provider's own colour fights the Ballyhass palette. */
.bh-social { display: grid; gap: 10px; }
.bh-social__btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 52px;
    padding: 0 18px;
    font-weight: 700;
    font-size: 14.5px;
    color: var(--bh-ink);
    text-decoration: none;
    background: #fff;
    border: 1.5px solid var(--bh-line);
    border-radius: var(--bh-r-btn);
}
.bh-social__btn:hover { background: var(--bh-wash); border-color: var(--bh-ink-45); }
.bh-social__mark {
    width: 22px; height: 22px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: var(--bh-ink);
    color: #fff;
    font-size: 12px; font-weight: 800;
}

.bh-or {
    position: relative;
    text-align: center;
    margin: 20px 0;
    font-size: 13px;
    color: var(--bh-ink-70);
}
.bh-or::before {
    content: "";
    position: absolute;
    top: 50%; left: 0; right: 0;
    border-top: 1px solid var(--bh-line);
}
.bh-or span { position: relative; background: #fff; padding: 0 12px; }

.bh-hint { display: block; font-size: 13px; color: var(--bh-ink-70); margin-top: 6px; }

/* ═══════════════════════════════════════════════════════════════════════════
   Quick Book — /book/{activity}

   One card, everything visible: the activity is fixed by the URL, so only
   date, time and party are left and they all fit on one screen. Reached most
   often from a phone (a CTA on an activity page, or a QR code at the venue),
   so it is laid out mobile-first with a sticky total.
   ═════════════════════════════════════════════════════════════════════════ */

.bh-quick__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 22px;
}

/* "Highlighted texts feature a straight square shape" — navy block, yellow
   text, square corners (brand guide p11). */
.bh-quick__activity {
    display: inline-block;
    background: var(--bh-ink);
    color: var(--bh-yellow);
    border-radius: var(--bh-r-highlight);
    padding: 6px 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .02em;
    font-size: clamp(1.05rem, 3.4vw, 1.3rem);
    line-height: 1.25;
}

.bh-quick__venue {
    display: block;
    margin-top: 8px;
    color: var(--bh-ink-70);
    font-weight: 500;
}

.bh-quick__change {
    color: var(--bh-blue-text);
    font-weight: 600;
    font-size: .875rem;
    white-space: nowrap;
}

.bh-quick__jumped {
    background: var(--bh-wash);
    border-left: 4px solid var(--bh-blue);
    border-radius: var(--bh-r-field);
    padding: 12px 14px;
    margin: 0 0 22px;
    color: var(--bh-ink);
    font-weight: 500;
}

.bh-quick__block {
    border: 0;
    padding: 0;
    margin: 0 0 24px;

    /* A fieldset takes its intrinsic width from its content and refuses to
       shrink, so the date strip's own overflow-x never engaged — the whole
       page scrolled sideways instead of the strip scrolling inside itself. */
    min-width: 0;
}

/* "Subtitles are in bold and all caps" (brand guide p10). */
.bh-quick__legend {
    padding: 0;
    margin-bottom: 10px;
    font-size: .75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--bh-ink-70);
}

/* ── Date strip ─────────────────────────────────────────────────────────── */
/* Only bookable days are listed, so this scrolls rather than paging: real
   availability is sparse and a fixed week would be mostly dead cells. */
/* Both strips swipe natively on touch. The arrows are for pointer devices,
   where there is nothing to swipe, and only appear when there is more to see. */
.bh-scroller {
    position: relative;
    display: flex;
    align-items: center;
    min-width: 0;
}

.bh-daystrip,
.bh-timestrip {
    display: flex;
    min-width: 0;
    max-width: 100%;
    flex: 1;
    gap: 8px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-inline: 8px;
    padding-bottom: 6px;
    -webkit-overflow-scrolling: touch;
}

.bh-daystrip::-webkit-scrollbar,
.bh-timestrip::-webkit-scrollbar { height: 4px; }

.bh-daystrip::-webkit-scrollbar-thumb,
.bh-timestrip::-webkit-scrollbar-thumb {
    background: var(--bh-line);
    border-radius: 2px;
}

.bh-scroller__arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 1.5px solid var(--bh-line);
    border-radius: 50%;
    background: var(--bh-panel);
    color: var(--bh-ink);
    cursor: pointer;
    box-shadow: var(--bh-shadow-sm);
}

.bh-scroller__arrow:hover { background: var(--bh-blue); border-color: var(--bh-ink); }
.bh-scroller__arrow svg { width: 17px; height: 17px; }

.bh-scroller__arrow--prev { left: -6px; }
.bh-scroller__arrow--next { right: -6px; }

/* Fade the chips into the arrow, so the one underneath reads as continuing
   off-screen rather than as being obscured by a button on top of it. */
.bh-scroller__arrow::before {
    content: "";
    position: absolute;
    /* Tall enough to cover a whole chip: the arrow is 34px and the date chips
       are ~76px, so a short fade left the selected chip peeking around it. */
    top: -30px;
    bottom: -30px;
    width: 30px;
    pointer-events: none;
}

.bh-scroller__arrow--prev::before {
    left: 100%;
    background: linear-gradient(to left, rgba(255, 255, 255, 0), var(--bh-panel));
}

.bh-scroller__arrow--next::before {
    right: 100%;
    background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--bh-panel));
}

/* Touch devices swipe; an arrow there is a target sitting on top of the chips. */
@media (hover: none), (pointer: coarse) {
    .bh-scroller__arrow { display: none; }
}

.bh-day {
    flex: 0 0 auto;
    scroll-snap-align: start;
    min-width: 64px;
    padding: 10px 8px;
    background: var(--bh-field);
    border: 2px solid transparent;
    border-radius: var(--bh-r-btn);
    color: var(--bh-ink);
    cursor: pointer;
    text-align: center;
    font-family: inherit;
    transition: background .12s ease, border-color .12s ease;
}

.bh-day:hover { background: var(--bh-field-hi); }

/* Navy text on blue — white on blue is 2.42:1 and fails WCAG AA. */
.bh-day.is-on {
    background: var(--bh-blue);
    border-color: var(--bh-ink);
    color: var(--bh-ink);
}

.bh-day__name {
    display: block;
    font-size: .65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--bh-ink-70);
}

.bh-day.is-on .bh-day__name { color: var(--bh-ink); }

.bh-day__num {
    display: block;
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.2;
}

.bh-day__note {
    display: block;
    font-size: .6rem;
    font-weight: 700;
    text-transform: uppercase;
    color: var(--bh-danger);
}

/* ── Time grid ──────────────────────────────────────────────────────────── */
.bh-time { flex: 0 0 auto; scroll-snap-align: start; min-width: 96px; }

.bh-time {
    padding: 10px 6px;
    background: var(--bh-field);
    border: 2px solid transparent;
    border-radius: var(--bh-r-btn);
    color: var(--bh-ink);
    cursor: pointer;
    font-family: inherit;
    text-align: center;
    transition: background .12s ease, border-color .12s ease;
}

.bh-time:hover:not(:disabled) { background: var(--bh-field-hi); }

.bh-time:disabled {
    opacity: .45;
    cursor: not-allowed;
    text-decoration: line-through;
}

.bh-time.is-on {
    background: var(--bh-blue);
    border-color: var(--bh-ink);
    color: var(--bh-ink);
}

.bh-time__at {
    display: block;
    font-size: 1.05rem;
    font-weight: 700;
}

.bh-time__left {
    display: block;
    font-size: .7rem;
    font-weight: 500;
    color: var(--bh-ink-70);
}

.bh-time.is-on .bh-time__left { color: var(--bh-ink); }

/* ── Party ──────────────────────────────────────────────────────────────── */
/* Three tiers on one line. A full-size stepper is ~138px, so three of those
   plus gaps overflow a narrow phone — below 30rem they stack back into rows
   rather than being squeezed to an untappable size. */
.bh-quick__tiers {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
}

.bh-quick__tier {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 12px 6px;
    background: var(--bh-wash);
    border-radius: var(--bh-r-card);
    text-align: center;
}

.bh-quick__tiername {
    font-weight: 600;
    font-size: .9rem;
    line-height: 1.2;
}

.bh-quick__tiername small {
    font-weight: 500;
    color: var(--bh-ink-70);
}

.bh-quick__tierprice {
    color: var(--bh-ink-70);
    font-weight: 500;
    font-size: .8rem;
}

/* Trimmed to fit three across; still a 34px target, above the 24px minimum
   for WCAG 2.5.8 and comfortably tappable. */
.bh-stepper--compact { gap: 2px; }

.bh-stepper--compact .bh-stepper__btn {
    width: 34px;
    height: 34px;
    font-size: 18px;
}

.bh-stepper--compact .bh-stepper__val {
    min-width: 30px;
    font-size: 16px;
}

@media (max-width: 30rem) {
    .bh-quick__tiers { grid-template-columns: 1fr; }

    .bh-quick__tier {
        flex-direction: row;
        justify-content: space-between;
        text-align: left;
        padding: 8px 12px;
    }

    .bh-quick__tiername { flex: 1; }

    .bh-stepper--compact .bh-stepper__btn { width: 38px; height: 38px; }
    .bh-stepper--compact .bh-stepper__val { min-width: 40px; }
}

/* ── Total and actions ──────────────────────────────────────────────────── */
.bh-quick__foot {
    border-top: 1px solid var(--bh-line);
    padding-top: 18px;
    display: grid;
    gap: 14px;
}

.bh-quick__total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.bh-quick__amount {
    font-size: clamp(1.5rem, 5vw, 1.9rem);
    font-weight: 800;
    color: var(--bh-ink);
}

.bh-quick__people {
    color: var(--bh-ink-70);
    font-weight: 500;
}

.bh-quick__or {
    position: relative;
    text-align: center;
    margin: 14px 0;
    color: var(--bh-ink-70);
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .08em;
}

.bh-quick__or::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 50%;
    border-top: 1px solid var(--bh-line);
}

.bh-quick__or span {
    position: relative;
    background: var(--bh-panel);
    padding: 0 12px;
}

#bh-express { min-height: 48px; }

/* On a phone the total and CTA stay in reach while the customer scrolls the
   time grid. Kept off larger screens, where the whole card is already visible. */
@media (max-width: 640px) {
    .bh-quick__foot {
        position: sticky;
        bottom: 0;
        background: var(--bh-panel);
        margin: 0 calc(var(--bh-gutter) * -1) calc(var(--bh-gutter) * -1);
        padding: 14px var(--bh-gutter) calc(14px + env(safe-area-inset-bottom));
        box-shadow: 0 -8px 24px rgba(33, 39, 47, .08);
        z-index: 2;
    }

    /* Scrolling to a control (tabbing, or a validation jump) stops above the
       foot rather than under it: the Under 18 stepper landed half hidden
       (WCAG 2.2 2.4.11). The foot is about 140px with a wallet, more with one. */
    :root:has(.bh-quick__foot) {
        scroll-padding-bottom: 180px;
    }
}
/* The same on a short screen as the booking page's panel (B12): at 400% zoom the foot, about 140px,
   would cover more than half of a 256px window, so there it stays in the page's flow. */
@media (max-width: 640px) and (max-height: 559.98px) {
    .bh-quick__foot { position: static; box-shadow: none; }
    :root:has(.bh-quick__foot) { scroll-padding-bottom: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .bh-day, .bh-time { transition: none; }
}

.bh-day__month {
    display: block;
    font-size: .6rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--bh-blue-text);
}

.bh-day.is-on .bh-day__month { color: var(--bh-ink); }

/* ==========================================================================
   Customer portal
   --------------------------------------------------------------------------
   The portal shipped on a separate Bootstrap 5 CDN layout with a hardcoded
   #1e3a5f navbar, so the screens a customer sees *after* they book looked
   nothing like the ones they booked through. Same brand, same tokens, same
   primitives as the checkout: only these few components were missing.
   ========================================================================== */

/* ----------------------------------------------------------- header nav ---- */

.bh-header__nav {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-left: 8px;
}
.bh-header__navlink {
    color: rgba(255,255,255,.75);
    text-decoration: none;
    font-weight: 600;
    font-size: 13.5px;
    letter-spacing: .02em;
    padding: 8px 14px;
    border-radius: var(--bh-r-btn);
    white-space: nowrap;
    transition: background .15s ease, color .15s ease;
}
.bh-header__navlink:hover { background: rgba(255,255,255,.1); color: #fff; }
.bh-header__navlink.is-on {
    color: var(--bh-ink);
    background: var(--bh-yellow);
}

/* The nav is the primary way around the portal, so it goes under the logo where the
   header cannot hold it in one row, rather than being hidden behind a toggle the customer
   has to find.

   Every link reachable at every width (Eoghan, 3 November 2026, comment 11931884, point 1).
   The row was moved down only at 720px, but logo, nav, greeting and Sign out need about
   1,050px, so from 721px to about 1,050px the header ran off the right edge and the whole
   page scrolled sideways. Below 720px the links scrolled in a strip with its scrollbar
   hidden, which a mouse cannot move. So the nav takes its own row below 1,180px (room for
   a long first name in the greeting) and wraps onto a second line when it needs to. Only a
   phone-sized touch screen swipes it, which is the one place a swipe exists. The header
   itself may wrap at any width, so a longer greeting never pushes it past the edge. */
.bh-header__in { flex-wrap: wrap; }
.bh-header__nav { flex-wrap: wrap; min-width: 0; }
@media (max-width: 1180px) {
    .bh-header__nav {
        order: 3;
        width: 100%;
        margin: 4px -6px 0;
    }
}
@media (max-width: 559px) and (pointer: coarse) {
    .bh-header__nav {
        flex-wrap: nowrap;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
    }
    .bh-header__nav::-webkit-scrollbar { display: none; }
}

/* ----------------------------------------------------------- slim hero ---- */

/* Portal pages are somewhere you land repeatedly, not a one-off flow, so the
   hero is trimmed back — enough to carry the brand, not enough to push the
   content the customer came for below the fold.

   It was stretched to 100% 100% so that a short header still showed both the
   blue and the yellow. That put the torn blue-to-yellow edge halfway down the
   header, through the description (comment 11932022, point 1). The strokes now
   have their own height, smaller here than on the checkout, and sit under the
   text as they do there (.bh-hero above). */
.bh-hero--slim {
    --bh-hero-paint: clamp(24px, 4.5vw, 64px);
    padding: clamp(22px, 3.5vw, 34px) 0 calc(var(--bh-hero-paint) + var(--bh-hero-paint-gap));
}
.bh-hero--slim .bh-hero__title { font-size: clamp(30px, 5vw, 46px); margin-top: 0; }

.bh-hero__crumb {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    color: var(--bh-ink);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    text-decoration: none;
    margin-bottom: 10px;
}
.bh-hero__crumb:hover { text-decoration: underline; }

/* --------------------------------------------------------- panel header ---- */

/* Title on the left, one action on the right, aligned on the title's baseline. */
.bh-panel__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 18px;
}
.bh-panel__head .bh-panel__title { margin-bottom: 0; }

/* A panel whose whole body is a table or a list sits flush to its own edges. */
.bh-panel--flush { padding: 0; overflow: hidden; }
.bh-panel--flush .bh-panel__head {
    margin: 0;
    padding: 18px clamp(20px, 3vw, 30px);
    border-bottom: 1px solid var(--bh-line);
}

/* --------------------------------------------------------------- chips ---- */

/* Square corners are the brand's highlight shape (p11) — buttons are rounded,
   highlights are not. A status is a highlight, so it takes the square form and
   never gets mistaken for something clickable.

   Tones are the bh-alert palette, so an "unsigned" chip and the alert warning
   the customer about it are visibly the same idea. */
.bh-chip {
    display: inline-block;
    padding: 4px 10px;
    border: 1px solid transparent;
    border-radius: var(--bh-r-highlight);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    white-space: nowrap;
    line-height: 1.5;
}
.bh-chip--paid    { background: #E8F5EE; border-color: var(--bh-success); color: #14603A; }
.bh-chip--pending { background: #F4FFB0; border-color: var(--bh-yellow-dark); color: var(--bh-ink); }
.bh-chip--failed  { background: #FDECEC; border-color: var(--bh-danger); color: #8E1F1F; }
.bh-chip--void    { background: var(--bh-field); border-color: var(--bh-line); color: var(--bh-ink-70); }
.bh-chip--info    { background: #E6F8FB; border-color: var(--bh-blue); color: #0A5A68; }

/* --------------------------------------------------------------- table ---- */

/* position:relative makes this the containing block for the absolutely
   positioned .bh-visually-hidden inside the table's header. Without it that
   span's containing block is the page, so on a phone it sat at its static
   position 618px across — outside the viewport but inside the document — and
   gave <html> a 619px scroll width. The page scrolled sideways by an amount
   nothing visible accounted for. */
.bh-tablewrap { overflow-x: auto; position: relative; }

.bh-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14.5px;
}
.bh-table th {
    text-align: left;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--bh-ink-70);
    background: var(--bh-wash);
    padding: 12px clamp(14px, 2vw, 20px);
    border-bottom: 1px solid var(--bh-line);
    white-space: nowrap;
}
.bh-table td {
    padding: 16px clamp(14px, 2vw, 20px);
    border-bottom: 1px solid var(--bh-line);
    vertical-align: middle;
}
.bh-table tbody tr:last-child td { border-bottom: 0; }
.bh-table tbody tr:hover { background: var(--bh-wash); }

.bh-table__ref { font-weight: 700; letter-spacing: .02em; }
.bh-table__num { text-align: right; font-variant-numeric: tabular-nums; }
.bh-table__act { text-align: right; white-space: nowrap; }
.bh-table__act .bh-btn + .bh-btn { margin-left: 8px; }

/* ---------------------------------------------------------------- list ---- */

/* Rows of bookings on the dashboard: same hairline rhythm as the table, but
   stacked rather than columnar, because two of them sit side by side. */
.bh-list { list-style: none; margin: 0; padding: 0; }
.bh-list__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 15px clamp(20px, 3vw, 30px);
    border-bottom: 1px solid var(--bh-line);
}
.bh-list__item:last-child { border-bottom: 0; }
.bh-list__main { min-width: 0; }
/* The button goes under the words when they would have less than 12rem beside it (signed-in pass,
   4 November 2026, finding B13). The name gave all the ground: on the overview's "A few things to
   sort", "Balance of €1,850.00 still to pay" had 115px beside VIEW BALANCE at 390px, and its
   two-line limit cut "still to pay" off; at 320px it had 45px and showed 2 of its 8 lines. */
.bh-list__item { flex-wrap: wrap; }
.bh-list__item > .bh-list__main { flex: 1 1 12rem; }
.bh-list__name {
    font-weight: 700;
    font-size: 15.5px;
    /* Two lines, then ellipsis. Truncating to one line turned every activity
       into "Ballyhass Coachfo…", which names nothing. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}
/* The button keeps its own width; only the name gives ground. */
.bh-list__item > .bh-btn,
.bh-list__item > a.bh-btn { flex: 0 0 auto; white-space: nowrap; }
.bh-list__meta {
    font-size: 13.5px;
    color: var(--bh-ink-70);
    margin-top: 2px;
}

/* --------------------------------------------------------- detail pairs ---- */

.bh-dl {
    display: grid;
    grid-template-columns: minmax(140px, 34%) minmax(0, 1fr);
    gap: 0;
    margin: 0;
}
.bh-dl dt {
    font-weight: 700;
    font-size: 14.5px;
    padding: 11px 0;
    border-bottom: 1px solid var(--bh-line);
}
.bh-dl dd {
    margin: 0;
    padding: 11px 0;
    color: var(--bh-ink-70);
    border-bottom: 1px solid var(--bh-line);
}
.bh-dl dt:last-of-type, .bh-dl dd:last-of-type { border-bottom: 0; }

@media (max-width: 520px) {
    .bh-dl { grid-template-columns: minmax(0, 1fr); }
    .bh-dl dt { padding-bottom: 0; border-bottom: 0; }
    .bh-dl dd { padding-top: 2px; }
}

/* --------------------------------------------------------------- cards ---- */

/* A card is at least 320px, or the whole width where the column is narrower: at 320px (400% zoom)
   the column is 288px, and a 320px minimum scrolled the account overview sideways (WCAG 1.4.10;
   signed-in pass, 4 November 2026, finding B8). */
.bh-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
    gap: 20px;
    align-items: start;
}

/* A row of actions that stays on one line until it can't. */
.bh-actions { display: flex; flex-wrap: wrap; gap: 10px; }

/* ------------------------------------------------------------ paginator ---- */

/* Laravel's default paginator markup is Tailwind-flavoured; the portal renders
   the simple variant, which is a plain <nav> of links. */
.bh-pager { margin-top: 22px; }
.bh-pager svg { width: 16px; height: 16px; }
.bh-pager nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.bh-pager .pagination,
.bh-pager ul {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
    padding: 0;
}
.bh-pager a,
.bh-pager span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0 12px;
    border: 1px solid var(--bh-line);
    border-radius: var(--bh-r-btn);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    color: var(--bh-ink);
    background: #fff;
}
.bh-pager a:hover { background: var(--bh-field); }
.bh-pager .active span,
.bh-pager [aria-current="page"] span {
    background: var(--bh-ink);
    border-color: var(--bh-ink);
    color: #fff;
}
.bh-pager .disabled span { opacity: .4; }

/* ---------------------------------------------------------------- auth ---- */

/* The sign-in page has no header nav to sit under — there is nothing to
   navigate to yet — so it centres a single panel under the same chrome. */
.bh-auth { max-width: 460px; margin: 0 auto; }
.bh-auth__foot {
    text-align: center;
    margin-top: 20px;
    font-size: 14px;
}

/* --------------------------------------------------------------- money ---- */

.bh-money {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 0;
    font-variant-numeric: tabular-nums;
}
.bh-money + .bh-money { border-top: 1px solid var(--bh-line); }
.bh-money__lbl { color: var(--bh-ink-70); font-size: 14.5px; }
.bh-money__val { font-weight: 700; }
.bh-money--due .bh-money__lbl,
.bh-money--due .bh-money__val { color: var(--bh-danger); }

/* An empty state inside a flush panel is already framed by the panel; the
   dashed box it carries elsewhere would draw a second border inside the first. */
.bh-empty p { margin: 0 0 12px; }
.bh-empty p:last-child { margin-bottom: 0; }
.bh-panel--flush .bh-empty {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 32px 20px;
}


/* --------------------------------------------------- table on a phone ---- */

/* Six columns do not fit a phone. Left as a scrolling table, the reference and
   activity are visible and View and Book again are not: a customer would have
   to discover a sideways scroll to open their own booking. Each row becomes a
   block of labelled pairs instead, with the actions at the bottom where a
   thumb reaches them.

   The labels come from data-label on each cell, so the <th> text and the
   stacked label cannot drift apart. */
@media (max-width: 719px) {
    .bh-table thead {
        position: absolute; width: 1px; height: 1px;
        margin: -1px; padding: 0; overflow: hidden;
        clip: rect(0 0 0 0); white-space: nowrap; border: 0;
    }
    .bh-table,
    .bh-table tbody,
    .bh-table tr,
    .bh-table td { display: block; width: 100%; }

    .bh-table tr {
        padding: 16px var(--bh-gutter);
        border-bottom: 1px solid var(--bh-line);
    }
    .bh-table tbody tr:last-child { border-bottom: 0; }
    .bh-table tbody tr:hover { background: transparent; }

    .bh-table td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 16px;
        padding: 4px 0;
        border: 0;
        text-align: left;
    }
    .bh-table td::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: 11.5px;
        font-weight: 700;
        letter-spacing: .09em;
        text-transform: uppercase;
        color: var(--bh-ink-70);
    }
    /* The reference names the row, so it leads: bigger, and a block rather
       than a label/value pair, so anything else in the cell (the participants
       table puts the category under the place name) stays underneath it
       instead of being pushed to the far edge by the flex row. */
    .bh-table td.bh-table__ref {
        display: block;
        font-size: 16px;
        padding-bottom: 10px;
    }

    .bh-table__act {
        display: flex;
        flex-wrap: wrap;
        gap: 10px;
        padding-top: 12px;
    }
    .bh-table__act .bh-btn { flex: 1 1 auto; justify-content: center; }
    .bh-table__act .bh-btn + .bh-btn { margin-left: 0; }
}

/* ── Multi-activity itinerary (REQ-F014) ──────────────────────────────────
   The order summary represents the whole visit rather than the most recent
   selection, so each session reads as its own entry with its venue, times and
   a way to remove it. */
.bh-summary__session + .bh-summary__session {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid rgba(33, 39, 47, 0.12);
}

.bh-summary__arrive {
    margin: 4px 0 8px;
    font-size: 13px;
    font-weight: 600;
    /* Brand blue fails AA on white (2.42:1), so the accessible blue. */
    color: #0B7A8E;
}

.bh-summary__remove {
    margin-top: 8px;
    padding: 0;
    border: 0;
    background: none;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--bh-navy, #21272F);
    text-decoration: underline;
    cursor: pointer;
}

.bh-summary__remove:hover,
.bh-summary__remove:focus-visible { color: #C2185B; }

.bh-summary__add {
    display: inline-block;
    margin-top: 16px;
    font-size: 14px;
    font-weight: 700;
    color: #0B7A8E;
    text-decoration: none;
}

.bh-summary__add:hover,
.bh-summary__add:focus-visible { text-decoration: underline; }

/* ── Adventure Pass detail ────────────────────────────────────────────────
   The page was a list of three names. It now compares price, term, what is
   included and what is not, from Ballyhass' own terms. */
.bh-pass__price { margin: 0 0 4px; font-size: 26px; font-weight: 800; color: var(--bh-navy, #21272F); }
.bh-pass__term { font-size: 15px; font-weight: 500; }
.bh-pass__member { margin: 0 0 12px; font-size: 14px; font-weight: 600; color: #0B7A8E; }
.bh-pass__subhead {
    margin: 20px 0 6px;
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--bh-navy, #21272F);
}
.bh-pass__list { margin: 0; padding-left: 20px; font-weight: 500; }
.bh-pass__list li { margin-bottom: 4px; }
.bh-pass__list--excluded li { color: #5b6470; }
.bh-pass__note { margin: 0; font-weight: 500; }

/* Removal confirmations in the order summary.

   Ballyhass' marketing team, 18 September: confirm the consequential removals
   and leave ordinary quantity changes alone. Rendered by the server rather than
   a script, so it works with JavaScript off and reads in order to a screen
   reader, which the rest of this summary already does. */
.bh-confirm {
    margin-top: 10px;
    padding: 12px 14px;
    border: 1px solid var(--bh-line);
    border-left: 3px solid var(--bh-pink);
    border-radius: var(--bh-r-field);
    background: var(--bh-field);
}
.bh-confirm__ask {
    margin: 0 0 10px;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.45;
    color: var(--bh-ink);
}
.bh-confirm__acts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.bh-confirm__acts form { margin: 0; }

/* A link that reads as the existing remove control. */
a.bh-summary__remove { display: inline-block; text-decoration: none; }

/* Booking calendar.

   Three states the customer can tell apart at a glance, which is what Ballyhass
   asked for: a day with places, a day that is full, and a day the activity does
   not run. A native date input could show none of them.

   Colour is never the only signal: a full day is struck through and disabled, a
   closed day is disabled and muted, and every day carries an aria-label saying
   which it is. */
.bh-cal {
    border: 1px solid var(--bh-line);
    border-radius: var(--bh-r-field);
    padding: 12px;
    background: var(--bh-surface, #fff);
}
.bh-cal__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 10px;
}
.bh-cal__month { font-size: 15px; font-weight: 700; color: var(--bh-ink); }
.bh-cal__nav {
    width: 32px; height: 32px;
    font: inherit; line-height: 1;
    color: var(--bh-ink);
    background: var(--bh-field);
    border: 1px solid var(--bh-line);
    border-radius: 6px;
    cursor: pointer;
}
.bh-cal__nav:disabled { opacity: .35; cursor: default; }
.bh-cal__dow, .bh-cal__grid {
    display: grid;
    /* minmax(0, ...): a day cell may be narrower than its 38px height, so seven of them fit a
       320px screen (WCAG 1.4.10; 1fr let each keep 38px and the week ran 20px off the edge). */
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 4px;
}
.bh-cal__dow {
    margin-bottom: 4px;
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    text-align: center;
    color: var(--bh-ink-70);
}
.bh-cal__day {
    width: 100%;
    min-width: 0;
    aspect-ratio: 1 / 1;
    min-height: 38px;
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    color: var(--bh-ink);
    background: var(--bh-field);
    border: 1px solid var(--bh-line);
    border-radius: 6px;
    cursor: pointer;
}
.bh-cal__day--empty { background: none; border: none; cursor: default; }
.bh-cal__day.is-available { background: #E8F8FC; border-color: var(--bh-blue, #00B6D9); }
.bh-cal__day.is-waitlist  { background: #FFF6E5; border-color: #E0A32E; }
.bh-cal__day.is-soldout   { text-decoration: line-through; opacity: .55; cursor: not-allowed; }
.bh-cal__day.is-closed    { opacity: .3; cursor: not-allowed; }
.bh-cal__day.is-chosen {
    background: var(--bh-navy, #21272F);
    border-color: var(--bh-navy, #21272F);
    color: #fff;
}
.bh-cal__key {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    margin: 10px 0 0;
    font-size: 12.5px;
    color: var(--bh-ink-70);
}
.bh-cal__swatch {
    width: 12px; height: 12px;
    border: 1px solid var(--bh-line);
    border-radius: 3px;
    background: var(--bh-field);
}
.bh-cal__swatch.is-available { background: #E8F8FC; border-color: var(--bh-blue, #00B6D9); }
.bh-cal__swatch.is-soldout   { opacity: .55; }
.bh-cal__swatch.is-closed    { opacity: .3; }
.bh-field--wide { grid-column: 1 / -1; }

/* Next dates, for offers chosen by date rather than from a month (Open Nights,
   hosted events). Same states and colours as the calendar days. */
.bh-datelist { display: grid; gap: 8px; }
.bh-datecard {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px 14px;
    font: inherit;
    text-align: left;
    color: var(--bh-ink);
    background: #E8F8FC;
    border: 1px solid var(--bh-blue, #00B6D9);
    border-radius: 6px;
    cursor: pointer;
}
.bh-datecard__day { font-weight: 600; }
.bh-datecard__state { font-size: 13px; color: var(--bh-ink-70); }
.bh-datecard.is-waitlist { background: #FFF6E5; border-color: #E0A32E; }
.bh-datecard.is-soldout { background: var(--bh-field); border-color: var(--bh-line); opacity: .55; cursor: not-allowed; }
.bh-datecard.is-chosen { background: var(--bh-navy, #21272F); border-color: var(--bh-navy, #21272F); color: #fff; }
.bh-datecard.is-chosen .bh-datecard__state { color: #fff; }
.bh-datelist__more {
    justify-self: start;
    padding: 0;
    font: inherit;
    font-size: 13px;
    color: #0B7A8E;
    text-decoration: underline;
    background: none;
    border: none;
    cursor: pointer;
}

/* ── Payment terms ────────────────────────────────────────────────────────
   What the customer pays today against what they still owe. Ballyhass asked
   for the whole commitment in plain language rather than a single figure, so
   the rows are equal weight apart from today's payment.

   Navy on white throughout: Blue and Pink both fail AA as a text colour.       */
.bh-panel--terms { border-left: 4px solid var(--bh-blue, #00B6D9); }

.bh-terms { margin: 0; }

.bh-terms__row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding: .55rem 0;
    border-bottom: 1px solid rgba(33, 39, 47, .08);
}

.bh-terms__row:last-child { border-bottom: 0; }

.bh-terms__row dt {
    margin: 0;
    color: var(--bh-navy, #21272F);
    font-weight: 500;
}

.bh-terms__row dd {
    margin: 0;
    color: var(--bh-navy, #21272F);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

/* Today's payment is the one figure that carries weight. */
.bh-terms__row--strong dt,
.bh-terms__row--strong dd {
    font-weight: 800;
    font-size: 1.0625rem;
}

.bh-terms__note {
    margin: .85rem 0 0;
    color: var(--bh-navy, #21272F);
    opacity: .75;
    font-size: .875rem;
}

/* My bookings search and filter. Layout only: the controls themselves reuse
   .bh-input, .bh-select and .bh-label so they match every other form in the
   portal rather than becoming a second visual language for one screen.

   The search box takes the spare width and the two dropdowns stay at their
   content width, because a year select as wide as a search field reads as though
   it expects typing. Everything stacks on a phone, where four controls in a row
   leaves each one too narrow to use. */
.bh-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px;
    margin-bottom: 22px;
}
.bh-filters__field { flex: 0 0 auto; }
.bh-filters__field:first-child { flex: 1 1 240px; min-width: 0; }
.bh-filters .bh-input, .bh-filters .bh-select {
    /* Shorter than the 60px checkout fields: this is a toolbar above a table,
       not a form somebody is filling in. */
    height: 48px;
    padding: 0 14px;
}
.bh-filters .bh-select { padding-right: 42px; }
.bh-filters .bh-label { font-size: 13px; margin-bottom: 6px; }
.bh-filters__actions { display: flex; gap: 8px; flex: 0 0 auto; }

@media (max-width: 640px) {
    .bh-filters { display: block; }
    .bh-filters__field { margin-bottom: 12px; }
    .bh-filters__actions { margin-top: 4px; }
}

/* Alternative sessions, offered when no session on the chosen date can take the
   whole party. Eoghan, 24 September 2026: the customer "should always explicitly
   choose the alternative", so these are links that look like choices rather than
   anything pre-selected, and they sit below the normal session list rather than
   replacing it. */
.bh-alts { display: grid; gap: 10px; margin-top: 14px; }
.bh-alt {
    display: block;
    padding: 14px 16px;
    background: var(--bh-field);
    border: 1px solid transparent;
    border-radius: var(--bh-r-field);
    text-decoration: none;
    color: var(--bh-ink);
    transition: background .15s ease, border-color .15s ease;
}
.bh-alt:hover { background: var(--bh-field-hi); border-color: var(--bh-ink); }
.bh-alt__lead { display: block; font-weight: 700; }
.bh-alt__detail { display: block; font-size: 13px; color: var(--bh-ink-70); margin-top: 2px; }

/* Mobile checkout header, lightened.

   Eoghan, 26 September 2026, after a pass on a real phone: "the dark navigation,
   cyan section, yellow paint strip, progress indicator, very large Checkout
   heading and explanatory copy all stack before the customer reaches the actual
   controls [...] I'd simplify the mobile header considerably and get the Activity
   / Location / Date controls much higher on the screen."

   Desktop is left alone, which he was explicit about: "On desktop this may have
   enough breathing room." So this is a narrow-screen change only.

   Three things go, in order of how little they were earning:

   The supporting sentence. Every step's panel heading already says the same thing
   in fewer words, so on a phone it was the second of two answers to one question.

   Most of the vertical padding. The banner image carries the yellow treatment he
   objected to, and less height shows less of it without touching the asset. Since
   3 November 2026 (comment 11932022) the strokes are a thin band of their own under
   the text, as on every other width, rather than a crop that moved with the header.

   The title's floor. clamp(38px, 7vw, 62px) never went below 38px, so a 390px
   phone got a 38px heading purely because the minimum said so.

   The repeated "Step N of 4" inside each panel is gone from the markup rather
   than hidden here: the progress rail above it already says where the customer
   is, and saying it twice was the duplication he actually named. */
@media (max-width: 640px) {
    .bh-hero,
    .bh-hero--slim {
        --bh-hero-paint: 24px;
        --bh-hero-paint-gap: 12px;
        padding: 14px 0 calc(var(--bh-hero-paint) + var(--bh-hero-paint-gap));
    }
    .bh-hero__title {
        font-size: 26px;
        letter-spacing: -.01em;
        margin-top: 10px;
    }
    .bh-hero__sub { display: none; }
}

/* "Activity added" confirmation, shown above the selector when something is
   already in the booking.

   Eoghan, 26 September 2026: pressing Add another activity landed on a screen
   almost identical to the first one, so "as a customer it feels like the booking
   has restarted". The order summary already listed what was held, but it is the
   grid's second column and stacks below the form on a phone, so the reassurance
   was off-screen exactly when it was wanted.

   Deliberately quiet: a confirmation, not an alert. The customer has not done
   anything wrong and the selector below is still the thing to look at. */
.bh-added {
    background: var(--bh-field);
    border-left: 4px solid var(--bh-ink);
    border-radius: var(--bh-r-field);
    padding: 14px 16px;
    margin-bottom: 18px;
}
.bh-added__title {
    margin: 0;
    font-weight: 700;
    font-size: 15px;
}
.bh-added__title::before {
    /* A tick, so the state reads at a glance before any of the words do. */
    content: '\2713\00a0';
    font-weight: 900;
}
.bh-added__list { margin: 8px 0 0; padding: 0; list-style: none; }
.bh-added__list li { margin-bottom: 6px; }
.bh-added__list li:last-child { margin-bottom: 0; }
.bh-added__meta { display: block; font-size: 13px; color: var(--bh-ink-70); }
.bh-added__hint { margin: 10px 0 0; font-size: 13px; color: var(--bh-ink-70); }

/* ── Step 1: location first, then a grouped experience picker ─────────────
   Eoghan, 29 September 2026: a grouped picker rather than a giant native
   select. Cards in the field colour like .bh-alt; the chosen one is navy with
   yellow text, the brand's highlight. */
.bh-choices { border: 0; padding: 0; margin: 0 0 20px; min-width: 0; }
.bh-choices .bh-label { padding: 0; margin-bottom: 8px; }
.bh-choices__row,
.bh-choices__grid {
    display: grid;
    gap: 8px;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 180px), 1fr));
}
.bh-choices__row { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.bh-choices__group + .bh-choices__group { margin-top: 14px; }
.bh-choices__heading {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bh-ink-70);
    margin: 0 0 6px;
}
.bh-choice {
    display: block;
    width: 100%;
    text-align: left;
    padding: 12px 14px;
    background: var(--bh-field);
    border: 1px solid transparent;
    border-radius: var(--bh-r-field);
    color: var(--bh-ink);
    font: inherit;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}
.bh-choice:hover:not(:disabled) { background: var(--bh-field-hi); border-color: var(--bh-ink); }
.bh-choice.is-chosen { background: var(--bh-ink); color: var(--bh-yellow); border-color: var(--bh-ink); }
.bh-choice.is-chosen .bh-choice__meta { color: var(--bh-white); }
.bh-choice:disabled { cursor: not-allowed; opacity: .55; }
.bh-choice__name { display: block; font-weight: 700; }
.bh-choice__meta { display: block; font-size: 13px; color: var(--bh-ink-70); margin-top: 2px; }
.bh-choice__meta:empty { display: none; }
.bh-choices__more { margin-top: 14px; }
.bh-choices__more summary { cursor: pointer; font-weight: 600; color: var(--bh-blue-text); }
.bh-choices__list { list-style: none; margin: 10px 0; padding: 0; }
.bh-choices__list li { padding: 6px 0; border-bottom: 1px solid var(--bh-line); display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.bh-choices__list li span { color: var(--bh-ink-70); font-size: 13px; }
.bh-summary__variant { display: block; font-size: 13px; color: var(--bh-ink-70); }

/* Experience cards with an image and a line of description (Eoghan, 2 Oct 2026). */
.bh-choice--card { display: flex; gap: 12px; align-items: flex-start; }
.bh-choice__img { flex: 0 0 64px; width: 64px; height: 64px; object-fit: cover; border-radius: var(--bh-r-field); background: var(--bh-field-hi); }
.bh-choice__body { min-width: 0; }
.bh-choice__desc { display: block; font-size: 13px; line-height: 1.35; margin-top: 2px; color: var(--bh-ink-70);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.bh-choice.is-chosen .bh-choice__desc { color: var(--bh-white); }
.bh-choices__grid:has(.bh-choice--card) { grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); }

/* A badge Ballyhass set in Admin on a featured offer: navy block, yellow text. */
.bh-choice__badge { display: inline-block; margin-bottom: 4px; padding: 1px 6px; font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em; background: var(--bh-ink); color: var(--bh-yellow); border-radius: var(--bh-r-highlight); }

/* ==========================================================================
   "You're going to Ballyhass!" - the pre-visit experience (bh-yg-*)
   --------------------------------------------------------------------------
   Eoghan, comment 11927649: "premium, polished and fun without becoming
   childish or gimmicky", "not unnecessary animations", and usable "on an
   ordinary phone with imperfect connectivity". So: one photograph that
   carries the opening, brand type doing the rest, and motion limited to a
   short rise on arrival and the tick at the end, both off under
   prefers-reduced-motion. Navy on blue and pink throughout, never white.
   ========================================================================== */

.bh-yg { display: grid; gap: 20px; }
/* A display rule on a component must not beat the hidden attribute the page's script sets. */
.bh-yg [hidden] { display: none !important; }

/* The opening: the photograph with the celebration over it. */
.bh-yg-hero {
    position: relative;
    margin: 0;
    border-radius: var(--bh-r-card);
    overflow: hidden;
    background: var(--bh-ink);
    color: #fff;
    min-height: 420px;
    display: flex;
    align-items: flex-end;
    isolation: isolate;
}
.bh-yg-hero__img,
.bh-yg-hero__img img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: -2;
}
/* Navy from the foot up, so white type sits on near-solid navy wherever it falls. */
.bh-yg-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(180deg, rgba(33, 39, 47, 0) 18%, rgba(33, 39, 47, .72) 55%, rgba(33, 39, 47, .96) 100%);
}
.bh-yg-hero__body { padding: clamp(22px, 5vw, 40px); width: 100%; }

/* The photograph above the words, never behind them (Eoghan, comment 11932022: decoration should
   never interfere with what a customer needs to read; finding B9, 4 November 2026). The gradient
   above left the heading on the photograph wherever the picture was bright: "You're going to
   Ballyhass!" measured 1.71:1 over the worst tenth of the archery photograph at 1366 pixels, where
   large text needs 3:1. Now the photograph keeps a band of its own at the top (--bh-yg-photo) and
   the words sit on navy, faded in over the first --bh-yg-fade of their box, so they are on navy
   however far they wrap. Nothing fixes the height: the opening grows with its words. */
.bh-yg-hero--photo {
    --bh-yg-photo: clamp(150px, 22vw, 200px);
    --bh-yg-fade: 36px;
}
.bh-yg-hero--photo .bh-yg-hero__body {
    margin-top: var(--bh-yg-photo);
    background: linear-gradient(180deg, transparent 0, var(--bh-ink) var(--bh-yg-fade));
}
.bh-yg-hero__title {
    font-size: clamp(36px, 10vw, 60px);
    font-weight: 900;
    letter-spacing: -.02em;
    line-height: 1.02;
    margin: 12px 0 10px;
    color: #fff;
}
.bh-yg-hero__lede { margin: 0 0 18px; font-size: 17px; max-width: 34ch; color: #fff; }

/* "Highlighted text: navy block, yellow text, straight square" (p11). */
.bh-yg-mark {
    display: inline-block;
    background: var(--bh-ink);
    color: var(--bh-yellow);
    border-radius: var(--bh-r-highlight);
    padding: 4px 10px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
}
.bh-yg-hero .bh-yg-mark { box-shadow: 0 0 0 1px rgba(228, 255, 26, .35); }

.bh-yg-facts-inline { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.bh-yg-facts-inline li {
    background: rgba(33, 39, 47, .55);
    border: 1px solid rgba(255, 255, 255, .35);
    border-radius: var(--bh-r-field);
    padding: 6px 10px;
    font-size: 14px;
    font-weight: 600;
    color: #fff;
}

/* A section of the journey. Quieter than a form panel: these are to read. */
.bh-yg-section__title { font-size: clamp(24px, 6vw, 32px); font-weight: 800; letter-spacing: -.01em; margin: 0 0 10px; }
.bh-yg-section__lede { font-size: 17px; margin: 0 0 18px; }

.bh-yg-facts { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.bh-yg-facts li { background: var(--bh-wash); border-left: 4px solid var(--bh-blue); padding: 14px 14px 12px; border-radius: 0 var(--bh-r-field) var(--bh-r-field) 0; }
.bh-yg-facts strong { display: block; font-size: clamp(18px, 5vw, 21px); font-weight: 800; line-height: 1.15; }
.bh-yg-facts span { display: block; font-size: 13.5px; color: var(--bh-ink-70); margin-top: 4px; }

.bh-yg-wide { margin: 18px 0 0; border-radius: var(--bh-r-card); overflow: hidden; aspect-ratio: 960 / 287; background: var(--bh-wash); }
.bh-yg-wide img { width: 100%; height: 100%; object-fit: cover; }

.bh-yg-answers { margin: 18px 0 0; display: grid; gap: 12px; }
.bh-yg-answers dt { font-weight: 700; }
.bh-yg-answers dd { margin: 2px 0 0; color: var(--bh-ink-70); }

.bh-yg-links { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 12px 0 0; font-weight: 600; }
.bh-yg-links a { min-height: 44px; display: inline-flex; align-items: center; }

/* Getting ready: who is on the booking, by ticket, and where each is up to. */
.bh-yg-ready { border-top: 4px solid var(--bh-blue); }
.bh-yg-people { list-style: none; margin: 0 0 20px; padding: 0; }
.bh-yg-people li { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-top: 1px solid var(--bh-line); }
.bh-yg-people li:first-child { border-top: 0; }
.bh-yg-people__name { flex: 1 1 auto; font-weight: 600; }
.bh-yg-people__state { font-size: 13.5px; color: var(--bh-ink-70); text-align: right; }
.bh-yg-dot { flex: 0 0 28px; width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--bh-ink-45); display: grid; place-items: center; font-size: 15px; font-weight: 800; }
.bh-yg-dot--done { background: var(--bh-ink); border-color: var(--bh-ink); color: var(--bh-yellow); }
.bh-yg-dot--again { border-color: var(--bh-pink); border-width: 3px; }

.bh-yg-bar { display: flex; gap: 4px; margin: 0 0 8px; }
.bh-yg-bar span { flex: 1 1 0; height: 6px; border-radius: 3px; background: var(--bh-line); }
.bh-yg-bar span.is-done { background: var(--bh-ink); }
.bh-yg-bar span.is-now { background: var(--bh-blue); }

/* One participant's form. Large targets, one question at a time to the eye. */
.bh-yg-form .bh-field { margin-bottom: 18px; }
.bh-yg-q { font-size: 17px; font-weight: 700; margin: 0 0 10px; display: block; }
.bh-yg-fieldset { border: 0; padding: 0; margin: 0 0 22px; min-width: 0; }
.bh-yg-fieldset legend { padding: 0; }
.bh-yg-choices { display: grid; gap: 8px; }
.bh-yg-choices--row { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
.bh-yg-choices--row .bh-yg-choice { padding: 10px 12px; gap: 10px; }
.bh-yg-choice span { min-width: 0; overflow-wrap: anywhere; }
.bh-yg-choice {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 56px;
    padding: 12px 14px;
    border: 2px solid var(--bh-line);
    border-radius: var(--bh-r-btn);
    background: #fff;
    cursor: pointer;
    font-weight: 600;
}
.bh-yg-choice input { width: 20px; height: 20px; flex: 0 0 auto; accent-color: var(--bh-ink); margin: 0; }
.bh-yg-choice:has(input:checked) { border-color: var(--bh-ink); background: var(--bh-wash); box-shadow: inset 0 0 0 1px var(--bh-ink); }

.bh-yg-signer { display: flex; justify-content: space-between; align-items: center; gap: 12px; background: var(--bh-wash); padding: 10px 14px; border-radius: var(--bh-r-field); margin: 0 0 22px; font-size: 15px; }
.bh-yg-signer a { font-weight: 600; white-space: nowrap; min-height: 44px; display: inline-flex; align-items: center; }

.bh-yg-terms { border: 1px solid var(--bh-line); border-radius: var(--bh-r-field); margin: 0 0 16px; }
.bh-yg-terms summary { cursor: pointer; font-weight: 700; padding: 14px; min-height: 48px; }
.bh-yg-terms__text { max-height: 300px; overflow-y: auto; padding: 0 14px 14px; font-size: 14.5px; line-height: 1.6; }
.bh-yg-agree { display: flex; gap: 12px; align-items: flex-start; cursor: pointer; font-size: 15px; margin: 0 0 14px; }
.bh-yg-agree input { width: 22px; height: 22px; margin-top: 1px; flex: 0 0 auto; accent-color: var(--bh-ink); }

.bh-yg-saved { display: flex; gap: 10px; align-items: center; background: var(--bh-ink); color: #fff; padding: 12px 14px; border-radius: var(--bh-r-field); font-weight: 600; }
.bh-yg-saved b { color: var(--bh-yellow); }

/* You're ready. */
.bh-yg-done { text-align: center; padding: clamp(28px, 6vw, 48px) clamp(18px, 4vw, 36px); background: var(--bh-ink); color: #fff; border-radius: var(--bh-r-card); }
.bh-yg-done .bh-yg-hero__title { margin-top: 18px; }
.bh-yg-done p { color: #fff; margin: 0 auto; max-width: 36ch; font-size: 17px; }
.bh-yg-tick { width: 88px; height: 88px; margin: 0 auto; display: block; }
.bh-yg-tick circle { fill: var(--bh-yellow); }
.bh-yg-tick path { fill: none; stroke: var(--bh-ink); stroke-width: 7; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 60; stroke-dashoffset: 0; }

.bh-yg-arrival { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.bh-yg-arrival li { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 12px; }
.bh-yg-arrival b { font-size: 13px; letter-spacing: .08em; text-transform: uppercase; color: var(--bh-blue-text); padding-top: 2px; }
@media (max-width: 420px) {
    .bh-yg-arrival li { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

.bh-yg-small { font-size: 13.5px; color: var(--bh-ink-70); }

/* Motion: a short rise as each part arrives, and the tick drawing itself. */
@keyframes bh-yg-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes bh-yg-draw { from { stroke-dashoffset: 60; } to { stroke-dashoffset: 0; } }
@keyframes bh-yg-pop { 0% { transform: scale(.6); opacity: 0; } 70% { transform: scale(1.06); opacity: 1; } 100% { transform: scale(1); } }
.bh-yg-rise { animation: bh-yg-rise .5s ease-out both; animation-delay: var(--d, 0s); }
.bh-yg-tick { animation: bh-yg-pop .45s ease-out both; }
.bh-yg-tick path { animation: bh-yg-draw .5s .3s ease-out both; }

@media (prefers-reduced-motion: reduce) {
    .bh-yg-rise, .bh-yg-tick, .bh-yg-tick path { animation: none; }
}

@media (min-width: 720px) {
    .bh-yg-hero { min-height: 460px; }
    .bh-yg-facts { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Polish (round 20 Oct 2026, yg-polish-1020; Eoghan, comment 11927952). The way in sits in the
   opening, so a phone reaches it without scrolling, and the opening is shorter on a phone while
   keeping the photograph. */
.bh-yg-hero__cta { margin-top: 18px; display: grid; gap: 4px; max-width: 420px; }
.bh-yg-hero__more { color: #fff; font-weight: 600; font-size: 15px; text-decoration: underline; text-underline-offset: 3px;
    min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
.bh-yg-hero__more:hover, .bh-yg-hero__more:focus { color: var(--bh-yellow); }
.bh-yg-back { border-top: 4px solid var(--bh-ink); }

/* "Not you?" is a button (it forgets the signer), dressed as the link it reads as. */
.bh-yg-linkbtn { background: none; border: 0; padding: 0; font: inherit; font-weight: 600; color: var(--bh-blue-text);
    text-decoration: underline; cursor: pointer; white-space: nowrap; min-height: 44px; }
.bh-yg-role { font-weight: 600; margin: 0 0 18px; }

/* Asked to confirm again: said plainly, before anything is asked. */
.bh-yg-again { border-left: 4px solid var(--bh-pink); background: var(--bh-wash); padding: 12px 14px; margin: 0 0 20px;
    border-radius: 0 var(--bh-r-field) var(--bh-r-field) 0; }
.bh-yg-again p { margin: 4px 0 0; font-size: 15px; }

@media (max-width: 559px) {
    .bh-yg { gap: 14px; }
    .bh-yg-hero { min-height: 0; }
    .bh-yg-hero__body { padding: 150px 18px 18px; }
    /* The photograph's band is the margin, so the words' navy starts below it. */
    .bh-yg-hero--photo { --bh-yg-photo: 132px; }
    .bh-yg-hero--photo .bh-yg-hero__body { padding: 18px; }
    .bh-yg-hero__title { font-size: 34px; margin: 8px 0 6px; }
    .bh-yg-hero__lede { font-size: 15.5px; margin: 0 0 12px; }
    .bh-yg-facts-inline { gap: 6px; }
    .bh-yg-facts-inline li { font-size: 13px; padding: 4px 8px; }
    .bh-yg-hero__cta { margin-top: 14px; max-width: none; }
    .bh-yg-section__title { font-size: 23px; }
    .bh-yg-section__lede { font-size: 16px; margin-bottom: 14px; }
    .bh-yg-facts { gap: 8px; }
    .bh-yg-facts li { padding: 10px 10px 8px; }
    .bh-yg-facts strong { font-size: 17px; }
    .bh-yg-wide { aspect-ratio: 960 / 200; margin-top: 14px; }
}

/* ==========================================================================
   The visit-centred Group Portal (bh-gp-*), round group-portal-1020
   --------------------------------------------------------------------------
   Eoghan, comment 11927953: "mobile-first, easy to navigate and contextual to
   the booking", in the same family as "You're going to Ballyhass!" (bh-yg-*),
   which it reuses for the opening, the marks and the people list. One page,
   anchored sections and a strip of jump links instead of tabs; the one next
   step sits under the opening. Navy on blue and pink, never white.
   ========================================================================== */

/* Grid items default to min-width: auto, so the jump links, when they scroll on a phone, widened the page. */
.bh-gp > * { min-width: 0; }
.bh-gp-nav { max-width: 100%; }
.bh-gp-hero { min-height: 0; background: var(--bh-ink); }
.bh-gp-hero::after { display: none; }
.bh-gp-hero .bh-yg-hero__title { font-size: clamp(32px, 9vw, 52px); }
.bh-gp-hero__group { display: block; margin: 14px 0 0; font-size: 15px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--bh-yellow); }
/* No photograph in a Group Portal or camp opening, so no room is kept for one on a phone (the
   pre-visit hero keeps 150px above its text for its photo). */
@media (max-width: 559px) { .bh-gp-hero .bh-yg-hero__body { padding-top: 22px; } }

.bh-gp-next { border-top: 4px solid var(--bh-pink); }
.bh-gp-next__label { font-size: clamp(20px, 5.5vw, 26px); font-weight: 800; margin: 0 0 6px; }
.bh-gp-next__due { margin: 0 0 16px; font-weight: 600; color: var(--bh-ink-70); }
.bh-gp-next__due.is-late { color: var(--bh-danger); }

/* The jump links (Group Portal and Your camp). Every one reachable at every width (Eoghan,
   3 November 2026, comment 11931884, point 1): the strip scrolled sideways with its scrollbar
   hidden, so on a desktop the links past the column's edge could not be reached at all, and
   the list items shrank, so "Your day" broke onto two lines inside its button. Now the links
   keep their width and wrap onto a second line. Only a phone-sized touch screen keeps the
   swipe, where a swipe exists; a narrow window on a computer wraps. The link for the section
   in view carries aria-current="location" (public/js/jump-nav.js) and the selected look. */
.bh-gp-nav { display: flex; flex-wrap: wrap; gap: 8px; padding: 2px 0 6px; margin: 0; list-style: none; }
.bh-gp-nav li { flex: 0 0 auto; }
.bh-gp-nav a {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px; white-space: nowrap;
    border: 2px solid var(--bh-ink); border-radius: var(--bh-r-btn); color: var(--bh-ink);
    font-weight: 700; font-size: 14px; text-transform: uppercase; text-decoration: none; letter-spacing: .03em; background: #fff;
}
/* Hover and focus are a light wash, so the selected link (navy, yellow text) is never confused
   with the one the keyboard is on, which also carries the focus ring. */
.bh-gp-nav a:hover, .bh-gp-nav a:focus-visible { background: var(--bh-wash); color: var(--bh-ink); }
.bh-gp-nav a[aria-current] { background: var(--bh-ink); color: var(--bh-yellow); }
@media (max-width: 559px) and (pointer: coarse) {
    .bh-gp-nav {
        flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
        scroll-padding-inline: 8px; scrollbar-width: none;
    }
    .bh-gp-nav::-webkit-scrollbar { display: none; }
}

.bh-gp-section { scroll-margin-top: 16px; }

/* The itinerary: a day, then its moments in order. */
.bh-gp-day + .bh-gp-day { margin-top: 18px; }
.bh-gp-day__label { font-size: 15px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; margin: 0 0 8px; }
.bh-gp-timeline { list-style: none; margin: 0; padding: 0; border-left: 3px solid var(--bh-line); }
.bh-gp-timeline li { position: relative; display: grid; grid-template-columns: 56px 1fr; gap: 4px 12px; padding: 10px 0 10px 14px; }
.bh-gp-timeline li::before { content: ""; position: absolute; left: -8px; top: 16px; width: 13px; height: 13px; border-radius: 50%; background: var(--bh-ink); }
.bh-gp-timeline li.is-provisional::before { background: #fff; border: 3px dashed var(--bh-ink-45); width: 9px; height: 9px; }
.bh-gp-timeline li.is-requested::before { background: var(--bh-yellow); border: 2px solid var(--bh-ink); width: 9px; height: 9px; }
.bh-gp-timeline__time { font-weight: 800; font-variant-numeric: tabular-nums; }
.bh-gp-timeline__title { font-weight: 700; }
.bh-gp-timeline__detail { grid-column: 2; margin: 0; font-size: 14.5px; color: var(--bh-ink-70); }

.bh-gp-tag { display: inline-block; margin-left: 6px; padding: 1px 7px; font-size: 11.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; border-radius: var(--bh-r-highlight); vertical-align: 2px; }
.bh-gp-tag--confirmed { background: var(--bh-ink); color: var(--bh-yellow); }
.bh-gp-tag--provisional { background: var(--bh-wash); color: var(--bh-ink); border: 1px dashed var(--bh-ink-45); }
.bh-gp-tag--requested { background: var(--bh-yellow); color: var(--bh-ink); }
/* Round p14-1022: quieter labels. What is settled carries none; what needs attention says so in small
   plain words, not a block (Eoghan, comment 11928402 point 4). Navy on every fill, never white. */
.bh-gp-tag { padding: 0; font-size: 12.5px; font-weight: 600; letter-spacing: 0; text-transform: none; background: none; border: 0; color: var(--bh-ink-70); }
.bh-gp-tag::before { content: "\00b7  "; }
.bh-gp-tag--provisional, .bh-gp-tag--awaiting { background: none; border: 0; color: var(--bh-ink-70); }
.bh-gp-tag--requested { background: none; color: var(--bh-ink); font-weight: 700; }
.bh-gp-timeline li.is-awaiting::before { background: #fff; border: 2px dotted var(--bh-ink-45); width: 9px; height: 9px; }
.bh-gp-timeline li.is-awaiting .bh-gp-timeline__title { font-weight: 600; color: var(--bh-ink-70); }
.bh-gp-day__title { display: block; margin-top: 2px; font-size: 18px; font-weight: 800; text-transform: none; letter-spacing: 0; }
/* What is included on a day trip. */
.bh-gp-part { margin: 0 0 18px; padding: 14px; background: var(--bh-wash); border-radius: var(--bh-r-card); }
.bh-gp-part__list { list-style: none; margin: 0 0 10px; padding: 0; display: grid; gap: 6px; }
.bh-gp-part__list li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 2px 12px; padding: 8px 0; border-top: 1px solid var(--bh-line); }
.bh-gp-part__list li:first-child { border-top: 0; }
.bh-gp-part__name { font-weight: 700; }
.bh-gp-part__scope { color: var(--bh-ink-70); font-size: 14.5px; }
.bh-gp-part__note { margin: 8px 0 0; font-size: 14.5px; color: var(--bh-ink-70); }
.bh-gp-part__note strong { display: block; color: var(--bh-ink); }

/* Preparation: a checklist that gets shorter as things are done. */
.bh-gp-checks { list-style: none; margin: 0; padding: 0; }
.bh-gp-checks li { display: grid; grid-template-columns: 28px 1fr; gap: 2px 12px; padding: 14px 0; border-top: 1px solid var(--bh-line); }
.bh-gp-checks li:first-child { border-top: 0; }
.bh-gp-checks__label { font-weight: 700; }
.bh-gp-checks__detail { grid-column: 2; margin: 0; font-size: 14.5px; color: var(--bh-ink-70); }
.bh-gp-checks__detail a { font-weight: 700; }
.bh-gp-meter { grid-column: 2; height: 8px; background: var(--bh-line); border-radius: 4px; overflow: hidden; margin-top: 6px; }
.bh-gp-meter span { display: block; height: 100%; background: var(--bh-ink); }

/* Sharing: the one link, ready to copy. */
.bh-gp-share { display: grid; gap: 10px; }
.bh-gp-share__row { display: flex; gap: 8px; }
.bh-gp-share__row .bh-input { flex: 1 1 auto; min-width: 0; font-size: 14px; }
.bh-gp-share__ways { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; }

.bh-gp-money { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.bh-gp-money .bh-stat { padding: 12px; }
@media (max-width: 420px) { .bh-gp-money { grid-template-columns: 1fr; } }

.bh-gp-names { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 8px 0 0; padding: 0; }
.bh-gp-names li { background: var(--bh-wash); border-radius: var(--bh-r-field); padding: 4px 9px; font-size: 14px; }

.bh-gp details > summary { cursor: pointer; font-weight: 700; min-height: 44px; display: flex; align-items: center; }

@media (prefers-reduced-motion: reduce) { .bh-gp-nav a { transition: none; } }

/* Status and the one next step, first on a booking page (Portal testing 21 Oct 2026,
   comment 11928675, point 5). Sticky on a phone so it stays in view while the page scrolls.
   Navy text on a white panel with a blue rule; the button is pink with navy text as elsewhere. */
.bh-next {
    background: #fff;
    border: 1px solid var(--bh-line);
    border-left: 4px solid var(--bh-blue);
    border-radius: 12px;
    padding: 14px 18px;
    margin-bottom: 20px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
}
.bh-next__status { display: flex; flex-wrap: wrap; gap: 6px; }
.bh-next__text { margin: 0; flex: 1 1 260px; font-weight: 600; color: var(--bh-ink); }
@media (max-width: 720px) {
    .bh-next { position: sticky; top: 0; z-index: 20; box-shadow: 0 2px 8px rgba(33, 39, 47, 0.12); }
    .bh-next .bh-btn { width: 100%; }
}
/* Not on a short screen (signed-in pass, 4 November 2026, finding B12). At 400% zoom a laptop is a
   320 by 256 window, and the panel, 185px tall there, covered 72% of it: 31 of a booking page's 79
   keyboard stops went entirely under it (WCAG 2.4.11), and the page could be read only through a
   70px strip (1.4.10). A phone held upright keeps it; a phone on its side is short too. */
@media (max-width: 720px) and (max-height: 559.98px) {
    .bh-next { position: static; box-shadow: none; }
}

/* ── Waiver journey redesign (round waiver-redesign-1022; Eoghan, comment 11928703) ──────── */

/* The welcome: navy block, yellow title, white text (contrast 15:1 and 16:1), a few lines only. */
.bh-welcome { background: var(--bh-ink); color: #fff; border-radius: var(--bh-r-card); padding: clamp(20px, 5vw, 32px); margin: 0 0 20px; }
.bh-welcome__title { margin: 0 0 8px; font-size: clamp(26px, 7vw, 36px); line-height: 1.1; font-weight: 800; color: var(--bh-yellow); }
.bh-welcome__lede { margin: 0 0 14px; font-size: 17px; line-height: 1.5; color: #fff; max-width: 36ch; }
.bh-welcome__facts { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: 15px; font-weight: 600; color: #fff; }

/* The approved terms, set out to be read: no inner scroll box, readable measure and type. A long
   text is folded by script on a phone, with one button to read all of it. */
/* Shown whole on every screen (comment 11931588 point 4): no fold, no mask, no inner scroll. A light
   panel that says so, so a phone's dark mode does not repaint it, with its colours set explicitly. */
.bh-terms { background: var(--bh-wash); color: var(--bh-ink); color-scheme: light; border: 1px solid var(--bh-line); border-radius: var(--bh-r-card); padding: clamp(16px, 4vw, 28px); margin: 0 0 16px; }
.bh-terms__title { margin: 0 0 4px; font-size: 20px; line-height: 1.25; font-weight: 700; color: var(--bh-ink); }
.bh-terms__intro { margin: 0 0 14px; font-size: 15px; color: var(--bh-ink-70); }
.bh-terms__body { max-width: 68ch; font-size: 16px; line-height: 1.7; color: var(--bh-ink); overflow-wrap: anywhere; }
.bh-terms__body h1, .bh-terms__body h2, .bh-terms__body h3, .bh-terms__body h4 { font-size: 17px; line-height: 1.35; margin: 22px 0 6px; font-weight: 700; color: var(--bh-ink); }
.bh-terms__body > :first-child { margin-top: 0; }
.bh-terms__body p { margin: 0 0 12px; }
.bh-terms__body ul, .bh-terms__body ol { margin: 0 0 12px; padding-left: 22px; }
.bh-terms__body li { margin: 0 0 6px; }
.bh-terms__body table { width: 100%; border-collapse: collapse; display: block; overflow-x: auto; }

/* The agreement, directly under the terms and above the button. */
.bh-agree { background: #fff; border: 2px solid var(--bh-ink); border-radius: var(--bh-r-card); padding: 16px; margin: 0 0 16px; }
.bh-agree .bh-yg-agree { margin: 0 0 12px; }
.bh-agree .bh-yg-agree:last-of-type { margin-bottom: 0; }

/* ── Camper ages (Eoghan, 25 October 2026, comments 11929486 and 11929491) ────────────── */

/* One age per camper on a camp whose ages Ballyhass approved, under the ticket steppers. The
   legend is a subtitle: bold and all caps (brand guide p10). min-width: 0 for the same reason
   as .bh-quick__block: a fieldset otherwise refuses to shrink on a phone. */
.bh-campages { border: 1px solid var(--bh-line); border-radius: var(--bh-r-card); background: var(--bh-wash); padding: 16px; margin: 16px 0 0; min-width: 0; }
.bh-campages__title { float: left; width: 100%; padding: 0; margin: 0 0 4px; font-size: .8rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--bh-ink); }
/* A legend sits on the fieldset's border unless floated; floated, it is the first line inside the box. */
.bh-campages__title + * { clear: both; }
.bh-campages .bh-panel__hint { margin: 0 0 12px; }
.bh-campages__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.bh-campages__field { display: grid; gap: 2px; }
.bh-campages__who { font-weight: 600; font-size: 14.5px; }
.bh-campages__ticket { font-size: 13px; font-weight: 500; color: var(--bh-ink-70); margin-bottom: 4px; }
.bh-campages__input { height: 52px; background: var(--bh-white); border-color: var(--bh-line); }
.bh-campages__pending { margin-top: 16px; font-weight: 600; color: var(--bh-ink); }
.bh-campages__pending a { color: var(--bh-blue-text); }

/* The waiver form's agreement lines (authority, and the terms on the older form). A class, never an
   inline display, so the hidden attribute can hide one (comment 11929142). */
.bh-agree-line { display: flex; gap: 12px; align-items: flex-start; cursor: pointer; font-size: 14.5px; }
.bh-agree-line input { width: 20px; height: 20px; margin-top: 2px; flex: 0 0 auto; }

/* ── The day on the Wakepark cable (Phase 2, task 27694625) ──────────────────────────── */

/* One row per hour, a cell per 15-minute block, so a phone at 360px still shows a whole hour
   on one line. Navy text throughout: navy on Ballyhass Blue is 6.23:1, and white on blue
   (2.42:1) is never used. The state is said in words under each time, never by colour alone. */
.bh-cable { margin-bottom: 8px; }
.bh-cable__key { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 0 0 14px; font-size: 12.5px; color: var(--bh-ink-70); }
.bh-cable__key > span { display: inline-flex; align-items: center; gap: 6px; }
.bh-cable__swatch { display: inline-block; width: 14px; height: 14px; border-radius: 3px; border: 1px solid var(--bh-line); background: var(--bh-white); }
.bh-cable__swatch.is-start  { border: 2px solid var(--bh-ink); }
.bh-cable__swatch.is-chosen { background: var(--bh-blue); border-color: var(--bh-ink); }
.bh-cable__swatch.is-held   { background: var(--bh-line); }
.bh-cable__swatch.is-closed { background: var(--bh-wash); border-style: dashed; }
.bh-cable__swatch.is-members { background: var(--bh-wash); border: 2px solid var(--bh-pink); }
.bh-cable__day { display: grid; gap: 8px; }
.bh-cable__hour { display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 8px; align-items: stretch; }
.bh-cable__label { font-size: 12.5px; font-weight: 700; color: var(--bh-ink-70); padding-top: 10px; }
.bh-cable__cells { display: grid; grid-template-columns: repeat(var(--bh-cable-cols, 4), minmax(0, 1fr)); gap: 6px; }
.bh-cable__slot { min-width: 0; }
.bh-cable__cell {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    width: 100%; min-height: 52px; padding: 6px 2px;
    border: 1px solid var(--bh-line); border-radius: var(--bh-r-field);
    background: var(--bh-white); color: var(--bh-ink-70);
    font: inherit; text-align: center;
}
.bh-cable__time { font-size: 13.5px; font-weight: 600; line-height: 1.2; }
.bh-cable__note { font-size: 11px; font-weight: 500; line-height: 1.2; min-height: 1.2em; }
.bh-cable__cell.is-held   { background: var(--bh-line); }
.bh-cable__cell.is-closed { background: var(--bh-wash); border-style: dashed; }
/* Members' time: navy text on the wash, the pink only as a border (white on pink fails AA). */
.bh-cable__cell.is-members { background: var(--bh-wash); border: 2px solid var(--bh-pink); color: var(--bh-ink); }
.bh-cable__cell.is-start  { border: 2px solid var(--bh-ink); color: var(--bh-ink); cursor: pointer; }
.bh-cable__cell.is-start .bh-cable__time { font-weight: 700; }
.bh-cable__cell.is-start:hover { background: var(--bh-field-hi); }
.bh-cable__cell.is-chosen { background: var(--bh-blue); border-color: var(--bh-ink); color: var(--bh-ink); }
.bh-cable__cell.is-chosen:hover { background: var(--bh-blue-dark); }
.bh-cable__chosen { margin: 14px 0 0; font-weight: 700; color: var(--bh-ink); }

/* A Wakepark member's included minutes for the week, above the day. */
.bh-allowance { margin: 0 0 14px; padding: 12px 14px; border: 1px solid var(--bh-line); border-left: 4px solid var(--bh-navy); border-radius: var(--bh-r-card); background: var(--bh-wash); font-size: 14px; color: var(--bh-ink); }
.bh-allowance__title { display: block; margin-bottom: 2px; font-weight: 700; }
.bh-cable .bh-empty { margin-top: 14px; }

/* Each learner's own turn on a lesson: on step 1 and on the confirmation. */
.bh-turns { margin: 16px 0 0; padding: 14px 16px; border: 1px solid var(--bh-line); border-radius: var(--bh-r-card); background: var(--bh-wash); }
.bh-turns__title { margin: 0 0 6px; font-size: .8rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--bh-ink); }
.bh-turns__lesson { margin: 8px 0 2px; font-weight: 600; font-size: 14.5px; }
.bh-turns__list { margin: 0; padding-left: 18px; font-weight: 600; line-height: 1.8; }
.bh-turns__note { margin: 6px 0 0; font-size: 13px; color: var(--bh-ink-70); }

/* Bunkhouse stay notices: bring your own bedding, and a school's first-day lunch (Eoghan, 29 October
   2026, comment 11930418). The brand highlight: a navy block with yellow text and square corners.
   White body text on navy is 14.7:1 and yellow on navy 13.6:1, so both pass WCAG AA. */
.bh-stay-notices { display: grid; gap: 12px; margin: 0 0 20px; }
.bh-stay-notice { background: var(--bh-ink); color: var(--bh-white); border-radius: 0; border-left: 8px solid var(--bh-yellow); padding: 16px 20px; }
.bh-stay-notice__title { margin: 0 0 6px; font-size: 1rem; line-height: 1.3; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; color: var(--bh-yellow); }
.bh-stay-notice__text { margin: 0; font-size: 1rem; line-height: 1.5; font-weight: 500; color: var(--bh-white); }

/* ── Gift vouchers (FSD REQ-F111) ──────────────────────────────────────────
   The radio sits inside the .bh-choice card: hidden from sight, still the
   control a keyboard and a screen reader use, and the card shows it chosen. */
.bh-gift__choice { position: relative; }
.bh-gift__radio {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    margin: 0;
}
.bh-gift__choice:has(.bh-gift__radio:checked) { background: var(--bh-ink); color: var(--bh-yellow); border-color: var(--bh-ink); }
.bh-gift__choice:has(.bh-gift__radio:checked) .bh-choice__meta { color: var(--bh-white); }
.bh-gift__note { min-height: 104px; resize: vertical; line-height: 1.5; }

/* ── Extras at step 2 (REQ-F011) ───────────────────────────────────────────
   Each extra is a plain card: name, price and how it is counted, the choice
   and the number, then Add. Once added it carries a navy edge and says so in
   words, never by colour alone. Navy on white and on the wash both pass AA. */
.bh-addons { margin: 28px 0 24px; padding-top: 24px; border-top: 1px solid var(--bh-line); }
.bh-addons__for { margin: 18px 0 10px; font-size: 14px; font-weight: 700; text-transform: uppercase; letter-spacing: .02em; color: var(--bh-ink); }
.bh-addon { margin: 0 0 14px; padding: 16px 18px; border: 1px solid var(--bh-line); border-radius: var(--bh-r-card); background: var(--bh-wash); min-width: 0; }
.bh-addon--added { border-left: 6px solid var(--bh-ink); background: var(--bh-white); }
/* Floated so the name sits inside the card rather than on its border; the next line clears it. */
.bh-addon__name { float: left; width: 100%; padding: 0; margin: 0; font-weight: 700; font-size: 16px; color: var(--bh-ink); }
.bh-addon__name + * { clear: both; }
.bh-addon__price { margin: 4px 0 8px; font-weight: 700; color: var(--bh-ink); }
.bh-addon__desc { margin: 0 0 10px; font-weight: 500; color: var(--bh-ink-70); }
.bh-addon__details { margin: 8px 0 0; padding-left: 18px; font-size: 14px; font-weight: 500; color: var(--bh-ink-70); }
.bh-addon__added { margin: 6px 0 10px; font-weight: 700; color: var(--bh-ink); }
.bh-addon__acts { display: flex; flex-wrap: wrap; gap: 10px; }
/* Required or Included (comment 11923154, point 12): the brand's highlight, a navy block with
   yellow text and square corners, so it reads as a fact about the booking and not a button. */
.bh-addon__state { display: inline-block; margin: 0 0 10px; padding: 2px 8px; border-radius: 0; background: var(--bh-navy); color: var(--bh-yellow); font-weight: 700; font-size: 14px; }
/* Add to your visit on Booking Details (comment 11931884, point 2): what can be added, then one
   ADD EXTRAS button that opens the choices in place. The button is a details summary, so it
   works without a script and says whether it is open; the chevron turns when it is. */
.bh-addto__list { margin: 0 0 16px; padding-left: 20px; font-weight: 500; color: var(--bh-ink); }
.bh-addto__list li + li { margin-top: 4px; }
.bh-addto { margin: 0 0 20px; }
.bh-addto > summary { list-style: none; }
.bh-addto > summary::-webkit-details-marker { display: none; }
.bh-addto > summary::after {
    content: ""; width: 8px; height: 8px; margin: -4px 0 0 2px;
    border-right: 2.5px solid currentColor; border-bottom: 2.5px solid currentColor; transform: rotate(45deg);
}
.bh-addto[open] > summary::after { margin-top: 4px; transform: rotate(-135deg); }
.bh-addto__body { margin-top: 18px; }
.bh-addto__note { margin: 4px 0 12px; font-weight: 500; color: var(--bh-ink); }
.bh-summary__line--extra span:first-child { padding-left: 12px; border-left: 3px solid var(--bh-line); }
.bh-summary__edit { display: inline-block; margin: 2px 0 6px 15px; font-size: 14px; font-weight: 600; color: var(--bh-blue-text); text-decoration: underline; }

/* --------------------------------------------------- basket and Cart ---- */

/* The Cart utility route (Eoghan, 3 October 2026, comment 11924622) with the item count and
   total the legacy header showed (comment 11931168), filled in by js/cart-summary.js. The icon
   is decoration. */
.bh-header__cart { display: inline-flex; align-items: center; gap: 6px; }
.bh-header__cart-icon { flex: none; }
.bh-header__cart-count { font-weight: 700; }
.bh-header__cart-amount { font-weight: 600; }
.bh-header__cart[aria-current="page"] { background: rgba(255,255,255,.12); border-color: #fff; }

/* The controls must fit a 390px phone beside the logo. The greeting goes first, then the word
   "Cart" (hidden from sight only, so the link's text, which is its name, still starts with it). */
@media (max-width: 480px) {
    .bh-header__hi { display: none; }
    .bh-header__right { gap: 8px; }
    .bh-header__link { padding: 8px 12px; }
    .bh-header__cart-word {
        position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
        clip: rect(0 0 0 0); white-space: nowrap; border: 0;
    }
}

/* What the hold sweep released (checkout/partials/released.blade.php, App\Support\BasketMemory).
   The warning alert's own colours: #7A4300 on #FFF6E5 is 7.44:1, navy on it 14.02:1. */
.bh-released__title { margin: 0 0 6px; font-size: 15px; font-weight: 700; text-transform: uppercase; color: inherit; }
.bh-released__lede { margin: 0 0 12px; }
.bh-released__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.bh-released__item { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding-top: 12px; border-top: 1px solid rgba(122, 67, 0, .25); }
.bh-released__name { margin: 0; color: var(--bh-ink); }
.bh-released__meta { display: block; font-size: 14px; font-weight: 500; }
.bh-released__actions { display: flex; flex-wrap: wrap; gap: 8px; }
.bh-released__actions form { margin: 0; }

/* The basket page (checkout/basket.blade.php). */
.bh-basket__list { list-style: none; margin: 0 0 20px; padding: 0; }
.bh-basket__item { display: grid; gap: 2px; padding: 12px 0; border-bottom: 1px solid var(--bh-line); }
.bh-basket__item:first-child { padding-top: 0; }
.bh-basket__meta { font-size: 14px; font-weight: 500; color: var(--bh-ink-70); }
.bh-basket__empty { margin: 0 0 20px; }
.bh-basket__actions { display: grid; gap: 12px; }
.bh-basket__actions form { margin: 0; }

/* The confirmation page's groups: each activity, the extras, the pass, gift vouchers and payment,
   told apart as the confirmation email tells them apart (30 October 2026, I20261030A1004). */
.bh-confirm-group { margin-top: 22px; padding-top: 14px; border-top: 2px solid var(--bh-ink); }
.bh-confirm-group__title { margin: 0 0 4px; font-size: .8rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--bh-ink); }

/* A gift voucher's personal message in the order summary, in the buyer's own words and case
   (comment 11931188, point 1). The venue line beside it is in capitals. */
.bh-summary__message { display: block; margin-top: 4px; font-size: 13px; font-weight: 500; color: var(--bh-ink-70); overflow-wrap: anywhere; }

/* Your bookings in the Group Portal (REQ-F023A): the organiser's other authorised bookings. A
   white panel with a navy rule and navy text, so nothing sits white on blue. */
.bh-gp-switch { background: #fff; border: 2px solid var(--bh-ink); border-radius: var(--bh-r-card); padding: 16px 18px; margin: 0 0 18px; color: var(--bh-ink); }
.bh-gp-switch__title { font-size: 15px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; margin: 0 0 4px; }
.bh-gp-switch__hint { margin: 0 0 12px; font-size: 14px; font-weight: 500; color: var(--bh-ink-70); }
.bh-gp-switch__row { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
.bh-gp-switch__field { flex: 1 1 260px; min-width: 0; margin: 0; }
.bh-gp-switch__field .bh-select { width: 100%; }
.bh-gp-switch__go { flex: 0 0 auto; }

/* A member of staff's read-only view of the Group Portal (WP-10 follow-up): the brand's highlight,
   a navy block with yellow text and square corners. */
.bh-gp-staffview { display: block; background: var(--bh-ink); color: var(--bh-yellow); border-radius: var(--bh-r-highlight); padding: 14px 18px; margin: 0 0 18px; }
.bh-gp-staffview__title { display: block; font-size: 15px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; }
.bh-gp-staffview__detail { display: block; margin-top: 4px; font-size: 14px; font-weight: 500; color: #fff; }
/* The fieldset that switches off a staff view's forms carries no box of its own: display: contents
   keeps the page's grid and spacing exactly as the organiser sees them. */
.bh-gp-readonly { display: contents; border: 0; margin: 0; padding: 0; min-width: 0; }

/* Your family (FSD ADD-F02): the people on the account, and choosing one of them on a waiver or a
   camper's form. Navy text on white or the wash throughout, so nothing sits white on blue. */
.bh-family__waiver { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: center; margin: 0 0 6px; font-size: 14.5px; font-weight: 500; }
.bh-family__bookings { margin: 10px 0 0; }
.bh-family__bookings .bh-list__item { padding-left: 0; padding-right: 0; }
.bh-family__acts { display: flex; flex-wrap: wrap; gap: 10px 24px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--bh-line); }
.bh-family__act { flex: 1 1 260px; min-width: 0; }
.bh-family__act > summary { cursor: pointer; font-size: 14px; font-weight: 700; color: var(--bh-ink); text-decoration: underline; text-underline-offset: 3px; }
.bh-family__act[open] > summary { margin-bottom: 12px; }
.bh-family__act form { margin: 0; }
.bh-family__act .bh-btn { margin-top: 4px; }
.bh-family-pick { background: var(--bh-wash); border: 1px solid var(--bh-line); border-radius: var(--bh-r-card); padding: 14px 16px; margin: 0 0 16px; }
.bh-family-pick .bh-label { margin-bottom: 6px; }
.bh-family-pick .bh-hint { display: block; margin-top: 8px; }

/* Who can help with your family (FSD ADD-F02): the adults trusted with a person, what each may do,
   and the invitation they answer. Lists of permissions are plain ticks, never colour alone. */
.bh-access__person { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--bh-line); }
.bh-access__label { margin: 8px 0 4px; font-size: 14px; font-weight: 700; }
.bh-access__list { margin: 0 0 10px; padding-left: 20px; font-size: 14.5px; font-weight: 500; }
.bh-access__list li { margin: 2px 0; }
.bh-access__list--off { color: var(--bh-ink); opacity: .85; }
.bh-access__not { margin: 10px 0 2px; font-size: 14px; font-weight: 700; }
.bh-access__links { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; margin-top: 8px; }
.bh-access__manage { font-size: 14px; font-weight: 700; color: var(--bh-ink); text-decoration: underline; text-underline-offset: 3px; }
.bh-access__checks { border: 0; margin: 0 0 14px; padding: 0; min-width: 0; }
.bh-access__checks .bh-agree-line { margin: 0 0 8px; }
.bh-access__membership + .bh-access__membership { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--bh-line); }
.bh-access__pay { margin-top: 14px; }
@media (max-width: 560px) {
    .bh-access__links .bh-btn { width: 100%; justify-content: center; }
}

/* ── The visit's programme in "What's ahead", and the emergency contact choice (1 November 2026) ──
   Eoghan, comment 11931269 points 1 and 3. A day per block, a row per activity: the time in a fixed
   column so the eye runs down the times, the activity and its length, and "To be confirmed" in
   words, never in colour alone. Navy on white and on the wash throughout. */
.bh-yg-plan { margin: 0 0 18px; display: grid; gap: 16px; }
.bh-yg-plan__note { margin: 0; background: var(--bh-wash); border-left: 4px solid var(--bh-pink); padding: 12px 14px; font-size: 15px; }
.bh-yg-plan__date { font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; margin: 0 0 6px; }
.bh-yg-plan__date span { display: block; text-transform: none; letter-spacing: 0; font-weight: 600; color: var(--bh-ink-70); margin-top: 2px; }
.bh-yg-plan__list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--bh-line); }
.bh-yg-plan__item { display: grid; grid-template-columns: 4.6em minmax(0, 1fr); gap: 4px 12px; padding: 11px 0; border-bottom: 1px solid var(--bh-line); align-items: baseline; }
.bh-yg-plan__time { font-weight: 700; font-variant-numeric: tabular-nums; }
.bh-yg-plan__what b { display: block; font-weight: 700; }
.bh-yg-plan__len, .bh-yg-plan__detail { display: block; font-size: 14px; color: var(--bh-ink-70); margin-top: 2px; }
.bh-yg-plan__state { grid-column: 2; justify-self: start; font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; border: 1px solid var(--bh-ink-45); border-radius: var(--bh-r-field); padding: 2px 8px; }
@media (min-width: 640px) {
    .bh-yg-plan__item { grid-template-columns: 5.2em minmax(0, 1fr) auto; }
    .bh-yg-plan__state { grid-column: 3; }
}

.bh-ec__said { margin: 0 0 6px; }
.bh-ec__summary { cursor: pointer; color: var(--bh-blue-text); font-weight: 600; margin: 0 0 10px; }
.bh-ec__change[open] > .bh-ec__summary { margin-bottom: 14px; }

/* ── Waiver in the Quick Checkout style (Eoghan, 2 November 2026, comment 11931572) ──────────
   The medical declaration is "one of the few questions that genuinely needs prominence": a
   washed block with a navy edge, square like a highlight, its Yes and No the large .bh-yg-choice
   controls. A short panel for a one-line offer (use an existing waiver), and a large primary
   action for the waiver's start and finish. Navy on the wash passes AA. */
.bh-declare { background: var(--bh-wash); border-left: 6px solid var(--bh-ink); border-radius: 0; padding: 16px 16px 12px; }
.bh-declare .bh-yg-q { font-size: 18px; line-height: 1.35; }
.bh-declare .bh-yg-choice { background: #fff; min-height: 60px; font-size: 17px; }
.bh-panel.bh-panel--tight { padding: 16px 20px; }
.bh-btn.bh-btn--xl { min-height: 60px; font-size: 17px; padding-inline: 24px; }
/* The next person's form (comment 11931588 point 2): the signer and the visit already given, in one line. */
.bh-carried > .bh-carried__summary { list-style: none; cursor: pointer; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; }
.bh-carried > .bh-carried__summary::-webkit-details-marker { display: none; }
.bh-carried__line { flex: 1 1 14em; min-width: 0; overflow-wrap: anywhere; font-weight: 600; color: var(--bh-ink); }
.bh-carried__change { color: var(--bh-blue-text); font-weight: 700; text-decoration: underline; }
.bh-carried[open] > .bh-carried__summary { margin-bottom: 14px; }
.bh-carried[open] .bh-carried__change { display: none; }
.bh-reference { display: inline-block; padding: 8px 14px; background: var(--bh-ink); color: var(--bh-yellow); border-radius: 0; letter-spacing: .08em; font-size: clamp(24px, 6vw, 32px); font-weight: 700; }

/* ── What a booking includes (Eoghan, 3 November 2026, comment 11931951, point 1) ──────────────
   A short, plain line near the booking action, in Ballyhass's words from the API (inclusionNote):
   what a sauna booking gives access to. Navy body text, medium weight, with a thin blue rule to
   mark it as part of the booking. Not a warning: no alert colour, no icon, no box. The rule is
   decoration; the text alone carries the meaning. */
.bh-inclusion { margin: 0; padding: 2px 0 2px 12px; border-left: 3px solid var(--bh-blue); color: var(--bh-ink); font-size: 14.5px; font-weight: 500; line-height: 1.45; }
.bh-quick__form > .bh-inclusion { margin: 4px 0 18px; }
.bh-panel > .bh-inclusion, .bh-confirm-group > .bh-inclusion { margin: 14px 0 6px; }
.bh-inclusion.bh-inclusion--summary { margin: 6px 0 10px; font-size: 13px; }
/* An activity's age and safety requirements before purchase (round 1104b, comment 11932114 point 1). */
.bh-activity-ages { margin: 14px 0 4px; }
.bh-activity-ages p { margin: 0; }
.bh-activity-ages p + p { margin-top: 4px; }

/* The date calendar at 320px, which is 400% zoom on a laptop (WCAG 1.4.10; accessibility
   assessment, 3 November 2026): the panel's padding and the gaps give a little back, so each day
   stays a 34px target, above the 24px WCAG 2.5.8 asks. */
@media (max-width: 359.98px) {
    .bh-cal { padding: 8px; }
    .bh-cal__dow, .bh-cal__grid { gap: 3px; }
    .bh-cal__day { min-height: 34px; }
}

/* Long addresses and references wrap (WCAG 1.4.10; found on the confirmation page at 390px,
   3 November 2026): an email address, a booking reference or a link printed in a narrow panel
   had nowhere to break and ran past the panel's edge. Any word too long for its line breaks now,
   on every page. Where such a value sits in a row beside its label (a flex row: the confirmation's
   facts, the summary's lines, the account's lists), it may also shrink below its longest word,
   so it wraps rather than pushing the row past the panel. A label keeps its words whole. */
body { overflow-wrap: break-word; }
dd,
.bh-summary__line > span:first-child,
.bh-kv__row > span:first-child,
.bh-list__main,
.bh-list__name,
.bh-list__meta,
.bh-table__ref,
.bh-reference,
.bh-panel__hint,
.bh-hint,
a[href^="mailto:"] {
    min-width: 0;
    overflow-wrap: anywhere;
}

/* Text spacing (WCAG 1.4.12; accessibility assessment, 3 November 2026). While the visitor's own
   letter, word or line spacing is in force (public/js/text-spacing.js puts bh-user-spacing on
   <html>), no text is cut to a number of lines: an account list's names show in full rather
   than lose the words the wider spacing pushed past the second line. */
.bh-user-spacing * {
    -webkit-line-clamp: none !important;
    line-clamp: none !important;
}

/* ------------------------------------------------ sign in before you pay -- */

/* Round 1104c (comment 11932411, point 2): the sign-in prompt before a membership is paid for. White panel,
   Navy rule, the title in the brand's highlight (Navy block, Yellow text: 11.9:1, square corners), body in
   Navy (15.9:1 on white) and the Navy primary button. Nothing here relies on colour alone. */
.bh-signin-prompt {
    background: #fff;
    border: 3px solid var(--bh-navy);
    border-radius: var(--bh-r-card);
    padding: clamp(16px, 2.5vw, 24px);
    margin-bottom: 16px;
}
.bh-signin-prompt__title {
    display: inline-block;
    margin: 0 0 10px;
    padding: 6px 10px;
    background: var(--bh-navy);
    color: var(--bh-yellow);
    border-radius: var(--bh-r-highlight);
    font-size: clamp(15px, 2vw, 18px);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .02em;
    line-height: 1.35;
}
.bh-signin-prompt__text { margin: 0 0 14px; color: var(--bh-navy); font-size: 15px; font-weight: 500; }
.bh-signin-prompt__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; }
.bh-signin-prompt__or { color: var(--bh-navy); font-size: 14px; font-weight: 500; }
