/*!
 * Proven component layer: base styles, the app shell, layout primitives and the handful of
 * UI5 control adjustments that CSS variables alone can't reach. Reads tokens only.
 *
 * Naming: Proven classes are prefixed `ev` (BEM-ish: pvPanel, pvPanel__header, pvPanel--flush)
 * and never collide with UI5's `sap*` classes.
 */

/* ============================================================== base */

html, body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--pv-bg);
  color: var(--pv-text);
  font-family: var(--pv-font);
  font-size: var(--pv-fs-base);
  line-height: var(--pv-lh);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* UI5 sets its own body background via sapUiBody; keep ours. */
html .sapUiBody {
  background: var(--pv-bg);
}

/* After a theme switch (shared/boot.js): a hair's change makes every icon draw again with the font that has just
   loaded — some phone browsers otherwise keep the "missing character" boxes they drew while it was loading. */
.pvIconRedraw .sapUiIcon,
.pvIconRedraw .sapUiIcon::before,
.pvIconRedraw .pvNavItem__icon {
  letter-spacing: .01px;
}

/* Focus ring for Proven's own elements; UI5 controls draw their own (re-coloured via --sapContent_FocusColor). */
.pvLink:focus-visible,
.pvBrand:focus-visible,
.pvNavItem:focus-visible,
.pvCard:focus-visible,
.pvStepper__step:focus-visible {
  outline: 2px solid var(--pv-accent);
  outline-offset: 2px;
}

a.pvLink {
  color: var(--pv-accent);
  font-size: var(--pv-fs-base);
  text-decoration: none;
}

a.pvLink:hover {
  text-decoration: underline;
}

/*
 * Utilities are prefixed with `html` (specificity 0,1,1) so they beat UI5's single-class
 * control rules (.sapMText, .sapMTitle — 0,1,0), which load after our stylesheets.
 * Without it, <Text class="pvMuted"> silently keeps UI5's text colour.
 */
html .pvMono {
  font-family: var(--pv-font-mono);
  font-size: var(--pv-fs-md);
}

html .pvMuted {
  color: var(--pv-text-muted);
}

html .pvFaint {
  color: var(--pv-text-faint);
}

/* Uppercase micro-label: the designer's "DOCUMENT", "PAGE", "MARGINS" section headers. */
html .pvLabel {
  font-size: var(--pv-fs-xs);
  font-weight: var(--pv-fw-semibold);
  letter-spacing: var(--pv-tracking-label);
  text-transform: uppercase;
  color: var(--pv-text-muted);
  line-height: var(--pv-lh-tight);
}

