/* ============================================================
 * OzBook · ozbook.css
 *
 * Component-level styles built on top of the design tokens in
 * colors_and_type.css. Assumes Bootstrap 5 is also loaded
 * (the --bs-* aliases at the bottom of colors_and_type.css mean
 * .btn-primary, .alert-warning, .text-success etc. already pick
 * up brand colours).
 *
 * Conventions:
 *   .ob-*  → OzBook-specific element. Component styles live here.
 *   data-bs-theme="dark" on <html> swaps the semantic tokens.
 *   data-touch="true" on <html> bumps hit targets 36→44 px.
 * ============================================================ */

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--ob-font-sans);
  color: var(--ob-fg-1);
  background: var(--ob-surface-app);
  display: flex;
  flex-direction: column;
}
main {
  flex: 1;
  /* Universal breathing room between the sticky top nav and page content.
     Pages that add their own top margin (e.g. Bootstrap .mt-4 wrappers) stack
     on top of this, which is fine — better a bit roomy than cramped.
     Footer supplies its own top margin so bottom padding stays modest. */
  padding: 24px 0 16px;
}

.ob-container { max-width: var(--ob-content-max); margin: 0 auto; padding: 0 16px; width: 100%; }
@media (min-width: 992px) { .ob-container { padding: 0 24px; } }

/* ========== TOP NAV ========== */
.ob-nav {
  background: var(--ob-surface-1);
  border-bottom: 1px solid var(--ob-border-1);
  height: var(--ob-nav-height);
  position: sticky; top: 0; z-index: var(--ob-z-nav);
  box-shadow: var(--ob-shadow-xs);
}
.ob-nav-inner { height: 100%; display: flex; align-items: center; gap: 8px; }
.ob-nav-logo { height: 36px; display: flex; align-items: center; padding: 0 4px; flex-shrink: 0; }
.ob-nav-logo img { height: 32px; display: block; }

/* Light/dark logo swap. Both <img>s are emitted; the inactive one is hidden.
   The two SVGs share the eucalyptus mark + gold boomerang + gold "Oz"; only
   the "Book" wordmark changes (ironbark on light, white on dark).
   `img.ob-logo-*` selectors match the specificity of `.ob-nav-logo img` so
   the swap wins on source order. */
img.ob-logo-dark { display: none; }
[data-bs-theme="dark"] img.ob-logo-light { display: none; }
[data-bs-theme="dark"] img.ob-logo-dark { display: block; }
.ob-nav-menu { display: flex; align-items: center; gap: 2px; margin-left: 12px; flex: 1; min-width: 0; }
@media (max-width: 991px) { .ob-nav-menu { display: none; } }

.ob-nav-item {
  position: relative;
  padding: 8px 12px;
  font-size: 13px; font-weight: 600;
  color: var(--ob-fg-1);
  background: transparent; border: 0; cursor: pointer;
  border-radius: var(--ob-radius-sm);
  text-decoration: none;
  transition: color var(--ob-dur-fast) var(--ob-ease-out),
              background var(--ob-dur-fast) var(--ob-ease-out),
              transform var(--ob-dur-fast) var(--ob-ease-out);
  white-space: nowrap;
  font-family: inherit;
  /* gap:0 — the icon/label/caret spacing is carried by per-child margins instead,
     so the label can collapse its own margin away in compact mode (below) without
     leaving a flex gap behind on either side of a zero-width span. */
  display: inline-flex; align-items: center; gap: 0;
}
.ob-nav-item::after {
  content: ""; position: absolute;
  left: 50%; bottom: -1px; width: 0; height: 2px;
  background: var(--ob-primary);
  border-radius: 2px;
  transform: translateX(-50%);
  transition: width var(--ob-dur-base) var(--ob-ease-out);
}
.ob-nav-item:hover { color: var(--ob-primary); background: var(--ob-surface-2); }
.ob-nav-item:hover::after { width: calc(100% - 24px); }
.ob-nav-item:active { transform: scale(0.97); }
.ob-nav-item.is-active { color: var(--ob-primary); }
.ob-nav-item.is-active::after { width: calc(100% - 24px); }
.ob-nav-item:focus-visible { outline: 0; box-shadow: var(--ob-ring); }
.ob-nav-item .caret { font-size: 10px; color: var(--ob-fg-3); transition: transform var(--ob-dur-base) var(--ob-ease-out); }
.ob-nav-item.is-open .caret { transform: rotate(180deg); color: var(--ob-primary); }
.ob-nav-item.is-open { color: var(--ob-primary); background: var(--ob-surface-2); }

