/* =============================================================================
   site-base.css  ·  the public site's DOCUMENT foundation
   =============================================================================
   Everything a public page needs before any page or component stylesheet runs:
   the reset, the <html>/<body> surface, the three inherited-element utilities,
   the focus ring, and one measure-bounded wrapper.

   WHY IT EXISTS
   ------------------------------------------------------------------------
   Until 2026-08-07 templates/public_base.html extended the legacy AUTHENTICATED
   WORKSPACE shell, and that shell's inline <style> was the ONLY source of the
   page background, the base font and `box-sizing` on every public page.
   site-tokens.css is 100% `:root` declarations and declares no rules at
   all, so removing that shell from the public chain without replacing that would
   have rendered every public page unstyled. This file is that replacement.

   LOAD ORDER
   ------------------------------------------------------------------------
       fonts.css  ->  site-tokens.css  ->  THIS FILE  ->  page CSS  ->  site-chrome.css

   It reads --bg-page / --ink-2 / --font-ui / --accent from site-tokens.css, so
   site-tokens.css must come first. It is deliberately UNLAYERED and low
   specificity (element selectors and one class) so any page stylesheet loaded
   after it wins without needing `!important`.

   THIS FILE ADDS NO `!important` AND MUST NOT.
   ============================================================================= */

/* =============================================================================
   1 · RESET
   -----------------------------------------------------------------------------
   Byte-for-byte the reset the legacy workspace shell always applied to these pages. Kept
   identical on purpose rather than "modernised": every public page stylesheet
   in this repo was authored against a zeroed margin/padding on EVERY element
   (e.g. how-to-access.css's `.hta-timeline` sets `list-style: none` but never
   `padding-left: 0`), so a softer reset would silently reflow all of them.
   ============================================================================= */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* =============================================================================
   2 · DOCUMENT
   ============================================================================= */
html {
  /* THE UA'S OWN WIDGETS ARE PART OF THIS PAGE'S PALETTE.   (2026-08-25)

     `color-scheme` tells the user agent which of its built-in appearances to
     paint form controls, scrollbars and the default focus ring in. Absent it,
     the computed value is `normal`, and Chromium resolves `normal` against the
     OS setting, so a visitor whose machine is in light mode was handed
     LIGHT-MODE controls on a #070a1c page.

     Measured on /signin at 1440 before this line existed: the unchecked "Keep
     me signed in" checkbox rendered a white (255,255,255) box with a
     rgb(118,118,118) border, mean luminance 0.4658, sitting on a rgb(17,20,37)
     card. It was the brightest object in the form apart from the CTA, at the
     optical centre of it, beside the dimmest label on the page.

     NOT THE SAME THING AS `prefers-color-scheme`, AND THAT IS WHY THIS WAS
     MISSED. The only `color-scheme: dark` in all 47 stylesheets was in the
     legacy responsive sheet, inside `@media (prefers-color-scheme: dark)`, on a
     file the public chain did not load. A media query reports the visitor's
     OS setting; this property states the DOCUMENT's. Declaring it inside that
     media query only fires it when the OS is already dark, which is exactly
     the case that did not need it. This product has one appearance, so it is
     declared unconditionally. */
  color-scheme: dark;

  /* Stops iOS Safari inflating body text in landscape, which breaks any
     clamp()-based type scale, and this site's is entirely clamp()-based. */
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100vh;
  background: var(--bg-page);
  color: var(--ink-2);
  font-family: var(--font-ui);
  font-size: var(--type-u4);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* `clip`, not `hidden`: prevents horizontal overflow without making <body> a
     scroll container, which would strand the viewport scroller and break every
     `position: sticky` on the page. Carried verbatim from the legacy workspace
     shell, including the reason. */
  overflow-x: clip;
  position: relative;
}

