/* @cascade-order: 8 — do not reorder. Split 9/10 of the former
   monolithic style.css (see docs/ui-pattern-audit.md and ADR-0095-style-css-split-into-ten-contiguous-files).
   Originally a contiguous slice of style.css in @cascade-order. That
   ordering is still enforced (tests/unit/css-split-structure.test.js);
   byte-for-byte reconstruction is NOT enforced and must not be relied on
   — the split files have been edited independently since. Earlier headers
   cited tests/unit/css-split-equality.test.js, which does not exist.
   Contains: the modal subtitle, admin-only/viewer-role gating (the !important role-visibility cluster), add-members modal, events tab, pass check-in modal, the notification system, group/family styles, and the start of analytics, and Online Orders (ADR-0193, at the end).
   Original line range: 16870-19141. */


/* ============================================================================
   ADMIN-ONLY ELEMENTS
   ============================================================================ */

/* Hide admin-only elements by default */
.admin-only {
  display: none;
}

/* Show admin-only elements when body has admin class */
body.is-admin .admin-only {
  display: inline-flex;
}

/* Hide management-only elements by default (entry-ban Ban/Unban controls).
   Mirrors the .admin-only pattern exactly: no !important on the show rule,
   so the .hidden utility (display:none !important, toggled by
   reflectBanState for the Ban<->Unban state) still wins. body.is-management
   is set for management AND admin (role >= 2). */
.management-only {
  display: none;
}

body.is-management .management-only {
  display: inline-flex;
}

/* ============================================================================
   VIEWER ROLE ; read-only, schedule + attendance only
   ============================================================================ */

/* Desktop sidebar: hide the viewer-irrelevant controls that are not pages. Page
   buttons are shown or hidden from `TAB_ACCESS` by the role painter (ADR-0170). */
body.is-viewer .app-nav .nav-item[data-action="openNewAccount"],
body.is-viewer .app-nav .nav-spacer,
body.is-viewer #editNavItem {
  display: none !important;
}

/* Desktop footer group: hide Help for viewers */
body.is-viewer .app-nav .nav-item[data-action="startTour"] {
  display: none !important;
}

/* Hide main search bar */
body.is-viewer .main-search-bar {
  display: none !important;
}

/* Class check-in: hide search/roster column, make attendance full-width. Scoped
   to the class page: the camp door's Registered column stays, read-only, so a
   counselor can see who is expected (check-in itself is a Viewer intent). */
body.is-viewer #tab-class-checkin .class-checkin-column.search-column {
  display: none !important;
}
body.is-viewer #tab-class-checkin .class-checkin-body {
  grid-template-columns: 1fr;
}

/* Hide write-action UI in attendance rows */
body.is-viewer .attendance-row .member-overflow,
body.is-viewer .attendance-row .member-icon-single.icon-checkout {
  display: none !important;
}

/* Camp check-in: hide the Add camper / Roll call write actions for viewers (the
   desktop toolbar; the phone's page draws its tools only for Employee), and the
   Groups manager whose only job is deleting a group. The rules refuse a Viewer
   every registration and day-record write; presence (check in / out) is the
   Viewer's camp intent. */
body.is-viewer #tab-camp-checkin .camp-toolbar .toolbar-right,
body.is-viewer #tab-camp-checkin .camp-header-menu [data-action="campManageGroups"] {
  display: none !important;
}

/* Hide class header overflow menu (Edit / History) */
body.is-viewer .class-header-overflow {
  display: none !important;
}

/* Today Visitors: hide the action column and its overflow menu */
body.is-viewer .member-cell-action-edit,
body.is-viewer .member-row .member-overflow-trigger {
  display: none !important;
}

/* Today Visitors: make check-in and schedule icons non-interactive (status-only) */
body.is-viewer .member-icon-single[data-action],
body.is-viewer .member-schedule-btn[data-action] {
  pointer-events: none;
  cursor: default;
}

/* Hide [USE] action buttons on pass badges */
body.is-viewer .badge-action {
  display: none !important;
}

/* Disable clickable membership badges */
body.is-viewer .pass-badge.clickable {
  pointer-events: none;
  cursor: default;
}

/* (`.staff-role.viewer` and `.pending-approval-badge` lived here — the second
    half of a badge family whose other half was in 20-settings. Both are gone:
    the staff list renders v3.css's `.state-chip` now, so the role no longer
    borrows a destination colour and "Approval" no longer hardcodes #f59e0b
    where --color-paused was the token for it.) */