/* ── Responsive compaction ────────────────────────────────────────────────
   How many entries the primary nav carries depends on the caller's permissions
   and the file's enabled features, so no single breakpoint is right for every
   file. `ozbook.js` measures the row instead: the moment the labels no longer
   fit the space between the logo and the right-hand actions it adds
   `.is-compact` to `.ob-nav-menu`, which morphs every entry back to its
   category icon and brings the label back as a hover / keyboard-focus tooltip.
   If the icons alone still overflow it adds `.is-tight` on top, which trims the
   padding and drops the mega-menu carets.

   Entries with no icon (no `.has-icon`) never compact — there would be nothing
   left to aim at. Below 992px the whole row is replaced by the drawer. */
.ob-nav-item > .ob-nav-label { margin-inline-start: 4px; }
.ob-nav-item > .caret { margin-inline-start: 4px; }

.ob-nav-label {
  display: inline-block;
  /* A finite max-width so the collapse can animate; comfortably past the longest
     top-level label in any host. */
  max-width: 26ch;
  overflow: hidden;
  white-space: nowrap;
  /* Only bites when the row's tail is too short for the whole label (see
     `--ob-nav-label-space` below); a hard clip mid-word reads as a glitch. */
  text-overflow: ellipsis;
  transition: max-width var(--ob-dur-base) var(--ob-ease-out),
              opacity var(--ob-dur-fast) var(--ob-ease-out),
              margin-inline-start var(--ob-dur-base) var(--ob-ease-out);
}
.ob-nav-menu.is-compact .ob-nav-item.has-icon > .ob-nav-label {
  max-width: 0; opacity: 0; margin-inline-start: 0;
}
/* Icon-only entries square up so the row reads as a strip of buttons. */
.ob-nav-menu.is-compact .ob-nav-item.has-icon { padding-left: 10px; padding-right: 10px; }
.ob-nav-menu.is-compact .ob-nav-item.has-icon > i:not(.caret) { font-size: 16px; }
/* Last resort — even the bare icons overflow, so give up the breathing room. */
.ob-nav-menu.is-tight { gap: 0; }
.ob-nav-menu.is-tight .ob-nav-item.has-icon { padding-left: 6px; padding-right: 6px; }

/* Hover or keyboard focus opens the label back out to the right of the icon. The
   label stays in flow, so the entry genuinely widens and every entry after it
   slides right by exactly the label's width — the row reflows rather than the
   label painting over its neighbours. The mega caret rides out alongside it, so a
   hovered entry reads exactly as it does in the uncompacted row. */
.ob-nav-menu.is-compact .ob-nav-item.has-icon > .ob-nav-label,
.ob-nav-menu.is-compact .ob-nav-item.has-icon > .caret {
  max-width: 0;
  opacity: 0;
  margin-inline-start: 0;
  overflow: hidden;
}
.ob-nav-menu.is-compact .ob-nav-item.has-icon > .caret {
  display: inline-block;
  transition: max-width var(--ob-dur-base) var(--ob-ease-out),
              opacity var(--ob-dur-fast) var(--ob-ease-out),
              margin-inline-start var(--ob-dur-base) var(--ob-ease-out);
}
.ob-nav-menu.is-compact .ob-nav-item.has-icon:hover > .ob-nav-label,
.ob-nav-menu.is-compact .ob-nav-item.has-icon:focus-visible > .ob-nav-label,
.ob-nav-menu.is-compact .ob-nav-item.has-icon.is-open > .ob-nav-label {
  /* `--ob-nav-label-space` is the row's unused tail, published by ozbook.js each
     time it measures. Everything to the hovered entry's right shifts by the
     label's width, so capping the label at the tail keeps the last entry inside
     the row instead of pushing it under the right-hand actions. */
  max-width: min(26ch, var(--ob-nav-label-space, 26ch));
  margin-inline-start: 4px;
  opacity: 1;
}
/* Held open while the entry's mega-menu is: letting the row snap back as the
   pointer travels down into the panel would shuffle the icons behind it. */