.pvSrOnly {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ============================================================== app shell */

.pvShell {
  display: grid;
  grid-template-rows: var(--pv-header-h) 1fr;
  grid-template-columns: var(--pv-sidenav-w) 1fr;
  grid-template-areas: "header header" "nav main";
  height: 100vh;
  min-height: 0;
}

/* Pages without side navigation (landing, sign-in, verification) scroll the document itself,
   so browser find, anchors and full-page screenshots behave normally; the header stays sticky. */
.pvShell--noNav {
  grid-template-columns: 1fr;
  grid-template-areas: "header" "main";
  height: auto;
  min-height: 100vh;
}

.pvShell--noNav > .pvHeader {
  position: sticky;
  top: 0;
}

.pvShell--noNav > .pvMain {
  overflow: visible;
}

.pvHeader {
  grid-area: header;
  display: flex;
  align-items: center;
  gap: var(--pv-space-4);
  padding: 0 var(--pv-space-4);
  background: var(--pv-surface);
  border-bottom: 1px solid var(--pv-border);
  position: relative;
  z-index: 2;
}

.pvHeader__spacer {
  flex: 1;
}

.pvBrand {
  display: inline-flex;
  align-items: center;
  min-height: 40px; /* a comfortable tap target on phones (it links home) */
  gap: var(--pv-space-2);
  color: var(--pv-text);
  text-decoration: none;
  font-weight: var(--pv-fw-semibold);
  font-size: var(--pv-fs-lg);
  letter-spacing: -.01em;
}

.pvBrand__mark {
  width: 26px;
  height: 26px;
  flex: none;
}

.pvBrand__context {
  font-weight: var(--pv-fw-regular);
  color: var(--pv-text-muted);
  font-size: var(--pv-fs-base);
  padding-left: var(--pv-space-3);
  margin-left: var(--pv-space-1);
  border-left: 1px solid var(--pv-border);
}

.pvNav {
  grid-area: nav;
  background: var(--pv-surface);
  border-right: 1px solid var(--pv-border);
  padding: var(--pv-space-3) var(--pv-space-2);
  overflow-y: auto;
}

.pvNav__section {
  padding: var(--pv-space-4) var(--pv-space-3) var(--pv-space-2);
}

.pvNavItem {
  display: flex;
  align-items: center;
  gap: var(--pv-space-3);
  height: 34px;
  padding: 0 var(--pv-space-3);
  font-size: var(--pv-fs-base);
  border-radius: var(--pv-radius);
  color: var(--pv-text);
  text-decoration: none;
  cursor: pointer;
  transition: background var(--pv-dur-fast) var(--pv-ease), color var(--pv-dur-fast) var(--pv-ease);
}

.pvNavItem:hover {
  background: var(--pv-surface-2);
}

.pvNavItem--active {
  background: var(--pv-accent-soft);
  color: var(--pv-accent);
  font-weight: var(--pv-fw-medium);
}

.pvMain {
  grid-area: main;
  min-width: 0;
  min-height: 0;
  overflow: auto;
}

/* ============================================================== page layout */

.pvPage {
  max-width: var(--pv-content-max);
  margin: 0 auto;
  padding: var(--pv-space-6) var(--pv-space-6) var(--pv-space-12);
}

.pvPageHeader {
  display: flex;
  align-items: flex-end;
  gap: var(--pv-space-4);
  margin-bottom: var(--pv-space-6);
}

.pvPageHeader__titles {
  flex: 1;
  min-width: 0;
}

.pvPageHeader__title {
  margin: 0;
  font-size: var(--pv-fs-xl);
  font-weight: var(--pv-fw-semibold);
  line-height: var(--pv-lh-tight);
  letter-spacing: -.01em;
}

.pvPageHeader__subtitle {
  margin: var(--pv-space-1) 0 0;
  color: var(--pv-text-muted);
}

.pvGrid {
  display: grid;
  gap: var(--pv-space-4);
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

.pvStack {
  display: flex;
  flex-direction: column;
  gap: var(--pv-space-4);
}

.pvRow {
  display: flex;
  align-items: center;
  gap: var(--pv-space-2);
  flex-wrap: wrap;
}

/* ============================================================== surfaces */

.pvPanel {
  background: var(--pv-surface);
  border: 1px solid var(--pv-border);
  border-radius: var(--pv-radius-lg);
  box-shadow: var(--pv-shadow-1);
}

/* A panel may be a UI5 FlexBox (to bind `visible`); keep the surface colour. */
html .pvPanel.sapMFlexBox {
  background: var(--pv-surface);
}

.pvPanel__header {
  display: flex;
  align-items: center;
  gap: var(--pv-space-2);
  min-height: 44px;
  box-sizing: border-box;
  padding: var(--pv-space-1) var(--pv-space-2) var(--pv-space-1) var(--pv-space-4);
  border-bottom: 1px solid var(--pv-border);
}

.pvPanel__body {
  padding: var(--pv-space-4);
}

.pvCard {
  display: flex;
  flex-direction: column;
  gap: var(--pv-space-2);
  padding: var(--pv-space-5);
  background: var(--pv-surface);
  border: 1px solid var(--pv-border);
  border-radius: var(--pv-radius-lg);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--pv-dur-fast) var(--pv-ease), box-shadow var(--pv-dur) var(--pv-ease), transform var(--pv-dur) var(--pv-ease);
}

a.pvCard:hover,
.pvCard--interactive:hover {
  border-color: var(--pv-border-strong);
  box-shadow: var(--pv-shadow-2);
  transform: translateY(-1px);
}

a.pvCard:focus-visible {
  box-shadow: var(--pv-focus-ring);
  outline: none;
}

.pvCard__icon {
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: var(--pv-radius);
  background: var(--pv-accent-soft);
  color: var(--pv-accent);
  margin-bottom: var(--pv-space-2);
}

.pvCard__title {
  margin: 0;
  font-size: var(--pv-fs-lg);
  font-weight: var(--pv-fw-semibold);
}

.pvCard__text {
  margin: 0;
  color: var(--pv-text-muted);
}

.pvCard__footer {
  margin-top: auto;
  padding-top: var(--pv-space-3);
  color: var(--pv-accent);
  font-weight: var(--pv-fw-medium);
  font-size: var(--pv-fs-md);
}

/* ============================================================== badges & status */

.pvBadge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 var(--pv-space-2);
  border-radius: var(--pv-radius-pill);
  font-size: var(--pv-fs-sm);
  font-weight: var(--pv-fw-medium);
  background: var(--pv-surface-3);
  color: var(--pv-text-muted);
  white-space: nowrap;
}

