/* The frame of every page and the pieces every area shares: forms, buttons,
   the error summary, notices, the empty state, tables, file lists, status
   labels. The screens of an area are styled in the stylesheet of that area
   (admin.css, cabinet.css and so on), which the layout links after this file;
   nothing area-specific is added here.

   Colors, fonts, the radius and the spacing come from the variables of the
   theme and from nowhere else: a test fails on a literal color.

   Two breakpoints serve the whole interface, and a stylesheet uses no other
   width in a media query:

     (max-width: 40rem)  narrow: a phone. One column, tables as cards or in
                         a scroll container, touch targets 44px high.
     (min-width: 64rem)  wide: room for the menu of staff at the side.

   Between them the page is the same one column as on a phone, only wider.
   A media query counts in the font size of the browser, not of the theme,
   so the breakpoints do not move with --font-size-base. */

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

html {
  font-size: var(--font-size-base);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* A long word, an address or a file name breaks instead of making the page
   wider than the screen. */
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  line-height: 1.5;
  overflow-wrap: break-word;
}

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

/* The mark of keyboard focus, the same for everything that takes it. The
   color is the one of links, which the contrast check holds against the
   page and against a surface in both variants of the theme. No rule of any
   stylesheet takes the outline away. */
:focus-visible {
  outline: 3px solid var(--color-link);
  outline-offset: 2px;
}

/* Drawn inside, where the edge of the screen cannot cut it off. */
main:focus-visible { outline-offset: -3px; }

/* For assistive technology only: read, never seen. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Text without spaces that sits in a table cell or in a row of a flexible
   box: an email address, a file name, an identifier. Such a place is as
   wide as its longest word unless the word may break anywhere. */
.wrap { min-width: 0; overflow-wrap: anywhere; }

/* The first stop of the Tab key on every page. It is out of sight until it
   has the focus. */
.skip-link {
  position: absolute;
  top: var(--space);
  left: var(--space);
  z-index: 10;
  padding: var(--space) calc(var(--space) * 2);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  transform: translateY(-300%);
}

.skip-link:focus { transform: none; }

.site-header, main, .site-footer {
  max-width: 46rem;
  margin: 0 auto;
  padding: calc(var(--space) * 2);
}

/* The header wraps: on a phone the name of the site, the account and the
   language switch stand one under another. */
.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space) calc(var(--space) * 2);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space);
  min-width: 0;
  color: var(--color-text);
  font-weight: 600;
  text-decoration: none;
}

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

/* The logo is a picture next to the name, which stays a text: the name is
   what a screen reader says, and it is translated. A very wide logo is
   scaled down rather than pushing the name off a phone. */
.brand-logo {
  flex: none;
  width: auto;
  height: var(--logo-height);
  max-width: 60vw;
  object-fit: contain;
  object-position: left center;
}

.lang-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space);
  margin: 0;
  font-size: 0.875rem;
}

main {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: calc(var(--space) * 3);
}

h1 {
  margin: 0 0 calc(var(--space) * 2);
  font-size: 1.5rem;
  line-height: 1.25;
}

h2 { margin: calc(var(--space) * 3) 0 var(--space); font-size: 1.15rem; line-height: 1.3; }
h3 { margin: calc(var(--space) * 2) 0 var(--space); font-size: 1rem; }

pre, code { font-family: var(--font-mono); }
pre { white-space: pre-wrap; overflow-wrap: anywhere; }

.muted { color: var(--color-muted); font-size: 0.875rem; }

/* The link to the product, and for staff the version of the CRM beside it. */
.site-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space);
  font-size: 0.875rem;
}

.account {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space);
  min-width: 0;
  font-size: 0.875rem;
}

.account .muted { min-width: 0; overflow-wrap: anywhere; }
.account form { margin: 0; }