/* (Legacy MERGE ACCOUNT MODAL styles removed ; replaced by the SSOT merge UI
    in public/js/merge-ui/ + public/css/merge-ui.css.) */

/* ============================================================================
   ADD MEMBERS MODAL
   ============================================================================ */

.add-members-modal-wide {
  max-width: 800px;
  width: 95vw;
}

.add-members-columns {
  display: flex;
  gap: var(--space-4);
  min-height: 400px;
}

.add-members-left {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  border-right: 1px solid var(--color-border);
  padding-right: var(--space-4);
}

.add-members-right {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.add-members-search-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.add-members-pending-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.add-members-pending-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-border);
  margin-bottom: var(--space-2);
}

.add-members-pending-list {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.add-members-pending-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--space-3);
  background: var(--color-bg-subtle);
  border-radius: var(--radius-md);
}

.add-members-pending-item.is-new {
  background: color-mix(in srgb, var(--color-success) 10%, var(--color-bg-subtle));
}

.add-members-pending-item.is-saved {
  background: transparent;
  border: 1px solid var(--color-border);
}

.add-members-pending-item-info {
  display: flex;
  flex-direction: column;
}

.add-members-pending-item-name {
  font-weight: var(--font-medium);
}

.add-members-pending-item-meta {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

.add-members-pending-item-remove {
  color: var(--color-text-muted);
  cursor: pointer;
  padding: var(--space-1);
}

.add-members-pending-item-remove:hover {
  color: var(--color-danger);
}

.add-members-create-header {
  font-weight: var(--font-semibold);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-border);
  margin-bottom: var(--space-3);
}

.add-members-create-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* --- Add Members Modal: mobile --- */
@media (max-width: 600px) {
  .add-members-modal-wide {
    max-width: 100%;
    max-height: 100vh;
    height: 100vh;
    border-radius: 0;
    margin: 0;
  }

  .add-members-columns {
    flex-direction: column;
    min-height: 0;
  }

  .add-members-left {
    border-right: none;
    padding-right: 0;
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--color-border);
  }

  .add-members-right {
    padding-top: var(--space-3);
  }

  .add-members-create-form .form-row {
    grid-template-columns: 1fr;
  }

  .add-members-create-form .add-member-birthday-group {
    max-width: none;
  }
}

/* ============================================================================
   BIRTHDAY AGE DISPLAY
   ============================================================================ */

/* The Add Members create form's DOB slot. A named class since ADR-0132 moved
   that modal onto `createModal`: the field carried `style="max-width: 320px"`
   as static markup, and the phone override had to reach it with a
   `.form-group[style*="max-width"]` attribute selector because there was
   nothing else to name it by. */
.add-members-create-form .add-member-birthday-group {
  max-width: 320px;
}

.birthday-input-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.birthday-input-row .form-input {
  flex: 1;
}

.birthday-age {
  font-size: var(--text-sm);
  font-style: italic;
  white-space: nowrap;
}

/* ============================================================================
   EVENTS TAB (Camp Registrations)
   ============================================================================ */

.events-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.event-card {
  padding: var(--space-3);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: border-color 0.15s;
}

.event-card:hover {
  border-color: var(--color-border-strong);
}

.event-card .event-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-2);
}

.event-card .event-name {
  font-weight: var(--font-medium);
  font-size: var(--text-base);
  color: var(--color-text);
}

.event-card .event-details {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.event-card .event-dates {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.event-card .event-dates i {
  color: var(--color-accent);
}

.event-days {
  padding: 2px 8px;
  background: var(--color-bg-subtle);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
}

/* ============================================================================
   PASS CHECK-IN MODAL (Family Account Flow)
   ============================================================================ */

/* No width rule here: the 400px one targeted `.modal-content`, which this
   modal never emitted (it has always been `.modal`), so it never applied.
   Deleted rather than repointed — narrowing it now would be a design change,
   not the construction unification of ADR-0097. */
#pass-checkin-modal .modal-body {
  padding: var(--space-5);
}

.pass-checkin-question {
  font-size: var(--text-base);
  color: var(--color-text);
  text-align: center;
  margin-bottom: var(--space-4);
}

.pass-checkin-buttons {
  display: flex;
  justify-content: center;
  gap: var(--space-3);
}

.pass-checkin-btn {
  flex: 1;
  max-width: 150px;
  padding: var(--space-3) var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  border-radius: var(--radius-md);
  border: 2px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: all 0.15s ease;
  text-align: center;
}

.pass-checkin-btn:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}