.pvBadge--ok { background: var(--pv-ok-soft); color: var(--pv-ok); }
.pvBadge--warn { background: var(--pv-warn-soft); color: var(--pv-warn); }
.pvBadge--danger { background: var(--pv-danger-soft); color: var(--pv-danger); }
.pvBadge--info { background: var(--pv-info-soft); color: var(--pv-info); }

.pvDot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* Key-value rows inside panels ("Database ........ Healthy"). */
.pvKv {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  align-items: center;
  gap: var(--pv-space-2) var(--pv-space-4);
}

.pvKv > dt { color: var(--pv-text-muted); margin: 0; }
.pvKv > dd { margin: 0; text-align: right; }

/* Key/value built from UI5 Text pairs: labels never wrap, values align right and may wrap. */
html .pvKv > .sapMText:nth-child(odd) { white-space: nowrap; }
html .pvKv > .sapMText:nth-child(even),
html .pvKv > .pvBadge:nth-child(even) { justify-self: end; text-align: right; overflow-wrap: anywhere; }

/* ============================================================== feedback */

@keyframes pvShimmer {
  from { background-position: -200px 0; }
  to { background-position: calc(200px + 100%) 0; }
}

.pvSkeleton {
  display: inline-block;
  height: 12px;
  border-radius: var(--pv-radius-sm);
  background: linear-gradient(90deg, var(--pv-surface-3) 0, var(--pv-surface-2) 50%, var(--pv-surface-3) 100%) no-repeat;
  background-size: 200px 100%;
  background-color: var(--pv-surface-3);
  animation: pvShimmer 1.2s infinite linear;
}

.pvEmpty {
  display: grid;
  justify-items: center;
  gap: var(--pv-space-2);
  padding: var(--pv-space-12) var(--pv-space-6);
  text-align: center;
  color: var(--pv-text-muted);
}

.pvEmpty__title {
  margin: 0;
  color: var(--pv-text);
  font-size: var(--pv-fs-lg);
  font-weight: var(--pv-fw-semibold);
}

.pvFadeIn {
  animation: pvFadeIn var(--pv-dur) var(--pv-ease) both;
}

@keyframes pvFadeIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

kbd, .pvKbd {
  display: inline-block;
  min-width: 18px;
  padding: 0 5px;
  border: 1px solid var(--pv-border-strong);
  border-bottom-width: 2px;
  border-radius: var(--pv-radius-sm);
  background: var(--pv-surface);
  font-family: var(--pv-font-mono);
  font-size: var(--pv-fs-sm);
  line-height: 18px;
  text-align: center;
  color: var(--pv-text-muted);
}

/* ============================================================== UI5 control adjustments */

/* Buttons: medium weight, compact height, no Horizon pill feel. */
html .sapMBtnInner {
  font-weight: var(--pv-fw-medium);
}

html .sapMBtn .sapMBtnInner.sapMBtnEmphasized {
  font-weight: var(--pv-fw-semibold);
}

/* Titles: Proven uses semibold with slight negative tracking. */
html .sapMTitle {
  font-weight: var(--pv-fw-semibold);
  letter-spacing: -.01em;
}

/* Table and list headers read as the designer's quiet uppercase labels. */
html .sapMListTblHeader .sapMColumnHeader,
html .sapMListTblHeader .sapMLabel,
html .sapMListTblHeader .sapMText {
  font-size: var(--pv-fs-xs);
  font-weight: var(--pv-fw-semibold);
  letter-spacing: var(--pv-tracking-label);
  text-transform: uppercase;
  color: var(--pv-text-muted);
}

