/* ==========================================================================
   Settings: the custom-field add row and the two blocking overlays the
   page puts up while the server restarts or a model is being tested.
   @layer pages: above the framework layers, below utilities.
   ========================================================================== */

@layer pages {
  /* --- blocking overlays (restart, model test) ---------------------------- */
  /* Both partials are toggled as a whole, so the spacing belongs to the
     elements rather than to a rule between them. */
  #modelTestOverlay .zr-fullscreen__card > .zr-row:first-child,
  #restartOverlay .zr-fullscreen__card > .zr-row:first-child {
    margin-bottom: var(--zr-3);
  }
  #restartOverlayPercent {
    margin-top: var(--zr-1);
    text-align: right;
  }
  #restartOverlayActions {
    margin-top: var(--zr-3);
    justify-content: flex-end;
  }

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

  /* An old link to a section (#sec-provider) opens its topic and scrolls the
     section into view; it lands below the sticky topbar, not under it. */
  .zr-settings .zr-module[id^='sec-'] {
    scroll-margin-top: calc(var(--zr-topbar-h) + var(--zr-4));
  }

  /* Sixty-odd settings rows separated by nothing but 16px of air read as one
     wall of controls: nothing says where a setting starts or ends. Rows get what
     rows get everywhere else in the app — a hairline between them and a hover
     band — drawn the way .zr-table draws them, from card edge to card edge, which
     the body's own padding has to be undone for.

     Scoped to a card's own body: the changelog uses .zr-module__body as a bare
     layout wrapper outside any .zr-module, where the release timeline brings its
     own rhythm and there is no card box for a full-bleed band to bleed into. */
  .zr-settings .zr-module > .zr-module__body.zr-col--loose {
    gap: 0;
  }
  /* With the gap gone the rows space themselves, and they ask whether anything is
     rendered above them with the general sibling combinator rather than the
     adjacent one: half of this form is toggled with .hidden and the custom-field
     list is an empty box until a field is added, so the row below one of those
     would otherwise be spaced and ruled off against nothing. */
  .zr-settings
    .zr-module
    > .zr-module__body.zr-col--loose
    > *:not(.hidden, #customFieldsList:not(:has(*)))
    ~ * {
    margin-top: var(--zr-4);
  }
  /* A switch tile, an alert or a lone button draws a box of its own, which makes
     it the exception to both rules below: it keeps the spacing the gap used to
     give it, and it never carries a hairline — the line would run along its own
     border, and the padding that comes with the line would push its content off
     centre. One switch row is wrapped in a field instead of coming from the
     partial, which is what the :has() catches. */
  .zr-settings
    .zr-module
    > .zr-module__body.zr-col--loose
    > *:not(.zr-switchrow, .zr-alert, .zr-btn, :has(> .zr-switchrow)) {
    /* The inset is part of the row at rest, not only under the pointer: added on
       hover, every row would shift sideways as its band appears. */
    margin-inline: calc(var(--zr-3) * -1);
    padding-inline: var(--zr-3);
  }
  .zr-settings
    .zr-module
    > .zr-module__body.zr-col--loose
    > *:not(.hidden, #customFieldsList:not(:has(*)))
    ~ *:not(.zr-switchrow, .zr-alert, .zr-btn, :has(> .zr-switchrow)) {
    border-top: 1px solid var(--zr-line);
    padding-top: var(--zr-3);
    margin-top: var(--zr-3);
  }

  /* The OCR block is a whole list of settings inside one .zr-field, so its rows
     are not the body's rows and none of the above reaches them — they were left
     5px apart, the spacing meant for a label and its input. They at least get the
     air the body gives its own rows. */
  .zr-settings .zr-module__body > .zr-field--stacked:has(.zr-field--stacked) {
    gap: var(--zr-4);
  }

  /* Only the fields light up: a hint or a heading is nothing to point at. A field
     holding other fields is a wrapper rather than a row — #ocrFieldsContainer is
     a .zr-field around the entire OCR block, and lighting that up would paint
     half the card. */
  .zr-settings
    .zr-module
    > .zr-module__body.zr-col--loose
    > .zr-field--stacked:not(:has(.zr-field--stacked, .zr-switchrow)):hover {
    background: var(--zr-surface-2);
  }
  /* The unsaved-change marker hangs one body padding to the left of its field —
     which, measured from a full-bleed row, is outside the card, where the
     module's overflow: hidden eats it. Zero puts it back on the same pixel. */
  .zr-settings
    .zr-module
    > .zr-module__body.zr-col--loose
    > .zr-field[data-dirty]:not(:has(> .zr-switchrow))::before {
    left: 0;
  }

  /* The "field name + type + Add" row: its controls sit in wrapper divs (a bare
     width:100% control would hijack the whole flex row), so the generic
     full-width phone rule cannot reach them. Stack the wrappers instead. */
  @media (max-width: 860px) {
    .customfield-add > div {
      flex: 1 1 100%;
    }
    /* The currency select hides until the type is monetary; stacked, its empty
       wrapper would still claim a row of gap. */
    .customfield-add > div:has(> .hidden:only-child) {
      display: none;
    }
  }

  /* --- one topic per view (js/modules/settings-nav.js) ------------------- */

  /* The topic list is wider than the old section list: the entries are names
     ("Schedule and tag filters"), not single words. */
  .zr-settings {
    grid-template-columns: 220px minmax(0, 1fr);
  }

  .zr-settings-nav {
    gap: var(--zr-3);
  }
  .zr-settings-nav__group {
    display: flex;
    flex-direction: column;
    gap: 1px;
  }
  .zr-settings-nav__label {
    display: flex;
    align-items: center;
    gap: var(--zr-2);
    padding: 0 var(--zr-2) var(--zr-1);
    font-size: var(--zr-fs-xs);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--zr-text-faint);
  }
  .zr-settings-nav a {
    font-weight: 500;
  }
  /* A topic with edits that are not saved yet, wherever they are. */
  .zr-settings-nav__dirty {
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: var(--zr-r-full);
    background: var(--zr-brand);
  }
  /* While searching, topics without a match step back but stay clickable. */
  .zr-settings-nav__miss {
    opacity: 0.4;
  }

  .zr-settings-picker .zr-input {
    width: 100%;
  }

  /* The search sits above both columns; its results float over the page. */
  .zr-settings-search__box {
    position: relative;
    flex: 1 1 320px;
    max-width: 520px;
  }
  .zr-settings-search__box > .zr-icon {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--zr-text-faint);
    pointer-events: none;
  }
  .zr-settings-search__box > .zr-input {
    width: 100%;
    padding-left: 32px;
  }
  .zr-settings-search__results {
    position: absolute;
    z-index: 30;
    top: calc(100% + var(--zr-1));
    left: 0;
    right: 0;
    max-height: min(420px, 60dvh);
    overflow-y: auto;
    padding: var(--zr-1);
    background: var(--zr-surface);
    border: 1px solid var(--zr-line);
    border-radius: var(--zr-r-lg);
    box-shadow: var(--zr-shadow-lg);
  }
  .zr-settings-search__item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0 var(--zr-2);
    width: 100%;
    padding: var(--zr-2);
    border: 0;
    border-radius: var(--zr-r-md);
    background: transparent;
    color: var(--zr-text);
    text-align: left;
    cursor: pointer;
  }
  .zr-settings-search__item:hover,
  .zr-settings-search__item[aria-selected='true'] {
    background: var(--zr-brand-soft);
  }
  .zr-settings-search__name {
    font-weight: 600;
  }
  .zr-settings-search__path {
    grid-column: 1;
    font-size: var(--zr-fs-xs);
    color: var(--zr-text-muted);
  }
  .zr-settings-search__key {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    font-family: var(--zr-font-mono);
    font-size: var(--zr-fs-xs);
    color: var(--zr-text-muted);
  }
  .zr-settings-search__empty {
    padding: var(--zr-2);
  }

  /* The topic's own head: group label, then the topic as the page heading. */
  .zr-settings-entry__head {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .zr-settings-entry__titlerow {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--zr-2);
  }
  .zr-settings-entry__title {
    font-family: var(--zr-font-brand);
    font-size: var(--zr-fs-xl);
    font-weight: 700;
    letter-spacing: -0.01em;
  }
  /* "On, but incomplete: ..." can be a sentence; it wraps instead of
     running out of the column. */
  .zr-settings-entry__status {
    white-space: normal;
    max-width: 100%;
  }

  /* The variable a field writes, named at the start of its hint. */
  .zr-envkey {
    font-family: var(--zr-font-mono);
    font-size: 0.95em;
    color: var(--zr-text-muted);
  }

  /* The row a search result or an error opened, for a moment. */
  .zr-settings-flash {
    animation: zr-settings-flash 1.6s var(--zr-ease);
  }
  @keyframes zr-settings-flash {
    0%,
    40% {
      background: var(--zr-brand-soft);
    }
    100% {
      background: transparent;
    }
  }

  /* --- single sign-on ---------------------------------------------------- */
  .zr-sso-preview {
    display: flex;
    flex-direction: column;
    gap: var(--zr-2);
  }
  /* A slice of the login card, on the login page's own canvas. */
  .zr-sso-preview__card {
    max-width: 360px;
    padding: var(--zr-4);
    border: 1px solid var(--zr-line);
    border-radius: var(--zr-r-lg);
    background: var(--zr-canvas);
  }
  .zr-sso-preview__card .login-sso__button {
    pointer-events: none;
  }
  .zr-sso-swatch {
    flex: none;
    align-self: stretch;
    width: 30px;
    border: 1px solid var(--zr-line-strong);
    border-radius: var(--zr-r-md);
    background: repeating-conic-gradient(
        var(--zr-surface-2) 0% 25%,
        var(--zr-surface) 0% 50%
      )
      50% / 10px 10px;
  }
  .zr-sso-swatch[data-state='invalid'] {
    border-color: var(--zr-danger);
  }
  .zr-input[aria-invalid='true'] {
    border-color: var(--zr-danger);
  }

  .zr-sso-advanced > summary {
    cursor: pointer;
    list-style: none;
  }
  .zr-sso-advanced > summary::-webkit-details-marker {
    display: none;
  }
  .zr-sso-advanced:not([open]) > summary {
    border-bottom: 0;
  }
  .zr-sso-advanced[open] > summary > .zr-icon {
    transform: rotate(180deg);
  }

  @media (max-width: 860px) {
    .zr-settings {
      grid-template-columns: minmax(0, 1fr);
    }
    .zr-settings-search__box {
      max-width: none;
    }
    .zr-settings-entry__title {
      font-size: var(--zr-fs-lg);
    }
  }
}
