/* GAMBIT application baseline. Public presentation has its own scoped layout;
   the logo and primary accent belong to both surfaces. */
@font-face {
  font-family: "FiraGO";
  src: url("/fonts/public/FiraGO-Regular.woff2?v=loading-01") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: block;
}

@font-face {
  font-family: "FiraGO";
  src: url("/fonts/public/FiraGO-Medium.woff2?v=loading-01") format("woff2");
  font-style: normal;
  font-weight: 500;
  font-display: block;
}

@font-face {
  font-family: "FiraGO";
  src: url("/fonts/public/FiraGO-Bold.woff2?v=loading-01") format("woff2");
  font-style: normal;
  font-weight: 700;
  font-display: block;
}

:root {
  /* neutral ramp */
  --color-surface: #ffffff;
  --color-bg: #f7f8fa;
  --color-surface-subtle: #eff1f4;
  --color-border-subtle: #e3e6eb;
  --color-border: #cbd1d9;
  --color-control-border: #7b8583;
  --color-text-muted: #5a6472;
  --color-text-faint: #8c96a3;
  --color-text: #2b323c;
  --color-text-strong: #171b21;

  /* accent — single and restrained (§66) */
  --color-accent: #245b5b;
  --color-accent-hover: #1b4545;
  --color-accent-tint: #e8f2ef;

  /* status families: fg / bg; border style is the non-colour channel */
  --status-danger-fg: #b3261e;
  --status-danger-bg: #fdecea;
  --status-warning-fg: #8a5300;
  --status-warning-bg: #fff3e0;
  --status-success-fg: #1b6b3a;
  --status-success-bg: #e8f5ec;
  --status-info-fg: #1f5fa8;
  --status-info-bg: #eaf1fa;
  --status-neutral-fg: #5a6472;
  --status-neutral-bg: #eff1f4;
  --status-unknown-fg: #4a4a4a;
  --status-unknown-bg: #f2f2f2;
  --status-stale-fg: #6e5300;
  --status-stale-bg: #fbf3dc;
  --status-muted-fg: #5a6472;
  --status-muted-bg: #f2f2f2;

  /* Keep the bundled private face when a weight finishes loading after the
     first paint; an optional deadline could retain a different system face. */
  --font-ui: "FiraGO", "Noto Sans Georgian", "Noto Sans", "Segoe UI", Arial, system-ui, sans-serif;
  --font-mono: "Noto Sans Mono", "Cascadia Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  --text-xs: 0.75rem;
  --text-sm: 0.8125rem;
  --text-base: 0.875rem;
  --text-md: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.375rem;
  --text-2xl: 1.75rem;
  --leading-tight: 1.3;
  --leading-base: 1.5;

  /* spacing, 4px base */
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 8px;
  --space-4: 12px;
  --space-5: 16px;
  --space-6: 20px;
  --space-7: 24px;
  --space-8: 32px;
  --space-9: 40px;
  --space-10: 48px;
  --space-11: 64px;

  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 8px;
  --radius-pill: 999px;

  --elev-2: 0 1px 2px rgba(23, 27, 33, 0.08);
  --elev-3: 0 8px 24px rgba(23, 27, 33, 0.16);

  --focus-ring: 2px solid var(--color-accent);
  --focus-offset: 2px;

  --row-comfortable: 40px;
  --row-compact: 32px;
  --touch-target: 44px;

  --motion-fast: 120ms;
  --motion-base: 180ms;

  --z-sticky: 100;
  --z-dropdown: 200;
  --z-dialog: 300;
  --z-toast: 400;

  --content-max: 1200px;
}

/* ---------------------------------------------------------------- reset */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-family: var(--font-ui);
  font-size: 100%;
  line-height: var(--leading-base);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-size: var(--text-base);
  min-height: 100vh;
}

h1,
h2,
h3 {
  color: var(--color-text-strong);
  font-weight: 600;
  line-height: var(--leading-tight);
  margin: 0 0 var(--space-4);
}

p {
  margin: 0 0 var(--space-4);
}

a {
  color: var(--color-accent);
}

a:hover {
  color: var(--color-accent-hover);
}

code,
.mono {
  font-family: var(--font-mono);
  font-size: 0.95em;
}

/* Focus is always visible and never removed (A-UI-A11Y-03). */
:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* ---------------------------------------------------------------- shell */

.skip-link {
  position: absolute;
  left: var(--space-3);
  top: -100px;
  z-index: var(--z-toast);
  padding: var(--space-3) var(--space-5);
  background: var(--color-surface);
  color: var(--color-accent);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

/* Read by assistive technology, not shown; still laid out (not display:
   none), which the intake form's implicit-submit button relies on. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link:focus {
  top: var(--space-3);
}

.shell-header {
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border-subtle);
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}

.shell-header__inner {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-2) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-6);
  min-height: var(--row-comfortable);
  flex-wrap: wrap;
}

/* The navigation row anchors the desktop Sections panel. */
.shell-header__inner--nav {
  position: relative;
  padding-top: 0;
  padding-bottom: 0;
}

.brand {
  display: inline-flex;
  align-items: center;
  flex: none;
  font-weight: 700;
  font-size: var(--text-md);
  letter-spacing: 0.04em;
  color: var(--color-text-strong);
  text-decoration: none;
}

.brand img {
  display: block;
  width: 112px;
  height: auto;
}

.auth__header .brand img {
  width: 140px;
}

/* The links wrap onto a second row rather than widen the page: six of
   them in Georgian are wider than a 390 px phone. */
.shell-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  min-width: 0;
}

/* Desktop daily links share the row with the native Sections disclosure. */
.shell-nav__links {
  display: contents;
}

.shell-nav__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--row-comfortable);
  padding: 0 var(--space-4);
  color: var(--color-text);
  text-decoration: none;
  border-bottom: 2px solid transparent;
}

.shell-nav__link:hover {
  color: var(--color-accent-hover);
}

/* Links in the mobile scrolling strip keep their whole focus ring inside. */
.shell-nav__link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

.shell-nav__link[aria-current="page"] {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
  font-weight: 500;
}

/* --- The "More" panel (owner navigation review, 2026-10-15): a native
   <details>; its summary sits in the row like a link, its links open in a
   panel under the row. No script: the panel closes with its summary (or the
   next page load). The group is not positioned: the panel is laid out
   against the navigation row and spans it, so wherever the summary lands
   when the row wraps, the panel never leaves the page. */
.shell-nav__group {
  position: static;
}

.shell-nav__summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--row-comfortable);
  padding: 0 var(--space-4);
  color: var(--color-text);
  border-bottom: 2px solid transparent;
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}

.shell-nav__summary::-webkit-details-marker {
  display: none;
}

/* A small chevron drawn with borders: down when closed, up when open. */
.shell-nav__summary::after {
  content: "";
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
}

.shell-nav__group[open] > .shell-nav__summary::after {
  transform: translateY(2px) rotate(-135deg);
}

.shell-nav__summary:hover,
.shell-nav__group[open] > .shell-nav__summary {
  color: var(--color-accent-hover);
}

.shell-nav__summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

/* The group holding the current page reads like the current link. */
.shell-nav__summary[aria-current="true"] {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
  font-weight: 500;
}

.shell-nav__panel {
  max-height: 60dvh;
  overflow-y: auto;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: var(--z-dropdown);
  display: flex;
  flex-direction: column;
  min-width: 14rem;
  padding: var(--space-2) 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: 0 6px 16px rgb(0 0 0 / 12%);
}

.shell-nav__panel .shell-nav__link {
  min-height: var(--row-comfortable);
  padding: 0 var(--space-5);
  border-bottom: 0;
  border-left: 3px solid transparent;
}

.shell-nav__panel .shell-nav__link[aria-current="page"] {
  border-left-color: var(--color-accent);
}

/* Explicit rows preserve the visible group order and keyboard reading order. */
.shell--staff .shell-nav .shell-nav__group > .shell-nav__panel {
  left: var(--space-5);
  right: var(--space-5);
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  align-items: start;
  gap: var(--space-4);
  padding: var(--space-4);
}

/* One heading with its links, in the registry's stable source order. */
.shell-nav__section {
  display: flex;
  flex-direction: column;
  min-width: 0;
  break-inside: avoid;
  padding-bottom: var(--space-4);
}

.shell-nav__heading {
  display: block;
  margin: 0 var(--space-5) var(--space-2) calc(var(--space-5) + 3px);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-border-subtle);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 500;
}

.shell-nav__section .shell-nav__link {
  min-height: var(--touch-target);
}

/* The staff intake action stays immediately available beside search. */
.shell-new-ticket {
  flex: none;
  margin-left: auto;
  white-space: nowrap;
}

/* Tinted with an accent border rather than filled: the page's own next step
   stays its one filled button (one primary per page). It fills on the
   intake pages it marks. Beside the first line when the row wraps. Two
   classes: the .btn rule comes later. */
.shell-header .shell-new-ticket {
  align-self: flex-start;
  margin-top: calc((var(--touch-target) - 32px) / 2);
  min-height: 32px;
  padding: 0 var(--space-4);
  border-color: var(--color-accent);
  background: var(--color-accent-tint);
  color: var(--color-accent);
  font-weight: 600;
}

.shell-header .shell-new-ticket:hover,
.shell-header .shell-new-ticket[aria-current="page"] {
  background: var(--color-accent);
  color: var(--color-surface);
}

.shell-new-ticket__plus {
  font-size: var(--text-md);
  line-height: 1;
}

.shell-new-ticket__short {
  display: none;
}

.shell-new-ticket:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

.shell-tools {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.shell-search {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  flex: 0 1 24rem;
  min-width: 0;
}

/* As tall as the language switch beside it: the header stays one compact
   row. Two classes: the .input and .btn--small rules come later. */
.shell-search .shell-search__input {
  flex: 1 1 auto;
  width: auto;
  max-width: 100%;
  min-width: 0;
  min-height: 32px;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-base);
}

/* One word on one line: squeezed among the links it broke as "ძებ / ნა". */
.shell-search .shell-search__button {
  flex: none;
  min-height: 32px;
  white-space: nowrap;
}

.shell-user {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  text-decoration: none;
}

.shell-user:hover {
  text-decoration: underline;
}

.shell-main {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-6) var(--space-5) var(--space-10);
}

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

/* ---------------------------------------------------------------- settings hub */

/* One card per group (owner navigation review, 2026-10-15): its name, one
   plain line on what it is for, and the pages under it. Up to three
   balanced columns: a one-link card leaves no empty band under it. */
.settings-hub {
  columns: 3 22rem;
  column-gap: var(--space-6);
}

.settings-hub .settings-hub__group {
  break-inside: avoid;
  margin-bottom: var(--space-6);
}

.settings-hub .card__title {
  margin-bottom: var(--space-2);
}

.settings-hub__hint {
  margin: 0 0 var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.settings-hub__links {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--color-border-subtle);
}

.settings-hub__links li {
  border-bottom: 1px solid var(--color-border-subtle);
}

/* A whole row is the link, with a chevron at its end; underlined on hover. */
.settings-hub__link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: var(--row-comfortable);
  padding: var(--space-2) 0;
  font-weight: 500;
  text-decoration: none;
}

.settings-hub__link::after {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
}

.settings-hub__link:hover {
  text-decoration: underline;
}

.settings-hub__link:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* Read-only: which module packs are switched off (platform administrator). */
.settings-hub__note {
  margin: var(--space-4) 0 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.inline-form {
  display: inline;
  margin: 0;
}

.lang-switch {
  display: inline-flex;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin: 0;
}

.lang-switch__option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: inherit;
  font-size: var(--text-sm);
  background: var(--color-surface);
  color: var(--color-text);
  border: 0;
  padding: var(--space-2);
  min-width: 44px;
  min-height: 44px;
  cursor: pointer;
}

.lang-switch__option + .lang-switch__option {
  border-left: 1px solid var(--color-border);
}

.lang-switch__option[aria-pressed="true"],
.lang-switch__option[aria-current="page"] {
  background: var(--color-accent-tint);
  color: var(--color-accent);
  font-weight: 500;
  box-shadow: inset 0 -2px 0 var(--color-accent);
}

.lang-switch__option:hover {
  background: var(--color-accent-tint);
}

.lang-switch__option:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -4px;
}

.lang-switch__flag {
  display: block;
  flex: none;
  width: 28px;
  height: auto;
  border-radius: 2px;
  box-shadow: 0 0 0 1px var(--color-border);
  stroke: none;
}

/* ---------------------------------------------------------------- auth */

.auth {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-8) var(--space-5);
}

.auth__header {
  flex-wrap: wrap;
  gap: var(--space-4);
  width: 100%;
  max-width: 420px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-6);
}

.auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
}

.auth-card__title {
  font-size: var(--text-xl);
}

.auth-card__lead {
  color: var(--color-text-muted);
}

.auth-card__footer {
  margin: var(--space-6) 0 0;
  font-size: var(--text-sm);
}

.auth-card__footer a {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-target);
}

/* ---------------------------------------------------------------- page */

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-5);
  flex-wrap: wrap;
  margin-bottom: var(--space-6);
}

/* The project hours table has seven columns; in one half of the dashboard
   grid it scrolled sideways even on a wide screen. */
#dash-project-hours-card {
  grid-column: 1 / -1;
}

.page-title {
  font-size: var(--text-xl);
  margin: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
}

.page-subtitle {
  color: var(--color-text-muted);
  margin: var(--space-2) 0 0;
}

/* Long Georgian words must still fit the tariff page at enlarged text. */
#offer-lead {
  overflow-wrap: anywhere;
}

.page-actions {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.section-actions {
  min-width: 0;
  margin: 0 0 var(--space-6);
}

.section-actions__title {
  font-size: var(--text-md);
  margin: 0 0 var(--space-3);
}

.breadcrumb {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-3);
}

.breadcrumb a {
  color: inherit;
}

.card {
  min-width: 0;
  overflow-wrap: anywhere;
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  margin-bottom: var(--space-6);
}

.card__title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-5);
}

.card__header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}

.card__header .card__title {
  margin-bottom: 0;
}

/* A card whose content matters once and now: a setup code, a warning
   before an irreversible action. The border carries it, not colour alone -
   the title says what it is. */
.card--notice {
  border: 2px solid var(--status-info-fg);
}

.card--caution {
  border: 2px solid var(--status-danger-fg);
}

/* Minimum readable widths scale with text enlargement as well as the viewport. */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, max(20rem, calc((100% - var(--space-6)) / 2))), 1fr));
  gap: var(--space-6);
}

/* Cards of different lengths side by side keep their own heights: a short
   card is not stretched into an empty block beside a long column. The grid's
   gap alone separates them, also when a phone stacks them; the grid keeps
   the space a card would have left below it. */
.grid-2--start {
  align-items: start;
  margin-bottom: var(--space-6);
}

.grid-2--start > .card,
.grid-2--start > .card-column > .card:last-child {
  margin-bottom: 0;
}

/* Several cards stacked in one column of a grid. */
.card-column {
  min-width: 0;
}

/* entity header: identifiers, independent status chips, actions (A.4 #3) */
/* The ticket's next step, at the top of the page: words and a link, the
   rule on the left only repeats them. */
