/* =====================================================================
   css/brandv2.app.css -- BRAND SYSTEM V2: app chrome + HOME restyle.
   Wave 1, flag-gated. Loaded AFTER css/premium.css so equal-or-higher
   specificity rules win by cascade order.

   LAW
   - EVERY selector is scoped under html.brand-v2 -- zero rules match
     when the flag is off.
   - Tokens only (public names: --surface/--line/--accent/...). Raw hex
     is BANNED here; rgba() appears exclusively for shadow/scrim/glass
     alpha values (spec section 5 elevation recipe uses rgba(6,42,44)).
   - CSS only: restyles EXISTING markup (js/home.js .uh-* family, the
     app.html .bnav/.fab/.modal shell). No renamed ids/classes assumed.
     The shared asset card (balenHome.assetCardHtml) also renders inside
     the org asset selector (app.js renderAssetPicker) -- every asset-card
     rule below works on both surfaces because both use .uh-asset-grid.
   - Photography: the MY ASSETS media overlay is a LOCALIZED bottom band
     (behind the serif name only) -- the image itself is NEVER filtered
     or darkened as a whole. Workspace-hero overlay math stays owned by
     balenAssetHero.heroCssVars (not this file).
   - Motion: 160ms micro / 240ms sheets, cubic-bezier(.2,.7,.3,1);
     every transition is disabled under prefers-reduced-motion.
   - Balo: the Home greeting strip (.bv2-balo-strip) is the ONE Balo
     presence on Home; the legacy v1 cartoon inside .uh-balo-fab is
     hidden under the flag (v1 art is off-brand for V2 per spec 1).
   ===================================================================== */

/* ---- 1. HOME header: Newsreader greeting + calmer command bar ------- */

html.brand-v2 .uh-greet {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 16px;
  color: var(--text-secondary);
}
html.brand-v2 .uh-name {
  font-family: var(--font-serif);
  font-weight: 550;
  font-size: 30px;
  line-height: 1.1;
  letter-spacing: -0.015em;
}
@media (min-width: 1024px) {
  html.brand-v2 .uh-name { font-size: 34px; }
}
html.brand-v2 .uh-date {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text-tertiary);
}

/* Official tile mark chip (28px, spec 7 HOME). Markup is the
   integrator's flag-gated home.js branch; class reserved here. */
html.brand-v2 .bv2-mark {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  display: block;
  flex: 0 0 auto;
}

/* Command bar: quiet ghost controls -- chrome recedes, content leads. */
html.brand-v2 .uh-cmdbar .uh-cmd,
html.brand-v2 .uh-bell {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-secondary);
  transition: background-color 160ms cubic-bezier(.2, .7, .3, 1),
              transform 160ms cubic-bezier(.2, .7, .3, 1);
}
@media (hover: hover) {
  html.brand-v2 .uh-cmdbar .uh-cmd:hover,
  html.brand-v2 .uh-bell:hover { background: var(--surface-2); }
}
html.brand-v2 .uh-cmdbar .uh-cmd:active,
html.brand-v2 .uh-bell:active { transform: scale(.94); }
html.brand-v2 .uh-qa-btn {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-secondary);
  font-weight: 600;
}
@media (hover: hover) {
  html.brand-v2 .uh-qa-btn:hover { background: var(--surface-2); }
}
html.brand-v2 .uh-avatar {
  border: 1px solid var(--line);
  background: var(--accent-tint);
}
html.brand-v2 .uh-avatar-ini { color: var(--accent-text, var(--accent)); }
html.brand-v2 .uh-ctx-chip {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-tertiary);
  font-weight: 500;
}

/* ---- 2. Balo greeting strip (.bv2-balo-strip) ------------------------
   One quiet line under the header: 32px circular avatar chip from
   /assets/balo/v2/, one deterministic sentence, chevron. Surface-2,
   never a card centerpiece. Markup: integrator branch in home.js. */