/* Focus halo on fields instead of Horizon's inner shadow. */
html .sapMInputBaseContentWrapper.sapMFocus,
html .sapMFocus > .sapMInputBaseContentWrapper {
  box-shadow: var(--pv-focus-ring);
}

/* Dialogs: flat header with a hairline, like the rest of the shell. */
html .sapMDialog {
  border-radius: var(--pv-radius-lg);
  box-shadow: var(--pv-shadow-pop);
}

html .sapMDialog .sapMDialogTitleGroup,
html .sapMDialog .sapMIBar.sapMHeader-CTX {
  box-shadow: inset 0 -1px 0 0 var(--pv-border);
}

/* Links: Horizon paints focused links as a filled accent box (high-specificity rule, and the
   router focuses the first link after navigation, so it shows on every page). Proven shows a ring
   for keyboard focus only. !important is deliberate: it overrides one specific theme rule. */
html body .sapMLnk.sapMLnk:focus {
  background: transparent !important;
  color: var(--pv-accent) !important;
  outline: none !important;
  box-shadow: none !important;
}

html body .sapMLnk.sapMLnk:focus-visible {
  outline: 2px solid var(--pv-accent) !important;
  outline-offset: 2px;
  border-radius: 2px;
}

html .sapMMessageToast {
  background: var(--pv-text);
  color: var(--pv-surface);
  border-radius: var(--pv-radius);
  box-shadow: var(--pv-shadow-pop);
  font-size: var(--pv-fs-md);
}

/* ============================================================== responsive */

@media (max-width: 900px) {
  .pvShell {
    grid-template-columns: 1fr;
    grid-template-areas: "header" "main";
  }

  .pvNav {
    display: none; /* collapsible drawer arrives with the Phase 2 shell control */
  }

  .pvPage {
    padding: var(--pv-space-4) var(--pv-space-4) var(--pv-space-10);
  }

  .pvPageHeader {
    flex-direction: column;
    align-items: stretch;
  }
}

/* ============================================================== activity (shared/util/Api.js) */

/* A thin bar at the very top while anything loads (shown after 150 ms, so quick answers don't flash it). */
.pvActivityBar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  height: 3px;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--pv-dur-fast) var(--pv-ease);
}

.pvActivityBar::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -40%;
  width: 40%;
  border-radius: 0 3px 3px 0;
  background: var(--pv-accent);
  animation: pvActivity 1.1s ease-in-out infinite;
}

.pvActivityBar--on {
  opacity: 1;
}

@keyframes pvActivity {
  0% { left: -40%; }
  60% { left: 60%; }
  100% { left: 100%; }
}

/* The button whose change is being processed can't be pressed twice. UI5 buttons show their own busy dots (set from
   Api.js); the account menu button, which isn't a UI5 control, pulses gently instead. No separate spinner. */
.pvBtnWorking {
  pointer-events: none;
}

.pvAccountBtn.pvBtnWorking {
  animation: pvWorkingPulse 1s ease-in-out infinite;
}

@keyframes pvWorkingPulse {
  50% { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
  .pvActivityBar::before { animation-duration: 2.4s; }
  .pvAccountBtn.pvBtnWorking { animation-duration: 2.4s; }
}

/*
 * Button focus (owner, 2026-10-12: "a strange little bar around" the home page's Sign in button after clicking).
 * UI5 draws a hard 2px frame (::before on the inner part) whenever a button has focus — after a mouse click too.
 * Proven: nothing after a click; for keyboard users (:focus-visible) the same soft halo as every other control.
 */
/* UI5: html.sap-desktop .sapMBtn:focus > .sapMFocusable:not(.sapMBadgeIndicator)::before — loaded after this file, so
 * the selector here is one step stronger. */
html.sap-desktop body .sapMBtn.sapMBtn:focus > .sapMFocusable:not(.sapMBadgeIndicator)::before,
html body .sapMBtn.sapMBtn:focus > .sapMFocusable::before {
  content: none;
  display: none;
}
html .sapMBtn:focus,
html .sapMBtn:focus .sapMBtnInner {
  outline: none;
}
html body .sapMBtn.sapMBtn:focus-visible > .sapMBtnInner {
  box-shadow: var(--pv-focus-ring);
}