.next-step {
  margin: var(--space-3) 0 0;
  padding: var(--space-2) var(--space-3);
  border-left: 3px solid var(--color-accent);
  background: var(--color-accent-tint);
  border-radius: var(--radius-sm);
}

.entity-header__meta {
  display: flex;
  gap: var(--space-4);
  align-items: center;
  flex-wrap: wrap;
  margin-top: var(--space-3);
}

/* One record header: identity, legal commands and context share a wrapping row.
   Keeping this axis horizontal prevents width bases from becoming empty height
   when the legacy narrow page-header layout changes to a column. */
.page-header.entity-header {
  flex-direction: row;
  gap: var(--space-4) var(--space-5);
}

.entity-header__identity {
  flex: 1 1 24rem;
  min-width: 0;
  max-width: 100%;
}

.entity-header__actions {
  flex: 0 1 auto;
  align-items: center;
  min-width: 0;
  max-width: 100%;
}

.entity-header__actions:empty {
  display: none;
}

.entity-header__actions > *,
.entity-header__actions form,
.entity-header__next-action {
  min-width: 0;
  max-width: 100%;
}

.entity-header__actions form {
  margin: 0;
}

.entity-header__next-action {
  margin: 0;
}

.entity-header__actions .btn {
  min-height: var(--touch-target);
  max-width: 100%;
  padding-block: var(--space-2);
  font-size: var(--text-base);
  white-space: normal;
  overflow-wrap: anywhere;
}

.entity-header__context {
  flex: 1 1 100%;
  min-width: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
}

.entity-header__context .next-step {
  margin: 0;
}

/* The ticket's header (ENG-09): who holds the ticket and for whom, then one
   row of actions - the primary step, at most two secondaries and "more". The
   row stays put: a panel a button opens takes the full width under the whole
   row, after every button, in the page's flow - nothing floats over the page,
   the button just pressed stays under the pointer and the others keep their
   places (review 2026-10-17). */
.ticket-header__people {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-5);
  margin: 0;
}

.ticket-header__person {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Organization, requester and the call link: a wrapped part starts at the
   line's own start, spaced by the gap rather than an indenting margin. */
#ticket-customer-contact {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--space-3);
}

/* The requester's name wraps as a whole; inside itself only when longer than the line. */
.ticket-header__contact {
  display: inline-block;
  max-width: 100%;
}

.ticket-header__call {
  white-space: nowrap;
}

.ticket-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

/* The primary's wrapper names it for a screen reader; its button sits in the row itself. */
.ticket-actions__primary {
  display: contents;
}

.ticket-actions > *,
.ticket-actions__primary > * {
  min-width: 0;
  max-width: 100%;
}

.ticket-actions .btn {
  min-height: var(--touch-target);
  white-space: normal;
  overflow-wrap: anywhere;
  text-align: start;
}

/* Whose step it is when it is not this person's (A-6): a status line in
   the primary's place, a glyph and words - not a field hint. */
.ticket-actions__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--status-info-fg);
  border-radius: var(--radius-md);
  background: var(--status-info-bg);
  color: var(--status-info-fg);
  font-weight: 500;
}

.ticket-actions__glyph {
  font-family: var(--font-mono);
  font-weight: 700;
}

/* What a secondary means, in words under the row ("accept": seen, start later). */
.ticket-actions__hint {
  flex: 1 1 100%;
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.ticket-action > summary {
  list-style: none;
}

.ticket-action > summary::-webkit-details-marker {
  display: none;
}

.ticket-action__summary::after {
  content: "▾";
  font-size: var(--text-xs);
}

.ticket-action[open] > .ticket-action__summary::after {
  content: "▴";
}

/* An opened button is a quiet toggle: the form's own submit is the one
   filled button, so pressing the large button again folds the panel
   without anyone mistaking it for "save" (A-1, review 2026-10-17). */
.ticket-action[open] > .ticket-action__summary {
  background: var(--color-surface);
  color: var(--color-accent);
  border-color: currentColor;
}

.ticket-action[open] > .ticket-action__summary:hover {
  background: var(--color-accent-tint);
  color: var(--color-accent);
}

/* Where a disclosure's content box cannot be placed on its own, the open
   disclosure takes the row's width (its button then starts the next line). */
.ticket-action[open] {
  flex: 1 1 100%;
}

.ticket-action__panel,
.ticket-more {
  margin-top: var(--space-3);
}

@supports selector(::details-content) {
  /* The button is a box of the row itself and the opened content one more,
     placed after every button on a line of its own: opening a panel moves
     no button. A closed panel takes no place in the row at all. */
  .ticket-actions > .ticket-action,
  .ticket-actions__primary > .ticket-action {
    display: contents;
  }

  .ticket-actions .ticket-action::details-content {
    position: absolute;
  }

  .ticket-actions .ticket-action[open]::details-content {
    position: static;
    order: 1;
    flex: 1 1 100%;
    min-width: 0;
  }

  .ticket-actions .ticket-action__panel,
  .ticket-actions .ticket-more {
    margin-top: 0;
  }
}

.ticket-more {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

/* An item of "more" is one folded line, not a box inside the box; its form
   opens under its title. Raised over .action, which comes later. */
.ticket-more > .ticket-more__item {
  border: 0;
  border-radius: 0;
  padding: 0;
  background: none;
}

.ticket-more > .ticket-more__item + .ticket-more__item,
.ticket-more > .ticket-more__link + .ticket-more__item {
  border-top: 1px solid var(--color-border-subtle);
  padding-top: var(--space-2);
}

.ticket-more__item > .action {
  border: 0;
  padding: 0 0 var(--space-4);
  background: none;
}

/* What ends the ticket comes last, set apart, in the danger colour (A-4). */
.ticket-more > .ticket-more__item.ticket-more__item--danger {
  margin-top: var(--space-2);
  border-top: 2px solid var(--color-border);
  padding-top: var(--space-3);
}

.ticket-more__item--danger > .action__summary .action__title {
  color: var(--status-danger-fg);
}

.ticket-more__link {
  margin: 0;
  min-height: var(--row-compact);
  display: flex;
  align-items: center;
}

/* Start work: how the work is done, then the button that commits it. */
.ticket-start {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-4);
  margin: 0;
}

.ticket-start__mode {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.ticket-start__mode .select {
  width: auto;
  min-width: 11rem;
  max-width: 100%;
}

/* The SLA chip (ENG-06), toned as Jira Service Management does: plain with
   more than an hour left, grey within the hour, amber within half an hour,
   red once the deadline passed; a dashed border while a wait stops it, a
   dotted one while its time is not known. A clock that ended: green when
   kept, red when late, neutral when cancelled or ended without a verdict.
   The words carry it too. A row's chip stays one line: it says a pause
   without its reason, which the header and the SLA card give (review
   2026-10-17); the header's own chips wrap when the line is too short. */
.sla-chip {
  font-variant-numeric: tabular-nums;
}

.sla-chip--calm {
  color: var(--color-text);
  background: var(--color-surface);
  border-color: var(--color-border);
}

.sla-chip--soon {
  color: var(--status-neutral-fg);
  background: var(--status-neutral-bg);
}

.sla-chip--near {
  color: var(--status-warning-fg);
  background: var(--status-warning-bg);
}

.sla-chip--late {
  color: var(--status-danger-fg);
  background: var(--status-danger-bg);
}

.sla-chip--paused {
  color: var(--status-info-fg);
  background: var(--status-info-bg);
  border-style: dashed;
}

.sla-chip--unknown {
  color: var(--status-unknown-fg);
  background: var(--status-unknown-bg);
  border-style: dotted;
}

.sla-chip--met {
  color: var(--status-success-fg);
  background: var(--status-success-bg);
}

.sla-chip--cancelled,
.sla-chip--ended {
  color: var(--status-neutral-fg);
  background: var(--status-neutral-bg);
}

/* The SLA card: a line per clock, each under its own small heading. */
.ticket-sla .sla-line + .sla-line {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-border-subtle);
}

.sla-line__title {
  font-size: var(--text-md);
  margin: 0 0 var(--space-3);
}

.entity-header .entity-header__meta {
  gap: var(--space-3) var(--space-4);
}

.entity-header .entity-header__meta .chip {
  min-width: 0;
  max-width: 100%;
  white-space: normal;
}

.entity-header .entity-header__meta .chip__glyph {
  flex: 0 0 auto;
}

.entity-header .entity-header__meta .chip span:last-child {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Key facts beside a record's name (an organization's legal form and field
   of activity): plain words after the chips, a middle dot between them that
   ends a line rather than starting the next one when a phone wraps them. */
.entity-header__fact {
  min-width: 0;
  color: var(--color-text-muted);
  overflow-wrap: anywhere;
}

.entity-header__fact:not(:last-child)::after {
  content: "·";
  padding-left: var(--space-3);
  color: var(--color-text-faint);
}

a.entity-header__fact {
  color: var(--color-accent);
  font-weight: 500;
}

.ticket-detail__grid > .card {
  min-width: 0;
}

.ticket-detail__grid .kv__value .chip {
  min-width: 0;
  max-width: 100%;
  white-space: normal;
}

.ticket-detail__grid .kv__value .chip span:last-child {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* A note's and an activity line's chips wrap inside their card: the
   delivery chip of a public reply whose e-mail was held back runs to a
   sentence, and on a 390 px phone it made the whole ticket page 653 px
   wide (role walk verification 2026-10-08). */
.note__meta .chip,
.note__foot .chip,
.timeline__what .chip {
  min-width: 0;
  max-width: 100%;
  white-space: normal;
}

.note__meta .chip span:last-child,
.note__foot .chip span:last-child,
.timeline__what .chip span:last-child {
  min-width: 0;
  overflow-wrap: anywhere;
}

.ticket-detail {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Company and ticket sections share native URL navigation. The small scoped
   enhancement switches the already rendered panels without discarding forms. */
.entity-sections,
[data-entity-panel] {
  min-width: 0;
}

.entity-tabs {
  margin: var(--space-4) 0 var(--space-5);
  border-bottom: 1px solid var(--color-border);
}

.entity-tabs__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  min-width: 0;
}

.entity-tabs__link {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  min-width: 0;
  max-width: 100%;
  padding: var(--space-2) var(--space-3);
  border-bottom: 3px solid transparent;
  color: var(--color-text-muted);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.entity-tabs__link:hover {
  color: var(--color-accent);
  background: var(--color-accent-tint);
}

.entity-tabs__link[aria-current="page"] {
  border-bottom-color: var(--color-accent);
  color: var(--color-accent);
  font-weight: 600;
}

[data-entity-panel][hidden] {
  display: none;
}

/* A display number, code or period is one value: it never breaks at its
   hyphen ("INC-" over "000001", visual QA 2026-10-16) - also the number
   that leads a link ("INC-000001 პრინტერი არ ბეჭდავს"). */
.identifier {
  font-family: var(--font-mono);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  white-space: nowrap;
}

a.mono,
.nowrap,
a > span.mono:first-child {
  white-space: nowrap;
}

/* ---------------------------------------------------------------- key/value */

.kv {
  margin: 0;
  display: grid;
  gap: var(--space-3);
}

.kv__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: var(--space-5);
  align-items: baseline;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-border-subtle);
}

.kv__key {
  color: var(--color-text-muted);
  font-weight: 500;
  font-size: var(--text-sm);
}

.kv__value {
  margin: 0;
  overflow-wrap: anywhere;
}

/* "Not recorded" reads apart by its italics; the muted colour keeps it
   legible (the faint grey was 3.0:1 on white, 2.8:1 on a subtle card). */
.kv__value--empty {
  color: var(--color-text-muted);
  font-style: italic;
}

/* What follows a list of facts in a card (a description, a "not finished"
   line, a button) starts below its last row, not on its rule. A form's
   grid gap already spaces its own children. */
:is(.card, .action, details) > .kv + :not(.kv__aside) {
  margin-top: var(--space-4);
}

/* One muted line under a list of facts: what is not recorded yet, and where
   to add it, instead of a row for each. */
.kv__aside {
  margin: var(--space-4) 0 0;
  font-size: var(--text-sm);
}

/* ---------------------------------------------------------------- chips */

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-3);
  min-height: 22px;
  border-radius: var(--radius-pill);
  border: 1px solid currentColor;
  font-size: var(--text-xs);
  font-weight: 500;
  white-space: nowrap;
  vertical-align: middle;
}

/* Razor trims the whitespace between an element and the chip after it, so
   in running content (a table cell, a list item, a heading) the chip touched
   the name before it ("GAMBIT• შიდა"). Flex rows keep their own gap. Only an
   inline neighbour on the same line: a chip that starts a line below a block
   (a milestone's line, a cell's second row) stays flush with it. */
:is(td, th, li, p, dd, dt, h1, h2, h3, h4, label, legend, summary) > :is(a, span, strong, em, b, code, time, abbr, small) + .chip {
  margin-inline-start: var(--space-3);
}

.chip__glyph {
  font-weight: 700;
  font-family: var(--font-mono);
}

.chip--danger {
  color: var(--status-danger-fg);
  background: var(--status-danger-bg);
}

.chip--warning {
  color: var(--status-warning-fg);
  background: var(--status-warning-bg);
}

.chip--success {
  color: var(--status-success-fg);
  background: var(--status-success-bg);
}

.chip--info {
  color: var(--status-info-fg);
  background: var(--status-info-bg);
}

.chip--neutral {
  color: var(--status-neutral-fg);
  background: var(--status-neutral-bg);
}

.chip--unknown {
  color: var(--status-unknown-fg);
  background: var(--status-unknown-bg);
  border-style: dotted;
}

.chip--stale {
  color: var(--status-stale-fg);
  background: var(--status-stale-bg);
  border-style: dashed;
}

.chip--muted {
  color: var(--status-muted-fg);
  background: var(--status-muted-bg);
  text-decoration: line-through;
}

/* ---------------------------------------------------------------- banners */

.banner {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-4) var(--space-5);
  border: 1px solid currentColor;
  border-radius: var(--radius-md);
  margin-bottom: var(--space-5);
}

.banner__glyph {
  font-family: var(--font-mono);
  font-weight: 700;
}

.banner__body {
  min-width: 0;
  overflow-wrap: anywhere;
}

.banner__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-base);
  font-weight: 700;
}

.banner__message {
  margin: 0;
}

.banner__errors {
  margin: var(--space-3) 0 0;
  padding-inline-start: var(--space-5);
}

.banner__errors a {
  color: inherit;
  font-weight: 600;
}

.banner--danger {
  color: var(--status-danger-fg);
  background: var(--status-danger-bg);
}

.banner--success {
  color: var(--status-success-fg);
  background: var(--status-success-bg);
}

.banner--info {
  color: var(--status-info-fg);
  background: var(--status-info-bg);
}

/* ---------------------------------------------------------------- forms */

/* One column that may be narrower than its widest item: a recipient table
   in the reply composer widened a 390 px phone page to 678 px. Wide content
   scrolls inside its own .table-wrap instead. */
.form {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  max-width: 640px;
}

.form--inline {
  max-width: none;
}

/* A form laid out in columns (intake: the ticket beside the customer's
   context) uses the page's width; 640 px squeezed its selects to a word. */