html.brand-v2 .bv2-balo-strip {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  margin: 10px 0 0;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface-2);
  color: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: 13.5px;
  cursor: pointer;
  transition: background-color 160ms cubic-bezier(.2, .7, .3, 1),
              border-color 160ms cubic-bezier(.2, .7, .3, 1);
}
@media (hover: hover) {
  html.brand-v2 .bv2-balo-strip:hover {
    background: var(--accent-tint);
    border-color: var(--line);
  }
}
html.brand-v2 .bv2-balo-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
  display: block;
  filter: none; /* Balo law: no CSS filters, no recolor */
}
html.brand-v2 .bv2-balo-line {
  flex: 1;
  min-width: 0;
  font-weight: 500;
  color: var(--text-secondary);
  /* Balo's sentence is the point of the strip: let it wrap to two calm
     lines instead of truncating mid-thought. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  line-height: 1.35;
}
html.brand-v2 .bv2-balo-chev {
  flex: 0 0 auto;
  color: var(--text-tertiary);
  font-size: 16px;
}

/* ---- 3. Section headers: 13px caps, +0.08em, tertiary --------------- */

html.brand-v2 .uh-sec,
html.brand-v2 .uh-x-label {
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
@media (min-width: 1024px) {
  html.brand-v2 .uh-sec { font-size: 13px; }
}

/* ---- 4. TODAY tiles: premium cards ----------------------------------
   16px radius, spec elevation, 20/24 padding, mono money. */

html.brand-v2 .uh-tile {
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(6, 42, 44, .05), 0 8px 24px rgba(6, 42, 44, .07);
  padding: 20px;
  transition: transform 160ms cubic-bezier(.2, .7, .3, 1),
              box-shadow 160ms cubic-bezier(.2, .7, .3, 1),
              border-color 160ms cubic-bezier(.2, .7, .3, 1);
}
@media (min-width: 1024px) {
  html.brand-v2 .uh-tile { padding: 24px; }
}
@media (hover: hover) {
  html.brand-v2 .uh-tile.uh-clickable:hover {
    transform: translateY(-2px);
    box-shadow: 0 2px 4px rgba(6, 42, 44, .06), 0 14px 32px rgba(6, 42, 44, .10);
  }
}
html.brand-v2 .uh-chip { border-radius: 10px; }
html.brand-v2 .uh-tile-title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
}
/* Money law: mono + bold + tabular-nums; per-currency lines stay
   one-per-line (the builder emits them as separate blocks). */
html.brand-v2 .uh-amount {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}
html.brand-v2 .uh-mini-when {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
html.brand-v2 .uh-mini-row { border-top: 1px solid var(--line); }
html.brand-v2 .uh-tile-link {
  font-weight: 600;
  color: var(--accent-text, var(--accent));
}
html.brand-v2 .uh-view-all {
  font-weight: 600;
  color: var(--accent-text, var(--accent));
}
html.brand-v2 .uh-skel { background: var(--surface-2); }
html.brand-v2 .uh-other-orgs {
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--surface-2);
}

/* ---- 5. WHAT'S HAPPENING card ---------------------------------------- */

html.brand-v2 .uh-card {
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(6, 42, 44, .05), 0 8px 24px rgba(6, 42, 44, .07);
}
html.brand-v2 .uh-hap-chip { border-radius: 10px; }

/* ---- 6. MY ASSETS: photography-hero cards -----------------------------
   The shared card (Home + org asset selector) becomes media-first:
   full-width 16:10 uh-thumb on top, serif asset name overlaid on a
   LOCALIZED bottom gradient band (behind text only -- the photo is never
   darkened as a whole), meta text below on the card surface.
   Existing DOM order (thumb, main, right) maps onto a 2-column grid.
   The name is lifted onto the media with container-query units:
   media bottom sits at 62.5cqw (16:10 => height = width * 0.625). */

html.brand-v2 .uh-asset-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 0;
  padding: 0;
  min-height: 0;
  overflow: hidden;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(6, 42, 44, .05), 0 8px 24px rgba(6, 42, 44, .07);
  container-type: inline-size;
  transition: transform 160ms cubic-bezier(.2, .7, .3, 1),
              box-shadow 160ms cubic-bezier(.2, .7, .3, 1),
              border-color 160ms cubic-bezier(.2, .7, .3, 1);
}
@media (hover: hover) {
  html.brand-v2 .uh-asset-row:hover {
    transform: translateY(-2px);
    box-shadow: 0 2px 4px rgba(6, 42, 44, .06), 0 14px 32px rgba(6, 42, 44, .10);
  }
}
html.brand-v2 .uh-asset-row:active { transform: translateY(0) scale(.99); }
html.brand-v2 .uh-asset-grid { gap: 16px; }
@media (min-width: 1024px) {
  html.brand-v2 .uh-asset-grid { gap: 20px; }
}

/* Media: full-bleed 16:10 hero. Async photo fills (resolveThumbs)
   replace innerHTML only, so the band pseudo-element survives. */
html.brand-v2 .uh-asset-row .uh-thumb {
  grid-column: 1 / -1;
  position: relative;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  border-radius: 0;
  background: var(--surface-2);
}
/* Localized bottom gradient band -- behind the overlay text ONLY,
   bottom-anchored, never a full-image darken (photography law). */
html.brand-v2 .uh-asset-row .uh-thumb::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 46%;
  pointer-events: none;
  background: linear-gradient(to top,
    rgba(6, 42, 44, .68) 0%,
    rgba(6, 42, 44, .30) 55%,
    rgba(6, 42, 44, 0) 100%);
}
html.brand-v2 .uh-asset-row .uh-thumb-glyph svg { width: 44px; height: 44px; }

/* Serif name overlay: absolutely anchored to the media bottom edge
   (top = media height in cqw), translated up by its own height so
   multi-line names grow upward over the band. White over the scrim in
   BOTH themes (the scrim is theme-invariant dark teal). */
html.brand-v2 .uh-asset-row .uh-asset-name {
  position: absolute;
  z-index: 2;
  left: 18px;
  right: 18px;
  top: 62.5cqw;
  transform: translateY(calc(-100% - 12px));
  font-family: var(--font-serif);
  font-weight: 550;
  font-size: 22px;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: rgba(255, 255, 255, .98);
  text-shadow: 0 1px 2px rgba(6, 42, 44, .35);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  pointer-events: none;
}
@media (min-width: 1024px) {
  html.brand-v2 .uh-asset-row .uh-asset-name { font-size: 24px; }
}

/* Glass live chip riding on the overlay (inside .uh-asset-name). */
html.brand-v2 .uh-asset-row .uh-live-chip {
  vertical-align: 4px;
  margin-left: 10px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, .28);
  background: rgba(255, 255, 255, .16);
  color: rgba(255, 255, 255, .98);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.04em;
  text-shadow: none;
}
html.brand-v2 .uh-asset-row .uh-x-chip {
  border: 1px solid rgba(255, 255, 255, .28);
  background: rgba(255, 255, 255, .16);
  color: rgba(255, 255, 255, .98);
}

/* Meta block below the media, on the card surface. */
html.brand-v2 .uh-asset-row .uh-asset-main {
  min-width: 0;
  padding: 14px 18px 16px;
}
html.brand-v2 .uh-asset-row .uh-asset-sub {
  margin-top: 0;
  font-size: 14px;
  color: var(--text-secondary);
}
html.brand-v2 .uh-asset-row .uh-asset-next {
  font-size: 13px;
  margin-top: 4px;
  color: var(--text-tertiary);
}
html.brand-v2 .uh-asset-row .uh-asset-right {
  padding: 14px 18px 16px 0;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
}
html.brand-v2 .uh-asset-row .uh-chev { color: var(--text-tertiary); }

/* Org group header + summary line under the new section rhythm. */
html.brand-v2 .uh-org-name {
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--text-primary);
}
html.brand-v2 .uh-org-sum { color: var(--text-tertiary); }

/* ---- 7. Bottom nav ------------------------------------------------------
   The LIVE bar is the app.html "BOTTOM BAR -- locked spec" block
   (~app.html:2048): every property is pinned with !important on
   --bz-* aliases, and the legacy floating .fab is display:none
   !important (app.html:2202) -- the real FAB is the in-bar .bnav-fab.
   Overrides below therefore need !important + the scope class to win;
   z-index/stacking (bar 50, quickadd-open frame 170) is untouched. */

