@import url("/assets/css/nzr-brand-surface.css");

/* The app shell: the landlord app, drawn once.
 *
 * William, 2026-09-26: "The way the landlord app is built is how we need the
 * other portals to match styling etc too." And 2026-09-28, shown the landlord
 * app before and after 14 Sep, when #264 had re-skinned it in the tenant
 * portal's scale: "the one on the left is better". So this is the landlord
 * app's own look: the compact header with the emblem, the sage strip under
 * it, 15px Inter on the pale ground, 16px panels on a phone and the 1200px
 * column. Every value here was read by
 * computed style from the landlord demo in Chromium at 390x844 and 1280x900
 * (docs/standards/design/app-shell.md has the table), and
 * tests/app-shell-parity.browser.mjs renders this file beside the landlord
 * demo and fails if the two disagree on any shared component.
 *
 * A portal links this file after the brand bridge, puts `nzr-app` on <body>,
 * and keeps only what is unique to its own screens in its local CSS. The
 * class vocabulary is `nzr-*`; the staff shell's own generic names (.top,
 * .btn, .panel, .kpi, .nzt, .nzm) are grouped in so the staff and landlord
 * shells can adopt the file by adding `nzr-app` to <body> without renaming
 * (Phase 4 of docs/markdown-standards-framework-plan.md).
 *
 * Phone first: the base rules are the 390px rules; `min-width: 701px` adds
 * the desk. The dock appears at 700px and below, exactly where the landlord
 * app's does. */

.nzr-app {
  --nzr-shell-header: rgba(18, 61, 42, .96);
  --nzr-shell-shadow: 0 1px 2px rgba(18, 61, 42, .035), 0 18px 38px -32px rgba(14, 44, 32, .38);
  --nzr-shell-column: 1200px;
  --nzr-shell-radius: 16px;
  --nzr-shell-radius-control: 12px;
  --nzr-shell-ease: cubic-bezier(.4, 0, .15, 1);
  margin: 0;
  font-family: Inter, -apple-system, system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink);
  /* the landlord's ground: pale green at the top, easing to off-white */
  background: linear-gradient(180deg, #F3F6F1 0, #F8F8F6 340px);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}
.nzr-app *, .nzr-app *::before, .nzr-app *::after { box-sizing: border-box; }
/* hidden= must win over every component's own display: a retry button that is
   .nzr-btn{display:inline-flex} otherwise stays on screen while hidden. Found
   2026-09-27 on the Maia conversion, from a screenshot, not a test. */
.nzr-app [hidden] { display: none !important; }
/* Resets use :where() so they never outrank a component class: the first
   draft used :is() and its specificity beat .nzr-btn, so every button
   inherited Inter 16px 400 while the parity test watched. */
.nzr-app :where(h1, h2, h3, h4) {
  margin: 0;
  font-family: Montserrat, Inter, sans-serif;
  font-weight: 800;
  line-height: 1.25;
}
.nzr-app :where(button, input, select, textarea) { font: inherit; }
.nzr-app :is(a, button, input, select, textarea, [role="button"]):focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
}
.nzr-app svg { stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- header ---------- */
.nzr-header, .nzr-app .top {
  position: sticky;
  top: 0;
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  /* 8px + the 44px emblem and header buttons + 8px + the 1px hairline: 61px
     on a phone; 12px each side on a desk makes 69px, where the section nav
     sticks */
  padding: 8px 10px;
  border-bottom: 1px solid rgba(255, 255, 255, .1);
  background: var(--nzr-shell-header);
  color: #fff;
}
/* line-height 1.25 here is for the anonymous line box a sibling mode span sits
   in on a desk: it would otherwise inherit the body's 25.6px and push the
   header from 72px to 74px, under which the pill row then slid. The title and
   the mode line carry their own line-heights and are untouched. */
.nzr-header__brand { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; line-height: 1.25; }
/* The emblem leads every portal header, as it leads the landlord app's
   (William, 2026-09-28: "the tenant portal was meant to match the landlord
   portal"): a 44px tap target back to the public site, the white emblem
   22px tall on a phone and 26px from 701px. */
.nzr-header__logo { flex: none; display: grid; place-items: center; min-width: 44px; min-height: 44px; }
.nzr-header__logo img { display: block; height: 22px; width: auto; }
@media (min-width: 701px) { .nzr-header__logo img { height: 26px; } }
.nzr-header__title, .nzr-app .top h1 {
  margin: 0;
  min-width: 0;
  overflow: hidden;
  font: 600 10.5px/1.55 Montserrat, Inter, sans-serif;
  letter-spacing: .02em;
  color: rgba(255, 255, 255, .92);
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* On a phone the landlord header is the emblem and the name; the mode joins
   the name on a desk, dimmed, as "· Landlord Portal" does. */
.nzr-header__mode, .nzr-app #brandMode {
  display: none;
  font: 500 10.5px/1.55 Montserrat, Inter, sans-serif;
  letter-spacing: 0;
  color: rgba(255, 255, 255, .5);
}
.nzr-header__actions { display: flex; flex: none; align-items: center; gap: 4px; }

/* ---------- buttons ---------- */
.nzr-btn, .nzr-app .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 11px 20px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--forest);
  color: #fff;
  font: 800 13.5px/1.25 Inter, -apple-system, system-ui, sans-serif;
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 250ms var(--nzr-shell-ease), transform 120ms var(--nzr-shell-ease);
}
.nzr-btn:hover, .nzr-app .btn:hover { background: var(--green); }
.nzr-btn:active, .nzr-app .btn:active { transform: scale(.975); }
.nzr-btn:disabled, .nzr-app .btn:disabled { opacity: .55; cursor: wait; transform: none; }
.nzr-btn--ghost, .nzr-btn--sm, .nzr-app .btn.ghost, .nzr-app .btn.sm {
  padding: 7px 14px;
  border: 1.5px solid var(--line);
  background: #fff;
  color: var(--forest);
  font-size: 12.5px;
  line-height: 20px;
}
.nzr-btn--ghost:hover, .nzr-btn--sm:hover, .nzr-app .btn.ghost:hover, .nzr-app .btn.sm:hover { background: var(--mint); }
/* A ghost button used as a tab or filter shows which one is selected, as a
   section pill does. The maintenance tabs and quote filters set .active and
   nothing drew it, so the open tab looked like the others (2026-09-27). */