.pass-checkin-step2-label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  text-align: center;
  margin-bottom: var(--space-3);
}

.pass-checkin-btn.addon {
  border-color: var(--color-success);
  color: var(--color-success);
}

.pass-checkin-btn.addon:hover {
  background: var(--color-success);
  color: white;
  border-color: var(--color-success);
}

.pass-checkin-btn.use-pass {
  border-color: var(--color-border);
  color: var(--color-text-secondary);
}

.pass-checkin-btn.use-pass:hover {
  border-color: var(--color-text-muted);
  color: var(--color-text);
  background: var(--color-bg-subtle);
}

/* ==========================================================================
   MOBILE ATTENDANCE LIST
   Row 1: Name ........................ [⋮]
   Row 2: Time .... Badges
   ========================================================================== */
@media (max-width: 600px) {
  .attendance-list .attendance-row:not(.is-roster) {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    gap: var(--space-1) var(--space-1);
    /* Keep the design's horizontal inset (v3.css gives `.attendance-row`
       `5px 14px`). This rule out-specifies it at (0,2,0), and zeroing the
       sides here put every roster name hard against the phone's bezel — the
       name's own -6px hover bleed then started off-screen. The vertical
       rhythm is this block's business; the inset is the design's. */
    padding: var(--space-2) 14px;
    align-items: center;
  }

  /* Row 1: Name | ⋮ */
  .attendance-list .attendance-name {
    grid-row: 1;
    grid-column: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* The action slot, not `.member-overflow` inside it: the row's grid children
     are the four slots the ONE builder emits (ADR-0130), and the overflow
     wrapper is a level down. */
  .attendance-list .row-actions {
    grid-row: 1;
    grid-column: 2;
  }

  /* Row 2: time | badges */
  .attendance-list .class-header-time {
    grid-row: 2;
    grid-column: 2;
    font-size: 0.7857rem;
    color: var(--color-text-muted);
    text-align: left;
    width: auto;
    min-width: 0;
  }

  .attendance-list .attendance-badges {
    grid-row: 2;
    grid-column: 1;
    justify-self: start;
    text-align: right;
  }

}

/* ==========================================================================
   GROUP/FAMILY ACCOUNT STYLES
   ========================================================================== */

/* Account Type Toggle: was its own two-button component (a gap between two
   fully-bordered buttons), now the shared `.btn-group-toggle`/`.btn-toggle`
   segmented control already used for Square's Environment toggle and Member
   Logins' role toggle (20-settings-design-system.css) — one owner for "pick
   one of two," not a second shape for the same job. Markup keeps the
   `#account-type-toggle` id for the mobile full-width override below. */

/* Group Details Section */
.group-details-section {
  margin-top: var(--space-4);
  padding: var(--space-4);
  background: var(--color-bg-subtle);
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
}

.group-details-section.hidden {
  display: none;
}

/* Inline Add Member Form */
.add-member-inline-form {
  padding: var(--space-3);
  background: var(--color-bg-subtle);
  border-radius: var(--radius-md);
  border: 1px dashed var(--color-border);
}

.group-member-actions {
  display: flex;
  gap: var(--space-2);
}

/* Group Badges in Search Results */

.badge-family {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-md);
  font-weight: var(--font-medium);
  margin-right: var(--space-1);
  background: var(--color-success);
  color: white;
}

.badge-group {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-md);
  font-weight: var(--font-medium);
  margin-right: var(--space-1);
  background: var(--color-info);
  color: white;
}

/* ==========================================================================
   GROUP ROWS IN SEARCH RESULTS
   ========================================================================== */

/* Single member icon (non-grouped members) */

/* Admin: checked-in today ; green icon */

/* Clickable waiver icon */
.member-icon-single:active:not(.checked-in) {
  transform: scale(0.93);
}
.member-icon-single.checked-in:active {
  transform: scale(0.93);
}
/* Contact variant ; neutral color, same size/shape */
.member-icon-single.icon-contact {
  color: var(--color-text-muted);
}
.member-icon-single.icon-contact:hover {
  background: var(--color-bg-subtle);
  color: var(--color-text);
}

