/* ═══════════════════════════════════════════════════════════════════════════
   VALIDURE ERP — layout: app shell, page anatomy, print sheets, phone frame
   owner: UX Architect · spec: docs/design/02-ia.md · consumes tokens.css only
   ───────────────────────────────────────────────────────────────────────────
   Responsive model (NFR-ACC-001; tested at 1920 · 1366 · 1024 · 390)
     ≥ 1281px   sidebar expanded (var(--sidebar-w)); html[data-sidebar="collapsed"] → icon rail
     1024–1280  icon rail (var(--sidebar-w-collapsed)); html[data-sidebar="expanded"] → expanded
     < 1024     sidebar is an off-canvas drawer: the .sidebar element carries the
                `popover` attribute and the topbar button uses popovertarget —
                opens/closes (Esc, click-outside) with NO JavaScript.
   Topbar compaction follows the width of .app__body (container "shell"):
     < 1300 profile name hidden · < 1000 New label hidden · < 900 switcher
     eyebrows hidden · < 760 branch + FY fold into the company menu, theme menu
     hidden · < 480 company name clipped.
   Rail styling is driven by a size container query on .sidebar, so the rail
   looks right whether it came from the media query or from data-sidebar.
   Page primitives respond to container "main" (the space the sidebar leaves).

   Contract for assets/js/app.js (UI Designer — implemented)
     [data-action="toggle-sidebar"]  (visible ≥1024 only) — flip the EFFECTIVE
       state: if the sidebar is currently a rail (data-sidebar="collapsed", or
       1024–1280 with no data-sidebar="expanded") set data-sidebar="expanded",
       else set data-sidebar="collapsed". Persist (erp_sidebar), and keep
       aria-expanded on the button in sync.
     [data-action="print"]  — window.print() (print layout toolbar).
     Details menus: close an open <details class="menu"> on outside click / Esc.

   Layout constants that are not design tokens live here as --lx-* and are
   used only in this file.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  --lx-narrow: 52rem;   /* .page--narrow — settings & single forms           */
  --lx-aside: 21rem;    /* .split aside — totals, timelines, help            */
  --lx-flyout: 16rem;   /* rail flyout panel                                 */
  --lx-drawer: 20rem;   /* off-canvas drawer (< 1024)                         */
  --lx-phone: 390px;    /* mobile CRM column (NFR-ACC-001 390×844)            */
  --lx-auth: 27rem;     /* auth panel                                         */
  --lx-page-pad: var(--sp-8);
}

/* ── 1. App shell ──────────────────────────────────────────────────────── */

.app {
  --lx-side: var(--sidebar-w);
  display: grid;
  grid-template-columns: var(--lx-side) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
}

@media (min-width: 1024px) and (max-width: 1280px) {
  html:not([data-sidebar="expanded"]) .app {
    --lx-side: var(--sidebar-w-collapsed);
  }
}

@media (min-width: 1281px) {
  html[data-sidebar="collapsed"] .app {
    --lx-side: var(--sidebar-w-collapsed);
  }
}

@media (max-width: 1023.98px) {
  .app {
    grid-template-columns: minmax(0, 1fr);
  }
}

.app__body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 100dvh;
  container: shell / inline-size; /* the topbar compacts by the space it really has */
}

.main {
  flex: 1 0 auto;
  min-width: 0;
  container: main / inline-size;
}

.main:focus {
  outline: none;
}

/* ── 2. Sidebar ────────────────────────────────────────────────────────── */

.sidebar {
  container: sidebar / inline-size;
  flex-direction: column;
  background: var(--e-sidebar);
  color: var(--e-sidebar-fg);
  z-index: var(--z-sidebar);
}

/* ≥1024: an ordinary sticky column. Overrides the UA [popover] styles. */
@media (min-width: 1024px) {
  .sidebar {
    display: flex;
    position: sticky;
    inset: 0 auto auto 0;
    top: 0;
    width: auto;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    border-inline-end: 1px solid var(--e-sidebar-border);
    overflow: visible;
  }

  .sidebar__close {
    display: none !important;
  }
}

/* < 1024: off-canvas drawer via the Popover API. */
@media (max-width: 1023.98px) {
  .sidebar:not(:popover-open) {
    display: none;
  }

  /* html[data-sidebar="open"] is app.js's scripted equivalent — same drawer */
  .sidebar:popover-open,
  html[data-sidebar="open"] .sidebar {
    display: flex;
    position: fixed;
    inset: 0 auto 0 0;
    width: min(var(--lx-drawer), 86vw);
    height: 100dvh;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    border-inline-end: 1px solid var(--e-sidebar-border);
    box-shadow: var(--shadow-pop);
    overflow: visible;
    z-index: var(--z-drawer);
  }

  .sidebar::backdrop {
    background: var(--e-overlay);
  }
}

@media (prefers-reduced-motion: no-preference) and (max-width: 1023.98px) {
  .sidebar:popover-open {
    animation: lx-drawer-in var(--dur-med) var(--ease-out);
  }
}

@keyframes lx-drawer-in {
  from {
    translate: -24px 0;
    opacity: 0;
  }
}

.sidebar__brand {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  min-height: var(--topbar-h);
  /* 20 px: the tile's left edge lines up with the nav icons (03-brand §3.2);
     the rail's container query below centres it instead */
  padding: var(--sp-2) var(--sp-3) var(--sp-2) var(--sp-5);
  border-bottom: 1px solid var(--e-sidebar-border);
}

.sidebar__close {
  color: var(--e-sidebar-fg);
}