html.brand-v2 .bnav {
  background: var(--surface) !important;
  border-top: 1px solid var(--line) !important;
  box-shadow: 0 -8px 24px rgba(6, 42, 44, .06) !important;
}
html.brand-v2 .bnav-tab {
  color: var(--text-tertiary) !important;
  font-family: var(--font-sans) !important;
  font-weight: 500 !important;
}
html.brand-v2 .bnav-tab-icon { color: var(--text-tertiary) !important; }
html.brand-v2 .bnav-tab.on {
  color: var(--accent-text, var(--accent)) !important;
  font-weight: 600 !important;
}
html.brand-v2 .bnav-tab.on .bnav-tab-icon {
  color: var(--accent-text, var(--accent)) !important;
}

/* ---- 8. FAB (in-bar center .bnav-fab) -----------------------------------
   Brand accent fill; --accent-on is the one token guaranteed to
   contrast on an accent fill in both themes (app.html contract). */

html.brand-v2 .bnav-fab {
  background: var(--accent) !important;
  color: var(--accent-on) !important;
  box-shadow: 0 2px 4px rgba(6, 42, 44, .12), 0 14px 32px rgba(6, 42, 44, .22) !important;
  transition: transform 160ms cubic-bezier(.2, .7, .3, 1),
              box-shadow 160ms cubic-bezier(.2, .7, .3, 1) !important;
}
html.brand-v2 .bnav-fab:active {
  transform: scale(.95) !important;
  background: var(--accent-press) !important;
}

/* Quick-add sheet: 24px top radius, token surfaces. */
html.brand-v2 .fab-sheet {
  background: var(--surface);
  border-top-left-radius: 24px;
  border-top-right-radius: 24px;
  box-shadow: 0 -12px 48px rgba(6, 42, 44, .16);
}
html.brand-v2 .fab-sheet::before { background: var(--line); }
html.brand-v2 .fab-sheet-row {
  color: var(--text-primary);
  border-radius: 12px;
  transition: background-color 160ms cubic-bezier(.2, .7, .3, 1);
}
@media (hover: hover) {
  html.brand-v2 .fab-sheet-row:hover { background: var(--surface-2); }
}
html.brand-v2 .fab-sheet-row-icon {
  border-radius: 10px;
  background: var(--accent-tint);
  color: var(--accent-text, var(--accent));
}
html.brand-v2 .fab-sheet-row-title { color: var(--text-primary); }
html.brand-v2 .fab-sheet-row-sub { color: var(--text-tertiary); }
html.brand-v2 .fab-sheet-header { border-bottom: 1px solid var(--line); }
html.brand-v2 .fab-sheet-title { color: var(--text-primary); }
html.brand-v2 .fab-sheet-sub { color: var(--text-tertiary); }
html.brand-v2 .fab-sheet-row-cancel { color: var(--text-tertiary); }
html.brand-v2 .fab-sheet-overlay { background: rgba(6, 20, 21, .40); }

/* ---- 9. Modal shell: 24px top radius, token surfaces ------------------ */

html.brand-v2 .modal-overlay { background: rgba(6, 20, 21, .50); }
html.brand-v2 .modal {
  background: var(--surface);
  border-top-left-radius: 24px;
  border-top-right-radius: 24px;
  box-shadow: 0 -12px 48px rgba(6, 42, 44, .18);
}
html.brand-v2 .modal::before { background: var(--line); }
html.brand-v2 .modal-title { color: var(--text-primary); }
html.brand-v2 .modal-close { color: var(--text-tertiary); }
@media (hover: hover) {
  html.brand-v2 .modal-close:hover {
    background: var(--surface-2);
    color: var(--text-primary);
  }
}
@media (min-width: 600px) {
  html.brand-v2 .modal { border-radius: 24px; }
}

/* ---- 10. Home Balo FAB + sheet ----------------------------------------
   Balo law: the greeting strip is the ONE Balo presence on Home, and
   the v1 cartoon art is off-brand for V2 -- hide the legacy img (inline
   style needs !important) and show a quiet spark glyph instead. The
   button stays the Ask Balo entry seam (_openBalo). z-index untouched. */

html.brand-v2 .uh-balo-fab {
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(6, 42, 44, .08), 0 10px 28px rgba(6, 42, 44, .16);
  transition: transform 160ms cubic-bezier(.2, .7, .3, 1),
              box-shadow 160ms cubic-bezier(.2, .7, .3, 1);
}
html.brand-v2 .uh-balo-fab:active { transform: scale(.94); }
html.brand-v2 .uh-balo-fab img { display: none !important; }
html.brand-v2 .uh-balo-fab::after {
  content: "\2731";
  font-size: 19px;
  line-height: 1;
  color: var(--accent-text, var(--accent));
}
html.brand-v2 .uh-balo-overlay { background: rgba(6, 20, 21, .50); }
html.brand-v2 .uh-balo-sheet {
  border-radius: 24px 24px 0 0;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 -12px 48px rgba(6, 42, 44, .18);
}
html.brand-v2 .uh-balo-close {
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text-secondary);
}

/* ---- 11. Focus rings (AA both themes) --------------------------------- */

html.brand-v2 .uh-clickable:focus-visible,
html.brand-v2 .uh-asset-row:focus-visible,
html.brand-v2 .uh-cmdbar .uh-cmd:focus-visible,
html.brand-v2 .uh-bell:focus-visible,
html.brand-v2 .uh-avatar:focus-visible,
html.brand-v2 .uh-qa-btn:focus-visible,
html.brand-v2 .bnav-tab:focus-visible,
html.brand-v2 .bnav-fab:focus-visible,
html.brand-v2 .fab-sheet-row:focus-visible,
html.brand-v2 .modal-close:focus-visible,
html.brand-v2 .uh-balo-fab:focus-visible,
html.brand-v2 .uh-balo-close:focus-visible,
html.brand-v2 .bv2-balo-strip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---- 12. Dark theme: shadows become lines + lighter surfaces ---------- */

