/**
 * Panel Asisa Vida — the parts of the design that inline styles cannot carry.
 *
 * The screens keep their layout in inline styles, exactly as the design writes
 * them, so a value can be compared against the design side by side. What has
 * to live here is everything a `style` attribute has no syntax for: hover
 * states, focus rings, and the placeholder colour.
 *
 * Each rule below names the element it belongs to and repeats the design's own
 * hover declaration verbatim. Nothing here introduces a colour of its own.
 */

/* ---- Reset ------------------------------------------------------------- */

html,
body {
  margin: 0;
  padding: 0;
  background: var(--surface-page);
}

* {
  box-sizing: border-box;
}

/* `hidden` has to beat the inline `display` the screens set on the elements it
   is toggled on -- an overlay, a sentinel, a spinner. Without this the UA's own
   `[hidden] { display: none }` loses to the style attribute and every one of
   them renders open. The `<noscript>` rule in base.html is more specific still,
   so a collapsed panel with no JavaScript stays open. */
[hidden] {
  display: none !important;
}

a {
  color: var(--brand-accent);
  text-decoration: none;
}

a:hover {
  color: var(--brand-accent-hover);
  text-decoration: underline;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-thumb {
  background: var(--brand-grey);
  border-radius: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

/* ---- Sidebar ----------------------------------------------------------- */

/* Nav items are links, so the global anchor hover has to be undone before the
   design's own background wash is applied. */
.nav-item,
.nav-item:hover {
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
}

.nav-item:hover {
  background: rgba(255, 255, 255, 0.12) !important;
}

/* Signing out is a POST, so the design's icon is a submit button and has a
   browser's button chrome to shed before it looks like the icon again. */
.logout-button {
  display: flex;
  padding: 0;
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, 0.65);
  cursor: pointer;
  transition: color var(--transition-fast);
}

.logout-button:hover {
  color: #fff;
}

/* The way out of the confirmation the sign-out button opens. It is the only
   button on the screen that has to read as the lesser of two, so it carries
   the card's own surface and answers hover with the border. */
.ghost-button:hover {
  border-color: var(--brand-accent-border-soft);
  background: var(--surface-subtle);
}

/* ---- Filter bar -------------------------------------------------------- */

.filter-button:hover {
  border-color: var(--brand-accent-border-soft);
}

.menu-option:hover {
  background: var(--surface-subtle);
}

.menu-option,
.menu-option:hover {
  color: var(--text-body);
  text-decoration: none;
}

/* The search field inherits the card's font; only the placeholder needs a
   colour of its own. */
.search-input::placeholder {
  color: var(--text-muted);
}

/* ---- Access screen ----------------------------------------------------- */

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

.reveal-button:hover {
  background: var(--surface-subtle);
  color: var(--brand-accent);
}

/* The button's fill, its border colour, its shadow and its cursor are declared
   here and not on the element, unlike every other measurement on this screen.
   All four change with the state -- the hover below, and the wait below that --
   and a `style` attribute beats any rule in this file, so declared inline they
   would have pinned all four to their idle values and the two rules under this
   one would have been ornaments. Which is what the hover was until now. */
.submit-button {
  background: var(--brand-accent);
  border: 1px solid var(--brand-accent);
  box-shadow: var(--shadow-btn);
  cursor: pointer;
  transition: background var(--transition-fast), opacity var(--transition-fast),
    box-shadow var(--transition-fast);
}

.submit-button:hover {
  background: var(--brand-accent-hover);
}

/* While the credentials are being checked the button is inert, and now it looks
   it. It used to keep its colour -- greying out reads a little like a refusal,
   and for the ~300ms this took locally that was the worse of the two readings.
   Deployed it is closer to 1.3s, and over that long a button that looks exactly
   as it did reads as a click that never landed; whoever is waiting clicks it
   again. So it goes flat and pale for as long as the answer takes, with
   "Verificando..." beside it saying which of the two it is.

   The hover is repeated because otherwise it still answers the cursor, and a
   button that brightens under the pointer is a button offering to be pressed. */
.submit-button:disabled,
.submit-button:disabled:hover {
  background: var(--brand-accent);
  opacity: 0.5;
  box-shadow: none;
  cursor: default;
}

/* The arrow of the wordmark spins when it is poked. One run, `login.js` takes
   the class off at `animationend`, and the next poke starts another. */
.logo-arrow.is-spinning {
  animation: rd-spin 0.75s cubic-bezier(0.34, 1.3, 0.64, 1) 1;
}

@keyframes rd-spin {
  0% {
    transform: rotate(0deg) scale(1);
  }
  45% {
    transform: rotate(200deg) scale(1.18);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}

/* ---- Waiting on the credentials ----------------------------------------

   One move, not a loop: the arrow turns twice on its own axis while
   `login.js` sends it to the middle of the window at the size the window can
   give it -- that half is a transition, declared on the element in the
   template, because the distance is measured rather than written. The wash
   under them puts the card behind glass rather than taking it away, so the
   arrow is seen leaving the wordmark it was part of.

   Both halves carry the same duration and the same curve, so the turn slows
   into the last of the growth and the arrow lands upright at full size rather
   than spinning on over a screen that has finished arriving. It does not stop
   there, though -- see `rd-settle` below, which is what the panel fades in
   over. */

/* One number for all three halves of the movement: the turn below, the travel
   declared on the element in the template, and the wait `login.js` holds the
   navigation for -- which it reads back off the computed style rather than
   being told. Changing this changes the movement and the wait together. */
:root {
  --turn-duration: 1.2s;
}

/* `forwards`, not `both`, on the second of them: `backwards` fill would have
   it applying its own first keyframe throughout the delay, and being the later
   animation it would win there -- which is to say the arrow would sit at
   `rotate(720deg)` from the first frame and never turn at all. */
.logo-arrow.is-turning {
  animation: rd-turn var(--turn-duration) ease-in-out both,
    rd-settle 6s linear var(--turn-duration) forwards;
}

@keyframes rd-turn {
  to {
    transform: rotate(720deg);
  }
}

/* And what is left of the wait after it arrives, which should not be a still
   frame. `login.js` prefetches the panel during the movement, so normally
   there is nothing here to cover -- but a cold task answers slowly whatever is
   asked of it, and an arrow stopped dead reads as a screen that has hung.

   So it does not stop, it drifts: a fixed rate rather than a curve, because
   this has no shape of its own to perform and no end it is heading for. It is
   only the screen saying it is still working, for however much longer that is.
   Six seconds is not a duration anything is expected to reach; it is long
   enough that the drift is still a drift whenever the panel cuts it off. */
@keyframes rd-settle {
  from {
    transform: rotate(720deg) scale(1);
  }
  to {
    transform: rotate(745deg) scale(1.25);
  }
}

/* No class to add: the layer is `hidden` until the submit, and an element that
   was `display: none` starts its animation the moment it is rendered. Hiding
   it again rewinds it, which is all the reset a cached page needs. It takes
   longer to arrive than the panel's own fade: the screen has to be seen going
   quiet, not found quiet. */
[data-turn-veil] {
  animation: rd-fade 0.45s ease both;
}

/* The screen the wait ends on. It arrives as a full page load -- there is no
   swap that could carry it in -- so this is where the fade lives. */
.app-shell {
  animation: rd-fade 0.3s ease both;
}

@keyframes rd-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* A reader who has asked for less motion gets none of this: `login.js` never
   shows the layer, and the submit is the plain post it always was. */
@media (prefers-reduced-motion: reduce) {
  .logo-arrow.is-spinning,
  .logo-arrow.is-turning,
  [data-turn-veil],
  .app-shell {
    animation: none;
  }
}

/* ---- Charts ------------------------------------------------------------ */

/* The hover bands laid over a line chart (`components/_hotspots.html`). The
   band itself is never drawn: what the pointer reveals is a guide down to the
   axis and a dot on each series, so the reader can see which bucket the
   tooltip is reading before they read it. */

.chart-hotspot {
  cursor: default;
}

.chart-guide,
.chart-dot {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-fast);
}

.chart-guide {
  top: 0;
  bottom: 0;
  width: 1px;
  margin-left: -1px;
  background: var(--border-strong);
}

.chart-dot {
  width: 7px;
  height: 7px;
  margin: 0 0 -4px -4px;
  border-radius: 50%;
  /* A ring in the card's own colour, so a dot sitting on the line it marks
     still reads as a dot and not as a thicker stretch of line. */
  box-shadow: 0 0 0 2px var(--surface-card);
}

.chart-hotspot:hover .chart-guide,
.chart-hotspot:hover .chart-dot {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .chart-guide,
  .chart-dot {
    transition: none;
  }
}

/* ---- Tables and lists -------------------------------------------------- */

.table-row:hover {
  background: var(--surface-subtle) !important;
}

.table-row,
.table-row:hover {
  color: var(--text-body);
  text-decoration: none;
}

/* The per-subcase table hovers a shade darker than the conversations table --
   its rows open a drawer rather than a page. */
.subcase-row:hover {
  background: var(--brand-grey-light);
}

.subcase-row,
.subcase-row:hover {
  color: var(--text-body);
  text-decoration: none;
}

.rail-item:hover {
  background: var(--surface-subtle);
}

.rail-item,
.rail-item:hover {
  text-decoration: none;
}

/* The case being read. This is a class rather than inline styles because
   stepping to the next case moves the marker without re-rendering the rail:
   the swap toggles `is-current` on two rows and nothing else changes. */
.rail-item.is-current {
  border-left-color: var(--brand-accent);
  background: var(--surface-subtle);
}

.rail-item.is-current [data-rail-reference],
.rail-item.is-current [data-rail-label] {
  color: var(--brand-accent);
}

.rail-item.is-current [data-rail-label] {
  font-weight: 600;
}

/* ---- Attachment chips and the document viewer -------------------------- */

/* A chip opens the file, so it is a button; these are the declarations that
   undo the browser's own button styling the inline styles cannot reach. */
.attachment-chip:hover {
  border-color: var(--brand-accent-border-soft);
  color: var(--text-body);
}

/* The viewer's ← / → steppers. Unlike the chrome inside the card these sit on
   the backdrop, so they carry their own surface rather than a border alone. */
.viewer-step {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface-card);
  box-shadow: var(--shadow-md);
  color: var(--text-muted);
  cursor: pointer;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.viewer-step:hover:not(:disabled) {
  border-color: var(--brand-accent-border-soft);
  color: var(--brand-accent);
}

/* At either end of the thread the arrow stays in place: taking it away would
   shift the document sideways on the last step of every walk. */
.viewer-step:disabled {
  opacity: 0.35;
  cursor: default;
}

/* ---- Detail view ------------------------------------------------------- */

.icon-button:hover {
  border-color: var(--brand-accent-border-soft);
  color: var(--brand-accent);
}

.step-button:hover {
  background: var(--tint-accent);
}

.step-button,
.step-button:hover {
  text-decoration: none;
}

.collapse-header:hover {
  background: var(--surface-subtle);
}

.collapse-header,
.collapse-header:hover {
  color: inherit;
  text-decoration: none;
}

/* ---- Focus ------------------------------------------------------------- */

/* The design focuses inputs with the accent border plus a soft indigo ring. */
input:focus-visible,
select:focus-visible {
  outline: none;
  border-color: var(--brand-accent);
  box-shadow: 0 0 0 3px var(--brand-accent-ring);
}

a:focus-visible,
[role="button"]:focus-visible,
button:focus-visible {
  outline: 2px solid var(--brand-accent);
  outline-offset: 2px;
}

/* ---- Range picker and tabs --------------------------------------------- */

/* The unselected presets sit on the grey track with no fill of their own, so
   hover has to supply the affordance. The selected one already has one. */
.range-option:hover {
  color: var(--text-strong);
}

.screen-tab:hover {
  color: var(--text-strong);
}

/* ---- Loading -----------------------------------------------------------

   A tab switch costs one round trip to a database in another region, so the
   content is swapped in place behind a skeleton rather than through a page
   load that would blank the shell. `--swap-busy` is set on the chrome while
   the fetch is in flight: the strip stays readable but stops inviting a
   second click. */

[data-swap-busy] {
  opacity: 0.6;
  pointer-events: none;
}

.skeleton-line {
  display: block;
  border-radius: var(--radius-md);
  background: linear-gradient(
    90deg,
    var(--brand-grey-light) 25%,
    rgba(208, 212, 240, 0.65) 37%,
    var(--brand-grey-light) 63%
  );
  background-size: 400% 100%;
  animation: skeleton-sweep 1.4s ease-in-out infinite;
}

@keyframes skeleton-sweep {
  0% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0 50%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton-line {
    animation: none;
    background: var(--brand-grey-light);
  }
}

/* Appending the next page is not the same event as replacing the table, so it
   does not get the same placeholder: a skeleton row promises content in the
   shape of a row, and what is loading here is the tail of a list the reader is
   already reading. A ring at the foot says "still coming" without pretending
   to be a row that never arrives. */

.spinner {
  display: inline-block;
  /* The sentinel is a flex row, which would otherwise shrink the ring into an
     ellipse to fit its label. */
  flex: none;
  width: 14px;
  height: 14px;
  border: 2px solid var(--brand-grey-light);
  border-top-color: var(--brand-accent);
  border-radius: 50%;
  animation: spinner-turn 0.7s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
  .spinner {
    animation-duration: 2s;
  }
}