.sidebar__context {
  display: none;
  flex-direction: column;
  gap: 2px;
  padding: var(--sp-2) var(--sp-4) 0;
  color: var(--e-sidebar-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.sidebar--admin .sidebar__context {
  display: flex;
}

.sidebar__foot {
  flex: none;
  padding: var(--sp-2);
  border-top: 1px solid var(--e-sidebar-border);
}

/* status and dates in the foot (plan validity, days left) are never ellipsized */
.sidebar__foot .nav__text,
.sidebar__foot .nav__text small {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}

/* nav ------------------------------------------------------------------- */

.nav {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--sp-3) var(--sp-2) var(--sp-6);
  scrollbar-color: var(--e-sidebar-border) transparent;
}

.nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav__group + .nav__group {
  margin-top: var(--sp-1);
}

.nav__label {
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 34px;
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--r-md);
  color: var(--e-sidebar-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  cursor: pointer;
  user-select: none;
}

.nav__label::-webkit-details-marker,
.nav__label::marker {
  display: none;
  content: "";
}

.nav__label:hover {
  color: var(--e-sidebar-fg);
  background: color-mix(in srgb, var(--e-sidebar-fg) 7%, transparent);
}

.nav__label > .icon:first-child {
  display: none; /* group icons show only in the rail */
}

.nav__label > .nav__text {
  white-space: normal;
  line-height: 1.25;
}

.nav__chevron {
  flex: none;
  width: 14px;
  height: 14px;
  margin-inline-start: auto;
  rotate: -90deg;
  transition: rotate var(--dur-fast) var(--ease-out);
}

.nav__group[open] > .nav__label .nav__chevron {
  rotate: 0deg;
}

.nav__list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 2px 0 var(--sp-2);
}

.nav__group > .nav__list::before {
  content: none;
}

.nav__sublabel {
  display: block;
  padding: var(--sp-2) var(--sp-3) var(--sp-1) calc(var(--sp-3) + 18px + var(--sp-3));
  color: var(--e-sidebar-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.02em;
}

.nav__sublabel--root {
  padding: var(--sp-4) var(--sp-3) var(--sp-1);
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.nav__item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 36px;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  color: var(--e-sidebar-fg);
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  text-decoration: none;
}

.nav__item > .icon {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--e-sidebar-muted);
}

.nav__item:hover {
  color: var(--e-sidebar-fg);
  background: color-mix(in srgb, var(--e-sidebar-fg) 8%, transparent);
}

.nav__item[aria-current="page"] {
  color: var(--e-sidebar-active-fg);
  background: var(--e-sidebar-active);
}

.nav__item[aria-current="page"] > .icon {
  color: currentColor;
}

.nav__text {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nav__text small {
  display: block;
  color: var(--e-sidebar-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
  overflow: hidden;
  text-overflow: ellipsis;
}

/* the current item's second line (Receipts · Payment In) sits on the active
   fill, where the muted sidebar ink fails AA: it takes the active ink (G06) */
.nav__item[aria-current="page"] .nav__text small {
  color: var(--e-sidebar-active-fg);
}

/* expanded sidebar inside the drawer / expanded state: undo brand collapse
   rules that key off data-sidebar (Brand Guardian's lockup) */
@container sidebar (min-width: 121px) {
  .brand-lockup__word {
    display: inline;
  }

  .brand-lockup__stack {
    display: grid;
  }
}

/* rail (icon-only) ------------------------------------------------------ */

@container sidebar (max-width: 120px) {
  .sidebar__brand {
    justify-content: center;
    padding-inline: 0;
  }

  .brand-lockup__word,
  .brand-lockup__stack {
    display: none;
  }

  .nav {
    padding-inline: 0;
    scrollbar-width: none;
  }

  .nav__group + .nav__group {
    margin-top: 0;
  }

  .nav__label {
    justify-content: center;
    min-height: 44px;
    padding: 0;
    border-radius: 0;
    color: var(--e-sidebar-fg);
  }

  .nav__label > .icon:first-child {
    display: block;
    width: 20px;
    height: 20px;
  }

  .nav__label > .nav__text,
  .nav__list--root > li > .nav__item > .nav__text,
  .sidebar__foot .nav__item > .nav__text {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .nav__label > .nav__chevron {
    display: none;
  }

  /* the group that holds the current page is marked in the rail */
  .nav__group:has([aria-current="page"]) > .nav__label {
    color: var(--e-sidebar-active-fg);
    background: var(--e-sidebar-active);
  }

  .nav__group:is(:hover, :focus-within) > .nav__label {
    color: var(--e-sidebar-fg);
    background: color-mix(in srgb, var(--e-sidebar-fg) 10%, transparent);
  }

  /* flyout: the group's list becomes a full-height panel beside the rail.
     Its containing block is .sidebar (outside the .nav scroller), so the
     scroller never clips it. */
  .nav__group > .nav__list {
    position: absolute;
    inset-block: 0;
    inset-inline-start: calc(100% - var(--sp-1));
    width: var(--lx-flyout);
    padding: var(--sp-4) var(--sp-2);
    overflow-y: auto;
    background: var(--e-sidebar);
    border-inline: 1px solid var(--e-sidebar-border);
    box-shadow: var(--shadow-pop);
    z-index: var(--z-drawer);
  }

  .nav__group > .nav__list::before {
    content: attr(data-label);
    display: block;
    padding: 0 var(--sp-3) var(--sp-3);
    color: var(--e-sidebar-muted);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semibold);
    letter-spacing: 0.07em;
    text-transform: uppercase;
  }

  /* show a flyout only while its group is hovered or holds focus —
     whether or not the <details> is open (::details-content, Chrome 131+) */
  .nav__group::details-content {
    content-visibility: visible;
  }

  .nav__group:not(:hover):not(:focus-within)::details-content {
    content-visibility: hidden;
  }

  .nav__list--root > li > .nav__item,
  .sidebar__foot .nav__item {
    justify-content: center;
    min-height: 44px;
    padding: 0;
    border-radius: 0;
  }

  .nav__list--root > li > .nav__item > .icon,
  .sidebar__foot .nav__item > .icon {
    width: 20px;
    height: 20px;
  }

  .sidebar__context,
  .sidebar--admin .sidebar__context {
    display: none;
  }

  .nav__sublabel--root {
    height: 1px;
    margin: var(--sp-2) var(--sp-3);
    padding: 0;
    overflow: hidden;
    background: var(--e-sidebar-border);
    color: transparent;
  }

  .sidebar__foot {
    padding-inline: 0;
  }
}

/* fallback where ::details-content is unsupported: open groups flyout on
   hover/focus only; closed groups open on click */
@supports not selector(::details-content) {
  @container sidebar (max-width: 120px) {
    .nav__group:not(:hover):not(:focus-within) > .nav__list {
      display: none;
    }
  }
}

/* rail tooltips for ungrouped items (Head Admin nav, sidebar foot) */
@supports (anchor-name: --a) {
  @container sidebar (max-width: 120px) {
    .nav__list--root > li > .nav__item,
    .sidebar__foot .nav__item {
      anchor-name: --lx-rail-item;
      anchor-scope: --lx-rail-item;
    }

    .nav__list--root > li > .nav__item:is(:hover, :focus-visible) > .nav__text,
    .sidebar__foot .nav__item:is(:hover, :focus-visible) > .nav__text {
      /* fixed, not absolute: the 64px rail is too narrow a containing block,
         so "right of the anchor" would be shifted back over the icon */
      position: fixed;
      position-anchor: --lx-rail-item;
      position-area: right;
      width: auto;
      height: auto;
      margin-inline-start: var(--sp-2);
      padding: var(--sp-1) var(--sp-3);
      overflow: visible;
      clip-path: none;
      border-radius: var(--r-md);
      background: var(--e-fg);
      color: var(--e-bg);
      font-size: var(--fs-sm);
      font-weight: var(--fw-semibold);
      box-shadow: var(--shadow-pop);
      z-index: var(--z-drawer);
      pointer-events: none;
    }

    .nav__list--root > li > .nav__item:is(:hover, :focus-visible) > .nav__text small,
    .sidebar__foot .nav__item:is(:hover, :focus-visible) > .nav__text small {
      color: var(--e-bg);
      opacity: 0.8;
    }
  }
}

/* ── 3. Topbar ─────────────────────────────────────────────────────────── */

.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--topbar-h);
  padding: var(--sp-2) var(--sp-4) var(--sp-2) var(--sp-3);
  background: var(--e-raised);
  border-bottom: 1px solid var(--e-border);
}