html.brand-v2[data-theme="dark"] .uh-tile,
html.brand-v2[data-theme="dark"] .uh-card,
html.brand-v2[data-theme="dark"] .uh-asset-row,
html.brand-v2[data-theme="dark"] .uh-other-orgs {
  box-shadow: none;
  border-color: var(--line);
}
@media (hover: hover) {
  html.brand-v2[data-theme="dark"] .uh-tile.uh-clickable:hover,
  html.brand-v2[data-theme="dark"] .uh-asset-row:hover {
    box-shadow: none;
    background: var(--surface-2);
  }
}
html.brand-v2[data-theme="dark"] .bnav { box-shadow: none !important; }
html.brand-v2[data-theme="dark"] .bnav-fab {
  box-shadow: 0 10px 28px rgba(0, 0, 0, .45) !important;
}
html.brand-v2[data-theme="dark"] .fab-sheet,
html.brand-v2[data-theme="dark"] .modal,
html.brand-v2[data-theme="dark"] .uh-balo-sheet {
  box-shadow: 0 -12px 48px rgba(0, 0, 0, .55);
  border-top: 1px solid var(--line);
}
html.brand-v2[data-theme="dark"] .uh-balo-fab {
  box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
}
html.brand-v2[data-theme="dark"] .modal-overlay,
html.brand-v2[data-theme="dark"] .fab-sheet-overlay,
html.brand-v2[data-theme="dark"] .uh-balo-overlay {
  background: rgba(0, 0, 0, .60);
}
/* The media overlay band + white serif name are theme-invariant (dark
   teal scrim under white text clears AA in both themes) -- no dark
   variant needed for .uh-thumb::after / .uh-asset-name. */

/* ---- 13. Reduced motion: kill every transition/transform we author --- */

@media (prefers-reduced-motion: reduce) {
  html.brand-v2 .uh-tile,
  html.brand-v2 .uh-asset-row,
  html.brand-v2 .uh-cmdbar .uh-cmd,
  html.brand-v2 .uh-bell,
  html.brand-v2 .bnav-tab,
  html.brand-v2 .fab-sheet-row,
  html.brand-v2 .uh-balo-fab,
  html.brand-v2 .bv2-balo-strip {
    transition: none;
  }
  html.brand-v2 .bnav-fab { transition: none !important; }
  html.brand-v2 .uh-tile.uh-clickable:hover,
  html.brand-v2 .uh-asset-row:hover,
  html.brand-v2 .uh-tile.uh-clickable:active,
  html.brand-v2 .uh-asset-row:active,
  html.brand-v2 .uh-cmdbar .uh-cmd:active,
  html.brand-v2 .uh-bell:active,
  html.brand-v2 .uh-balo-fab:active {
    transform: none;
  }
  html.brand-v2 .bnav-fab:active { transform: none !important; }
}

/* ---- 12. Ask Balo sheet (.bv2-ask-*) ----------------------------------
   The flagship conversational-card surface (js/brand-v2-ask-balo.js),
   rendered inside the existing .uh-balo-sheet. Cards, not chat bubbles.
   One Balo avatar (greeting) only; answer cards carry no mascot. */

html.brand-v2 .uh-balo-sheet {
  max-height: 82vh;
  overflow-y: auto;
  padding: 24px 20px 28px;
}
html.brand-v2 .bv2-ask {
  display: block;
  font-family: var(--font-sans);
  color: var(--text-primary);
}
html.brand-v2 .bv2-ask-greeting {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin: 2px 36px 16px 0; /* right gap clears the sheet close button */
}
html.brand-v2 .bv2-ask-avatar { flex: 0 0 auto; }
html.brand-v2 .bv2-ask-avatar img {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--accent-tint);
}
html.brand-v2 .bv2-ask-greeting-main { flex: 1; min-width: 0; }
html.brand-v2 .bv2-ask-headline {
  font-family: var(--font-serif) !important;
  font-size: 26px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  font-optical-sizing: auto;
}
html.brand-v2 .bv2-ask-greet-line {
  margin-top: 4px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--text-secondary);
}
html.brand-v2 .bv2-ask-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 14px;
}
html.brand-v2 .bv2-ask-chip {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  padding: 9px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--accent-text);
  font-family: var(--font-sans);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  max-width: 100%;
  transition: background-color 160ms cubic-bezier(.2, .7, .3, 1),
              border-color 160ms cubic-bezier(.2, .7, .3, 1),
              color 160ms cubic-bezier(.2, .7, .3, 1);
}
@media (hover: hover) {
  html.brand-v2 .bv2-ask-chip:hover {
    background: var(--accent-tint);
    border-color: var(--accent);
  }
}
html.brand-v2 .bv2-ask-chip[aria-pressed="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-on);
}
html.brand-v2 .bv2-ask-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
html.brand-v2 .bv2-ask-answer { min-height: 8px; }
html.brand-v2 .bv2-ask-card {
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(6, 42, 44, .05), 0 8px 24px rgba(6, 42, 44, .07);
  padding: 18px 18px 14px;
  margin: 0 0 10px;
}
html.brand-v2 .bv2-ask-card-title {
  font-family: var(--font-serif) !important;
  font-size: 19px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--text-primary);
  margin: 0 0 10px;
  font-optical-sizing: auto;
}
html.brand-v2 .bv2-ask-section { margin: 0 0 12px; }
html.brand-v2 .bv2-ask-section:last-of-type { margin-bottom: 4px; }
html.brand-v2 .bv2-ask-section-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin: 0 0 5px;
}
html.brand-v2 .bv2-ask-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 3px 0;
}
html.brand-v2 .bv2-ask-row-main {
  flex: 1;
  min-width: 0;
  font-size: 14.5px;
  line-height: 1.45;
  color: var(--text-primary);
}
html.brand-v2 .bv2-ask-row-meta {
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-secondary);
}
html.brand-v2 .bv2-ask-money-line {
  font-size: 16px;
  line-height: 1.5;
  color: var(--text-primary);
  padding: 1px 0;
}
html.brand-v2 .bv2-ask-prov {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--text-tertiary);
}
html.brand-v2 .bv2-ask-thinking {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 2px;
  font-size: 13.5px;
  color: var(--text-secondary);
}
html.brand-v2 .bv2-ask-thinking-dots { display: inline-flex; gap: 4px; }
html.brand-v2 .bv2-ask-thinking-dots span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  opacity: .35;
  animation: bv2-ask-dot 900ms cubic-bezier(.2, .7, .3, 1) infinite;
}
html.brand-v2 .bv2-ask-thinking-dots span:nth-child(2) { animation-delay: 150ms; }
html.brand-v2 .bv2-ask-thinking-dots span:nth-child(3) { animation-delay: 300ms; }
@keyframes bv2-ask-dot {
  0%, 100% { opacity: .3; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-2px); }
}