.ob-nav-menu.is-compact .ob-nav-item.has-icon:hover > .caret,
.ob-nav-menu.is-compact .ob-nav-item.has-icon:focus-visible > .caret,
.ob-nav-menu.is-compact .ob-nav-item.has-icon.is-open > .caret {
  max-width: 1em;
  margin-inline-start: 4px;
  opacity: 1;
}
/* An entry that is active but not hovered is still icon-wide, so the underline —
   sized off the entry — would be a stub. Pin it to the icon; once hovered the
   entry is label-wide again and the standard rule reads correctly. */
.ob-nav-menu.is-compact .ob-nav-item.has-icon.is-active:not(:hover)::after { width: 20px; }

/* ozbook.js drops `.is-compact` for a single frame to measure the expanded row,
   then restores it to measure the collapsed one. `.is-measuring` keeps both
   measurements from animating, and holds the labels shut for the collapsed pass so
   an entry that happens to be under the pointer does not inflate it. */
.ob-nav-menu.is-measuring .ob-nav-label,
.ob-nav-menu.is-measuring .caret { transition: none; }
.ob-nav-menu.is-measuring.is-compact .ob-nav-item.has-icon > .ob-nav-label,
.ob-nav-menu.is-measuring.is-compact .ob-nav-item.has-icon > .caret {
  max-width: 0; margin-inline-start: 0;
}

@media (prefers-reduced-motion: reduce) {
  .ob-nav-label,
  .ob-nav-item .caret { transition: none; }
}

.ob-nav-right { display: flex; align-items: center; gap: 8px; flex-shrink: 0; margin-left: auto; }

.ob-iconbtn {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent;
  background: transparent;
  border-radius: var(--ob-radius-sm);
  color: var(--ob-fg-2); cursor: pointer;
  transition: all var(--ob-dur-fast) var(--ob-ease-out);
  font-size: 18px;
  text-decoration: none;
}
.ob-iconbtn:hover { background: var(--ob-surface-2); color: var(--ob-fg-1); }
.ob-iconbtn:active { transform: scale(0.94); }
.ob-iconbtn:focus-visible { outline: 0; box-shadow: var(--ob-ring); }
[data-touch="true"] .ob-iconbtn { width: 44px; height: 44px; font-size: 20px; }
[data-touch="true"] .ob-nav-item { padding: 12px 14px; font-size: 14px; }

.ob-user-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 10px 4px 4px;
  border: 1px solid var(--ob-border-1);
  border-radius: var(--ob-radius-pill);
  background: transparent;
  font-family: inherit; font-size: 13px; font-weight: 600;
  color: var(--ob-fg-1);
  cursor: pointer;
  text-decoration: none;
  transition: all var(--ob-dur-fast) var(--ob-ease-out);
}
.ob-user-pill:hover { background: var(--ob-surface-2); color: var(--ob-fg-1); }
.ob-user-pill:active { transform: scale(0.97); }
.ob-user-pill:focus-visible { outline: 0; box-shadow: var(--ob-ring); }
.ob-user-pill .name { display: none; }
@media (min-width: 768px) { .ob-user-pill .name { display: inline; } }

.ob-avatar {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--ob-primary);
  color: var(--ob-primary-on);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0;
  flex-shrink: 0;
}

/* Dropdown menu (single column) */
.ob-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 280px;
  background: var(--ob-surface-1);
  border: 1px solid var(--ob-border-1);
  border-radius: var(--ob-radius-lg);
  box-shadow: var(--ob-shadow-lg);
  overflow: hidden;
  z-index: var(--ob-z-dropdown);
  animation: ob-menu-in 180ms var(--ob-ease-out);
}
@keyframes ob-menu-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.ob-menu-section { padding: 6px 0; }
.ob-menu-section + .ob-menu-section { border-top: 1px solid var(--ob-border-1); }
.ob-menu-header {
  padding: 12px 14px;
  display: flex; align-items: center; gap: 10px;
  border-bottom: 1px solid var(--ob-border-1);
}
.ob-menu-header-meta { line-height: 1.3; min-width: 0; }
.ob-menu-header-meta .name { font-size: 13px; font-weight: 600; color: var(--ob-fg-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ob-menu-header-meta .sub  { font-size: 11px; color: var(--ob-fg-3); }
.ob-menu-label {
  padding: 8px 14px 4px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ob-fg-3);
}
.ob-menu-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 14px;
  font-size: 13px; color: var(--ob-fg-1);
  background: transparent; border: 0; width: 100%; text-align: left;
  cursor: pointer; font-family: inherit;
  text-decoration: none;
  transition: background var(--ob-dur-fast) var(--ob-ease-out);
}
.ob-menu-item:hover { background: var(--ob-surface-2); color: var(--ob-fg-1); }
.ob-menu-item:focus-visible { outline: 0; background: var(--ob-surface-2); box-shadow: inset 0 0 0 2px var(--ob-primary); }
.ob-menu-item .meta { margin-left: auto; font-size: 11px; color: var(--ob-fg-3); }
.ob-menu-item.danger { color: var(--ob-danger); }
.ob-menu-item.danger:hover { color: var(--ob-danger); }
.ob-menu-item i { font-size: 16px; color: var(--ob-fg-3); width: 18px; }
[data-touch="true"] .ob-menu-item { padding: 12px 16px; font-size: 14px; }