.form--wide {
  max-width: none;
}

/* A form whose long choices sit beside a narrow companion (an organization's
   legal form beside its identification number) needs a little more room. */
.form--medium {
  max-width: 48rem;
}

/* Content-sized controls (organization form, 2026-10-15): a control is as
   wide as what it holds - a count, a 9- or 11-digit code, a person's name, a
   long label - so a form reads as one sequence instead of a wall of equal
   boxes. The extra width of a number field is room for its arrows. On a
   phone every control takes the full width again. */
.input--w-xs { max-width: calc(10ch + 2 * var(--space-4) + 2px); }
.input--w-s { max-width: calc(14ch + 2 * var(--space-4) + 2px); }
.input--w-m { max-width: 22rem; }
.input--w-l { max-width: 32rem; }

/* The search box a long list gets (entity-sections.js puts it right before
   the select) is as wide as the select it filters. */
.choice-search:has(+ .input--w-xs) { max-width: calc(10ch + 2 * var(--space-4) + 2px); }
.choice-search:has(+ .input--w-s) { max-width: calc(14ch + 2 * var(--space-4) + 2px); }
.choice-search:has(+ .input--w-m) { max-width: 22rem; }
.choice-search:has(+ .input--w-l) { max-width: 32rem; }

@media (max-width: 40rem) {
  .input--w-xs,
  .input--w-s,
  .input--w-m,
  .input--w-l,
  .choice-search {
    max-width: none;
  }
}

/* Fields that belong together - who a company is, how to reach it, who
   looks after it - keep the form's own rhythm inside, and twice that
   between groups, so the groups read apart (T-1). */
.form__group {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  min-width: 0;
}

.form__group + .form__group {
  margin-top: var(--space-5);
}

/* Short fields of one fact side by side (an organization's employee and
   computer counts): each as wide as its label, a clear gap apart, stacked
   on a phone. */
.form__inline {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-5) var(--space-8);
  min-width: 0;
}

.form__inline > .field {
  flex: 0 1 auto;
}

@media (max-width: 40rem) {
  .form__inline > .field {
    flex-basis: 100%;
  }
}

.form__row {
  align-items: stretch;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, max(12rem, calc((100% - var(--space-5)) / 2))), 1fr));
  column-gap: var(--space-5);
  row-gap: 0;
  margin-bottom: calc(-1 * var(--space-5));
}

/* In a half-width action box two 13 rem columns cut a select's chosen text
   with no ellipsis ("ლაშა გელაშვილი — ღია ბილ"): a pair there sits side by
   side only from 16 rem a column, else one under the other. The one-column
   rules for a phone and for no shared tracks name it too: this selector's
   weight overrode them. */
.action .form__row {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, max(16rem, calc((100% - var(--space-5)) / 2))), 1fr));
}

/* The four shared tracks align complete controls even when a sibling's
   label, hint or error wraps. Each wrapped pair starts its own tracks. */
.form__row > .field,
.form__row > .filter-actions {
  display: grid;
  grid-row: span 4;
  grid-template-rows: auto auto auto auto;
  gap: 0;
  margin-bottom: var(--space-5);
}

@supports (grid-template-rows: subgrid) {
  .form__row > .field,
  .form__row > .filter-actions {
    grid-template-rows: subgrid;
  }
}

@supports not (grid-template-rows: subgrid) {
  .form__row,
  .action .form__row { grid-template-columns: minmax(0, 1fr); }
}

.form__row > .field > .field__label {
  grid-row: 1;
  padding-bottom: var(--space-2);
}

.form__row > .field > .field__control,
.form__row > .filter-actions > .filter-actions__controls {
  grid-row: 2;
  align-self: start;
  min-width: 0;
}

.form__row > .field > .field__hint {
  grid-row: 3;
  padding-top: var(--space-2);
}

.form__row > .field > .field__error {
  grid-row: 4;
  padding-top: var(--space-2);
}

/* A wide field with a narrow companion on one row (the legal form and its
   identification number); one column again where the two would not fit.
   Each keeps its own rows: the number's two-line hint does not push the
   legal form's error away from its select. */
.form__row--wide-narrow {
  grid-template-columns: minmax(0, 1fr) minmax(0, 17rem);
  align-items: start;
}

.form__row--wide-narrow > .field {
  grid-row: auto;
  grid-template-rows: none;
}

@media (max-width: 40rem) {
  .form__row--wide-narrow { grid-template-columns: minmax(0, 1fr); }
}

/* Independent visit commands contain whole forms, rather than fields.
   Their handlers and their internal reading order stay independent. */
.form__row--groups {
  align-items: start;
  row-gap: var(--space-5);
  margin-bottom: 0;
}

.form__actions {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  align-items: center;
}

/* The original save/cancel controls remain available during long entry. */
.form--assisted > .form__actions:last-child {
  position: sticky;
  bottom: 0;
  z-index: 2;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border-subtle);
  padding-block: var(--space-4);
  margin-top: var(--space-4);
}

/* On a phone three actions wrap into three rows: a bar of about 170 px
   (a fifth of the screen) covered the form the whole time. It stays at
   the form's end there instead. */
@media (max-width: 40rem) {
  .form--assisted > .form__actions:last-child:has(> :nth-child(3)) {
    position: static;
  }
}

.choice-search { margin-bottom: var(--space-2); }
.choice-search__status { margin-block: var(--space-2) 0; }

/* A connection's status and commands stay together, with checks in their
   own column. On a phone this table scrolls in its named keyboard region. */
.table--connections {
  table-layout: fixed;
  min-width: 52rem;
}

.table--connections th:first-child { width: 30%; }
.table--connections th:nth-child(2) { width: 24%; }
.table--connections th:nth-child(3) { width: 22%; }
.table--connections th:nth-child(4) { width: 24%; }

.table.table--connections td { vertical-align: top; }

.table--connections td.wrap { overflow-wrap: anywhere; }

.table--connections .chip {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
}

.table--connections td > .form__actions + .form__actions {
  margin-top: var(--space-2);
}

/* A boxed group inside a form (an invoice line) keeps the form's rhythm:
   as a plain block its description, amounts and remove button touched. */
.form > fieldset.card {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
}

.form > fieldset.card > .btn {
  justify-self: start;
}

/* A lone submit is an action, rather than a full-width grid item.
   Authentication keeps its established full-width primary action. */
.form > .btn {
  justify-self: start;
  max-width: 100%;
  white-space: normal;
}

.auth-card .form > .btn {
  justify-self: stretch;
}

/* Shared create/edit field groups keep their context visible and retain
   the same field names, validation and keyboard order. */
.form-section {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  min-width: 0;
  margin: 0;
  padding: var(--space-4) 0 0;
  border: 0;
  border-top: 1px solid var(--color-border-subtle);
}

.form-section > legend {
  padding: 0 var(--space-3) 0 0;
  font-weight: 600;
  color: var(--color-text-strong);
}

.form-disclosure {
  min-width: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
}

.form-disclosure > summary,
.form-disclosure > legend {
  cursor: pointer;
  color: var(--color-text-strong);
  font-weight: 500;
  overflow-wrap: anywhere;
}

.form-disclosure > legend {
  padding-inline: var(--space-2);
}

.form-disclosure[open] > summary {
  margin-bottom: var(--space-4);
}

.form-disclosure .form-section {
  border-top: 0;
  padding-top: 0;
}

/* What a disclosure holds keeps the form's own rhythm, on every form that
   uses it, with or without script: without this its fields followed one
   another with no space between a hint and the next label. A row's
   negative bottom margin meets the next item's top margin and cancels it,
   leaving the row's own spacing. */
.form-disclosure > :not(legend, summary) + :not(legend, summary) {
  margin-top: var(--space-5);
}

fieldset.form-disclosure > legend + * {
  margin-top: var(--space-3);
}

/* A long translated label or hint must not stretch a neighbouring input's
   painted surface or push it beyond the form's own column. */
.field {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  min-width: 0;
  gap: var(--space-2);
}

.field__control {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: var(--space-2);
  min-width: 0;
}

.field__label,
.field__hint,
.field__error {
  overflow-wrap: anywhere;
}

/* A fieldset's default minimum width is its content's: it grew to fit
   instead of letting what is inside it scroll. */
fieldset.field {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

/* A group of choices is labelled by its legend, spaced like a label. */
fieldset.field > legend.field__label {
  padding: 0;
  margin-bottom: var(--space-2);
}

.field__label {
  font-weight: 500;
  color: var(--color-text-strong);
}

.field__required {
  color: var(--status-danger-fg);
  margin-left: var(--space-1);
}

.field__hint {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* A hint used as a paragraph of its own - a page's, a card's or an action's
   lead before a form, table, empty state or button - keeps a paragraph's
   space below it (it touched the next block, visual QA 2026-10-16). Inside a
   field, form or fieldset the grid gap spaces it. */
:is(.shell-main, .card, .action, .publish-preview, .grid-2 > div) > .field__hint:not(:last-child) {
  margin-bottom: var(--space-4);
}

/* A table, an empty state, a plain list, a fold or a form followed by more
   in its card or page keeps a gap below it: a label, a heading or a hint
   touched its border. A card after a table keeps a card's distance. */
:is(.shell-main, .card) > :is(.table-wrap, .empty, .plain-list, .details, .form):not(:last-child) {
  margin-bottom: var(--space-4);
}

.table-wrap + .card {
  margin-top: var(--space-6);
}

/* A page's lead reads with its title, not a full header gap below it. */
.page-header + .field__hint {
  margin-top: calc(-1 * var(--space-3));
}

/* A secondary fact in a cell or a value (a backup's schedule, a window's
   time zone) reads on its own line: inline, Razor glued it to the text
   before it ("ასლიყოველდღე") and a squeezed cell split it mid-word
   ("Asia/Tb" over "ilisi"). */
:is(td, dd) > span.field__hint {
  display: block;
  overflow-wrap: break-word;
}

/* The field a refusal names: the words say it, the colour and the thick
   left rule only repeat it (non-colour indicator, WCAG 1.4.1). */
.field__error {
  margin: 0;
  padding-left: var(--space-2);
  border-left: 3px solid var(--status-danger-fg);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--status-danger-fg);
}

/* The password and authenticator code an access change asks for when the
   session's last confirmation is not recent. A fieldset of its own, with a
   dashed rule, so it reads as "confirm it's you", not as data about the
   account being changed. */
.stepup {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: var(--space-4) var(--space-5);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  min-width: 0;
}

.stepup__legend {
  padding: 0 var(--space-2);
  font-weight: 500;
  color: var(--color-text-strong);
}

/* A refused field: aria-invalid from FieldState, kept by the shared
   GambitInput* components (InputBase alone drops one it did not set). */
.select.select--invalid,
.select[aria-invalid="true"],
.input[aria-invalid="true"],
.textarea[aria-invalid="true"] {
  border-color: var(--status-danger-fg);
  border-width: 2px;
}

.input,
.select,
.textarea {
  min-width: 0;
  font: inherit;
  font-size: var(--text-md);
  line-height: var(--leading-base);
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  min-height: max(var(--row-comfortable), calc(1lh + var(--space-3) + var(--space-3) + 2px));
  width: 100%;
}

.textarea {
  min-height: 96px;
  resize: vertical;
}

.input--code {
  font-family: var(--font-mono);
  letter-spacing: 0.15em;
}

.input:disabled,
.select:disabled {
  background: var(--color-surface-subtle);
  color: var(--color-text-muted);
}

.checkbox {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  min-height: var(--row-compact);
  min-width: 0;
  overflow-wrap: anywhere;
}

.checkbox input {
  flex: 0 0 18px;
  font: inherit;
  width: 18px;
  height: 18px;
  margin: 0;
  margin-top: max(0px, calc((1lh - 18px) / 2));
}

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font: inherit;
  font-weight: 500;
  min-height: 36px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--motion-fast) ease-out, color var(--motion-fast) ease-out;
}

.btn--primary {
  background: var(--color-accent);
  color: var(--color-surface);
}

.btn--primary:hover {
  background: var(--color-accent-hover);
  color: var(--color-surface);
}

.btn--secondary {
  background: var(--color-surface);
  color: var(--color-accent);
  border-color: var(--color-border);
}

.btn--secondary:hover {
  background: var(--color-accent-tint);
}

.btn--danger {
  background: var(--color-surface);
  color: var(--status-danger-fg);
  border-color: var(--status-danger-fg);
}

.btn--danger:hover {
  background: var(--status-danger-bg);
}

.btn--ghost {
  background: transparent;
  color: var(--color-text-muted);
}

.btn--ghost:hover {
  color: var(--color-text-strong);
  background: var(--color-surface-subtle);
}

.btn--block {
  width: 100%;
}

.btn--small {
  min-height: 28px;
  padding: 0 var(--space-3);
  font-size: var(--text-sm);
}

/* ---------------------------------------------------------------- tables */

/* Positioned, so it is also the containing block of what a table holds
   absolutely - the visually hidden "actions" header label: with none, that
   label escaped the scroll box and widened the catalogue page to 668 px on a
   390 px phone (browser check 2026-10-02). */
.table-wrap {
  position: relative;
  overflow-x: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  /* Whole words define a readable minimum width. The named, focusable
     frame carries any overflow, including inside a card on a phone. */
  overflow-wrap: normal;
}

/* Readable, report and daily-work tables keep whole words at enlarged text. Their natural minimum
   width scrolls inside the existing frame instead of splitting every glyph. */
.table--readable,
.report-section .table,
.mywork-table {
  overflow-wrap: normal;
}

.report-section .grid-2 > div {
  min-width: 0;
}

.table caption {
  text-align: left;
  padding: var(--space-4) var(--space-5);
  color: var(--color-text-muted);
  caption-side: top;
}

.table th,
.table td {
  text-align: left;
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--color-border-subtle);
  height: var(--row-compact);
  vertical-align: middle;
}

/* Below 1280 px a dense table (eight or nine columns) keeps 12 px beside
   each cell, so its last column stays on a 1024 px screen instead of behind
   a sideways scroll; from 1280 px cells keep 16 px. The caption keeps the
   cells' inset, so it starts over the first column. */
@media (max-width: 1279px) {
  .table caption,
  .table th,
  .table td {
    padding-inline: var(--space-4);
  }
}

/* Not sticky: every table sits in a .table-wrap, which is its own scroll
   container, so a header held at the shell's height slid down over the
   first row instead (the intake match, the edit conflict's Title row). */
.table th {
  background: var(--color-surface-subtle);
  color: var(--color-text-muted);
  font-weight: 500;
}

.table tbody tr:hover {
  background: var(--color-accent-tint);
}

.table td a {
  font-weight: 500;
}

/* A number column: right-aligned with even figures. The header keeps the
   interface font - the monospace stack has no Georgian, so a Georgian
   header fell back to another face - and a value never splits across
   lines ("4,680.00" over "GEL", "0 სთ 0" over "წთ"). */
.table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.table td.num {
  font-family: var(--font-mono);
  white-space: nowrap;
}

/* A count's explanation beside it may wrap; the number itself does not. */
.table td.num > .muted {
  white-space: normal;
}

.table a[href^="tel:"] {
  white-space: nowrap;
}