.topbar__start,
.topbar__end {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  min-width: 0;
}

.topbar__start {
  flex: 1 1 auto;
}

.topbar__end {
  flex: none;
  gap: var(--sp-2);
}

.topbar__collapse {
  display: none !important;
}

@media (min-width: 1024px) {
  .topbar__drawer {
    display: none !important;
  }

  .topbar__collapse {
    display: inline-flex !important;
  }
}

.topbar__sep {
  flex: none;
  width: 1px;
  height: var(--sp-6);
  margin-inline: var(--sp-1);
  background: var(--e-border);
}

/* context switchers: company · branch · financial year (SRS §3.1.4) */
.topbar__context {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  min-width: 0;
}

.topbar__switch {
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  max-width: 17rem;
  min-height: 40px;
  padding: var(--sp-1) var(--sp-2);
  border-radius: var(--r-md);
  color: var(--e-fg);
  cursor: pointer;
}

.topbar__switch::-webkit-details-marker,
.topbar__switch::marker {
  display: none;
  content: "";
}

.topbar__switch:hover {
  background: var(--e-subtle);
}

.menu[open] > .topbar__switch {
  background: var(--e-surface);
}

.topbar__switch > .icon {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--e-faint);
}

.topbar__switch-text {
  display: grid;
  min-width: 0;
  line-height: 1.2;
  text-align: start;
}

.topbar__switch-label {
  color: var(--e-muted);
  font-size: var(--fs-xs);
}

.topbar__switch-value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: var(--fw-semibold);
}

.topbar__company .topbar__switch-value {
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  letter-spacing: -0.005em;
}

.topbar__company {
  flex: 0 1 auto;
  min-width: 0;
}

.topbar__company .topbar__switch {
  max-width: 19rem;
}

.topbar__branch,
.topbar__fy {
  flex: none;
}

.topbar__fy .topbar__switch {
  max-width: 9rem;
}

/* the unread count is a count, not a money status: ink on a neutral well with
   a control-strength ring — never red (red = Unpaid / Overdue, 03-brand §6.3),
   never the theme colour (green in Dark Professional / Emerald = Paid) */
.topbar__count {
  position: absolute;
  inset-block-start: 1px;
  inset-inline-end: 0;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-full);
  background: var(--e-surface);
  box-shadow: inset 0 0 0 1px var(--e-border-strong);
  color: var(--e-fg);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  line-height: 18px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.topbar__notify > summary {
  position: relative;
}

.topbar__user {
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 40px;
  padding: var(--sp-1);
  border-radius: var(--r-full);
  cursor: pointer;
}

.topbar__user::-webkit-details-marker,
.topbar__user::marker {
  display: none;
  content: "";
}

.topbar__user:hover {
  background: var(--e-subtle);
}

.topbar__user-text {
  display: grid;
  line-height: 1.2;
  padding-inline-end: var(--sp-2);
  text-align: start;
}

.topbar__user-text > span {
  display: grid;
}

.topbar__user-name {
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}

.topbar__user-role {
  color: var(--e-muted);
  font-size: var(--fs-xs);
  white-space: nowrap;
}

/* menus that open from the right half of the bar align to their right edge */
.topbar__end .menu > .menu__list {
  inset-inline-start: auto;
  inset-inline-end: 0;
}

/* menu rows used by the chrome: two-line text, trailing tick, notes */
.topbar .menu__list {
  min-width: 15rem;
  max-width: min(21rem, calc(100vw - 2 * var(--sp-4)));
}

.topbar__item-text {
  display: grid;
  flex: 1 1 auto;
  min-width: 0;
  line-height: var(--lh-snug);
  white-space: normal;
}