/* Dark theme: Ask Balo materials. */
html.brand-v2[data-theme="dark"] .bv2-ask-card {
  box-shadow: none;
  border-color: var(--line);
  background: var(--surface-2);
}
html.brand-v2[data-theme="dark"] .bv2-ask-chip {
  background: var(--surface-2);
}
html.brand-v2[data-theme="dark"] .bv2-ask-avatar img {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--accent-tint);
}

/* Reduced motion: the thinking dots hold still. */
@media (prefers-reduced-motion: reduce) {
  html.brand-v2 .bv2-ask-thinking-dots span { animation: none; opacity: .7; }
}

/* ---- 14. Critique round 1 fixes (panel consensus) --------------------- */

/* P1 (Apple/Stripe/Linear/Porsche/Pixar): dark-theme SELECTED chip was
   dark ink on a dark pill (the later dark chip rule overrode the fill
   but not the label). Solid accent fill + dark ink, clearly heavier
   than idle chips. Dark accent #4FB3AC vs --accent-on #06282A = 7.0:1. */
html.brand-v2[data-theme="dark"] .bv2-ask-chip[aria-pressed="true"] {
  background: var(--accent);
  color: var(--accent-on);
  border-color: var(--accent);
}

/* P1 (Linear/Pixar) + P2 (Porsche): photo-LESS asset cards rendered a
   ~400px empty gradient void with one small glyph, inflating Home by
   ~44% and washing white names over a pale band (SUNSHINE 2.5:1).
   Cards without a real photograph collapse to a compact 120px band
   with a deeper, flatter localized band behind the name (white name
   on rgba(6,42,44,.78) clears AA large-text in both themes).
   Photo cards and the pinned overlay geometry are untouched -- the
   selector excludes any thumb containing an <img>. */
/* RESERVED PHOTO BOX (2026-08-12, asset surface render stability).
   A thumb marked [data-photo-pending] belongs to an asset that HAS a photo
   whose signed URL has not been minted yet. It must keep the PHOTO geometry
   (the base 16/10 rule above) so that injecting the <img> one round-trip
   later shifts nothing. Measured before this rule, against these very
   stylesheets: +114px at 390px and +269px at 1280px per plain card, +74px /
   +229px per curated-art card, every photo card moving at once.
   The compact 120px/160px bands below are for cards that have NO photo, and
   they keep them -- the exclusion is narrow on purpose. */
html.brand-v2 .uh-asset-row:not(:has(.uh-thumb img)):not(:has(.uh-thumb[data-photo-pending])) .uh-thumb {
  aspect-ratio: auto;
  height: 120px;
}
html.brand-v2 .uh-asset-row:not(:has(.uh-thumb img)):not(:has(.uh-thumb[data-photo-pending])) .uh-thumb::after {
  height: 70%;
  background: linear-gradient(to top,
    rgba(6, 42, 44, .78) 0%,
    rgba(6, 42, 44, .44) 60%,
    rgba(6, 42, 44, .08) 100%);
}
html.brand-v2 .uh-asset-row:not(:has(.uh-thumb img)):not(:has(.uh-thumb[data-photo-pending])) .uh-asset-name {
  top: 120px;
}

/* P2 (Pixar): desktop full-width photo cards had no height clamp (a
   single-asset card rendered a ~1400px hero). Clamp the media and keep
   the name anchored to the real media bottom edge. */
html.brand-v2 .uh-asset-row .uh-thumb { overflow: hidden; }
html.brand-v2 .uh-asset-row .uh-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
@media (min-width: 1024px) {
  html.brand-v2 .uh-asset-row .uh-thumb { max-height: 420px; }
  html.brand-v2 .uh-asset-row .uh-asset-name { top: min(62.5cqw, 420px); }
}

/* ---- 15. Correction mission: one brand hierarchy ----------------------- */

/* Home: the greeting strip IS the Balo entry -- the redundant FAB (same
   sheet, second Balo presence) is retired under V2. */
html.brand-v2 .uh-balo-fab { display: none !important; }

/* The strip graduates from notification-bar to intentional insight card:
   surface card, overline identity, larger avatar, primary-ink insight. */
html.brand-v2 .bv2-balo-strip {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 12px 16px;
  margin: 14px 0 0;
  box-shadow: 0 1px 2px rgba(6, 42, 44, .05), 0 8px 24px rgba(6, 42, 44, .07);
}
html.brand-v2 .bv2-balo-avatar { width: 36px; height: 36px; }
html.brand-v2 .bv2-balo-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
html.brand-v2 .bv2-balo-overline {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--accent-text, var(--accent));
}
html.brand-v2 .bv2-balo-line {
  font-size: 14.5px;
  color: var(--text-primary);
}
html.brand-v2[data-theme="dark"] .bv2-balo-strip { box-shadow: none; background: var(--surface-2); }

/* Wordmark typography aligned to the approved board (BALEN, tracked caps).
   Glyphs unchanged; treatment only. Applies wherever the wordmark renders
   next to the mark (global header + auth hero). */
html.brand-v2 .hero-brand-wordmark,
html.brand-v2 .auth-hero-wordmark {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-weight: 600;
}

/* Auth: the official tile needs no white plate behind it -- the tile IS
   the container. Plate becomes a neutral holder. */
html.brand-v2 .auth-hero-logo-plate {
  background: transparent;
  box-shadow: none;
  padding: 0;
}
/* Auth Balo welcome (BALO_SYSTEM 'Welcome'): one calm circular portrait
   chip + one line. Photography-real, never cartoon. */
html.brand-v2 .bv2-auth-guide {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 18px;
}
html.brand-v2 .bv2-auth-balo {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .85), 0 6px 18px rgba(4, 18, 18, .35);
}
html.brand-v2 .bv2-auth-balo-line {
  font-size: 14.5px;
  line-height: 1.5;
  max-width: 34ch;
}