.nzr-btn--ghost.active, .nzr-btn--ghost[aria-pressed="true"] { border-color: var(--forest); background: var(--forest); color: #fff; }
.nzr-btn--header, .nzr-app .owner-session-actions .btn {
  min-width: auto;
  padding: 7px 9px;
  border-radius: 10px;
  border-color: rgba(255, 255, 255, .24);
  background: rgba(255, 255, 255, .08);
  color: #fff;
  font: 700 10px/1.55 Inter, sans-serif;
}
.nzr-btn--header:hover { background: rgba(255, 255, 255, .14); }
.nzr-btn--danger, .nzr-btn--danger:hover { background: var(--nzr-status-error-text); }

/* ---------- panels, disclosures, KPI tiles ---------- */
.nzr-panel, .nzr-app .panel {
  margin-bottom: 26px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--nzr-shell-radius);
  background: #fff;
  box-shadow: var(--nzr-shell-shadow);
}
.nzr-panel__title, .nzr-panel > h2, .nzr-panel > h3, .nzr-app .panel > h2, .nzr-app .panel > h3 {
  margin: 0 0 14px;
  font-size: 15px;
  font-weight: 800;
  line-height: 1.25;
}
.nzr-panel > p, .nzr-app .panel > p { margin: 0 0 12px; }
.nzr-disclosure {
  margin-bottom: 24px;
  border: 1px solid var(--line);
  border-radius: var(--nzr-shell-radius);
  background: #fff;
  box-shadow: var(--nzr-shell-shadow);
  overflow: hidden;
}
.nzr-disclosure > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 66px;
  padding: 15px 16px;
  background: transparent;
  cursor: pointer;
  list-style: none;
}
.nzr-disclosure > summary::-webkit-details-marker { display: none; }
.nzr-disclosure > :not(summary) { padding: 0 16px 16px; }
.nzr-kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 24px; }
.nzr-kpi, .nzr-app .kpi {
  min-width: 0;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--nzr-shell-radius-control);
  background: #fff;
}
.nzr-kpi__n, .nzr-app .kpi .n { font: 800 24px/1.1 Montserrat, sans-serif; color: var(--forest); overflow-wrap: anywhere; }
.nzr-kpi__l { margin-top: 4px; font-size: 12px; color: var(--mute); }