.topbar__item-text small {
  color: var(--e-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
}

.topbar__item-note {
  margin-inline-start: auto;
  padding-inline-start: var(--sp-3);
  color: var(--e-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
}

.topbar__tick {
  flex: none;
  margin-inline-start: auto;
  color: var(--e-primary);
}

.topbar .menu__item > .code {
  flex: none;
}

.topbar__notify-list .menu__item {
  align-items: flex-start;
  white-space: normal;
}

.topbar__theme-list .menu__item[aria-pressed="true"] {
  color: var(--e-primary-dark);
  font-weight: var(--fw-semibold);
}

.topbar__theme-list .menu__item[aria-pressed="true"]::after {
  content: "✓" / "";
  margin-inline-start: auto;
  padding-inline-start: var(--sp-2);
}

.topbar__theme-list .menu__item[aria-pressed="true"]:has(.topbar__item-note)::after {
  margin-inline-start: 0;
}

.topbar__modes {
  display: flex;
  flex-wrap: nowrap;
  margin: var(--sp-1) var(--sp-2) var(--sp-2);
}

.topbar__modes > button {
  flex: 1 1 0;
  justify-content: center;
  gap: var(--sp-1);
  padding-inline: var(--sp-2);
}

.topbar__modes .icon {
  width: 14px;
  height: 14px;
}

.topbar__readonly {
  border-color: var(--e-info);
  background: var(--e-info-soft);
  color: var(--e-info-fg);
}

/* Branch scope (02-ia §3.1): the topbar Branch switcher is the working
   context. A page that shows every branch declares data-branch-scope="all" on
   its .page; the switcher then shows "All branches" as current. Everything
   else shows the home branch. ctx/branch.html and ctx/branch-options.html
   carry both variants as [data-branch-when="home" | "all"]; exactly one
   is displayed, so assistive technology reads one current value.           */
body:not(:has([data-branch-scope="all"])) [data-branch-when="all"],
body:has([data-branch-scope="all"]) [data-branch-when="home"] {
  display: none !important;
}

/* compact-only menu sections (branch + FY folded into the company menu) */
.menu__section--compact {
  display: none;
}

@container shell (max-width: 1299.98px) {
  .topbar__user-text {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

@container shell (max-width: 999.98px) {
  .topbar__new-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

@container shell (max-width: 899.98px) {
  .topbar__switch-label {
    display: none;
  }

  .topbar__switch {
    min-height: 36px;
  }
}

@container shell (max-width: 759.98px) {
  .topbar {
    gap: var(--sp-1);
    padding-inline: var(--sp-2);
  }

  .topbar__branch,
  .topbar__fy,
  .topbar__theme,
  .topbar__context .topbar__sep {
    display: none !important;
  }

  .menu__section--compact {
    display: block;
  }

  .topbar__end {
    gap: var(--sp-1);
  }
}

@container shell (max-width: 479.98px) {
  .topbar__company .topbar__switch {
    max-width: 8.5rem;
    padding-inline: var(--sp-1);
  }

  .topbar__company .topbar__switch-label {
    display: none;
  }

  .topbar__company .topbar__switch > .icon {
    display: none;
  }

  /* the tenant name is the identity that leads (03-brand §0): the demo chip
     gives up its side padding so "Meghmala Fresh" is never cut on a phone */
  .topbar .chip--demo {
    padding-inline: 6px;
  }
}

/* 360 px phones (SRS size): the chip keeps its dashed outline and flask — the
   "not real" signal — and gives up its word, so the tenant name fits whole.
   Its accessible name stays "Demo tenant" (aria-label). */
@container shell (max-width: 399.98px) {
  .topbar .chip--demo {
    gap: 0;
    padding-inline: 7px;
  }

  .topbar .chip--demo > span[aria-hidden] {
    display: none;
  }
}

/* Head Admin topbar: the platform console sits on logo navy, so nobody
   mistakes it for a tenant company. Token remaps are scoped to the bar's
   own controls — dropdown panels keep the normal raised surface. */
.topbar--admin {
  background: var(--e-sidebar);
  border-bottom-color: var(--e-sidebar-border);
  color: var(--e-sidebar-fg);
}

.topbar--admin > .topbar__start > .btn,
.topbar--admin > .topbar__end > .btn,
.topbar--admin .menu > summary,
.topbar--admin .topbar__title,
.topbar--admin .chip--demo {
  --e-fg: var(--e-sidebar-fg);
  --e-muted: var(--e-sidebar-muted);
  --e-faint: var(--e-sidebar-muted);
  --e-border-strong: var(--e-sidebar-muted);
  --e-subtle: color-mix(in srgb, var(--e-sidebar-fg) 10%, transparent);
  --e-surface: color-mix(in srgb, var(--e-sidebar-fg) 14%, transparent);
  --e-focus: var(--e-sidebar-fg);
  color: var(--e-sidebar-fg);
}

.topbar--admin .topbar__tenant-only {
  display: none;
}

.topbar__title {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
  padding-inline: var(--sp-2);
}

.topbar__title-text {
  display: grid;
  min-width: 0;
  line-height: 1.2;
}

.topbar__title-text strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: var(--fw-semibold);
}

.topbar__title-text span {
  color: var(--e-muted);
  font-size: var(--fs-xs);
}

.topbar__badge {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: 26px;
  padding: 0 var(--sp-2);
  border: 1px solid var(--e-sidebar-muted);
  border-radius: var(--r-sm);
  color: var(--e-sidebar-fg);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
}

.topbar__badge .icon {
  width: 14px;
  height: 14px;
}

@container shell (max-width: 759.98px) {
  .topbar__title-text span {
    display: none;
  }
}

@container shell (max-width: 479.98px) {
  .topbar__badge {
    display: none;
  }
}

/* ── 4. Page anatomy ───────────────────────────────────────────────────── */

.page {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  width: 100%;
  max-width: calc(var(--content-max) + 2 * var(--lx-page-pad));
  margin-inline: auto;
  padding: var(--sp-6) var(--lx-page-pad) var(--sp-12);
}

/* Head Admin footer: the platform-owner credit (brand/owner-line, 03-brand §1.2 / §2), aligned with the page
   column and pulled into the page's bottom padding. Tenant screens never carry it. */
.app-foot {
  width: 100%;
  max-width: calc(var(--content-max) + 2 * var(--lx-page-pad));
  margin: calc(-1 * var(--sp-6)) auto 0;
  padding: 0 var(--lx-page-pad) var(--sp-6);
}

.page--narrow {
  max-width: calc(var(--lx-narrow) + 2 * var(--lx-page-pad));
}

.page--wide {
  max-width: none;
}

@container main (max-width: 1100px) {
  .page {
    --lx-page-pad: var(--sp-6);
  }
}

@container main (max-width: 720px) {
  .page {
    --lx-page-pad: var(--sp-4);
    gap: var(--sp-5);
    padding-top: var(--sp-4);
    padding-bottom: var(--sp-10);
  }
}

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-6);
}

.page-head__main {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  min-width: 0;
  flex: 1 1 24rem;
}

.page-head__title {
  font-family: var(--font-display);
  font-stretch: var(--display-stretch);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tracking);
  font-size: var(--fs-2xl);
  line-height: var(--lh-tight);
  overflow-wrap: anywhere;
}

.page-head__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-4);
  color: var(--e-muted);
  font-size: var(--fs-sm);
}