/* =============================================================================
   3 · INHERITED-ELEMENT UTILITIES
   -----------------------------------------------------------------------------
   These three lived ONLY in the legacy responsive sheet, a workspace-chain
   stylesheet that stopped loading on public pages. They are not cosmetic:
   without the second rule every <input>, <button>, <select> and <textarea> on
   the public site renders in the UA default (13.33px Arial), which is visible
   on /signin, the contact form and the newsletter field.
   ============================================================================= */
img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
}

/* Visually hidden, still announced. Was defined in exactly one place —
   components/landing/head_styles.html's inline <style> — which is landing-only,
   so `.sr-only` was dead everywhere else it is used (whitepapers.html, and
   anything the shared components render). The legacy design-system sheet had
   the same recipe under a DIFFERENT name (.r-sr-only), off the public chain.
   Standard clip-rect recipe; defined once, here. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* =============================================================================
   4 · FOCUS
   -----------------------------------------------------------------------------
   The UA default focus ring is `rgb(16,16,16)` in Chromium — near-black, and
   therefore invisible on a navy page. site-chrome.css already draws an accent
   ring on the header and footer's own controls; this is the same ring for
   everything else, so a keyboard visitor never loses their place in page body
   content. `:focus-visible` only, so a mouse click does not paint it.
   ============================================================================= */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

/* =============================================================================
   5 · LAYOUT PRIMITIVES
   ============================================================================= */

/* The default content landmark public_base.html renders. Block-level and
   otherwise inert: pages own their own layout. */
.site-main {
  display: block;
}

/* Reading measure. `ch` units, so the line length follows the rendered face
   instead of a guessed pixel width. --measure-wide is for prose that carries
   inline code or a table. */
.site-measure {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
}

.site-measure--wide {
  max-width: var(--measure-wide);
}

/* =============================================================================
   6 · FLASH MESSAGES
   -----------------------------------------------------------------------------
   The flash region's MARKUP is rendered by public_base.html (and by the React
   app shell, for the workspace). Its public styles once existed only inside the
   legacy workspace shell's inline <style>, so carrying the markup off that chain
   without carrying these rules would have left /signin's "Invalid credentials"
   as a bare unstyled line at the top of the document.

   Copied from that shell (deleted 2026-09-29) rather than shared. The React
   workspace skins the same markup differently, in
   frontend/src/styles/flash-toasts.css, so the two are not expected to match. Namespaced
   `.flash-toast*`, so nothing here can reach anything else.

   Positioning note: the stack's inline script (public_base.html) measures
   `.quantum-nav, .site-header` and writes `style.top`, because the header's
   rendered height varies with scroll state and breakpoint. The 110px below is
   only the no-JS fallback.
   ============================================================================= */
.flash-toast-stack {
  position: fixed;
  top: 110px;
  left: 0;
  right: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  z-index: 100;
  pointer-events: none;
}

.flash-toast-stack > .flash-toast {
  pointer-events: auto;
}

.flash-toast {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
  box-sizing: border-box;
  padding: 14px 60px 14px 32px;
  /* Layered background for the frosted-glass feel: a top-edge sheen over a
     translucent tinted gradient, with backdrop-filter blurring the page behind
     both so the banner reads as a sheet of tinted glass. */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.02) 32%, transparent 75%),
    linear-gradient(90deg, var(--toast-bg-start, rgba(16, 185, 129, 0.78)) 0%, var(--toast-bg-mid, rgba(5, 150, 105, 0.82)) 55%, var(--toast-bg-end, rgba(4, 120, 87, 0.86)) 100%);
  backdrop-filter: blur(36px) saturate(125%);
  -webkit-backdrop-filter: blur(36px) saturate(125%);
  border-top: 1px solid rgba(255, 255, 255, 0.10);
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow:
    0 12px 32px rgba(0, 0, 0, 0.30),
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 0 48px -10px var(--toast-glow, rgba(20, 200, 160, 0.40));
  color: #ffffff;
  line-height: 1.4;
  overflow: hidden;
  opacity: 0;
  transform: translateY(-12px);
  animation: flashToastIn 0.4s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.flash-toast.flash-toast--leaving {
  animation: flashToastOut 0.35s cubic-bezier(0.4, 0, 1, 1) forwards;
}