/* Mega-menu dropdown (multi-column) */
.ob-mega {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  background: var(--ob-surface-1);
  border: 1px solid var(--ob-border-1);
  border-radius: var(--ob-radius-lg);
  box-shadow: var(--ob-shadow-lg);
  padding: 18px;
  min-width: 380px;
  max-width: min(880px, calc(100vw - 32px));
  z-index: var(--ob-z-dropdown);
  animation: ob-menu-in 180ms var(--ob-ease-out);
  display: grid;
  gap: 18px 28px;
}
.ob-mega.cols-1 { grid-template-columns: 1fr; }
.ob-mega.cols-2 { grid-template-columns: 1fr 1fr; }
.ob-mega.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
.ob-mega-section { min-width: 200px; }
.ob-mega-section h4 {
  margin: 0 0 8px;
  font: 700 10px/1.1 var(--ob-font-sans);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ob-fg-3);
  padding: 0 8px;
}
.ob-mega-item {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 8px 10px;
  border-radius: var(--ob-radius-sm);
  background: transparent; border: 0; cursor: pointer;
  font-family: inherit; text-align: left; width: 100%;
  color: var(--ob-fg-1);
  text-decoration: none;
  transition: background var(--ob-dur-fast) var(--ob-ease-out),
              color var(--ob-dur-fast) var(--ob-ease-out);
}
.ob-mega-item:hover { background: var(--ob-surface-2); }
.ob-mega-item:hover .ob-mega-item-icon { background: var(--ob-primary-soft); color: var(--ob-primary); }
.ob-mega-item:focus-visible { outline: 0; background: var(--ob-surface-2); box-shadow: inset 0 0 0 2px var(--ob-primary); }
.ob-mega-item.is-active { background: var(--ob-primary-soft); }
.ob-mega-item.is-active .ob-mega-item-icon { background: var(--ob-primary); color: var(--ob-primary-on); }
.ob-mega-item.is-active .label { color: var(--ob-primary); }
.ob-mega-item-icon {
  width: 30px; height: 30px;
  flex-shrink: 0;
  border-radius: var(--ob-radius-sm);
  background: var(--ob-surface-2);
  color: var(--ob-fg-2);
  display: flex; align-items: center; justify-content: center;
  font-size: 15px;
  transition: background var(--ob-dur-fast) var(--ob-ease-out),
              color var(--ob-dur-fast) var(--ob-ease-out);
}
.ob-mega-item .text { flex: 1; min-width: 0; line-height: 1.3; padding-top: 1px; }
.ob-mega-item .label { font-size: 13px; font-weight: 600; color: var(--ob-fg-1); }
.ob-mega-item .desc { font-size: 11px; color: var(--ob-fg-3); margin-top: 2px; }
.ob-mega-foot {
  grid-column: 1 / -1;
  border-top: 1px solid var(--ob-border-1);
  padding: 10px 8px 0;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 12px; color: var(--ob-fg-2);
}

/* Wrap that lets the parent .ob-nav-item position absolute children correctly */
.ob-nav-item-wrap { position: relative; display: inline-flex; }