/* View variant — neutral, same size/shape as icon-contact (a separate name
   because it's a distinct action; the "share the base, vary only color" rule
   applies to structure, not to collapsing unrelated actions onto one class). */
/* The optical nudge for this icon lives in v3.css, next to its base rule —
   v3.css declares the SAME selector and loads after this file, so a second
   copy here would be dead weight the moment the two agreed, and a silent
   bug the moment they didn't (see the redundant-CSS audit, port-status.md). */
/* Schedule icon button in name cell */
/* Check-in button — V3 (design-system/checkin-button.html).

   Idle is NEUTRAL: no category has been committed yet, so the button must
   not pre-announce one. Once checked in it tints to the DESTINATION's own
   colour via --class-color (open gym green, camp brown, a class's own hue),
   so the state says how they checked in, not merely that they did.

   Waiver-only is a STATUS, not a destination, so it takes a neutral fill
   rather than competing with Open Gym's green.

   Hover on either checked state goes red: on a checked row the gesture is
   undo, and the colour should say so before the click. */
.member-schedule-btn {
  /* The design's `var(--class-color, var(--color-classes))` fallback is DEAD in
     production, and silently so. Custom properties inherit, and the content
     card publishes `--class-color` to paint its own edge — so a button that
     never got an inline colour does not fall back to classes blue, it reads the
     CARD's: the selected destination's hue on a check-in page, and the neutral
     `--color-border-strong` on a `.no-tab` page like the Members table. The
     button then says "checked in somewhere" in a colour that means something
     else entirely, which is the opposite of its job.

     Resetting the property here restores the authored behaviour: `initial` on a
     custom property is the guaranteed-invalid value, so `var()` takes its
     fallback. An inline `style="--class-color: …"` from the row builder still
     wins, because inline beats author. */
  --class-color: initial;
}

/* ICON-ONLY CONTROLS: the glyph is centred, not baselined.

   Measured, because two earlier passes guessed at this. Rendering every
   Bootstrap glyph we use to a canvas and reading its ink box shows the FONT is
   not the problem: at 100px the em box runs baseline-100 -> baseline-0, and
   every glyph's ink centre lands at -50.5 or -51. The ink is centred in the em
   box by design, for calendar-plus, calendar-check, clipboard2-plus, eye and
   three-dots-vertical alike. Centre the em box and the glyph is centred.

   Two things were stopping the em box from being centred:

   1. Bootstrap Icons sets `vertical-align: -.125em` on `.bi::before`. That is a
      TEXT idiom — it drops the glyph below the baseline so it sits level with
      lowercase letters beside it. In a button whose only content is the icon
      there is no text to align to, and the nudge is pure error: 1.75px low at
      14px, which is what "the icon isn't centred" was.
   2. The <i>'s own line box has a STRUT from the inherited sans font, whose
      metrics differ from the icon font's, so the pseudo's baseline lands off
      the box's middle even with `line-height: 1`. Worth ~0.35px at 14px.

   An earlier fix set `line-height: 1` here and stopped, which addressed neither:
   it collapsed the <i>'s box onto its own strut but left both offsets intact.

   Making the <i> a centring flex box removes both at once — the pseudo becomes
   a flex item, so it is placed by its margin box and never consults a baseline.
   No magic numbers, and it holds at any font-size.

   Scoped to controls whose ONLY content is the icon. A `.btn` with a label
   keeps the baseline nudge, because there the glyph SHOULD sit with the text. */
