/* ============================================================================
   Semantic tokens.

   These name a *role* — "the page background", "a subtle border", "danger" —
   rather than a colour. Feature code should reach for these instead of a hex,
   because a hex cannot follow the colour scheme and a Mantine shade index
   (`gray.5`) says nothing about why that shade was chosen.

   Every token resolves to a Mantine variable rather than a literal. That is
   deliberate: Mantine already recomputes its own variables under
   [data-mantine-color-scheme], so tokens defined in terms of them switch for
   free and can never drift from the theme. A parallel palette of raw hexes
   would recreate exactly the problem this layer exists to fix.

   Loaded once per app, after Mantine's CSS.
   ============================================================================ */

:root {
  /* --- Surfaces ---------------------------------------------------------- */
  /* The page itself, a raised card, and a recessed well. */
  --ema-surface-page: var(--mantine-color-gray-0);
  --ema-surface-raised: var(--mantine-color-white);
  --ema-surface-sunken: var(--mantine-color-gray-1);

  /* --- Borders ----------------------------------------------------------- */
  /* Subtle separates rows; strong outlines an input or a focused container. */
  --ema-border-subtle: var(--mantine-color-gray-2);
  --ema-border-strong: var(--mantine-color-gray-4);

  /* --- Text -------------------------------------------------------------- */
  /* Secondary must stay a *text* colour: it has to clear 4.5:1, not 3:1, so
     it deliberately sits darker than the gray-5 that reads as "dimmed". */
  --ema-text-primary: var(--mantine-color-gray-9);
  --ema-text-secondary: var(--mantine-color-gray-7);
  --ema-text-disabled: var(--mantine-color-gray-5);

  /* --- Status ------------------------------------------------------------
     Six tones, which is the entire vocabulary a status needs. Domain statuses
     map onto these rather than each picking their own colour.

     `-fg` is text on the app background; `-bg` is a tint to sit that text on.
     Both are needed because a badge and a label have different contrast
     requirements against the same surface. */
  --ema-status-success-fg: var(--mantine-color-green-8);
  --ema-status-success-bg: var(--mantine-color-green-0);
  --ema-status-warning-fg: var(--mantine-color-yellow-8);
  --ema-status-warning-bg: var(--mantine-color-yellow-0);
  --ema-status-danger-fg: var(--mantine-color-red-8);
  --ema-status-danger-bg: var(--mantine-color-red-0);
  --ema-status-info-fg: var(--mantine-color-blue-8);
  --ema-status-info-bg: var(--mantine-color-blue-0);
  --ema-status-pending-fg: var(--mantine-color-orange-8);
  --ema-status-pending-bg: var(--mantine-color-orange-0);
  --ema-status-neutral-fg: var(--mantine-color-gray-7);
  --ema-status-neutral-bg: var(--mantine-color-gray-1);

  /* --- Focus -------------------------------------------------------------
     One ring for the whole platform. Sized to stay visible against both a
     white card and a tinted surface. */
  --ema-focus-ring: var(--mantine-primary-color-filled);
  --ema-focus-ring-width: 2px;
  --ema-focus-ring-offset: 2px;
}

[data-mantine-color-scheme='dark'] {
  /* Dark is not light inverted. Surfaces lift with elevation rather than
     dropping, and text steps down from white rather than up from black. */
  --ema-surface-page: var(--mantine-color-dark-8);
  --ema-surface-raised: var(--mantine-color-dark-7);
  --ema-surface-sunken: var(--mantine-color-dark-9);

  --ema-border-subtle: var(--mantine-color-dark-4);
  --ema-border-strong: var(--mantine-color-dark-3);

  --ema-text-primary: var(--mantine-color-gray-0);
  --ema-text-secondary: var(--mantine-color-gray-4);
  --ema-text-disabled: var(--mantine-color-dark-2);

  /* Saturated mid-shades go muddy on a dark ground; these step lighter so the
     foreground still clears 4.5:1 and the tint stays distinguishable. */
  --ema-status-success-fg: var(--mantine-color-green-4);
  --ema-status-success-bg: var(--mantine-color-green-9);
  --ema-status-warning-fg: var(--mantine-color-yellow-4);
  --ema-status-warning-bg: var(--mantine-color-yellow-9);
  --ema-status-danger-fg: var(--mantine-color-red-4);
  --ema-status-danger-bg: var(--mantine-color-red-9);
  --ema-status-info-fg: var(--mantine-color-blue-4);
  --ema-status-info-bg: var(--mantine-color-blue-9);
  --ema-status-pending-fg: var(--mantine-color-orange-4);
  --ema-status-pending-bg: var(--mantine-color-orange-9);
  --ema-status-neutral-fg: var(--mantine-color-gray-4);
  --ema-status-neutral-bg: var(--mantine-color-dark-5);
}

/* ============================================================================
   Focus.

   The codebase had no :focus-visible rule anywhere, which is the single
   largest accessibility gap in it. :focus-visible rather than :focus so a
   mouse click does not leave a ring behind — that is the behaviour that gets
   focus rings deleted from designs in the first place.
   ============================================================================ */

/* Mantine already rings its own controls (`.mantine-focus-auto:focus-visible`
   resolves to the same 2px solid primary). This rule is the safety net for
   everything it does not own: plain anchors, custom elements, and the
   UnstyledButtons this codebase uses for its own controls.

   Note there is deliberately no `outline: none` opt-out for the Mantine
   classes. An earlier attempt at one suppressed Mantine's working ring and
   left portal buttons with no focus indicator at all — which of the two rules
   won came down to stylesheet order, and that differs between the apps.
   Matching values mean overlap is invisible, so overlap is the safe default. */
:focus-visible {
  outline: var(--ema-focus-ring-width) solid var(--ema-focus-ring);
  outline-offset: var(--ema-focus-ring-offset);
}

/* ============================================================================
   Screen-reader-only utility.

   No equivalent existed anywhere in the codebase, so anything needing a text
   alternative had nowhere to put it.
   ============================================================================ */

.ema-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  /* clip-path rather than the legacy clip: it does not force a layer and is
     not deprecated. */
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* A skip link is sr-only until focused, then must be plainly visible. */
.ema-skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 9999;
  padding: 0.75rem 1.25rem;
  background: var(--ema-surface-raised);
  color: var(--ema-text-primary);
  border: 1px solid var(--ema-border-strong);
  border-radius: 0 0 var(--mantine-radius-md) 0;
  font-weight: 600;
  text-decoration: none;
  /* Off-screen rather than display:none, so it stays focusable. */
  transform: translateY(-150%);
}

.ema-skip-link:focus-visible {
  transform: translateY(0);
}

/* ============================================================================
   Reduced motion.

   Honour the OS setting globally. Animation is not removed outright — a
   near-instant transition still conveys that something changed, without the
   movement that triggers vestibular symptoms.
   ============================================================================ */

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