/* ========== BUTTONS ========== */
.ob-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px;
  height: var(--ob-touch-desktop);
  border-radius: var(--ob-radius-md);
  font-family: var(--ob-font-sans);
  font-size: 13px; font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--ob-dur-fast) var(--ob-ease-out),
              color var(--ob-dur-fast) var(--ob-ease-out),
              border-color var(--ob-dur-fast) var(--ob-ease-out),
              transform var(--ob-dur-fast) var(--ob-ease-out),
              box-shadow var(--ob-dur-fast) var(--ob-ease-out);
  white-space: nowrap;
  line-height: 1;
}
[data-touch="true"] .ob-btn { height: var(--ob-touch-touch); padding: 10px 16px; font-size: 14px; }
.ob-btn:active { transform: scale(0.97); }
.ob-btn:focus-visible { outline: 0; box-shadow: var(--ob-ring); }
.ob-btn:disabled, .ob-btn[disabled] { opacity: 0.5; cursor: not-allowed; pointer-events: none; }
.ob-btn-primary { background: var(--ob-primary); color: var(--ob-primary-on); }
.ob-btn-primary:hover { background: var(--ob-primary-hover); color: var(--ob-primary-on); }
.ob-btn-primary:active { background: var(--ob-primary-active); }
.ob-btn-secondary { background: var(--ob-secondary); color: var(--ob-secondary-on); }
.ob-btn-secondary:hover { background: var(--ob-secondary-hover); color: var(--ob-secondary-on); }
.ob-btn-tertiary { background: var(--ob-tertiary); color: var(--ob-tertiary-on); }
.ob-btn-ghost { background: transparent; color: var(--ob-fg-1); border-color: var(--ob-border-2); }
.ob-btn-ghost:hover { background: var(--ob-surface-2); border-color: var(--ob-border-2); color: var(--ob-fg-1); }
.ob-btn-danger { background: var(--ob-danger); color: #fff; }
.ob-btn-danger:hover { filter: brightness(1.08); color: #fff; }
.ob-btn-link { background: transparent; color: var(--ob-fg-link); padding-left: 4px; padding-right: 4px; height: auto; }
.ob-btn-link:hover { color: var(--ob-fg-link-hover); text-decoration: underline; }
.ob-btn-sm { height: 28px; padding: 4px 10px; font-size: 12px; }
[data-touch="true"] .ob-btn-sm { height: 36px; padding: 6px 12px; font-size: 13px; }
.ob-btn i { font-size: 15px; }

/* ========== CARDS ========== */
.ob-card {
  background: var(--ob-surface-1);
  border: 1px solid var(--ob-border-1);
  border-radius: var(--ob-radius-lg);
  box-shadow: var(--ob-shadow-sm);
}
.ob-card-pad { padding: 24px; }
.ob-card-head {
  padding: 16px 24px;
  border-bottom: 1px solid var(--ob-border-1);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.ob-card-head h2, .ob-card-head h3 {
  margin: 0; font-size: 16px; font-weight: 600; color: var(--ob-fg-1);
}
.ob-card-body { padding: 20px 24px; }

.ob-stat { display: flex; flex-direction: column; gap: 6px; }
.ob-stat .label {
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ob-fg-3);
}
.ob-stat .value {
  font-family: var(--ob-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 26px; font-weight: 700; color: var(--ob-fg-1);
  line-height: 1.1;
}
.ob-stat .delta { font-size: 12px; }
.ob-stat .delta.pos { color: var(--ob-pos); }
.ob-stat .delta.neg { color: var(--ob-neg); }
.ob-stat .delta.warn { color: var(--gold-600); }
[data-bs-theme="dark"] .ob-stat .delta.warn { color: var(--gold-300); }

/* ========== PILLS / BADGES ========== */
.ob-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px;
  border-radius: var(--ob-radius-pill);
  font-size: 11px; font-weight: 600;
  white-space: nowrap;
}
.ob-pill .dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
.ob-pill-success { background: var(--ob-success-soft); color: var(--ob-success); }
.ob-pill-success .dot { background: var(--ob-success); }
.ob-pill-warning { background: var(--ob-warning-soft); color: var(--gold-600); }
[data-bs-theme="dark"] .ob-pill-warning { color: var(--gold-300); }
.ob-pill-warning .dot { background: var(--ob-warning); }
.ob-pill-danger { background: var(--ob-danger-soft); color: var(--ob-danger); }
.ob-pill-danger .dot { background: var(--ob-danger); }
.ob-pill-info { background: var(--ob-info-soft); color: var(--ob-info); }
.ob-pill-info .dot { background: var(--ob-info); }
.ob-pill-neutral { background: var(--ob-surface-2); color: var(--ob-fg-2); }
.ob-pill-neutral .dot { background: var(--ob-fg-3); }

/* ========== FORM ========== */
.ob-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ob-label {
  font-size: 11px; font-weight: 600; color: var(--ob-fg-2);
  letter-spacing: 0.02em;
}
.ob-input, .ob-select, .ob-textarea {
  width: 100%;
  padding: 0 12px;
  height: var(--ob-touch-desktop);
  border: 1px solid var(--ob-border-input);
  border-radius: var(--ob-radius-md);
  background: var(--ob-surface-1);
  color: var(--ob-fg-1);
  font: 14px var(--ob-font-sans);
  transition: border-color var(--ob-dur-fast) var(--ob-ease-out),
              box-shadow var(--ob-dur-fast) var(--ob-ease-out);
}
.ob-textarea { padding: 8px 12px; height: auto; min-height: 80px; }
[data-touch="true"] .ob-input, [data-touch="true"] .ob-select, [data-touch="true"] .ob-textarea {
  height: var(--ob-touch-touch);
}
[data-touch="true"] .ob-textarea { height: auto; min-height: 96px; }
.ob-input::placeholder, .ob-textarea::placeholder { color: var(--ob-fg-muted); }
.ob-input:hover, .ob-select:hover, .ob-textarea:hover { border-color: var(--ob-border-2); }
.ob-input:focus, .ob-select:focus, .ob-textarea:focus {
  outline: 0;
  border-color: var(--ob-border-focus);
  box-shadow: var(--ob-ring);
}
.ob-input.numeric { font-family: var(--ob-font-mono); font-variant-numeric: tabular-nums; text-align: right; }
.ob-field-error { font-size: 11px; color: var(--ob-danger); }
.ob-input.is-invalid { border-color: var(--ob-danger); }
.ob-input.is-invalid:focus { box-shadow: 0 0 0 3px rgba(181, 61, 31, 0.2); }
.ob-help { font-size: 11px; color: var(--ob-fg-3); }

/* ========== TABLE ========== */
.ob-table-wrap {
  background: var(--ob-surface-1);
  border: 1px solid var(--ob-border-1);
  border-radius: var(--ob-radius-lg);
  overflow: hidden;
}
.ob-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.ob-table thead th {
  text-align: left;
  padding: 10px 14px;
  background: var(--ob-surface-2);
  color: var(--ob-fg-2);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--ob-border-1);
  position: sticky; top: 0;
}
.ob-table tbody td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--ob-border-1);
  color: var(--ob-fg-1);
  vertical-align: middle;
}
.ob-table tbody tr { transition: background var(--ob-dur-fast) var(--ob-ease-out); }
.ob-table tbody tr:hover { background: var(--ob-surface-2); }
.ob-table tbody tr:last-child td { border-bottom: 0; }
.ob-table .money { text-align: right; font-family: var(--ob-font-mono); font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
.ob-table .money.neg { color: var(--ob-neg); }
.ob-table .ref { font-family: var(--ob-font-mono); font-variant-numeric: tabular-nums; font-size: 12px; color: var(--ob-fg-2); }
.ob-table th.right, .ob-table td.right { text-align: right; }

@media (max-width: 767px) {
  .ob-table thead { display: none; }
  .ob-table, .ob-table tbody, .ob-table tr, .ob-table td { display: block; width: 100%; }
  .ob-table tbody tr { padding: 12px 14px; border-bottom: 1px solid var(--ob-border-1); }
  .ob-table tbody td { padding: 4px 0; border: 0; display: flex; justify-content: space-between; }
  .ob-table tbody td::before {
    content: attr(data-label);
    font-size: 11px; color: var(--ob-fg-3);
    text-transform: uppercase; letter-spacing: 0.04em;
    font-weight: 600;
  }
  .ob-table .money { text-align: right; }
}

/* ========== PAGE HEADER ========== */
/* No top padding — <main> already supplies 24px below the sticky nav. */
.ob-page-header {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
  padding: 0 0 20px;
  flex-wrap: wrap;
}
.ob-page-header .left .eyebrow { font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ob-fg-3); margin-bottom: 4px; }
.ob-page-header .left h1 { font-size: 28px; font-weight: 700; letter-spacing: -0.02em; margin: 0; color: var(--ob-fg-1); }
.ob-page-header .right { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ========== FOOTER ========== */
.ob-footer {
  margin-top: 32px;
  padding: 24px 0 32px;
  border-top: 1px solid var(--ob-border-1);
  background: transparent;
}
.ob-footer-inner {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  font-size: 12px; color: var(--ob-fg-3);
  flex-wrap: wrap;
}
.ob-footer-links { display: flex; gap: 16px; flex-wrap: wrap; }
.ob-footer-links a { color: var(--ob-fg-3); text-decoration: none; }
.ob-footer-links a:hover { color: var(--ob-fg-1); }

/* ========== SAVE BAR ========== */
.ob-savebar {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: var(--ob-z-save-bar);
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px;
  background: color-mix(in srgb, var(--ob-surface-1) 92%, transparent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid var(--ob-border-1);
  border-radius: var(--ob-radius-lg);
  box-shadow: var(--ob-shadow-lg);
  animation: savebar-in var(--ob-dur-base) var(--ob-ease-out);
}
@keyframes savebar-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
.ob-savebar[hidden] { display: none; }
.ob-savebar .status {
  font-size: 12px; color: var(--ob-fg-2);
  display: flex; align-items: center; gap: 6px;
}
.ob-savebar .status .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ob-warning); }
@media (max-width: 600px) {
  .ob-savebar { left: 16px; right: 16px; bottom: 16px; justify-content: space-between; }
}

