/* Tenant surface: sign-in, onboarding and the workspace at /app.

   This file carries ONLY tenant-specific layout. Every colour, radius, shadow
   and typeface comes from the shared design tokens in styles.css, which
   tenant.html loads first. Do not redefine :root here - a second palette is
   what made this surface diverge from the engineering studio and the platform
   console in the first place.

   Everything below therefore themes correctly in both light and dark, because
   styles.css swaps the token values on body.dark.

   THE SHELL IS THE SAME SHELL. The v4 experience is one structure repeated on
   all three surfaces: a full-width surface bar, a 242px sidebar carrying the
   brand, the current surface and role, grouped navigation and the signed-in
   identity, then a main column with its own sticky top bar. shell.css owns
   the surface bar and the page grammar shared with the Engineering Studio
   (.workspace-chip, .task-row, .usage-grid); styles.css owns the element-level
   shell rules (aside, header, .brand, .operator, .metrics, .card, .pill).
   What is left - and all this file now holds for the workspace - is the parts
   that differ because /app hangs its shell inside <section id="workspace">
   rather than at the top level, and because its navigation is a list of
   buttons rather than a nav of anchors. */

* {
  box-sizing: border-box;
}

/* The surface bar's own height, needed twice: the sign-in panel measures the
   viewport against it, and both sticky elements in the workspace (the sidebar
   and the page top bar) have to start BELOW it rather than at 0. Two sticky
   elements at top:0 do not stack - the bar wins on z-index and the page header
   slides under it, taking the breadcrumb and the sign-out control with it.
   shell.css floors the bar at 46px and nothing inside it is taller. */
body {
  --surface-bar-h: 46px;
  min-height: 100vh;
  /* Subtle brand wash built from the accent tint, so it holds in both themes. */
  background:
    radial-gradient(circle at 15% 10%, var(--accent2) 0, transparent 45%),
    var(--bg);
}

/* ---------- Sign-in / onboarding ---------- */

.auth-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, 440px);
  gap: 8vw;
  align-items: center;
  min-height: calc(100vh - var(--surface-bar-h));
  padding: clamp(32px, 7vw, 96px);
}

.auth-copy {
  max-width: 720px;
}

/* The by-SC mark is drawn for 180 px and up; smaller places use the plain mark. */
.auth-hero-mark {
  display: block;
  width: 180px;
  height: 180px;
  margin-bottom: 18px;
}

.eyebrow {
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--accent);
  font-size: .75rem;
  font-weight: 800;
}

.auth-copy h1 {
  font-size: clamp(2.5rem, 6vw, 5.6rem);
  line-height: .98;
  margin: .25em 0;
  color: var(--text);
}

.auth-copy p:last-child {
  font-size: 1.15rem;
  color: var(--muted);
  max-width: 580px;
}

.auth-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 32px;
  box-shadow: var(--shadow);
}

.auth-card h2 {
  margin-top: 0;
  font-size: 1.7rem;
}

.auth-card label {
  display: grid;
  gap: 7px;
  margin: 18px 0;
  color: var(--muted);
  font-size: .9rem;
}

.auth-card input,
.auth-card select {
  width: 100%;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--text);
  border-radius: 10px;
  padding: 13px;
  outline: none;
}

.auth-card input:focus,
.auth-card select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent2);
}

/* Submit controls carry the shared .primary class from styles.css; only the
   full-width sign-in sizing is tenant-specific. */
.auth-card button[type="submit"] {
  width: 100%;
  padding: 13px;
  font-size: 1rem;
}

.auth-links {
  display: flex;
  justify-content: space-between;
  margin: 20px 0 0;
}

.auth-links a {
  color: var(--accent);
}

.hint,
.notice {
  color: var(--muted);
  font-size: .88rem;
}

.notice {
  padding: 12px;
  border-radius: 9px;
  background: var(--accent2);
  border: 1px solid var(--line);
  color: var(--text);
  margin-bottom: 16px;
}

.notice.error {
  background: var(--panel2);
  border-color: var(--bad);
  color: var(--bad);
}

