﻿/* =====================================================================
   BBCRM form standard — ASPxFormLayout restyle (draft, FormDemo.aspx)
   Sections come from dx:LayoutGroup; this sheet restyles the DX-rendered
   group boxes, captions, and editors. Theme-ready via CSS variables.
   [class*=] selectors match both _Office365 and _Office365Dark suffixes.
   ===================================================================== */

:root {
    --form-surface: #ffffff;
    --form-border: #dde4ee;
    --form-text: #28303c;
    --form-muted: #6b7686;
    --form-strong: #1b2a4a;
    --form-accent: #0a6486;
    --form-accent-soft: #e3eff5;
    /* Neutral recessed panel for asides that are NOT part of the required flow.
       Deliberately gray, not accent-tinted — a tint would read as emphasis. */
    --form-inset: #f3f6fa;
    --form-shadow: 0 1px 2px rgba(27, 42, 74, .05), 0 6px 18px rgba(27, 42, 74, .06);
    --form-input-bg: #ffffff;
    --form-input-border: #c8d3e2;
}

[data-bs-theme="dark"] {
    --form-surface: #1a2029;
    --form-border: #2a3240;
    --form-text: #c9d1db;
    --form-muted: #8b96a5;
    --form-strong: #dde4ee;
    --form-accent: #7cc5ea;
    --form-accent-soft: #152733;
    /* Dark: lift the panel instead of sinking it — going darker would collide with
       --form-input-bg and the fields inside would disappear into it. */
    --form-inset: #212936;
    --form-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 6px 18px rgba(0, 0, 0, .25);
    --form-input-bg: #141922;
    --form-input-border: #333d4d;
}

/* ---------- scope: any ASPxFormLayout inside .bb-form ---------- */

/* ---------- Section anatomy: label rail left, fields right ----------
   The outer .bb-form-canvas is the ONLY surface — a group must not repeat its
   border/radius/shadow or the same box nests inside itself.
   DX gives each group exactly three direct children (caption, heading line, field
   table), so the group becomes a 2-column grid: the section identifies itself in the
   left rail while the fields keep one uninterrupted column on the right.
   The trailing underscore keeps this off dxflGroupBoxCaption_*, which a bare
   [class*="dxflGroupBox"] also matches — that was giving the section LABEL its own
   border and shadow. */
.bb-form [class*="dxflGroupBox_"] {
    display: grid !important;
    grid-template-columns: 176px minmax(0, 1fr);
    column-gap: 40px;
    align-items: start;
    background: transparent;
    border: 0 !important;
    border-radius: 0;
    box-shadow: none;
    margin: 0 0 26px 0 !important;
    padding: 0 !important;
}

/* The rail label rides with its fields. On a tall section - a long memo, a big
   grid - the label would otherwise strand at the top with an empty rail beneath
   it, and the two columns stop reading as one thing. Offset clears the fixed top
   bar (127px) and the sticky page header (40px); a page with different chrome
   re-points --bb-sec-sticky-top. */
.bb-form [class*="dxflGroupBox_"] > [class*="dxflGroupBoxCaption"] {
    grid-column: 1;
    grid-row: 1;
}

/* OPT-IN, never global (Ivan, 2026-08-31: "that feature needs to be by page").
   Whether a caption should stick depends on the page's own chrome and section
   height - no global rule can know that, and a wrong guess rides the caption down
   the whole page. A page that wants it adds .bb-sticky-caption to its .bb-form
   and, if its header differs, re-points --bb-sec-sticky-top. */
.bb-form.bb-sticky-caption [class*="dxflGroupBox_"] > [class*="dxflGroupBoxCaption"] {
    position: sticky;
    top: var(--bb-sec-sticky-top, 183px);
}

/* The group's own heading rule is redundant once the label moved into the rail. */
.bb-form [class*="dxflGroupBox_"] > .dxflHLSys {
    display: none;
}

/* Fields are ONE column — one logical field per row (Baymard/NN-g: multi-column forms cause
   skipped and misread fields). Compound fields stay inline because they live inside a single
   LayoutItem. The measure is capped so a lone input doesn't stretch into an unreadable line;
   extra page width goes to the layout, never to line length. */
.bb-form [class*="dxflGroupBox_"] > [class*="dxflGroup_"] {
    grid-column: 2;
    grid-row: 1;
    max-width: 560px;
}

/* The measure cap protects LINE LENGTH; a choice widget isn't reading matter. At 560px the
   two member-type tiles squeeze to 250px and their descriptions wrap to three lines, which
   makes the form's first decision its most cramped element. */
.bb-form [class*="dxflGroupBox_"]:has(.bb-sec--mtype) > [class*="dxflGroup_"] {
    max-width: 760px;
}

/* Hairline + breathing room between sections (not before the first). */
.bb-form [class*="dxflGroupBox_"]:not(:has(.bb-sec--first)) {
    border-top: 1px solid var(--form-border) !important;
    padding-top: 30px !important;
}