/* ========== SKELETON ========== */
.ob-skel {
  background: linear-gradient(90deg, var(--ob-surface-2) 0%, var(--ob-surface-3) 50%, var(--ob-surface-2) 100%);
  background-size: 200% 100%;
  border-radius: var(--ob-radius-sm);
  animation: ob-shimmer 1.4s linear infinite;
}
@keyframes ob-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* ========== TOAST ========== */
.ob-toast-region {
  position: fixed; top: 72px; right: 24px;
  display: flex; flex-direction: column; gap: 8px;
  z-index: var(--ob-z-toast);
  pointer-events: none;
}
.ob-toast {
  pointer-events: auto;
  min-width: 280px; max-width: 420px;
  padding: 10px 14px;
  background: var(--ob-surface-1);
  border: 1px solid var(--ob-border-1);
  border-radius: var(--ob-radius-md);
  box-shadow: var(--ob-shadow-lg);
  display: flex; align-items: flex-start; gap: 10px;
  font-size: 13px;
  animation: toast-in var(--ob-dur-slow) var(--ob-ease-out);
}
@keyframes toast-in { from { opacity: 0; transform: translateX(12px); } to { opacity: 1; transform: translateX(0); } }
.ob-toast.success { border-left: 3px solid var(--ob-success); }
.ob-toast.warning { border-left: 3px solid var(--ob-warning); }
.ob-toast.danger { border-left: 3px solid var(--ob-danger); }