/* ---------- forms ---------- */
.nzr-input, .nzr-select, .nzr-textarea,
.nzr-app :where(input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="hidden"]), select, textarea) {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--nzr-shell-radius-control);
  background: #fff;
  color: var(--forest);
  font-size: 16px;
  line-height: 1.6;
}
.nzr-select, .nzr-app :where(select) {
  min-height: 48px;
  padding-right: 40px;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23123d2a' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  background-size: 18px;
}
.nzr-textarea, .nzr-app :where(textarea) { min-height: 88px; resize: vertical; }
.nzr-label { display: block; margin-bottom: 6px; font: 600 13px/1.4 Inter, system-ui, sans-serif; color: var(--ink); }
.nzr-field { margin-bottom: 16px; }
.nzr-help { margin-top: 6px; font-size: 12px; color: var(--mute); }
.nzr-error { margin-top: 6px; font-size: 13px; color: var(--nzr-status-error-text); }

/* ---------- section navigation ---------- */
.nzr-section-nav, .nzr-app .owner-section-nav {
  position: sticky;
  top: 69px; /* the header's height on a desk; measured 2026-09-27: at 50px the tenant's pills slid 22px under its header */
  z-index: 110;
  display: flex;
  gap: 6px;
  padding: 8px 16px;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--line);
  background: rgba(243, 246, 241, .92);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.nzr-section-nav::-webkit-scrollbar { display: none; }
.nzr-section-nav button, .nzr-section-nav a, .nzr-app .owner-section-nav button {
  display: flex;
  align-items: center;
  flex: none;
  min-height: 44px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 99px;
  background: #fff;
  color: var(--mute);
  font: 600 11.5px/1.4 Inter, sans-serif;
  text-decoration: none;
  cursor: pointer;
}
.nzr-section-nav .is-active, .nzr-section-nav [aria-current] { border-color: var(--forest); background: var(--forest); color: #fff; }
/* A workspace's sections sit in its column under the heading, not stuck
   under the header: the app's own row holds that edge on a desk. */
.nzr-section-nav--workspace { position: static; flex-wrap: wrap; overflow: visible; margin: 0 0 20px; padding: 0 0 4px; background: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
/* It wraps rather than scrolls: five pills are 460px at 390, and a row that
   cuts "Contractors" mid-word with Messages past the edge gives no sign it
   scrolls. Every section in sight, on two lines if need be. */

/* ---------- main column and banner ---------- */
.nzr-main, .nzr-app #appMain.wrap {
  max-width: var(--nzr-shell-column);
  margin: 0 auto;
  padding: 26px 12px 60px;
}
/* The landlord's strip, not a hero: one bold line on sage under the header,
   "Built on transparency." then its sentence in the same line. */
.nzr-banner, .nzr-app .ro-banner {
  padding: 9px 24px;
  background: var(--sage);
  color: var(--forest);
  font: 800 12.5px/1.45 Inter, -apple-system, system-ui, sans-serif;
  letter-spacing: 0;
}
/* A heading in the strip is the strip's bold lead, not a hero headline. */
.nzr-banner :is(h1, h2) { display: inline; font: inherit; letter-spacing: inherit; color: inherit; }
.nzr-banner__sub, .nzr-app .ro-banner span {
  display: inline;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--forest);
  opacity: .82;
}
.nzr-muted, .nzr-app .mute { font-size: 11.5px; color: var(--mute); }