.table .pre-wrap {
  overflow-wrap: normal;
}

.table--wide td {
  white-space: nowrap;
}

/* Free-text cells of a wide table may wrap, so the columns that matter -
   result, details - stay on screen at desktop width. */
.table--wide td.wrap {
  white-space: normal;
  /* 12 rem on a phone screen (after the queue's phone rules below). */
  min-width: 7rem;
}

/* A status with its reason ("შეჩერდა: კონტაქტი ჯერ არ არის ვერიფიცირებული
   და უფლებამოსილი") wraps inside a wrapping cell instead of widening the
   table by 460 px; a short status still reads on one line. */
.table--wide td.wrap .chip {
  white-space: normal;
  /* Half the one-line chip's height (24 px with this padding): a pill on
     one line, a rounded box when it wraps. */
  border-radius: 12px;
  align-items: flex-start;
  padding-block: var(--space-1);
}

/* Expanded audit evidence is prose and key/value detail. Keep it readable
   inside the keyboard-scrollable table instead of inheriting a single line.
   Closed, the column needs only its summary's width. */
.audit-details-cell .details {
  white-space: normal;
}

.audit-details-cell .details[open],
.table--wide td.wrap > .details[open] {
  width: min(22rem, calc(100vw - 6rem));
}

/* A fold in a table cell draws its marker as text joined to the first word
   by a no-break space: squeezed to its longest word, the browser's marker
   stood alone above "დეტალების" / "ჩვენება" in every row. On one line the
   summary widened the audit table past a 1024 px screen; now it reads
   "▸ დეტალების" / "ჩვენება" at most. The marker is not read aloud. */
.table td > .details > summary {
  list-style: none;
}

.table td > .details > summary::-webkit-details-marker {
  display: none;
}

.table td > .details > summary::before {
  content: "▸\00a0";
  content: "▸\00a0" / "";
  color: var(--color-text-muted);
}

.table td > .details[open] > summary::before {
  content: "▾\00a0";
  content: "▾\00a0" / "";
}

.audit-details-cell .kv__key {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------- toolbar / search */

/* The queue views above the filter bar: links, wrapping on a phone. */
.queue-views {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.queue-views__count {
  font-family: var(--font-mono);
  color: var(--color-text-muted);
}

/* The person's own day on top of the queue: one wrapping line, not a card. */
.my-work-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
}

.my-work-strip__title {
  font-size: var(--text-base);
  margin: 0;
}

.my-work-strip__item {
  margin-left: var(--space-2);
}

/* What waits on the reader's decision, above the queue they land on, marked
   as the dashboard's card is (role walk 2026-10-08, V2-MGR-08). */
.waiting-strip {
  border: 2px solid var(--status-danger-fg);
}

.toolbar {
  display: flex;
  gap: var(--space-3);
  align-items: flex-end;
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}

.toolbar .field {
  min-width: 200px;
}

.toolbar .btn {
  min-height: var(--row-comfortable);
}

/* Regular filter forms align label, control, hint and error independently.
   A wrapped set starts a fresh set of tracks; optional hints never shift a
   sibling's control or its actions. Navigation/search toolbars keep their
   existing layout. */
.toolbar--filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16em), 1fr));
  column-gap: var(--space-3);
  row-gap: 0;
  align-items: stretch;
  container-type: inline-size;
}

/* An action pair takes two tracks where the bar has two, so "Filter" and
   "Clear" stay side by side; in one 16em track the Georgian pair stacked
   (dead letters, visual QA 2026-10-16). A single button keeps one track:
   two left an empty track beside it and narrowed the fields. One track (a
   phone, the stacked fallback below): it keeps that track. */
@supports (grid-template-rows: subgrid) {
  @container (min-width: 33em) {
    .toolbar--filters > .filter-actions:has(> .filter-actions__controls > :nth-child(2)) {
      grid-column: span 2;
    }
  }
}

.toolbar--filters > .field,
.toolbar--filters > .filter-actions,
.toolbar--filters > .filter-toggle {
  display: grid;
  grid-row: span 4;
  grid-template-rows: auto auto auto auto;
  gap: 0;
  min-width: 0;
  margin-bottom: var(--space-3);
}

@supports (grid-template-rows: subgrid) {
  .toolbar--filters > .field,
  .toolbar--filters > .filter-actions,
  .toolbar--filters > .filter-toggle {
    grid-template-rows: subgrid;
  }
}

/* A browser without shared tracks stacks complete fields/actions in reading
   order rather than approximating alignment with independent label heights. */
@supports not (grid-template-rows: subgrid) {
  .toolbar--filters { grid-template-columns: minmax(0, 1fr); }
}

.toolbar--filters > .field > .field__label {
  grid-row: 1;
  padding-bottom: var(--space-2);
}

/* A wrapped action pair may need another line, but the first control keeps
   its own usable height instead of stretching sibling inputs into blanks. */
.toolbar--filters > .field > .field__control,
.toolbar--filters > .filter-actions > .filter-actions__controls,
.toolbar--filters > .filter-toggle > .checkbox {
  grid-row: 2;
  align-self: start;
  min-width: 0;
  min-height: var(--touch-target);
}

.toolbar--filters > .field > .field__control > .input,
.toolbar--filters > .field > .field__control > .select {
  width: 100%;
  min-height: max(var(--touch-target), calc(1lh + var(--space-3) + var(--space-3) + 2px));
}

.toolbar--filters > .field > .field__hint {
  grid-row: 3;
  padding-top: var(--space-2);
}

.toolbar--filters > .field > .field__error {
  grid-row: 4;
  padding-top: var(--space-2);
}

.filter-actions__controls {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  align-content: start;
  gap: var(--space-3);
}

.toolbar--filters .filter-actions__controls > .btn {
  font-size: var(--text-md);
  min-height: max(var(--touch-target), calc(1lh + var(--space-3) + var(--space-3) + 2px));
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
  white-space: normal;
}

.toolbar--filters > .filter-toggle > .checkbox {
  align-items: center;
}

.toolbar--filters > .filter-toggle > .checkbox > input {
  margin-top: 0;
}

/* A search field's action belongs beside its input, above the shared hint.
   The input uses available width and wraps the action on a narrow screen. */
.toolbar--search {
  margin-bottom: 0;
}

.toolbar--search .input {
  flex: 1 1 14rem;
  min-width: 0;
}

.toolbar--search .btn {
  flex-shrink: 0;
}

/* The queue gives the problem title space first. Six columns: the age reads
   under the number and a waiting ticket's next review under its state, so
   the queue fits a 1024 px screen without a sideways scroll (visual QA
   2026-10-16: eight columns needed 1225 px in Georgian). */
.table--queue .queue-title { width: 36%; min-width: 14rem; }
.table--queue .queue-customer { width: 22%; }
.table--queue .queue-owner { width: 20%; }
/* The number, state and priority take what their chips need; the room left
   goes to the title, the customer and the owner, which wrap. */
.table--queue .queue-number,
.table--queue .queue-state,
.table--queue .queue-priority { width: 1%; }
.table--queue td.queue-number { white-space: nowrap; }
/* A short date and clock time (the full instant is its title): one value. */
.table--queue .queue-review time { white-space: nowrap; }

/* A second chip in a cell (the SLA standing under the priority, "review
   due" under the state) reads on its own line, flush with the first and a
   small gap below it; inline, it wrapped indented by the chip gap and
   touching the chip above (visual QA review 2026-10-17). */
.table--queue .queue-stacked { margin-top: var(--space-2); }

/* The title link carries the gap to its "internal" chip at its own end:
   a chip that wraps under a long title starts flush with it, where a
   start margin indented it by the gap. */
.table--queue .queue-title > a:has(+ .chip) { margin-inline-end: var(--space-3); }
.table--queue .queue-title > a + .chip { margin-inline-start: 0; }

/* On a phone the queue keeps the number and the title; the state, priority,
   SLA standing and owner read under the title instead of six columns that
   needed a sideways scroll (role walk 2026-10-07: at 390 px only the number
   and the title showed). A screen only: print keeps every column. */
.table--queue .queue-compact { display: none; }

@media screen and (max-width: 767px) {
  .table--queue col:nth-child(n+3),
  .table--queue th:nth-child(n+3),
  .table--queue td:nth-child(n+3) {
    display: none;
  }

  .table--queue caption,
  .table--queue th,
  .table--queue td {
    padding-inline: var(--space-3);
  }

  /* The number stays level with the title's first line, not mid-row. */
  .table--queue td {
    vertical-align: top;
  }

  .table--queue .queue-title {
    width: auto;
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .table--queue .queue-compact {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin-top: var(--space-2);
    font-size: var(--text-xs);
  }

  .table--queue .queue-compact .chip {
    white-space: normal;
  }
}

/* A wide table's wrapping cells (above): on a phone the table scrolls
   sideways in its frame anyway, so a wider column keeps a row to two or
   three lines instead of five to seven beside blank space (the audit page
   was 66% longer at 7 rem). A screen only: on paper the table cannot
   scroll and keeps 7 rem. */
@media screen and (max-width: 767px) {
  .table--wide td.wrap {
    min-width: 12rem;
  }
}

/* The queue's filters fold under one "Filters" line on a phone, open while
   a filter is set, so the first screen holds the rows (role walk
   verification 2026-10-08). From 768 px the line is hidden and the form
   shows as before, closed or open; a browser that cannot show a closed
   fold's content keeps the line there, one press away. */
.queue-filters > .queue-filters__summary {
  cursor: pointer;
  margin: 0 0 var(--space-3);
  font-weight: 600;
}

@media screen and (min-width: 768px) {
  @supports selector(::details-content) {
    .queue-filters > .queue-filters__summary {
      display: none;
    }

    .queue-filters::details-content {
      display: block;
      content-visibility: visible;
    }
  }
}

/* My work on a phone, as the queue: each row keeps its title and its next
   step, and its priority, SLA flag, state, customer - for a visit its time,
   place and whom to call - read under the title. The action sat beyond a
   sideways scroll in every table (role walk verification 2026-10-08). A
   screen only: print keeps every column. */
.mywork-table .mywork-compact { display: none; }

@media screen and (max-width: 767px) {
  .mywork-table .mywork-wide {
    display: none;
  }

  .mywork-table th,
  .mywork-table td {
    padding-left: var(--space-3);
    padding-right: var(--space-3);
    vertical-align: top;
  }

  .mywork-table .mywork-title {
    overflow-wrap: anywhere;
  }

  .mywork-table .mywork-compact {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin-top: var(--space-2);
    font-size: var(--text-xs);
  }

  .mywork-table .mywork-compact .chip {
    white-space: normal;
  }

  .mywork-table .mywork-compact .reach {
    margin: 0;
  }
}

/* A visit's set-off with a running timer asks for the timer's words: they
   take a row of their own under the visit, across the whole table, read as
   part of it. Beside the title a phone squeezed them into a 125 px column
   and broke "billable" mid-word (role walk verification 2026-10-08). */
.mywork-table tr:has(+ .mywork-setoff) > td {
  border-bottom: 0;
}

.mywork-table .mywork-setoff > td {
  padding-top: 0;
}

.mywork-table .mywork-setoff .form--inline {
  max-width: 40rem;
}

/* ---------------------------------------------------------------- billing and ledger on a phone */

/* Role walk 2026-10-08 (V-MGR-15): at 390 px the billing and ledger tables
   showed the month, the customer and the record count and scrolled the
   hours, export and lock off-screen. As the queue does, below 768 px a row
   keeps its first columns and reads the rest under them. A screen only:
   print keeps every column. The locked month's entries do the same, and
   a month or a contract number never breaks at its hyphen ("2026-" over
   "09"; role walk 2026-10-08, V2-MGR-04 and V2-MGR-11). */
.billing-compact { display: none; }

@media screen and (max-width: 767px) {
  #billing-table th:nth-child(n+3),
  #billing-table td:nth-child(n+3),
  #ledger-entry-table th:nth-child(2),
  #ledger-entry-table td:nth-child(2),
  #ledger-entry-table th:nth-child(n+4),
  #ledger-entry-table td:nth-child(n+4),
  #batch-entry-table th:nth-child(n+3),
  #batch-entry-table td:nth-child(n+3) {
    display: none;
  }

  #billing-table th,
  #billing-table td,
  #ledger-entry-table th,
  #ledger-entry-table td,
  #batch-entry-table th,
  #batch-entry-table td {
    padding-left: var(--space-3);
    padding-right: var(--space-3);
    vertical-align: top;
  }

  #billing-table th:first-child,
  #billing-table td:first-child,
  #billing-table .identifier,
  #batch-entry-table .identifier {
    white-space: nowrap;
  }

  .billing-compact {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1) var(--space-3);
    margin-top: var(--space-2);
  }
}

/* The once-shown approval link (role walk 2026-10-08, V-MGR-11): the field
   spans the card; on a phone, which cuts the field off and has no Ctrl+A,
   the whole link wraps below it and one long press selects all of it. */
#issued-url {
  width: 100%;
  max-width: none;
}

.issued-url-whole { display: none; }

@media screen and (max-width: 767px) {
  .issued-url-whole {
    display: block;
    margin-top: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    overflow-wrap: anywhere;
    -webkit-user-select: all;
    user-select: all;
  }
}

/* ---------------------------------------------------------------- misc */

.empty {
  padding: var(--space-9) var(--space-5);
  text-align: center;
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
}

.empty__title {
  color: var(--color-text-strong);
  font-weight: 500;
}

.outcome {
  max-width: 640px;
}

.outcome__correlation {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.pager {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin-top: var(--space-5);
  flex-wrap: wrap;
}

.pager__summary {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  margin: var(--space-5) auto 0 0;
}

.pager .pager__summary {
  margin: 0 auto 0 0;
}

.steps {
  padding-left: var(--space-6);
}

.steps li {
  margin-bottom: var(--space-4);
}

.qr {
  width: 200px;
  max-width: 100%;
  margin: var(--space-4) 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

.qr svg {
  display: block;
  width: 100%;
  height: auto;
}

.key {
  font-size: var(--text-md);
  letter-spacing: 0.1em;
  overflow-wrap: anywhere;
}

.code-list {
  columns: 2;
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-5);
  font-size: var(--text-md);
}

.code-list li {
  padding: var(--space-2) 0;
}

.details {
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-top: var(--space-3);
}

.details summary {
  cursor: pointer;
  font-weight: 500;
}

.actions-list {
  display: grid;
  gap: var(--space-4);
}

.muted {
  color: var(--color-text-muted);
}

.text-sm {
  font-size: var(--text-sm);
}

/* ---------------------------------------------------------------- timeline (A.4 #4) */

.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 2px solid var(--color-border);
}

.timeline__entry {
  position: relative;
  padding: var(--space-2) 0 var(--space-4) var(--space-6);
}

.timeline__entry::before {
  content: "";
  position: absolute;
  left: -7px;
  top: 10px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--color-surface);
  border: 2px solid var(--color-accent);
}

/* Notes in the merged activity keep the notes' colours: internal and public never look alike. */
.timeline__entry--internal::before {
  border-color: var(--status-warning-fg);
  background: var(--status-warning-bg);
}

