
/* ---- buttons, prev/next ---- */

.aucra-btn {
  height: 32px;
  padding: 0 12px;
  border-radius: 6px;
  font-size: 0.81rem;
  font-weight: var(--weight-bold);
}
.aucra-btn > .q-btn__content {
  flex-wrap: nowrap;
}
.aucra-btn-primary {
  background: var(--ink);
  color: var(--on-ink);
  border: 1px solid var(--ink);
}
.aucra-btn-gold {
  background: var(--gold);
  color: var(--ink);
  border: 1px solid var(--gold);
}
.aucra-btn-ghost {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--line);
}
/* A button that reads as a link: the row it sits under is the frame, so it
   carries none of its own. */
.q-btn.aucra-btn-text {
  background: none;
  border: none;
  color: var(--gold-deep);
  font-size: 12.5px;
  /* The mockup's text ghosts are body weight, not the 500 a bordered button
     carries: the words are a link, not a button face. */
  font-weight: 400;
  /* The words are the button, so it is as tall as its line and no taller: a
     32px box on every line of a band reads as a second register. */
  height: 18px;
  min-height: 18px;
  padding: 0 6px;
  align-self: flex-start;
}
.q-btn.aucra-btn-text .q-icon {
  font-size: 14px;
}
.q-btn.aucra-btn-text:hover {
  background: var(--gold-wash);
}
.q-btn.aucra-btn-text:active {
  background: var(--gold);
  color: var(--ink);
}
/* A control that is its icon: no label, no border, no background. */
.q-btn.aucra-icon-btn {
  width: 32px;
  height: 32px;
  min-height: 32px;
  padding: 0;
  border: none;
  background: none;
  color: var(--muted);
}
.q-btn.aucra-icon-btn .q-icon {
  font-size: 16px;
}
.q-btn.aucra-icon-btn:hover {
  color: var(--text);
  background: var(--mist);
}
.q-btn.aucra-icon-btn:active {
  background: var(--line);
}

.aucra-prevnext {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  gap: 8px;
  font-size: 0.78rem;
}
a.aucra-step {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  /* Two steps side by side are wider than a phone's content column, so the
     pair wraps and each one gives up its fixed cap. */
  max-width: min(260px, 100%);
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel);
  color: var(--text);
  text-decoration-line: none;
  transition: background var(--motion-quick) var(--ease-out);
}
a.aucra-step:hover {
  background: var(--gold-tint);
  opacity: 1;
}
.aucra-step-id {
  color: var(--muted);
}
.aucra-step-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.aucra-clause-number {
  font-size: 1.35rem;
  color: var(--gold-deep);
}
/* One row, never two: the number, the gap count and the chip keep their size
   and the title takes what is left, wrapping inside it. */
.aucra-clause-headline {
  flex-wrap: nowrap;
  gap: 16px;
}
.aucra-clause-headline > * {
  flex: 0 0 auto;
}
.aucra-clause-headline > .aucra-title {
  flex: 1 1 auto;
  min-width: 0;
}
/* Below 640px of the head's own width (a phone, or 1024 with the assistant
   drawer open) one line is too narrow for the number, the title and the chip:
   the chip sat on the title. The title claims most of the first line, so the
   gap count and the chip wrap to a line of their own under it. The head is
   the container (`content.css`), never the viewport (FT2). */
@container aucra-clause-head (max-width: 639px) {
  .aucra-clause-headline {
    flex-wrap: wrap;
    gap: 8px 12px;
  }
  .aucra-clause-headline > * {
    max-width: 100%;
  }
  .aucra-clause-headline > .aucra-title {
    flex: 1 1 70%;
  }
}

/* ---- toasts (the "Saved" toast and every /debug call result) ---- */

/* A toast floats, so the floating scale of the softer look: 12px, the soft
   line, and the clause preview card's shadow (kit_fields.css). A negative,
   positive or warning toast keeps its own edge colour below. */
.q-notification {
  background: var(--panel) !important;
  border: 1px solid var(--soft-line);
  border-radius: 12px;
  box-shadow: var(--soft-float-shadow);
  font-family: var(--font-text);
  font-size: 13px;
  min-height: 0;
  padding: 6px 12px;
}
/* Quasar stacks a repeated "Saved" toast (`kit/saving.py`, `undo.py`) into
   one with a red count over its words, which reads as a failure (7.4 P2):
   the count is not drawn. */
.aucra-toast .q-notification__badge {
  display: none;
}
.q-notification .q-notification__message {
  padding: 0;
}
.q-notification.bg-negative {
  border-color: var(--warn);
}
.q-notification.bg-positive {
  border-color: var(--pass);
}
/* A warning, such as a change refused because someone else holds the row:
   the warn colour on the warn wash, as the mockups draw a notice. */
.q-notification.bg-warning {
  border-color: var(--warn);
}

