*, *::before, *::after { box-sizing: border-box; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      background: #f3f4f6;
      margin: 0;
      padding: 20px;
    }

    /* ── Test-mode CSV loader panel ── */
    .sbap-test-bar {
      max-width: 860px;
      margin: 0 auto 20px;
      background: #fff8e1;
      border: 1px solid #ffe082;
      border-radius: 6px;
      padding: 14px 18px;
      font-size: 13px;
    }
    .sbap-test-bar strong { display: block; margin-bottom: 8px; color: #5a4000; font-size: 14px; }
    .sbap-test-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
    .sbap-test-bar input[type="file"] { font-size: 13px; }
    .sbap-test-bar input[type="number"] { width: 64px; padding: 5px 8px; border: 1px solid #d1d5db; border-radius: 4px; font-size: 13px; }
    .sbap-test-bar label { font-size: 13px; color: #374151; display: flex; align-items: center; gap: 6px; }
    .sbap-test-btn {
      display: inline-flex; align-items: center; padding: 6px 14px;
      font-size: 13px; font-weight: 600; border: none; border-radius: 4px;
      cursor: pointer; background: #1a56a0; color: #fff;
    }
    .sbap-test-btn:hover { background: #134080; }
    .sbap-test-btn-ghost {
      background: transparent; color: #1a56a0;
      border: 1px solid #1a56a0;
    }
    .sbap-test-btn-ghost:hover { background: rgba(26,86,160,.08); }
    #sbap-csv-status { font-size: 13px; color: #6b7280; }
    .sbap-test-divider { width: 1px; height: 22px; background: #d1d5db; flex-shrink: 0; }
    .sbap-test-hint { margin-top: 8px; color: #6b7280; font-size: 12px; }

    /* ════════════════════════════════════════════════
       SBAP Intake — Frontend Styles v1.0.0
    ════════════════════════════════════════════════ */
    :root {
      /* brand */
      --sbap-primary:       #1a56a0;
      --sbap-primary-dark:  #134080;
      /* status */
      --sbap-success:       #1a6e3c;
      --sbap-success-bg:    #d4edda;
      --sbap-error:         #8b1a1a;
      --sbap-error-bg:      #fde8e8;
      --sbap-warning-bg:    #fff8e1;
      /* neutrals — lighter borders + softer background carry the modern surface look */
      --sbap-border:        #e4e8ef;
      --sbap-border-strong: #d0d7e2;
      --sbap-bg:            #f5f7fb;
      --sbap-card-bg:       #ffffff;
      --sbap-text:          #0f172a;
      --sbap-muted:         #5b6675;
      /* radius scale */
      --sbap-radius:        10px;
      --sbap-radius-sm:     7px;
      --sbap-radius-lg:     16px;
      --sbap-step-done:     #1a56a0;
      --sbap-step-active:   #1a56a0;
      --sbap-step-pending:  #94a3b8;
      /* elevation */
      --sbap-shadow-sm: 0 1px 2px rgba(15,23,42,.06), 0 1px 3px rgba(15,23,42,.05);
      --sbap-shadow-md: 0 4px 12px rgba(15,23,42,.08), 0 2px 4px rgba(15,23,42,.04);
      --sbap-shadow-lg: 0 18px 44px rgba(15,23,42,.16);
      /* motion */
      --sbap-dur-fast: 140ms;
      --sbap-dur:      220ms;
      --sbap-dur-slow: 340ms;
      --sbap-ease: cubic-bezier(.16, 1, .3, 1);
      /* spacing scale */
      --sbap-sp-1: 4px; --sbap-sp-2: 8px; --sbap-sp-3: 12px;
      --sbap-sp-4: 16px; --sbap-sp-5: 24px; --sbap-sp-6: 32px;
      /* brief-named aliases → mapped onto the tokens above */
      --color-bg: var(--sbap-bg);           --color-surface: var(--sbap-card-bg);
      --color-primary: var(--sbap-primary); --color-primary-hover: var(--sbap-primary-dark);
      --color-text: var(--sbap-text);       --color-muted: var(--sbap-muted);
      --color-border: var(--sbap-border);
    }

    #sbap-app {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      font-size: 15px;
      color: var(--sbap-text);
      max-width: 860px;
      margin: 0 auto;
      padding: 0 0 40px;
    }

    .sbap-hidden { display: none !important; }

    .sbap-header {
      background: var(--sbap-card-bg);
      border: 1px solid var(--sbap-border);
      border-radius: var(--sbap-radius);
      padding: 16px 20px 0;
      margin-bottom: 24px;
      position: sticky;
      top: var(--mosdga-chrome-top, 0px); /* v270 — below the WP admin bar */
      z-index: 100;
    }

    .sbap-steps {
      display: flex;
      gap: 0;
      overflow-x: auto;
      padding-bottom: 12px;
    }

    .sbap-step-link {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 6px 16px 6px 0;
      color: var(--sbap-step-pending);
      font-size: 13px;
      cursor: default;
      white-space: nowrap;
      flex-shrink: 0;
    }

    .sbap-step-link:not(:first-child)::before {
      content: '';
      display: inline-block;
      width: 24px;
      height: 1px;
      background: var(--sbap-border);
      margin-right: 16px;
      flex-shrink: 0;
    }

    .sbap-step-mark {
      width: 26px;
      height: 26px;
      border-radius: 50%;
      border: 2px solid var(--sbap-step-pending);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      font-weight: 700;
      flex-shrink: 0;
      transition: border-color .2s, background .2s, color .2s;
    }

    .sbap-step-link.sbap-step-active { color: var(--sbap-step-active); font-weight: 600; }
    .sbap-step-link.sbap-step-active .sbap-step-mark {
      border-color: var(--sbap-step-active);
      background: var(--sbap-step-active);
      color: #fff;
    }

    .sbap-step-link.sbap-step-done { color: var(--sbap-step-done); }
    .sbap-step-link.sbap-step-done .sbap-step-mark {
      border-color: var(--sbap-step-done);
      background: var(--sbap-step-done);
      color: #fff;
    }
    .sbap-step-link.sbap-step-done .sbap-step-mark::after { content: '✓'; font-size: 11px; }
    .sbap-step-link.sbap-step-done .sbap-step-mark { font-size: 0; }

    .sbap-progress-wrap {
      height: 3px;
      background: var(--sbap-border);
      border-radius: 0 0 var(--sbap-radius) var(--sbap-radius);
      overflow: hidden;
      margin: 0 -20px;
    }
    .sbap-progress-bar {
      height: 100%;
      background: var(--sbap-primary);
      transition: width .35s ease;
    }

    .sbap-panel {
      background: var(--sbap-card-bg);
      border: 1px solid var(--sbap-border);
      border-radius: var(--sbap-radius);
      padding: 28px 32px 24px;
    }

    .sbap-panel h2 { margin: 0 0 8px; font-size: 20px; font-weight: 700; color: var(--sbap-text); }
    .sbap-panel > p { margin: 0 0 20px; color: var(--sbap-muted); }
    .sbap-muted { color: var(--sbap-muted); font-size: 13px; }

    .sbap-field-group { margin-bottom: 20px; }

    .sbap-label { display: block; font-weight: 600; font-size: 14px; margin-bottom: 6px; }

    .sbap-input, .sbap-select {
      display: block;
      width: 100%;
      max-width: 360px;
      padding: 9px 12px;
      font-size: 15px;
      border: 1px solid var(--sbap-border);
      border-radius: var(--sbap-radius);
      background: #fff;
      color: var(--sbap-text);
      transition: border-color .15s;
      box-sizing: border-box;
    }
    .sbap-input:focus, .sbap-select:focus {
      outline: none;
      border-color: var(--sbap-primary);
      box-shadow: 0 0 0 3px rgba(26,86,160,.12);
    }

    .sbap-inline-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
    .sbap-inline-row .sbap-input { flex: 1; min-width: 180px; max-width: 300px; }

    .sbap-btn {
      display: inline-flex; align-items: center; justify-content: center;
      padding: 9px 20px; font-size: 14px; font-weight: 600;
      border: none; border-radius: var(--sbap-radius);
      background: var(--sbap-primary); color: #fff;
      cursor: pointer; transition: background .15s, opacity .15s; white-space: nowrap;
    }
    .sbap-btn:hover:not(:disabled) { background: var(--sbap-primary-dark); }
    .sbap-btn:disabled { opacity: .45; cursor: not-allowed; }

    .sbap-btn-ghost {
      background: transparent; color: var(--sbap-primary); border: 1px solid var(--sbap-border);
    }
    .sbap-btn-ghost:hover:not(:disabled) { background: var(--sbap-bg); border-color: var(--sbap-primary); }

    .sbap-btn-add {
      background: transparent; color: var(--sbap-primary);
      border: 1.5px dashed var(--sbap-primary); padding: 9px 20px; margin-top: 4px;
    }
    .sbap-btn-add:hover:not(:disabled) { background: rgba(26,86,160,.05); }

    .sbap-btn-link {
      background: none; border: none; color: var(--sbap-primary);
      font-size: 13px; cursor: pointer; padding: 0 4px; text-decoration: underline;
    }

    .sbap-btn-icon {
      background: none; border: none; font-size: 22px; line-height: 1;
      cursor: pointer; color: var(--sbap-muted); padding: 2px 6px;
    }
    .sbap-btn-icon:hover { color: var(--sbap-text); }

    .sbap-msg { font-size: 13px; margin-top: 6px; min-height: 18px; }
    .sbap-msg-error   { color: var(--sbap-error); }
    .sbap-msg-success { color: var(--sbap-success); }
    .sbap-msg-loading { color: var(--sbap-muted); }

    /* ⚠ v177 — WAS `display:flex; gap:8px`, AND IT BROKE ON EVERY PHONE.
       A flex container makes each child element AND each contiguous run of TEXT
       its own flex item. This notice is written as prose —
         <span>✓</span> <strong>Grade Confirmation:</strong> You selected
         <strong>Nursery 1</strong> for the <strong>2026/2027</strong> school year.
       — which is EIGHT flex items in a row that could not wrap: measured at
       375px the content ran to 371px inside a 345px box and spilled off the
       card. The 8px `gap` was also landing BETWEEN WORDS, which is why the
       spacing looked wrong even before it overflowed.

       Block, not flex. The text is prose, so let it flow and wrap like prose;
       the tick is an inline mark with a margin. All 18 uses of this class are
       prose with an optional <strong> — none holds a button or a field, so
       none needed flex in the first place. */
    .sbap-prefill-notice {
      display: block; line-height: 1.5;
      background: var(--sbap-success-bg); border: 1px solid #a3d9b8;
      border-radius: var(--sbap-radius); padding: 10px 14px;
      font-size: 14px; color: var(--sbap-success); margin-top: 12px; margin-bottom: 4px;
      overflow-wrap: break-word; /* v306 — wrap at spaces; never split a name */
    }
    .sbap-prefill-check { font-size: 16px; font-weight: 700; margin-right: 6px; }

    .sbap-notice {
      background: var(--sbap-warning-bg); border: 1px solid #ffe082;
      border-radius: var(--sbap-radius); padding: 10px 14px;
      font-size: 13px; color: #5a4000; margin-top: 10px;
    }

    .sbap-divider-or {
      display: flex; align-items: center; gap: 12px;
      color: var(--sbap-muted); font-size: 13px; margin: 20px 0;
    }
    .sbap-divider-or::before, .sbap-divider-or::after {
      content: ''; flex: 1; height: 1px; background: var(--sbap-border);
    }

    .sbap-nav { margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--sbap-border); }
    .sbap-nav-split { display: flex; justify-content: space-between; align-items: center; }

    .sbap-card-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }

    .sbap-entry-card {
      border: 1px solid var(--sbap-border); border-radius: var(--sbap-radius);
      background: var(--sbap-bg); padding: 14px 16px;
    }
    .sbap-entry-card--editing { border-color: var(--sbap-primary); background: #fff; padding: 20px 20px 16px; }

    .sbap-entry-card-head {
      display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
    }
    .sbap-entry-title {
      font-weight: 600; font-size: 15px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    }
    .sbap-entry-sub { color: var(--sbap-muted); font-size: 13px; margin-top: 3px; }
    .sbap-entry-actions { display: flex; gap: 6px; flex-shrink: 0; }

    .sbap-btn-sm { padding: 5px 12px; font-size: 13px; }

    .sbap-badge {
      display: inline-block; background: var(--sbap-primary); color: #fff;
      font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 20px;
      letter-spacing: .02em; vertical-align: middle;
    }

    .sbap-backdrop {
      position: fixed; inset: 0; background: rgba(0,0,0,.55);
      z-index: 9000; display: flex; align-items: flex-start;
      justify-content: center; padding: 20px; overflow-y: auto;
    }
    .sbap-modal {
      background: #fff; border-radius: var(--sbap-radius); width: 100%;
      max-width: 860px; display: flex; flex-direction: column;
      max-height: calc(100vh - 40px); overflow: hidden;
    }
    .sbap-modal-head {
      display: flex; align-items: center; justify-content: space-between;
      padding: 14px 20px; border-bottom: 1px solid var(--sbap-border); flex-shrink: 0;
    }
    .sbap-modal-title { font-weight: 700; font-size: 15px; }
    .sbap-modal-body { flex: 1; overflow: hidden; }
    .sbap-modal-body iframe { width: 100%; height: 70vh; border: none; display: block; }
    .sbap-modal-foot {
      padding: 14px 20px; border-top: 1px solid var(--sbap-border);
      display: flex; align-items: center; gap: 16px; flex-shrink: 0;
    }
    .sbap-modal-hint { margin: 0; font-size: 13px; }

    .sbap-form-heading {
      font-weight: 700; font-size: 16px; margin-bottom: 18px;
      padding-bottom: 10px; border-bottom: 1px solid var(--sbap-border);
    }
    .sbap-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 20px; }
    .sbap-form-section-title {
      grid-column: 1 / -1; font-weight: 700; font-size: 13px;
      text-transform: uppercase; letter-spacing: .06em; color: var(--sbap-primary);
      margin-top: 10px; padding-top: 14px; border-top: 1px solid var(--sbap-border);
    }
    .sbap-form-section-title:first-child { margin-top: 0; padding-top: 0; border-top: none; }
    .sbap-form-field { display: flex; flex-direction: column; gap: 5px; }
    .sbap-full { grid-column: 1 / -1; }

    .sbap-input, .sbap-select {
      width: 100%; padding: 9px 12px; font-size: 14px;
      border: 1px solid var(--sbap-border); border-radius: var(--sbap-radius);
      background: #fff; color: var(--sbap-text); transition: border-color .15s;
      box-sizing: border-box; max-width: 100%; min-width: 0;
    }

    .sbap-check-label { display: flex; align-items: flex-start; gap: 8px; font-size: 14px; cursor: pointer; line-height: 1.4; }
    .sbap-check-label input[type="checkbox"] { margin-top: 2px; flex-shrink: 0; width: 16px; height: 16px; cursor: pointer; }

    .sbap-form-error {
      color: var(--sbap-error); background: var(--sbap-error-bg);
      border: 1px solid #f5c6c6; border-radius: var(--sbap-radius);
      padding: 10px 14px; font-size: 13px; grid-column: 1 / -1;
    }
    .sbap-form-actions { display: flex; gap: 10px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--sbap-border); }
    .sbap-textarea { resize: vertical; min-height: 76px; font-family: inherit; line-height: 1.5; }

    .sbap-dob { display: grid; grid-template-columns: 1fr 1.3fr 0.9fr; gap: 8px; }

    .sbap-prog-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
    .sbap-prog-option { display: block; cursor: pointer; }
    .sbap-prog-option input[type="checkbox"] { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
    .sbap-prog-card {
      display: flex; align-items: center; gap: 10px; padding: 13px 14px;
      border: 2px solid var(--sbap-border); border-radius: var(--sbap-radius);
      background: #fff; font-size: 14px; font-weight: 500; cursor: pointer;
      min-height: 48px; user-select: none; transition: border-color .15s, background .15s, color .15s;
    }
    .sbap-prog-card::before {
      content: ''; width: 16px; height: 16px; min-width: 16px;
      border: 2px solid var(--sbap-border); border-radius: 3px; background: #fff;
      transition: background .15s, border-color .15s;
    }
    .sbap-prog-option input[type="checkbox"]:checked + .sbap-prog-card {
      border-color: var(--sbap-primary); background: rgba(26,86,160,.06);
      color: var(--sbap-primary); font-weight: 600;
    }
    .sbap-prog-option input[type="checkbox"]:checked + .sbap-prog-card::before {
      background: var(--sbap-primary) url("data:image/svg+xml,%3Csvg viewBox='0 0 12 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 5l3.5 3.5L11 1' stroke='white' stroke-width='2.2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 10px no-repeat;
      border-color: var(--sbap-primary);
    }
    .sbap-prog-option:hover .sbap-prog-card { border-color: var(--sbap-primary); }

    .sbap-prog-badges { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
    .sbap-prog-badge {
      display: inline-block; background: rgba(26,86,160,.08); color: var(--sbap-primary);
      border: 1px solid rgba(26,86,160,.2); font-size: 12px; font-weight: 600;
      padding: 2px 9px; border-radius: 20px;
    }

    .sbap-rel-card { border: 1px solid var(--sbap-border); border-radius: var(--sbap-radius); background: var(--sbap-card-bg); overflow: hidden; }
    .sbap-rel-card--conflict { border-color: var(--sbap-error); }
    .sbap-rel-card-head { background: var(--sbap-bg); padding: 14px 18px 12px; border-bottom: 1px solid var(--sbap-border); }
    .sbap-rel-body { padding: 16px 18px 14px; display: flex; flex-direction: column; gap: 14px; }
    .sbap-rel-pg-row { display: flex; flex-direction: column; gap: 6px; }
    .sbap-rel-pg-label { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13px; color: var(--sbap-text); }
    .sbap-req-badge { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 20px; letter-spacing: .03em; }
    .sbap-req-required { background: rgba(139,26,26,.1); color: var(--sbap-error); border: 1px solid rgba(139,26,26,.2); }
    .sbap-req-optional { background: var(--sbap-bg); color: var(--sbap-muted); border: 1px solid var(--sbap-border); }
    .sbap-rel-cg-info {
      font-size: 13px; color: var(--sbap-primary); font-weight: 500;
      padding: 5px 10px; background: rgba(26,86,160,.05); border-radius: 4px; border: 1px solid rgba(26,86,160,.15);
    }
    .sbap-rel-conflict-msg { font-size: 13px; color: var(--sbap-error); font-weight: 500; }
    .sbap-rel-card--conflict .sbap-rel-conflict-msg { display: block !important; }
    .sbap-rel-rolerel { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 2px; }

    .sbap-session-banner {
      display: flex; align-items: center; gap: 10px; background: var(--sbap-bg);
      border: 1px solid var(--sbap-border); border-radius: var(--sbap-radius);
      padding: 12px 16px; margin-bottom: 12px; flex-wrap: wrap;
    }
    .sbap-session-label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--sbap-muted); }
    .sbap-session-id { font-family: monospace; font-size: 13px; color: var(--sbap-text); word-break: break-all; }

    .sbap-review-card { border: 1px solid var(--sbap-border); border-radius: var(--sbap-radius); overflow: hidden; background: var(--sbap-card-bg); }
    .sbap-review-summary { padding: 16px 18px 14px; border-bottom: 1px solid var(--sbap-border); background: var(--sbap-bg); }
    .sbap-review-child-name { font-weight: 700; font-size: 16px; margin-bottom: 2px; }
    .sbap-review-adults { display: flex; flex-direction: column; gap: 3px; font-size: 13px; color: var(--sbap-muted); }
    .sbap-group-heading { font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--sbap-muted); margin-bottom: 8px; }
    .sbap-group-children { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 8px; font-size: 13px; color: var(--sbap-text); }
    .sbap-submit-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 0; border-top: 1px solid var(--sbap-border); flex-wrap: wrap; }
    .sbap-submit-row:first-child { border-top: none; padding-top: 4px; }
    /* min-width:200px was a floor, not a preference: inside the review card's own
   padding a 320px phone has less than 200px to give, so the row carrying the
   child's name, grade and chosen programmes pushed straight out through the
   border. min() keeps the 200px on anything wide enough and yields on a phone. */
.sbap-submit-row-info { flex: 1; min-width: min(200px, 100%); }
    .sbap-review-submit { padding: 16px 18px; display: flex; flex-direction: column; gap: 12px; }

    .sbap-submit-status { font-size: 13px; font-weight: 600; }
    .sbap-status-pending     { color: var(--sbap-muted); }
    .sbap-status-parent_done { color: #7c5a00; }
    .sbap-status-complete    { color: var(--sbap-success); }

    .sbap-submit-steps { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
    .sbap-submit-arrow { color: var(--sbap-muted); font-size: 18px; font-weight: 300; }
    .sbap-btn-submit-step { display: inline-flex; align-items: center; gap: 8px; }
    .sbap-btn-done-step { background: var(--sbap-success); cursor: default; opacity: .9; }
    .sbap-btn-pending-step { background: var(--sbap-bg); color: var(--sbap-muted); border: 1px solid var(--sbap-border); cursor: not-allowed; }

    .sbap-step-num-badge {
      display: inline-flex; align-items: center; justify-content: center;
      width: 20px; height: 20px; border-radius: 50%;
      background: rgba(255,255,255,.25); font-size: 11px; font-weight: 700; flex-shrink: 0;
    }
    .sbap-step-num-badge.sbap-done { background: rgba(255,255,255,.3); }

    .sbap-all-done-banner {
      display: flex; align-items: flex-start; gap: 16px;
      background: var(--sbap-success-bg); border: 1px solid #a3d9b8;
      border-radius: var(--sbap-radius); padding: 18px 20px; margin-top: 8px;
      font-size: 14px; color: var(--sbap-success);
    }
    .sbap-all-done-icon { font-size: 28px; line-height: 1; flex-shrink: 0; }
    .sbap-all-done-wrap { display: flex; flex-direction: column; align-items: flex-start; }
    .sbap-complete-screen { text-align: center; padding: 28px 16px 12px; }
    .sbap-complete-icon { width: 64px; height: 64px; border-radius: 50%; background: var(--sbap-success-bg); color: var(--sbap-success); font-size: 34px; line-height: 64px; margin: 0 auto 8px; }
    .sbap-complete-title { margin: 6px 0 4px; font-size: 22px; color: var(--sbap-success); }

    @media (max-width: 640px) {
      .sbap-panel { padding: 20px 16px 18px; }
      .sbap-entry-card--editing { padding: 16px 14px 12px; }
      .sbap-step-label { display: none; }
      .sbap-inline-row .sbap-input { max-width: 100%; }
      .sbap-modal-body iframe { height: 60vh; }
      /* minmax(0,1fr), NOT 1fr. A bare `1fr` is minmax(AUTO,1fr), and an auto
         minimum refuses to go below the content's min-content width — so on a
         320px phone the fields, the section titles and the selected-programme
         cards all rendered 26px wider than the card and sat outside its border.
         A zero minimum lets the column shrink and the content wrap instead. */
      .sbap-form-grid { grid-template-columns: minmax(0, 1fr); }
      .sbap-full { grid-column: 1; min-width: 0; }
      .sbap-form-section-title { grid-column: 1; min-width: 0; }
      .sbap-prog-grid { grid-template-columns: 1fr; }
      .sbap-rel-rolerel { grid-template-columns: 1fr; }
    }

/* ── shell ── */
body { margin:0; background:var(--sbap-bg); }
.ms-bar { display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  background:var(--sbap-primary); color:#fff; padding:10px 20px; position:sticky;
  /* v270 — below whatever WordPress pins at the top: #wpadminbar is fixed and
     owns 32px (46px under 783px wide). The height is MEASURED live and
     published as --mosdga-chrome-top (app.js, the v-drawer fix); 0 on the
     public page. Without this the admin bar slid over the app's own bar on
     small screens. */
  top:var(--mosdga-chrome-top,0px); z-index:150; }
/* v289 — the running version, a quiet chip beside the signed-in name */
.ms-ver { font-size:10px; font-weight:700; letter-spacing:.4px; opacity:.7;
  border:1px solid rgba(255,255,255,.35); border-radius:999px; padding:2px 8px;
  white-space:nowrap; align-self:center; }
/* v288 — the band ABOVE the masthead is masked. v286 pushed the masthead
   below the WRAPPED admin bar, which opened a strip of ordinary page between
   them — and page content scrolling under the sticky masthead showed through
   it (live: a case banner riding across the gap). The masthead now carries an
   opaque strip up to the very top, in the admin bar's own dark, so the
   wrapped toolbar row reads as part of the bar and nothing scrolls through.
   Behind the real (opaque) admin bar it is invisible; with no bar its height
   is 0. The admin bar's own z-index (99999) keeps its items clickable. */
.ms-bar::before { content:''; position:absolute; left:0; right:0; bottom:100%;
  height:var(--mosdga-chrome-top,0px); background:#1d2327; }
.ms-crest { width:32px; height:32px; border-radius:5px; background:rgba(255,255,255,.16);
  display:flex; align-items:center; justify-content:center; font-weight:700; font-size:15px; }
.ms-brand { font-weight:700; font-size:15px; line-height:1.15; }
.ms-brand span { display:block; font-weight:400; font-size:10.5px; opacity:.82;
  text-transform:uppercase; letter-spacing:.07em; }
.ms-sp { flex:1; }
/* who is signed in — replaces the demo's officer dropdown, so it reads like the
   brand block beside it rather than like a control you can change */
.ms-who { font-weight:600; font-size:13px; line-height:1.2; text-align:right; }
.ms-who span { display:block; font-weight:400; font-size:10.5px; opacity:.82;
  text-transform:uppercase; letter-spacing:.06em; }
.ms-bar a.ms-btn { text-decoration:none; }
.ms-seg { display:flex; background:rgba(255,255,255,.15); border-radius:5px; padding:3px; }
.ms-seg button { border:none; background:none; color:rgba(255,255,255,.85); font-size:13px;
  font-weight:600; padding:6px 13px; border-radius:4px; cursor:pointer; }
.ms-seg button.on { background:#fff; color:var(--sbap-primary); }
.ms-bar select, .ms-bar .ms-btn { border:1px solid rgba(255,255,255,.4); background:rgba(255,255,255,.12);
  color:#fff; border-radius:5px; padding:6px 10px; font-size:13px; cursor:pointer; }
.ms-bar select option { color:var(--sbap-text); }
.ms-wrap { max-width:1120px; margin:0 auto; padding:22px 20px 80px; }

/* workspace shell */
.ms-shell { display:grid; grid-template-columns:212px 1fr; gap:22px; align-items:start; }
.ms-nav { background:#fff; border:1px solid var(--sbap-border); border-radius:var(--sbap-radius);
  padding:10px; position:sticky; top:calc(var(--mosdga-chrome-top,0px) + 74px);
  /* the sidebar scrolls on its own when taller than the viewport, independent
     of the page scroll, so its lower items stay reachable */
  max-height:calc(100vh - var(--mosdga-chrome-top,0px) - 90px); overflow-y:auto; overscroll-behavior:contain; }
/* ⚠ THE WHEEL BELONGS TO WHATEVER IS UNDER THE POINTER.
   `.ms-nav` is a sticky column the full height of the viewport, so a pointer
   anywhere in the left 212px is over IT, not the page — and the two scrollers
   traded the wheel between them depending on which had reached its end.
   `contain` on the nav stops the nav handing off to the page; this stops the
   page handing off to the nav, and `overflow-anchor` stops the browser
   re-anchoring the page when the sticky column changes height mid-scroll,
   which is the other half of the jumpiness. */
/* ⚠ v194 — THIS RULE WAS INERT AND IS KEPT ONLY AS A WARNING.
   `overscroll-behavior` applies to SCROLL CONTAINERS. `.ms-shell` computes
   `overflow-y: visible`, so it is not one, and the declaration below never
   did anything — which is why 1.121.0 did not fix the reported problem.
   The page's scroller is the document, not this element. The real handling
   is the wheel hand-off in app.js (v194); measure before adding CSS here. */
.ms-shell { overscroll-behavior:contain; }   /* no-op: not a scroll container */
.ms-nav { overflow-anchor:none; }
.ms-nav-grp { font-size:10.5px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--sbap-muted); padding:12px 10px 5px; }
.ms-nav a { display:flex; justify-content:space-between; align-items:center; gap:8px;
  padding:7px 10px; border-radius:4px; font-size:13.5px; color:var(--sbap-text);
  cursor:pointer; text-decoration:none; }
.ms-nav a:hover { background:var(--sbap-bg); }
.ms-nav a.on { background:rgba(26,86,160,.09); color:var(--sbap-primary); font-weight:600; }
.ms-nav .n { font-size:11.5px; font-weight:700; color:var(--sbap-muted); }
/* the menu toggle: a compact ghost button on wide screens (collapses the sidebar),
   a full primary button on narrow screens (opens the stacked menu) */
.ms-burger { display:inline-flex; align-items:center; gap:8px; margin:0 0 12px; padding:6px 12px;
  background:#fff; color:var(--sbap-primary); border:1px solid var(--sbap-border);
  border-radius:var(--sbap-radius); font-size:13px; font-weight:600; cursor:pointer; }
.ms-burger:hover { background:var(--sbap-bg); }
/* wide screens: hide the sidebar on demand and let the content fill the banner width */
@media (min-width:901px){
  .ms-shell.nav-hidden{grid-template-columns:1fr}
  .ms-shell.nav-hidden .ms-nav{display:none}
}
.ms-wrap.nav-wide{max-width:none}
@media (max-width:900px){
  .ms-shell{grid-template-columns:1fr}
  /* the sidebar collapses behind a burger so it doesn't take up space when idle */
  .ms-nav{position:static; max-height:none; overflow:visible; display:none; margin-bottom:14px}
  .ms-shell.nav-open .ms-nav{display:block}
  .ms-burger{margin:0 0 12px; padding:9px 15px; background:var(--sbap-primary); color:#fff;
    border:none; font-size:14px; box-shadow:var(--sbap-shadow-sm)}
  .ms-burger:hover{background:var(--sbap-primary)}
}

/* department landing */
.ms-tiles { display:grid; grid-template-columns:repeat(auto-fill,minmax(240px,1fr)); gap:14px; }
.ms-tile { background:#fff; border:1px solid var(--sbap-border); border-radius:var(--sbap-radius);
  padding:18px; text-align:left; cursor:pointer; }
.ms-tile:hover:not(:disabled) { border-color:var(--sbap-primary); }
.ms-tile:disabled { opacity:.5; cursor:not-allowed; }
.ms-tile b { display:block; font-size:22px; color:var(--sbap-primary); }
.ms-tile h3 { margin:6px 0 4px; font-size:14px; }
.ms-tile p { margin:0; font-size:12.5px; color:var(--sbap-muted); }

/* generic blocks */
.ms-block { background:#fff; border:1px solid var(--sbap-border); border-radius:var(--sbap-radius);
  margin-bottom:18px; overflow:hidden; }
.ms-head { padding:12px 16px; border-bottom:1px solid var(--sbap-border); background:var(--sbap-bg);
  display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.ms-head h3 { margin:0; font-size:15px; font-weight:700; }
.ms-body { padding:16px; }
/* v301 — the title block anchors LEFT and every trailing control clusters
   TIGHT at the right (Ministry 2026-08-19: "inline ... not so spaced out").
   space-between spread three or more children across the full width. */
.ms-secbar { display:flex; justify-content:flex-start; align-items:flex-start; gap:10px;
  flex-wrap:wrap; margin-bottom:14px; }
.ms-secbar > div:first-child { margin-right:auto; }
.ms-secbar h2 { margin:0; font-size:21px; font-weight:700; }
.ms-eyebrow { font-size:11.5px; font-weight:700; text-transform:uppercase; letter-spacing:.07em;
  color:var(--sbap-primary); }

.ms-tw { overflow-x:auto; }
table.ms-t { width:100%; border-collapse:collapse; font-size:13.5px; }
/* ⚠⚠ v335 — THE HEADERS WERE `white-space:nowrap`, AND THAT IS WHY LISTS
   SCROLLED SIDEWAYS WITH SPACE TO SPARE (Ministry, 2026-08-20: "the case
   list now has a scroll horizontally … check the other lists too, that
   shouldn't be"). A nowrap header makes its whole phrase the column's
   minimum width: "Awaiting verification" demanded 170px, "Appointments"
   119px, and eight such columns overflowed a container that had room for
   the DATA. Headers now wrap at spaces like any other text — words stay
   whole (break-word, v306), so a two-line header is the worst case, and
   the .ms-tw scroller is left for tables that are genuinely too wide. */
/* 3.20.5 — CHIPS FOLLOW THE SAME LAW AS HEADERS (Ministry, live: "the case
   [list] has that horizontal scroll again"). v335 let headers wrap; the DATA
   cells' chips stayed nowrap, so "Assessment 2/2" or "0 linked" set hard
   column minimums and eight such columns still overflowed. Inside a table a
   chip wraps at spaces — whole words (v306), so the worst case is two short
   lines; outside tables chips keep their single line. */
table.ms-t .ms-tag { white-space:normal; }
table.ms-t th { text-align:left; font-size:11px; font-weight:700; text-transform:uppercase;
  letter-spacing:.04em; color:var(--sbap-muted); padding:9px 11px;
  border-bottom:1px solid var(--sbap-border); background:var(--sbap-bg);
  white-space:normal; overflow-wrap:break-word; }
table.ms-t td { padding:10px 11px; border-bottom:1px solid var(--sbap-border); vertical-align:top; }
table.ms-t tbody tr:last-child td { border-bottom:none; }
table.ms-t tr.klk { cursor:pointer; }
table.ms-t tr.klk:hover { background:rgba(26,86,160,.05); }
.ms-num { font-variant-numeric:tabular-nums; } .ms-r { text-align:right; }
.ms-mono { font-family:monospace; font-size:12.5px; }

.ms-tag { display:inline-block; padding:3px 9px; border-radius:20px; font-size:12px;
  font-weight:600; white-space:nowrap; }
.t-ok{background:var(--sbap-success-bg);color:var(--sbap-success)}
.t-bad{background:var(--sbap-error-bg);color:var(--sbap-error)}
.t-warn{background:var(--sbap-warning-bg);color:#7c5a00}
.t-idle{background:var(--sbap-bg);color:var(--sbap-muted);border:1px solid var(--sbap-border)}
.t-pri{background:rgba(26,86,160,.09);color:var(--sbap-primary)}
/* 3.28.0 - the stage colour law: purple = the case manager's tier is done;
   light orange = a fund request is out / the account awaits JAD */
.t-pur{background:rgba(109,40,217,.10);color:#5b21b6}
.t-org{background:rgba(234,88,12,.13);color:#c2410c}

.ms-kv { display:grid; grid-template-columns:auto 1fr; gap:7px 18px; font-size:13.5px; margin:0; }
.ms-kv dt { color:var(--sbap-muted); white-space:nowrap; }
.ms-kv dd { margin:0; font-weight:500; }

.ms-tier { border:1px solid var(--sbap-border); border-radius:var(--sbap-radius);
  padding:13px 15px; margin-bottom:10px; background:#fff; }
.ms-tier--done { border-color:var(--sbap-success); background:var(--sbap-success-bg); }
.ms-tier--lock { opacity:.58; background:var(--sbap-bg); }
.ms-tier b { font-size:14.5px; }

.row { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.ms-tog { display:inline-block; padding:7px 14px; border:1px solid var(--sbap-border);
  border-radius:20px; font-size:13px; margin:0 6px 6px 0; cursor:pointer; background:#fff; }
.ms-tog.on { background:rgba(26,86,160,.08); border-color:var(--sbap-primary);
  color:var(--sbap-primary); font-weight:600; }

/* wizard rail */
/* 3.20.8 — TABS WRAP, THE PAGE DOES NOT SCROLL (Ministry: "you can have two
   rows of tabs in administration addressing to avoid having a horizontal
   scroll"). One shared strip serves the wizards and the addressing shell, so
   every strip gains the second row instead of the scroller. */
.ms-wiz { display:flex; flex-wrap:wrap; gap:0; border-bottom:1px solid var(--sbap-border);
  margin-bottom:16px; }
.ms-wiz button { border:none; background:none; padding:10px 16px; font-size:13.5px;
  color:var(--sbap-muted); cursor:pointer; border-bottom:2px solid transparent; white-space:nowrap; }
.ms-wiz button.on { color:var(--sbap-primary); font-weight:700; border-bottom-color:var(--sbap-primary); }
.ms-wiz button.done { color:var(--sbap-success); }

/* linked-record suggestions */
.ms-sugg { border:1px dashed var(--sbap-primary); background:rgba(26,86,160,.04);
  border-radius:var(--sbap-radius); padding:13px 15px; margin-bottom:14px; }
.ms-sugg h4 { margin:0 0 4px; font-size:14px; color:var(--sbap-primary); }
.ms-sugg p { margin:0 0 10px; font-size:13px; color:var(--sbap-muted); }
.ms-pick { display:flex; align-items:center; justify-content:space-between; gap:12px;
  background:#fff; border:1px solid var(--sbap-border); border-radius:var(--sbap-radius);
  padding:10px 13px; margin-bottom:8px; flex-wrap:wrap; }
.ms-pick div b { font-size:14px; } .ms-pick div span { font-size:12.5px; color:var(--sbap-muted); }

.ms-mail { position:fixed; right:14px; bottom:14px; width:290px; background:#fff;
  border:1px solid #ffe082; border-radius:var(--sbap-radius); box-shadow:0 6px 22px rgba(0,0,0,.15);
  z-index:250; font-size:13px; overflow:hidden; }
.ms-mail h4 { margin:0; padding:9px 12px; background:var(--sbap-warning-bg); color:#5a4000;
  font-size:11px; text-transform:uppercase; letter-spacing:.06em; }
.ms-mail div { padding:12px; }
.ms-code { font-family:monospace; font-size:22px; font-weight:700; letter-spacing:.16em; color:var(--sbap-primary); }
.ms-toast { position:fixed; bottom:18px; left:50%; transform:translateX(-50%); background:var(--sbap-text);
  color:#fff; padding:10px 18px; border-radius:5px; font-size:14px; z-index:300; opacity:0;
  pointer-events:none; transition:opacity .18s; max-width:90vw; }
.ms-toast.show { opacity:1; }
/* ── v70: typed, stacked toasts (top-right) + on-item banners ── */
/* BELOW the ministry bar, not over it.
   The bar is sticky at top:0; the toasts were fixed at top:16px, so a
   notification sat on top of the branding — and on a phone, where the bar wraps
   onto two lines and is taller, it covered it outright. --ms-bar-h is written
   from the bar's real height after each render (see app.js), because a wrapping
   header has no height CSS can know in advance; the fallback covers the moment
   before the first measurement. */
.ms-toasts { position:fixed; top:calc(var(--mosdga-chrome-top,0px) + var(--ms-bar-h, 56px) + 12px); right:16px; z-index:600;
  display:flex; flex-direction:column;
  gap:8px; width:min(340px,92vw); pointer-events:none; }
.ms-tst { display:flex; gap:10px; align-items:flex-start; background:var(--sbap-card-bg); color:var(--sbap-text);
  border:1px solid var(--sbap-border); border-left:4px solid var(--sbap-muted); border-radius:10px;
  padding:10px 12px; box-shadow:var(--sbap-shadow-lg); font-size:13px; line-height:1.35;
  pointer-events:auto; cursor:pointer; opacity:0; transform:translateX(14px);
  transition:opacity .2s ease, transform .2s ease; }
.ms-tst.show { opacity:1; transform:translateX(0); }
.ms-tst.hide { opacity:0; transform:translateX(14px); }
.ms-tst .ti { font-size:15px; flex:0 0 auto; margin-top:1px; }
.ms-tst .tb { flex:1; min-width:0; word-wrap:break-word; }
.ms-tst .tk { display:block; font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  color:var(--sbap-muted); margin-bottom:2px; }
.ms-tst.k-success { border-left-color:var(--sbap-success); }
.ms-tst.k-warn    { border-left-color:#b45309; }
.ms-tst.k-dup     { border-left-color:#c2410c; }
.ms-tst.k-verify  { border-left-color:var(--sbap-primary); }
.ms-tst.k-note    { border-left-color:#6d28d9; }
.ms-tst.k-info    { border-left-color:var(--sbap-primary); }
@media (max-width:720px){ .ms-toasts { left:12px; right:12px; width:auto; } }
.ms-ibanners { display:flex; flex-direction:column; gap:8px; margin:0 0 14px; }
.ms-ibn { display:flex; gap:10px; align-items:flex-start; background:var(--sbap-card-bg);
  border:1px solid var(--sbap-border); border-left:4px solid var(--sbap-muted); border-radius:10px;
  padding:10px 12px; font-size:13px; line-height:1.4; }
.ms-ibn .bi { font-size:15px; flex:0 0 auto; margin-top:1px; }
.ms-ibn .bb { flex:1; min-width:0; }
.ms-ibn .bk { display:block; font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  color:var(--sbap-muted); margin-bottom:1px; }
.ms-ibn a { color:var(--sbap-primary); cursor:pointer; font-weight:600; text-decoration:none; }
.ms-ibn a:hover { text-decoration:underline; }
.ms-ibn.k-warn   { border-left-color:#b45309; }
.ms-ibn.k-dup    { border-left-color:#c2410c; }
.ms-ibn.k-verify { border-left-color:var(--sbap-primary); }
.ms-ibn.k-info   { border-left-color:var(--sbap-primary); }
.ms-ibn.k-success{ border-left-color:var(--sbap-success); }
/* minmax(0,1fr), not 1fr — this block comes AFTER the 640px one and was
   quietly undoing it. `1fr` means minmax(AUTO,1fr), and an auto minimum will
   not shrink below the content's min-content width, so on a narrow phone the
   single column measured wider than the card and every field, section title
   and selected-programme card sat outside the border. */
@media (max-width:720px){ .sbap-form-grid,.sbap-prog-grid,.sbap-rel-rolerel{grid-template-columns:minmax(0,1fr)} }
/* ── Appointments calendar (per the Appointment MXD and appointments.tsx layout) ── */
.ap-grid { display:grid; grid-template-columns:minmax(0,1fr) 420px; gap:18px; align-items:start; }
@media (max-width:900px){ .ap-grid{grid-template-columns:1fr} }
.cal-grid { display:grid; grid-template-columns:repeat(7,1fr); gap:4px; }
.cal-dow { text-align:center; font-size:11px; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--sbap-muted); padding:4px 0; }
.cal-cell { position:relative; text-align:center; padding:10px 0 14px; border-radius:var(--sbap-radius);
  font-size:14px; cursor:pointer; border:1px solid transparent; }
.cal-cell:hover:not(.cal-empty) { background:var(--sbap-bg); }
.cal-empty { cursor:default; }
.cal-on { background:var(--sbap-primary) !important; color:#fff; font-weight:700; }
.cal-has { border-color:var(--sbap-border); }
.cal-dot { position:absolute; left:50%; bottom:5px; transform:translateX(-50%);
  width:5px; height:5px; border-radius:50%; background:var(--sbap-primary); }
.cal-on .cal-dot { background:#fff; }

/* proof image thumbnails */
.proof-thumb { height:34px; max-width:70px; object-fit:cover; border:1px solid var(--sbap-border);
  border-radius:4px; cursor:pointer; vertical-align:middle; }
.proof-thumb:hover { border-color:var(--sbap-primary); }
/* v139 — a photograph the server still holds. Same footprint as the real
   thumbnail so a row does not shift when the image arrives. */
.proof-thumb--pending { display:inline-flex; align-items:center; justify-content:center;
  width:44px; height:34px; font-size:15px; background:var(--sbap-surface-2,#f1f5f9);
  border-style:dashed; color:var(--sbap-muted,#64748b); }
.proof-thumb--pending:hover { border-color:var(--sbap-primary); }

/* ═══════════════════════════════════════════════════════════════════
   v2.0 — UI/UX modernization layer. Applies the design tokens above for
   refined elevation, typography, focus states, purposeful motion, and
   responsive + accessibility polish. Layered LAST so it refines the base
   styles without touching the markup or any business logic. Motion is
   deliberately restrained: the app re-renders wholesale on every action,
   so broad entrance animation would flicker — instead motion is reserved
   for genuine appear/disappear (drawers, toasts) and direct interaction.
   ═══════════════════════════════════════════════════════════════════ */
body, #sbap-app, .ms-wrap {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}
body { background: var(--sbap-bg); color: var(--sbap-text); }

/* top bar — quiet depth */
.ms-bar { background: linear-gradient(180deg, var(--sbap-primary), var(--sbap-primary-dark));
  box-shadow: var(--sbap-shadow-md); }

/* sidebar — soft lift, an accent bar marks the active page (not colour alone) */
.ms-nav { box-shadow: var(--sbap-shadow-sm); }
.ms-nav a { position: relative;
  transition: background var(--sbap-dur-fast) var(--sbap-ease), color var(--sbap-dur-fast) var(--sbap-ease); }
.ms-nav a.on::before { content:''; position:absolute; left:0; top:6px; bottom:6px; width:3px;
  border-radius:0 3px 3px 0; background: var(--sbap-primary); }

/* cards / panels — subtle elevation instead of heavy borders */
.ms-block, .sbap-panel, .ms-tile, .ms-sugg, .sbap-rel-card, .sbap-review-card {
  box-shadow: var(--sbap-shadow-sm);
  transition: box-shadow var(--sbap-dur) var(--sbap-ease),
    transform var(--sbap-dur) var(--sbap-ease), border-color var(--sbap-dur-fast) var(--sbap-ease);
}
.ms-tile { cursor: pointer; }
.ms-tile:hover:not(:disabled) { box-shadow: var(--sbap-shadow-md); transform: translateY(-2px); }

/* buttons — press feedback + hover lift */
.sbap-btn { box-shadow: var(--sbap-shadow-sm);
  transition: background var(--sbap-dur-fast) var(--sbap-ease),
    transform var(--sbap-dur-fast) var(--sbap-ease), box-shadow var(--sbap-dur-fast) var(--sbap-ease); }
.sbap-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--sbap-shadow-md); }
.sbap-btn:active:not(:disabled) { transform: translateY(0); box-shadow: var(--sbap-shadow-sm); }
.sbap-btn-ghost, .sbap-btn-add, .sbap-btn-link, .sbap-btn-icon, .sbap-btn-sm { box-shadow: none; }
.sbap-btn-sm:hover:not(:disabled) { box-shadow: none; }

/* visible keyboard focus on every real focus target */
.sbap-btn:focus-visible, .sbap-btn-ghost:focus-visible, .sbap-btn-sm:focus-visible,
.sbap-input:focus-visible, .sbap-select:focus-visible, .sbap-textarea:focus-visible,
.ms-nav a:focus-visible, .ms-wiz button:focus-visible, .ms-tog:focus-visible,
.ms-seg button:focus-visible, .sbap-prog-card:focus-visible {
  outline: 2px solid var(--sbap-primary); outline-offset: 2px; border-radius: var(--sbap-radius-sm);
}

/* inputs — smoother, slightly stronger focus ring */
.sbap-input, .sbap-select { transition: border-color var(--sbap-dur-fast) var(--sbap-ease),
    box-shadow var(--sbap-dur-fast) var(--sbap-ease); }
.sbap-input:focus, .sbap-select:focus { box-shadow: 0 0 0 3px rgba(26,86,160,.14); }

/* searchable dropdowns — a filter input overlaying each long <select> */
/* max-width matters as much as the width ssEnhance() sets.
   The inline branch (a select carrying width:auto, or one sitting in a .row —
   the day/month/year pickers) is given NO width, so the wrapper sizes to the
   input's natural width: wide enough for "September", which is 214px and 26px
   past the edge of a 320px phone's card. A cap costs nothing on a wide screen
   and is the difference between fitting and spilling on a narrow one. */
.ss-wrap { vertical-align: middle; max-width: 100%; }
.ss-input { max-width: 100%; }

/* Inside a .row the wrapper is a FLEX ITEM, and max-width:100% resolves against
   the row — so two of them (month + year on the school-enrolment picker, the
   grade selectors) could each be 100% and together overrun the right edge.
   A flex item needs a zero basis and min-width:0 to be allowed to shrink. */
.row > .ss-wrap { flex: 1 1 0; min-width: 0; }

/* Long programme names have nowhere to break inside a flex card, so the card
   grew past the grid column instead of wrapping. */
.sbap-prog-card { min-width: 0; overflow-wrap: break-word; } /* v306 */

/* ── the field a validation message is about ────────────────────────────────
   A toast names the problem and then vanishes, leaving the applicant to find
   the field it meant. This marks it, and clears the moment they type. */
.sbap-bad input, .sbap-bad select, .sbap-bad .sbap-input, .sbap-bad .sbap-select,
input.sbap-bad, select.sbap-bad, .sbap-bad .ss-input {
  border-color: #b91c1c !important;
  box-shadow: 0 0 0 3px rgba(185, 28, 28, .14);
}
.sbap-bad > label, .sbap-bad .sbap-field-label { color: #b91c1c; }
.ss-input { cursor: text; background-image: linear-gradient(45deg, transparent 50%, var(--sbap-muted) 50%),
    linear-gradient(135deg, var(--sbap-muted) 50%, transparent 50%);
  background-position: calc(100% - 15px) calc(1em + 1px), calc(100% - 10px) calc(1em + 1px);
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 30px; }
.ss-list { position: absolute; z-index: 205; top: 100%; left: 0; min-width: 100%; max-width: 380px;
  max-height: 260px; overflow-y: auto; margin-top: 3px; display: none;
  background: var(--sbap-card-bg, #fff); border: 1px solid var(--sbap-border);
  border-radius: var(--sbap-radius); box-shadow: var(--sbap-shadow-md); }
.ss-opt { padding: 8px 12px; font-size: 14px; cursor: pointer;
  white-space: normal; word-break: break-word; line-height: 1.35; }
.ss-opt:hover, .ss-opt.on { background: rgba(26,86,160,.10); color: var(--sbap-primary); }
/* long measurement paths in the criteria builder wrap (and carry a full-text tooltip) */
.crit-path { white-space: normal; word-break: break-word; line-height: 1.35; max-width: 320px; }

/* tables, wizard tabs, toggles — ease their state changes */
table.ms-t tbody tr { transition: background var(--sbap-dur-fast) var(--sbap-ease); }
.ms-wiz button { transition: color var(--sbap-dur-fast) var(--sbap-ease),
    border-color var(--sbap-dur-fast) var(--sbap-ease); }
.ms-tog { transition: background var(--sbap-dur-fast) var(--sbap-ease),
    border-color var(--sbap-dur-fast) var(--sbap-ease), color var(--sbap-dur-fast) var(--sbap-ease); }

/* toast — slides up as it fades in */
.ms-toast { box-shadow: var(--sbap-shadow-lg); border-radius: 8px;
  transform: translateX(-50%) translateY(10px);
  transition: opacity var(--sbap-dur) var(--sbap-ease), transform var(--sbap-dur) var(--sbap-ease); }
.ms-toast.show { transform: translateX(-50%) translateY(0); }

/* slideouts (criteria editor, beneficiary services, record edit) — animated entrance +
   backdrop fade. z-index must clear the sticky top bar (150) and page header so the
   drawer covers them; kept below the toast (300) and modal (400). */
/* THE DRAWER MUST START BELOW WHATEVER IS PINNED ABOVE IT.
   The markup sets `top:0`, which is right on a bare page and wrong on a
   logged-in WordPress one: #wpadminbar is itself position:fixed over the top
   32px (46px under 783px wide), so the drawer's header slid underneath it and
   the Close button ended up half off the screen. WordPress moves the DOCUMENT
   down with `html{margin-top:32px}`, which does nothing for a fixed element.
   `--mosdga-chrome-top` is measured at runtime (v121) rather than assumed,
   because the variable WordPress sets is not present on every version, and a
   theme may pin a header of its own. Falls back to 0 — i.e. today's
   behaviour — when there is nothing above. */
.crit-scrim { z-index: 200 !important; animation: sbap-fade var(--sbap-dur) var(--sbap-ease) both;
  top: var(--mosdga-chrome-top, 0px) !important; }
.crit-drawer { z-index: 201 !important; box-shadow: var(--sbap-shadow-lg);
  border-top-left-radius: var(--sbap-radius-lg); border-bottom-left-radius: var(--sbap-radius-lg);
  animation: sbap-slidein var(--sbap-dur-slow) var(--sbap-ease) both;
  top: var(--mosdga-chrome-top, 0px) !important; }
@keyframes sbap-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes sbap-slidein { from { transform: translateX(28px); opacity: .3; } to { transform: none; opacity: 1; } }
/* left-anchored drawer (the Location Builder slideout opens from the opposite side) */
.crit-drawer-left { border-top-left-radius: 0; border-bottom-left-radius: 0;
  border-top-right-radius: var(--sbap-radius-lg); border-bottom-right-radius: var(--sbap-radius-lg);
  animation: sbap-slideinleft var(--sbap-dur-slow) var(--sbap-ease) both; }
@keyframes sbap-slideinleft { from { transform: translateX(-28px); opacity: .3; } to { transform: none; opacity: 1; } }

/* headings breathe a little with the viewport */
.ms-secbar h2 { font-size: clamp(19px, 1rem + 1vw, 23px); letter-spacing: -.01em; }
.sbap-panel h2 { letter-spacing: -.01em; }

/* responsive: roomier tap targets and tighter gutters on small screens */
@media (max-width: 720px) {
  .ms-wrap { padding: 16px 14px 72px; }
  .ms-bar { padding: 9px 14px; }
  .sbap-btn { padding: 10px 18px; }
  .ms-nav a { padding: 9px 10px; }
  .ms-head { padding: 11px 14px; }
  .ms-body { padding: 14px; }
}

/* honour a reduced-motion preference — strip every transition and animation */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}

/* ── v270: NOTHING PUSHES THE PAGE SIDEWAYS ─────────────────────────────
   Long unbroken tokens — uuids in older notification texts, raw vendor
   replies, references — must wrap where they stand instead of widening
   the page (the reported right-side overrun). Two mechanics:
   1. flex/grid children default to min-width:auto, which lets one long
      token widen a whole row — min-width:0 restores the right to shrink;
   2. overflow-wrap:anywhere lets a token break mid-string when there is
      no other way. Wide TABLES keep their own scroller (.ms-tw
      overflow-x:auto) — the page body itself never scrolls sideways,
      which `overflow-x:clip` on the wrap enforces as the backstop. */
.ms-wrap { overflow-x: clip; }
.ms-shell > * { min-width: 0; }
.ms-ibanners { max-width: 100%; }
.ms-ibn { min-width: 0; }
/* v306 — WORDS WRAP WHOLE. `anywhere` counts the mid-word break in
   min-content sizing, so table columns squeezed below word width and split
   names letter-by-letter ("Stephan Jose / ph" — Ministry 2026-08-19).
   `break-word` wraps at spaces first and keeps whole-word minimums; a long
   unbroken token still breaks rather than widening the page, and a table
   whose columns no longer fit scrolls inside .ms-tw exactly as v270/v271
   intended. Numbers and money never split across lines at all. */
.ms-ibn .bb { min-width: 0; overflow-wrap: break-word; }
.ms-head > * { min-width: 0; }
.ms-kv dd, .sbap-entry-sub, .ms-mono { overflow-wrap: break-word; }
.ms-body { overflow-wrap: break-word; }
.ms-t td, .ms-t th { overflow-wrap: break-word; }
.ms-num { white-space: nowrap; }
/* v271 — TEXT MAY WRAP; CONTROLS MAY NOT CRUSH. Letting cells wrap anywhere
   (above) removed the width the table used to demand, so at narrow widths
   every column compressed to minimum and a <select> shrank to a sliver —
   its label stacking one letter per line. A control keeps a working
   minimum; when those minimums no longer fit, the TABLE scrolls inside
   .ms-tw, which is exactly what that wrapper exists for. */
.ms-t td .sbap-select, .ms-t td select { min-width: 140px; }
.ms-t td .sbap-input,  .ms-t td input[type="text"] { min-width: 140px; }
.ms-t td .sbap-btn { white-space: nowrap; }

/* ── v272: the Education follow-ups worklist as CARDS ───────────────────
   No columns, no sideways scroll — each call is a block whose rows WRAP.
   Dealt-with cards fade but stay visible (dealt-but-still-failing is a
   fact, not a secret). */
.ef-card { border:1px solid var(--sbap-border); border-radius:8px;
  padding:10px 12px; margin-bottom:10px; background:var(--sbap-card-bg); }
.ef-card.ef-done { opacity:.62; }
.ef-top, .ef-mid, .ef-act { display:flex; align-items:center; gap:10px;
  flex-wrap:wrap; min-width:0; }
.ef-mid { margin-top:6px; }
.ef-act { margin-top:8px; }
.ef-kid { font-weight:700; color:var(--sbap-primary); cursor:pointer; }
.ef-case { color:var(--sbap-primary); cursor:pointer; font-size:12px; }
.ef-school { color:var(--sbap-muted); font-size:12.5px; }
.ef-phone { font-weight:600; letter-spacing:.02em; }
.ef-top .sbap-select { min-width:170px; }
.ef-note { flex:1 1 220px; min-width:180px; }
/* the searchable-select enhancer (.ss-wrap) replaces the native select and
   pins itself inline at width:100% — full-row in a card, a sliver in a
   crushed cell. Contain it: a fixed, comfortable trigger in the card row,
   and a working minimum inside any table cell. !important because the
   widget's width is an inline style. */
/* v273 — filter-pill rows (stage/programme chips and kin) cluster to their
   content instead of spanning the page; reusable on any future pill band */
.ms-chiprow { max-width: fit-content; }
.ef-top .ss-wrap { width:190px !important; flex:0 0 auto; }
.ef-top .ss-wrap .ss-input { width:100% !important; min-width:0 !important; }
.ms-t td .ss-wrap { width:160px !important; min-width:160px; }
.ms-t td .ss-wrap .ss-input { width:100% !important; }


/* ═══ v298 — the case notification bell + overlay panel ═══
   The bell floats fixed at top-right, measured under the real masthead by
   bindMsn (same measured-chrome discipline as the stickies). The panel is a
   page within a page: fixed scrim + fixed panel, the page beneath untouched.
   ⚠⚠ v346 — THE BELL NO LONGER SITS ON TOP OF SLIDEOUTS. This line used to
   read "above drawers/slideouts (60–202)", and it meant it: at 210 the bell
   cleared the drawer scrim (200) and the drawer itself (201), so opening any
   slideout left the button floating over it (Ministry, 2026-08-21). That was
   a deliberate choice once and it was the wrong one — a drawer is modal, its
   scrim dims the page precisely to say "finish this first", and a control
   riding above it invites a click that the scrim then swallows.
   It now sits at 190: clear of the sticky bar (150) and the page, under the
   scrim (200). Toasts stay at 300 — a message about what just happened SHOULD
   reach you through a drawer — and the bell's own panel keeps its own scrim
   at 378/380, so opening the bell still covers everything.
   z-order now: page < bell (190) < drawer scrim/drawer (200/201) < toast (300)
   < bell panel (378/380) < modal() at 400. */
.msn-bell{position:fixed;right:14px;top:120px;z-index:190;width:40px;height:40px;
  border-radius:999px;border:1px solid var(--sbap-border,#d5dbe3);
  background:var(--sbap-card,#fff);color:var(--sbap-ink,#16324f);
  box-shadow:0 3px 10px rgba(15,23,42,.18);cursor:pointer;
  display:flex;align-items:center;justify-content:center;padding:0}
.msn-bell:hover{box-shadow:0 5px 14px rgba(15,23,42,.28)}
.msn-bell svg{width:20px;height:20px;display:block}
.msn-badge{position:absolute;top:-4px;right:-4px;min-width:18px;height:18px;
  border-radius:999px;background:#c2362b;color:#fff;
  font:700 11px/18px system-ui,sans-serif;text-align:center;padding:0 4px}
.msn-scrim{position:fixed;inset:0;background:rgba(15,23,42,.35);z-index:378}
.msn-panel{position:fixed;right:12px;top:168px;z-index:380;
  width:min(440px,calc(100vw - 24px));max-height:min(64vh,560px);overflow:auto;
  background:var(--sbap-card,#fff);border:1px solid var(--sbap-border,#d5dbe3);
  border-radius:12px;box-shadow:0 12px 34px rgba(15,23,42,.3)}
.msn-ph{display:flex;gap:8px;align-items:center;padding:10px 12px;
  border-bottom:1px solid var(--sbap-border,#d5dbe3);
  position:sticky;top:0;background:var(--sbap-card,#fff);z-index:1}
.msn-row{display:flex;gap:8px;align-items:flex-start;padding:10px 12px;
  border-bottom:1px solid var(--sbap-border,#d5dbe3);flex-wrap:wrap}
.msn-row.is-clr{opacity:.62}
.msn-txt{flex:1;min-width:200px}
.msn-histbar{padding:9px 12px;cursor:pointer;font-weight:600;
  color:var(--sbap-primary,#0b3a75);border-bottom:1px solid var(--sbap-border,#d5dbe3)}
.msn-histbar:hover{background:rgba(11,58,117,.06)}

/* ═══ v318 — the case strip: District / Appointments / Community as
   named controls carrying their own status chips; each opens a
   bell-style overlay holding the full panel (supersedes the v303/v307
   two-column block). ═══ */
.ms-vpo-strip{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 14px}
.ms-vpo-btn{display:flex;align-items:center;gap:7px;padding:8px 12px;
  background:var(--sbap-card,#fff);border:1px solid var(--sbap-border,#d5dbe3);
  border-radius:10px;cursor:pointer;font:600 13.5px/1 system-ui,sans-serif;
  color:var(--sbap-ink,#16324f);box-shadow:0 1px 4px rgba(15,23,42,.06)}
.ms-vpo-btn:hover{box-shadow:0 3px 9px rgba(15,23,42,.14)}
.ms-vpo-btn.on{border-color:var(--sbap-primary,#0b3a75);
  box-shadow:0 0 0 2px rgba(11,58,117,.15)}
.ms-vpo-name{margin-right:2px}
.ms-vpo-wrap{display:none}
.ms-vpo-wrap.on{display:block}
.ms-vpo-panel{width:min(640px,calc(100vw - 24px));max-height:78vh;
  top:calc(var(--mosdga-chrome-top,0px) + 110px)}
.ms-vpo-panel .ms-block{margin:0;border:0;border-radius:0}
.ms-vpo-panel .ms-head{position:static}

/* v328 — the order / date-range bar that sits above a paged list */
.ms-lsbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:0 0 10px}
.ms-lsbar .sbap-input[type="date"]{max-width:158px;padding:6px 8px;font-size:13px}
.ms-lsbar .ms-sp{flex:0 0 6px}
/* v334 — the range dropdown, in the notification panel's manner */
.ms-lsdd-panel{width:min(380px,calc(100vw - 24px));
  top:calc(var(--mosdga-chrome-top,0px) + 150px)}
.ms-lsdd-panel .ms-body{padding:14px 16px}

/* v327 — a dense stats table: tighter cells, and a name column with a
   working minimum so it never collapses to one word per line */
.ms-t-tight th, .ms-t-tight td { padding-left:8px; padding-right:8px; }
.ms-t-tight tbody td:first-child, .ms-t-tight thead th:first-child { min-width:150px; }

/* v322 — the JAD reply, contained: wraps, scrolls past 220px, never
   pushes the drawer sideways */
.jad-raw{white-space:pre-wrap;overflow-wrap:break-word;font-size:12px;
  margin:6px 0 0;max-height:220px;overflow:auto}

/* v319 — the ← Back / bell column at the case header's right edge.
   The badge overhangs the bell by 4px; docked at the page's right edge
   that overhang became a 4px sideways scroll — the padding absorbs it. */
.ms-backcol{display:flex;flex-direction:column;gap:8px;align-items:flex-end;
  padding-right:4px}
/* ⚠ RELATIVE, NOT STATIC. The badge is absolutely positioned against the
   bell; a static bell is not a containing block, so the badge escaped to
   the page's own top-right corner — a red count floating above the
   masthead with an empty bell below it (Ministry, 2026-08-20). */
/* ⚠ v346 — and the DOCKED bell drops its z-index entirely. It is inline in
   the column under ← Back, so it needs no stacking order of its own; keeping
   210 here made `position:relative` create a stacking context that still
   painted above a drawer, which is how the docked bell floated over slideouts
   on the case screen even though it is not fixed. `auto` lets it be covered
   like any other part of the page. */
.ms-backcol .msn-bell{position:relative;top:auto;right:auto;z-index:auto}
.ms-backcol .msn-badge{right:0;top:-3px}  /* docked: no overhang past the page edge */

/* ═══ v316 — the CDSS boot splash: full-viewport, paints with the shell,
   fades once the register and rules have landed ═══ */
#ms-splash{position:fixed;inset:0;z-index:999;background:#fff;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:10px;text-align:center;padding:24px;
  opacity:1;transition:opacity .45s ease}
#ms-splash.ms-splash-out{opacity:0;pointer-events:none}
.ms-splash-logo{max-width:min(240px,55vw);height:auto}
/* v342 — the TEXT mark is the fallback for a missing logo, not a second
   masthead beside it. It sits in its own centred column so the fallback keeps
   the layout the splash had before, and ⚠ the [hidden] rule is REQUIRED: a
   class setting display:flex outranks the browser's own rule for the hidden
   attribute, so without it the thing this fixes would simply come back. */
.ms-splash-mark{display:flex;flex-direction:column;align-items:center;gap:10px}
.ms-splash-mark[hidden]{display:none}
.ms-splash-name{font:400 17px/1.35 system-ui,sans-serif;color:#1d2327;letter-spacing:.04em}
.ms-splash-name strong{font-weight:800;font-size:21px;letter-spacing:.01em}
.ms-splash-rule{width:min(300px,70vw);height:3px;background:#c81e1e;border-radius:2px;margin-top:4px}
.ms-splash-tag{font:400 14px/1.3 system-ui,sans-serif;color:#3c434a}
.ms-splash-bar{width:min(220px,60vw);height:4px;border-radius:999px;background:#e8ebef;
  overflow:hidden;margin-top:18px}
.ms-splash-bar span{display:block;width:40%;height:100%;border-radius:999px;background:#c81e1e;
  animation:ms-splash-slide 1.15s ease-in-out infinite}
@keyframes ms-splash-slide{0%{margin-left:-40%}100%{margin-left:100%}}
.ms-splash-status{font:400 12.5px/1.3 system-ui,sans-serif;color:#5b6675;min-height:16px}
@media (prefers-reduced-motion:reduce){.ms-splash-bar span{animation:none;width:100%}}

/* ═══ v313 — the split stage chip: white text over the proportional
   outcome gradient; the segment hues are the palette's own darks ═══ */
.ms-tag.ms-mix{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.55);border:0;
  white-space:nowrap}

/* ═══ v304/v305 — the "first 3, then Show more" preview bar ═══ */
.ms-showmore{padding:9px 16px;cursor:pointer;font-weight:600;font-size:13px;
  color:var(--sbap-primary,#0b3a75);border-top:1px solid var(--sbap-border,#d5dbe3)}
.ms-showmore:hover{background:rgba(11,58,117,.06)}

/* 3.25.0 - the Ministry: numeric columns center under their heading; cells that only right-align actions (ms-r without ms-num) keep right. */
table.ms-t th.ms-r { text-align:center; }
table.ms-t td.ms-r.ms-num { text-align:center; }
