  body { margin: 0; background: #000; color: #e8e8e8; font-family: 'Montserrat', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
  main.sa-app { padding: 24px 28px 40px; max-width: 1480px; margin: 0 auto; }
  .roster-split-head { margin-bottom: 14px; }
  .roster-split-head h1 { margin: 0 0 6px; font-size: 28px; font-weight: 900; letter-spacing: -0.02em; color: #fff; }
  .roster-split-head .sub { margin: 0; font-size: 12px; color: #aaa; }

  /* Two independently-scrollable panes (Brett 2026-05-02 PM).
     Each .sa-col gets its own overflow-y: auto inside a fixed-
     height grid, so triaging registrations on the left doesn't
     drag the roster on the right. Col-head sticks to the top of
     each pane so context never scrolls off. Total chrome budget:
     site-nav (~46) + topbar (~56) + page padding (~20) +
     roster-head (~70) ≈ 195 px. */
  .roster-split-pane-host { height: calc(100vh - 200px); min-height: 480px; overflow: hidden; }
  .roster-split-pane-host .roster-split { height: 100%; }
  .roster-split-pane-host .sa-col {
    height: 100%;
    overflow-y: auto;
    padding-right: 6px;
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.18) transparent;
  }
  .roster-split-pane-host .sa-col::-webkit-scrollbar { width: 8px; }
  .roster-split-pane-host .sa-col::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.16); border-radius: 4px; }
  .roster-split-pane-host .sa-col-head {
    position: sticky;
    top: 0;
    background: #000;
    padding: 8px 0 12px;
    z-index: 5;
    border-bottom: 1px solid #161616;
    margin-bottom: 12px;
  }
  .roster-split { display: grid; grid-template-columns: minmax(320px, 1fr) minmax(320px, 1fr); gap: 18px; align-items: start; }
  @media (max-width: 900px) { .roster-split { grid-template-columns: 1fr; } }
  .sa-col { min-width: 0; }
  .sa-col-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 14px; gap: 12px; }
  .sa-col-head h2 { margin: 0; font-size: 12px; font-weight: 900; letter-spacing: 0.22em; text-transform: uppercase; color: #FF0000; }
  .sa-col-head .count { font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: #888; }
  .sa-stack { display: flex; flex-direction: column; gap: 10px; }

  .reg-card { background: #101010; border: 1px solid #1a1a1a; border-left: 3px solid #FF0000; border-radius: 6px; padding: 14px 16px; display: grid; grid-template-columns: 1fr auto; gap: 8px 16px; }
  .reg-head { display: flex; gap: 10px; align-items: center; margin-bottom: 6px; flex-wrap: wrap; }
  .reg-name { font-size: 15px; font-weight: 800; margin: 0; }
  .reg-meta { font-size: 12px; color: #aaa; line-height: 1.5; }
  .reg-side { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
  .reg-when { font-size: 10px; color: #777; letter-spacing: 0.12em; text-transform: uppercase; }
  .reg-type { font-size: 10px; color: #777; letter-spacing: 0.12em; text-transform: uppercase; }

  .roster-row-list { display: flex; flex-direction: column; gap: 6px; }
  .roster-row { display: grid; grid-template-columns: 96px 116px auto 40px 1fr; gap: 10px; padding: 12px 14px; background: rgba(255,255,255,0.02); border: 1px solid transparent; border-radius: 6px; text-decoration: none; color: inherit; align-items: center; transition: background 120ms, border-color 120ms, transform 120ms; }
  .roster-row { cursor: pointer; }
  .roster-row:hover { background: rgba(255,0,0,0.06); border-color: rgba(255,0,0,0.25); text-decoration: none; transform: translateX(2px); }
  .roster-row.is-active { background: rgba(255,0,0,0.08); border-color: rgba(255,0,0,0.45); }
  .roster-row .rr-num { font-family: 'Montserrat', system-ui, sans-serif; font-style: italic; font-weight: 900; font-size: 38px; color: #fff; text-align: center; padding: 0; border: none; background: transparent; line-height: 1; letter-spacing: -0.02em; -webkit-text-stroke: 2px #FF0000; paint-order: stroke fill; }
  .roster-row .rr-thumb { width: 116px; height: 66px; background: center 22% / cover no-repeat #000; border-radius: 4px; flex-shrink: 0; }
  .roster-row .rr-thumb--none { background: linear-gradient(135deg,#1a1a1a 0%,#080808 100%); display: flex; align-items: center; justify-content: center; color: rgba(255,255,255,0.18); font-size: 26px; font-weight: 900; }
  .roster-row .rr-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
  .roster-row .rr-line1 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .roster-row .rr-name { font-size: 15px; font-weight: 800; letter-spacing: -0.005em; color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
  .roster-row .rr-meta { font-size: 10px; opacity: 0.6; text-transform: uppercase; letter-spacing: 0.12em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .roster-row .rr-meta--empty { opacity: 0.32; font-style: italic; text-transform: none; letter-spacing: 0.04em; }
  .roster-row .rr-meter { display: flex; align-items: center; gap: 8px; margin-top: 2px; }
  .roster-row .rr-meter-track { flex: 1 1 0; height: 4px; background: rgba(255,255,255,0.06); border-radius: 999px; overflow: hidden; }
  .roster-row .rr-meter-fill { height: 100%; border-radius: 999px; transition: width 200ms; }
  .roster-row .rr-meter-pct { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; font-weight: 800; min-width: 32px; text-align: right; color: #888; }
  .rr-pizza { position: relative; width: 40px; height: 40px; flex-shrink: 0; }
  .rr-pizza svg { width: 100%; height: 100%; display: block; }
  .rr-pizza-pct { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-family: 'Montserrat', system-ui, sans-serif; font-weight: 900; font-size: 11px; line-height: 1; color: #fff; }
  .roster-row .rr-tridents { display: flex; gap: 4px; flex-wrap: wrap; margin: 2px 0 2px; }
  .roster-row .rr-trident { width: 20px; height: 20px; fill: #FF0000; flex-shrink: 0; }
  .roster-row .rr-contacts { display: flex; gap: 8px; flex-wrap: wrap; font-size: 11px; }
  .roster-row .rr-contact { color: #4ea3ff; text-decoration: none; }
  .roster-row .rr-contact:hover { text-decoration: underline; }
  .roster-row .rr-contact--mobile { color: #4ea3ff; }

  .pill { font-size: 9px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; padding: 3px 8px; border-radius: 999px; background: #1a1a1a; color: #aaa; }
  .pill--live { background: #143; color: #7affc8; }
  .pill--building { background: #432; color: #ffc47a; }
  .pill--registered, .pill--new { background: #401; color: #ff7a7a; }
  .pill--verified { background: #432; color: #ffc47a; }
  .pill--certified { background: #043; color: #7affc8; }
  .pill--competitive { background: #432; color: #ffc47a; }

  .empty { padding: 40px 20px; text-align: center; font-size: 13px; color: #555; }
  .sa-embed-pane { margin-top: 22px; border: 1px solid #1a1a1a; border-radius: 6px; overflow: hidden; height: 800px; }
  main.sa-app--builder { max-width: none; padding: 0; }
  .sa-builder-bar { display: flex; align-items: center; gap: 16px; padding: 10px 24px; background: #0c0c0c; border-bottom: 1px solid #1a1a1a; }
  .sa-back { font-size: 12px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: #ff7a7a; padding: 6px 12px; border: 1px solid #2a0a0a; border-radius: 4px; }
  .sa-back:hover { background: rgba(255,0,0,0.08); border-color: rgba(255,0,0,0.4); text-decoration: none; }
  .sa-builder-title { font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: #888; }
  .sa-embed-pane--full { margin: 0; border: none; border-radius: 0; height: calc(100vh - 110px); }
  .sa-embed { width: 100%; height: 100%; border: none; background: #080808; }

  /* ── ARRI camera aesthetic (Brett 2026-05-02). Sleek hardware feel.
     Pure black surfaces, hairline 1px dividers, microtype labels.
     Brett 2026-05-02 (revision): rounded corners back at 6px on cards,
     and the Data tab now regroups SSOT sections into 4 thematic blocks
     (Contact · Physical · Swimming · Stars+Social), each in its own
     card, with a 2-column field grid inside so the wide screen earns
     its keep. Red is still the only accent. */
  main.sa-app--detail { max-width: 1480px; padding: 0 16px 24px; margin: 0 auto; }
  /* Brett-locked 2026-05-18 PM: when the Pages tab is active, the
     detail-page container widens to 1800px so the Magazine Build panel +
     Media Galleries panel use the horizontal real estate on a 4K/Mac
     Studio monitor. Other tabs keep the 1480 cap (their forms + content
     read better at the narrower width).

     Margin asymmetry (Brett-locked 2026-05-18 PM round 2): right margin
     fixed at 24px, left margin auto. Content shifts rightward, leaving
     a wider "black strip" on the LEFT — that's where the operator's
     wheel scrolls the BODY (vs the inner panel scrolls). The narrow
     centered margin (default `auto auto`) gave too small a hit-zone. */
  main.sa-app--detail:has(.sa-tab-panel[data-tab="pages"].is-active) {
    max-width: 1800px;
    margin-left: auto;
    margin-right: 24px;
  }

  /* Brett-locked 2026-05-05 PM: SCROLL ARCHITECTURE REWRITTEN.
     Multiple attempts to fix the panel-level overflow-y:auto pattern
     all failed for the same root cause — modern browsers truncate
     scrollHeight when an internally-scrolling panel contains tall
     children (forms, photo grids), making the bottom unreachable.
     New approach: body scrolls naturally. Header stays sticky at the
     top via its existing `position: sticky`. Panels flow as regular
     blocks with no overflow. The page scrolls; nothing is clipped.
     Pages tab gets its own override below because its iframe + side-
     rail layout still wants flex column inside a fixed-height region. */
  body:has(main.sa-app--detail) { overflow: visible; height: auto; }
  main.sa-app--detail {
    min-height: calc(100vh - var(--lp-header-h, 49px));
    display: block;
    overflow: visible;
  }
  main.sa-app--detail > .sa-detail { display: block; }
  main.sa-app--detail .sa-tab-panels { display: block; }
  /* Sticky tab strip — keeps the tab nav visible as the body scrolls.
     Parks directly under the launchpad header (already
     position:sticky;top:0 from the shell). The builder bar (small
     breadcrumb above tabs) is allowed to scroll away — only tabs
     need to remain reachable. */
  main.sa-app--detail .sa-tabs {
    position: sticky;
    top: var(--lp-header-h, 49px);
    /* Brett-locked 2026-05-18 PM: bumped z-index from 5 → 49 to match
       the base .sa-tabs rule. At z-5 the iframe + panel content could
       overlay the nav on scroll, making the 1/2/3/4 step-bar feel like
       it disappeared. 49 sits below the global topbar (z-50) and above
       every panel + iframe surface. */
    z-index: 49;
    background: #000;
  }
  /* Pages tab — Brett-locked 2026-05-05 PM v3, updated 2026-05-18 PM.
     History: was padding-bottom 120px to give breathing room above the
     auto-appended end-of-page trident. That trident is now hidden on
     this tab (see > .sa-end-trident rule below), so the 120px became
     dead scroll space — body scrolled past the panel to reveal an
     empty black band. Reset to 0 so the panel ends exactly at its
     content. The panel's own flex column (line ~806) keeps it
     viewport-locked; nested scrolls live in iframe + .sa-pages-gallery. */
  main.sa-app--detail .sa-tab-panel[data-tab="pages"].is-active {
    padding-bottom: 0;
  }
  .sa-app--detail .sa-builder-bar { margin: 0 -16px 0; padding: 14px 20px; align-items: center; background: #000; border-bottom: 1px solid #1a1a1a; border-radius: 0; gap: 16px; }
  .sa-app--detail .sa-builder-bar .sa-back { font-size: 10px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; color: #888; padding: 4px 0; border: none; background: transparent; }
  .sa-app--detail .sa-builder-bar .sa-back:hover { color: #fff; text-decoration: none; }
  .sa-app--detail .sa-builder-title { font-size: 12px; font-weight: 700; letter-spacing: 0.05em; color: #fff; text-transform: none; font-family: 'SF Mono', 'Monaco', 'Menlo', monospace; }
  .sa-app--detail .sa-builder-spacer { flex: 1; }
  .sa-app--detail .sa-builder-link { font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #888; padding: 4px 10px; border: 1px solid #333; border-radius: 4px; transition: color 120ms, border-color 120ms; }
  .sa-app--detail .sa-builder-link:hover { background: transparent; color: #fff; border-color: #fff; text-decoration: none; }

  /* Tab strip — minimal hardware-control feel. Caps, monospace tracking,
     1px under-rule that turns red on active. No gradients, no shadows. */
  /* Brett-locked 2026-05-02 NIGHT v6: detail-page nav is now a
     FLOATING sticky bar that anchors just below the topbar. Brett
     was losing the nav on resize/scroll — sticky keeps it visible at
     all times. The bar reads as a process flow: Profile → Training
     → Media → Ad-Builder → Pages → Publish. Each tab carries a
     small step number for orientation. z-index 49 sits below the
     global topbar (z-index 50) but above the iframe + panels. */
  .sa-tabs {
    display: flex;
    gap: 0;
    padding: 0;
    margin: 0 -16px 0;
    background: rgba(0,0,0,0.95);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-bottom: 1px solid #1a1a1a;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    position: sticky;
    top: 49px;
    z-index: 49;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
    /* Brett-locked 2026-05-03: flex-shrink:0 so the parent flex can
       NOT squash the tabs to 7px when .sa-tab-panels eats all space.
       Brett: "I can't see the navigation bar … on this page". The
       sticky positioning was correct; the bar just had zero height. */
    flex: 0 0 auto;
    min-height: 44px;
  }
  .sa-tabs::-webkit-scrollbar { display: none; }
  .sa-tab {
    flex: 0 0 auto;
    padding: 14px 20px 12px;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    color: #555;
    font-family: inherit;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    cursor: pointer;
    transition: color 120ms, border-color 120ms;
    display: flex;
    align-items: center;
    gap: 8px;
  }
  /* Step number in front of every tab — process-flow cue. */
  .sa-tab[data-step]::before {
    content: attr(data-step);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border: 1px solid #2a2a2a;
    border-radius: 50%;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0;
    color: #666;
    background: #0a0a0a;
    transition: color 120ms, border-color 120ms, background 120ms;
  }
  .sa-tab:hover { color: #ccc; }
  .sa-tab:hover::before { color: #ccc; border-color: #444; }
  .sa-tab.is-active { color: var(--profile-accent, #fff); border-bottom-color: var(--profile-accent, #FF0000); }
  .sa-tab.is-active::before {
    color: #fff;
    background: var(--profile-accent, #FF0000);
    border-color: var(--profile-accent, #FF0000);
  }
  .sa-tab:focus { outline: none; color: #fff; }

  /* Panels — flat black, no border, no rounding. The tab-strip rule
     above the panel is the only edge. */
  .sa-tab-panels { background: #000; }
  /* Brett-locked 2026-05-05 PM v2: panels are plain blocks now.
     No internal overflow:auto — body scrolls instead. The previous
     `flex:1; overflow-y:auto` triggered scrollHeight truncation on
     long forms (data/training/ai tabs), making the bottom 110-400px
     of content unreachable. Body-level scroll has no such limit. */
  .sa-tab-panel { display: none !important; padding: 28px 24px 40px; }
  .sa-tab-panel.is-active { display: block !important; }
  /* Pages tab — iframe to /admin/magazine.html. Use natural document
     flow (block, NOT flex 1) so the page scrolls normally + the
     launchpad topbar + builder bar + tab strip stay visible above. */
  /* Pages tab uses zero padding (the iframe + side-rail split fills
     edge-to-edge) and scrolls internally like every other panel.
     Brett-locked 2026-05-05: was `flex: none` which made the panel
     collapse to its natural-content height (~237px) instead of
     taking the remaining viewport. Now uses default flex:1 from the
     base .sa-tab-panel rule. */
  .sa-tab-panel[data-tab="pages"] { padding: 0; }

  /* Status banner — tiny monospace strip, no rounded box. */
  /* Brett-locked 2026-05-20: margin tightened 24 → 10 to pull the red
     Confidential box closer to the name above. */
  .sa-tab-panel #adminFormStatus, .sa-tab-panel #adminPhotoStatus, .sa-form-status { margin: 0 0 10px; padding: 6px 0; font-family: 'SF Mono', Menlo, monospace; font-size: 10px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: #444; background: transparent !important; border: none; border-bottom: 1px solid #1a1a1a !important; border-radius: 0 !important; }
  .sa-form-status[data-state="saving"] { color: #ffc47a; border-bottom-color: #ffc47a !important; }
  .sa-form-status[data-state="saved"]  { color: #7affc8; border-bottom-color: #7affc8 !important; }
  .sa-form-status[data-state="error"]  { color: #ff7a7a; border-bottom-color: #ff7a7a !important; }

  /* Data tab — Brett 2026-05-02 (alignment pass): every panel is full
     width and stacked. Outside edges align by definition. The accent
     colour drives the border + heading on every panel except the
     Confidential PII vault which keeps its red pin-line. */
  /* Brett-locked 2026-05-20: section-to-section gap tightened 16 → 8
     so all panels on the Profile/Training tab sit closer together. The
     gap above PORTFOLIO PUBLISHING was the reference Brett called
     "perfect" — now consistent everywhere. */
  .sa-tab-panel[data-tab="data"] .edit-form,
  .sa-tab-panel[data-tab="training"] .edit-form { display: flex; flex-direction: column; gap: 8px; }
  .sa-tab-panel[data-tab="data"] .edit-section--private,
  .sa-tab-panel[data-tab="training"] .edit-section--private { width: 100%; }
  .sa-tab-panel[data-tab="data"] .sa-identity,
  .sa-tab-panel[data-tab="training"] .sa-identity { width: 100%; margin: 0; }
  .sa-tab-panel[data-tab="data"] .sa-group,
  .sa-tab-panel[data-tab="training"] .sa-group { width: 100%; background: #0b0b0b; border: 1px solid var(--profile-accent, #7ab9ff); border-radius: 6px; overflow: hidden; }
  .sa-group-head { padding: 12px 18px; background: #141414; border-bottom: 1px solid #1a1a1a; font-size: 10px; font-weight: 900; letter-spacing: 0.24em; text-transform: uppercase; color: var(--profile-accent, #7ab9ff); }
  .sa-group-body { padding: 18px 20px; display: flex; flex-direction: column; gap: 0; }
  .sa-group-body .edit-section { margin: 0 0 22px; padding: 0 0 18px; border-bottom: 1px solid #141414; background: transparent; }
  .sa-group-body .edit-section:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
  .sa-group-body .edit-section h3 { font-size: 13px; font-weight: 800; letter-spacing: 0.04em; text-transform: none; margin: 0 0 4px; color: #fff; }
  .sa-group-body .edit-section-sub, .sa-group-body .edit-section p { font-size: 11px; line-height: 1.6; color: #666; margin: 0 0 14px; }
  /* Inside group cards, lay multiple labels side-by-side in 2 columns. */
  .sa-group-body .edit-section { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 18px; }
  .sa-group-body .edit-section h3,
  .sa-group-body .edit-section .edit-section-sub,
  .sa-group-body .edit-section > p,
  .sa-group-body .edit-section .pb-row,
  .sa-group-body .edit-section .aasf-pickers,
  .sa-group-body .edit-section .profile-section-grid { grid-column: 1 / -1; }
  .sa-group-body .edit-section label { max-width: none; margin: 0; }
  @media (max-width: 720px) {
    .sa-group-body .edit-section { grid-template-columns: 1fr; }
  }

  /* Other tabs — keep the flat hairline section style (no group cards). */
  .sa-tab-panel:not([data-tab="data"]):not([data-tab="training"]) .edit-form { display: flex; flex-direction: column; gap: 0; }
  .sa-tab-panel:not([data-tab="data"]):not([data-tab="training"]) .edit-section { margin: 0 0 32px; padding: 0 0 24px; border-bottom: 1px solid #141414; background: transparent; }
  .sa-tab-panel:not([data-tab="data"]):not([data-tab="training"]) .edit-section:last-child { border-bottom: none; }
  .sa-tab-panel:not([data-tab="data"]):not([data-tab="training"]) .edit-section h3 { font-size: 11px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; margin: 0 0 6px; color: #fff; }
  .sa-tab-panel:not([data-tab="data"]):not([data-tab="training"]) .edit-section-sub { font-size: 11px; line-height: 1.6; color: #666; margin: 0 0 18px; }

  /* Training Log — wide-field treatment. Notes / textareas span full
     panel width inside the 2-col grid; Apple-pass dropdowns + inputs
     stay capped at --sa-w. Mic hint sits on the right of the head. */
  .sa-tab-panel[data-tab="training"] .sa-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
  .sa-tab-panel[data-tab="training"] .sa-mic-hint { font-size: 9px; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase; color: #666; }
  .sa-tab-panel[data-tab="training"] .sa-field-wide { grid-column: 1 / -1; max-width: none; }
  .sa-tab-panel[data-tab="training"] .sa-field-wide textarea { width: 100%; max-width: none; }

  /* Journal entries list (Training Log tab). Newest first. Each is
     a <details> for native expand/collapse. Date+time on the left in
     monospace; excerpt in italic American Typewriter so it reads as
     a diary fragment. Transcript expands underneath in body type. */
  .sa-tab-panel[data-tab="training"] .sa-journal-count { font-size: 10px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: #666; font-family: 'SF Mono', Menlo, monospace; }
  .sa-journal-list { list-style: none; padding: 0; margin: 0; grid-column: 1 / -1; }
  .sa-journal-entry { border-bottom: 1px solid #1a1a1a; }
  .sa-journal-entry:last-child { border-bottom: none; }
  .sa-journal-entry details { padding: 12px 0; }
  .sa-journal-entry summary { display: flex; align-items: baseline; gap: 18px; cursor: pointer; list-style: none; padding: 4px 0; }
  .sa-journal-entry summary::-webkit-details-marker { display: none; }
  .sa-journal-entry summary::before { content: '+'; flex: 0 0 16px; color: var(--profile-accent, #7ab9ff); font-family: 'SF Mono', Menlo, monospace; font-size: 14px; line-height: 1; }
  .sa-journal-entry details[open] summary::before { content: '−'; }
  .sa-journal-date { flex: 0 0 auto; font-family: 'SF Mono', Menlo, monospace; font-size: 11px; font-weight: 700; letter-spacing: 0.06em; color: #aaa; min-width: 140px; }
  .sa-journal-excerpt { flex: 1; font-family: 'American Typewriter', 'Courier New', Courier, monospace; font-style: italic; font-size: 13px; color: #e8e8e8; }
  .sa-journal-meta { margin: 8px 0 0 34px; padding: 6px 0; font-family: 'SF Mono', Menlo, monospace; font-size: 10px; color: #666; letter-spacing: 0.06em; }
  .sa-journal-transcript { margin: 6px 0 4px 34px; padding: 12px 16px; background: #050505; border-left: 2px solid var(--profile-accent, #7ab9ff); font-size: 12px; line-height: 1.7; color: #d0d0d0; max-width: 820px; }
  .sa-journal-empty { font-size: 11px; color: #666; font-style: italic; margin: 0; grid-column: 1 / -1; }
  .sa-journal-actions { margin: 12px 0 0 34px; display: flex; gap: 8px; }
  .sa-journal-edit, .sa-journal-delete, .sa-journal-save, .sa-journal-cancel { padding: 6px 12px; font-family: inherit; font-size: 9px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; background: transparent; border: 1px solid #2a2a2a; border-radius: 4px; color: #888; cursor: pointer; transition: color 120ms, border-color 120ms; }
  .sa-journal-edit:hover, .sa-journal-save:hover { color: var(--profile-accent, #7ab9ff); border-color: var(--profile-accent, #7ab9ff); }
  .sa-journal-delete:hover { color: #ff7a7a; border-color: #ff7a7a; }
  .sa-journal-cancel:hover { color: #ccc; border-color: #444; }
  .sa-journal-editor { margin: 12px 0 0 34px; padding: 14px 16px; background: #0a0a0a; border: 1px solid #1a1a1a; border-radius: 6px; max-width: 820px; }
  .sa-journal-editor-label { display: block; font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #888; margin: 0 0 8px; }
  .sa-journal-excerpt-input { width: 100%; padding: 8px 10px; background: #050505; border: 1px solid #2a2a2a; border-radius: 4px; color: #e8e8e8; font-family: 'American Typewriter', 'Courier New', Courier, monospace; font-style: italic; font-size: 13px; resize: vertical; }
  .sa-journal-editor-row { display: flex; gap: 12px; margin: 12px 0 0; }
  .sa-journal-editor-field { display: flex; flex-direction: column; gap: 4px; }
  .sa-journal-editor-field span { font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #888; }
  .sa-journal-editor-field input { width: 80px; padding: 6px 8px; background: #050505; border: 1px solid #2a2a2a; border-radius: 4px; color: #ddd; font-family: 'SF Mono', Menlo, monospace; font-size: 12px; }
  .sa-journal-editor-actions { margin: 14px 0 0; display: flex; align-items: center; gap: 10px; }
  .sa-journal-status { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; letter-spacing: 0.12em; color: #555; }
  .sa-journal-status[data-state="saving"] { color: #ffc47a; }
  .sa-journal-status[data-state="saved"]  { color: #7affc8; }
  .sa-journal-status[data-state="error"]  { color: #ff7a7a; }

  /* Voice memo drop zone + result-review (Training Log tab). */
  .sa-voice-drop { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 28px 20px; background: #0a0a0a; border: 1px dashed var(--profile-accent, #2a2a2a); border-radius: 8px; cursor: pointer; transition: border-color 120ms, background 120ms; grid-column: 1 / -1; max-width: 820px; }
  .sa-voice-drop:hover { background: #0d0d0d; border-color: var(--profile-accent, #7ab9ff); }
  .sa-voice-drop-label { font-size: 13px; font-weight: 800; letter-spacing: 0.04em; color: #fff; }
  .sa-voice-drop-hint { font-size: 11px; color: #888; margin-top: 6px; font-style: italic; }
  .sa-voice-status { margin: 14px 0 0; padding: 10px 14px; background: #050505; border-left: 2px solid var(--profile-accent, #7ab9ff); font-family: 'SF Mono', Menlo, monospace; font-size: 11px; color: #ccc; max-width: 820px; grid-column: 1 / -1; }
  .sa-voice-status[data-state="error"] { border-color: #ff7a7a; color: #ff7a7a; }
  .sa-voice-result { margin: 18px 0 0; padding: 18px 20px; background: #050505; border: 1px solid #1a1a1a; border-radius: 8px; max-width: 820px; grid-column: 1 / -1; }
  .sa-voice-result-head { font-size: 11px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: var(--profile-accent, #7ab9ff); margin: 0 0 16px; }
  .sa-voice-field { display: flex; flex-direction: column; gap: 6px; margin: 0 0 14px; }
  .sa-voice-field span { font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #888; }
  .sa-voice-field textarea, .sa-voice-field input, .sa-voice-field select { padding: 8px 10px; background: #0a0a0a; border: 1px solid #2a2a2a; border-radius: 4px; color: #ddd; font-family: inherit; font-size: 12px; }
  .sa-voice-excerpt { font-family: 'American Typewriter', 'Courier New', Courier, monospace !important; font-style: italic; font-size: 13px !important; color: #e8e8e8 !important; }
  .sa-voice-meta-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; margin: 0 0 14px; }
  .sa-voice-field--small input, .sa-voice-field--small select { width: 100%; }
  .sa-voice-actions { display: flex; align-items: center; gap: 10px; margin: 14px 0 0; }
  .sa-voice-publish { padding: 10px 18px; background: var(--profile-accent, #7ab9ff); color: #000; border: none; border-radius: 4px; font-family: inherit; font-size: 11px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; cursor: pointer; transition: opacity 120ms; }
  .sa-voice-publish:hover { opacity: 0.85; }
  .sa-voice-publish[disabled] { background: #1a1a1a; color: #555; cursor: not-allowed; }
  .sa-voice-discard { padding: 10px 18px; background: transparent; border: 1px solid #2a2a2a; border-radius: 4px; color: #888; font-family: inherit; font-size: 11px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; cursor: pointer; }
  .sa-voice-discard:hover { color: #ff7a7a; border-color: #ff7a7a; }
  .sa-voice-publish-status { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; letter-spacing: 0.12em; color: #555; }
  .sa-voice-publish-status[data-state="saving"] { color: #ffc47a; }
  .sa-voice-publish-status[data-state="saved"] { color: #7affc8; }
  .sa-voice-publish-status[data-state="error"] { color: #ff7a7a; }

  /* AI tab — Phase 0 SHELL. NDA gate sits over the dashboard until
     accepted; data-nda-accepted="true" hides the gate and reveals
     the dashboard below. Modules render as a responsive 4-col grid
     (locked tiles desaturated + greyed out, active tile gets the
     accent border). */
  .sa-tab-panel[data-tab="ai"] { padding: 28px 24px 40px; }
  .ai-shell { position: relative; min-height: 60vh; }
  .ai-shell .ai-dashboard { display: block; }
  .ai-shell .ai-nda-gate { display: none; }
  .ai-shell[data-nda-accepted="false"] .ai-nda-gate { display: flex; }
  .ai-shell[data-nda-accepted="false"] .ai-dashboard { display: none; }

  /* NDA gate */
  .ai-nda-gate { position: relative; flex-direction: column; align-items: center; padding: 24px 0; }
  .ai-nda-card { width: 100%; max-width: 880px; background: #0b0b0b; border: 1px solid #2a2a2a; border-radius: 8px; overflow: hidden; display: flex; flex-direction: column; max-height: 75vh; }
  .ai-nda-head { padding: 24px 28px 16px; border-bottom: 1px solid #1a1a1a; }
  .ai-nda-head h2 { font-size: 16px; font-weight: 800; letter-spacing: 0.04em; color: #fff; margin: 0 0 6px; text-transform: uppercase; }
  .ai-nda-sub { font-size: 11px; color: #888; margin: 0; }
  .ai-nda-body { padding: 22px 28px; overflow-y: auto; flex: 1; font-size: 12px; line-height: 1.7; color: #c8c8c8; scrollbar-width: thin; scrollbar-color: #333 transparent; }
  .ai-nda-body::-webkit-scrollbar { width: 8px; }
  .ai-nda-body::-webkit-scrollbar-thumb { background: #333; border-radius: 0; }
  .ai-nda-foot { padding: 18px 28px 22px; border-top: 1px solid #1a1a1a; background: #0a0a0a; display: flex; justify-content: flex-end; }
  .ai-nda-accept { padding: 12px 24px; font-family: inherit; font-size: 11px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; background: var(--profile-accent, #7ab9ff); color: #000; border: none; border-radius: 4px; cursor: pointer; transition: opacity 120ms; }
  .ai-nda-accept[disabled] { background: #1a1a1a; color: #555; cursor: not-allowed; }
  .ai-nda-accept:not([disabled]):hover { opacity: 0.85; }

  /* AI dashboard */
  .ai-tier-strip { padding: 20px 22px; border: 1px solid #1a1a1a; border-radius: 8px; background: #0a0a0a; margin: 0 0 24px; }
  .ai-tier-strip-head { display: flex; align-items: baseline; gap: 14px; margin: 0 0 14px; flex-wrap: wrap; }
  .ai-tier-label { font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #666; }
  .ai-tier-current { font-size: 14px; font-weight: 900; letter-spacing: 0.04em; color: var(--profile-accent, #7ab9ff); }
  .ai-tier-accepted { font-size: 10px; color: #555; margin-left: auto; font-family: 'SF Mono', Menlo, monospace; }
  .ai-tier-pills { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 0 0 12px; }
  .ai-tier-pill { display: flex; flex-direction: column; align-items: center; padding: 12px 14px; background: #141414; border: 1px solid #1a1a1a; border-radius: 6px; cursor: pointer; transition: border-color 120ms, background 120ms; }
  .ai-tier-pill:hover { border-color: #444; }
  .ai-tier-pill input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
  .ai-tier-pill.is-current,
  .ai-tier-pill:has(input:checked) { border-color: var(--profile-accent, #7ab9ff); background: #0f0f0f; }
  .ai-tier-pill-name { font-size: 11px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #fff; }
  .ai-tier-pill-price { font-size: 10px; color: #888; margin-top: 4px; font-family: 'SF Mono', Menlo, monospace; }
  .ai-tier-note { font-size: 11px; color: #555; margin: 0; font-style: italic; }
  @media (max-width: 720px) { .ai-tier-pills { grid-template-columns: repeat(2, 1fr); } }

  .ai-modules-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; margin: 0 0 28px; }
  .ai-module { padding: 22px 20px; border: 1px solid #1a1a1a; border-radius: 8px; background: #0b0b0b; display: flex; flex-direction: column; gap: 8px; min-height: 240px; transition: border-color 120ms, background 120ms; }
  .ai-module--active { border-color: var(--profile-accent, #7ab9ff); background: #0d0d0d; }
  .ai-module--locked { opacity: 0.86; }
  .ai-module--locked:hover { opacity: 1; border-color: #2a2a2a; }
  .ai-module-icon { font-size: 22px; line-height: 1; color: var(--profile-accent, #7ab9ff); margin: 0 0 4px; font-family: 'SF Mono', Menlo, monospace; }
  .ai-module-icon--locked { color: #555; }
  .ai-module-title { font-size: 13px; font-weight: 900; letter-spacing: 0.02em; text-transform: none; color: #fff; margin: 0; }
  .ai-module-tier { font-size: 9px; font-weight: 800; letter-spacing: 0.2em; text-transform: uppercase; color: #888; font-family: 'SF Mono', Menlo, monospace; }
  .ai-module-blurb { font-size: 11px; line-height: 1.6; color: #aaa; margin: 4px 0 12px; flex: 1; }
  .ai-module-cta { padding: 10px 14px; font-family: inherit; font-size: 10px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; background: transparent; border: 1px solid #2a2a2a; border-radius: 4px; color: #ccc; cursor: pointer; transition: color 120ms, border-color 120ms, background 120ms; align-self: stretch; }
  .ai-module-cta--run { background: var(--profile-accent, #7ab9ff); color: #000; border-color: var(--profile-accent, #7ab9ff); }
  .ai-module-cta--run:hover { opacity: 0.85; }
  .ai-module-cta--notify:hover { color: var(--profile-accent, #7ab9ff); border-color: var(--profile-accent, #7ab9ff); }
  .ai-module[data-on-waitlist="true"] .ai-module-cta--notify { color: #7affc8; border-color: #7affc8; cursor: default; }
  .ai-module-result { margin: 12px 0 0; padding: 14px 16px; background: #050505; border: 1px solid #1a1a1a; border-radius: 6px; font-size: 12px; line-height: 1.6; color: #ddd; white-space: pre-wrap; }

  .ai-insights-history { padding: 20px 22px; border: 1px solid #1a1a1a; border-radius: 8px; background: #0a0a0a; }
  .ai-insights-title { font-size: 11px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #fff; margin: 0 0 14px; display: flex; align-items: baseline; gap: 10px; }
  .ai-insights-count { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; color: var(--profile-accent, #7ab9ff); font-weight: 700; }
  .ai-insights-empty { font-size: 11px; color: #666; margin: 0; font-style: italic; }
  .ai-insights-list { list-style: none; padding: 0; margin: 0; }
  .ai-insight { border-bottom: 1px solid #1a1a1a; }
  .ai-insight:last-child { border-bottom: none; }
  .ai-insight details { padding: 12px 0; }
  .ai-insight summary { display: flex; align-items: baseline; gap: 14px; cursor: pointer; list-style: none; padding: 4px 0; flex-wrap: wrap; }
  .ai-insight summary::-webkit-details-marker { display: none; }
  .ai-insight summary::before { content: '+'; flex: 0 0 16px; color: var(--profile-accent, #7ab9ff); font-family: 'SF Mono', Menlo, monospace; font-size: 14px; line-height: 1; }
  .ai-insight details[open] summary::before { content: '−'; }
  .ai-insight-when { font-family: 'SF Mono', Menlo, monospace; font-size: 11px; font-weight: 700; color: #ddd; min-width: 180px; }
  .ai-insight-module { font-size: 10px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: var(--profile-accent, #7ab9ff); }
  .ai-insight-context { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; color: #666; }
  .ai-insight-body { margin: 12px 0 4px 30px; padding: 14px 18px; background: #050505; border-left: 2px solid var(--profile-accent, #7ab9ff); font-size: 12px; line-height: 1.65; color: #e0e0e0; max-width: 820px; }
  .ai-insight-body p { margin: 0 0 12px; }
  .ai-insight-body p:last-child { margin-bottom: 0; }
  .ai-insight-meta { margin: 8px 0 0 30px; font-family: 'SF Mono', Menlo, monospace; font-size: 9px; letter-spacing: 0.06em; color: #555; }
  .ai-module-status { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; letter-spacing: 0.12em; color: #555; min-height: 14px; margin-top: 4px; }
  .ai-module-status[data-state="saving"] { color: #ffc47a; }
  .ai-module-status[data-state="saved"] { color: #7affc8; }
  .ai-module-status[data-state="error"] { color: #ff7a7a; }

  /* Basic Info vault — Brett 2026-05-02: 1px FF0000 hairline + red
     heading. Subgroups inside (Contact / Address / Emergency / Medical /
     Connections) get a small red microtype subhead. */
  .sa-tab-panel .edit-section--private { background: transparent; border: 1px solid #FF0000; padding: 20px 22px; border-radius: 6px; }
  .sa-tab-panel .edit-section--private h3 { color: #FF0000; font-size: 14px; font-weight: 900; letter-spacing: 0.02em; text-transform: none; margin: 0 0 4px; }
  .sa-tab-panel .edit-section--private .edit-section-sub { color: #aaa; }
  .sa-dob-row { display: grid; grid-template-columns: 1fr 1.4fr 1fr; gap: 8px; }
  .sa-dob-row select { width: 100%; }
  .sa-pii-subhead { font-size: 9px; font-weight: 900; letter-spacing: 0.24em; text-transform: uppercase; color: #FF0000; margin: 18px 0 8px; padding-top: 10px; border-top: 1px solid rgba(255,0,0,0.18); }
  .sa-pii-subhead:first-of-type { margin-top: 6px; padding-top: 0; border-top: none; }
  /* Brett-locked 2026-05-20: Medical + Stripe in a 2-column row inside
     Confidential. ONE shared red hairline above the whole row + a
     vertical hairline between the two columns. Subheads inside the row
     drop their own divider since the row's border-top covers it. */
  .sa-pii-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 28px;
    margin-top: 18px;
    padding-top: 10px;
    border-top: 1px solid rgba(255, 0, 0, 0.18);
  }
  .sa-pii-row > .sa-pii-col + .sa-pii-col {
    padding-left: 28px;
    border-left: 1px solid rgba(255, 0, 0, 0.12);
  }
  .sa-pii-row .sa-pii-subhead {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
  }
  @media (max-width: 720px) {
    .sa-pii-row { grid-template-columns: 1fr; gap: 0; }
    .sa-pii-row > .sa-pii-col + .sa-pii-col {
      padding-left: 0;
      margin-top: 18px;
      padding-top: 10px;
      border-left: none;
      border-top: 1px solid rgba(255, 0, 0, 0.18);
    }
  }
  .sa-tab-panel .edit-section--private label { margin: 0; }

  /* Data tab heading — Brett 2026-05-02: bigger, sexier. The name
     and the Formula H2O wordmark share the same visual weight; the
     mark stays at 25% opacity so it whispers under the name. " Profile"
     suffix removed — the panel speaks for itself. */
  /* Brett-locked 2026-05-20: bottom margin tightened 28 → 10 so the red
     Confidential box (and the green Portfolio Publishing panel below it)
     sit closer to the athlete name. */
  .sa-data-heading { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; margin: 0 0 10px; font-size: 36px; line-height: 1; font-weight: 900; letter-spacing: -0.02em; color: var(--profile-accent, #7ab9ff); text-transform: none; }
  .sa-data-name { display: inline-block; }
  /* Formula H2O wordmark — Brett 2026-05-02: rebuilt in Montserrat
     so it sits on the same baseline as the athlete name. Same size,
     italic for the team-livery feel, mid-grey so it whispers next to
     the accent-coloured name without competing. */
  .sa-fh2o-mark {
    font-family: 'Montserrat', system-ui, sans-serif;
    font-size: 1em;
    font-weight: 900;
    font-style: italic;
    letter-spacing: 0.01em;
    color: rgba(255, 255, 255, 0.35);
    text-transform: none;
    line-height: 1;
    display: inline-block;
  }
  .sa-fh2o-mark sub { font-size: 0.55em; vertical-align: -0.18em; font-style: normal; padding: 0 0.05em; }

  /* Identity panel — sits directly under the Confidential vault. The
     1px border + heading colour both pick up --profile-accent which
     the JS swatch handler writes onto the panel's inline style on
     change. Default accent is the same light blue used everywhere. */
  .sa-identity { --profile-accent: #7ab9ff; margin: 18px 0 22px; padding: 20px 22px; background: transparent; border: 1px solid var(--profile-accent); border-radius: 6px; }
  .sa-identity h3 { color: var(--profile-accent); font-size: 18px; font-weight: 900; letter-spacing: -0.005em; text-transform: none; margin: 0 0 4px; }
  .sa-identity > .edit-section-sub { color: #aaa; font-size: 11px; }
  /* Brett 2026-05-02: Identity sub-headings are bigger + bolder; the
     instruction line beneath them is smaller. Visual hierarchy: heading
     leads, instruction whispers. */
  .sa-identity .sa-id-subhead {
    font-size: 13px;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: none;
    color: var(--profile-accent);
    border-top-color: color-mix(in srgb, var(--profile-accent) 25%, transparent);
    padding-top: 14px;
    margin-top: 22px;
  }
  .sa-identity .sa-id-subhead + .edit-section-sub { font-size: 10px; line-height: 1.5; color: #777; margin: 4px 0 12px; }
  .sa-identity-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 18px; }
  .sa-identity-grid--3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
  @media (max-width: 720px) { .sa-identity-grid, .sa-identity-grid--3 { grid-template-columns: 1fr; } }
  .sa-identity .field { margin: 0; max-width: none; }

  /* Swimming panel — Brett 2026-05-02. Bespoke layout with the team
     header, tier-badge strip, support staff, and structured PB rows. */
  .sa-group--swimming .sa-team-header { display: flex; align-items: baseline; gap: 0; padding: 6px 0 18px; border-bottom: 1px solid color-mix(in srgb, var(--profile-accent) 30%, transparent); margin-bottom: 18px; }
  .sa-team-prefix { font-size: 28px; font-weight: 300; letter-spacing: -0.01em; color: #888; font-style: italic; }
  .sa-team-surname { font-size: 28px; font-weight: 900; letter-spacing: -0.01em; color: var(--profile-accent, #fff); text-transform: uppercase; }
  .sa-tier-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; margin-bottom: 22px; }
  .sa-tier { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px; background: var(--profile-accent, #7ab9ff); border: 1px solid #000; border-radius: 4px; }
  .sa-tier .sa-tier-label { font-size: 9px; font-weight: 900; letter-spacing: 0.18em; text-transform: uppercase; color: #fff; opacity: 0.92; }
  .sa-tier select { background: rgba(0,0,0,0.55); border: 1px solid rgba(0,0,0,0.6); color: #fff; padding: 6px 8px; border-radius: 3px; font-size: 12px; font-weight: 700; }
  .sa-tier select:hover { background: rgba(0,0,0,0.7); }
  .sa-tier select option { background: #0a0a0a; color: #fff; }

  /* Dismissable panels (Multi-Class · EO Lab). Pin-line border in
     --profile-accent. Header shows title + ✕ Not Applicable button.
     Click → the body collapses to a one-line tombstone with a
     Restore link. Both states are in the DOM — CSS toggles which
     shows based on data-dismissed. */
  .sa-group--dismissable { border: 1px solid var(--profile-accent, #7ab9ff); border-radius: 6px; overflow: hidden; }
  .sa-group-head--dismissable { display: flex; align-items: center; gap: 14px; padding: 10px 14px 10px 18px; }
  .sa-group-head--dismissable .sa-group-head-title { flex: 1; font-size: 11px; font-weight: 900; letter-spacing: 0.22em; text-transform: uppercase; color: var(--profile-accent, #7ab9ff); }
  .sa-group-dismiss { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; background: transparent; border: 1px solid #2a2a2a; border-radius: 4px; color: #888; font-family: inherit; font-size: 10px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; cursor: pointer; transition: color 120ms, border-color 120ms; }
  .sa-group-dismiss:hover { color: #fff; border-color: #fff; }
  .sa-group-dismiss-x { font-size: 12px; line-height: 1; }
  .sa-group-tombstone { display: none; padding: 12px 18px; align-items: center; gap: 14px; background: #0a0a0a; }
  .sa-group-tombstone-label { font-size: 11px; font-weight: 900; letter-spacing: 0.22em; text-transform: uppercase; color: var(--profile-accent, #7ab9ff); flex: 0 0 auto; }
  .sa-group-tombstone-state { font-size: 11px; color: #555; flex: 1; font-style: italic; }
  .sa-group-restore { background: transparent; border: 1px solid #2a2a2a; border-radius: 4px; padding: 5px 10px; color: #888; font-family: inherit; font-size: 10px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; cursor: pointer; transition: color 120ms, border-color 120ms; }
  .sa-group-restore:hover { color: var(--profile-accent, #7ab9ff); border-color: var(--profile-accent, #7ab9ff); }
  /* Toggle visibility by data-dismissed. */
  .sa-group--dismissable[data-dismissed="true"] .sa-group-head--dismissable,
  .sa-group--dismissable[data-dismissed="true"] .sa-group-body--dismissable { display: none; }
  .sa-group--dismissable[data-dismissed="true"] .sa-group-tombstone { display: flex; }
  .sa-group--dismissable[data-dismissed="true"] { border-color: #2a2a2a; }

  /* The three live data panels under the pathway dropdowns. They show
     the chosen AASF / Elite Tier / FTEM value in big type and update
     instantly via the inline script at the bottom of the panel. */
  .sa-aasf-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; margin: 6px 0 22px; }
  .sa-aasf-card { padding: 14px 16px; background: #0d0d0d; border: 1px solid #1a1a1a; border-radius: 4px; display: flex; flex-direction: column; gap: 6px; }
  .sa-aasf-card-label { font-size: 9px; font-weight: 900; letter-spacing: 0.22em; text-transform: uppercase; color: var(--profile-accent, #7ab9ff); }
  .sa-aasf-card-value { font-size: 18px; font-weight: 800; letter-spacing: -0.005em; color: #fff; }

  .sa-staff-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px 14px; margin: 10px 0 6px; }
  .sa-staff-grid .field { margin: 0; max-width: none; }
  .sa-support .sa-mic { display: inline-block; margin-right: 4px; filter: saturate(0); opacity: 0.8; }
  /* Brett 2026-05-02: drop the 2-col edit-section grid inside the
     Swimming card so each section's children flow normally. The grid
     was squeezing the thanks textarea + staff list into half-columns
     and orphaning the favourite-strokes subhead. */
  .sa-group--swimming .sa-group-body .edit-section { display: block; grid-template-columns: none; gap: 0; }
  .sa-group--swimming .sa-group-body .edit-section > * { grid-column: auto; }

  .sa-thanks { display: block; margin: 0 0 14px; max-width: none; }
  .sa-thanks textarea { width: 100%; box-sizing: border-box; }

  /* Staff roster — 4 columns (down from 8). Each subgroup gets its
     own row of 4. Cleaner, breathing room, all labels readable. */
  .sa-staff-rows { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px 14px; margin: 8px 0 14px; }
  @media (max-width: 1100px) { .sa-staff-rows { grid-template-columns: repeat(2, 1fr); } }
  @media (max-width: 600px)  { .sa-staff-rows { grid-template-columns: 1fr; } }
  .sa-staff-rows .field { margin: 0; max-width: none; }

  /* Rankings — 4 fields side-by-side (National · State · Age · Club). */
  .sa-rankings { padding: 0 0 6px; }
  .sa-rank-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px 14px; margin: 8px 0 0; }
  @media (max-width: 900px) { .sa-rank-grid { grid-template-columns: repeat(2, 1fr); } }
  .sa-rank-grid .field { margin: 0; max-width: none; }

  /* White Swimming-panel subheads — Brett 2026-05-02: "those two
     titles need to change from red to white." Applies inside the
     Swimming card, so PII red subheads stay red. */
  .sa-group--swimming .sa-pii-subhead,
  .sa-group--swimming .sa-swim-subhead { font-size: 10px; font-weight: 900; letter-spacing: 0.24em; text-transform: uppercase; color: #fff; margin: 16px 0 8px; padding-top: 10px; border-top: 1px solid rgba(255,255,255,0.12); }
  .sa-group--swimming .sa-pii-subhead:first-of-type,
  .sa-group--swimming .sa-swim-subhead:first-of-type { padding-top: 0; border-top: none; }
  .sa-group--swimming .sa-swim-h3 { color: #fff; }

  /* Tick-to-rank stroke picker. */
  .sa-stroke-picker { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 4px; }
  .sa-stroke-btn { display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; background: #0a0a0a; border: 1px solid #2a2a2a; border-radius: 4px; color: #ccc; font-family: inherit; font-size: 12px; font-weight: 700; letter-spacing: 0.04em; cursor: pointer; transition: border-color 120ms, color 120ms, background 120ms; }
  .sa-stroke-btn:hover { border-color: #555; color: #fff; }
  .sa-stroke-btn.is-picked { background: var(--profile-accent, #7ab9ff); border-color: var(--profile-accent, #7ab9ff); color: #fff; }
  .sa-stroke-rank { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 4px; border-radius: 9px; background: rgba(0,0,0,0.45); color: #fff; font-size: 10px; font-weight: 900; }
  .sa-stroke-btn:not(.is-picked) .sa-stroke-rank { display: none; }

  /* PB table — Brett 2026-05-02 Apple-pass: one 7-column grid, all 5
     PBs locked into the same ruler. Heading row at the top, hairline
     dividers between rows, no per-row card chrome. Inputs INSIDE
     this table override the global --sa-w max-width so they fill
     their grid column exactly under the heading. */
  .sa-pb-table {
    display: grid;
    grid-template-columns: 1fr 0.85fr 0.6fr 1fr 1fr 1.6fr 1.3fr;
    gap: 8px;
    background: #0a0a0a;
    border: 1px solid #2a2a2a;
    border-radius: 8px;
    padding: 14px 16px;
    align-items: center;
  }
  .sa-pb-thead { display: contents; }
  .sa-pb-thead > span { font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #888; padding: 0 2px 6px; border-bottom: 1px solid #1f1f1f; }
  .sa-pb-row { display: contents; }
  .sa-pb-row > input,
  .sa-pb-row > select { max-width: none; }
  .sa-pb-divider { grid-column: 1 / -1; height: 1px; background: #1a1a1a; margin: 2px 0; }
  @media (max-width: 1100px) {
    /* Wrap to 4 + 3 split when there isn't horizontal room. */
    .sa-pb-table { grid-template-columns: 1fr 0.85fr 0.6fr 1fr; }
    .sa-pb-thead > span:nth-child(n+5) { display: none; }
    .sa-pb-row > *:nth-child(n+5) { grid-column: span 2; }
  }
  @media (max-width: 720px) {
    .sa-pb-table { grid-template-columns: 1fr 1fr; }
    .sa-pb-thead { display: none; }
    .sa-pb-row > *:nth-child(n+5) { grid-column: span 1; }
  }

  /* Brett-locked 2026-05-20: bottom-right floating save pill retired.
     The topbar #lpSavePill (admin.css .lp-save-pill) is the single
     confidence cue now — driven from setState() in sales-athletes.js
     via window.LP.flashSaving / flashSaved / flashFail. */
  @keyframes sa-save-pulse { 0%,100% { opacity: 0.4; } 50% { opacity: 1; } }

  /* EO Lab section — placeholder graphs. */
  .sa-eolab .sa-eo-import { display: flex; align-items: center; gap: 12px; margin: 4px 0 14px; flex-wrap: wrap; }
  .sa-eo-btn { padding: 8px 14px; background: var(--profile-accent, #7ab9ff); border: 1px solid var(--profile-accent, #7ab9ff); color: #fff; font-family: inherit; font-size: 11px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; border-radius: 4px; cursor: pointer; opacity: 0.5; }
  .sa-eo-btn[disabled] { cursor: not-allowed; }
  .sa-eo-status { font-size: 11px; color: #888; }
  .sa-eo-graphs { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin: 6px 0 14px; }
  .sa-eo-graph { aspect-ratio: 16/9; background: #050505; border: 1px solid #1a1a1a; border-radius: 4px; display: flex; align-items: flex-end; padding: 8px 10px; }
  .sa-eo-graph-label { font-size: 10px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: var(--profile-accent, #888); }

  /* IOC-code country avatars (Basic panel). Flat pill in the nation's
     primary colour with the 3-letter code in the contrast ink. */
  .sa-country-picker { margin: 0; }
  .sa-country-row { display: grid; grid-template-columns: 56px 1fr; gap: 8px; align-items: stretch; }
  .sa-country-avatar { display: inline-flex; align-items: center; justify-content: center; min-height: 38px; padding: 0 6px; font-family: 'SF Mono', Menlo, monospace; font-size: 13px; font-weight: 900; letter-spacing: 0.06em; border-radius: 4px; border: 1px solid rgba(255,255,255,0.12); }

  /* Prefix-locked social input. The platform prefix sits glued to the
     left of the input field — user only types their handle. */
  .sa-social .sa-social-row { display: grid; grid-template-columns: auto 1fr; align-items: stretch; border: 1px solid #1f1f1f; border-radius: 4px; overflow: hidden; transition: border-color 120ms; }
  .sa-social .sa-social-row:hover { border-color: #2e2e2e; }
  .sa-social .sa-social-row:focus-within { border-color: var(--profile-accent, #7ab9ff); }
  .sa-social .sa-social-prefix { display: inline-flex; align-items: center; padding: 0 10px; background: #050505; color: #888; font-family: 'SF Mono', Menlo, monospace; font-size: 11px; font-weight: 700; letter-spacing: 0.02em; border-right: 1px solid #1f1f1f; user-select: none; }
  .sa-social .sa-social-row input { background: #0a0a0a; border: none; border-radius: 0; padding: 9px 11px; color: #fff; font-size: 13px; font-family: inherit; width: 100%; box-sizing: border-box; }
  .sa-social .sa-social-row input:focus { outline: none; }

  .sa-swatches { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }
  .sa-swatch { width: 32px; height: 32px; border-radius: 4px; border: 2px solid #1f1f1f; cursor: pointer; padding: 0; transition: border-color 120ms, transform 120ms; }
  .sa-swatch:hover { border-color: #555; transform: translateY(-1px); }
  .sa-swatch.is-active { border-color: #fff; box-shadow: 0 0 0 2px var(--profile-accent); }

  /* Universal field reset — covers BOTH .edit-field labels AND raw
     <label><span><input> patterns the SSOT form uses (Walk-up song,
     Three words, etc). This is what was unstyled in the screenshot. */
  .sa-tab-panel label { display: flex; flex-direction: column; gap: 6px; margin: 0 0 14px; font-size: 11px; max-width: 540px; }
  .sa-tab-panel label > span,
  .sa-tab-panel .edit-voice-label,
  .sa-tab-panel .edit-prompt-label { font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #888; display: block; margin: 0 0 4px; }
  /* Brett 2026-05-02 (Apple pass): uniform widths across the panel.
     One ruler — every input + select reaches the same maximum (--sa-w).
     Long option labels truncate with ellipsis instead of expanding.
     Selects get a slightly lighter background, rounder corners, and
     a real chevron so the affordance reads as a dropdown, not a text
     field. Native arrow suppressed so all browsers render the same. */
  :root, .sa-tab-panel { --sa-w: 240px; }

  .sa-tab-panel input[type="text"],
  .sa-tab-panel input[type="email"],
  .sa-tab-panel input[type="tel"],
  .sa-tab-panel input[type="date"],
  .sa-tab-panel input[type="number"],
  .sa-tab-panel input[type="url"],
  .sa-tab-panel select,
  .sa-tab-panel textarea {
    background: #0a0a0a;
    border: 1px solid #2e2e2e;
    border-radius: 6px;
    color: #fff;
    padding: 10px 12px;
    font-size: 13px;
    font-family: inherit;
    width: 100%;
    max-width: var(--sa-w);
    box-sizing: border-box;
    transition: border-color 120ms, background 120ms;
  }
  .sa-tab-panel textarea { max-width: 100%; }
  .sa-tab-panel input:hover,
  .sa-tab-panel select:hover,
  .sa-tab-panel textarea:hover { border-color: #444; }

  .sa-tab-panel select {
    background: #141414;
    border-radius: 8px;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    padding-right: 32px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%237ab9ff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
    background-repeat: no-repeat;
    background-position: right 12px center;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
  }
  .sa-tab-panel select:hover { background-color: #1a1a1a; }
  .sa-tab-panel select option { background: #0a0a0a; color: #fff; padding: 6px; }
  .sa-tab-panel input:focus,
  .sa-tab-panel select:focus,
  .sa-tab-panel textarea:focus { outline: none; border-color: var(--profile-accent, #7ab9ff); box-shadow: none; }
  .sa-tab-panel .edit-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; max-width: 540px; }

  /* Profile section grid (PII vault) — keep dense grid look. */
  .sa-tab-panel .profile-section-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; max-width: none; }
  .sa-tab-panel .profile-section-grid label { max-width: none; margin: 0; }

  /* Chips / sign-chips / word-chips inside the SSOT form. */
  .sa-tab-panel .chip, .sa-tab-panel .sign-chip, .sa-tab-panel .word-chip {
    display: inline-block; padding: 4px 10px; margin: 0 4px 4px 0;
    background: #0a0a0a; border: 1px solid #2a2a2a; border-radius: 0;
    color: #ccc; font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
    cursor: pointer;
  }
  .sa-tab-panel .chip:hover, .sa-tab-panel .sign-chip:hover, .sa-tab-panel .word-chip:hover { border-color: #fff; color: #fff; }
  .sa-tab-panel .chip.is-active, .sa-tab-panel .sign-chip.is-active, .sa-tab-panel .word-chip.is-active { background: var(--profile-accent, #FF0000); border-color: var(--profile-accent, #FF0000); color: #fff; }

  /* Voice mic + tap-to-speak buttons. */
  .sa-tab-panel .voice-btn, .sa-tab-panel button[class*="voice"] {
    background: transparent; border: 1px solid #2a2a2a; color: #888;
    padding: 4px 10px; border-radius: 0; font-size: 10px; font-weight: 700;
    letter-spacing: 0.18em; text-transform: uppercase; cursor: pointer;
  }
  .sa-tab-panel .voice-btn:hover { border-color: #fff; color: #fff; }

  /* Iframe (Pages tab) — true full bleed, no margin. */
  /* Brett 2026-05-02: cap the iframe so the launchpad topbar (lp-nav)
     + builder bar + tab strip stay visible above it, AND the body
     scroll isn't trapped inside the iframe. Pages tab now has normal
     page scroll instead of a full-viewport iframe lock. */
  .sa-embed--tab { width: 100%; height: calc(100vh - 280px); min-height: 520px; border: none; background: #000; display: block; }

  /* Pages tab — Brett-locked 2026-05-02 NIGHT v4, rebuilt 2026-05-12.
     Two scrolling panels, CENTRED in the page (no edge-burst). Designed
     for neuro-divergent operators: clear column hierarchy, generous
     spacing, consistent type scale.
       LEFT  · magazine pages iframe (single-column, ?pagesonly=1).
       RIGHT · Branding pads on top, Media gallery underneath.
     Both panels scroll independently — no wheel-forwarding hack.
     Tab is viewport-locked so the parent page doesn't fight either pane
     for the scroll event. Cursor over iframe = iframe scrolls. Cursor
     over aside = aside scrolls. Cursor over chrome = nothing scrolls. */
  .sa-tab-panel[data-tab="pages"] {
    padding: 0 24px 12px;
    background: #050505;
    /* Viewport-fitting flex column so the split fills remaining height
       without overflowing the page. Topbar + tab strip + context header
       all share the page chrome; their combined natural height + this
       panel's own padding adds up to whatever's left of 100vh. The
       !important on display/flex-direction matches the existing
       .sa-tab-panel.is-active { display: block !important } pattern
       elsewhere in this file — without it the is-active rule wins
       on cascade-order and forces block layout. */
    height: calc(100vh - 160px);
    min-height: 560px;
    overflow: hidden;
  }
  .sa-tab-panel[data-tab="pages"].is-active {
    display: flex !important;
    flex-direction: column;
  }
  .sa-tab-panel[data-tab="pages"] .sa-mag-context {
    flex: 0 0 auto;
  }
  .sa-pages-split {
    display: flex;
    gap: 0;
    flex: 1 1 auto;
    min-height: 0;
    /* Brett 2026-05-03 v10: width 100% + max-width is required because
       `margin: 24px auto 0` was disabling flex-stretch on this item,
       so the split collapsed to its children's intrinsic width (~662px).
       That starved the iframe to 361px wide and every downstream cqw
       computation broke (cover masthead clipped, etc). */
    width: 100%;
    /* Brett-locked 2026-05-18 PM: bumped from 1400px → 1800px to
       match the widened parent on the Pages tab. Eats the empty
       horizontal margins on a Mac Studio monitor. The iframe + aside
       grow proportionally within. */
    max-width: 1800px;
    margin: 12px auto 0;
    background: #000;
    border: 1px solid #1a1a1a;
    border-radius: 8px;
    overflow: hidden;
  }
  .sa-pages-split .sa-embed--tab {
    flex: 1 1 auto;
    height: 100%;
    min-height: 0;
    border-right: 1px solid #1a1a1a;
    background: #000;
  }
  .sa-pages-side {
    width: 360px;
    flex: 0 0 360px;
    background: #060606;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* CRITICAL — without min-height:0 on a flex child whose own
       children scroll, the intrinsic content size sets the minimum
       and the inner overflow-y:auto never engages. Brett 2026-05-02
       NIGHT v7: "Can't scroll to the bottom of photographs". */
    min-height: 0;
  }
  /* Top-of-aside pane label — sits at the same vertical position as
     the iframe's .mag-pane-label--stage so "MEDIA GALLERIES" reads on
     the same line as "MAGAZINE-BUILD PANEL". Brett-locked 2026-05-18 PM
     (renamed from "Branding"). */
  .sa-pages-pane-label {
    position: sticky;
    top: 0;
    z-index: 5;
    padding: 6px 12px;
    background: rgba(0, 0, 0, 0.85);
    -webkit-backdrop-filter: blur(6px);
            backdrop-filter: blur(6px);
    border-bottom: 1px solid rgba(255, 0, 0, 0.35);
    color: #FF0000;
    font-family: 'Montserrat', sans-serif;
    font-size: 10px;
    font-weight: 900;
    letter-spacing: 0.22em;
    text-transform: uppercase;
  }

  /* Branding block — Avatar / Logo / Pill colour / Accent. */
  .sa-pages-branding {
    padding: 14px 18px 16px;
    border-bottom: 1px solid #181818;
    background: #080808;
  }
  .sa-pages-branding-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }
  .sa-brand-pad {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 10px;
    background: #0c0c0c;
    border: 1px dashed #2a2a2a;
    border-radius: 6px;
    cursor: pointer;
    transition: border-color 120ms, background 120ms, transform 120ms;
    text-align: center;
  }
  .sa-brand-pad:hover {
    border-color: var(--profile-accent, #FF0000);
    background: #111;
    transform: translateY(-1px);
  }
  .sa-brand-pad-preview {
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--profile-accent, #FF0000);
    color: #fff;
    font-size: 16px;
    font-weight: 900;
    letter-spacing: 0.04em;
    border-radius: 6px;
    background-size: cover;
    background-position: center;
  }
  .sa-brand-pad-preview--logo {
    background: #2a2a2a;
    color: #ccc;
    font-size: 11px;
    letter-spacing: 0.18em;
  }
  .sa-brand-pad-preview.has-image {
    background-color: #000;
    color: transparent;
  }
  .sa-brand-pad-cta {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: #ccc;
    text-transform: none;
  }
  /* Brett-locked 2026-05-13 night: two client-customisable accent swatches
     under the Branding row. Each is a native colour input visually wrapped
     in a circle preview + label. Pill / accent colours flow through to
     the back cover profile pill, link rows, and other accent surfaces. */
  .sa-pages-branding-colours {
    display: flex;
    gap: 16px;
    padding: 12px 16px 0;
    align-items: center;
    justify-content: center;
  }
  .sa-brand-swatch {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    flex: 0 0 auto;
  }
  .sa-brand-swatch input[type="color"] {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.18);
    cursor: pointer;
    padding: 0;
    background: #0a0a0a;
    transition: border-color 120ms ease, transform 120ms ease;
    -webkit-appearance: none;
            appearance: none;
  }
  .sa-brand-swatch input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
  .sa-brand-swatch input[type="color"]::-webkit-color-swatch { border: none; border-radius: 50%; }
  .sa-brand-swatch input[type="color"]::-moz-color-swatch { border: none; border-radius: 50%; }
  .sa-brand-swatch:hover input[type="color"] {
    border-color: rgba(255, 255, 255, 0.4);
    transform: translateY(-1px);
  }
  .sa-brand-swatch-cta {
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
  }
  /* Gallery — fills the rest of the right column. */
  .sa-pages-gallery {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 0;
    border: none;
    background: transparent;
    width: auto;
    min-height: 0;  /* same flex-scroll fix as .sa-pages-side */
  }
  .sa-pages-gallery-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    padding: 14px 18px 8px;
  }
  .sa-pages-gallery-head h3 { margin: 0; font-size: 13px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: #ddd; }
  .sa-pages-gallery-count {
    font-size: 11px;
    font-weight: 700;
    color: var(--profile-accent, #FF0000);
    letter-spacing: 0.1em;
  }
  .sa-pages-gallery-hint {
    margin: 0;
    padding: 0 18px 12px;
    font-size: 11px;
    color: #777;
    line-height: 1.5;
    border-bottom: 1px solid #111;
  }
  .sa-pages-gallery-grid {
    flex: 1 1 0;
    min-height: 0;  /* same flex-scroll fix — grid is the actual scroll surface */
    overflow-y: auto;
    overflow-x: hidden;
    padding: 12px 10px 24px;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
    align-content: start;
    /* Brett-locked 2026-05-05 PM: every tile renders at a UNIFORM
       16:9 aspect with object-fit: cover. The earlier 2026-05-02
       "render every photo at native aspect" rule looked nice when
       all photos were landscape, but a single portrait thumb left
       a tall void in the OTHER column (CSS grid won't masonry-pack
       across rows). A uniform aspect kills the void entirely and
       matches the flat compact-thumb language used by the magazine
       builder's per-page photo strip. Operators only need a
       recognisable preview to pick the right photo — full crop is
       fine, the public profile + magazine cover use the actual
       photo at full resolution. */
    align-items: stretch;
    grid-auto-rows: auto;
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.45) rgba(255,255,255,0.06);
  }
  .sa-pages-gallery-grid::-webkit-scrollbar { width: 10px; }
  .sa-pages-gallery-grid::-webkit-scrollbar-track { background: rgba(255,255,255,0.06); }
  .sa-pages-gallery-grid::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.45); border-radius: 4px; }
  .sa-pages-gallery-grid::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.65); }
  /* Brett-locked 2026-05-05 PM: every tile renders at a UNIFORM
     16:9 aspect with object-fit: cover. The earlier 2026-05-02
     "render every photo at native aspect" rule looked nice when
     all photos were landscape, but a single portrait left a tall
     void in the OTHER column (CSS grid won't masonry-pack across
     rows). A uniform aspect kills the void entirely and matches
     the flat compact-thumb language used by the magazine builder's
     per-page photo strip. Operators only need a recognisable
     preview to pick the right photo — a centre-crop is fine; the
     public profile + magazine cover use the photo at full res. */
  .sa-pages-gallery-grid .sa-photo-tile {
    grid-column: span 1 !important;
    aspect-ratio: auto !important;
    width: 100% !important;
    height: auto !important;
    /* Brett-locked 2026-05-05 PM: explicit min-height anchors the
       grid row so a tall portrait thumb (or any uneven image)
       can't leave a void in the OTHER column. Earlier attempts —
       aspect-ratio on the tile, CSS columns, native-aspect — all
       fought either the base .sa-photo-tile overflow:hidden or
       the grid's stretch behaviour. A flat min-height + img with
       its own 16:9 aspect-ratio is the simplest stable answer:
       every row track is the same size, no math required. The
       149px target = 117px image (16:9 of a 208px column at
       1456 viewport) + 32px caption. Slightly looser at narrower
       parents; never voids. */
    min-height: 149px;
    background: #0a0a0a;
    display: flex !important;
    flex-direction: column;
  }
  /* Brett-locked 2026-05-05 PM: hide the storage-side HERO pill in
     the Pages-tab Media gallery. The pill was set when the photo
     was first uploaded (auto-flag-first-image), not when an operator
     picked a cover, so it routinely lied about which photo is on
     the cover. The magazine builder iframe has its own COVER badge
     (#magPhotoGallery) that tracks state.portraitUrl and can be
     trusted. The Media tab (#adminPhotoGallery) still shows the
     star + HERO pill for the storage flag — that's where the flag
     can be toggled, so it stays meaningful there. */
  .sa-pages-gallery-grid .sa-photo-hero-tag,
  .sa-pages-gallery-grid .sa-photo-btn--hero { display: none !important; }
  /* Brett-locked 2026-05-05 PM: drive the uniform 16:9 thumb shape
     from the IMG itself rather than the tile. Putting aspect-ratio
     on the tile with height:auto inside a CSS grid collapses the
     tile to its caption height (browsers compute the row track as
     min-content of the tile, and aspect-ratio doesn't promote a
     stretchy width into a definite block-size in that flow). The
     img with `width: 100%` + `aspect-ratio: 16/9` sets a definite
     img height; the tile sizes around it. Result: every thumb is
     identical-sized, the grid never voids, and there's no padding
     hack. */
  .sa-pages-gallery-grid .sa-photo-tile img {
    width: 100% !important;
    height: auto !important;
    aspect-ratio: 16 / 9 !important;
    display: block;
    /* Brett-locked 2026-05-12: contain (not cover) so portrait + landscape
       photos both render in full. Tile shape stays predictable (16:9 grid);
       letterboxing inside the tile is diagnostic — instantly tells the
       operator the photo's orientation. */
    object-fit: contain !important;
    background: #0a0a0a;
  }
  /* Tile is the drag-source AND a click-to-pick target. Show with
     grab cursor so the operator knows. v5: brief flash on click to
     confirm "yep, picked that one as cover hero". */
  .sa-pages-gallery-grid .sa-photo-tile { cursor: grab; }
  .sa-pages-gallery-grid .sa-photo-tile:active { cursor: grabbing; }
  .sa-pages-gallery-grid .sa-photo-tile.is-just-picked {
    outline: 3px solid var(--profile-accent, #FF0000);
    outline-offset: -1px;
    transition: outline 80ms ease;
  }
  /* Brett 2026-05-02 NIGHT v5: tile-local action feedback. The
     Media-tab status banner is hidden when on the Pages tab, so the
     tile itself surfaces what's happening. */
  .sa-photo-tile.is-deleting { opacity: 0.45; transition: opacity 120ms ease; }
  .sa-photo-tile.is-deleting::after {
    content: 'DELETING…';
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 9px; font-weight: 800; letter-spacing: 0.18em;
    color: #fff; background: rgba(180, 30, 30, 0.55);
    pointer-events: none;
  }
  .sa-photo-tile.is-saving { opacity: 0.7; }
  .sa-photo-tile.is-action-failed {
    outline: 3px solid #ff4040;
    outline-offset: -1px;
  }
  .sa-photo-tile.is-action-failed::after {
    content: 'FAILED';
    position: absolute; top: 4px; left: 4px;
    padding: 2px 6px;
    font-size: 9px; font-weight: 800; letter-spacing: 0.18em;
    color: #fff; background: #c01818; border-radius: 3px;
    pointer-events: none;
  }
  /* Brett-locked 2026-05-12 night: green tick badge on any Media-tab
     photo that's placed somewhere on the active magazine (cover hero
     or any inside-page slot). Green = "go" per feedback_green_means_go
     — placement is good. Unpublished placements count as used: operator
     intent is clear the moment they drop a photo on a slot. Top-right
     position keeps it clear of the bottom-right trash icon. */
  .sa-pages-gallery-grid .sa-photo-tile.is-used::after {
    content: '\2713';   /* ✓ */
    position: absolute;
    top: 6px;
    right: 6px;
    width: 22px;
    height: 22px;
    background: #3ad27a;
    color: #0a0a0a;
    font-weight: 900;
    font-size: 13px;
    font-family: -apple-system, 'Helvetica Neue', Arial, sans-serif;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
    z-index: 3;
    pointer-events: none;
  }
  /* Small trash icon pinned bottom-right (Brett-locked 2026-05-02
     night: 18px tile button, smaller than the Media-tab default). */
  .sa-pages-gallery-grid .sa-photo-actions {
    opacity: 1 !important;
    top: auto !important;
    right: 3px !important;
    bottom: 3px !important;
  }
  .sa-pages-gallery-grid .sa-photo-btn--del {
    width: 14px; height: 14px;
    background: rgba(0,0,0,0.7);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.14);
    font-size: 0;
    line-height: 1;
    padding: 0;
  }
  .sa-pages-gallery-grid .sa-photo-btn--del::before {
    content: "🗑";
    font-size: 8px;
  }
  .sa-pages-gallery-grid .sa-photo-btn--del:hover {
    background: rgba(180,30,30,0.95);
    border-color: rgba(255,80,80,0.7);
  }
  /* Hide the hero-set ★ button in the pages gallery — it's for the
     Media tab's hero-pick UX. The pages gallery is a drag-source. */
  .sa-pages-gallery-grid .sa-photo-btn--hero { display: none; }

  /* Ad-Builder tab iframe — same height treatment as the Pages tab,
     no split. */
  .sa-embed--ads { width: 100%; height: calc(100vh - 280px); min-height: 520px; border: none; background: #000; display: block; }

  /* Publish tab card — flat panel with hairline. */
  /* Brett-locked 2026-05-18 PM: two-column shell — left is the publish
     chrome (status / urls / publish button / share), right is the cover
     preview card. Prototype for the horizontal newsstand at the bottom
     of the portfolio. Collapses to single-column under 980px. */
  .sa-publish-shell { display: grid; grid-template-columns: minmax(0, 720px) minmax(260px, 340px); gap: 24px; align-items: start; max-width: 1100px; margin-top: 12px; }
  @media (max-width: 980px) { .sa-publish-shell { grid-template-columns: 1fr; max-width: 720px; } }
  .sa-publish-shell .sa-publish-card { margin-top: 0; max-width: none; }
  .sa-publish-card { margin-top: 12px; max-width: 720px; background: #0a0a0a; border: 1px solid #1a1a1a; border-radius: 6px; padding: 20px 24px; }
  .sa-publish-row { display: flex; align-items: baseline; gap: 14px; padding: 10px 0; border-bottom: 1px solid #1a1a1a; flex-wrap: wrap; }
  .sa-publish-row:last-of-type { border-bottom: none; }
  .sa-publish-label { font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #888; min-width: 140px; }
  .sa-publish-link { font-size: 12px; color: #fff; font-family: 'SF Mono', Menlo, monospace; word-break: break-all; }
  .sa-publish-link:hover { color: #FF0000; }
  .sa-publish-note { margin: 16px 0 0; font-size: 11px; color: #666; line-height: 1.6; }
  .sa-ad-placeholder { margin-top: 32px; padding-top: 24px; border-top: 1px solid #1a1a1a; }

  /* Publish-tab cover preview — iframes the actual flipbook so the
     operator sees the EXACT cover that will publish (masthead, theme,
     avatar, QR, sponsor logo — every overlay). Iframe is the only
     fidelity-preserving path; server-rendering a duplicate cover would
     drift from the real flipbook. Newsstand prototype: same iframe
     pattern drops straight into the portfolio strip later. */
  .sa-publish-preview { background: #0a0a0a; border: 1px solid #1a1a1a; border-radius: 6px; padding: 14px; display: flex; flex-direction: column; gap: 12px; }
  .sa-publish-preview-frame { position: relative; width: 100%; aspect-ratio: 4 / 5; background: #0a0a0a; border-radius: 4px; overflow: hidden; box-shadow: 0 4px 14px rgba(0,0,0,0.4); }
  .sa-publish-preview-iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: #0a0a0a; }
  .sa-publish-preview-empty { width: 100%; aspect-ratio: 4 / 5; background: #141414; border-radius: 4px; display: flex; align-items: center; justify-content: center; color: rgba(255,255,255,0.3); font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase; text-align: center; padding: 12px; }
  .sa-publish-preview-open { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.14); color: #fff; padding: 10px 14px; border-radius: 4px; text-decoration: none; text-align: center; font-size: 11px; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; transition: background 120ms, border-color 120ms, color 120ms; }
  .sa-publish-preview-open:hover { background: rgba(255,255,255,0.10); border-color: #fff; color: #fff; }

  /* Photo upload + gallery — squared off, hairline borders. */
  /* Visually-hidden — keeps the input clickable through the wrapping
     label, but invisible. Avoids the 'hidden' attribute / display:none
     pitfalls in some browsers that block file-picker open. */
  .sa-vhidden { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
  .sa-tab-panel .sa-photo-upload { position: relative; display: block; padding: 24px; margin: 14px 0; background: transparent; color: #fff; border: 1px dashed #333; border-radius: 6px; text-align: center; font-weight: 800; cursor: pointer; transition: border-color 120ms, color 120ms; }
  .sa-tab-panel .sa-photo-upload:hover { border-color: var(--profile-accent, #FF0000); color: var(--profile-accent, #FF0000); }
  .sa-tab-panel .sa-photo-upload.is-drag-over { border-color: #7affc8; color: #7affc8; background: rgba(122,255,200,0.06); }
  .sa-tab-panel .sa-photo-upload span { display: block; }
  .sa-tab-panel .sa-photo-upload-label { font-size: 13px; letter-spacing: 0.18em; text-transform: uppercase; }
  .sa-tab-panel .sa-photo-upload-hint { font-size: 10px; font-weight: 600; letter-spacing: 0.04em; color: #666; text-transform: none; margin-top: 6px; }
  .sa-tab-panel .sa-photo-upload:hover .sa-photo-upload-hint { color: #ff7a7a; }
  /* Media tab — main column on the left, credits aside on the right. */
  .sa-tab-panel[data-tab="media"] { display: flex; flex-direction: column; }
  .sa-media-grid { display: grid; grid-template-columns: 1fr minmax(280px, 360px); gap: 24px; align-items: start; }
  @media (max-width: 1100px) { .sa-media-grid { grid-template-columns: 1fr; } }
  .sa-media-main { min-width: 0; }
  .sa-media-credits { background: #0a0a0a; border: 1px solid #1a1a1a; border-radius: 6px; padding: 18px 20px; position: sticky; top: 0; }
  .sa-media-credits h3 { font-size: 13px; font-weight: 800; letter-spacing: 0.04em; margin: 0 0 4px; color: #7ab9ff; }
  .sa-media-credits .field { display: flex; flex-direction: column; gap: 5px; margin: 14px 0 0; font-size: 12px; }
  .sa-media-credits .field span { font-size: 9px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #888; }

  /* Kind-aware tiles. */
  .sa-tab-panel .sa-photo-tile video { width: 100%; height: 100%; object-fit: cover; display: block; background: #000; }
  .sa-photo-kind-block { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; font-family: 'SF Mono', Menlo, monospace; font-size: 24px; font-weight: 900; color: #444; background: #050505; }
  .sa-photo-kind-badge { position: absolute; top: 6px; left: 6px; padding: 2px 6px; background: rgba(0,0,0,0.75); color: #fff; font-family: 'SF Mono', Menlo, monospace; font-size: 9px; font-weight: 800; letter-spacing: 0.16em; border-radius: 2px; }
  .sa-photo-filename { display: block; padding: 6px 8px; background: #0a0a0a; color: #888; font-size: 10px; font-family: 'SF Mono', Menlo, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-top: 1px solid #1a1a1a; }
  .sa-photo-tile.sa-photo-tile--video,
  .sa-photo-tile.sa-photo-tile--audio,
  .sa-photo-tile.sa-photo-tile--pdf { aspect-ratio: auto; height: auto; }
  .sa-photo-tile.sa-photo-tile--video > video,
  .sa-photo-tile.sa-photo-tile--audio > .sa-photo-kind-block,
  .sa-photo-tile.sa-photo-tile--pdf > .sa-photo-kind-block { aspect-ratio: 3/4; }

  .sa-photo-progress { margin: 0 0 14px; padding: 10px 12px; background: #0a0a0a; border: 1px solid #1a1a1a; border-radius: 6px; }
  .sa-photo-progress-bar { width: 100%; height: 4px; background: #1a1a1a; border-radius: 2px; overflow: hidden; margin-bottom: 6px; }
  .sa-photo-progress-fill { height: 100%; background: #FF0000; width: 0%; transition: width 200ms ease-out; }
  .sa-photo-progress-text { font-family: 'SF Mono', Menlo, monospace; font-size: 10px; font-weight: 700; letter-spacing: 0.16em; color: #888; text-transform: uppercase; text-align: right; }

  /* Per-file upload queue (Brett 2026-05-02). One row per file dropped.
     Thumbnail (image preview / kind icon for video/audio/pdf) on the
     left, filename + size in the middle, status badge on the right.
     Status colours: queued=grey, uploading=amber, done=green, failed=red.
     Failed rows show the specific error message under the filename. */
  .sa-upload-queue { margin: 14px 0; padding: 16px 18px; background: #0a0a0a; border: 1px solid #1a1a1a; border-radius: 6px; }
  .sa-upload-queue-head { display: flex; align-items: baseline; gap: 14px; margin: 0 0 12px; }
  .sa-upload-queue-title { font-size: 11px; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: #fff; }
  .sa-upload-queue-summary { flex: 1; font-family: 'SF Mono', Menlo, monospace; font-size: 11px; color: #888; }
  .sa-upload-queue-clear { padding: 6px 12px; font-family: inherit; font-size: 9px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; background: transparent; border: 1px solid #2a2a2a; border-radius: 4px; color: #888; cursor: pointer; }
  .sa-upload-queue-clear:hover { color: #fff; border-color: #444; }
  .sa-upload-queue-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
  .sa-upload-row { display: grid; grid-template-columns: 56px 1fr auto; gap: 14px; align-items: center; padding: 8px 10px; background: #050505; border: 1px solid #1a1a1a; border-radius: 4px; }
  .sa-upload-thumb { width: 56px; height: 56px; border-radius: 4px; background: #141414; background-size: cover; background-position: center; display: flex; align-items: center; justify-content: center; font-family: 'SF Mono', Menlo, monospace; font-size: 11px; font-weight: 800; color: #555; }
  .sa-upload-meta { min-width: 0; }
  .sa-upload-name { display: block; font-size: 12px; font-weight: 700; color: #ddd; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sa-upload-sub { display: block; font-family: 'SF Mono', Menlo, monospace; font-size: 10px; color: #666; margin-top: 2px; }
  .sa-upload-error { display: block; font-size: 11px; color: #ff7a7a; margin-top: 4px; line-height: 1.4; }
  .sa-upload-badge { padding: 4px 10px; border-radius: 12px; font-family: 'SF Mono', Menlo, monospace; font-size: 9px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; white-space: nowrap; }
  .sa-upload-row[data-state="queued"]    .sa-upload-badge { background: #1a1a1a; color: #888; }
  .sa-upload-row[data-state="uploading"] .sa-upload-badge { background: rgba(255,196,122,0.16); color: #ffc47a; }
  .sa-upload-row[data-state="done"]      .sa-upload-badge { background: rgba(122,255,200,0.16); color: #7affc8; }
  .sa-upload-row[data-state="failed"]    .sa-upload-badge { background: rgba(255,122,122,0.16); color: #ff7a7a; }
  .sa-upload-row[data-state="failed"] { border-color: rgba(255,122,122,0.35); }
  .sa-upload-progress { width: 100%; height: 3px; background: #1a1a1a; border-radius: 2px; overflow: hidden; margin-top: 6px; opacity: 0; transition: opacity 200ms; }
  .sa-upload-progress-fill { height: 100%; width: 0%; background: var(--profile-accent, #7ab9ff); transition: width 120ms ease-out; }
  .sa-upload-row[data-state="uploading"] .sa-upload-progress { opacity: 1; }
  .sa-upload-row[data-state="uploading"] .sa-upload-progress-fill { background: #ffc47a; }
  .sa-upload-row[data-state="done"]      .sa-upload-progress { opacity: 1; }
  .sa-upload-row[data-state="done"]      .sa-upload-progress-fill { background: #7affc8; width: 100% !important; }
  .sa-upload-row[data-state="failed"]    .sa-upload-progress { opacity: 1; }
  .sa-upload-row[data-state="failed"]    .sa-upload-progress-fill { background: #ff7a7a; }

  /* Credits save indicator — pill next to the Copyright · Acknowledgements
     heading. Mirrors the autosave state for the credit fields. */
  .sa-credits-head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; margin: 0 0 6px; }
  .sa-credits-head h3 { margin: 0; }
  .sa-credits-save { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px; font-family: 'SF Mono', Menlo, monospace; font-size: 10px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; transition: background 200ms, color 200ms; }
  .sa-credits-save-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
  .sa-credits-save[data-state="saved"]   { background: rgba(122,255,200,0.16); color: #7affc8; }
  .sa-credits-save[data-state="saving"]  { background: rgba(255,196,122,0.16); color: #ffc47a; }
  .sa-credits-save[data-state="error"]   { background: rgba(255,122,122,0.16); color: #ff7a7a; }
  .sa-tab-panel .sa-photo-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 4px; margin-top: 14px; }
  .sa-tab-panel .sa-photo-tile { background: #0a0a0a; border: 1px solid #1a1a1a; border-radius: 4px; overflow: hidden; }
  .sa-tab-panel .sa-photo-tile.is-hero { border-color: var(--profile-accent, #FF0000); }
  .sa-tab-panel .sa-photo-btn { border-radius: 0; }
  .sa-tab-panel .sa-photo-empty { color: #444; font-size: 11px; letter-spacing: 0.08em; padding: 32px; }
  .sa-tab-panel .sa-photo-hero-tag { border-radius: 0; }
  .sa-photo-upload { display: block; padding: 18px; margin: 10px 0; background: #1a3a5a; color: #fff; border: 2px dashed #4ea3ff; border-radius: 6px; text-align: center; font-weight: 800; font-size: 13px; letter-spacing: 0.06em; cursor: pointer; transition: background 120ms; }
  .sa-photo-upload:hover { background: #2a4a6a; }
  .sa-photo-gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-top: 10px; }
  .sa-photo-tile { position: relative; aspect-ratio: 3/4; background: #0a0a0a; border: 1px solid #2a2a2a; border-radius: 4px; overflow: hidden; }
  .sa-photo-tile.is-hero { border-color: #FF0000; }
  .sa-photo-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .sa-photo-actions { position: absolute; top: 4px; right: 4px; display: flex; gap: 4px; opacity: 0; transition: opacity 120ms; }
  .sa-photo-tile:hover .sa-photo-actions { opacity: 1; }
  .sa-photo-btn { width: 22px; height: 22px; border: none; border-radius: 3px; background: rgba(0,0,0,0.7); color: #fff; cursor: pointer; font-size: 12px; }
  .sa-photo-btn:hover { background: #000; }
  .sa-photo-hero-tag { position: absolute; bottom: 4px; left: 4px; background: #FF0000; color: #fff; font-size: 9px; font-weight: 900; letter-spacing: 0.1em; padding: 2px 5px; border-radius: 2px; }
  .sa-photo-empty { grid-column: 1 / -1; padding: 24px; text-align: center; font-size: 12px; color: #555; }

  /* Spread tick — top-left corner of each image tile. Always visible
     (unlike .sa-photo-actions which is hover-only) because the tick IS
     the state indicator: at-a-glance, operator sees which photos are
     ticked into The Spread. Green-means-go palette per platform lock. */
  .sa-photo-tick {
    position: absolute;
    top: 6px;
    left: 6px;
    width: 24px;
    height: 24px;
    border: 1.5px solid rgba(255,255,255,0.45);
    border-radius: 5px;
    background: rgba(0,0,0,0.55);
    color: transparent;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    font: 900 14px/1 inherit;
    transition: background 120ms, border-color 120ms, color 120ms;
    z-index: 2;
  }
  .sa-photo-tick:hover { border-color: rgba(255,255,255,0.85); background: rgba(0,0,0,0.7); }
  .sa-photo-tick.is-ticked {
    background: #3ad27a;
    border-color: #3ad27a;
    color: #0a0a0a;
  }
  .sa-photo-tick.is-ticked:hover { background: #5aff9e; border-color: #5aff9e; }
  .sa-photo-tick-mark { display: inline-block; line-height: 1; transform: translateY(-1px); }

  /* Auto-save status banner — quiet by default, brightens on save. */
  .sa-form-status { font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: #555; margin: 0 0 12px; padding: 6px 10px; background: rgba(255,255,255,0.02); border-radius: 3px; transition: color 200ms, background 200ms; }
  .sa-form-status[data-state="saving"] { color: #ffc47a; background: rgba(255,196,122,0.06); }
  .sa-form-status[data-state="saved"]  { color: #7affc8; background: rgba(122,255,200,0.06); }
  .sa-form-status[data-state="error"]  { color: #ff7a7a; background: rgba(255,122,122,0.08); }

  /* PII section — locked-vault styling. Mirrors the look of the
     captured snapshot so the operator's eye doesn't have to relearn
     the layout. */
  .edit-section--private { background: #1a1408; border: 1px solid #3a2a14; border-radius: 6px; padding: 16px 18px; }
  .edit-section--private h3 { margin: 0 0 4px; font-size: 14px; color: #ffc47a; }
  .edit-section--private .edit-section-sub { font-size: 11px; color: #aaa; margin: 0 0 12px; }
  .profile-section-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; }
  .field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; }
  .field span { font-size: 11px; color: #aaa; letter-spacing: 0.04em; display: flex; align-items: center; gap: 6px; }
  .field-lock { font-size: 10px; opacity: 0.7; }
  .field input { background: #0a0a0a; border: 1px solid #2a2a2a; border-radius: 4px; color: #fff; padding: 8px 10px; font-size: 13px; font-family: inherit; }
  .field input:focus { outline: none; border-color: var(--profile-accent, #FF0000); }
  a { color: #ff7a7a; text-decoration: none; }
  a:hover { text-decoration: underline; }

  /* ── Ad Builder (Brett-locked 2026-05-02 night v2) ────────────
     Server-rendered on #tab=ads. Was previously inside the magazine.html
     iframe; moved out so it lives natively in the parent's tab panel. */
  .sa-adbuilder { display: flex; flex-direction: column; gap: 14px; max-width: 880px; }
  .sa-adbuilder-head { margin: 0; font-size: 16px; font-weight: 800; letter-spacing: 0.04em; color: #fff; }
  .sa-adbuilder-hint { margin: 0; font-size: 12px; color: rgba(255,255,255,0.55); line-height: 1.45; font-style: italic; }
  .msb-slots { display: flex; flex-direction: column; gap: 10px; }
  .msb-slot {
    background: rgba(0,0,0,0.35);
    border: 1px solid rgba(255,255,255,0.1);
    border-left: 3px solid #FF0000;
    border-radius: 4px;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .msb-slot-head { display: flex; align-items: center; gap: 10px; }
  .msb-slot-num { font-size: 13px; font-weight: 900; color: #FF0000; width: 18px; text-align: center; }
  .msb-fmt-picker { flex: 1; display: inline-flex; gap: 4px; padding: 2px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.08); border-radius: 4px; }
  .msb-fmt-btn { flex: 1; background: transparent; border: 1px solid transparent; border-radius: 3px; color: rgba(255,255,255,0.55); font-family: inherit; font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; padding: 8px 10px; cursor: pointer; transition: color 120ms, background 120ms, border-color 120ms; }
  .msb-fmt-btn:hover { color: #fff; background: rgba(255,255,255,0.05); }
  .msb-fmt-btn.is-active { color: #fff; background: rgba(255,0,0,0.18); border-color: rgba(255,0,0,0.6); }
  .msb-slot-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(255,255,255,0.75); cursor: pointer; }
  .msb-slot-toggle input[type="checkbox"] { accent-color: #FF0000; cursor: pointer; }
  .msb-slot-body { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
  .msb-logo-wrap { flex: 0 0 64px; width: 64px; height: 64px; }
  .msb-logo-pad { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; background: rgba(255,255,255,0.04); border: 1px dashed rgba(255,255,255,0.25); border-radius: 3px; cursor: pointer; flex-direction: column; gap: 2px; overflow: hidden; transition: border-color 120ms; }
  .msb-logo-pad:hover { border-color: #FF0000; }
  .msb-logo-pad-plus { font-size: 18px; font-weight: 800; color: rgba(255,255,255,0.6); }
  .msb-logo-pad-label { font-size: 8px; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(255,255,255,0.4); }
  .msb-logo-img { width: 100%; height: 100%; object-fit: contain; display: block; }
  .msb-track-readout { flex: 1; display: flex; flex-direction: column; gap: 2px; background: #0a0a0a; border: 1px solid rgba(255,255,255,0.08); border-radius: 3px; padding: 8px 10px; min-width: 200px; }
  .msb-track-label { font-size: 8px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(255,255,255,0.45); }
  .msb-track-code { font-family: 'SF Mono', Menlo, monospace; font-size: 11px; color: #fff; letter-spacing: 0.04em; }
  .msb-status { font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: rgba(255,255,255,0.5); }
  .msb-status[data-kind="ok"]      { color: #5AFF9E; }
  .msb-status[data-kind="err"]     { color: #FF6680; }
  .msb-status[data-kind="pending"] { color: rgba(255,255,255,0.6); }

  /* ────────────────────────────────────────────────────────────
     MAGAZINES module — Brett-locked 2026-05-04 PM
     Multi-magazine-per-record. Designed to lift cleanly into
     other tenants (scottwagner: many magazines per property).
     Numbered tabs 1-4 (Magazines / Media / Pages / Publish).
     ──────────────────────────────────────────────────────────── */

  /* Visual divider in the tab strip — separates athlete-level
     tabs (Profile / Training / AI / Sponsors) from magazine-
     scoped tabs (1. Magazines onward). */
  .sa-tab-divider {
    flex: 0 0 auto;
    width: 1px;
    align-self: stretch;
    margin: 0 6px;
    background: linear-gradient(
      to bottom,
      transparent 0%,
      rgba(255,255,255,0.18) 25%,
      rgba(255,255,255,0.18) 75%,
      transparent 100%
    );
  }

  /* Magazine-scoped tabs (Media / Pages / Publish) dim until a
     magazine is active. Toggled by client JS adding/removing
     [data-mag-active] on the .sa-tabs element. */
  .sa-tabs:not([data-mag-active="true"]) .sa-tab--mag-scoped {
    opacity: 0.32;
    pointer-events: none;
  }
  .sa-tabs:not([data-mag-active="true"]) .sa-tab--mag-scoped:focus-visible {
    pointer-events: auto;
  }

  /* Brett-locked 2026-05-20: .sa-mag-pill rules retired with the
     "Editing: <magazine>" pill itself. The .sa-mag-context bar inside
     each magazine-scoped tab carries the "Back to Magazines" action. */

  /* Magazines panel chrome */
  .sa-mag-header { margin-bottom: 18px; }
  .sa-mag-h {
    font-size: 22px;
    font-weight: 600;
    color: #fff;
    margin: 0 0 6px;
    letter-spacing: -0.005em;
  }
  .sa-mag-create {
    display: flex;
    gap: 10px;
    margin-bottom: 22px;
    max-width: 720px;
  }
  .sa-mag-create-title {
    flex: 1 1 auto;
    background: #0a0a0a;
    border: 1px solid #2a2a2a;
    border-radius: 6px;
    color: #f2f2f2;
    font-size: 13px;
    font-family: inherit;
    padding: 10px 14px;
  }
  .sa-mag-create-title:focus {
    outline: none;
    border-color: #ff3d3d;
    background: #111;
  }
  /* Brett-locked 2026-05-06 night — advance buttons go green per
     feedback_green_means_go.md. + New magazine creates forward; red
     was conflicting with stop-and-think semantics. */
  .sa-mag-create-btn {
    flex: 0 0 auto;
    background: #3ad27a;
    color: #0a0a0a;
    border: 1px solid #3ad27a;
    border-radius: 6px;
    padding: 10px 18px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.02em;
    font-family: inherit;
    cursor: pointer;
    transition: background 120ms, border-color 120ms;
  }
  .sa-mag-create-btn:hover { background: #5aff9e; border-color: #5aff9e; }
  .sa-mag-create-btn:disabled { opacity: 0.45; cursor: not-allowed; }

  /* Brett-locked 2026-05-09: two-column layout — magazine cards on the
     left, newsstand gallery on the right. The gallery is structured as
     sections so Collections (when built) drop in as additional section
     headers + thumbnail grids without re-laying out the panel. */
  .sa-mag-grid {
    display: grid;
    grid-template-columns: minmax(0, 480px) minmax(260px, 320px);
    gap: 12px;
    max-width: 1400px;
    align-items: start;
  }
  @media (max-width: 1024px) {
    .sa-mag-grid {
      grid-template-columns: 1fr;
    }
  }
  .sa-mag-list-col { min-width: 0; }
  .sa-mag-newsstand {
    background: #0a0a0a;
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 8px;
    padding: 16px;
    position: sticky;
    top: 16px;
  }
  .sa-mag-newsstand-section + .sa-mag-newsstand-section {
    margin-top: 22px;
    padding-top: 22px;
    border-top: 1px solid rgba(255,255,255,0.06);
  }
  .sa-mag-newsstand-section-title {
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.55);
    margin: 0 0 12px;
  }
  .sa-mag-newsstand-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
  }
  .sa-mag-thumb-wrap {
    position: relative;
    display: block;
  }
  .sa-mag-thumb {
    background: transparent;
    border: 0;
    padding: 0;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    color: inherit;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
    transition: transform 140ms ease;
  }
  .sa-mag-thumb:hover { transform: translateY(-1px); }
  /* Hover-revealed toolbar — Edit / Archive / Delete pencils on every
     thumb. Brett-locked 2026-05-11: every magazine gets the same affordances
     regardless of position (featured card or newsstand thumb). */
  .sa-mag-thumb-toolbar {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 2;
    display: flex;
    gap: 4px;
    opacity: 0;
    transform: translateY(-3px);
    transition: opacity 160ms ease, transform 160ms ease;
    pointer-events: none;
  }
  .sa-mag-thumb-wrap:hover .sa-mag-thumb-toolbar,
  .sa-mag-thumb-wrap:focus-within .sa-mag-thumb-toolbar {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  .sa-mag-thumb-tool {
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(0,0,0,0.78);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 4px;
    cursor: pointer;
    padding: 0;
    transition: background 140ms ease, border-color 140ms ease, transform 140ms ease;
  }
  .sa-mag-thumb-tool:hover {
    background: rgba(255,255,255,0.16);
    border-color: rgba(255,255,255,0.4);
    transform: translateY(-1px);
  }
  .sa-mag-thumb-tool:focus-visible {
    outline: 2px solid #FF0000;
    outline-offset: 2px;
  }
  .sa-mag-thumb-tool--danger:hover {
    background: rgba(255,0,0,0.28);
    border-color: rgba(255,0,0,0.6);
  }
  .sa-mag-thumb-cover {
    position: relative;
    aspect-ratio: 4 / 5;
    background: #050505 center / cover no-repeat;
    border: 1px solid rgba(255,255,255,0.10);
    border-radius: 5px;
    overflow: hidden;
    transition: border-color 120ms ease, box-shadow 120ms ease;
    /* Brett-locked 2026-05-21: container-type enables cqi units for
       children so the masthead font-size auto-fits the thumb width
       (mirrors the builder's clamp+cqi pattern). */
    container-type: inline-size;
  }
  /* Graduation backing the masthead area so the title reads against any
     cover photo. Brett-locked 2026-05-18 PM: title carries through every
     step of the flow — sits ON the cover, not as adjacent text.
     Brett-locked 2026-05-21: gradient lives at TOP because the masthead
     lives at TOP — that's where it sits on the real cover, and the thumb
     must look like the cover. */
  .sa-mag-thumb-cover::after {
    content: '';
    position: absolute;
    left: 0; right: 0; top: 0;
    height: 55%;
    background: linear-gradient(180deg, rgba(0,0,0,0.78) 0%, rgba(0,0,0,0) 100%);
    pointer-events: none;
    z-index: 1;
  }
  .sa-mag-thumb-cover--empty::after { display: none; }
  .sa-mag-thumb:hover .sa-mag-thumb-cover {
    border-color: rgba(255,61,61,0.55);
  }
  .sa-mag-thumb.is-active .sa-mag-thumb-cover {
    border-color: #3ad27a;
    box-shadow: 0 0 0 1.5px #3ad27a, 0 0 10px rgba(58,210,122,0.32);
  }
  .sa-mag-thumb-cover--empty {
    background: linear-gradient(135deg, rgba(255,255,255,0.04) 0%, rgba(0,0,0,0.6) 100%);
    border-style: dashed;
    border-color: rgba(255,255,255,0.08);
  }
  .sa-mag-thumb-edition {
    position: absolute;
    top: 6px;
    left: 6px;
    background: rgba(0,0,0,0.7);
    color: #fff;
    border: 1px solid rgba(255,61,61,0.55);
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.05em;
  }
  /* Brett-locked 2026-05-21: thumb title is the masthead. Sits at the
     TOP of the cover, where the masthead lives on the real cover. Bold
     italic white uppercase mirrors the .sa-mag-card-masthead-static
     treatment at thumb scale — one visual identity from card to thumb
     to builder. Edition badge stays top-left; title clears below it.
     font-size uses clamp + cqi (container query inline) so the masthead
     auto-fits the thumb width — mirrors the builder's clamp+cqi pattern.
     14cqi = 14% of the thumb cover width, clamped between 12px and 28px
     so very short words don't blow up and very long words stay readable. */
  .sa-mag-thumb-title {
    position: absolute;
    left: 10px;
    right: 10px;
    top: 26px;
    z-index: 2;
    font-family: 'Montserrat', system-ui, sans-serif;
    font-size: clamp(12px, 13cqi, 26px);
    font-weight: 900;
    font-style: italic;
    letter-spacing: -0.03em;
    line-height: 1;
    color: #fff;
    text-transform: uppercase;
    text-shadow: 0 2px 8px rgba(0,0,0,0.7);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .sa-mag-thumb.is-active .sa-mag-thumb-title { color: #5aff9e; }
  .sa-mag-thumb--placeholder { cursor: default; }
  .sa-mag-thumb--placeholder:hover { transform: none; }
  .sa-mag-thumb--placeholder:hover .sa-mag-thumb-cover { border-color: rgba(255,255,255,0.08); }

  .sa-mag-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 14px;
  }

  /* Brett-locked 2026-05-09: contextual cover header above mag-scoped
     tabs. Anchors the operator's eye to which magazine they're working
     on once they've advanced past the Magazines tab. Click the cover
     OR the Back link to return to Magazines. */
  .sa-mag-context {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    margin-bottom: 18px;
    background: #0a0a0a;
    border: 1px solid rgba(255,255,255,0.10);
    border-radius: 8px;
    max-width: 1400px;
  }
  .sa-mag-context-back {
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid rgba(255,255,255,0.18);
    color: rgba(255,255,255,0.72);
    font-family: inherit;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    padding: 8px 12px;
    border-radius: 4px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: background 120ms, border-color 120ms, color 120ms;
  }
  .sa-mag-context-back:hover {
    background: rgba(255,255,255,0.06);
    border-color: rgba(255,255,255,0.4);
    color: #fff;
  }
  .sa-mag-context-cover {
    position: relative;
    flex: 0 0 auto;
    width: 56px;
    height: 70px;            /* 4:5 cover ratio */
    background: #111 center / cover no-repeat;
    border: 1px solid rgba(255,61,61,0.55);
    border-radius: 4px;
    cursor: pointer;
    transition: border-color 120ms, box-shadow 120ms;
  }
  .sa-mag-context-cover:hover {
    border-color: #ff5757;
    box-shadow: 0 0 0 2px rgba(255,61,61,0.18);
  }
  .sa-mag-context-cover--empty {
    background: linear-gradient(135deg, rgba(255,255,255,0.04) 0%, rgba(0,0,0,0.6) 100%);
    border-style: dashed;
    border-color: rgba(255,255,255,0.18);
  }
  .sa-mag-context-edition {
    position: absolute;
    bottom: 4px;
    right: 4px;
    background: rgba(0,0,0,0.75);
    color: #fff;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.04em;
    padding: 1px 5px;
    border-radius: 2px;
  }
  .sa-mag-context-text {
    flex: 1 1 auto;
    min-width: 0;
  }
  .sa-mag-context-title {
    color: #fff;
    font-size: 16px;
    font-weight: 800;
    margin: 0 0 2px;
    letter-spacing: 0.01em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .sa-mag-context-theme {
    color: rgba(255,255,255,0.55);
    font-size: 12px;
    font-style: italic;
    margin: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Header is always rendered but hidden by default; JS unhides only when
     a magazine is active AND the operator is on a mag-scoped tab. */
  .sa-mag-context[hidden] { display: none; }

  /* Brett-locked 2026-05-09: dim the Media-tab photo gallery so the
     context header above it is the visual anchor. The tiles are still
     fully visible + interactive (HERO badge, delete X), just receded. */
  .sa-photo-gallery--mag-scoped .sa-photo-tile {
    opacity: 0.55;
    transition: opacity 140ms ease;
  }
  .sa-photo-gallery--mag-scoped .sa-photo-tile:hover,
  .sa-photo-gallery--mag-scoped .sa-photo-tile:focus-within {
    opacity: 1;
  }
  .sa-mag-empty {
    grid-column: 1 / -1;
    padding: 32px;
    color: #666;
    font-size: 13px;
    font-style: italic;
    text-align: center;
    border: 1px dashed rgba(255,255,255,0.08);
    border-radius: 8px;
  }
  .sa-mag-card {
    display: flex;
    flex-direction: column;
    background: #0e0e0e;
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 8px;
    overflow: hidden;
    transition: border-color 120ms, transform 120ms;
  }
  .sa-mag-card:hover {
    border-color: rgba(255,61,61,0.45);
    transform: translateY(-1px);
  }
  .sa-mag-card-cover {
    /* Brett-locked 2026-05-05: 4:5 — matches the actual magazine page
       ratio (magazine.css:404 → page is width × width*1.25). The earlier
       9:16 card was misleading because magazine pages are NOT phone-tall. */
    position: relative;
    aspect-ratio: 4 / 5;
    background: #050505 center / cover no-repeat;
    border-bottom: 1px solid rgba(255,255,255,0.06);
    display: flex;
    align-items: flex-end;
    justify-content: flex-start;
    padding: 12px;
  }
  .sa-mag-card-cover[data-empty="true"] {
    background: linear-gradient(135deg, #1a1a1a 0%, #050505 100%);
  }
  .sa-mag-card-cover[data-empty="true"]::after {
    content: 'No cover yet';
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    color: rgba(255,255,255,0.18);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
  }
  .sa-mag-card-edition {
    position: relative;
    z-index: 1;
    background: rgba(0,0,0,0.65);
    border: 1px solid rgba(255,61,61,0.6);
    color: #fff;
    border-radius: 4px;
    padding: 3px 8px;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.06em;
  }
  .sa-mag-card-body { padding: 12px 14px 14px; }
  /* Brett-locked 2026-05-09 — redesigned card.
     Masthead text box at TOP of frame, always visible from creation.
     Theme text box BELOW cover. Action row at the bottom in colors:
     Save (green), Edit (blue), Open (green arrow), Archive (orange),
     Delete (red). Both text boxes have an edit form (input) and a
     static form (h4 / p) toggled by [data-editing] on the card. */
  /* Magazine card cover overlay — Brett-locked 2026-05-11.
     Three stacked text rows in the position where a published cover
     puts them: SLUGLINE on top, MASTHEAD (big italic) in the middle,
     MAGAZINE label below. All left-aligned to match the Walker /
     real-magazine reference. Operator clicks any of them to edit. */
  .sa-mag-card-masthead-overlay {
    position: absolute;
    top: 28px;
    left: 16px;
    right: 16px;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    /* Brett-locked 2026-05-28 (Explore-diagnosed): gap = 0 because
       child margins (masthead margin-bottom + magword margin-top) own
       the spacing now, mirroring the engine's flex-column model in
       Magazine/engine/css/cover.css.js. Was gap: 2px which conflicted
       with the absolute 24px on masthead. */
    gap: 0;
    /* container-type enables `cqi` resolution inside the overlay so
       both masthead AND magword scale with overlay width — same shape
       on every card, no edit/static drift. */
    container-type: inline-size;
    /* pointer-events auto so the listEl click handler can route
       overlay clicks to startEdit instead of falling through to the
       cover's upload-cover action. */
    pointer-events: auto;
  }
  /* Shared text-style helpers — kicker + masthead + magword all live
     in the same overlay but use different sizes. Common: left-aligned,
     uppercase, Montserrat, no input borders, transparent backgrounds. */
  .sa-mag-card-kicker,
  .sa-mag-card-kicker-static,
  .sa-mag-card-magword,
  .sa-mag-card-magword-static {
    display: block;
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
    outline: none;
    width: 100%;
    text-align: left;
    font-family: 'Montserrat', system-ui, sans-serif;
    text-transform: uppercase;
  }
  /* SLUGLINE — small caps eyebrow at the top.
     Brett-locked 2026-05-28 (Explore-diagnosed): color + font-size now
     mirror the engine's .mag-cover-kicker math
     (Magazine/engine/css/cover.css.js:46-62):
       - color: rgba(255,255,255,0.9) — white, NOT red. Card was
         hardcoded #FF0000; engine renders white. Drift fixed.
       - font-size: clamp(8px, 2.2cqi, 12px) — scales with overlay
         width, same as engine. Card was fixed 10px. */
  .sa-mag-card-kicker-static,
  .sa-mag-card-kicker {
    font-size: clamp(8px, 2.2cqi, 12px);
    font-weight: 700;
    letter-spacing: 0.32em;
    color: rgba(255, 255, 255, 0.9);
    text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55);
    line-height: 1.1;
    cursor: text;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .sa-mag-card-kicker::placeholder,
  .sa-mag-card-kicker-static:empty::before {
    color: rgba(255, 255, 255, 0.35);
  }

  /* MASTHEAD — Montserrat Black Italic, white, scaled by JS to fill
     the cover width. Input + static share the same base size so the
     visual swap between edit and display modes feels seamless.
     Brett-locked 2026-05-11: no red text-stroke — the masthead is the
     wordmark, not a sticker. Plain white over the cover photo with a
     soft shadow for legibility. */
  .sa-mag-card-masthead-static {
    cursor: text;
    /* Brett-locked 2026-05-28 (Explore-diagnosed): margin-bottom dropped
       from 24px → 0. The 24px was an ABSOLUTE gap that didn't scale with
       the masthead font-size, so when JS bumped font-size up, the magword
       stayed too far below ("disjointed from BEACH"). Now the magword's
       own margin-top: 0.1em owns the gap (matches engine math). */
    margin: 4px 0 0;
    font-family: 'Montserrat', system-ui, sans-serif;
    font-weight: 900;
    /* italic state-driven from data-italic on the card root; mirrors
       what the operator saved on the Pages tab. Card was hardcoded
       italic and drifted from the saved state. */
    font-style: normal;
    /* cqi-based clamp matches engine's .mag-cover-title math
       (Magazine/engine/css/cover.css.js:80): clamp(28px, 13.5cqi, 84px).
       Card was clamp(20px, 14cqi, 56px) — drift on both lower bound and
       upper bound. JS fitMastheadInCard then computes a target font-size
       from this baseline (capped at engine's 1.65× scale). */
    font-size: clamp(28px, 13.5cqi, 84px);
    line-height: 0.9;
    letter-spacing: -0.04em;
    color: #fff;
    text-transform: uppercase;
    text-shadow: 0 2px 12px rgba(0,0,0,0.6);
    white-space: nowrap;
    overflow: visible;
    text-align: left;
    width: 100%;
    display: block;
  }
  .sa-mag-card-masthead {
    /* MATCH static-mode margin (no bottom gap — magword owns spacing). */
    margin: 4px 0 0;
    padding: 0;
    width: 100%;
    background: transparent;
    border: 0;
    outline: none;
    font-family: 'Montserrat', system-ui, sans-serif;
    font-weight: 900;
    /* MATCH static-mode italic — driven from data-italic, not hardcoded. */
    font-style: normal;
    /* MATCH static + engine math exactly: clamp(28px, 13.5cqi, 84px). */
    font-size: clamp(28px, 13.5cqi, 84px);
    line-height: 0.9;
    letter-spacing: -0.04em;
    color: #fff;
    text-transform: uppercase;
    text-align: left;
    text-shadow: 0 2px 12px rgba(0,0,0,0.6);
    display: none;
  }
  /* Italic state-driven CSS — toggled from data-italic="true" on the
     card root. Same shape as the engine cover's .mag-cover[data-italic]
     pattern. Brett-locked 2026-05-28. */
  .sa-mag-card[data-italic="true"] .sa-mag-card-masthead-static,
  .sa-mag-card[data-italic="true"] .sa-mag-card-masthead {
    font-style: italic;
  }
  .sa-mag-card-masthead::placeholder {
    color: rgba(255,255,255,0.35);
  }
  .sa-mag-card-masthead:focus {
    background: rgba(0,0,0,0.25);
  }
  .sa-mag-card-masthead-hint {
    display: none;
    font-family: 'Montserrat', system-ui, sans-serif;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #FFD680;
    background: rgba(0,0,0,0.7);
    border: 1px solid rgba(255,170,0,0.4);
    border-radius: 3px;
    padding: 4px 8px;
    text-align: left;
    align-self: flex-start;
    max-width: 100%;
    line-height: 1.3;
    text-shadow: none;
    -webkit-text-stroke: 0;
    text-stroke: 0;
    margin-top: 2px;
  }
  .sa-mag-card-masthead-hint[data-visible="true"] {
    display: inline-block;
  }

  /* MAGAZINE label — bold caps below the masthead. Format type:
     MAGAZINE, NEWSLETTER, BROCHURE, etc. Editable inline.
     Brett-locked 2026-05-28 (Explore-diagnosed): font-size and gap now
     mirror the engine's .mag-cover-mag math (Magazine/engine/css/cover.css.js):
       - clamp(10px, 6.5cqi, 26px) — same 6.5cqi ratio as engine, scaled
         clamp bounds for the smaller thumbnail context
       - margin-top: 0.1em — gap proportional to magword's OWN font-size,
         exactly like engine. Was hardcoded 13px + absolute 24px masthead
         margin = "disjointed from BEACH" when title grew via JS autofit. */
  .sa-mag-card-magword-static,
  .sa-mag-card-magword {
    font-size: clamp(10px, 6.5cqi, 26px);
    margin-top: 0.1em;
    font-weight: 900;
    letter-spacing: 0.22em;
    color: #fff;
    text-shadow: 0 1px 4px rgba(0,0,0,0.5);
    line-height: 1;
    cursor: text;
  }
  .sa-mag-card-magword::placeholder {
    color: rgba(255,255,255,0.5);
  }

  .sa-mag-card-theme-row {
    padding: 12px 14px 8px;
  }
  .sa-mag-card-theme-label {
    display: block;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: #FF0000;
    margin-bottom: 6px;
  }
  .sa-mag-card-theme-static {
    color: #ccc;
    font-size: 12.5px;
    line-height: 1.4;
    margin: 0;
    font-style: italic;
  }
  .sa-mag-card-theme-placeholder {
    color: rgba(255,255,255,0.30);
    font-style: italic;
  }
  .sa-mag-card-theme {
    width: 100%;
    background: #0a0a0a;
    border: 1px solid rgba(255,255,255,0.16);
    border-radius: 5px;
    color: #fff;
    font-family: inherit;
    font-size: 12.5px;
    padding: 7px 10px;
    display: none;
    font-style: italic;
  }
  .sa-mag-card-theme::placeholder {
    color: rgba(255,255,255,0.32);
  }
  .sa-mag-card-theme:focus {
    outline: none;
    border-color: rgba(255,61,61,0.55);
    background: #111;
  }

  .sa-mag-card-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    color: #888;
    font-size: 11px;
    padding: 4px 14px 10px;
  }
  .sa-mag-card-status {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }
  .sa-mag-card-status[data-status="draft"]     { background: rgba(255,255,255,0.05); color: #aaa; border: 1px solid rgba(255,255,255,0.12); }
  .sa-mag-card-status[data-status="published"] { background: rgba(58,210,122,0.10); color: #5aff9e; border: 1px solid rgba(58,210,122,0.45); }
  .sa-mag-card-status[data-status="archived"]  { background: rgba(255,255,255,0.03); color: #555; border: 1px solid rgba(255,255,255,0.06); }
  .sa-mag-card-actions {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    padding: 0 14px 14px;
  }
  .sa-mag-card-btn {
    flex: 1 1 auto;
    background: transparent;
    border: 1px solid rgba(255,255,255,0.14);
    color: #d6d6d6;
    border-radius: 5px;
    padding: 7px 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    font-family: inherit;
    cursor: pointer;
    transition: background 120ms, border-color 120ms, color 120ms;
  }
  .sa-mag-card-btn:hover {
    background: rgba(255,255,255,0.05);
    border-color: rgba(255,255,255,0.28);
    color: #fff;
  }
  .sa-mag-card-btn--primary {
    background: #ff3d3d;
    border-color: #ff3d3d;
    color: #0a0a0a;
  }
  .sa-mag-card-btn--primary:hover {
    background: #ff5757;
    border-color: #ff5757;
    color: #0a0a0a;
  }
  .sa-mag-card-btn--danger:hover {
    background: rgba(255,61,61,0.10);
    border-color: rgba(255,61,61,0.55);
    color: #ff7a7a;
  }

  /* Brett-locked 2026-05-09 — edit-mode visibility:
     [data-edit] elements (text inputs + Save button) hide in static mode,
     show in edit mode.
     [data-static] elements (h4 / p / Edit / Open / Archive / Delete) hide
     in edit mode, show in static mode.
     Card defaults to static mode; [data-editing="true"] flips it. */
  .sa-mag-card [data-edit] { display: none; }
  .sa-mag-card[data-editing="true"] [data-edit] { display: block; }
  .sa-mag-card[data-editing="true"] [data-static] { display: none; }
  /* Buttons need flex display in edit mode, not block. */
  .sa-mag-card[data-editing="true"] .sa-mag-card-btn[data-edit] { display: inline-flex; align-items: center; }

  /* Coloured action buttons. Brett-locked 2026-05-09:
     Save = green (commit), Edit = blue (modify), Open = existing green
     arrow (advance), Archive = orange (stop-and-think hide), Delete =
     red (stop-and-think remove). */
  .sa-mag-card-btn--save {
    background: #3ad27a;
    border-color: #3ad27a;
    color: #0a0a0a;
    flex: 1 1 100%;  /* full-width Save in edit mode (only edit-action visible) */
    font-weight: 800;
    letter-spacing: 0.06em;
  }
  .sa-mag-card-btn--save:hover {
    background: #5aff9e;
    border-color: #5aff9e;
    color: #0a0a0a;
  }
  .sa-mag-card-btn--edit {
    background: rgba(80,140,255,0.14);
    border-color: rgba(80,140,255,0.55);
    color: #82a8ff;
  }
  .sa-mag-card-btn--edit:hover {
    background: rgba(80,140,255,0.24);
    border-color: #82a8ff;
    color: #b9d0ff;
  }
  .sa-mag-card-btn--archive {
    background: rgba(255,165,80,0.10);
    border-color: rgba(255,165,80,0.55);
    color: #ffb05a;
  }
  .sa-mag-card-btn--archive:hover {
    background: rgba(255,165,80,0.20);
    border-color: #ffb05a;
    color: #ffd09a;
  }
  .sa-mag-card-btn--delete {
    background: rgba(255,61,61,0.10);
    border-color: rgba(255,61,61,0.55);
    color: #ff7a7a;
  }
  .sa-mag-card-btn--delete:hover {
    background: rgba(255,61,61,0.22);
    border-color: #ff5757;
    color: #ffaaaa;
  }

  /* Cover dropzone — Brett-locked 2026-05-04 PM v3.
     The 9:16 cover area is itself the upload target. Click anywhere on
     it (empty OR filled) to replace. Drag-drop image onto it works too.
     Progress bar at the bottom edge during upload. */
  .sa-mag-card-cover {
    cursor: pointer;
    transition: background-color 120ms;
  }
  .sa-mag-card-cover:focus-visible {
    outline: 2px solid #ff3d3d;
    outline-offset: 2px;
  }
  .sa-mag-card-cover[data-drag-active="true"] {
    background-color: rgba(255,61,61,0.14) !important;
  }
  .sa-mag-card-cover[data-empty="true"]::after {
    /* Override the existing "No cover yet" placeholder with a clearer
       upload affordance. The CTA below provides the action label. */
    content: '';
  }
  .sa-mag-card-cover-cta {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    pointer-events: none;
    z-index: 1;
  }
  .sa-mag-cover-upload {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px;
    background: rgba(255,61,61,0.10);
    border: 1.5px dashed rgba(255,61,61,0.55);
    border-radius: 6px;
    color: #ff7a7a;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }
  .sa-mag-card-cover[data-empty="true"]:hover .sa-mag-cover-upload,
  .sa-mag-card-cover[data-empty="true"]:focus-visible .sa-mag-cover-upload {
    background: rgba(255,61,61,0.18);
    border-color: #ff3d3d;
    color: #fff;
  }
  /* Filled cover: hide CTA by default, show on hover. */
  .sa-mag-card-cover[data-empty="false"] .sa-mag-card-cover-cta {
    opacity: 0;
    background: rgba(0,0,0,0.55);
    transition: opacity 140ms;
  }
  .sa-mag-card-cover[data-empty="false"]:hover .sa-mag-card-cover-cta,
  .sa-mag-card-cover[data-empty="false"]:focus-visible .sa-mag-card-cover-cta {
    opacity: 1;
  }
  .sa-mag-cover-replace {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: rgba(0,0,0,0.6);
    border: 1px solid rgba(255,255,255,0.28);
    border-radius: 6px;
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }
  /* When data-empty=true the existing ::after used to render "No cover
     yet" — disable it so our CTA button stands alone. */
  .sa-mag-card-cover[data-empty="true"]::after { content: none; }

  /* Progress bar — slides up from the bottom edge of the cover. */
  .sa-mag-card-cover-progress {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: rgba(0,0,0,0.4);
    z-index: 2;
  }
  .sa-mag-card-cover-progress-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, #ff3d3d, #ff7a7a);
    transition: width 180ms ease-out;
  }
  .sa-mag-card-cover-progress[data-label]::after {
    content: attr(data-label);
    position: absolute;
    bottom: 6px;
    right: 6px;
    background: rgba(0,0,0,0.75);
    color: #fff;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
  }

  /* Reposition affordance — Brett-locked 2026-05-04 PM v4.
     16:9 photo dropped into 9:16 frame is the common case. Drag the
     cover to pan. Cursor: grab → grabbing. The "Drag to reposition"
     label pairs with "Replace cover" inside the hover overlay. */
  .sa-mag-card-cover[data-empty="false"] { cursor: grab; }
  .sa-mag-card-cover[data-empty="false"][data-repositioning="true"] {
    cursor: grabbing;
  }
  .sa-mag-card-cover[data-empty="false"] .sa-mag-card-cover-cta {
    background: rgba(0,0,0,0.50);
    flex-direction: column;
    gap: 8px;
  }
  .sa-mag-cover-reposition {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(0,0,0,0.6);
    border: 1px solid rgba(255,255,255,0.20);
    border-radius: 6px;
    color: #d6d6d6;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    pointer-events: none; /* it's just a label — drag happens on the cover itself */
  }
  /* Replace button DOES need pointer events (it triggers file picker). */
  .sa-mag-card-cover[data-empty="false"] .sa-mag-cover-replace {
    pointer-events: auto;
  }
  /* During an active reposition drag, fade the overlay so the user
     can see the photo motion clearly. */
  .sa-mag-card-cover[data-repositioning="true"] .sa-mag-card-cover-cta {
    opacity: 0;
  }

  /* End-of-page trident marker (Brett-locked 2026-05-05).
     Appended to every .sa-tab-panel by admin shell-sync JS. White
     trident + small "End of page" label, faint, sits below the last
     real content. Two roles: operator gets a clear "you're at the
     bottom" cue; if it isn't visible after scrolling down, that's a
     diagnostic that something in the layout chain is clipping. */
  .sa-end-trident {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 28px 0 16px;
    margin-top: 24px;
    opacity: 0.45;
  }
  .sa-end-trident img {
    width: 22px;
    height: 22px;
    filter: drop-shadow(0 0 4px rgba(255,0,0,0.35));
  }
  .sa-end-trident span {
    font-family: inherit;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: #777;
  }
  /* On the Pages tab the parent-level trident (auto-appended to the
     panel root by appendEndTridents) is meaningless — the panel is
     viewport-locked and that trident just inflates it past viewport.
     But the manually-placed trident inside .sa-pages-gallery DOES
     belong (gallery has its own scroll). Brett-locked 2026-05-18 PM:
     scope this hide to DIRECT CHILDREN only so nested tridents survive. */
  .sa-tab-panel[data-tab="pages"] > .sa-end-trident {
    display: none;
  }

  /* CageRacer Card preview — Brett-locked 2026-05-11. Replaces the
     standalone QR + raw "Download Card" button in the operator hero.
     Shows the actual landscape /card/<slug>.svg as a clickable
     membership card. Hover lifts + glows red; the "Tap to Download"
     CTA fades in over a darkened bottom gradient. The whole pad is
     a <button class="sa-card-pad sa-card-download"> so the existing
     SVG-to-PNG download handler in sales-athletes.js still wires
     unchanged. Feel = membership / belonging / reward. */
  .sa-card-pad {
    position: relative;
    display: block;
    width: 400px;
    aspect-ratio: 16 / 9;
    background: #000;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 12px;
    overflow: hidden;
    cursor: pointer;
    padding: 0;
    margin: 0;
    box-shadow: 0 12px 32px rgba(0,0,0,0.55), 0 2px 6px rgba(0,0,0,0.4);
    transition: transform 220ms ease, box-shadow 220ms ease, border-color 220ms ease;
  }
  .sa-card-pad:hover,
  .sa-card-pad:focus-visible {
    transform: translateY(-3px);
    border-color: rgba(255,0,0,0.55);
    box-shadow: 0 18px 44px rgba(255,0,0,0.22), 0 6px 16px rgba(0,0,0,0.6);
    outline: none;
  }
  .sa-card-pad:active {
    transform: translateY(-1px);
    transition-duration: 80ms;
  }
  .sa-card-pad-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 320ms ease;
  }
  .sa-card-pad:hover .sa-card-pad-img,
  .sa-card-pad:focus-visible .sa-card-pad-img {
    transform: scale(1.015);
  }
  .sa-card-pad-shine {
    position: absolute; inset: 0;
    background: linear-gradient(180deg, transparent 50%, rgba(0,0,0,0.65) 100%);
    pointer-events: none;
    opacity: 0;
    transition: opacity 220ms ease;
  }
  .sa-card-pad:hover .sa-card-pad-shine,
  .sa-card-pad:focus-visible .sa-card-pad-shine {
    opacity: 1;
  }
  .sa-card-pad-cta {
    position: absolute;
    bottom: 14px;
    left: 0; right: 0;
    text-align: center;
    font-family: 'Montserrat', system-ui, sans-serif;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.20em;
    text-transform: uppercase;
    color: #fff;
    text-shadow: 0 2px 6px rgba(0,0,0,0.6);
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 220ms ease, transform 220ms ease;
    pointer-events: none;
  }
  .sa-card-pad:hover .sa-card-pad-cta,
  .sa-card-pad:focus-visible .sa-card-pad-cta {
    opacity: 1;
    transform: translateY(0);
  }
  .sa-card-pad-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: 'Montserrat', system-ui, sans-serif;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.20em;
    text-transform: uppercase;
  }
  .sa-card-pad-meta-eyebrow {
    color: #FF0000;
  }
  .sa-card-pad-meta-spec {
    color: rgba(255,255,255,0.4);
    letter-spacing: 0.12em;
  }