.member-schedule-btn .bi,
.member-icon-single .bi,
.schedule-day-btn .bi {
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.member-schedule-btn .bi::before,
.member-icon-single .bi::before,
.schedule-day-btn .bi::before {
  vertical-align: 0;
  line-height: 1;
}

/* NO PER-GLYPH NUDGE. Three passes tried to hand-correct calendar-plus /
   calendar-check with a manual `top` offset (first -0.5px reasoning about
   visual weight, then a "symmetric, remove it" pass that measured the wrong
   codepoint, then a "1px of ink mass sits high, nudge down" pass) — every
   one of them fighting the flex-centring above instead of trusting it. The
   flex box already centres the glyph correctly; removed the offset. */

.member-schedule-btn:active:not(.checked-in):not(.checked-waiver) {
  transform: scale(0.93);
}

/* Member card overflow menu (mobile) */

/* The quiet 28px icon-button form: the card corner on mobile, and the check-in
   rows. `:not(.btn)` because the member row's trigger is a real `.btn.btn-sm`
   in a segmented group, where the button family owns the metrics — without the
   guard this forced it to 28px beside a 22px View and the segments went
   uneven. */

/* Dark mode: add colored borders */
[data-theme="dark"] .member-icon-single:hover {
  border-color: transparent;
}
[data-theme="dark"] .member-icon-single.icon-contact {
  border-color: var(--color-border);
}
[data-theme="dark"] .member-icon-single.icon-noshow {
  border-color: var(--color-danger);
}

/* Group header row (desktop only ; mobile sets background on the row itself) */
@media (min-width: 601px) {
  .member-table .group-header-row td {
    background: color-mix(in srgb, var(--color-accent) 12%, var(--color-bg-elevated));
  }
}

.group-header-row .group-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 27px;
  height: 27px;
  background: var(--color-accent);
  border-radius: var(--radius-md);
  color: white;
  font-size: var(--text-lg);
  margin-right: var(--space-2);
  vertical-align: middle;
}

.group-header-row .group-name {
  font-size: var(--text-base);
  font-weight: var(--font-bold);
  vertical-align: middle;
}

.group-header-row .group-type-badge {
  font-size: var(--text-xs);
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  margin-left: var(--space-2);
  vertical-align: middle;
}

.group-header-row .group-type-badge.badge-family {
  background: color-mix(in srgb, var(--color-info) 15%, transparent);
  color: var(--color-info);
}

.group-header-row .group-type-badge.badge-group {
  background: var(--color-bg-muted);
  color: var(--color-text-muted);
}

.group-header-row .group-count-badge {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  background: var(--color-bg-muted);
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  margin-left: var(--space-2);
  vertical-align: middle;
}

/* Nested group members */

.group-member-search-row td:first-child {
  padding-left: calc(var(--space-3) + 8px);
}

.group-member-search-row .nested-indicator {
  color: var(--color-accent);
  font-size: var(--text-lg);
  margin-right: var(--space-1);
}

/* Last member in group - thicker bottom border
.group-member-search-row.group-member-last td {
  border-bottom: 2px solid color-mix(in srgb, var(--color-accent) 30%, transparent);
} */

/* Attendance Row with Group Info */
.attendance-group-info {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  margin-top: var(--space-1);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.attendance-group-info .badge-family,
.attendance-group-info .badge-group {
  font-size: 0.7143rem;
  padding: 1px 4px;
}

/* Multi-select Modal for Smartwaiver */
.multi-select-section {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.participant-checkboxes {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.participant-checkbox {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--color-bg-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
}

.participant-checkbox:hover {
  background: var(--hover-row);
}

.participant-checkbox input[type="checkbox"] {
  width: 18px;
  height: 18px;
}

/* Group Pass Badge in Check-in */
.pass-badge.group-pass {
  background: var(--color-info);
  color: white;
}

/* `.checkin-option.shared-pass` (+ its `::after` "Shared" tag) was here and is
   DELETED with the rest of `.checkin-option` (ADR-0132): its only emitter was
   the unreachable static `#checkin-modal`. */

/* ==============================================
   TRANSFER PASSES MODAL
   ============================================== */

.transfer-bundles-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-height: 500px;
  overflow-y: auto;
}

.transfer-bundle-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all 0.15s ease;
}

.transfer-bundle-row:hover {
  border-color: var(--color-accent);
  background: var(--hover-row);
}

.transfer-bundle-row input[type="checkbox"] {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.transfer-bundle-info {
  display: flex;
  flex: 1;
  align-items: center;
  gap: var(--space-3);
}

.transfer-bundle-member {
  font-weight: 500;
  min-width: 120px;
}

/* Badge inside transfer row - auto margins for spacing */
.transfer-bundle-info .pass-badge {
  margin-left: auto;
}

.transfer-select-all {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.transfer-select-all input {
  width: 16px;
  height: 16px;
}

/* ==========================================================================
   ONLINE ORDERS (#tab-square, ADR-0193) — a queue and one page per order.

   Ported from the approved mockup's hist-orders.css (`.ox-*`, the convention the
   Follow-ups port set) with the few shared pieces the mockup took from its own
   scaffolding written once here. Everything else is the app's own components:
   `.settings-subnav`, `.attendance-toolbar`, `.camp-reg-what`, `.waiver-status`,
   `.class-checkin-banner`, `.settings-attention`, `.member-overflow`, `.chip`,
   `.empty-state`, `renderBadge` and `stateChip`. No one-sided coloured borders, no
   gradients, no pill radii. The phone rules are in mobile.css, in its SQUEEZED PAGES block.
   ========================================================================== */

/* ── the header: one fixed line, the way Camps' is (ADR-0122 §5) ────────── */
.orders-header {
  height: 52px;
  box-sizing: border-box;
  gap: var(--space-3);
  flex: none;
  flex-wrap: nowrap;
}
.orders-header .class-header-name-row {
  min-width: 0;
  align-items: baseline;
}
.orders-header .class-header-name {
  overflow: hidden;
  text-overflow: ellipsis;
}
.orders-header .class-header-name .bi {
  margin-right: var(--space-2);
}
.orders-back {
  flex: none;
}
.orders-header a,
.orders-header a:hover {
  text-decoration: none;
}
.orders-header-sub {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  white-space: nowrap;
}
.orders-header-sub:empty {
  display: none;
}
.orders-header .class-header-actions {
  flex: none;
}
.orders-header .member-overflow {
  display: inline-flex;
}
#tab-square > .settings-subnav {
  flex: none;
}
#tab-square > .page-body {
  display: flex;
  flex-direction: column;
}
/* The status band's sentence wraps (the shared band clips it to one line). */
#tab-square .waiver-status-detail {
  white-space: normal;
}
.btn.is-blocked:where(:not(:disabled, [aria-disabled="true"])) {
  opacity: .75;
}