.page-head__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}

@container main (max-width: 720px) {
  .page-head__title {
    font-size: var(--fs-xl);
  }

  .page-head__actions {
    flex-basis: 100%;
  }
}

.crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--e-muted);
  font-size: var(--fs-sm);
}

.crumbs li + li::before {
  content: "/" / "";
  margin-inline-end: var(--sp-1);
  color: var(--e-faint);
}

.crumbs a {
  color: var(--e-muted);
  text-decoration: none;
}

.crumbs a:hover {
  color: var(--e-primary);
  text-decoration: underline;
}

.crumbs [aria-current="page"] {
  color: var(--e-fg);
}

/* sticky action bar at the foot of editors (Save / Save & print / Cancel) */
.page-bar {
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  margin: 0 calc(-1 * var(--lx-page-pad)) calc(-1 * var(--sp-12));
  padding: var(--sp-3) var(--lx-page-pad);
  background: var(--e-raised);
  border-top: 1px solid var(--e-border);
}

.page-bar__status {
  margin-inline-end: auto;
  color: var(--e-muted);
  font-size: var(--fs-sm);
}

/* the document's total — the highest-contrast figure in the bar:
   <p class="page-bar__status">Not saved yet · 4 lines</p>
   <p class="page-bar__total"><span>Grand total</span> <strong class="money">₹17,325.00</strong></p> */