/* The bb-sec--first section can be conditionally hidden (ucFamily hides the member-type
   layout on edit), which would leave a stray rule at the top of the canvas. Whichever
   FormLayout renders first opens the surface, so its first section never gets one. */
.bb-form-canvas > div:first-child [class*="dxflGroupBox_"]:first-of-type {
    border-top: 0 !important;
    padding-top: 0 !important;
}

/* ---------- .bb-reg — configurator variant (member registration) ----------
   Opts out of the entry-form section anatomy: caption sits ABOVE its section, not in a
   label rail, and there is no reading-measure cap — a wide selection grid and paired
   numeric fields need the width. Canvas, hairlines, caption type and field styling are
   the shared vocabulary. */
.bb-reg [class*="dxflGroupBox_"] {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 8px;
}

.bb-reg [class*="dxflGroupBox_"] > [class*="dxflGroupBoxCaption"],
.bb-reg [class*="dxflGroupBox_"] > [class*="dxflGroup_"] {
    grid-column: 1;
    grid-row: auto;
}

/* The grid and the paired numeric fields ARE the content — no reading-measure cap. */
.bb-reg [class*="dxflGroupBox_"] > [class*="dxflGroup_"] {
    max-width: none;
}


/* An aside, not a step: recessed neutral panel with no section caption and no hairline,
   so it can't be mistaken for a required part of the flow. */
.bb-reg .bb-opt {
    background: var(--form-inset);
    border: 1px solid var(--form-border);
    border-radius: 12px;
    padding: 16px 20px 12px !important;
    margin: 6px 0 26px;
}

/* Label lives inside the panel, clear of the top edge. */
.bb-reg .bb-opt-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--form-muted);
    padding-bottom: 6px;
}

/* No context rail (wizard/create): use the full content width. The section rail needs
   the room, and a capped/centred column left large dead margins on wide screens.
   Overrides the col-lg-8 the markup carries. Edit forms (with a .bb-rail) are unaffected. */
.bb-form-page .row:not(:has(.bb-rail)) > .bb-form {
    flex: 0 0 100%;
    max-width: 100%;
    width: 100%;
    margin-left: 0;
    margin-right: 0;
}

/* Forms not yet on the section-rail prototype (no .bb-sec) have no field-measure cap of their
   own, so full width stretches their DX FormLayout to the full canvas — on ucFamily that put
   "How did they find us?" and "Preferred language:" 620px apart. Cap the layout itself until
   those forms are converted; the prototype caps its own field column instead and is excluded,
   as is .bb-reg, which wants the full canvas for its selection grid. */
.bb-form:not(:has(.bb-sec)):not(.bb-reg) [class*="dxflFormLayout"] {
    max-width: 940px;
}

/* Stack the rail above the fields once there isn't room for two columns. */
@media (max-width: 992px) {
    .bb-form [class*="dxflGroupBox_"] {
        grid-template-columns: minmax(0, 1fr);
        row-gap: 4px;
    }

    .bb-form [class*="dxflGroupBox_"] > [class*="dxflGroupBoxCaption"],
    .bb-form [class*="dxflGroupBox_"] > [class*="dxflGroup_"] {
        grid-column: 1;
        grid-row: auto;
    }

    .bb-form [class*="dxflGroupBox_"] > [class*="dxflGroupBoxCaption"] {
        position: static;
    }
}

/* Spacing lives on the CAPTION, not the group: DX wraps every group in its own
   dxflGroupCell, so each is an only child and sibling selectors never match. */

.bb-form [class*="dxflGroupBoxCaption"] {
    display: inline-block;
    margin-bottom: 6px;
}

/* ---------- Form section heading (PROTOTYPE — see Member Setup) ----------
   Icon + small-caps label, sitting on the group's heading line. The icon is a MASK,
   not an <img>, so it inherits the label color and is correct in both themes —
   a baked-fill SVG would need the dark-mode brightness hack and still drift. */
/* No top margin: the group's own padding-top already separates the sections, and a margin
   here pushed the rail label 30px below the fields it labels. --first stays as the marker
   the hairline rule keys on. */
.bb-form .bb-sec {
    display: inline-flex !important;
    align-items: center;
    gap: 9px;
}

.bb-form .bb-sec::before {
    content: "";
    width: 17px;
    height: 17px;
    flex: 0 0 17px;
    background-color: currentColor;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    opacity: .95;
}

.bb-form .bb-sec--identity::before {
    -webkit-mask-image: url("/Images/Icons/fa-id-badge.svg");
    mask-image: url("/Images/Icons/fa-id-badge.svg");
}

.bb-form .bb-sec--membership::before {
    -webkit-mask-image: url("/Images/Icons/fa-clipboard-list.svg");
    mask-image: url("/Images/Icons/fa-clipboard-list.svg");
}

.bb-form .bb-sec--notes::before {
    -webkit-mask-image: url("/Images/Icons/fa-file-lines.svg");
    mask-image: url("/Images/Icons/fa-file-lines.svg");
}