/* ── small shared pieces ─────────────────────────────────────────────────── */
.ox-page {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}
.ox-subnav-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 18px;
  padding: 0 5px;
  margin-left: 6px;
  border-radius: var(--radius-sm);
  background: var(--color-bg-muted, var(--color-bg-subtle));
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
}
.ox-subnav-count:empty {
  display: none;
}
.settings-subnav-item.active .ox-subnav-count {
  background: var(--color-accent-tint);
  color: var(--color-accent);
}
#ox-field {
  flex: 1 1 280px;
  min-width: 0;
}
.ox-count {
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
}
.ox-faint {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.ox-bad {
  color: var(--color-danger);
}
.ox-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--text-sm);
}
.ox-lead {
  margin: 0 0 var(--space-3);
  color: var(--color-text-secondary);
}
.ox-link {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--color-accent);
  cursor: pointer;
  text-decoration: none;
}
.ox-link:hover {
  text-decoration: underline;
}
.ox-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--space-3);
}
.ox-details > summary {
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
  padding: 4px 0;
}

/* ── the queue ───────────────────────────────────────────────────────────── */
.ox-layout {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(250px, 2fr);
  gap: var(--space-4) var(--space-6);
  align-items: start;
}
.ox-layout.is-single {
  grid-template-columns: minmax(0, 1fr);
}
.ox-main {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}
.ox-side {
  min-width: 0;
}
.ox-section-head {
  display: flex;
  gap: 8px;
  align-items: baseline;
  margin: 0; /* the column's gap spaces it (.ox-main) */
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--color-text-secondary);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.ox-list {
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin-bottom: 0; /* the column gap spaces lists and headings (.ox-main) */
}
.ox-row {
  display: grid;
  grid-template-columns: minmax(170px, 1.1fr) minmax(0, 1.9fr) 64px 150px 128px;
  gap: var(--space-3);
  align-items: center;
  padding: 9px var(--space-3);
  border-bottom: 1px solid var(--color-border-subtle);
  cursor: pointer;
}
.ox-row:last-child {
  border-bottom: 0;
}
.ox-row:hover {
  background: var(--hover-row, var(--color-bg-subtle));
}
.ox-row:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}
.ox-who .what {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 6px;
  font-weight: var(--font-medium);
}
.ox-who .who {
  display: block;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.ox-lines {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.ox-mini-for,
.ox-ref {
  white-space: nowrap;
}
.ox-mini .badge {
  flex: none;
}
.ox-mini {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 8px;
  font-size: var(--text-md);
}
.ox-qty {
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
}
.ox-total {
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-semibold);
  text-align: right;
}
.ox-status {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}
.ox-more {
  margin-left: 4px;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}
.ox-act {
  display: flex;
  justify-content: flex-end;
  font-size: var(--text-sm);
  cursor: default;
}
.ox-act .member-overflow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.ox-row-done .ox-act {
  justify-content: flex-start;
  text-align: left;
  line-height: 1.3;
}
.ox-flow {
  font-size: var(--text-sm);
}
.ox-kinds {
  margin-bottom: var(--space-3);
  flex-wrap: wrap;
  row-gap: 6px;
}
.ox-sync {
  margin: var(--space-2) 0 0;
}
.ox-details-warn > summary {
  list-style: none;
  cursor: pointer;
  margin-bottom: 0;
}
.ox-details-warn > summary::-webkit-details-marker {
  display: none;
}
.ox-details-warn[open] > summary {
  margin-bottom: 4px;
}
.ox-warn-count {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-semibold);
}
.ox-details-warn:not([open]) > summary::after {
  content: '\F282';
  font-family: 'bootstrap-icons';
  font-size: 11px;
  margin-left: 6px;
}
.ox-details-warn[open] > summary::after {
  content: '\F286';
  font-family: 'bootstrap-icons';
  font-size: 11px;
  margin-left: 6px;
}