/* Shared Balo state figure (BALO_SYSTEM): empty/calm/welcome pattern. */
html.brand-v2 .bv2-balo-state {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  margin: 0 0 12px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(6, 42, 44, .05), 0 8px 24px rgba(6, 42, 44, .07);
}
html.brand-v2 .bv2-balo-state-line {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.4;
}
html.brand-v2 .bv2-balo-state-sub {
  margin-top: 2px;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.45;
}
html.brand-v2[data-theme="dark"] .bv2-balo-state { box-shadow: none; background: var(--surface-2); }

/* Ask Balo gentle guidance hint (photo prompts etc.) */
html.brand-v2 .bv2-ask-hint {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--line);
}

/* ---- 16. Assets page (portfolio) V2 card grid -------------------------- */

/* The org section hosts the SAME shared visual card Home uses; the grid
   is responsive: 1-col mobile, 2-col >=720px, 3-col >=1200px. */
html.brand-v2 .bv2-pf-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
  padding: 4px 14px 14px;
}
@media (min-width: 720px) {
  html.brand-v2 .bv2-pf-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1200px) {
  html.brand-v2 .bv2-pf-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
html.brand-v2 .bv2-pf-cell { min-width: 0; }
/* Card fills its cell; the shared media-first treatment (section 6)
   applies unchanged. Filtered-out cells hide via [data-pf-row]. */
html.brand-v2 .bv2-pf-cell > .uh-asset-row { height: 100%; }
/* Inside an org card the grid cards sit on the card surface: give them
   a hairline so they read as objects on both themes. */
html.brand-v2 .bv2-pf-cell > .uh-asset-row {
  border: 1px solid var(--line);
}

/* ---- 17. Brand Book lockup law (identity migration) ------------------- */

/* The official wordmark is BALEN -- tracked caps, no product-domain
   suffix in the lockup. The ".app" tld is Classic-only. */
html.brand-v2 .hero-brand-wordmark,
html.brand-v2 .auth-hero-wordmark {
  text-transform: uppercase;
  letter-spacing: 0.20em;
  font-weight: 500;
}
/* Clear space: the gap between mark and wordmark is ~half the mark
   width (Brand Book proportion), and the mark never renders below
   20px. Sizing classes stay owned by app.html (.balen-logo-md etc). */
html.brand-v2 .hero-brand { gap: 14px; align-items: center; }
html.brand-v2 .hero-brand .balen-logo { min-width: 20px; min-height: 20px; }

/* Auth lockup: mark | BALEN over tagline (Brand Book lockup shape). */
html.brand-v2 .auth-hero-brand {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 14px;
  row-gap: 3px;
  align-items: center;
}
html.brand-v2 .auth-hero-brand .auth-hero-logo-plate { grid-row: 1 / span 2; }
html.brand-v2 .bv2-tagline {
  grid-column: 2;
  font-family: var(--font-sans);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(244, 251, 251, .72);
  white-space: nowrap;
}

/* ---- 18. Hero header (approved concept) + Balo attention center -------- */

/* BELL REMOVAL (decision 2026-07-27): Balo is the single attention
   authority. Home command-bar bell + the hero/workspace nav bells are
   retired under V2; no placeholder space remains (flex gaps collapse). */
html.brand-v2 .uh-bell { display: none !important; }
html.brand-v2 .hero-icon-btn[aria-label="Notifications"] { display: none !important; }

/* The context strip's data now lives in the metric cards. */
html.brand-v2 .uh-ctx { display: none !important; }

/* Header grid: desktop 3 zones (brand | personal | operating), the
   metric row under the operating zone; purpose-built mobile stack. */
html.brand-v2 .uh-head {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    "brand personal actions"
    "brand personal metrics";
  align-items: start;
  column-gap: 28px;
  row-gap: 10px;
  padding-top: 8px;
}
html.brand-v2 .bv2-brand-zone { grid-area: brand; }
html.brand-v2 .uh-avatar { grid-area: personal; }
html.brand-v2 .uh-head-main { grid-area: personal; margin-left: 64px; }
html.brand-v2 .uh-head-right { grid-area: actions; justify-self: end; }
html.brand-v2 .bv2-metrics { grid-area: metrics; justify-self: end; }

/* Brand zone: official assets only. Mark ~72px desktop; wordmark image
   below; approved descriptor under it. Theme variants toggle by class. */
html.brand-v2 .bv2-brand-zone {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 150px;
}
/* The brand zone renders through js/brand-lockup.js now, which sizes the
   mark and the wordmark inline from ONE ratio (BRAND_V2_SPEC section 10).
   The retired `.bv2-bz-mark` / `.bv2-bz-word` rules paired a 72px mark
   with a 132px wordmark, a 0.389 word/mark ratio against the Brand
   Book's 0.46. That drift is what a second implementation buys you. */
html.brand-v2 .bv2-bz-tagline {
  font-family: var(--font-sans);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--text-tertiary);
  white-space: nowrap;
}
/* Theme visibility for the lockup is owned by js/brand-lockup.js, which
   injects it once. The `.bv2-on-light` / `.bv2-on-dark` pair had no
   remaining markup after the brand zone was consolidated. */

/* Metric cards: real data, quiet chrome, obvious click affordance. */
html.brand-v2 .bv2-metrics {
  display: grid;
  grid-template-columns: repeat(4, minmax(96px, auto));
  gap: 10px;
}
html.brand-v2 .bv2-m-card {
  appearance: none;
  -webkit-appearance: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(6, 42, 44, .05), 0 8px 24px rgba(6, 42, 44, .07);
  font-family: var(--font-sans);
  text-align: left;
  cursor: pointer;
  transition: transform 160ms cubic-bezier(.2, .7, .3, 1),
              box-shadow 160ms cubic-bezier(.2, .7, .3, 1);
}
html.brand-v2 .bv2-m-card.is-static { cursor: default; }
@media (hover: hover) {
  html.brand-v2 .bv2-m-card:not(.is-static):hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(6, 42, 44, .06), 0 14px 32px rgba(6, 42, 44, .10);
  }
}
html.brand-v2 .bv2-m-num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 20px;
  line-height: 1.1;
  color: var(--text-primary);
}
html.brand-v2 .bv2-m-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
}
html.brand-v2 .bv2-m-sub {
  font-size: 10.5px;
  color: var(--text-tertiary);
}
html.brand-v2 .bv2-m-card.is-attn .bv2-m-num { color: var(--accent-text, var(--accent)); }
html.brand-v2 .bv2-m-card.is-ok .bv2-m-num { color: var(--pos-text, var(--accent-text)); }
html.brand-v2[data-theme="dark"] .bv2-m-card { box-shadow: none; background: var(--surface-2); }