.bb-form .bb-sec--attachment::before {
    -webkit-mask-image: url("/Images/Icons/fa-camera.svg");
    mask-image: url("/Images/Icons/fa-camera.svg");
}

/* A variant with no mask paints the 17px box as a solid block of currentColor,
   so every variant in use needs a rule here. */
.bb-form .bb-sec--preferences::before {
    -webkit-mask-image: url("/Images/Icons/fa-gear.svg");
    mask-image: url("/Images/Icons/fa-gear.svg");
}

.bb-form .bb-sec--mtype::before {
    -webkit-mask-image: url("/Images/Icons/fa-list-check.svg");
    mask-image: url("/Images/Icons/fa-list-check.svg");
}

.bb-form .bb-sec--referral::before {
    -webkit-mask-image: url("/Images/Icons/fa-bullhorn.svg");
    mask-image: url("/Images/Icons/fa-bullhorn.svg");
}

.bb-form .bb-sec--billing::before {
    -webkit-mask-image: url("/Images/Icons/fa-money-bill.svg");
    mask-image: url("/Images/Icons/fa-money-bill.svg");
}

/* Compound field on one row (First/Last, City/State/Zip). One logical field split into
   parts — NOT a second column. Wraps instead of overflowing on a narrow screen. */
.bb-inline-fields {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: flex-start;
}

.bb-inline-fields > * {
    flex: 1 1 140px;
    min-width: 0;
}

/* Toggles read as a list, not a paragraph — one per line with room to tap. */
.bb-toggle-stack {
    display: flex;
    flex-direction: column;
    gap: 10px;
    align-items: flex-start;
}

/* DX renders a checkbox as a two-cell <table> that stretches to its container, which
   pushed each label to the far right, half a screen from the switch it belongs to.
   Shrink-wrap it so the label sits beside its own toggle. */
.bb-toggle-stack > table,
.bb-toggle-stack > span > table {
    width: auto !important;
}

.bb-toggle-stack td.dxichCellSys {
    padding-right: 8px;
}

/* Billing rail. Stored cards and bank accounts are not fields you fill in — they are
   reference panels with actions — so they sit beside the form rather than lengthening
   the single-column field flow. Stacks under the form below 1200px. */
.bb-billing-rail .bb-sec--rail {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--field-label);
    margin-bottom: 14px;
}

/* In the rail the two payment panels stack — side by side they would be too narrow to
   read the toggle labels. Each box must size to its CONTENT: flex-basis works on the
   main axis, so the shared "flex: 1 1 300px" became a 300px minimum HEIGHT here and the
   dead space pushed the two document buttons below the fold. */
.bb-billing-rail .bb-paybox-group {
    flex-direction: column;
}

.bb-billing-rail .bb-paybox {
    flex: 0 0 auto;
}

/* Stored payment instrument. A quiet inset panel, not another card: the form already
   has exactly one surface and nesting cards is what made this page read as clutter. */
.bb-paybox-group {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 18px;
}

.bb-paybox {
    flex: 1 1 300px;
    min-width: 0;
    padding: 14px 16px;
    border: 1px solid var(--box-border-color);
    border-radius: 8px;
    background: rgba(127, 127, 127, 0.05);
}

.bb-paybox__title {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--field-label);
    margin-bottom: 10px;
}

/* The stored card / account number. Without this it inherits the body #333 and lands at
   about 1.3:1 on the dark panel — the one value on the panel you actually need to read. */
.bb-paybox .bb-field-value,
.bb-paybox .bb-field-value span {
    color: var(--text-color);
    font-weight: 600;
}

/* Breathing room between the stored card/account number and the toggles that act on it —
   set on the toggle stack rather than the field, whose box collapses around inline spans. */
.bb-paybox .bb-field {
    margin-bottom: 6px;
}

.bb-paybox .bb-toggle-stack {
    margin-top: 22px;
}

.bb-paybox__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 14px;
}

.bb-form .bb-sec--contact::before {
    -webkit-mask-image: url("/Images/Icons/fa-envelope.svg");
    mask-image: url("/Images/Icons/fa-envelope.svg");
}

.bb-form .bb-sec--authorizations::before {
    -webkit-mask-image: url("/Images/Icons/fa-circle-check.svg");
    mask-image: url("/Images/Icons/fa-circle-check.svg");
}

.bb-form .bb-sec--status::before {
    -webkit-mask-image: url("/Images/Icons/fa-user-check.svg");
    mask-image: url("/Images/Icons/fa-user-check.svg");
}

/* Group caption — Sora, spaced small caps, accent color */
.bb-form [class*="dxflGroupBoxCaption"],
.bb-form [class*="dxflHLGroupBoxCaption"] {
    font-family: Sora, "Hanken Grotesk", sans-serif;
    font-size: 12.5px !important;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--form-accent) !important;
    background: transparent;
}