.timeline__entry--public::before {
  border-color: var(--status-info-fg);
  background: var(--status-info-bg);
}

.timeline__time {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* What happened, then its visibility and delivery chips: Razor writes no
   space between the text and the chips, so the row's gap separates them;
   a long delivery chip wraps flush left on a phone. */
.timeline__what {
  font-weight: 500;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
}

.timeline__reason {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  margin: var(--space-1) 0 0;
}

.action-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
}

/* Whole command forms opt into at most two readable columns. Font-relative
   minimums stack them as available width or enlarged text requires. */
.action-grid--responsive {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, max(26rem, calc((100% - var(--space-5)) / 2))), 1fr));
  align-items: start;
}

.action {
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
}

/* Action boxes stacked in a card (start a timer, log time; an asset, a
   credential) keep a gap instead of touching border to border. An
   .action-grid spaces its own. */
.card > .action + .action,
.card > :is(form, .form, p, .hints, .notes, ol, ul) + .action {
  margin-top: var(--space-4);
}

/* A link line under a lone button in a card sits below it, not on it. */
.card > .btn + p.field__hint {
  margin-top: var(--space-3);
}

.action__title {
  font-size: var(--text-base);
  font-weight: 600;
  margin: 0 0 var(--space-3);
}

.action--visible {
  min-width: 0;
  padding: var(--space-5);
  background: var(--color-surface);
  border-color: var(--color-border);
}

.action--visible > .action__title {
  font-size: var(--text-md);
  margin-bottom: var(--space-4);
}

.action.action--visible .form {
  gap: var(--space-4);
}

.action--danger {
  border-color: var(--status-danger-fg);
  border-inline-start-width: 3px;
}

.action--danger > .action__title {
  color: var(--status-danger-fg);
}

/* A folded action is one line: its title is the summary (a heading still,
   for heading navigation), the form stays in the page. Keyboard: the
   summary is focusable and Enter or Space unfolds it. */
.action__summary {
  cursor: pointer;
  min-height: var(--row-compact);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  list-style: none;
}

.action__summary .action__title {
  display: inline;
  margin: 0;
}

.action__summary::-webkit-details-marker {
  display: none;
}

.action__summary::before {
  content: "▸";
  color: var(--color-text-muted);
}

details.action[open] > .action__summary::before {
  content: "▾";
}

details.action[open] > .action__summary {
  margin-bottom: var(--space-3);
}

.action__summary:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* Keep the delivery outcome visible on a phone, before the recipient details.
   The list lays its rows out by its own width, not the screen's: in a
   half-width action card the four columns were 50-146 px wide and split
   plain words ("ხარაიშვი" over "ლი", visual QA 2026-10-16). */
.recipient-list {
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  container-type: inline-size;
}

.recipient-list__caption {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.recipient-list__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  margin: 0;
  padding: var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
}

/* One row per recipient when the list has room for four readable columns.
   After the one-column rule above: a container query adds no specificity,
   so placed before it the four columns never applied. */
@container (min-width: 48rem) {
  .recipient-list__item {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, .65fr);
  }
}

.recipient-list__field {
  min-width: 0;
}

.recipient-list__field dt {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.recipient-list__field dd {
  margin: var(--space-1) 0 0;
  overflow-wrap: anywhere;
}

.recipient-list .chip {
  max-width: 100%;
  align-items: flex-start;
  padding-block: var(--space-1);
  border-radius: var(--radius-md);
  white-space: normal;
}

.recipient-list .chip span:last-child {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* What a preview row lacks and where it is set: under its outcome. */
.recipient-fix {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  white-space: normal;
}

.action .form {
  gap: var(--space-3);
}

.conflict {
  border: 1px solid var(--status-danger-fg);
  background: var(--status-danger-bg);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
}

.conflict__title {
  color: var(--status-danger-fg);
  font-size: var(--text-lg);
  margin-bottom: var(--space-3);
}

/* ---------------------------------------------------------------- calendars */

/* A group of radio buttons or checkboxes with its legend: no box, the
   form's own spacing. */
.fieldset {
  border: 0;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}

/* The legend lines up with the labels under it (the browser insets it). */
.fieldset > legend {
  padding: 0;
}

/* A group of whole fields (a checklist's notes, a schedule, conditions)
   spaces them as a form does; the 4 px gap is for a list of choices. */
.fieldset:has(> .field, > .form__row) {
  gap: var(--space-5);
}

/* A choice's explanation belongs to its own radio or checkbox: it sits
   under the choice's text, closer to it than to the next choice. The
   label keeps a 24 px target (WCAG 2.5.8) rather than the 32 px row. */
.fieldset > .checkbox:has(+ .field__hint) {
  min-height: 24px;
}

.fieldset > .checkbox + .field__hint {
  padding-inline-start: calc(18px + var(--space-3));
  margin-bottom: var(--space-3);
}

/* The seven day checkboxes: one row that wraps on a phone. */
.checkbox-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
}

/* An ordered scale (a 5-to-1 rating) reads as one column in its order;
   wrapped into a row it broke into "5" / "4 3" / "2" / "1" on a phone. */
.checkbox-row--scale {
  flex-direction: column;
}

/* Business hours and holidays (2026-10-16): what the hours are for reads
   at prose width; the week, the holidays and the history read as short
   lines in words, not as a version table. */
.calendar-lead {
  max-width: 70ch;
}

.calendar-table__name {
  font-weight: 500;
}

/* A run of days and its hours stays on one line; runs wrap between them. */
.calendar-table__hours-part {
  white-space: nowrap;
}

/* On a phone a row reads as one block under the name (the queue's pattern):
   the other columns sat beyond a sideways scroll. A screen only. */
.calendar-table__compact {
  display: none;
}

@media screen and (max-width: 767px) {
  .calendar-table .calendar-table__wide {
    display: none;
  }

  .calendar-table__compact {
    display: grid;
    justify-items: start;
    gap: var(--space-2);
    margin-top: var(--space-3);
    font-size: var(--text-sm);
  }

  .calendar-table__compact .chip {
    white-space: normal;
  }
}

.calendar-holiday-year + .calendar-holiday-year {
  margin-top: var(--space-5);
}

/* "Select every unconfirmed day of 2027": above its year's table, quiet. */
.calendar-holiday-year__tools {
  display: flex;
  justify-content: flex-end;
  margin-bottom: var(--space-2);
}

.calendar-holiday-table__earlier {
  margin-top: var(--space-1);
}

/* On a phone a holiday reads as one block under its date: the name, short
   hours and state sat beyond a sideways scroll. A screen only. */
.calendar-holiday-table__compact {
  display: none;
}

@media screen and (max-width: 767px) {
  .calendar-holiday-table .calendar-holiday-table__wide {
    display: none;
  }

  .calendar-holiday-table__compact {
    display: grid;
    justify-items: start;
    gap: var(--space-2);
    margin-top: var(--space-2);
  }

  .calendar-holiday-table__compact .chip {
    white-space: normal;
  }
}

/* The years' tables line up: the same column widths in each, on a phone
   too. "screen and", like the other calendar rules, keeps the shell's own
   "(min-width: 768px)" block the first of its kind. */
@media screen {
  #calendar-holidays .calendar-holiday-table {
    table-layout: fixed;
  }

  .calendar-holiday-table__pick {
    width: 3rem;
  }
}

/* On a phone the checkbox column stays narrow: its heading is said by the
   lead above the tables and by each box's own label. */
@media screen and (max-width: 767px) {
  .calendar-holiday-table__pick-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

@media screen and (min-width: 768px) {
  .calendar-holiday-table__pick {
    width: 7rem;
  }

  .calendar-holiday-table__date {
    width: 13rem;
  }

  .calendar-holiday-table__hours {
    width: 9rem;
  }

  .calendar-holiday-table__state {
    width: 12rem;
  }
}

.calendar-table td,
.calendar-holiday-table td {
  vertical-align: top;
}

/* One link above the list shows or hides the retired sets (only when there are any). */
.calendar-retired-toggle {
  display: flex;
  justify-content: flex-end;
  margin: 0 0 var(--space-3);
}

.calendar-header__summary {
  color: var(--color-text-strong);
  font-weight: 500;
}

/* The week: seven rows, a day and its hours; a day off is quieter. */
.calendar-week-view {
  width: 100%;
  max-width: 28rem;
  border-collapse: collapse;
}

.calendar-week-view th,
.calendar-week-view td {
  text-align: left;
  padding: var(--space-3) var(--space-4) var(--space-3) 0;
  border-bottom: 1px solid var(--color-border-subtle);
  font-variant-numeric: tabular-nums;
}

.calendar-week-view th {
  font-weight: 500;
  width: 45%;
}

.calendar-week-view__off th,
.calendar-week-view__off td {
  color: var(--color-text-muted);
  font-weight: 400;
}

.calendar-week-view__continuous {
  font-size: var(--text-md);
  font-weight: 500;
}

.calendar-uses li {
  display: grid;
  gap: var(--space-1);
}

.calendar-holiday-table .nowrap {
  white-space: nowrap;
}

.calendar-holiday-table__past td {
  color: var(--color-text-muted);
}

.calendar-confirm {
  display: grid;
  gap: var(--space-5);
  max-width: 40rem;
  margin-top: var(--space-5);
}

/* What to do with the days, said before them. */
.calendar-confirm__lead {
  max-width: 70ch;
  margin: var(--space-3) 0 var(--space-4);
}

/* What a scheduled change adds or drops, under the days in use. */
.calendar-holiday-changes {
  margin: var(--space-5) 0 0;
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--status-info-fg);
}

.calendar-holiday-changes__title {
  margin: 0;
  font-weight: 500;
}

.calendar-holiday-changes__title + .calendar-holiday-changes__list {
  margin: var(--space-2) 0 0;
}

.calendar-holiday-changes__list + .calendar-holiday-changes__title {
  margin-top: var(--space-3);
}

.calendar-holiday-changes__list li + li {
  margin-top: var(--space-1);
}

.calendar-confirm .form__actions {
  margin-top: 0;
}

.calendar-next-year {
  margin: var(--space-5) 0 0;
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--status-warning-fg);
}

/* The history: "from 15.10.2026: Mon-Fri 09:00-18:00", newest first. */
.calendar-history {
  list-style: none;
  margin: 0;
  padding: 0;
}

.calendar-history__item {
  display: grid;
  grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr) auto;
  gap: var(--space-2) var(--space-5);
  align-items: baseline;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--color-border-subtle);
}

.calendar-history__item:last-child {
  border-bottom: 0;
}

.calendar-history__when {
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.calendar-history__what {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}

@media (max-width: 40rem) {
  .calendar-history__item {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The week form: a day's name beside its line of hours, one row per day;
   on a phone the name sits above. */
.calendar-change .form-section + .form-section,
.calendar-change .calendar-week + .form-section,
.calendar-change .form-section + .form-disclosure {
  margin-top: var(--space-5);
}

.calendar-week__coverage {
  display: grid;
  gap: var(--space-2);
}

.calendar-week__days {
  display: grid;
  gap: var(--space-3);
}

.calendar-week__day {
  display: grid;
  grid-template-columns: 9rem minmax(0, 22rem);
  gap: var(--space-2) var(--space-4);
  align-items: baseline;
}

.calendar-week__control {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}

.calendar-week__control .input {
  font-variant-numeric: tabular-nums;
}

@media (max-width: 40rem) {
  .calendar-week__day {
    grid-template-columns: minmax(0, 1fr);
  }
}

.calendar-fill {
  display: grid;
  gap: var(--space-3);
}

.calendar-fill__buttons {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.calendar-change__check {
  font-weight: 500;
}

.calendar-change__reload {
  margin: 0 0 var(--space-5);
}

.calendar-change__scheduled {
  margin: var(--space-2) 0 0;
}

.calendar-fill-disclosure .calendar-fill {
  margin-top: var(--space-3);
}

/* The contract's SLA targets on a phone (durations, and per-target hours):
   the target reads under its priority and the field takes the rest of the
   row instead of sitting beyond a sideways scroll. */
.contract-targets-table__clock {
  display: none;
}

@media screen and (max-width: 767px) {
  .contract-targets-table {
    table-layout: fixed;
    width: 100%;
  }

  .contract-targets-table .contract-targets-table__wide {
    display: none;
  }

  .contract-targets-table th[scope="row"] {
    width: 32%;
  }

  .contract-targets-table th,
  .contract-targets-table td {
    padding-inline: var(--space-2);
  }

  .contract-targets-table .select {
    padding-left: var(--space-2);
  }

  .contract-targets-table__clock {
    display: block;
    margin-top: var(--space-1);
    font-weight: 400;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
  }
}

/* Calendar and contract target tables may be wider than a phone. Keep
   off-screen labels and headings inside each table's scroll frame. */
#hours .table-wrap,
#preview .table-wrap,
#terms .table-wrap {
  position: relative;
  max-width: 100%;
}

/* Long Georgian ticket type names must wrap within the contract scope form
   when text is enlarged on a narrow screen. */
#terms .fieldset,
#terms .checkbox {
  min-width: 0;
  overflow-wrap: anywhere;
}

#contract-cover-title,
#contract-preview-title {
  overflow-wrap: anywhere;
}

#preview .toolbar .field,
#publish .field {
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
}

#preview .toolbar .field {
  flex: 1 1 100%;
}

#preview .input,
#publish .input {
  min-width: 0;
}

#exceptions .form__row .field {
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
}

#exceptions .input,
#exceptions .select {
  min-width: 0;
}

.calendar-banner p {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* The Georgian heading has a long single word at 200% text size. */
#exceptions-title {
  overflow-wrap: anywhere;
}

/* A preview's answer in words: the sentence the operator reads first. */
.preview-answer {
  font-size: var(--text-md);
  font-weight: 500;
  color: var(--color-text-strong);
  margin: var(--space-4) 0;
}

/* In a short window an enlarged header must scroll away so every allowed
   dropdown link can be brought into view by native keyboard focus. */
@media (max-height: 40rem) {
  .shell-header { position: static; }
}

/* ---------------------------------------------------------------- responsive */