.page-bar__total {
  display: inline-flex;
  align-items: baseline;
  gap: var(--sp-2);
  margin-inline-end: var(--sp-2);
  color: var(--e-muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}

.page-bar__total > strong {
  color: var(--e-fg);
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-stretch: 106%;
  font-weight: var(--display-weight);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

/* an optional second figure under the total answers the next question
   ("is the advance used?"): it spans the label and the figure, quieter
   <p class="page-bar__total"><span>Grand total</span> <strong class="money">₹42,214.00</strong>
     <span class="page-bar__sub"><span class="money">₹17,214.00</span> due after advance</span></p> */
.page-bar__total:has(> .page-bar__sub) {
  display: inline-grid;
  grid-template-columns: auto auto;
  column-gap: var(--sp-2);
  align-items: baseline;
  justify-items: end;
}

.page-bar__total:has(> .page-bar__sub) > strong {
  line-height: 1.15;
}

.page-bar__sub {
  grid-column: 1 / -1;
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
  line-height: 1.2;
}

.page-bar__sub > .money {
  color: var(--e-fg);
  font-weight: var(--fw-semibold);
}

/* a button whose long label is shown needs no icon; below 720 px the label
   folds away and the icon carries the button (the text stays its name) */
.page-bar > .btn:has(> .page-bar__label) > .icon {
  display: none;
}

/* An editor's bar is ONE row: status · total · Discard (ghost) · Save draft
   (the one secondary) · the primary as a split button whose menu holds the
   save variants (05-page-patterns §3.2). On phones the bar keeps only the
   total and the split button; Discard and Save draft move into its menu as
   the .page-bar__narrow rows, which are hidden on wider screens. */
.page-bar .page-bar__narrow {
  display: none;
}

/* a split button with no save variants (its menu holds only the narrow
   Discard / Save draft rows) is a plain primary above 720 px: the toggle
   would open an empty menu (G04 bulk billing) */
@container main (min-width: 720.02px) {
  .page-bar .btn-split:not(:has(.menu__item:not(.page-bar__narrow))) > .menu {
    display: none;
  }

  .page-bar .btn-split:not(:has(.menu__item:not(.page-bar__narrow))) > .btn {
    border-radius: var(--r-md);
  }
}

@container main (max-width: 720px) {
  .page-bar:has(.btn-split) > .btn {
    display: none;
  }

  .page-bar .menu__item.page-bar__narrow {
    display: flex;
  }

  .page-bar .menu__sep.page-bar__narrow {
    display: block;
  }
  .page-bar > .btn:has(> .page-bar__label) > .icon {
    display: inline-block;
  }

  .page-bar {
    margin-bottom: calc(-1 * var(--sp-10));
  }

  /* phones: the total leads the bar; the line count is in the grid's footer */
  .page-bar {
    padding-block: var(--sp-2);
  }

  .page-bar__status:has(+ .page-bar__total),
  .page-bar__status:has(+ .page-bar__status--invalid + .page-bar__total) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .page-bar__status {
    flex: 1 1 auto;
  }

  .page-bar__total {
    margin-inline-end: auto;
  }

  /* status + total share the first line; the actions wrap below as a row */
  .page-bar > .btn {
    flex: 1 1 auto;
  }

  /* long labels fold to their icon; the text stays the accessible name */
  .page-bar__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* ── 5. Composition primitives ─────────────────────────────────────────── */

.stack,
.stack-sm,
.stack-lg {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

.stack-sm {
  gap: var(--sp-2);
}

.stack-lg {
  gap: var(--sp-8);
}

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
}

/* a label + control pair inside a toolbar wraps as one unit
   (partials/filters/period-branch.html) */
.toolbar > .cluster {
  flex-wrap: nowrap;
  gap: var(--sp-2);
  min-width: 0;
  max-width: 100%;
}

.toolbar > .cluster > :is(.input, .select) {
  width: auto;
  min-width: 0;
  max-width: 100%;
}

/* …also inside the filters disclosure, so period + branch fold into the one
   Filters button on phones (G06 passbook, G07 capital, G09 reports) */
.toolbar__filters > .cluster {
  flex-wrap: nowrap;
  gap: var(--sp-2);
  min-width: 0;
  max-width: 100%;
}

.toolbar__filters > .cluster > :is(.input, .select) {
  width: auto;
  min-width: 0;
  max-width: 100%;
}

.grid,
.grid-2,
.grid-3,
.grid-4,
.grid-auto {
  display: grid;
  gap: var(--sp-4);
}

.grid-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* cards of unequal height keep their own height (no empty well under a
   short chart or list) */
.grid-start {
  align-items: start;
}

/* a child that takes a whole row of its grid (a wide field or a note in a
   .grid-2 form; batch 4, from G11 settings) */
.grid-full {
  grid-column: 1 / -1;
}

.grid-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.grid-4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.grid-auto {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
}

@container main (max-width: 800px) {
  .grid-4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@container main (max-width: 860px) {
  .grid-3 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ext: a grid row whose cards keep their own height (a chart beside a long
   list, a short summary beside a timeline): no stretched blank card bottoms */
.grid--start {
  align-items: start;
}

@container main (max-width: 600px) {
  .grid-2,
  .grid-3 {
    grid-template-columns: minmax(0, 1fr);
  }

  /* an editor's totals follow its lines on a phone: the column holding the
     document totals comes before notes and terms */
  .grid-2 > :has(> .card .dl--totals) {
    order: -1;
  }
}

@container main (max-width: 320px) {
  .grid-4 {
    grid-template-columns: minmax(0, 1fr);
  }
}

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--lx-aside);
  gap: var(--sp-6);
  align-items: start;
}

.split > * {
  min-width: 0;
}

.split--sticky > :last-child {
  position: sticky;
  top: calc(var(--topbar-h) + var(--sp-4));
}

@container main (max-width: 960px) {
  .split {
    grid-template-columns: minmax(0, 1fr);
  }

  .split--sticky > :last-child {
    position: static;
  }
}

.section {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  min-width: 0;
}

.section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
}

.section__title {
  font-size: var(--fs-lg);
}

.section__meta {
  color: var(--e-muted);
  font-size: var(--fs-sm);
}

/* keyboard legend for document line grids (partials/grid-keys.html) */
/* a legend of keys means nothing on a touch phone: it shows where a keyboard is likely */
@media (max-width: 767.98px), (pointer: coarse) {
  .grid-keys {
    display: none;
  }
}

.grid-keys .card__title {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.grid-keys__list {
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--sp-2) var(--sp-4);
  align-items: baseline;
}

.grid-keys__list > div {
  display: contents;
}

.grid-keys__list dt {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  align-items: center;
  white-space: nowrap;
}

.grid-keys__list dd {
  font-size: var(--fs-sm);
}

.grid-keys__note {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--e-border);
  color: var(--e-muted);
  font-size: var(--fs-sm);
}

@media (max-width: 479.98px) {
  .grid-keys .dl.grid-keys__list {
    grid-template-columns: max-content minmax(0, 1fr);
    gap: var(--sp-2) var(--sp-3);
  }

  .grid-keys .dl.grid-keys__list dd + dt {
    margin-top: 0;
  }
}

/* ── 6. Prototype state & role conventions (02-ia.md §10) ───────────────── */

/* State variants on one page: siblings; the default shows until a variant is
   the URL :target (links like href="#empty"). No JavaScript. */
[data-state]:not([data-state="default"]):not(:target):not(:has(:target)) {
  display: none !important;
}

[data-state]:target ~ [data-state="default"],
[data-state="default"]:has(~ [data-state]:target) {
  display: none !important;
}

/* A state stays open while one of ITS OWN elements is the target: the error
   summary of a failed save links to its fields (#invalid → #x-gstin), and
   following that link must not close the errors and bring back the default. */
[data-state]:not([data-state="default"]):has(:target) ~ [data-state="default"],
[data-state="default"]:has(~ [data-state]:not([data-state="default"]) :target) {
  display: none !important;
}

/* A detail page with an in-page #edit panel (02-ia §10): while it is open its
   own Save is the only primary action, so the page head's actions go; and its
   page bar — the last child of .page, marked .page-bar--edit — exists only
   while the panel is open.
   <div class="page"> … <section id="edit" data-state="edit">…</section>
     <div class="page-bar page-bar--edit">…Save changes</div></div> */
.page:has(#edit:target) .page-head__actions {
  display: none;
}

.page:not(:has(#edit:target)) > .page-bar--edit {
  display: none;
}

/* A failed-save state swaps the page bar's status line: write both lines,
   .page-bar__status--invalid shows while [data-state="invalid"] (or one of
   its fields) is the target, and the plain status line hides then.
   <p class="page-bar__status">Not saved yet</p>
   <p class="page-bar__status page-bar__status--invalid">Not saved: 2 fields need attention</p> */
.page-bar__status--invalid {
  display: none;
  color: var(--e-err-fg);
}

.page:has([data-state="invalid"]:target, [data-state="invalid"] :target) .page-bar__status--invalid {
  display: block;
}

.page:has([data-state="invalid"]:target, [data-state="invalid"] :target) .page-bar:has(> .page-bar__status--invalid) > .page-bar__status:not(.page-bar__status--invalid) {
  display: none;
}

/* …and any other part may follow it: [data-when="invalid"] shows only while
   the failed-save state is the target, [data-when="default"] hides then.
   Typical: two primaries in the page bar, the invalid one returning to the
   error summary (G06 short forms, G07 opening balances).
   <a class="btn btn--primary" href="#x-invalid" data-when="default" data-shortcut="ctrl+s">Save</a>
   <a class="btn btn--primary" href="#x-err" data-when="invalid" data-shortcut="ctrl+s">Save</a> */
.page:not(:has([data-state="invalid"]:target, [data-state="invalid"] :target)) [data-when="invalid"],
.page:has([data-state="invalid"]:target, [data-state="invalid"] :target) [data-when="default"] {
  display: none !important;
}

/* Success confirmations: a toast/alert that appears only when the page is
   reached with its fragment, e.g. /erp/docs/invoices/inv-0142.html#saved */
[data-show-on-target]:not(:target) {
  display: none !important;
}

/* Prototype-only state switcher — dashed, like the demo chip: not product UI */
.proto-states {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border: 1px dashed var(--e-border-strong);
  border-radius: var(--r-md);
  color: var(--e-muted);
  font-size: var(--fs-sm);
}

.proto-states > strong {
  color: var(--e-fg);
  font-weight: var(--fw-semibold);
}

/* Role variants: a page whose file name ends in -auditor / -sales /
   -accountant renders the chrome as that role sees it (body[data-path]). */
[data-path$="-auditor.html"] [data-hide-for~="auditor"],
[data-path$="-sales.html"] [data-hide-for~="sales"],
[data-path$="-accountant.html"] [data-hide-for~="accountant"] {
  display: none !important;
}

/* data-show-for lists the roles that DO see an element (owner = the default,
   un-suffixed page); it stays hidden for every other role */
body:not([data-path$="-auditor.html"]):not([data-path$="-sales.html"]):not([data-path$="-accountant.html"]) [data-show-for]:not([data-show-for~="owner"]),
[data-path$="-auditor.html"] [data-show-for]:not([data-show-for~="auditor"]),
[data-path$="-sales.html"] [data-show-for]:not([data-show-for~="sales"]),
[data-path$="-accountant.html"] [data-show-for]:not([data-show-for~="accountant"]) {
  display: none !important;
}

/* Company-state variant (batch 4, from G11): a page whose file name ends in
   "expired.html" (erp/subscription/expired.html, or a …-expired.html copy)
   renders the chrome of a company whose plan has lapsed (02-ia §11): the
   sidebar keeps only System → Subscription, and the plan footer and the
   topbar New menu go. Like the role suffixes, the page never styles the
   chrome itself.                                                          */
.layout-app[data-path$="expired.html"] .sidebar .nav__group:not([data-nav-group="system"]),
.layout-app[data-path$="expired.html"] .sidebar [data-nav-group="system"] .nav__list > li:not(:has([data-nav="system.subscription"])),
.layout-app[data-path$="expired.html"] .sidebar__foot,
.layout-app[data-path$="expired.html"] .topbar__new {
  display: none;
}

.readonly-note {
  width: calc(100% - 2 * var(--lx-page-pad));
  max-width: var(--content-max);
  margin: var(--sp-5) auto 0;
}

@container main (max-width: 1100px) {
  .readonly-note {
    --lx-page-pad: var(--sp-6);
  }
}

@container main (max-width: 720px) {
  .readonly-note {
    --lx-page-pad: var(--sp-4);
  }
}

/* ── 7. Auth layout ────────────────────────────────────────────────────── */

.auth {
  display: grid;
  grid-template-columns: clamp(22rem, 38vw, 36rem) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
}

.auth__brand {
  /* dark brand panel: remap ink tokens so brand partials read on navy */
  --e-fg: var(--e-sidebar-fg);
  --e-muted: var(--e-sidebar-muted);
  --e-faint: var(--e-sidebar-muted);
  --e-focus: var(--e-sidebar-fg);
  display: flex;
  flex-direction: column;
  gap: var(--sp-8);
  padding: var(--sp-12) var(--sp-10) var(--sp-8);
  background: var(--e-sidebar);
  color: var(--e-sidebar-fg);
}

/* annotation micro-label (03-brand §6.1): ≤ 12px, tracked, muted */
.auth__context {
  display: none;
  align-self: flex-start;
  color: var(--e-sidebar-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

[data-path^="/erp/admin/"] .auth__context {
  display: inline-flex;
}


.auth__points {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  margin: auto 0 var(--sp-4);
  padding: 0;
  list-style: none;
  max-width: 30rem;
}

.auth__points.auth__points--admin,
[data-path^="/erp/admin/"] .auth__points.auth__points--tenant {
  display: none;
}

[data-path^="/erp/admin/"] .auth__points.auth__points--admin {
  display: flex;
}

.auth__points li {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  gap: var(--sp-3);
  color: var(--e-sidebar-muted);
  line-height: var(--lh-ui);
}

.auth__points .icon {
  width: 20px;
  height: 20px;
  margin-top: 1px;
  color: var(--e-sidebar-fg);
}

.auth__points strong {
  display: block;
  color: var(--e-sidebar-fg);
}

.auth__legal {
  padding-top: var(--sp-5);
  border-top: 1px solid var(--e-sidebar-border);
}

.auth__main {
  display: grid;
  place-items: center;
  padding: var(--sp-10) var(--sp-6);
}

.auth__main:focus {
  outline: none;
}

.auth__legal--narrow {
  display: none;
}

.auth__panel {
  width: 100%;
  max-width: var(--lx-auth);
}

@media (max-width: 1023.98px) {
  .auth {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr;
  }

  .auth__brand {
    gap: var(--sp-3);
    padding: var(--sp-5) var(--sp-5) var(--sp-5);
  }

  .auth__points,
  .auth__legal {
    display: none !important;
  }

  /* the owner line moves to the foot of the form panel (03-brand §3.3) */
  .auth__main > .auth__legal--narrow {
    display: block !important;
    width: 100%;
    max-width: var(--lx-auth);
    margin-top: var(--sp-8);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--e-border);
  }

  .auth__main {
    align-items: start;
    padding: var(--sp-8) var(--sp-4) var(--sp-10);
  }
}

/* ── 8. Bare layout ────────────────────────────────────────────────────── */

.bare {
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--sp-10) var(--sp-4);
}

.bare:focus {
  outline: none;
}

.bare__panel {
  width: 100%;
  max-width: var(--lx-narrow);
}

/* ── 9. Mobile CRM: phone frame, app bar, tab bar ──────────────────────── */

.layout-mobile {
  background: var(--e-surface);
}

.phone {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: var(--lx-phone);
  min-height: 100vh;
  min-height: 100dvh;
  margin-inline: auto;
  background: var(--e-bg);
}

@media (min-width: 480px) {
  .phone {
    border-inline: 1px solid var(--e-border);
    box-shadow: var(--shadow-2);
  }
}

.m-appbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--topbar-h);
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-4);
  padding-top: max(var(--sp-2), env(safe-area-inset-top));
  background: var(--e-raised);
  border-bottom: 1px solid var(--e-border);
}