/* Variant B — GroupBoxDecoration="HeadingLine": keep flat, tint the rule */
.bb-form [class*="dxflHLGroupBox"] {
    border: 0 !important;
    background: transparent;
}

/* Tighten vertical rhythm between fields (DX item wrapper defaults to 6px top/bottom). */
.bb-form [class*="dxflItem"] { padding-top: 2px !important; padding-bottom: 2px !important; }

/* Item captions (labels above fields) */
.bb-form [class*="dxflCaptionCell"],
.bb-form [class*="dxflCaptionCell"] span {
    font-family: "Hanken Grotesk", system-ui, sans-serif;
    font-size: 12px !important;
    font-weight: 600;
    letter-spacing: .03em;
    color: var(--form-muted) !important;
    padding-bottom: 4px;
}

/* DX stamps a per-group width inline on each caption cell, so one shared seam
   needs !important. Both cards carry this class, which is what aligns them. */
.bb-form .bb-caption-left [class*="dxflCaptionCell"] {
    width: 150px !important;
    min-width: 150px !important;
    padding: 0 12px 0 0;
    vertical-align: middle;
    white-space: nowrap;
}

/* Nested groups each add their own left indent, which puts every group on a
   different seam. Flatten them so one caption column serves the whole card. */
.bb-form .bb-caption-left [class*="dxflGroup_"],
.bb-form .bb-caption-left [class*="dxflGroupCell"] { padding-left: 0 !important; }
.bb-form .bb-caption-left .bb-opt { padding-left: 20px !important; }

.bb-form .bb-caption-left [class*="dxflCaptionCell"] span {
    padding-bottom: 0;
}

.bb-agreement { margin-bottom: 16px; }

/* DX editors — soften boxes, unify radius/border, focus ring */
.bb-form [class*="dxeTextBox"],
.bb-form [class*="dxeButtonEdit"],
.bb-form [class*="dxeMemo"] {
    background: var(--form-input-bg) !important;
    border: 1px solid var(--form-input-border) !important;
    border-radius: 8px !important;
    color: var(--form-text);
}

/* Invalid state.

   The themed-input rule above is `.bb-form [class*="dxeTextBox"]` — specificity 0,2,0 WITH
   !important — and theme.css's invalid rule is `.validation-error`, only 0,1,0. The themed rule
   therefore won, and a .bb-form field showed red TEXT on a plain white box: the fill and the
   border never appeared. Repeating the invalid class on the same compound selector takes this to
   0,3,0 so it wins back.

   DX stamps BOTH `validation-error` (our InvalidStyle) and `dxeInvalid_<Theme>` (its own), and a
   mask violation sets the DX one WITHOUT any ValidationSettings — so both are matched, otherwise
   an incomplete phone stays silently unstyled.

   Semantic tokens, so this follows light/dark with everything else. */
.bb-form [class*="dxeTextBox"].validation-error,
.bb-form [class*="dxeButtonEdit"].validation-error,
.bb-form [class*="dxeMemo"].validation-error,
.bb-form [class*="dxeTextBox"][class*="dxeInvalid"],
.bb-form [class*="dxeButtonEdit"][class*="dxeInvalid"],
.bb-form [class*="dxeMemo"][class*="dxeInvalid"] {
    background: var(--bb-danger-bg) !important;
    border-color: var(--bb-danger) !important;
}

/* The DX edit-area cell carries a theme grey by default — clear it so the
   editor root (set above) is the only background the user sees. */
.bb-form [class*="dxeEditArea"],
.bb-form [class*="dxeIInput"],
.bb-form td[class*="dxic"] {
    background: transparent !important;
}

.bb-form [class*="dxeTextBox"] input,
.bb-form [class*="dxeButtonEdit"] input,
.bb-form [class*="dxeMemo"] textarea {
    background: transparent !important;
    color: var(--form-text) !important;
    font-family: "Hanken Grotesk", system-ui, sans-serif;
    font-size: 14.5px;
    padding: 4px 10px;
}

/* Right-aligned edit inputs (money / number spin-edits): DX sizes the edit-area
   input without accounting for the 10px theme padding above, so the input runs a
   few px past its bordered box and the value clips at the rounded right edge.
   Constrain ONLY right-aligned inputs to the box — left-aligned ones merely hide
   trailing empty space (no clip), and constraining combos would truncate their
   displayed text. */
/* DX renders HorizontalAlign="Right" as style="text-align:Right;" - capital R, no space -
   and attribute-selector values are CASE-SENSITIVE, so the original lowercase selector never
   matched. The `i` flag plus both spacings covers every form DX emits.
   Scope stays on right-aligned edit areas only: constraining all of them steals the combo's
   padding and truncates its display text. */
.bb-form [class*="dxeEditArea"][style*="text-align:right" i],
.bb-form [class*="dxeEditArea"][style*="text-align: right" i] {
    width: 100% !important;
    box-sizing: border-box !important;
}