/* ── one order ───────────────────────────────────────────────────────────── */
/* (0,2,0): it has to outrank v3.css's `.record-card` gap, which loads later. */
.record-card.ox-line {
  gap: 8px;
  padding: 10px 14px;
}
.ox-line.has-problem {
  border-color: color-mix(in srgb, var(--color-warning) 55%, var(--color-border));
  background: var(--color-warning-tint);
}
.ox-line.is-flash {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.ox-line-head {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  align-items: baseline;
}
.ox-line-price {
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-semibold);
}
.ox-field {
  display: grid;
  grid-template-columns: 80px minmax(0, 1fr);
  gap: var(--space-3);
  align-items: center;
  font-size: var(--text-md);
}
.ox-k {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}
.ox-assign {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 8px;
}
.ox-days {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.ox-day {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  border-radius: var(--radius-sm);
  background: var(--color-bg-subtle);
  font-size: var(--text-sm);
}
.ox-day.is-off {
  background: var(--color-danger-tint, color-mix(in srgb, var(--color-danger) 14%, transparent));
  color: var(--color-danger);
  font-weight: var(--font-semibold);
}
.ox-problem {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  padding-top: 6px;
  border-top: 1px solid var(--color-border-subtle);
  font-size: var(--text-md);
}
.ox-fix {
  display: inline-flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-left: auto;
  align-items: center;
}
.ox-outcome {
  padding-top: 6px;
  border-top: 1px solid var(--color-border-subtle);
  color: var(--color-text-secondary);
  font-size: var(--text-md);
}
.ox-outcome .bi {
  color: var(--color-success);
}

/* ── the windows ─────────────────────────────────────────────────────────── */
.ox-import-out {
  margin-top: var(--space-2);
}
.ox-import-found {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 10px;
  background: var(--color-info-tint);
  border-radius: var(--radius-md);
}
.ox-import-found .bi {
  color: var(--color-success);
}
.ox-acct-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin-top: 6px;
}
.ox-acct-row .camp-reg-what {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.ox-acct-end {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.ox-acct-sug {
  margin-bottom: var(--space-3);
}
.ox-acct-new {
  margin-top: var(--space-3);
}
.ox-bulk {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  max-height: 50vh;
  overflow: auto;
}
.ox-bulk-row {
  padding: 8px 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.ox-bulk-who {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: baseline;
  flex-wrap: wrap;
}
.ox-bulk-row ul {
  margin: 4px 0 0;
  padding-left: 18px;
  color: var(--color-text-secondary);
  font-size: var(--text-sm);
}
.ox-bulk-state {
  margin-left: auto;
  font-size: var(--text-sm);
  color: var(--color-text-secondary);
}
.ox-bulk-fail {
  margin-top: 6px;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  background: var(--color-danger-tint, color-mix(in srgb, var(--color-danger) 14%, transparent));
  color: var(--color-danger);
  font-size: var(--text-sm);
}
.ox-bulk-fail[hidden] {
  display: none;
}

/* ── narrower screens ──────────────────────────────────────── */
@media (max-width: 1100px) {
  .ox-layout {
    grid-template-columns: minmax(0, 1fr);
  }
}