/* The menu of a logged-in user; its entries come from the areas. */
.site-nav {
  max-width: 46rem;
  margin: 0 auto;
  padding: 0 calc(var(--space) * 2) var(--space);
  font-size: 0.875rem;
}

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space) calc(var(--space) * 2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav a[aria-current="page"] {
  color: var(--color-text);
  font-weight: 600;
  text-decoration: none;
}

/* Forms. A control never has text smaller than 16px: a phone zooms into a
   smaller one when it gets the focus. The stylesheet of an area therefore
   sets no font on a control. */
input, select, textarea, button { font: inherit; }

input, select, textarea {
  font-size: 16px;
  font-size: max(1rem, 16px);
  max-width: 100%;
}

select, button {
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: calc(var(--space) / 2) var(--space);
}

button { cursor: pointer; }

input[type="email"], input[type="text"], input[type="number"], input[type="search"],
input[type="date"], input[type="tel"], input[type="url"], textarea {
  width: 100%;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space);
}

input[type="file"] { max-width: 100%; }

.stack {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space);
  max-width: 24rem;
}

.stack.wide { max-width: none; align-items: stretch; }

/* A field: its label, its help, the control, its error. */
.field { display: flex; flex-direction: column; gap: calc(var(--space) / 2); min-width: 0; }

.help { margin: 0; color: var(--color-muted); font-size: 0.875rem; }

.error { color: var(--color-danger); }
.field .error { margin: 0; }

/* A refused field differs by its frame, and by its message in words. */
[aria-invalid="true"] {
  border-color: var(--color-danger);
  box-shadow: inset 0 0 0 1px var(--color-danger);
}

fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
fieldset[aria-invalid="true"] { padding-left: var(--space); box-shadow: inset 3px 0 0 var(--color-danger); }
legend { padding: 0; margin-bottom: calc(var(--space) / 2); }

.option { display: flex; align-items: baseline; gap: var(--space); }
.option.unknown { color: var(--color-muted); font-size: 0.875rem; }

.actions { display: flex; flex-wrap: wrap; gap: var(--space); margin-top: var(--space); }

button.primary {
  color: var(--color-on-primary);
  background: var(--color-primary);
  border-color: var(--color-primary);
  padding: var(--space) calc(var(--space) * 2);
}

a.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: calc(var(--space) / 2) var(--space);
  text-decoration: none;
}

a.button.primary {
  color: var(--color-on-primary);
  background: var(--color-primary);
  border-color: var(--color-primary);
  padding: var(--space) calc(var(--space) * 2);
}

/* Loading: static/js/forms.js marks the button that sent a form as busy and
   disables the buttons of the form until the answer arrives. */
button:disabled { opacity: 0.6; cursor: not-allowed; }
button[aria-busy="true"] { cursor: progress; }

button[aria-busy="true"]::after {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  margin-left: var(--space);
  vertical-align: -0.15em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: busy-turn 0.8s linear infinite;
}

@keyframes busy-turn {
  to { transform: rotate(360deg); }
}

/* The only thing that moves on a page. For a viewer who asked for no
   motion the ring stands still, and still says "busy". */
@media (prefers-reduced-motion: reduce) {
  button[aria-busy="true"]::after { animation: none; }
}

/* The error summary, templates/_errors.html: what a form refused, on top of
   the form, each entry a link to its field. */
.error-summary {
  margin: 0 0 calc(var(--space) * 2);
  padding: var(--space) calc(var(--space) * 2);
  border: 2px solid var(--color-danger);
  border-radius: var(--radius);
}

.error-summary-title { margin: 0 0 var(--space); color: var(--color-danger); font-weight: 600; }
.error-summary ul { margin: 0; padding-left: calc(var(--space) * 2.5); }
.error-summary li { color: var(--color-danger); }
.error-summary a { color: var(--color-danger); }

/* A notice: what the page says about the action before it. The plain one
   informs; the variants confirm, warn and refuse. The kind is in the words
   as well, never in the color alone. */
.notice {
  margin: calc(var(--space) * 2) 0;
  padding: var(--space) calc(var(--space) * 2);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-info);
  border-radius: var(--radius);
}

.notice-success { border-left-color: var(--color-success); }
.notice-warning { border-left-color: var(--color-warning); }
.notice-error { border-left-color: var(--color-danger); }
.notice > :first-child { margin-top: 0; }
.notice > :last-child { margin-bottom: 0; }

/* The empty state of a list: a sentence saying what will appear here and,
   under it, the next action. */
