/*
  Document-level rules only - the handful of things that genuinely have no
  component to belong to. Everything else lives in a <Component>.razor.css.

  If you are about to add a component rule here, you are about to start the
  4 500-line stylesheet this project exists to avoid. Add a .razor.css instead.
*/

/*
  The display face, served by this site and by nobody else.

  Self-hosted rather than linked from a font host: an external link would put a
  third-party network dependency on the rendering path and show every visitor's
  IP address to a service with no business seeing it.

  One variable font, one request, 400 to 700 in 31.5KB. `swap` makes the system
  stack readable during the download: the text is legible at once, and stays
  legible if the file never arrives.

  This rule lives here and not in tokens.css, which holds custom properties and
  nothing else.
*/
@font-face {
  font-family: "Outfit";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/outfit-latin-var.woff2") format("woff2");
  /* Latin subset: it covers the accents, the cedilla, the oe ligature, the
     French quotation marks and the narrow no-break space of fr-FR formatting. */
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: dark;
}

html {
  /* No JS-driven scroll behaviour anywhere; this is the only scroll rule. */
  -webkit-text-size-adjust: 100%;
}

body {
  background-color: var(--color-bg);
  /*
    FR-021: a cold glow in the top-left corner, so the background has a
    direction rather than being flat. In CSS: no image, no bytes, crisp at
    every zoom level.

    The grid pattern that came with this glow was removed on 2026-08-31: the
    owner judged it unprofessional, and they were right - a technical mesh
    behind a statistics card suggests a spreadsheet, not esport.

    Text laid over it keeps its contrast: the glow moves the background's
    luminance by a few thousandths, which SC-007 checks against the final
    colours rather than against the intention.
  */
  background-image:
    radial-gradient(120% 90% at 12% 0%, var(--backdrop-glow) 0%, var(--color-bg) 62%);
  background-attachment: fixed;
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  line-height: var(--leading-normal);
  min-height: 100dvh;
  /*
    FR-027 / SC-004: nothing between 320px and 1920px may produce a horizontal
    scrollbar. This is the document-level backstop; each component is still
    responsible for not overflowing in the first place.
  */
  overflow-x: hidden;
}

/*
  FR-028 / SC-005: one visible focus ring, defined once, for every interactive
  element in the app. A component may reposition it; no component may remove it.
*/
:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-sm);
}

/*
  Blazor's <FocusOnNavigate Selector="h1"> moves focus to the heading on
  navigation. The heading is not interactive, so the ring would be noise -
  :focus-visible above still covers every element that is.
*/
h1:focus {
  outline: none;
}

a {
  text-decoration-thickness: from-font;
  text-underline-offset: 0.15em;
}

/*
  THE MOVE BETWEEN RÉSEAUX AND SKINS (012, amendment A2 of 2026-09-14).

  A page navigation, animated by the browser, with no script: both pages opt in
  here, and three pieces carry the same name on both - the left column
  (shell-frame: the rail's identity strip, the Skins plate), the tab surface
  (shell-surface) and the avatar (shell-avatar). The browser moves and resizes
  each from its place on one page to its place on the other.

  What makes it read as the page changing shape rather than as an effect, after
  the owner turned down a first try as « kitsch à mort » on the mockup:
  - the page itself does not fade (root: no animation);
  - one movement, one decelerating curve, no bounce, nothing turns;
  - the old content of the column and the surface fades out at once and is
    never stretched (drawn at its own size from the top left, clipped to the
    moving box), and the new one fades in once the room is made.

  Above 64rem only, where the column changes shape; below, the header is the
  same band on both tabs and there is nothing to explain. Off for a visitor who
  asked for less motion. A browser without cross-document view transitions -
  Firefox today - changes page as it always has.

  A document-level rule by nature: the transition belongs to no component.
*/
@media (min-width: 64rem) and (prefers-reduced-motion: no-preference) {
  @view-transition {
    navigation: auto;
  }
}

::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
}

::view-transition-group(shell-frame),
::view-transition-group(shell-surface),
::view-transition-group(shell-avatar) {
  animation-duration: var(--shell-move);
  animation-timing-function: var(--shell-ease);
}

::view-transition-image-pair(shell-frame),
::view-transition-image-pair(shell-surface) {
  overflow: clip;
}

::view-transition-old(shell-frame),
::view-transition-new(shell-frame),
::view-transition-old(shell-surface),
::view-transition-new(shell-surface) {
  inline-size: auto;
  block-size: auto;
  object-fit: none;
  object-position: left top;
}

::view-transition-old(shell-frame),
::view-transition-old(shell-surface) {
  animation: shell-leave var(--shell-leave) var(--ease-out) both;
}

::view-transition-new(shell-frame),
::view-transition-new(shell-surface) {
  animation: shell-enter var(--shell-enter) var(--ease-out) var(--shell-enter-delay) both;
}

@keyframes shell-leave {
  to {
    opacity: 0;
  }
}

@keyframes shell-enter {
  from {
    opacity: 0;
  }
}

/*
  Visually hidden but present for assistive technology. Used for the labels
  that identify a link destination when the visible text alone would not.
*/
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