/* ========== MOBILE DRAWER ========== */
.ob-drawer-backdrop {
  position: fixed; inset: 0;
  background: var(--ob-surface-overlay);
  z-index: calc(var(--ob-z-nav) + 5);
  animation: ob-fade-in 180ms var(--ob-ease-out);
}
@keyframes ob-fade-in { from { opacity: 0; } to { opacity: 1; } }
.ob-drawer {
  position: fixed; top: 0; left: 0; bottom: 0;
  width: 280px; max-width: 84vw;
  background: var(--ob-surface-1);
  border-right: 1px solid var(--ob-border-1);
  z-index: calc(var(--ob-z-nav) + 10);
  display: flex; flex-direction: column;
  animation: drawer-in 240ms var(--ob-ease-out);
  box-shadow: var(--ob-shadow-xl);
}
@keyframes drawer-in { from { transform: translateX(-100%); } to { transform: translateX(0); } }
.ob-drawer .ob-drawer-head { padding: 16px; border-bottom: 1px solid var(--ob-border-1); display: flex; align-items: center; justify-content: space-between; }
.ob-drawer .ob-drawer-list { flex: 1; padding: 8px 0; overflow-y: auto; }
.ob-drawer .ob-drawer-item {
  padding: 12px 18px;
  font-size: 14px; font-weight: 500;
  display: flex; align-items: center; gap: 12px;
  color: var(--ob-fg-1);
  background: transparent; border: 0; width: 100%; text-align: left;
  cursor: pointer; font-family: inherit;
  text-decoration: none;
}
.ob-drawer .ob-drawer-item.is-active { color: var(--ob-primary); background: var(--ob-primary-soft); border-left: 3px solid var(--ob-primary); padding-left: 15px; }
.ob-drawer .ob-drawer-item:hover { background: var(--ob-surface-2); color: var(--ob-fg-1); }
.ob-drawer .ob-drawer-item i { font-size: 18px; }
.ob-drawer-group h4 {
  margin: 12px 18px 4px;
  font: 700 10px/1.1 var(--ob-font-sans);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ob-fg-3);
}
.ob-drawer-item.is-child { padding-left: 32px; font-size: 13px; font-weight: 500; }