@media (max-width: 767px) {
  .grid-2,
  .form__row,
  .action .form__row {
    grid-template-columns: minmax(0, 1fr);
  }

  #exceptions .form__row {
    grid-template-columns: minmax(0, 1fr);
  }

  .kv__row {
    grid-template-columns: 1fr;
    gap: var(--space-1);
  }

  .ticket-detail__grid,
  .ticket-detail__grid .kv__row {
    grid-template-columns: minmax(0, 1fr);
  }

  .table th,
  .table td {
    height: 48px;
  }

  .btn {
    min-height: var(--touch-target);
  }

  /* Not sticky on a phone: wrapped onto several rows the shell covered
     half the screen (231 px at 390 px). It scrolls away with the page and
     stays compact while it is in view. */
  .shell-header {
    position: static;
  }

  .shell-header__inner {
    padding: var(--space-2) var(--space-4);
    gap: var(--space-2) var(--space-4);
    min-height: 0;
  }

  .shell-header__inner--nav {
    position: relative;
    padding-top: 0;
    padding-bottom: 0;
  }

  /* Portal retains its compact two-column navigation. Staff opts into
     the complete native phone menu in its scoped rules below. */
  .shell-nav {
    flex: 1 1 0;
    min-width: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0;
  }

  /* Below the brand and the tools, across the whole width. */
  .shell-search {
    order: 1;
    flex: 1 1 100%;
  }

  .shell-search .shell-search__input,
  .shell-search .shell-search__button {
    min-height: var(--touch-target);
  }

  /* The language and sign-out on the first line, the inbox and the name
     under them: in the page's order the language stood alone on a line. */
  .shell-inbox,
  .shell-user {
    order: 1;
  }

  .shell-nav__link {
    min-height: 36px;
    padding: 0 var(--space-3);
  }

  /* Nav lane: the group names scroll with the links; an open group's panel
     spans the whole width under the strip. The panel's containing block is the
     nav row (positioned above; the group and the strip are not), so the
     strip's own scrolling does not clip it. */
  .shell-nav__group {
    position: static;
  }

  .shell-nav__summary {
    min-height: 36px;
    padding: 0 var(--space-3);
  }

  .shell-nav__panel .shell-nav__link,
  .shell-nav__section .shell-nav__link {
    min-height: var(--touch-target);
    padding: 0 var(--space-5);
  }

  .shell-header .shell-new-ticket {
    align-self: center;
    margin-top: 0;
    min-height: 36px;
    padding: 0 var(--space-3);
  }

  .shell-tools {
    gap: var(--space-2) var(--space-4);
  }

  .shell-main {
    padding: var(--space-5) var(--space-4) var(--space-9);
  }

  .auth-card {
    padding: var(--space-6);
  }

  .code-list {
    columns: 1;
  }
}

/* Keep a single row when it fits, and let enlarged text reflow instead of
   widening the page. A forced desktop nowrap overflowed at 200% text size. */
@media (min-width: 768px) {
  .shell-header__inner {
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-5);
  }

  .shell-nav {
    flex: 1 1 12rem;
    min-width: 0;
  }

  .shell-nav__link,
  .shell-nav__summary {
    padding: 0 var(--space-3);
  }

  .shell-nav__panel .shell-nav__link {
    padding: 0 var(--space-5);
  }

  .shell-tools {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 100%;
    flex-wrap: wrap;
    white-space: normal;
    overflow-wrap: anywhere;
    gap: var(--space-4);
  }
}

@media (max-width: 479px) {
  .shell-header .brand img {
    width: 100px;
  }

  /* The full intake name remains available to assistive technology when
     the narrow header shows its short label. */
  .shell-new-ticket__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  .shell-new-ticket__short {
    display: inline;
  }

  .shell-tools {
    flex: 1 1 0;
    justify-content: flex-end;
    gap: var(--space-2) var(--space-3);
  }

  .page-header {
    flex-direction: column;
  }
}

/* ---------------------------------------------------------------- notes (§25, §84): internal and public must not look alike */

.notes {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

.note {
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border-subtle);
  border-left-width: 6px;
}

.note--internal {
  border-left-color: var(--status-warning-fg);
  background: var(--status-warning-bg);
}

.note--public {
  border-left-color: var(--status-info-fg);
  background: var(--color-surface);
}

.note--system {
  border-left-color: var(--color-text-faint);
  background: var(--color-surface-subtle);
  font-size: var(--text-sm);
}

.note__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

.note__author {
  font-weight: 600;
  color: var(--color-text-strong);
}

.note__body {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.note__foot {
  margin: var(--space-2) 0 0;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.composer__visibility {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.composer__visibility label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
}

.composer__visibility label:has(input:checked) {
  border-color: var(--color-accent);
  background: var(--color-accent-tint);
}

/* The composer wears the timeline's colours for the same two kinds of
   entry (review 2026-10-17): an internal note - the default - amber with its
   amber edge, as internal notes read below; a public reply white with the
   blue edge of a public reply, a sentence saying the customer will read it
   and a button naming the act. Words carry it - the badge beside the button
   and its verb - colour repeats it. Without :has() the server-side class
   does the same after a redraw, and the button falls back to its own words. */
.composer {
  border: 1px solid var(--color-border-subtle);
  border-left: 6px solid var(--status-warning-fg);
  background: var(--status-warning-bg);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}

.composer__send {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.composer__public-warning,
.composer__submit-public,
.composer__kind--public {
  display: none;
}

/* The actual audience belongs beside an explicitly public reply. The server
   class covers a posted Public value; :has follows the live native radio. */
.composer__public-preview {
  display: none;
}

.composer:has(input[name="Note.Visibility"][value="Public"]:checked) .composer__public-preview,
.composer--public .composer__public-preview {
  display: block;
}

.composer:has(input[name="Note.Visibility"][value="Internal"]:checked) .composer__public-preview {
  display: none;
}

.composer:has(input[name="Note.Visibility"][value="Public"]:checked),
.composer--public {
  border-left-color: var(--status-info-fg);
  background: var(--color-surface);
}

.composer:has(input[name="Note.Visibility"][value="Public"]:checked) .composer__public-warning,
.composer--public .composer__public-warning {
  display: block;
  margin: 0;
  font-weight: 500;
  color: var(--status-info-fg);
}

.composer:has(input[name="Note.Visibility"][value="Public"]:checked) .composer__submit-public,
.composer--public .composer__submit-public,
.composer:has(input[name="Note.Visibility"][value="Public"]:checked) .composer__kind--public,
.composer--public .composer__kind--public {
  display: inline;
}

.composer:has(input[name="Note.Visibility"][value="Public"]:checked) .composer__submit-internal,
.composer--public .composer__submit-internal,
.composer:has(input[name="Note.Visibility"][value="Public"]:checked) .composer__kind--internal,
.composer--public .composer__kind--internal {
  display: none;
}

.composer:has(input[name="Note.Visibility"][value="Internal"]:checked) .composer__public-warning,
.composer:has(input[name="Note.Visibility"][value="Internal"]:checked) .composer__submit-public,
.composer:has(input[name="Note.Visibility"][value="Internal"]:checked) .composer__kind--public {
  display: none;
}

.composer:has(input[name="Note.Visibility"][value="Internal"]:checked) .composer__submit-internal,
.composer:has(input[name="Note.Visibility"][value="Internal"]:checked) .composer__kind--internal {
  display: inline;
}

.composer--public:has(input[name="Note.Visibility"][value="Internal"]:checked) {
  border-left-color: var(--status-warning-fg);
  background: var(--status-warning-bg);
}

.publish-preview {
  border: 1px solid var(--status-warning-fg);
  background: var(--status-warning-bg);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
}

.publish-preview__body {
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  white-space: pre-wrap;
  margin: var(--space-3) 0;
}

.links {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
  display: grid;
  gap: var(--space-2);
}

.links li {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  align-items: baseline;
}

/* In the narrow intake context an open ticket wraps into three lines
   (chip, link, state): a wider gap keeps each state with its own ticket
   instead of reading as the next ticket's. */
.intake__context .links {
  gap: var(--space-4);
}

.hints {
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-4) 0;
}

.hints ul {
  margin: var(--space-2) 0 0;
  padding-left: var(--space-5);
}

/* ---------------------------------------------------------------- quick intake (08-wireflows WF-1) */

.intake__network-status {
  display: grid;
  gap: var(--space-3);
}

.intake__network-status[hidden] {
  display: none;
}

.invoice-network-status[hidden] {
  display: none;
}

.intake__network-status p {
  margin: 0;
}

.verification {
  border: 2px dashed var(--status-warning-fg);
  background: var(--status-warning-bg);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
}

.verification--success {
  border-style: solid;
  border-color: var(--status-success-fg);
  background: var(--status-success-bg);
}

.verification--danger {
  border-style: solid;
  border-color: var(--status-danger-fg);
  background: var(--status-danger-bg);
}

/* Closed, the strip is one line: the state chip and "change". */
.verification:not([open]) {
  padding: var(--space-2) var(--space-4);
  margin-bottom: var(--space-4);
}

.verification__title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-size: var(--text-lg);
  font-weight: 600;
  cursor: pointer;
}

.verification[open] > .verification__title {
  margin-bottom: var(--space-2);
}

.verification__change {
  font-size: var(--text-sm);
  font-weight: 400;
  text-decoration: underline;
}

.verification[open] .verification__change {
  display: none;
}

/* The unverified chip otherwise extends beyond a 320 px intake page when
   text is enlarged. Keep this reflow local to the pinned verification strip. */
.verification__title .chip {
  max-width: 100%;
  min-width: 0;
  white-space: normal;
}

.verification__title .chip span:last-child {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Use an asymmetric pair only at desktop widths; the reference panel keeps
   a readable minimum while native field rows reflow with enlarged text. */
.intake {
  align-items: start;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 64rem) {
  .intake {
    grid-template-columns: minmax(0, 2fr) minmax(18rem, 1fr);
  }
}

/* Native sections and optional dispatch remain usable without scripts. */
.intake.intake--internal {
  grid-template-columns: minmax(0, 1fr);
  max-width: 48rem;
}

.intake__section {
  margin-top: var(--space-6);
}

/* An internal request's card has no visible heading: its first section
   starts at the card's top instead of under an empty band. */
.intake__form > h2.visually-hidden + .intake__section {
  margin-top: 0;
}

.intake__section > legend {
  max-width: 100%;
}

.intake__section > :last-child {
  margin-bottom: 0;
}

.intake__context > h3 {
  border-top: 1px solid var(--color-border-subtle);
  padding-top: var(--space-4);
  margin-top: var(--space-5);
}

/* The intake actions stay in reach while the form is longer than the screen
   (L-5): a bar at the bottom of the viewport, its own surface and a top rule,
   that settles in place once the form ends above it. */
.intake__actions-main {
  margin-top: var(--space-5);
}

#intake-form .intake__actions-main {
  position: sticky;
  bottom: 0;
  z-index: var(--z-sticky);
  margin: var(--space-5) calc(-1 * var(--space-6)) 0;
  padding: var(--space-3) var(--space-6);
  background: var(--color-surface);
  border-top: 1px solid var(--color-border-subtle);
}

/* On a phone the bar keeps the two buttons on one row: "cancel" leads where
   the breadcrumb's first link already does, so the bar leaves it out. */
@media (max-width: 40rem) {
  #intake-form .intake__actions-main > .btn--ghost {
    display: none;
  }
}

.intake__actions-secondary {
  border-top: 1px solid var(--color-border-subtle);
  padding-top: var(--space-4);
  margin-top: var(--space-4);
}

/* The ticket card must shrink with the phone grid when text is enlarged. */
.intake > .card {
  min-width: 0;
}

.intake__context {
  font-size: var(--text-sm);
}

.intake__priority {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-2);
  padding: 0 0 var(--space-5);
}

.intake__priority-label {
  font-weight: 600;
}

/* The full matrix behind a small help link beside the live chip (OP-14):
   the summary reads as a link; the open table takes the row below. */
.intake__matrix-help > summary {
  list-style: none;
  cursor: pointer;
  color: var(--color-accent);
  font-size: var(--text-sm);
  text-decoration: underline;
}

.intake__matrix-help > summary::-webkit-details-marker {
  display: none;
}

.intake__matrix-help[open] {
  flex-basis: 100%;
}

.intake__matrix {
  margin: var(--space-3) 0 0;
}

/* Keep matrix words readable under text enlargement; the existing table
   frame scrolls horizontally instead of squeezing each cell to a glyph. */
.intake__matrix .table {
  min-width: 28rem;
  font-size: var(--text-xs);
}

.intake__matrix .table caption {
  padding: var(--space-3) var(--space-4);
}

.intake__matrix .table th,
.intake__matrix .table td {
  padding: var(--space-2) var(--space-3);
  height: auto;
}

.intake__details {
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin: var(--space-2) 0;
}

.intake__details > summary {
  cursor: pointer;
  font-weight: 600;
}

.intake__details[open] > summary {
  margin-bottom: var(--space-3);
}

/* What the intake script or the server hides stays hidden, whatever display
   a field or a row would otherwise take (the backup beside the owner). */
#intake-form [hidden] {
  display: none;
}

/* OP-15: the single match the search opened, and the way back to its results. */
.intake__found {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  margin: 0 0 var(--space-5);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border-subtle);
  border-left: 4px solid var(--status-warning-fg);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

/* The six rows keep one rhythm: each field its own row, impact and urgency
   and the owner and backup as pairs (OP-14). A choice is as wide as its
   longest option needs, not the whole column (F-7). */
.intake__form > .field,
.intake__caller > .field {
  margin-bottom: var(--space-5);
}

.intake__form > .field .select,
.intake__caller .select,
.intake__owner .select {
  max-width: 28rem;
}

.intake__owner-p1 {
  margin: calc(-1 * var(--space-2)) 0 var(--space-5);
  color: var(--status-warning-fg);
}

/* The sticky actions never cover the field that takes the focus: a field
   scrolled into view stops above the bar (WCAG 2.4.11). */
#intake-form :is(input, select, textarea, button, summary, a) {
  scroll-margin-bottom: 6rem;
}

/* The caller's own open tickets: information, in the warning tone of a hint,
   never the danger border (S-3). */
.intake__caller-open {
  border-left: 4px solid var(--status-warning-fg);
}

/* Another contact has the new caller's number: both answers side by side. */
.intake__known {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

/* A new caller (OP-11): two fields folded under the caller until they matter. */
.intake__new-caller {
  margin: calc(-1 * var(--space-3)) 0 var(--space-5);
}

.intake__new-caller > summary,
.intake__entitlement-other > summary {
  cursor: pointer;
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: 600;
}

.intake__new-caller[open] {
  border-left: 2px solid var(--color-border);
  padding: 0 0 var(--space-2) var(--space-4);
  margin-bottom: var(--space-6);
}

.intake__restricted-hint {
  margin: calc(-1 * var(--space-2)) 0 var(--space-5);
}

.intake__new-caller[open] > summary,
.intake__entitlement-other[open] > summary {
  margin-bottom: var(--space-3);
}

/* The coverage (OP-13): one line, its SLA for the priority, one tick. Its
   rule stands clear of the owner's hint above it (T-1). */
.intake__coverage {
  display: grid;
  gap: var(--space-3);
  border-top: 1px solid var(--color-border-subtle);
  margin-top: var(--space-5);
  padding: var(--space-4) 0 var(--space-5);
}

.intake__coverage-current {
  display: grid;
  gap: var(--space-2);
}

.intake__coverage-current > p {
  margin: 0;
}

/* One line: the contract and what it says, the SLA, the tick. Nothing on it
   is in the success tone - it is a suggestion until the ticket is saved. */
.intake__coverage-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
}

.intake__coverage-label {
  font-weight: 600;
}

.intake__confirm-check {
  min-height: var(--touch-target);
  align-items: center;
  font-weight: 600;
  margin-left: var(--space-3);
}

/* "More" (OP-14): the channel, site, queue, override and what is deferred. */
.intake__more {
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin: 0 0 var(--space-2);
}

/* The summary stays a list item: the browser's own open/closed marker is
   what says this box opens (intake review 2026-10-17). */
.intake__more > summary {
  cursor: pointer;
  font-weight: 600;
  padding: var(--space-2) 0;
}