/* Balo strip CTA */
html.brand-v2 .bv2-balo-cta {
  flex: 0 0 auto;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-on);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

/* Attention center rows (inside the Ask Balo sheet). */
html.brand-v2 .bv2-att-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}
html.brand-v2 .bv2-att-row:first-of-type { border-top: 0; }
html.brand-v2 .bv2-att-main { flex: 1; min-width: 0; }
html.brand-v2 .bv2-att-title {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.35;
}
html.brand-v2 .bv2-att-explain {
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.4;
  margin-top: 1px;
}
html.brand-v2 .bv2-att-ctx {
  font-size: 11.5px;
  color: var(--text-tertiary);
  margin-top: 2px;
}
html.brand-v2 .bv2-att-act {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 auto;
  padding: 8px 14px;
  border: 0;
  border-radius: 12px;
  background: var(--accent);
  color: var(--accent-on);
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
@media (hover: hover) {
  html.brand-v2 .bv2-att-act:hover { background: var(--accent-press); }
}
html.brand-v2 .bv2-att-empty {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 2px;
}
html.brand-v2 .bv2-att-empty-line {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text-primary);
}

/* Atmospheric header background: ivory -> cool teal wash + one soft
   contour; pure CSS gradients (no rasters, no motion). Text sits on
   the page tokens above it -- contrast unchanged. */
html.brand-v2 .uh-root {
  position: relative;
}
html.brand-v2 .uh-root::before {
  content: "";
  position: absolute;
  left: -24px;
  right: -24px;
  top: -18px;
  height: 320px;
  pointer-events: none;
  z-index: -1;
  background:
    radial-gradient(120% 90% at 8% 0%, rgba(27, 107, 109, .07) 0%, rgba(27, 107, 109, 0) 55%),
    radial-gradient(90% 70% at 90% 10%, rgba(62, 155, 150, .06) 0%, rgba(62, 155, 150, 0) 60%),
    linear-gradient(180deg, rgba(238, 246, 245, .85) 0%, rgba(238, 246, 245, 0) 100%);
}
html.brand-v2[data-theme="dark"] .uh-root::before {
  background:
    radial-gradient(120% 90% at 8% 0%, rgba(79, 179, 172, .06) 0%, rgba(79, 179, 172, 0) 55%),
    linear-gradient(180deg, rgba(16, 25, 27, .8) 0%, rgba(16, 25, 27, 0) 100%);
}

/* Mobile: purpose-built stack (not a shrunken desktop hero). */
@media (max-width: 819px) {
  html.brand-v2 .uh-head {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "brand actions"
      "personal personal"
      "metrics metrics";
    column-gap: 12px;
  }
  html.brand-v2 .bv2-brand-zone { flex-direction: row; align-items: center; gap: 10px; min-width: 0; }
  /* Narrow: the zone lays out horizontally and the lockup shrinks. The
     component sets height inline on purpose (it reserves the box before
     decode so the header cannot shift), so overriding it here needs
     !important. Width stays `auto`, so the intrinsic aspect ratio still
     governs and neither image can distort. */
  html.brand-v2 .bv2-bz-lockup { flex-direction: row !important; align-items: center !important; gap: 8px !important; }
  html.brand-v2 .bv2-bz-lockup .balen-lockup-mark { height: 34px !important; }
  html.brand-v2 .bv2-bz-lockup .balen-lockup-word { height: 16px !important; }
  html.brand-v2 .bv2-bz-tagline { display: none; }
  html.brand-v2 .uh-head-main { margin-left: 64px; }
  html.brand-v2 .bv2-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    justify-self: stretch;
    width: 100%;
  }
  html.brand-v2 .bv2-m-card { width: 100%; }
}
@media (min-width: 820px) and (max-width: 1119px) {
  html.brand-v2 .bv2-metrics { grid-template-columns: repeat(2, minmax(96px, auto)); }
}

/* ---- 19. Curated asset-hero placeholders (display priority tier 3) ---- */

/* Branded atmospheric artwork per type -- SWAPPABLE files awaiting final
   designer / AI-hero art. Photo cards are untouched (an <img> always
   wins the priority chain in JS). */
html.brand-v2 .bv2-thumb-art {
  background-size: cover;
  background-position: center;
  position: relative;
}
html.brand-v2 .bv2-art-aircraft  { background-image: url(/assets/brand/v2/asset-heroes/aircraft.jpg); }
html.brand-v2 .bv2-art-boat      { background-image: url(/assets/brand/v2/asset-heroes/boat.jpg); }
html.brand-v2 .bv2-art-property  { background-image: url(/assets/brand/v2/asset-heroes/property.jpg); }
html.brand-v2 .bv2-art-vehicle   { background-image: url(/assets/brand/v2/asset-heroes/vehicle.jpg); }
html.brand-v2 .bv2-art-equipment { background-image: url(/assets/brand/v2/asset-heroes/equipment.jpg); }
html.brand-v2 .bv2-art-other     { background-image: url(/assets/brand/v2/asset-heroes/other.jpg); }

/* Artwork cards get a mid-height presentation: taller than the retired
   empty-gradient compact band, shorter than a real photo hero. The name
   anchor follows. */
html.brand-v2 .uh-asset-row:not(:has(.uh-thumb img)):not(:has(.uh-thumb[data-photo-pending])) .uh-thumb.bv2-thumb-art {
  height: 160px;
}
html.brand-v2 .uh-asset-row:has(.bv2-thumb-art):not(:has(.uh-thumb[data-photo-pending])) .uh-asset-name {
  top: 160px;
}

/* Elegant Add-photo affordance: glass pill, bottom-right, admin-only
   (markup-gated), opens Asset Settings directly. */
html.brand-v2 .bv2-addphoto {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 3;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(6, 20, 20, .38);
  border: 1px solid rgba(255, 255, 255, .35);
  color: #FFFFFF;
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 160ms cubic-bezier(.2, .7, .3, 1);
}
@media (hover: hover) {
  html.brand-v2 .bv2-addphoto:hover { background: rgba(6, 20, 20, .55); }
}
html.brand-v2 .bv2-addphoto:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
}