/* Mobile menu button (visible on small viewports) */
.ob-menu-toggle { display: none; }
@media (max-width: 991px) { .ob-menu-toggle { display: inline-flex; } }

/* ========== MISC ========== */
.ob-divider { height: 1px; background: var(--ob-border-1); margin: 16px 0; }
.ob-spacer-6 { height: 24px; }
.ob-row { display: flex; gap: 12px; flex-wrap: wrap; }
.ob-grid { display: grid; gap: 16px; }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 991px) { .grid-3, .grid-4 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .grid-3, .grid-4 { grid-template-columns: 1fr; } }

.ob-meta { color: var(--ob-fg-3); font-size: 12px; }
.ob-text-2 { color: var(--ob-fg-2); }

/* Tabs */
.ob-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--ob-border-1); margin-bottom: 16px; flex-wrap: wrap; }
.ob-tab {
  padding: 10px 14px; font-size: 13px; font-weight: 600;
  color: var(--ob-fg-2); background: transparent; border: 0;
  border-bottom: 2px solid transparent;
  cursor: pointer; font-family: inherit;
  text-decoration: none;
  transition: color var(--ob-dur-fast) var(--ob-ease-out);
}
.ob-tab:hover { color: var(--ob-fg-1); }
.ob-tab.is-active { color: var(--ob-primary); border-bottom-color: var(--ob-primary); }

/* Empty-state placeholder used by Coming-soon module cards */
.ob-placeholder {
  padding: 48px 24px;
  text-align: center;
  color: var(--ob-fg-3);
  background: var(--ob-surface-2);
  border-radius: var(--ob-radius-lg);
  border: 1px dashed var(--ob-border-2);
}
.ob-placeholder i { font-size: 32px; color: var(--ob-fg-3); margin-bottom: 8px; display: block; }
.ob-placeholder h3 { margin: 0 0 4px; font-size: 16px; font-weight: 600; color: var(--ob-fg-2); }
.ob-placeholder p  { margin: 0; font-size: 13px; }

/* ========== FEATURE LIST (subscription plan cards) ========== */
.ob-feature-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.ob-feature-list-item { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; color: var(--ob-fg-1); }
.ob-feature-list-item i { font-size: 14px; flex-shrink: 0; margin-top: 2px; }

/* ========== PLAN PICKER ========== */
.ob-plan-grid { gap: 16px; }
.ob-plan-card { display: flex; flex-direction: column; }
.ob-plan-card .ob-card-body { display: flex; flex-direction: column; flex: 1; }
.ob-plan-card.is-current { border-color: var(--ob-primary); box-shadow: var(--ob-shadow-md); }
/* A plan whose Stripe price would not resolve is rendered NON-SELECTABLE on a transacting surface —
   never as $0.00 and never blank. It stays readable; only its radio is disabled. */
.ob-plan-card.is-unavailable { opacity: .6; cursor: not-allowed; }
.ob-plan-card.is-unavailable .ob-card-body { pointer-events: none; }

/* ========== SPINNER (in-flight and confirming states) ========== */
.ob-spinner {
  display: inline-block;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border: 2px solid var(--ob-border-1);
  border-top-color: var(--ob-primary);
  border-radius: var(--ob-radius-pill);
  animation: ob-spin 720ms linear infinite;
}
.ob-spinner-sm { width: 14px; height: 14px; border-width: 2px; vertical-align: -2px; margin-right: 6px; }
@keyframes ob-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .ob-spinner { animation-duration: 2.4s; }
}

/* ========== CALLOUT (lightweight panel) ========== */
.ob-callout {
  padding: 16px;
  border-radius: var(--ob-radius-md);
  background: var(--ob-surface-2);
  border: 1px solid var(--ob-border-1);
}

/* ========== FORM GROUP (label + control + help) ========== */
.ob-form-group { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ob-form-group .ob-label { display: block; font-size: 12px; font-weight: 600; color: var(--ob-fg-2); }