.intake__more-summary {
  font-weight: 400;
  font-size: var(--text-sm);
  margin-left: var(--space-3);
}

.intake__more[open] > summary {
  margin-bottom: var(--space-4);
}

/* Within "more", a group's title is a heading, not another label: larger,
   with the space of a new group above it (T-1). Scoped to the form: the
   shared "fieldset.field" and its legend rules otherwise win on weight and
   the title sat against the field above it (recaptured screens 2026-10-17). */
#intake-form fieldset.intake__override,
#intake-form fieldset.intake__deferred {
  border: 0;
  padding: 0;
  margin: var(--space-8) 0 0;
  min-width: 0;
}

#intake-form fieldset.intake__override > legend,
#intake-form fieldset.intake__deferred > legend {
  font-size: var(--text-md);
  font-weight: 600;
  margin-bottom: var(--space-3);
}

/* OP-04: similar open tickets "create ticket" stopped for, shown once. */
.intake__similar {
  border: 2px solid var(--status-warning-fg);
  background: var(--status-warning-bg);
  margin: var(--space-5) 0 0;
}

.intake__similar .links {
  margin: var(--space-3) 0;
}

/* The status line after Enter's check, in the bar above its buttons:
   nothing was created, and which button creates. */
.intake__checked {
  flex-basis: 100%;
  margin: 0;
  padding: var(--space-2) var(--space-4);
  border-left: 4px solid var(--status-info-fg);
  background: var(--status-info-bg);
  border-radius: var(--radius-md);
}

/* The quieter creates, folded below the actions: for whoever can start
   work during the call; the work type comes before its button. */
.intake__more-ways {
  margin-top: var(--space-5);
}

.intake__more-ways > summary {
  cursor: pointer;
  color: var(--color-accent);
  font-size: var(--text-sm);
  font-weight: 600;
}

.intake__start-remote {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-4);
  max-width: 28rem;
}

.intake__start-remote > .form__actions {
  margin: 0;
}

/* OP-16: each draft says whose call it was, with its own continue and delete. */
.intake-drafts {
  list-style: none;
  margin: 0;
  padding: 0;
}

.intake-drafts__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3) var(--space-5);
  padding: var(--space-4) 0;
  border-top: 1px solid var(--color-border-subtle);
}

.intake-drafts__row:first-child {
  border-top: 0;
  padding-top: 0;
}

.intake-drafts__text {
  display: grid;
  gap: var(--space-1);
  flex: 1 1 20rem;
  min-width: 0;
}

.intake-drafts__title {
  font-weight: 600;
  overflow-wrap: anywhere;
}

.intake-drafts__meta {
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

.intake-drafts__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-3);
}

/* Delete asks once, in place: the summary reads as a quiet button, the
   answer is the danger-outline one under it (A-1, A-7). */
.intake-drafts__discard > summary {
  list-style: none;
}

.intake-drafts__discard > .btn--danger {
  margin-top: var(--space-3);
}

.intake-drafts__discard > summary::-webkit-details-marker {
  display: none;
}

.intake-drafts__discard[open] {
  flex-basis: 100%;
}

.intake-drafts__discard[open] > summary {
  color: var(--color-text-strong);
  background: var(--color-surface-subtle);
}

.followups {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
  display: grid;
  gap: var(--space-2);
}

.followup {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-3);
}

.followup--done {
  color: var(--color-text-muted);
}

/* Existing cards and tokens, with the queue figures easy to scan first. */
.dashboard-overview {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--space-6);
  margin-bottom: var(--space-6);
}

.dashboard-overview > .card,
.dashboard-grid > .card {
  margin-bottom: 0;
}

.dashboard-grid {
  align-items: start;
  margin-bottom: var(--space-6);
}

.dashboard-section__title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-4);
}

.dashboard-overview .card__title {
  margin-bottom: var(--space-3);
}

.dash-number {
  font-size: 2.5rem;
  line-height: 1.2;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--space-3);
}

.dash-number a {
  display: inline-block;
  min-width: var(--touch-target);
  text-decoration-thickness: 1px;
  text-underline-offset: .12em;
}

.dashboard-overview .card--caution .dash-number a {
  color: var(--status-danger-fg);
}

/* Definitions remain available without taking space ahead of urgent work. */
.dashboard-definition {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
}

.dashboard-definition > summary {
  cursor: pointer;
  color: var(--color-accent);
  min-height: var(--touch-target);
  align-content: center;
}

.dashboard-definition[open] > summary {
  margin-bottom: var(--space-2);
}

@media (max-width: 600px) {
  .dashboard-overview {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
    gap: var(--space-3);
  }

  .dashboard-overview > .card {
    min-width: 0;
    padding: var(--space-4);
  }

  .dashboard-overview .card__title {
    font-size: var(--text-md);
  }

  .dashboard-overview .dash-number {
    font-size: 2rem;
  }
}

/* ---------------------------------------------------------------- lists */

/* A second heading inside a card (the dashboard's "today's visits" under
   "my work"): set apart from the lines above it, close to its own list. */
.card__section-title {
  margin: var(--space-6) 0 var(--space-3);
}

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

.plain-list li {
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-border-subtle);
}

/* ---------------------------------------------------------------- in-app inbox (header count and /notifications) */

.shell-inbox {
  color: var(--color-text);
  font-size: var(--text-sm);
  text-decoration: none;
}

.shell-inbox:hover {
  text-decoration: underline;
}

.shell-inbox--unread {
  font-weight: 600;
  color: var(--color-accent);
}

.inbox {
  list-style: none;
  margin: 0 0 var(--space-5);
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

.inbox__item {
  border: 1px solid var(--color-border-subtle);
  border-left-width: 6px;
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface-subtle);
}

.inbox__item--unread {
  border-left-color: var(--color-accent);
  background: var(--color-surface);
}

.inbox__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

.inbox__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--color-text-strong);
  overflow-wrap: anywhere;
}

.inbox__body {
  margin: 0 0 var(--space-3);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.inbox__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* ---------------------------------------------------------------- operations */

/* Jobs board tiles: the sentence carries the state; tone and border repeat it
   for sighted readers (never colour alone, A-UI-A11Y-05). */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-5);
  margin-bottom: var(--space-6);
}

.tile {
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-left-width: 4px;
  border-radius: var(--radius-md);
  padding: var(--space-5);
}

.tile__title {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-bottom: var(--space-3);
}

.tile__value {
  font-size: var(--text-md);
  color: var(--color-text-strong);
  margin: 0;
}

.tile__detail {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: var(--space-3) 0 0;
  overflow-wrap: anywhere;
}

.tile--ok {
  border-left-color: var(--status-success-fg);
}

.tile--neutral {
  border-left-color: var(--color-border);
}

.tile--warning {
  border-left-color: var(--status-warning-fg);
  border-left-style: dashed;
  background: var(--status-warning-bg);
}

.tile--danger {
  border-left-color: var(--status-danger-fg);
  border-left-style: double;
  border-left-width: 6px;
  background: var(--status-danger-bg);
}

.banner--warning {
  color: var(--status-warning-fg);
  background: var(--status-warning-bg);
}

/* A run abandoned by a dead worker is crash evidence: the row stands out. */
.table tr.row--alert td {
  background: var(--status-danger-bg);
}

.ticket-notifications li {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-2) 0;
}

/* A customer email still inside its grace window: it goes out in minutes,
   so it stands above the folded record with its cancel form. */
.email-cancel-list {
  border: 1px solid var(--status-warning-fg);
  background: var(--status-warning-bg);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-4);
}

.email-cancel {
  flex-basis: 100%;
  margin-top: var(--space-2);
  background: var(--color-surface);
}

.email-cancel .form {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-3);
  max-width: 40rem;
}

.email-cancel .btn {
  justify-self: start;
}

/* Call, mail and map links beside a requester or site (wrap on a phone). */
ul.reach {
  list-style: none;
  margin: var(--space-1) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  align-items: baseline;
}

.reach a {
  overflow-wrap: anywhere;
}

.reach__access {
  margin: var(--space-2) 0 0;
  white-space: pre-line;
}

/* ------------------------------------------------------------ prospect board */

/* The §11 pipeline: one column per stage, scrolling sideways on a narrow
   screen rather than squeezing fourteen columns into one width. */
.board {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(200px, 1fr);
  gap: var(--space-4);
  overflow-x: auto;
  padding-bottom: var(--space-4);
}

.board__column {
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  min-width: 0;
}

.board__title {
  font-size: var(--text-sm);
  color: var(--color-text-strong);
  margin: 0 0 var(--space-3);
}

.board__count {
  color: var(--color-text-muted);
  font-weight: normal;
}

.board__empty {
  color: var(--color-text-muted);
  margin: 0;
}

.board__cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

.board__card {
  display: grid;
  gap: var(--space-1);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  overflow-wrap: anywhere;
}

.board__meta {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* Free text typed with line breaks (prospect notes, activity summaries). */
.pre-wrap {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Printing (§52 monthly report and any other page): the content only, no
   menus, forms or buttons; tables shown whole, sections kept together. */
@media print {
  .skip-link,
  .shell-header,
  .no-print,
  .page-actions {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }

  .card {
    border: 1px solid #999;
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .table-wrap {
    overflow: visible;
    border: none;
  }

  .table thead {
    display: table-header-group;
  }

  .table tr {
    break-inside: avoid;
  }

  a {
    color: inherit;
    text-decoration: none;
  }
}

/* ------------------------------------------------------------ projects (§20) */

.project-progress {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  vertical-align: middle;
  font-weight: 400;
}

.project-progress__bar {
  inline-size: 8rem;
  max-inline-size: 40vw;
  block-size: 0.6rem;
  appearance: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-subtle);
  overflow: hidden;
}

/* In a project list the bar is a glance beside its percentage. */
.table .project-progress__bar {
  inline-size: 5rem;
}

.project-progress__bar::-webkit-progress-bar {
  background: var(--color-surface-subtle);
}

.project-progress__bar::-webkit-progress-value {
  background: var(--color-accent);
}

.project-progress__bar::-moz-progress-bar {
  background: var(--color-accent);
}

.project-progress__value {
  font-variant-numeric: tabular-nums;
  min-inline-size: 3.5ch;
}

.project-phase + .project-phase {
  margin-top: var(--space-6);
}

/* ---------------------------------------------------------------- productivity lane: quick actions and /my-work (§33, §34) */
/* One wrapping row of large enough targets on a phone; the accept form sits inline with the links. */
.quick-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2, 0.5rem);
  align-items: center;
  margin: 0 0 var(--space-4, 1rem);
}

.quick-actions .form--inline {
  margin: 0;
}

.quick-actions .btn {
  min-height: 2.75rem;
}

.mywork-table td .form--inline {
  margin: 0;
}

/* One compact warning group on Customer, Ticket and Intake. Every linked label
   wraps in full; shared status colors and glyphs retain its existing meaning. */
.warning-strip {
  min-width: 0;
  margin: 0 0 var(--space-5);
  padding: var(--space-4) var(--space-5);
  background: var(--color-surface);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-md);
}

.warning-strip__title {
  font-size: var(--text-base);
  margin: 0 0 var(--space-3);
}

.warning-strip__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
}

.warning-strip__item,
.warning-strip__item .chip {
  min-width: 0;
  max-width: 100%;
}

.warning-strip__item .chip {
  align-items: flex-start;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--text-base);
  white-space: normal;
}

.warning-strip__item .chip__glyph {
  flex: 0 0 auto;
}

.warning-strip__item .chip span:last-child {
  min-width: 0;
  overflow-wrap: anywhere;
}

.warning-strip__link {
  display: inline-flex;
  min-height: var(--touch-target);
  max-width: 100%;
  align-items: center;
  text-decoration: none;
}

.warning-strip__link:hover .chip,
.warning-strip__link:focus-visible .chip {
  text-decoration: underline;
}

/* ------------------------------------------------------- compact staff header */
/* MainLayout opts in; portal, authentication and public shells keep their layout. */
.shell--staff .shell-header__inner {
  position: relative;
  gap: var(--space-2);
  min-height: var(--touch-target);
}

/* Daily links lead; remaining groups stay in one native disclosure. */
.shell--staff .shell-header__inner--nav {
  column-gap: var(--space-4);
}

.shell--staff .shell-nav {
  flex: 1 1 100%;
}

.shell--staff .shell-nav__link,
.shell--staff .shell-nav__summary {
  min-height: var(--touch-target);
  max-width: 100%;
  overflow-wrap: anywhere;
}

.shell--staff .shell-nav__summary {
  white-space: normal;
  flex-wrap: wrap;
}

.shell--staff .shell-nav__summary::after {
  flex: none;
}

.shell--staff .shell-nav__mobile-label,
.shell--staff .shell-nav__mobile-primary,
.shell--staff .shell-nav__current,
.shell--staff .shell-nav__more--primary-only {
  display: none;
}

.shell--staff .shell-nav__current--remaining {
  display: inline;
}

.shell--staff .shell-nav__current {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: 400;
  padding-left: var(--space-2);
  border-left: 1px solid var(--color-border);
}

.shell--staff .shell-nav__panel .shell-nav__link {
  padding: var(--space-2) var(--space-3);
}

.shell--staff .shell-nav__heading {
  margin: 0 var(--space-3) var(--space-2) calc(var(--space-3) + 3px);
}

.shell--staff .shell-nav__section {
  padding-bottom: 0;
}

/* Configuration is one clear destination after the daily-work groups. */
.shell--staff .shell-nav__section[aria-labelledby="shell-more-settings"] {
  grid-column: 1 / -1;
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-border-subtle);
}

.shell--staff .shell-new-ticket {
  align-self: center;
  margin: 0 var(--space-2);
  min-height: var(--touch-target);
}

/* Another role's view is on: one line, with the way back at its end. */
.shell-view-strip {
  align-items: center;
  flex-wrap: wrap;
}

.shell-view-strip__text {
  flex: 1 1 16rem;
  min-width: 0;
}

.shell-view-strip__form {
  margin: 0;
}

.shell--staff .brand {
  min-height: var(--touch-target);
}

.shell--staff .shell-search {
  flex: 1 1 16rem;
}

.shell--staff .shell-search__input,
.shell--staff .shell-search__button {
  min-height: var(--touch-target);
  font-size: var(--text-md);
}

.shell--staff .shell-search__input {
  text-overflow: ellipsis;
}

.shell--staff .shell-search__button {
  padding: var(--space-2) var(--space-3);
}

.shell--staff .shell-tools {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  gap: var(--space-2);
}

.shell--staff .shell-inbox {
  order: 0;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-width: var(--touch-target);
  min-height: var(--touch-target);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  text-decoration: none;
}

.shell--staff .shell-inbox:hover,
.shell--staff .shell-account__summary:hover {
  background: var(--color-accent-tint);
}