.empty {
  margin: calc(var(--space) * 2) 0;
  padding: calc(var(--space) * 3) calc(var(--space) * 2);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius);
  text-align: center;
}

.empty p { margin: 0 0 var(--space); }
.empty > :last-child { margin-bottom: 0; }

.files { list-style: none; margin: 0 0 calc(var(--space) * 2); padding: 0; }
.files li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space);
  padding: var(--space) 0;
  border-bottom: 1px solid var(--color-border);
}
.files li > span, .files li > a { min-width: 0; overflow-wrap: anywhere; }
.files form { margin: 0; }

.answers dl { margin: 0; }
.answers dt { margin-top: var(--space); color: var(--color-muted); font-size: 0.875rem; }
.answers dd { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }

/* A field for scripts only: people never see or reach it. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Tables. A table is never left to make a phone scroll sideways as a whole
   page; it takes one of two forms there.

   .table-scroll  a container around a table of five columns or more. The
                  table keeps its shape and scrolls inside the container,
                  which is reachable from the keyboard and has a name:
                  <div class="table-scroll" role="region" tabindex="0"
                       aria-labelledby="id of the heading above">.
   .cards         on a table of up to four columns: <table class="list
                  cards">. On a narrow screen every row becomes a block and
                  every cell a line of it, under the name of its column,
                  which the cell carries as data-label. */
.list { width: 100%; border-collapse: collapse; }
.list th, .list td { text-align: left; padding: var(--space); border-bottom: 1px solid var(--color-border); vertical-align: top; }
.list th { color: var(--color-muted); font-size: 0.875rem; font-weight: normal; }

.table-scroll { overflow-x: auto; margin-bottom: calc(var(--space) * 2); }
.table-scroll th, .table-scroll td { white-space: nowrap; }
.table-scroll .wrap { min-width: 12rem; white-space: normal; }

.pager { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space) * 2); margin: calc(var(--space) * 2) 0; }
.pager-position { color: var(--color-muted); font-size: 0.875rem; }

.status { font-weight: 600; }
.status-new, .status-in_progress { color: var(--color-info); }
.status-waiting_client { color: var(--color-warning); }
.status-resolved { color: var(--color-success); }
.status-closed { color: var(--color-muted); }

/* Narrow: a phone. */
@media (max-width: 40rem) {
  .site-header, .site-footer { padding: var(--space) calc(var(--space) * 2); }
  main { padding: calc(var(--space) * 2); border-left: 0; border-right: 0; border-radius: 0; }

  .stack { max-width: none; align-items: stretch; }

  /* The header row of a card table is kept for screen readers; a sighted
     reader gets the name of a column in front of each value. */
  .cards thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
  .cards, .cards tbody, .cards tr, .cards th, .cards td { display: block; }
  .cards tr { padding: var(--space) 0; border-bottom: 1px solid var(--color-border); }
  .cards th, .cards td { padding: calc(var(--space) / 4) 0; border: 0; overflow-wrap: anywhere; }
  .cards td[data-label]::before {
    content: attr(data-label);
    display: block;
    color: var(--color-muted);
    font-size: 0.875rem;
  }
}

/* What a finger presses is at least 44px high: on a phone, and on any
   screen that is touched. Links inside a sentence are left as they are. */
@media (max-width: 40rem), (pointer: coarse) {
  button, select, a.button,
  input[type="email"], input[type="text"], input[type="number"], input[type="search"],
  input[type="date"], input[type="tel"], input[type="url"], input[type="file"] {
    min-height: 44px;
  }

  .site-nav a, .pager a, .account > a, .skip-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .site-nav ul { gap: 0 calc(var(--space) * 2); }

  .option { min-height: 44px; align-items: center; }
}

/* The page of the privacy policy: a text, and the storage periods of the
   installation under it, each period beside what it is the period of. */
.policy-periods > div {
  padding: calc(var(--space) / 2) 0;
  border-top: 1px solid var(--color-border);
}
.policy-periods dt { font-weight: 600; }
.policy-periods dd { margin: 0; }

/* The button "Copy" under a multi-line field (static/js/copy.js). */
.copy-field {
  display: block;
  margin: 0.25rem 0 0;
  padding: 0.15rem 0.5rem;
  font-size: 0.8rem;
}