/* Quasar puts `text-white` on every notification and paints a negative one
   `bg-negative`; both utilities are `!important` inside Quasar's own cascade
   layer, where an unlayered `!important` cannot reach them however specific it
   is (measured: white ink on the white panel, so every toast read as blank).
   An important declaration in an EARLIER layer does win, and NiceGUI declares
   `base` before `quasar`, hence this block. */
@layer base {
  .q-notification.text-white {
    color: var(--text) !important;
  }
  /* A negative toast is the warn colour on the warn wash, like every other
     negative surface in the app. */
  .q-notification.bg-negative {
    background: var(--warn-wash) !important;
  }
  .q-notification.bg-negative.text-white {
    color: var(--warn) !important;
  }
  .q-notification.bg-positive {
    background: var(--panel) !important;
  }
  .q-notification.bg-positive.text-white {
    color: var(--pass) !important;
  }
  /* Quasar paints a warning `bg-warning text-dark`, its own yellow. */
  .q-notification.bg-warning {
    background: var(--warn-wash) !important;
  }
  .q-notification.bg-warning.text-dark {
    color: var(--warn) !important;
  }
  /* A kit button a viewer cannot use (kit/readonly.guard) reads as off: grey
     words on the mist fill, as the mockups draw it, not Quasar's faded face
     that looks like a live one. */
  .q-btn.aucra-btn-ghost.disabled,
  .q-btn.aucra-btn-ghost[disabled] {
    background: var(--mist) !important;
    color: var(--placeholder) !important;
    border: 1px solid var(--line) !important;
    opacity: 1 !important;
    cursor: default !important;
  }
}

/* ---- one focus vocabulary ---- */

.aucra-nav:focus-visible,
.aucra-clause:focus-visible,
.aucra-step:focus-visible,
.aucra-row-link:focus-visible,
.aucra-input-link:focus-visible,
.aucra-open-link:focus-visible,
.aucra-row-delete:focus-visible,
.aucra-toggle-option:focus-visible,
.aucra-tabs .q-tab:focus-visible,
.aucra-btn:focus-visible,
.aucra-ai-tab:focus-visible,
.aucra-user:focus-visible,
.aucra-editor .q-editor__toolbar .q-btn:focus-visible,
.aucra-outline-row:focus-visible,
.aucra-threshold-chip:focus-visible,
.aucra-guidance .q-item:focus-visible,
.aucra-matrix-cell .q-field__native:focus-visible,
select.aucra-select:focus-visible,
.q-btn.aucra-icon-btn:focus-visible,
.q-btn.aucra-btn-text:focus-visible {
  /* !important beats Quasar's .no-outline, which otherwise removes the ring
     from every button it draws, the applicability toggle included. */
  outline: 2px solid var(--focus-ring) !important;
  outline-offset: 2px;
}
/* Quasar draws its buttons with the class `no-outline`, and its own sheet wins
   the outline back even from an !important rule, so a button's focus ring is a
   shadow instead: the applicability toggle and the editor toolbar. On a picked
   option it replaces the gold edge, 5.20:1 on the gold wash. */
.aucra-toggle-option:focus-visible,
.aucra-editor .q-editor__toolbar .q-btn:focus-visible {
  box-shadow: inset 0 0 0 2px var(--focus-ring);
}
/* The same for every kit button: Quasar's importants sheet sits in a cascade
   layer, and an important rule in a layer beats an unlayered one, so the
   outline above never lands on a q-btn. The ring is drawn outside the box, the
   way outline-offset draws it on the other controls. */
.q-btn.aucra-btn:focus-visible,
.q-btn.aucra-icon-btn:focus-visible,
.q-btn.aucra-row-delete:focus-visible {
  box-shadow: 0 0 0 2px var(--focus-ring);
}
/* The Dashboard row's delete showed only Quasar's pale focus helper. */
.aucra-row-delete .q-focus-helper {
  display: none;
}

/* The header's two menu buttons are q-btns too, so they take the same shadow
   ring; without it Quasar's own white focus helper is all a keyboard reader
   gets, on a wash that is already white. */
.q-btn.aucra-menu-btn:focus-visible {
  box-shadow: 0 0 0 2px var(--focus-ring);
}
.aucra-menu-btn .q-focus-helper {
  display: none;
}

/* A text box and a text area take the focus on their native input, and the
   class that says so lands on the field root, so the ring is drawn on the
   control the reader sees rather than on the input inside it. */