.m-appbar__title {
  display: grid;
  flex: 1 1 auto;
  min-width: 0;
  line-height: 1.15;
}

.m-appbar__eyebrow {
  color: var(--e-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.04em;
}

.m-appbar__title h1 {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--fs-xl);
}

.m-appbar__actions {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}

.m-main {
  flex: 1 0 auto;
  min-width: 0;
  padding: var(--sp-4) var(--sp-4) var(--sp-8);
  container: main / inline-size;
}

.m-main:focus {
  outline: none;
}

.m-main > .page {
  padding: 0;
}

/* back link a mobile page may put first in its content */
.m-back {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: 44px;
  margin: calc(-1 * var(--sp-2)) 0 var(--sp-2);
  color: var(--e-muted);
  font-weight: var(--fw-semibold);
  text-decoration: none;
}

.m-back:hover {
  color: var(--e-primary);
}

.m-tabbar {
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--e-raised);
  border-top: 1px solid var(--e-border);
}

.m-tabbar__item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 58px;
  padding: var(--sp-2) var(--sp-1);
  color: var(--e-muted);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  text-decoration: none;
}

.m-tabbar__item > .icon {
  width: 22px;
  height: 22px;
}

.m-tabbar__item:hover {
  color: var(--e-fg);
}

.m-tabbar__item[aria-current="page"] {
  color: var(--e-primary);
  font-weight: var(--fw-semibold);
}