/* Placeholder (DX NullText) must read as a hint, not typed text. More specific
   than the input color rule above so it wins when the editor is empty. */
.bb-form [class*="dxeNullText"] input,
.bb-form [class*="dxeNullText"] textarea {
    color: var(--form-muted) !important;
    opacity: 0.65 !important;
    font-style: italic;
}

/* Two-column field rhythm: every paired row shares one left-column width and a
   flexible right column, so left controls (City, Phone 1, Email, Facebook) end
   on the same line and right controls (State/Zip, Phone 2, callout, X) start on
   the same line. No zigzag. */
.bb-form .bb-fld-l { flex: 0 0 320px; max-width: 320px; }
.bb-form .bb-fld-r { flex: 1 1 260px; max-width: 360px; }
.bb-form .bb-fld-l [class*="dxeTextBox"],
.bb-form .bb-fld-l [class*="dxeButtonEdit"] { width: 100% !important; }

/* Social inputs fill their column so Facebook matches the left width and X the
   right; the wrapper carries the border, the editor flexes inside it. */
/* Match the standard form input box (8px radius, theme border/bg, ~39px tall)
   so the social fields don't read smaller/less-rounded than the rest. */
.bb-form .bbcrm-social-input {
    display: flex;
    align-items: center;
    border-radius: 8px;
    border-color: var(--form-input-border);
    background: var(--form-input-bg);
    padding: 5px 10px;
}
.bb-form .bbcrm-social-input:focus-within {
    border-color: var(--form-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--form-accent) 18%, transparent);
}
.bb-form .bb-social-main { flex: 0 0 320px; max-width: 320px; }
.bb-form .bb-social-side { flex: 1 1 260px; max-width: 360px; }

/* Two links, one field: stacked but tight, so they read as a pair rather than as two
   unrelated inputs a full row apart. */
.bb-form .bb-social-stack {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
}
.bb-form .bbcrm-social-input [class*="dxeTextBox"] { flex: 1 1 auto; width: auto !important; min-width: 0; }

/* Inline field hint — small in-flow callout (replaces floating DX help popups). */
.bb-form .bb-form-hint {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    margin: 6px 2px 2px;
    padding: 7px 11px;
    max-width: 420px;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--form-muted);
    background: var(--form-accent-soft);
    border-left: 3px solid var(--form-accent);
    border-radius: 6px;
}
.bb-form .bb-form-hint i {
    color: var(--form-accent);
    margin-top: 1px;
}
/* Side variant — sits beside its field (uses horizontal space) instead of below. */
.bb-form .bb-form-hint--side {
    margin: 0;
    flex: 1 1 240px;
    max-width: 340px;
}

.bb-form [class*="dxeFocused"] {
    border-color: var(--form-accent) !important;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--form-accent) 18%, transparent);
}

/* Social inputs: the .bbcrm-social-input wrapper carries the border —
   the DX textbox inside must stay borderless or the borders double up. */
.bb-form .bbcrm-social-input [class*="dxeTextBox"] {
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
}

/* Checkbox/radio item text */
.bb-form [class*="dxichTextCellSys"],
.bb-form [class*="dxe"] label {
    color: var(--form-text);
    font-size: 14px;
}

/* Sub-option (e.g. opt-out checkbox under its field) */
.bb-form .bb-form-sub {
    margin: -4px 0 10px 1px;
    color: var(--form-muted);
}

/* Member section is always rendered (so its fields post reliably) but hidden until
   the "also a member" toggle is on — pure client-side show/hide, no flash. DX wraps
   the group content in an outer "group box" (the heading-line card chrome), so hide
   that whole box when collapsed — not just the inner content (which left an empty card). */
.bb-form .bb-collapsed { display: none !important; }
/* [class*="GroupBox"] covers both Box (dxflGroupBox) and HeadingLine (dxflHLGroupBox)
   wrappers, in both light and dark theme suffixes. */
.bb-form [class*="GroupBox"]:has(.bb-member-section.bb-collapsed) { display: none !important; }

/* Member-type tiles (ucFamily create flow) — two clickable cards driving the hidden
   chkIsStudent boolean. Theme-safe via --form-* / --bb-info tokens. */