/* ---------- chips, flags, status ---------- */
.nzr-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding: 4px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  color: var(--ink);
  font: 600 12px/1.2 Inter, system-ui, sans-serif;
}
.nzr-chip--success { border-color: var(--nzr-status-success-border); background: var(--nzr-status-success-surface); color: var(--nzr-status-success-text); }
.nzr-chip--warning { border-color: var(--nzr-status-warning-border); background: var(--nzr-status-warning-surface); color: var(--nzr-status-warning-text); }
.nzr-chip--info { border-color: var(--nzr-status-information-border); background: var(--nzr-status-information-surface); color: var(--nzr-status-information-text); }
.nzr-chip--error { border-color: var(--nzr-status-error-border); background: var(--nzr-status-error-surface); color: var(--nzr-status-error-text); }
.nzr-flag, .nzr-app .flag {
  position: absolute;
  top: -10px;
  left: 16px;
  padding: 3px 11px;
  border-radius: 99px;
  background: var(--accent);
  color: var(--forest);
  font: 800 10px/1.6 Montserrat, sans-serif;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* ---------- the four states every list owes ---------- */
.nzr-state { padding: 20px; border: 1px dashed var(--line); border-radius: var(--nzr-shell-radius); background: #fff; color: var(--mute); font-size: 14px; line-height: 1.6; }
.nzr-state--failed { border-style: solid; border-color: var(--nzr-status-error-border); background: var(--nzr-status-error-surface); color: var(--nzr-status-error-text); }
.nzr-state--failed .nzr-btn { margin-top: 12px; }
.nzr-state--partial { border-color: var(--nzr-status-warning-border); background: var(--nzr-status-warning-surface); color: var(--nzr-status-warning-text); }

/* ---------- toast ---------- */
.nzr-toasts { position: fixed; left: 16px; right: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); z-index: 950; display: grid; gap: 8px; pointer-events: none; }
.nzr-toast, .nzr-app .nzt {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: #fff;
  color: var(--ink);
  font-size: 14px;
  line-height: 1.45;
  box-shadow: 0 18px 52px -22px rgba(8, 31, 21, .5);
  pointer-events: auto;
  animation: nzrToastIn 200ms ease-out;
}
.nzr-toast__reason { flex: 1; min-width: 0; }
.nzr-toast .nzr-btn { flex: none; min-width: 44px; }
@keyframes nzrToastIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------- sheet ---------- */
.nzr-sheet__backdrop {
  position: fixed;
  inset: 0;
  z-index: 940;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 20px;
  background: rgba(14, 44, 32, .45);
}
.nzr-sheet, .nzr-app .nzm {
  width: 100%;
  max-width: 430px;
  max-height: calc(100dvh - 40px);
  padding: 22px;
  border-radius: 16px;
  background: #fff;
  color: var(--ink);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  box-shadow: 0 30px 80px -30px rgba(8, 31, 21, .55);
}
.nzr-sheet__title { margin-bottom: 12px; font-size: 19px; }
.nzr-sheet__actions { display: flex; gap: 8px; margin-top: 20px; }
.nzr-sheet__actions .nzr-btn { flex: 1; }

/* ---------- the phone dock ---------- */
.nzr-dock, .nzr-app .owner-mobile-nav { display: none; }
@media (max-width: 700px) {
  .nzr-app { padding-bottom: calc(82px + env(safe-area-inset-bottom, 0px)); }
  .nzr-dock, .nzr-app .owner-mobile-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 890;
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    align-items: stretch;
    padding: 6px max(6px, env(safe-area-inset-right, 0px)) calc(6px + env(safe-area-inset-bottom, 0px)) max(6px, env(safe-area-inset-left, 0px));
    border-top: 1px solid var(--line);
    background: rgba(255, 255, 255, .96);
    box-shadow: 0 -14px 34px -24px rgba(14, 44, 32, .52);
    backdrop-filter: blur(18px) saturate(150%);
    -webkit-backdrop-filter: blur(18px) saturate(150%);
  }
  .nzr-dock__tab, .nzr-app .owner-mobile-nav button {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    min-width: 0;
    min-height: 56px;
    padding: 5px 2px;
    border: 0;
    border-radius: 12px;
    background: transparent;
    color: var(--mute);
    font: 750 9.5px/1 Inter, sans-serif;
    letter-spacing: .01em;
    text-decoration: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .nzr-dock__tab svg { width: 24px; height: 24px; }
  .nzr-dock__tab.is-active, .nzr-dock__tab[aria-current], .nzr-app .owner-mobile-nav button.active { color: var(--forest); }
  .nzr-dock__tab.is-active .nzr-dock__icon, .nzr-dock__tab[aria-current] .nzr-dock__icon { background: var(--mint); border-radius: 10px; }
  .nzr-dock__icon { display: grid; place-items: center; width: 40px; height: 28px; }
  .nzr-header { backdrop-filter: none; -webkit-backdrop-filter: none; }
  /* The dock replaces the section pills on a phone: the landlord app hides
     its .owner-section-nav at 700px and shows the dock instead. */
  .nzr-section-nav, .nzr-app .owner-section-nav { display: none; }
  /* A workspace's own sections (Maintenance, Leasing) are not the dock's
     destinations, so they stay on a phone. */
  .nzr-section-nav--workspace { display: flex; }
  /* Toasts sit above the dock, as the landlord app lifts its .nzt-stack at
     700px and below: at 16px a failure toast and its Try again landed on the
     dock's tabs (found 2026-09-27 on the contractor conversion). */
  .nzr-toasts { bottom: calc(74px + env(safe-area-inset-bottom, 0px)); }
}

/* ---------- the desk ---------- */
@media (min-width: 701px) {
  .nzr-header, .nzr-app .top {
    gap: 14px;
    padding: 12px 24px;
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
  }
  .nzr-header__brand { gap: 14px; }
  .nzr-header__title, .nzr-app .top h1 { font-size: 13px; letter-spacing: .04em; }
  .nzr-header__mode, .nzr-app #brandMode { display: inline; font-size: 13px; }
  /* inline after the title, as the landlord's brandMode sits inside its h1;
     a title that stays block makes a taller header under the sticky nav */
  .nzr-header__title + .nzr-header__mode { margin-left: 6px; }
  .nzr-btn--header, .nzr-app .owner-session-actions .btn { padding: 8px 13px; font-size: 11.5px; }
  .nzr-panel, .nzr-app .panel { padding: 20px; border-radius: 18px; }
  .nzr-disclosure { border-radius: 18px; }
  .nzr-disclosure > summary { min-height: 70px; padding: 17px 19px; }
  .nzr-disclosure > :not(summary) { padding: 0 20px 20px; }
  .nzr-kpi, .nzr-app .kpi { padding: 20px; }
  .nzr-kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .nzr-main, .nzr-app #appMain.wrap { padding: 26px 28px 60px; }
  .nzr-banner, .nzr-app .ro-banner { line-height: 1.55; }
  .nzr-banner__sub, .nzr-app .ro-banner span { margin-left: 3px; }
  .nzr-sheet__backdrop { align-items: center; }
  .nzr-toasts { left: auto; right: 24px; bottom: 24px; width: 360px; }
}

/* ---------- print and reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .nzr-app *, .nzr-app *::before, .nzr-app *::after { transition-duration: 1ms !important; animation-duration: 1ms !important; }
}
@media print {
  .nzr-header, .nzr-dock, .nzr-section-nav, .nzr-toasts, .nzr-sheet__backdrop { display: none !important; }
  .nzr-app { background: #fff; color: #000; padding-bottom: 0; }
  .nzr-panel, .nzr-app .panel { box-shadow: none; border-color: #000; }
  .nzr-banner { background: #fff; color: var(--forest); padding: 20px; }
}