/* Bottom progress bar — drains over the auto-dismiss window. */
.flash-toast::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: 100%;
  background: rgba(255, 255, 255, 0.75);
  transform-origin: left center;
  animation: flashToastProgress 5s linear forwards;
}

.flash-toast__icon {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.95);
  color: var(--toast-icon-color, #047857);
  font-size: 13px;
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.20),
    0 0 0 3px rgba(255, 255, 255, 0.18);
}

.flash-toast__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}

.flash-toast__title {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.92);
  margin: 0;
  line-height: 1.2;
  white-space: nowrap;
}

.flash-toast__message {
  margin: 0;
  color: #ffffff;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
  word-wrap: break-word;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
}

.flash-toast__close {
  position: absolute;
  top: 50%;
  right: 16px;
  transform: translateY(-50%);
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  border: none;
  background: rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.85);
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
  font-size: 12px;
  padding: 0;
}

.flash-toast__close:hover {
  background: rgba(255, 255, 255, 0.28);
  color: #ffffff;
}

/* Category palettes — emerald-teal success, rose error, amber warning, sky info. */
.flash-toast--success {
  --toast-bg-start: rgba(16, 185, 129, 0.78);
  --toast-bg-mid: rgba(5, 150, 105, 0.82);
  --toast-bg-end: rgba(4, 120, 87, 0.86);
  --toast-icon-color: #064e3b;
  --toast-glow: rgba(16, 185, 129, 0.45);
}

.flash-toast--danger,
.flash-toast--error {
  --toast-bg-start: rgba(225, 75, 100, 0.50);
  --toast-bg-mid: rgba(180, 50, 78, 0.58);
  --toast-bg-end: rgba(130, 32, 56, 0.66);
  --toast-icon-color: #7a1a32;
  --toast-glow: rgba(244, 100, 130, 0.40);
}

.flash-toast--warning {
  --toast-bg-start: rgba(220, 160, 40, 0.50);
  --toast-bg-mid: rgba(180, 122, 25, 0.58);
  --toast-bg-end: rgba(130, 86, 16, 0.66);
  --toast-icon-color: #6e4308;
  --toast-glow: rgba(245, 180, 60, 0.40);
}

.flash-toast--info {
  --toast-bg-start: rgba(70, 175, 220, 0.50);
  --toast-bg-mid: rgba(40, 135, 178, 0.58);
  --toast-bg-end: rgba(22, 95, 130, 0.66);
  --toast-icon-color: #134e6f;
  --toast-glow: rgba(80, 195, 245, 0.40);
}

@keyframes flashToastIn {
  0%   { transform: translateY(-12px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}

@keyframes flashToastOut {
  0%   { transform: translateY(0); opacity: 1; max-height: 80px; }
  100% { transform: translateY(-12px); opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0; }
}

@keyframes flashToastProgress {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0); }
}

@media (max-width: 640px) {
  .flash-toast {
    gap: 12px;
    padding: 12px 52px 12px 22px;
  }
  .flash-toast__icon {
    width: 30px;
    height: 30px;
    font-size: 13px;
  }
  .flash-toast__message {
    font-size: 13px;
  }
}

/* The legacy workspace shell's copy of this block flagged all three declarations `!important`.
   They are not needed and are dropped here: this rule's selector list matches
   both `.flash-toast` (0,1,0) and `.flash-toast.flash-toast--leaving` (0,2,0)
   at equal specificity to the rules it overrides, and comes later in the file,
   so it wins on source order alone. A media query adds no specificity of its
   own. Verified by the animation actually being suppressed — not assumed.
   THIS FILE CONTAINS NO `!important`. */
@media (prefers-reduced-motion: reduce) {
  .flash-toast,
  .flash-toast.flash-toast--leaving {
    animation: none;
    opacity: 1;
    transform: none;
  }
  .flash-toast::after { animation-duration: 5s; }
}