/* THIS BLOCK IS GONE, and what it was doing is worth recording.

   It redeclared `.secondary` in full - border, radius, padding, background,
   colour, weight - and every one of those declarations already exists in
   `styles.css`, which this surface loads. So it changed nothing about a
   full-size secondary control and did exactly one thing: at equal specificity
   and a later load, its `padding: 9px 13px` beat `.small { padding: 5px 8px }`.

   Every button classed `small secondary` on this surface therefore rendered
   FULL SIZE, while a `small danger` button in the same table cell rendered
   small - measured on the deployed appliance, 36px beside 26px in one row of
   Sites & Customers. That is the same defect as the `.row-actions` override
   below and it has the same cause: this stylesheet redeclaring a class the
   global sheet owns and winning by load order.

   The comment that stood here said a full-size secondary "matched nothing and
   fell back to the browser's default button". That was true of a page which
   did not load `styles.css`; `tenant.html` loads it, and
   `.primary,.danger,.small,.secondary` there carries the full-size padding
   with `.secondary` carrying the panel background beneath it. The hover and
   disabled rules below are genuine additions and stay. */

.secondary:hover:not([disabled]) {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  color: var(--accent);
}

.secondary[disabled],
.primary[disabled],
.small[disabled] {
  opacity: .55;
  cursor: not-allowed;
}

.tenant-choice {
  margin-top: 10px !important;
  background: var(--panel2) !important;
  color: var(--text) !important;
}

/* ---------- The workspace shell ---------- */

.workspace {
  display: grid;
  grid-template-columns: 242px minmax(0, 1fr);
  min-height: calc(100vh - var(--surface-bar-h));
}

.workspace > aside {
  background: var(--panel);
  border-right: 1px solid var(--line);
  padding: 16px 13px;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: var(--surface-bar-h);
  height: calc(100vh - var(--surface-bar-h));
  overflow-x: hidden;
  overflow-y: auto;
  z-index: 9;
}

/* Two children, not three: the Engineering Studio's brand row carries a
   collapse control and this one does not, so the inherited three-column grid
   left a 26px gutter that pushed the wordmark off centre. */
.workspace .brand {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  gap: 10px;
  align-items: center;
  padding: 4px 8px 18px;
}

.workspace .brand-mark {
  width: 36px;
  height: 36px;
  border-radius: 11px;
  font-size: 13px;
}

.workspace .brand b {
  font-size: 13px;
  font-weight: 800;
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The group label above the navigation. */
.workspace > aside h2 {
  margin: 4px 0 6px;
  padding: 0 10px;
  font-size: 9px;
  font-weight: 800;
  line-height: 1.4;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--muted);
}

/* THE NAVIGATION RULE IS SCOPED TO THE SIDEBAR, and that is the whole point.
   It used to read `.workspace button, .workspace a`, which is one class plus
   one element - heavier than the bare `.primary` in styles.css - so every
   button the content column rendered came out transparent, muted and
   left-aligned. Save, Create API client, Rotate secret and Export CSV all
   looked like navigation links that had wandered into the page. */
.workspace > aside button[data-view] {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  align-items: center;
  gap: 9px;
  width: 100%;
  margin: 2px 0;
  padding: 9px 10px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--muted);
  text-align: left;
  font-size: 12.5px;
  font-weight: 600;
}

.workspace > aside button[data-view] i {
  font-style: normal;
  font-size: 11px;
  text-align: center;
  opacity: .9;
}

.workspace > aside button[data-view] span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.workspace > aside button[data-view]:hover {
  background: var(--panel2);
  color: var(--text);
}

.workspace > aside button[data-view].active {
  background: var(--accent2);
  color: var(--accent);
  font-weight: 750;
}

/* The identity footer, pinned to the bottom of the rail. `.operator` and
   `.avatar` come from styles.css; only the spacing differs here. */
.workspace .operator {
  margin-top: auto;
  padding: 14px 8px 2px;
}

.workspace .operator b {
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- The main column ---------- */

.workspace-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.workspace-main > header {
  top: var(--surface-bar-h);
  padding: 0 24px;
  gap: 14px;
}

.workspace-main > header .crumb {
  min-width: 0;
  font-size: 12px;
  font-weight: 650;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.workspace-main .session-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.workspace-main .session-controls button {
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--muted);
  border-radius: 9px;
  padding: 8px 11px;
  font-size: 12px;
  font-weight: 700;
}

.workspace-main .session-controls button:hover {
  color: var(--text);
  background: var(--panel2);
}

#workspaceContent {
  display: block;
  width: 100%;
  max-width: 1720px;
  margin: 0 auto;
  padding: 24px 26px 48px;
}

#workspaceContent h2 {
  font-size: 16px;
  margin: 26px 0 12px;
}

#workspaceContent .card h2 {
  margin: 0 0 14px;
}

#workspaceContent .page-head p {
  max-width: 850px;
  margin-top: 7px;
}

#workspaceContent .metric strong.value-sm {
  font-size: 20px;
  overflow-wrap: anywhere;
}