.aucra-control.q-field--focused .q-field__control {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
/* The rich text editor clips an outward ring on its own box, so the ring is
   drawn on the wrapper when the editable area holds the caret. The toolbar
   buttons inside it keep their own inset ring and never double this one. */
.aucra-editor:has(.q-editor__content:focus-visible) {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 6px;
}
/* The checkbox draws no outline of its own, whichever of the two elements
   takes the caret, so the ring goes on the box the reader is looking at. */
.aucra-check:focus-visible .q-checkbox__inner,
.aucra-check:has(.q-checkbox__native:focus-visible) .q-checkbox__inner {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* ---- Quasar's own motion, at the brand.css pace ----

   A menu or a dialog writes its 300 ms inline as --q-transition-duration, so
   only an important rule replaces it; the tooltip keeps its own. */
.q-menu,
.q-dialog__inner,
.q-dialog__backdrop {
  --q-transition-duration: var(--motion-base) !important;
  --q-transition-easing: var(--ease-out) !important;
}
/* The fold writes its height transition inline. Quasar ends the slide by a
   timer at 1.1 times its 300 ms prop, so --motion-base stays under 330ms. */
.q-expansion-item__content {
  transition: height var(--motion-base) var(--ease-out) !important;
}
.q-expansion-item__toggle-icon {
  transition: transform var(--motion-base) var(--ease-in-out);
}
@media (prefers-reduced-motion: reduce) {
  aside.q-drawer--left,
  .q-page-container,
  .nav-label,
  .aucra-collapsible,
  .aucra-nav,
  .aucra-clause,
  .aucra-row,
  .aucra-step,
  .aucra-status,
  .aucra-search .q-field__control,
  .aucra-tabs .q-tab,
  .aucra-editor .q-editor__toolbar .q-btn,
  .aucra-outline-row,
  .aucra-threshold-chip,
  .aucra-ai-tab .tab-chevron,
  .aucra-ai-tab .tab-spark,
  .aucra-ai-tab stop,
  .aucra-content-window .aucra-tool-side,
  .aucra-content-window .aucra-tool-checks-side,
  .aucra-content-window .aucra-tool-main {
    transition: none !important;
  }
  /* Quasar's slide transition writes the height and its transition onto the
     element itself, so only an important rule reaches it: the fold's height
     jumps in one frame instead of sliding. */
  .q-expansion-item__content {
    transition: none !important;
    animation: none !important;
  }
  .aucra-ai-tab:hover .tab-icon {
    animation: none;
  }
  /* Quasar's own component transitions ignore the setting: the field's
     border line, and the tooltip and menu, which enter and leave through the
     q-transition--* classes Vue adds for the named transition. The duration
     is a custom property Quasar also writes inline, so the rule is important
     and removes the transition itself. */
  .q-field__control:before,
  .q-field__control:after,
  .q-tooltip,
  .q-menu,
  [class*="q-transition--"] {
    transition: none !important;
    animation: none !important;
  }
}
@media (prefers-reduced-motion: reduce) {
  .q-expansion-item__toggle-icon {
    transition: none;
  }
  /* One rule for the whole app (#51): the rules above name the motion they
     know of, and Quasar's others slipped through, such as the hover fade on
     every button and list item. A near zero duration, not none, so code that
     waits for transitionend or animationend still hears it. */
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
  }
}
/* Quasar slides the drawers and the content beside them at 0.12s under this
   body class, for 155 ms only, from NiceGUI's quasar_importants layer, which
   outranks any unlayered important rule; so these join that layer. A running
   transition keeps the duration it started with, so the slide runs its full
   length after the class goes. */
@layer quasar_importants {
  .q-body--layout-animate .q-layout aside.q-drawer {
    transition: transform var(--motion-slow) var(--ease-in-out), width var(--motion-slow) var(--ease-in-out),
      top var(--motion-slow) var(--ease-in-out), bottom var(--motion-slow) var(--ease-in-out) !important;
  }
  .q-body--layout-animate .q-layout .q-page-container {
    transition: padding var(--motion-slow) var(--ease-in-out) !important;
  }
  .q-body--layout-animate .q-layout .q-layout__section--marginal {
    transition: transform var(--motion-slow) var(--ease-in-out), left var(--motion-slow) var(--ease-in-out), right var(--motion-slow) var(--ease-in-out) !important;
  }
  .q-body--layout-animate .q-layout .q-drawer__backdrop {
    transition: background-color var(--motion-slow) var(--ease-out) !important;
  }
  @media (prefers-reduced-motion: reduce) {
    .q-body--layout-animate .q-layout aside.q-drawer,
    .q-body--layout-animate .q-layout .q-page-container,
    .q-body--layout-animate .q-layout .q-layout__section--marginal,
    .q-body--layout-animate .q-layout .q-drawer__backdrop {
      transition: none !important;
    }
  }
}

/* ---- content region ---- */

/* The one container ui.sub_pages swaps; positioned so the loading veil and the
   error panel can cover the content without touching the shell. */
.aucra-region {
  position: relative;
  min-width: 0;
  container: aucra-workspace / inline-size;
}
/* The assistant's edge handle (brand.css, 30px at the right edge, halfway
   down) sits over the page while the drawer is shut: from 1024px the panels
   keep a 36px gutter for it. A page on the 896px measure takes the gutter
   only while its column would reach the handle (a region under 968px), so a
   wider region keeps the column centred as the artboards draw it and the
   outline's width test (content_text.css) reads the whole region; the
   outline keeps clear of the handle by its own margin there. The Dashboard's wider
   measure and a tool window keep the gutter always. On a phone the panels
   already end 32px in from the edge, 8px past the narrower handle. */
@media (min-width: 1024px) {
  body:has(button.aucra-ai-tab:not(.aucra-ai-tab-open))
    .aucra-region:not(:has(.aucra-content.max-w-4xl)) {
    padding-right: 36px;
  }
  @container aucra-workspace (max-width: 967.98px) {
    body:has(button.aucra-ai-tab:not(.aucra-ai-tab-open)) .aucra-subpages {
      padding-right: 36px;
    }
  }
}

/* ---- loading veil ---- */

/* Covers the content region only (see .aucra-region above). Two modes: the
   loading veil with the ring and its label, and the frozen veil a dropped
   socket leaves behind, which says nothing because nothing is in progress. */
.aucra-veil {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 5;
  background: color-mix(in srgb, var(--panel) 55%, transparent);
  backdrop-filter: blur(6px);
  font-size: 0.81rem;
  color: var(--muted);
}
.aucra-veil-loading,
.aucra-veil-navigating,
.aucra-veil-frozen {
  display: block;
}
/* The content region can be many viewports tall, so the ring and the label
   ride in a sticky body instead of being centred on the whole region. Both
   offsets are set and the body is exactly the height between them, so it is
   centred on the visible part of the region at any scroll position. The header
   is fixed and 56px tall; `backdrop-filter` above makes .aucra-veil a
   containing block, so `position: fixed` would not escape it either. */
.aucra-veil-body {
  position: sticky;
  top: 56px;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  height: calc(100vh - 56px);
  max-height: 100%;
}
/* ui.sub_pages empties the region the moment a navigation starts, so a veil
   over a slow page would otherwise be a strip at the top of nothing. */
.aucra-region:has(> .aucra-veil-loading),
.aucra-region:has(> .aucra-veil-navigating),
.aucra-region:has(> .aucra-veil-frozen) {
  min-height: 320px;
}
.aucra-veil-ring {
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid var(--line);
  border-top-color: var(--gold);
  animation: aucra-spin 0.9s linear infinite;
}
.aucra-veil-frozen .aucra-veil-ring,
.aucra-veil-frozen .aucra-veil-label {
  display: none;
}
@keyframes aucra-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ---- connection banner and the header's cloud states ---- */

.aucra-banner {
  display: none;
  align-items: center;
  gap: 10px;
  height: 36px;
  padding: 0 18px;
  background: var(--warn-wash);
  color: var(--warn);
  font-size: 0.81rem;
}
.aucra-banner-on {
  display: flex;
}
.aucra-banner-icon {
  font-size: 18px;
}

.aucra-status-slot {
  display: inline-flex;
  align-items: center;
}
.aucra-status-icon {
  display: none;
  font-size: inherit;
  color: inherit;
}
.aucra-status-online {
  display: inline-flex;
}
.aucra-status-slot.aucra-status-reconnecting .aucra-status-online,
.aucra-status-slot.aucra-status-offline .aucra-status-online {
  display: none;
}
.aucra-status-slot.aucra-status-reconnecting .aucra-status-syncing {
  display: inline-flex;
  color: var(--chrome-gold);
}
/* The slot is the header's alone: --chrome-warn reads 5.02:1 on the light
   chrome, and the slate's orange 4.31:1 where --warn read 1.94:1. */
.aucra-status-slot.aucra-status-offline .aucra-status-gone {
  display: inline-flex;
  color: var(--chrome-warn);
}

/* NiceGUI's own "Connection lost" overlay: the banner and the frozen veil say
   the same thing inside the shell, so its popup stays out of the way. */
#popup.nicegui-error-popup {
  display: none !important;
}

/* ---- the error panel of a page that could not be built ---- */

/* The head is a band on the warn wash, the way a section head is a band on
   the head wash: an inset bar followed the soft panel's 16px corner into a
   crescent. On the wash the icon reads 4.51:1 (--warn) and the title
   13.04:1 (--text). */
.aucra-error-head {
  padding: 14px 18px;
  background-color: var(--warn-wash);
}
.aucra-error-icon {
  color: var(--warn);
  font-size: 18px;
}
.aucra-error-route {
  font-size: 0.75rem;
  color: var(--muted);
}
.aucra-error-copy {
  font-size: 0.81rem;
}

@media (prefers-reduced-motion: reduce) {
  .aucra-veil-ring {
    animation: none;
  }
}