.shell--staff .shell-inbox__icon,
.shell--staff .shell-account__icon {
  display: block;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.shell--staff .shell-inbox__count {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.shell--staff .shell-account {
  position: relative;
  flex: 0 1 auto;
  min-width: 0;
  max-width: 14rem;
}

.shell--staff .shell-account__summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  min-height: var(--touch-target);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  cursor: pointer;
  list-style: none;
}

.shell--staff .shell-account__summary::-webkit-details-marker {
  display: none;
}

.shell--staff .shell-account__summary::after {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
}

.shell--staff .shell-account[open] > .shell-account__summary::after {
  transform: rotate(225deg);
}

.shell--staff .shell-account__name {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 14ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.shell--staff .shell-account__panel {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: var(--z-dropdown);
  width: min(22rem, calc(100vw - var(--space-5) * 2));
  max-height: calc(100dvh - 4rem);
  overflow-y: auto;
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  box-shadow: 0 6px 16px rgb(0 0 0 / 12%);
}

.shell--staff .shell-account__attribution {
  margin: 0 0 var(--space-2);
  padding: 0 var(--space-2) var(--space-2);
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

.shell--staff .shell-account__link,
.shell--staff .shell-account__signout {
  display: flex;
  align-items: center;
  min-height: var(--touch-target);
  width: 100%;
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  text-align: left;
  text-decoration: none;
  overflow-wrap: anywhere;
}

.shell--staff .shell-account__link:hover {
  background: var(--color-accent-tint);
}

/* A settings page with no link of its own in the row: the account menu
   holds its way back, so the menu's summary and its settings link are
   marked like the current link - colour, weight and a bar, never case. */
.shell--staff .shell-account__summary[aria-current="true"] {
  color: var(--color-accent);
  background: var(--color-accent-tint);
  font-weight: 500;
}

.shell--staff .shell-account__link[aria-current="page"] {
  color: var(--color-accent);
  font-weight: 500;
  box-shadow: inset 3px 0 0 var(--color-accent);
}

.shell--staff .shell-account__summary:focus-visible,
.shell--staff .shell-account__link:focus-visible,
.shell--staff .shell-account__signout:focus-visible,
.shell--staff .shell-inbox:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

@media (max-width: 767px) {
  .shell--staff .shell-search {
    flex: 1 1 10rem;
    order: 1;
  }

  .shell--staff .shell-new-ticket {
    order: 1;
    margin: 0;
  }

  .shell--staff .shell-tools {
    flex: 1 1 auto;
    justify-content: flex-end;
    flex-wrap: wrap;
  }

  .shell--staff .shell-nav {
    display: block;
    width: 100%;
  }

  .shell--staff .shell-nav__links,
  .shell--staff .shell-nav__desktop-label {
    display: none;
  }

  .shell--staff .shell-nav__more,
  .shell--staff .shell-nav__mobile-label,
  .shell--staff .shell-nav__current {
    display: block;
  }

  .shell--staff .shell-nav__summary {
    display: flex;
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border-top: 1px solid var(--color-border-subtle);
  }

  .shell--staff .shell-nav__current {
    flex: 1 1 auto;
    text-align: right;
    border-left: 0;
    padding-left: 0;
  }

  .shell--staff .shell-nav .shell-nav__group > .shell-nav__panel {
    position: static;
    grid-template-columns: minmax(0, 1fr);
    max-height: min(65dvh, 36rem);
    overflow-y: auto;
    overscroll-behavior-y: contain;
    scrollbar-gutter: stable;
    box-shadow: none;
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-2);
    margin-bottom: var(--space-3);
  }

  .shell--staff .shell-nav__mobile-primary {
    display: flex;
    flex-direction: column;
    min-width: 0;
  }

  .shell--staff .brand img {
    width: 80px;
  }

  .shell--staff .shell-account {
    position: static;
    flex: none;
    max-width: var(--touch-target);
  }

  .shell--staff .shell-account__summary {
    justify-content: center;
    min-width: var(--touch-target);
  }

  .shell--staff .shell-account__name,
  .shell--staff .shell-account__summary::after {
    display: none;
  }

  .shell--staff .shell-account__panel {
    left: var(--space-2);
    right: var(--space-2);
    width: auto;
  }
}

@media (max-width: 359px) {
  .shell--staff .brand img {
    width: 56px;
  }
}

/* ---------------------------------------------------------------- staff assistant (ADR-0016 §13.2-13.4) */

/* The header's link: a tool of the shell like the inbox's bell and the
   account - its icon and its word, no frame, the same 44 px target, tint and
   focus ring; the word gives way to the icon alone on a phone. */
.shell-assistant {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-width: var(--touch-target);
  min-height: var(--touch-target);
  padding: var(--space-2);
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-size: var(--text-sm);
  text-decoration: none;
}

.shell-assistant:hover,
.shell-assistant[aria-current="page"] {
  background: var(--color-accent-tint);
}

.shell-assistant:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}

.shell-assistant__icon {
  display: block;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The provider and model answering, and the data-scope chip, under the title. */
.assistant-header__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-top: var(--space-2);
}

/* One column on a phone; beside each other from 768 px (below). */
.assistant {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  min-width: 0;
}

.assistant > .card {
  margin-bottom: 0;
}

/* A class that sets display (a button, a row of chips) would show while hidden. */
.assistant [hidden] {
  display: none;
}

.assistant .btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.assistant-conversations {
  min-width: 0;
  padding: var(--space-4) var(--space-5);
}

.assistant-conversations__summary {
  cursor: pointer;
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--color-text-strong);
}

.assistant-conversations__list {
  list-style: none;
  margin: var(--space-3) 0;
  padding: 0;
}

.assistant-conversation {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "link delete" "time delete";
  align-items: center;
  column-gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border-subtle);
}

.assistant-conversation:last-child {
  border-bottom: 0;
}

.assistant-conversation:has(> .assistant-conversation__link[aria-current="page"]) {
  border-radius: var(--radius-md);
  background: var(--color-accent-tint);
}

.assistant-conversation__link {
  grid-area: link;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-text);
  font-weight: 500;
  text-decoration: none;
}

.assistant-conversation__link:hover {
  color: var(--color-accent-hover);
  text-decoration: underline;
}

.assistant-conversation__link[aria-current="page"] {
  color: var(--color-accent);
}

.assistant-conversation__time {
  grid-area: time;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}

.assistant-conversation__delete {
  grid-area: delete;
}

.assistant-conversations__empty {
  margin: var(--space-3) 0;
}

.assistant-chat {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
  padding: var(--space-4) var(--space-5);
}

.assistant-chat__title {
  margin: 0;
  font-size: var(--text-md);
  overflow-wrap: anywhere;
}

.assistant-thread {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
}

/* The thread takes the keyboard focus to scroll: its ring is drawn inside,
   where the card's edge cannot hide it. */
.assistant-thread:focus-visible {
  outline-offset: -2px;
}

/* Above a long conversation's newest messages: earlier ones are left out. */
.assistant-thread__earlier {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  text-align: center;
}

/* The person's words on the accent tint, the assistant's on the card itself:
   told apart without a box inside the box. */
.assistant-message {
  max-width: 100%;
  min-width: 0;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  overflow-wrap: anywhere;
}

.assistant-message--question {
  align-self: flex-end;
  max-width: min(40rem, 88%);
  background: var(--color-accent-tint);
}

.assistant-message--answer {
  align-self: stretch;
  padding-left: 0;
  padding-right: 0;
}

/* A failed answer: the rule says so beside the words, not colour alone. */
.assistant-message--failed {
  padding-left: var(--space-4);
  border-left: 3px solid var(--status-danger-fg);
  border-radius: 0;
}

.assistant-message__body {
  margin: 0;
}

.assistant-message__note {
  margin: var(--space-2) 0 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.assistant-message--failed .assistant-message__note {
  margin-top: 0;
  color: var(--status-danger-fg);
}

.assistant-message__tools {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-2) 0 0;
}

.assistant-tool {
  padding: 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--color-surface-subtle);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
  line-height: 1.8;
}

.assistant-message__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-3);
  margin: var(--space-2) 0 0;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}

.assistant-message--question .assistant-message__meta {
  justify-content: flex-end;
}

.assistant-message__fact + .assistant-message__fact::before {
  content: "·";
  margin-right: var(--space-3);
  color: var(--color-text-faint);
}

.assistant-feedback {
  display: inline-flex;
  gap: var(--space-1);
}

.assistant-feedback__button[aria-pressed="true"] {
  color: var(--color-accent);
  background: var(--color-accent-tint);
}

/* An answer's Markdown, as assistant.js renders it: readable prose, code that
   scrolls sideways inside itself, tables in the tables' own frame. */
.assistant-md > * {
  margin: 0 0 var(--space-3);
}

.assistant-md > :last-child {
  margin-bottom: 0;
}

.assistant-md h3,
.assistant-md h4,
.assistant-md h5 {
  margin: var(--space-5) 0 var(--space-2);
  color: var(--color-text-strong);
  font-size: var(--text-base);
  line-height: var(--leading-tight);
}

.assistant-md h3 {
  font-size: var(--text-md);
}

.assistant-md > h3:first-child,
.assistant-md > h4:first-child,
.assistant-md > h5:first-child {
  margin-top: 0;
}

.assistant-md ul,
.assistant-md ol {
  padding-left: var(--space-7);
}

.assistant-md li {
  margin: var(--space-1) 0;
}

.assistant-md li > ul,
.assistant-md li > ol {
  margin: var(--space-1) 0 0;
}

.assistant-md code {
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-surface-subtle);
}

.assistant-md pre {
  overflow-x: auto;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-surface-subtle);
  white-space: pre;
  overflow-wrap: normal;
}

.assistant-md pre code {
  padding: 0;
  background: none;
  font-size: var(--text-sm);
}

.assistant-md blockquote {
  margin-left: 0;
  margin-right: 0;
  padding-left: var(--space-4);
  border-left: 3px solid var(--color-border);
  color: var(--color-text-muted);
}

.assistant-md hr {
  border: 0;
  border-top: 1px solid var(--color-border-subtle);
}

/* Where a link that leaves GAMBIT leads, written after its label. */
.assistant-link__host {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

.assistant-md .table th,
.assistant-md .table td {
  white-space: normal;
  min-width: 6rem;
}

.assistant-welcome {
  padding: var(--space-3) 0;
}

.assistant-welcome__title {
  margin: 0 0 var(--space-2);
  color: var(--color-text-strong);
  font-size: var(--text-lg);
  font-weight: 600;
}

.assistant-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-4) 0 0;
  padding: 0;
  list-style: none;
}

.assistant-suggestion {
  margin: 0;
}

/* A whole question on the button, wrapped when it is long. */
.assistant-suggestion__button {
  height: auto;
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
  text-align: left;
  white-space: normal;
}

.assistant-status {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* The ticket the person came from: a chip with its own remove link. */
.assistant-context {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
}

.assistant-context__chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  max-width: 100%;
  min-height: 26px;
  padding: 0 var(--space-1) 0 var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--color-accent-tint);
}

.assistant-context__chip > a:first-child {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}

.assistant-context__remove {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: var(--radius-pill);
  color: var(--color-text-muted);
  font-size: var(--text-md);
  line-height: 1;
  text-decoration: none;
}

.assistant-context__remove:hover {
  color: var(--color-text-strong);
  background: var(--color-surface);
}

.assistant-composer {
  display: grid;
  gap: var(--space-2);
  margin: 0;
}

.assistant-composer .assistant-composer__input {
  min-height: 3.5rem;
  max-height: 40vh;
  overflow-y: auto;
}

.assistant-composer__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
}

.assistant-composer__keys {
  margin-left: auto;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}

.assistant-composer__note {
  margin: 0;
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}

/* Beside each other from 768 px; the thread scrolls inside the chat card and
   the composer stays in view under it: the cards are as tall as the window
   below the header and the page title. */
@media (min-width: 768px) {
  .assistant {
    grid-template-columns: minmax(13rem, 17rem) minmax(0, 1fr);
    align-items: start;
  }

  .assistant-chat {
    height: calc(100vh - 14rem);
    min-height: 26rem;
  }

  /* Hairlines above and below say where the scrolling part ends. */
  .assistant-thread {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-3) var(--space-2);
    border-block: 1px solid var(--color-border-subtle);
  }

  .assistant-conversations {
    max-height: calc(100vh - 14rem);
    overflow-y: auto;
  }
}

/* On a phone the page itself scrolls; the header link keeps only its icon,
   like the inbox's bell, so the compact header keeps its one line of tools,
   and small targets grow. The word stays for screen readers. */
@media (max-width: 767px) {
  .shell-assistant__text {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  .assistant-message--question {
    max-width: 92%;
  }

  .assistant-context__remove {
    width: 36px;
    height: 36px;
  }
}

/* Printed, a conversation is its messages: no list, composer or buttons. */
@media print {
  .assistant-conversations,
  .assistant-composer,
  .assistant-composer__note,
  .assistant-context,
  .assistant-status,
  .assistant-suggestions,
  .assistant-feedback,
  .assistant-message__meta .btn {
    display: none !important;
  }

  .assistant {
    display: block;
  }

  .assistant-chat {
    height: auto;
  }

  .assistant-thread {
    overflow: visible;
  }
}

/* ---------------------------------------------------------------- staff assistant settings (ADR-0016 §13.5) */

/* The Coding Plan warning on a connection's form: shown while that kind is
   the chosen one - at once with :has(), after a redraw by the server's class
   without it - and gone again when another kind is picked. */
.assistant-coding-plan {
  display: none;
}

#assistant-connection-form:has(#connection-kind option[value="zai_coding_plan"]:checked) .assistant-coding-plan,
.assistant-coding-plan--chosen {
  display: flex;
}

#assistant-connection-form:has(#connection-kind option:checked:not([value="zai_coding_plan"])) .assistant-coding-plan--chosen {
  display: none;
}

/* Agent onboarding follows the current server stage, with a short ordered path. */
.agent-onboarding { max-inline-size: 58rem; }
.agent-onboarding [data-agent-copy][hidden] { display: none; }
.agent-onboarding__steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-6);
}
.agent-onboarding__steps li {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding-block: var(--space-3);
  border-bottom: 2px solid var(--color-border-subtle);
  color: var(--color-text-muted);
  min-inline-size: 0;
  overflow-wrap: anywhere;
}
.agent-onboarding__steps li[aria-current="step"] {
  border-color: var(--color-accent);
  color: var(--color-text);
  font-weight: 600;
}
.agent-onboarding__number {
  display: grid;
  place-items: center;
  flex: 0 0 1.75rem;
  inline-size: 1.75rem;
  min-inline-size: 1.75rem;
  block-size: 1.75rem;
  border: 1px solid currentColor;
  border-radius: 50%;
}
.agent-onboarding__code {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-block: var(--space-4);
}
.agent-onboarding__code code {
  font-size: var(--text-lg);
  min-inline-size: 0;
  overflow-wrap: anywhere;
}
.agent-onboarding__fields {
  display: grid;
  gap: var(--space-5);
  border: 0;
  padding: 0;
  margin: 0;
  min-inline-size: 0;
}
.agent-onboarding__blocked {
  border-left: 3px solid var(--status-warning-fg);
  padding-left: var(--space-4);
}
.agent-onboarding__blocked h3 { margin-top: 0; }
@media (max-width: 40rem) {
  .agent-onboarding__steps li { flex-direction: column; align-items: flex-start; font-size: var(--text-sm); }
}

/* The literal installed-helper command stays selectable without page overflow. */
.agent-connect-command {
  max-inline-size: 100%;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