/* Tables come out of tenantTable() bare; the border, radius and horizontal
   scroll are the shared .table-wrap in styles.css. */
#workspaceContent .table-wrap {
  margin-bottom: 18px;
}

/* Forms rendered into the content column - single sign-on, API client
   creation, authenticator enrollment. The sign-in card's rules are scoped to
   .auth-card, so these inherited nothing at all and rendered as unlabelled
   browser defaults stacked against the left margin. */
#workspaceContent form {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
  margin-bottom: 18px;
  max-width: 720px;
}

#workspaceContent form label {
  display: grid;
  gap: 6px;
  margin: 0 0 16px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
}

/* A tick box and its wording sit on one line, with any explanation dropped
   underneath. The renderers mark these labels `.check` rather than the
   stylesheet guessing from the input type, because two of these forms put the
   box before the wording and one puts it after. */
#workspaceContent form label.check {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  color: var(--text);
}

#workspaceContent form label.check > .hint {
  flex-basis: 100%;
}

#workspaceContent form label .hint {
  font-weight: 500;
  font-size: 11px;
  line-height: 1.5;
  color: var(--muted);
}

#workspaceContent form input,
#workspaceContent form select {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 10px 11px;
  background: var(--bg);
  color: var(--text);
  font-weight: 500;
}

#workspaceContent form input[type="checkbox"] {
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
}

#workspaceContent form input:focus,
#workspaceContent form select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent2);
}

#workspaceContent form button {
  margin-right: 8px;
}

#workspaceContent pre {
  margin: 0;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel2);
  color: var(--text);
  font: 13px/1.6 var(--mono);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

/* An unlimited allowance has no ceiling to draw. The track is decoration for
   the number and drawing an empty one would state a limit that does not
   exist, so the word replaces the bar rather than sitting beside a bar at 0%. */
.usage-note {
  font-size: 12px;
  font-weight: 750;
  color: var(--accent);
  padding: 2px 0;
}

.usage-note.absent {
  color: var(--muted);
  font-weight: 600;
}

/* ROW ACTIONS ARE THE WORKSPACE'S, NOT THIS SURFACE'S.
   `styles.css:319` pins this class to a single line - display:flex,
   flex-wrap:nowrap, white-space:nowrap - and every table in the Engineering
   Studio obeys it. This file redeclared it with `flex-wrap: wrap` and loads
   AFTER styles.css, so at equal specificity it won: a member row carrying
   five verbs, a site row carrying "Lift call separation", and the domain,
   credential and support-access rows all folded onto a second line and
   doubled their row height, on the one surface a customer spends its time in
   (owner report, 2026-08-27: "make all buttons in tables on same row like all
   other pages"). The declaration is deleted rather than corrected: a second
   copy that happens to agree is the next drift. `.small`'s margin reset stays
   because styles.css sets it too and repeating it here costs nothing if this
   file is ever loaded alone. */
.row-actions .small {
  margin-right: 0;
}

/* A row of controls under an empty state or beside a heading. */
.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  justify-content: center;
  margin-top: 14px;
}

.card .empty {
  padding: 22px 6px;
}

.card .empty h3 {
  margin: 0 0 7px;
  color: var(--text);
  font-size: 15px;
}

.card .empty p {
  margin: 0 auto;
  max-width: 460px;
  line-height: 1.6;
}

/* The task list's own trailing note: what this check could NOT see, stated
   rather than left as a silent gap in the list. */
.scope-note {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 11px;
  line-height: 1.6;
}

/* ---------- Narrowing a list ---------- */

/* The filter row above a table. It uses .filter-field rather than the shared
   .toolbar because every control here carries a label: an unlabelled select
   whose first option reads "Any role" is only legible while it is untouched,
   and becomes an unexplained word the moment somebody chooses something. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
  margin: 0 0 14px;
}

.filter-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 11px;
  color: var(--muted);
}

.filter-field > span {
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.filter-field input,
.filter-field select {
  min-width: 170px;
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 8px 11px;
  background: var(--panel);
  color: var(--text);
  font-size: 12px;
}

/* "3 of 19 members match the filters above" - the line that stops a narrow
   filter reading as an empty organization. */
/* `.result-count` moved to styles.css when the provider console grew the same
   strip. Two sheets declaring one class is how they drift, and this file has
   already been the losing side of that twice. */

/* THE PAGER, one shape for every list on this surface. It sits above its
   table beside the count, so "where am I" and "how much is there" are read in
   one glance rather than at opposite ends of a long list. `.result-count`
   inside it loses its bottom margin because the strip owns the spacing. */
.pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0 0 12px;
}

.pager .result-count {
  margin: 0;
  flex: 1 1 240px;
}

.pager-position {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* The size picker is a filter field on a control strip rather than above one,
   so it lays out along the row instead of stacking its label. */
.pager-size {
  flex-direction: row;
  align-items: center;
  gap: 7px;
}

.pager-size select {
  min-width: 72px;
}

.section {
  margin-bottom: 8px;
}

/* ---------- A confirmed write ---------- */

/* The dialog is fixed and covers the page because the decision it asks for is
   the only thing on screen that matters at that moment. It is never dismissed
   while its write is in flight, so no state here depends on a timer. */
.tenant-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: #04070ecc;
}

.tenant-modal {
  width: min(560px, 100%);
  max-height: min(86vh, 720px);
  overflow: auto;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  box-shadow: 0 30px 70px #04070e66;
}

.tenant-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}

.tenant-modal-head h2 {
  margin: 0;
  font-size: 16px;
}

.tenant-modal-close {
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}

.tenant-modal-close[disabled] {
  opacity: 0.4;
  cursor: default;
}

.tenant-modal p {
  margin: 0 0 12px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.65;
}

.tenant-modal label {
  display: block;
  margin-bottom: 12px;
  font-size: 12px;
}

.tenant-modal label > span:first-child {
  display: block;
  margin-bottom: 5px;
  color: var(--muted);
}

/* A dialog field whose answers are a closed set renders as a select, and it
   has to sit on the same box as the text fields beside it - an unstyled
   control in a styled dialog reads as a different kind of thing. */
.tenant-modal input,
.tenant-modal select,
.tenant-modal textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 9px 11px;
  background: var(--panel2);
  color: var(--text);
  font: inherit;
}

.tenant-modal textarea {
  min-height: 76px;
  resize: vertical;
}

/* The failure path renders here, inside a dialog that is still open, rather
   than into a node the success path would already have removed. */
.tenant-modal-error {
  margin: 0 0 12px;
  padding: 9px 11px;
  border-left: 3px solid var(--bad);
  border-radius: 7px;
  background: color-mix(in srgb, var(--bad) 10%, var(--panel));
  color: var(--text);
}

.tenant-modal-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 4px;
}

/* ---------- The workspace message ---------- */

/* #workspaceNotice is the LAST element of the main column, so a message about
   a save that just happened rendered below the fold of whatever page produced
   it - the operator saw nothing move. It is a corner panel instead, and it
   carries its own dismiss control: a message that cannot be dismissed either
   stays over the page forever or has to disappear on a timer, and a timer
   deciding when an error stops being true is the wrong owner for that. */
#workspaceNotice {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 40;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0;
  padding: 13px 14px;
  max-width: min(460px, calc(100vw - 44px));
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  box-shadow: var(--shadow);
  font-size: 13px;
  line-height: 1.5;
}

#workspaceNotice.error {
  border-left-color: var(--bad);
  color: var(--bad);
  background: var(--panel);
}

.notice-dismiss {
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
}

.notice-dismiss:hover {
  color: var(--text);
}

/* ---------- Responsive ---------- */

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

  /* The off-canvas drawer styles.css defines for the Engineering Studio, at
     the specificity the sidebar rule above now sits at. The surface bar stays
     put: which surface you are in is the one piece of chrome that survives
     every width. */
  .workspace > aside {
    position: fixed;
    top: var(--surface-bar-h);
    left: -270px;
    width: 254px;
    height: calc(100vh - var(--surface-bar-h));
    z-index: 30;
    transition: left .2s;
  }

  body.menu-open .workspace > aside {
    left: 0;
    box-shadow: 20px 0 45px #0b183044;
  }

  #workspaceContent {
    padding: 20px 16px 40px;
  }

  /* styles.css collapses .grid-2 to one column in this same range and then
     RE-DECLARES the two-column template further down the file, unconditionally,
     so the later rule wins and the collapse never happens. The tasks card and
     the usage card were sharing 375px. Restated here for the content column,
     where the two cards live. */
  #workspaceContent .grid-2 {
    grid-template-columns: minmax(0, 1fr);
  }

  .workspace-main > header {
    padding: 0 16px;
  }
}

@media (max-width: 800px) {
  .auth-shell {
    grid-template-columns: 1fr;
  }

  .auth-copy {
    display: none;
  }

  #workspaceNotice {
    right: 12px;
    left: 12px;
    bottom: 12px;
    max-width: none;
  }
}