/* ---- 18. Canonical header lockup (js/brand-lockup.js) ---------------- */
/*
   The lockup ships BOTH surface variants and CSS reveals one, so a theme
   flip needs no JS re-render. Default = light surface.

   Replaces the old treatment, which put the rounded-square APP ICON in
   page headers and re-typeset BALEN as UI text. Both are forbidden by
   BRAND_V2_SPEC.md section 10: the tile is an icon treatment, and the
   wordmark is drawn artwork that must never be re-typeset.
*/
html.brand-v2 .balen-lockup .balen-on-dark  { display: none; }
html.brand-v2 .balen-lockup .balen-on-light { display: block; }

html.brand-v2[data-theme="dark"] .balen-lockup .balen-on-light { display: none; }
html.brand-v2[data-theme="dark"] .balen-lockup .balen-on-dark  { display: block; }

/* Surfaces that are dark in BOTH themes (auth cockpit hero, dark heroes)
   always take the knockout variant. */
html.brand-v2 .balen-lockup--on-dark .balen-on-light { display: none; }
html.brand-v2 .balen-lockup--on-dark .balen-on-dark  { display: block; }

/* Aspect ratio is protected: height is authored inline, width stays
   auto. This guards against a future flex/grid rule stretching either
   image. */
html.brand-v2 .balen-lockup img { width: auto !important; max-width: none; flex: 0 0 auto; }

/* The lockup replaces the text wordmark under V2, so the legacy text
   nodes must not also render (they would double the wordmark). */
html.brand-v2 .hero-brand .balen-lockup ~ .hero-brand-wordmark,
html.brand-v2 .auth-hero-brand .balen-lockup ~ .auth-hero-wordmark { display: none; }

/* Small viewports: drop to the mark alone rather than shrinking the
   wordmark below legibility. */
@media (max-width: 380px) {
  html.brand-v2 .hero-brand .balen-lockup .balen-lockup-word { display: none; }
}

/* The legacy pre-logo dot (app.html `.hero-brand:not(:has(.balen-logo))::before`)
   is a fallback for hero-brand instances that never got the inline SVG
   mark. The canonical lockup emits `.balen-lockup`, NOT `.balen-logo`, so
   without this rule the V2 header would render a stray glowing dot in
   front of the lockup. Suppress it wherever the lockup is present. */
html.brand-v2 .hero-brand:has(.balen-lockup)::before,
html.brand-v2 .auth-hero-brand:has(.balen-lockup)::before { display: none !important; }

/* The lockup owns its own spacing, so the parent's legacy gap would add a
   second, larger gutter between mark and wordmark. */
html.brand-v2 .hero-brand:has(.balen-lockup) { gap: 0; }

/* ---- 20. Canonical auth steps (login / code entry / set password) -----
   Every authentication step renders through the one shell in js/auth.js
   (_authShellHtml), so it inherits the hero, the lockup, the split-panel
   collapse and both themes. These rules style the step-specific pieces
   of the FORM PANE only.

   Why this section exists: the code-entry and set-password screens used
   to be bare `.card`s assembled from inline style attributes -- fixed
   pixel sizes, a hardcoded `var(--navy)` link, and the OS envelope emoji
   as the only "icon". Inline styles inherit no token, so those screens
   never followed the theme and never carried the brand. Everything below
   is authored against tokens so light/dark and the type ramp come free. */

/* Step glyph: replaces the emoji. Quiet brand-ink mark on a soft tint,
   sized to sit with the title rather than shout over it. */
html.brand-v2 .auth-step-icon {
  width: 44px;
  height: 44px;
  margin: 0 0 14px;
  border-radius: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--k-brand, var(--accent));
  background: var(--k-surface-2, var(--surface-2));
  border: 1px solid var(--line);
}

/* The address the code went to. Not a colour accent -- weight carries it,
   so it stays legible in both themes. */
html.brand-v2 .auth-step-strong {
  color: var(--text-primary);
  font-weight: 600;
  overflow-wrap: anywhere;
}

/* One-time code field. Tabular figures + generous tracking so six digits
   read as six discrete characters; the caret stays visible because the
   field is left-padded by the tracking, not centred text with a gap. */
html.brand-v2 .auth-otp-input {
  width: 100%;
  text-align: center;
  font-family: var(--font-mono, var(--mono, monospace));
  font-variant-numeric: tabular-nums;
  font-size: 30px;
  font-weight: 600;
  letter-spacing: .22em;
  text-indent: .22em; /* re-centre: tracking adds a trailing gap */
  padding: 14px 12px;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-primary);
}
html.brand-v2 .auth-otp-input:focus {
  outline: none;
  border-color: var(--k-brand, var(--accent));
  box-shadow: var(--bv2-focus-ring, 0 0 0 3px rgba(21, 90, 92, .22));
}
html.brand-v2 .auth-otp-input::placeholder {
  color: var(--text-tertiary);
  letter-spacing: .22em;
}

/* Back / resend pair. Text buttons, evenly weighted so neither reads as
   the primary action -- the primary action is the Verify button above. */
html.brand-v2 .auth-step-actions {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 16px;
  flex-wrap: wrap;
}
html.brand-v2 .auth-step-actions .btn-text { font-size: 13px; }
html.brand-v2 .auth-step-action-strong {
  color: var(--k-brand, var(--accent));
  font-weight: 600;
}

/* Login footer help. Was an inline style block referencing --ink3, a
   token that does not exist under V2 (the real name is --text-tertiary),
   so the text fell back to inherit and rendered at full ink weight. */
html.brand-v2 .auth-footer-help {
  font-size: 12px;
  color: var(--text-tertiary);
  margin-top: 4px;
  line-height: 1.5;
}

/* Interior steps keep the hero but drop the value-prop list, so the hero
   column would otherwise stretch its remaining children apart. */
html.brand-v2 .auth-hero:not(:has(.auth-hero-bullets)) {
  justify-content: flex-start;
  gap: 28px;
}

/* The code field is the focal element of its step: give it room above
   the Verify button so the two do not read as one stacked control. */
html.brand-v2 .auth-otp-input { margin-bottom: 16px; }