.m-tabbar__item[aria-current="page"]::before {
  content: "";
  position: absolute;
  inset: 0 28% auto;
  height: 3px;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  background: var(--e-primary);
}

/* PIN lock: no tab bar, no lock button (nav: m.lock) */
[data-screen="m.lock"] .m-tabbar,
[data-screen="m.lock"] .m-appbar__lock {
  display: none;
}

/* ── 10. Print layout: toolbar + sheets ────────────────────────────────── */

.layout-print {
  background: var(--e-surface);
}

.print-toolbar {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  min-height: var(--topbar-h);
  padding: var(--sp-2) var(--sp-4);
  background: var(--e-raised);
  border-bottom: 1px solid var(--e-border);
}

.print-toolbar__title {
  flex: 1 1 12rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: var(--fw-semibold);
}

.print-toolbar__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}

.print-toolbar__hint {
  color: var(--e-muted);
  font-size: var(--fs-xs);
}

/* the title is "Tenant · Document NO" (it names the saved PDF); a phone shows
   only the document number ({{docno}}) and the short hint */
.print-toolbar__short,
.print-toolbar__hint--short {
  display: none;
}

@media (max-width: 599.98px) {
  .print-toolbar__long,
  .print-toolbar__hint:not(.print-toolbar__hint--short) {
    display: none;
  }

  .print-toolbar__short {
    display: inline;
  }

  /* Share + Print keep one row; the short hint is a line under them */
  .print-toolbar__hint--short {
    display: block;
    flex-basis: 100%;
    order: 3;
  }
}

.print-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-6);
  padding: var(--sp-6) var(--sp-4) var(--sp-12);
}

.print-main:focus {
  outline: none;
}

/* optional paper-format switch a print page may put first in its content */
.print-variants {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
}

/* one .sheet = one physical page on screen; it is paper in every theme */
.sheet {
  width: min(210mm, 100%);
  min-height: 297mm;
  padding: 12mm;
  background: var(--e-raised);
  color: var(--e-fg);
  border: 1px solid var(--e-border);
  box-shadow: var(--shadow-2);
}

.sheet--80mm,
.sheet--58mm {
  min-height: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
}

.sheet--80mm {
  width: min(80mm, 100%);
  padding: 5mm 4mm 6mm;
}

.sheet--58mm {
  width: min(58mm, 100%);
  padding: 4mm 3mm 5mm;
}

@media (max-width: 820px) {
  .print-main {
    padding-inline: 0;
  }

  .sheet:not(.sheet--80mm, .sheet--58mm) {
    min-height: 0;
    padding: 6mm 5mm;
    border-inline: 0;
  }
}

@media print {
  /* The default A4 @page lives in print.css (UI Designer). A thermal roll is
     one continuous page as long as the slip: each thermal print page sets its
     own named @page (size: 80mm <L>mm; margin: 0) for its sheet id, with L
     measured by tools/G10/rolls.mjs — the product measures the rendered slip
     at print time. No fixed 297 mm roll page here: it would cut a 400 mm slip
     in two, and a later unnamed @page wins over it in Chrome anyway.       */
  .layout-print {
    background: none;
  }

  .print-toolbar,
  .print-variants,
  .proto-states,
  .skip-link {
    display: none !important;
  }

  .print-main {
    display: block;
    padding: 0;
  }

  .sheet {
    width: auto;
    min-height: 0;
    padding: 0;
    border: 0;
    box-shadow: none;
  }

  .sheet + .sheet {
    break-before: page;
  }

  .sheet--80mm {
    width: 80mm;
    padding: 3mm 4mm;
  }

  .sheet--58mm {
    width: 58mm;
    padding: 3mm 3mm;
  }

  /* app chrome never prints */
  .sidebar,
  .topbar,
  .m-appbar,
  .m-tabbar,
  .page-bar,
  .page-head__actions {
    display: none !important;
  }

  .app {
    display: block;
  }
}