.bb-mtype-tip { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--field-label); margin: 0 0 8px; }
.bb-mtype-tip i { font-size: 13px; opacity: .9; }
.bb-mtype-group { display: flex; gap: 12px; flex-wrap: wrap; margin: 2px 0 8px; }
.bb-mtype-tile {
    flex: 1 1 240px; min-width: 220px;
    display: flex; align-items: flex-start; gap: 12px; padding: 13px 15px;
    border: 2px solid var(--form-border); border-radius: 11px;
    background: var(--form-surface); cursor: pointer; user-select: none;
    transition: border-color .15s, background .15s, box-shadow .15s;
}
.bb-mtype-tile:hover { border-color: var(--bb-info); }
.bb-mtype-tile.active {
    border-color: var(--bb-info); background: var(--bb-info-bg);
    box-shadow: 0 0 0 3px var(--bb-info-bg);
}
.bb-mtype-ico {
    width: 36px; height: 36px; flex: 0 0 auto; border-radius: 50%;
    display: flex; align-items: center; justify-content: center; font-size: 16px;
    background: var(--form-border); color: var(--field-label);
    transition: background .15s, color .15s;
}
.bb-mtype-tile.active .bb-mtype-ico { background: var(--bb-info); color: #fff; }
.bb-mtype-txt { display: flex; flex-direction: column; gap: 2px; }
.bb-mtype-title { font-weight: 600; color: var(--text-color); line-height: 1.2; }
.bb-mtype-desc { font-size: 11.5px; color: var(--field-label); line-height: 1.4; }
@media (max-width: 767px) { .bb-mtype-tile { min-width: 100%; } }

/* Two-card layout (ucFamily) — the wrapper containers ARE the cards; the inner DX
   groups go flat (HeadingLine) and read as section dividers inside Card 2. */
.bb-form .bb-famcard {
    background: var(--form-surface);
    border: 1px solid var(--form-border);
    border-radius: 16px;
    box-shadow: var(--form-shadow);
    margin: 0 0 18px 0;
    padding: 16px 20px 10px;
}
.bb-form .bb-famcard-header {
    font-family: Sora, "Hanken Grotesk", sans-serif;
    font-size: 12.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
    color: var(--form-accent);
    padding-bottom: 10px; margin-bottom: 12px;
    border-bottom: 1px solid var(--form-border);
}

/* Save-route note — explains where the save lands (Family only vs Family + Member).
   Text is swapped client-side by bbSyncMemberMode on member-type change. */
.bb-save-route {
    display: flex; align-items: flex-start; gap: 7px;
    font-size: 12px; line-height: 1.45; color: var(--form-muted);
    background: var(--form-accent-soft); border: 1px solid var(--form-border);
    border-radius: 8px; padding: 7px 12px; margin: 2px 0 14px;
}
.bb-save-route i { color: var(--form-accent); margin-top: 2px; flex-shrink: 0; }
.bb-save-route strong { color: var(--form-strong); font-weight: 600; }

/* Parent/Guardian billing-contact sub-label — shown only when "Child" is selected
   (the contact is the parent, not the member). Toggled by bbSyncMemberMode. */
.bb-billing-sublabel {
    display: flex; align-items: center; gap: 7px;
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
    color: var(--form-muted); margin: 0 0 10px;
}
.bb-billing-sublabel i { color: var(--form-accent); font-size: 12px; }

/* Inline DX help text (HelpTextSettings DisplayMode=Inline, Position=Bottom) sits ~9px
   below the editor by default — tighten so the hint reads as part of the control. */
.bb-form [class*="dxeVHelpTextSys"] { padding-top: 1px !important; }

/* Billing-contact panel (top of the member form) — read-only family billing contact.
   Teal accent to set it apart from the form's blue; theme-safe via a dark override. */
.bb-billing-contact {
    display: flex; align-items: center; gap: 16px;
    background: linear-gradient(135deg, #effbfa 0%, #ddf4f1 100%);
    border: 1.5px solid #99d6d2; border-radius: 13px;
    padding: 14px 20px; margin: 4px 0 6px;
    box-shadow: 0 4px 14px rgba(13,118,110,.10);
}
[data-bs-theme="dark"] .bb-billing-contact {
    background: linear-gradient(135deg, rgba(45,212,191,.10) 0%, rgba(13,148,136,.06) 100%);
    border-color: rgba(45,212,191,.30); box-shadow: 0 4px 16px rgba(0,0,0,.35);
}
.bb-billing-contact-icon {
    width: 46px; height: 46px; flex: 0 0 auto; border-radius: 50%;
    background: linear-gradient(135deg, #14b8a6 0%, #0d7d72 100%); color: #fff;
    display: flex; align-items: center; justify-content: center; font-size: 19px;
    box-shadow: 0 0 0 4px rgba(13,148,136,.16), 0 6px 16px rgba(13,118,110,.40);
}
[data-bs-theme="dark"] .bb-billing-contact-icon {
    background: linear-gradient(135deg, #2dd4bf 0%, #0d9488 100%); color: #042f2c;
    box-shadow: 0 0 0 4px rgba(45,212,191,.18), 0 6px 16px rgba(0,0,0,.5);
}
.bb-billing-contact-body { flex: 1; min-width: 0; }
.bb-billing-contact-eyebrow { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: #0d7d72; margin-bottom: 4px; }
[data-bs-theme="dark"] .bb-billing-contact-eyebrow { color: #2dd4bf; }
.bb-billing-contact-name { font-weight: 700; color: var(--text-color); font-size: 15px; line-height: 1.25; margin-bottom: 5px; }
[data-bs-theme="dark"] .bb-billing-contact-name { color: #c9d1db; }
.bb-billing-contact-meta { display: flex; flex-wrap: wrap; gap: 16px; font-size: 12px; color: var(--field-label); }
.bb-billing-contact-meta span { display: flex; align-items: center; gap: 5px; }
.bb-billing-contact-meta i { color: #0d9488; font-size: 11px; flex-shrink: 0; }
[data-bs-theme="dark"] .bb-billing-contact-meta i { color: #2dd4bf; }
@media (max-width: 767px) { .bb-billing-contact { flex-direction: column; gap: 10px; } }

/* Computed-value chip (e.g. live age beside the birthday field). Neutral accent
   by default; red variant for an invalid value. Reusable across forms. */
.bb-age-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 12px;
    border-radius: 999px;
    font-size: 13px;
    font-weight: 600;
    color: var(--form-accent);
    background: var(--form-accent-soft);
    border: 1px solid color-mix(in srgb, var(--form-accent) 30%, transparent);
}
.bb-age-chip--bad {
    color: #b3261e;
    background: #fdecea;
    border-color: #f3c2bd;
}
/* Dark: the soft accent fill sits too close to the surface and the pill edges
   bleed. Use a contained translucent fill + a defined border so it reads crisp. */
[data-bs-theme="dark"] .bb-age-chip {
    color: #9ad2ee;
    background: rgba(124, 197, 234, .10);
    border-color: rgba(124, 197, 234, .42);
}
[data-bs-theme="dark"] .bb-age-chip--bad {
    color: #f2b8b5;
    background: #2a1714;
    border-color: #5c2b27;
}

/* Centered action row under the form */
/* Actions sit at the natural end of the form, NOT pinned. A sticky bar reads as "the form
   ends here" while content continues behind it — ambiguous for non-expert users, which is the
   audience that matters most. Reachability is handled by keeping ONE scroll region (see the
   nav-rail fix in theme.css), not by floating the buttons. */
.bb-form-actions {
    display: flex;
    justify-content: center;
    gap: 14px;
    padding: 24px 0 38px;
}

/* Slim, elongated CTAs for the form action bar — refined admin, not the chunky
   touch-sized variant used in popups. Longer (wider) and shorter (slimmer). */
.bb-form-actions .asp-button {
    width: auto !important;
    min-width: 210px;
    padding: 8px 30px !important;
    font-size: 13.5px;
    letter-spacing: .04em;
}
.bb-form-actions .asp-button::before {
    width: 18px;
    height: 18px;
}

/* ---------- page scaffold ---------- */

/* Tighten the page-title -> first form element gap to ~10px. Bootstrap's g-*
   gutter puts ~24px top-margin on row columns; collapse it on form pages so the
   form starts right under the title. Applies to every standard form page. */
.bb-form-page > .row {
    margin-top: 0 !important;
}
.bb-form-page > .row > [class*="col-"] {
    margin-top: 10px !important;
}

.bb-form-title {
    font-family: Sora, "Hanken Grotesk", sans-serif;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: .03em;
    color: var(--form-strong);
    margin: 10px 0 0 10px;
}

.bb-form-canvas {
    background: var(--form-surface);
    border: 1px solid var(--form-border);
    border-radius: 16px;
    box-shadow: var(--form-shadow);
    padding: 20px 24px 6px;
}

/* ---------- context rail ---------- */

.bb-rail {
    background: var(--form-surface);
    border: 1px solid var(--form-border);
    border-radius: 16px;
    box-shadow: var(--form-shadow);
    overflow: hidden;
    position: sticky;
    top: 116px; /* clears the fixed app top bar (~100px) with breathing room */
}

.bb-rail-hero {
    padding: 26px 20px 18px;
    text-align: center;
    background: linear-gradient(160deg, var(--form-accent-soft) 0%, transparent 70%);
}

.bb-avatar {
    width: 88px;
    height: 88px;
    margin: 0 auto 14px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: Sora, sans-serif;
    font-size: 28px;
    font-weight: 600;
    color: #fff;
    background: linear-gradient(145deg, #1b2a4a, #0a6486);
    /* WOW ring: surface gap + accent ring + soft glow. Picture (if any) fills the circle. */
    box-shadow: 0 0 0 3px var(--form-surface), 0 0 0 6px rgba(54, 166, 207, .55), 0 10px 24px rgba(10, 100, 134, .42);
    overflow: hidden;
}
.bb-avatar-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
    display: block;
}

.bb-rail-name {
    font-family: Sora, sans-serif;
    font-size: 18px;
    font-weight: 600;
    color: var(--form-strong);
    margin-bottom: 6px;
}

.bb-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 12px;
    border-radius: 999px;
    font-size: 12.5px;
    font-weight: 600;
}

.bb-pill::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}

.bb-pill--ok { color: #2e7d32; background: #e6f3e7; }
.bb-pill--warn { color: #9a6700; background: #fdf3df; }
.bb-pill--muted { color: var(--form-muted); background: var(--form-accent-soft); }
[data-bs-theme="dark"] .bb-pill--ok { color: #6fbf73; background: #16271a; }
[data-bs-theme="dark"] .bb-pill--warn { color: #e3b341; background: #2a2210; }

.bb-rail-meta { padding: 6px 20px 14px; }

.bb-rail-row {
    display: flex;
    justify-content: space-between;
    padding: 8px 2px;
    font-size: 13.5px;
    border-bottom: 1px solid var(--form-border);
}

.bb-rail-row:last-child { border-bottom: 0; }
.bb-rail-row .k { color: var(--form-muted); }
.bb-rail-row .v { font-weight: 600; color: var(--form-text); }

/* Rail members list (edit-mode side card) — member name + status pill per row. */
.bb-rail-members { padding: 2px 20px 16px; }
.bb-rail-members-title {
    font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
    color: var(--form-muted); margin-bottom: 6px;
}
.bb-rail-member {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 7px 0; border-top: 1px solid var(--form-border);
}
.bb-rail-member:first-of-type { border-top: 0; }
.bb-rail-member-name { font-weight: 600; color: var(--form-text); font-size: 12.5px; }
.bb-rail-members-empty {
    display: flex; align-items: center; gap: 8px;
    color: var(--form-muted); font-size: 12px; font-style: italic; padding: 8px 0;
}
.bb-rail-members-empty i { font-size: 14px; opacity: .85; }

/* Add-member CTA. Tonal rather than solid so the form keeps ONE obvious primary action —
   this adds a person, it does not save the form. */
.bb-rail-add {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 12px;
    padding: 9px 12px;
    border: 1px solid var(--form-border);
    border-radius: 10px;
    background: var(--form-accent-soft);
    color: var(--form-accent);
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
    transition: border-color .15s ease, background-color .15s ease;
}

.bb-rail-add:hover,
.bb-rail-add:focus {
    border-color: var(--form-accent);
    color: var(--form-accent);
    text-decoration: none;
}

.bb-rail-add:focus-visible {
    outline: 2px solid var(--form-accent);
    outline-offset: 2px;
}

.bb-rail-add i { font-size: 13px; }

.bb-rail-belt {
    margin: 4px 20px 20px;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--form-border);
    text-align: center;
}

.bb-rail-belt-img {
    display: block;
    width: 100%;
    max-height: 44px;
    object-fit: contain;
    padding: 6px 10px 0;
}

.bb-rail-belt-label {
    font-size: 12.5px;
    padding: 6px 10px;
    color: var(--form-muted);
}

.bb-rail-belt-label strong { color: var(--form-text); }

/* Registration billing summary rail — reuses .bb-rail (card + sticky) and
   .bb-rail-row (key/value), adds a section title and a bold "Payment Due" total. */
.bb-billing-rail-title {
    font-family: Sora, "Hanken Grotesk", sans-serif;
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--form-accent);
    padding: 16px 20px 6px;
}
/* Billing on/off closes the rail, under the figures it governs. Plain text, not a callout —
   a tinted box would compete with the totals for attention. */
.bb-billing-toggle {
    padding: 14px 20px 16px;
    border-top: 1px solid var(--form-border);
}

.bb-billing-toggle-note {
    margin-top: 8px;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--form-muted);
}

.bb-billing-toggle-note strong { color: var(--form-text); font-weight: 600; }

.bb-billing-figures { padding: 2px 20px 14px; }
.bb-billing-figures .bb-rail-row .v { font-variant-numeric: tabular-nums; }
.bb-billing-figures .bb-billing-total {
    margin-top: 2px;
    border-top: 2px solid var(--form-border);
    border-bottom: 0;
}
.bb-billing-figures .bb-billing-total .k,
.bb-billing-figures .bb-billing-total .v {
    font-weight: 700;
    color: var(--form-strong);
}
.bb-billing-rail .bb-form-hint { margin: 0 16px 16px; }

/* Dev-only metadata line: internal IDs for troubleshooting. Values stay hidden,
   but a faint "· · ·" marks the spot as hoverable (an insider affordance); the
   real values reveal on rail hover and never compete for a staff member's eye. */
.bb-rail-dev {
    position: relative;
    margin: 0 20px 16px;
    padding-top: 9px;
    min-height: 13px;
    border-top: 1px dashed var(--form-border);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 11px;
    letter-spacing: .02em;
    color: transparent;
    transition: color .15s ease;
}
.bb-rail-dev::before {
    content: "\00B7 \00B7 \00B7";
    position: absolute;
    left: 0;
    top: 1px;
    font-size: 17px;
    line-height: 1;
    color: var(--form-muted);
    opacity: .7;
    letter-spacing: .18em;
    transition: opacity .15s ease;
}
.bb-rail:hover .bb-rail-dev { color: var(--form-muted); }
.bb-rail:hover .bb-rail-dev::before { opacity: 0; }

@media (max-width: 991px) {
    .bb-rail { position: static; margin-bottom: 20px; }
}
