/* Phoenix — shared design foundation.
   Loaded first by every page (marketing, legal, console). No build step, no
   framework, no webfont: the portal runs on a LAN beside the robot and must
   render correctly with no outside host reachable, so the type stack is the
   system stack, tuned rather than downloaded.

   Dark is the product's own look. Light follows the system, and either can be
   forced with data-theme on <html> for the theme switch. */

/* ==========================================================================
   Tokens
   ========================================================================== */

:root {
  color-scheme: dark;

  /* Surfaces, darkest to lightest. `canvas` is the page; `raised` is a card;
     `overlay` is a popover or modal sitting above everything. */
  --bg: #08090d;
  --bg-soft: #0c0e14;
  --panel: #12151d;
  --panel-2: #171b25;
  --panel-3: #1e2331;
  --overlay: #161a23;

  /* Text, in descending prominence. */
  --fg: #f2f4f9;
  --fg-dim: #b8bfd0;
  --muted: #7d8497;
  --faint: #5a6072;

  /* The phoenix gradient: ember through flame. Used sparingly — a product
     that gradients everything reads as a template. */
  --accent: #ffb347;
  --accent-warm: #ff7a3d;
  --accent-hot: #ff5470;
  --accent-ink: #1a1105;
  --accent-soft: rgba(255, 179, 71, .13);
  --accent-line: rgba(255, 179, 71, .30);
  --accent-glow: rgba(255, 140, 60, .22);

  /* The light end of the brand ramp. Derived from --accent rather than fixed,
     so an operator who configures a single hex in branding.json gets a
     coherent gradient instead of this palette's cream bleeding into theirs.
     The literal is the fallback where color-mix is unsupported; for the default
     amber the two are within a shade of each other. */
  --accent-lift: #ffd08a;
  --accent-lift: color-mix(in srgb, var(--accent) 62%, #fff);

  --grad-brand: linear-gradient(115deg, var(--accent) 0%, var(--accent-warm) 52%, var(--accent-hot) 100%);
  --grad-text: linear-gradient(100deg, var(--accent-lift) 0%, var(--accent) 38%, var(--accent-warm) 100%);

  /* A cool counterweight so the page is not uniformly warm. */
  --cool: #6ea8fe;
  --cool-soft: rgba(110, 168, 254, .13);

  /* Borders. `border` is visible structure; `hairline` is barely-there
     separation that keeps dense data readable without drawing boxes. */
  --border: #262c3a;
  --border-soft: #1b202b;
  --hairline: rgba(255, 255, 255, .06);

  /* Status. Each has a soft companion for filled badges. */
  --ok: #5fd68d;
  --ok-soft: rgba(95, 214, 141, .13);
  --warn: #ffd166;
  --warn-soft: rgba(255, 209, 102, .13);
  --error: #ff7b8a;
  --error-soft: rgba(255, 123, 138, .13);
  --info: var(--cool);
  --info-soft: var(--cool-soft);

  /* Geometry. */
  --radius-xs: 6px;
  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 20px;
  --radius-xl: 28px;
  --radius-pill: 999px;

  /* Elevation. Dark UI needs the shadow plus a light top edge, or cards look
     painted on rather than lifted. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .40);
  --shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 10px 28px -14px rgba(0, 0, 0, .70);
  --shadow-lg: 0 2px 4px rgba(0, 0, 0, .30), 0 28px 60px -22px rgba(0, 0, 0, .80);
  --shadow-glow: 0 10px 40px -12px var(--accent-glow);
  --edge: inset 0 1px 0 rgba(255, 255, 255, .045);
  --ring: 0 0 0 3px var(--accent-soft);

  /* Motion. One easing curve for almost everything keeps the whole product
     feeling like one hand made it. */
  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  --fast: .14s;
  --step: .22s;
  --slow: .45s;

  /* Type. The system stack, with the metrics tightened so it does not read as
     a default. */
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter, Roboto,
    "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  /* Fluid scale — no media queries needed for headings. */
  --t-xs: .75rem;
  --t-sm: .8125rem;
  --t-base: .9375rem;
  --t-md: 1rem;
  --t-lg: clamp(1.0625rem, .98rem + .38vw, 1.25rem);
  --t-xl: clamp(1.375rem, 1.24rem + .62vw, 1.75rem);
  --t-2xl: clamp(1.625rem, 1.42rem + .9vw, 2.125rem);
  --t-3xl: clamp(1.875rem, 1.6rem + 1.3vw, 2.75rem);
  /* The hero headline shares its row with the pipeline card, so its column is
     roughly half the page. Sized against that column, not the viewport. */
  --t-4xl: clamp(2.25rem, 1.85rem + 1.9vw, 3.5rem);

  /* Layout. */
  --wide: 1200px;
  --prose: 760px;
  --gutter: clamp(1.25rem, .9rem + 1.6vw, 2.5rem);
  --section-y: clamp(4.5rem, 3rem + 7vw, 9rem);
  --header-h: 64px;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;

    --bg: #fbfbfd;
    --bg-soft: #f4f5f9;
    --panel: #ffffff;
    --panel-2: #f7f8fc;
    --panel-3: #eef0f6;
    --overlay: #ffffff;

    --fg: #14161d;
    --fg-dim: #3c4354;
    --muted: #666d80;
    --faint: #8a90a2;

    /* The amber has to darken hard to stay legible on white; the gradient
       keeps the warmth that the flat colour loses. */
    --accent: #b25f00;
    --accent-warm: #c4451f;
    --accent-hot: #c02a4c;
    --accent-ink: #ffffff;
    --accent-soft: rgba(178, 95, 0, .10);
    --accent-line: rgba(178, 95, 0, .26);
    --accent-glow: rgba(196, 69, 31, .16);
    --accent-lift: #a85a00;
    --accent-lift: color-mix(in srgb, var(--accent) 88%, #000);
    --grad-text: linear-gradient(100deg, var(--accent-lift) 0%, var(--accent-warm) 55%, var(--accent-hot) 100%);

    --cool: #2d64d8;
    --cool-soft: rgba(45, 100, 216, .10);

    --border: #dde1ea;
    --border-soft: #e9ecf3;
    --hairline: rgba(16, 24, 40, .07);

    --ok: #147a3d;
    --ok-soft: rgba(20, 122, 61, .10);
    --warn: #8a5d00;
    --warn-soft: rgba(138, 93, 0, .12);
    --error: #c03040;
    --error-soft: rgba(192, 48, 64, .10);

    --shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);
    --shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 10px 26px -16px rgba(16, 24, 40, .30);
    --shadow-lg: 0 2px 4px rgba(16, 24, 40, .05), 0 26px 56px -24px rgba(16, 24, 40, .35);
    --edge: inset 0 1px 0 rgba(255, 255, 255, .9);
  }
}

/* Explicit light, chosen in the theme switch. Mirrors the block above. */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #fbfbfd;
  --bg-soft: #f4f5f9;
  --panel: #ffffff;
  --panel-2: #f7f8fc;
  --panel-3: #eef0f6;
  --overlay: #ffffff;
  --fg: #14161d;
  --fg-dim: #3c4354;
  --muted: #666d80;
  --faint: #8a90a2;
  --accent: #b25f00;
  --accent-warm: #c4451f;
  --accent-hot: #c02a4c;
  --accent-ink: #ffffff;
  --accent-soft: rgba(178, 95, 0, .10);
  --accent-line: rgba(178, 95, 0, .26);
  --accent-glow: rgba(196, 69, 31, .16);
  --accent-lift: #a85a00;
  --accent-lift: color-mix(in srgb, var(--accent) 88%, #000);
  --grad-text: linear-gradient(100deg, var(--accent-lift) 0%, var(--accent-warm) 55%, var(--accent-hot) 100%);
  --cool: #2d64d8;
  --cool-soft: rgba(45, 100, 216, .10);
  --border: #dde1ea;
  --border-soft: #e9ecf3;
  --hairline: rgba(16, 24, 40, .07);
  --ok: #147a3d;
  --ok-soft: rgba(20, 122, 61, .10);
  --warn: #8a5d00;
  --warn-soft: rgba(138, 93, 0, .12);
  --error: #c03040;
  --error-soft: rgba(192, 48, 64, .10);
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, .06);
  --shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 10px 26px -16px rgba(16, 24, 40, .30);
  --shadow-lg: 0 2px 4px rgba(16, 24, 40, .05), 0 26px 56px -24px rgba(16, 24, 40, .35);
  --edge: inset 0 1px 0 rgba(255, 255, 255, .9);
}

/* ==========================================================================
   Reset
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Anchors land below the sticky header rather than under it. */
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: var(--t-base);
  line-height: 1.6;
  letter-spacing: -.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, h4, h5 {
  margin: 0;
  font-weight: 640;
  line-height: 1.15;
  letter-spacing: -.022em;
  text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }
img, svg, video { max-width: 100%; display: block; }
svg { flex: none; }

a {
  color: inherit;
  text-decoration: none;
  transition: color var(--fast) var(--ease), opacity var(--fast) var(--ease);
}

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; padding: 0; }

code, pre, kbd, samp {
  font-family: var(--font-mono);
  font-size: .92em;
  font-variant-ligatures: none;
}

hr { border: 0; border-top: 1px solid var(--border-soft); margin: 2rem 0; }

::selection { background: var(--accent-soft); color: var(--fg); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}
:focus:not(:focus-visible) { outline: none; }

/* Scrollbars, so the chrome matches the product in both themes. */
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border);
  border: 3px solid transparent;
  border-radius: var(--radius-pill);
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--panel-3); background-clip: content-box; }

/* ==========================================================================
   Layout helpers
   ========================================================================== */

.wrap {
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.stack > * + * { margin-top: var(--gap, 1rem); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Keyboard users land here first on every page. */
.skip-link {
  position: absolute;
  left: 50%;
  top: .5rem;
  translate: -50% -200%;
  z-index: 200;
  padding: .6rem 1rem;
  background: var(--panel);
  border: 1px solid var(--accent-line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  font-weight: 600;
  transition: translate var(--step) var(--ease-out);
}
.skip-link:focus-visible { translate: -50% 0; }

/* ==========================================================================
   Brand lockup
   ========================================================================== */

/* Shared by the marketing header, the legal pages, the console sidebar and the
   sign-in screen — so it is defined here rather than in either page-level
   stylesheet, where only one of them would get it. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  font-weight: 640;
  font-size: var(--t-md);
  letter-spacing: -.024em;
  flex: none;
}
.brand-mark {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  flex: none;
  transition: transform var(--slow) var(--ease-spring);
}
.brand-mark svg { width: 100%; height: 100%; display: block; }
.brand:hover .brand-mark { transform: rotate(-6deg) scale(1.06); }
.brand-logo-img { width: 28px; height: 28px; object-fit: contain; border-radius: 6px; }

/* ==========================================================================
   Type utilities
   ========================================================================== */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--accent);
}
.eyebrow::before {
  content: "";
  width: 18px;
  height: 1px;
  background: var(--accent-line);
}

.lede {
  font-size: var(--t-lg);
  line-height: 1.62;
  color: var(--fg-dim);
  letter-spacing: -.011em;
}

.muted { color: var(--muted); }
.faint { color: var(--faint); }
.mono { font-family: var(--font-mono); }

/* Gradient headline text. Falls back to the flat accent where
   background-clip:text is unsupported. */
.grad {
  background: var(--grad-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: var(--accent);
}
@supports (-webkit-background-clip: text) or (background-clip: text) {
  .grad { color: transparent; }
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  --btn-bg: var(--panel-2);
  --btn-fg: var(--fg);
  --btn-border: var(--border);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .625rem 1.1rem;
  min-height: 40px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-border);
  border-radius: var(--radius-sm);
  font-size: var(--t-base);
  font-weight: 560;
  letter-spacing: -.01em;
  white-space: nowrap;
  box-shadow: var(--edge);
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease),
              transform var(--fast) var(--ease), box-shadow var(--step) var(--ease),
              color var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
.btn:hover { border-color: var(--panel-3); background: var(--panel-3); }
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn[aria-disabled="true"] {
  opacity: .5;
  pointer-events: none;
}

.btn-primary {
  --btn-fg: var(--accent-ink);
  --btn-border: transparent;
  background: var(--grad-brand);
  background-size: 160% 160%;
  background-position: 0% 50%;
  font-weight: 620;
  box-shadow: var(--shadow-sm), var(--shadow-glow);
  transition: background-position var(--slow) var(--ease), transform var(--fast) var(--ease),
              box-shadow var(--step) var(--ease), filter var(--fast) var(--ease);
}
.btn-primary:hover {
  background-position: 100% 50%;
  box-shadow: var(--shadow), 0 14px 46px -10px var(--accent-glow);
  filter: brightness(1.05);
}

.btn-ghost {
  --btn-bg: transparent;
  --btn-border: var(--border);
}
.btn-ghost:hover { background: var(--panel-2); border-color: var(--accent-line); }

.btn-quiet {
  --btn-bg: transparent;
  --btn-border: transparent;
  box-shadow: none;
  color: var(--fg-dim);
  padding-inline: .7rem;
}
.btn-quiet:hover { background: var(--panel-2); color: var(--fg); border-color: transparent; }

.btn-danger { --btn-fg: var(--error); --btn-border: var(--border); }
.btn-danger:hover { background: var(--error-soft); border-color: var(--error); }

.btn-lg { min-height: 48px; padding: .8rem 1.5rem; font-size: var(--t-md); border-radius: var(--radius); }
.btn-sm { min-height: 32px; padding: .35rem .7rem; font-size: var(--t-sm); border-radius: var(--radius-xs); }
.btn-block { width: 100%; }

/* The arrow nudges on hover — the smallest possible signal that a control is
   alive, and it costs nothing. */
.btn .arrow { transition: transform var(--step) var(--ease-out); }
.btn:hover .arrow { transform: translateX(3px); }

/* A text link that still reads as a link inside dense UI. */
.link {
  color: var(--accent);
  font-weight: 540;
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  text-underline-offset: 3px;
}
.link:hover { text-decoration: underline; }
.link.danger { color: var(--error); }

/* ==========================================================================
   Surfaces
   ========================================================================== */

.card {
  background: var(--panel);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  box-shadow: var(--shadow), var(--edge);
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .28rem .7rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--panel-2);
  font-size: var(--t-xs);
  font-weight: 560;
  letter-spacing: -.005em;
  color: var(--fg-dim);
}
.pill-accent { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent); }
.pill-ok { border-color: transparent; background: var(--ok-soft); color: var(--ok); }
.pill-warn { border-color: transparent; background: var(--warn-soft); color: var(--warn); }
.pill-error { border-color: transparent; background: var(--error-soft); color: var(--error); }

.dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
/* A live indicator, for things that are genuinely live. */
.dot-live { position: relative; }
.dot-live::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1px solid currentColor;
  opacity: .5;
  animation: ping 2.4s var(--ease-out) infinite;
}

/* ==========================================================================
   Forms
   ========================================================================== */

.field { display: flex; flex-direction: column; gap: .4rem; }
.field-label {
  font-size: var(--t-sm);
  font-weight: 560;
  color: var(--fg-dim);
  letter-spacing: -.005em;
}
.field-hint { font-size: var(--t-xs); color: var(--muted); line-height: 1.5; }

input[type="text"], input[type="email"], input[type="password"], input[type="search"],
input[type="date"], input[type="time"], input[type="tel"], input[type="number"],
input[type="url"], select, textarea {
  width: 100%;
  padding: .55rem .75rem;
  min-height: 40px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--fg);
  font-size: var(--t-base);
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease),
              background var(--fast) var(--ease);
}
textarea { min-height: 90px; resize: vertical; line-height: 1.55; padding-block: .6rem; }

input::placeholder, textarea::placeholder { color: var(--faint); }

input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) {
  border-color: var(--panel-3);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
  background: var(--panel);
}
input:disabled, select:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }
input[aria-invalid="true"] { border-color: var(--error); }

select {
  appearance: none;
  padding-right: 2.2rem;
  /* Inline SVG chevron — currentColor is not available in a data URI, so the
     stroke is picked to sit acceptably on both themes. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%237d8497' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .8rem center;
}

fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
legend { padding: 0; }

/* Switch — a real control, not a bare checkbox. The input keeps its name and
   checked semantics so FormData reads it exactly as before. */
.switch {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  cursor: pointer;
  user-select: none;
  padding: .15rem 0;
}
.switch input {
  position: absolute;
  opacity: 0;
  width: 0; height: 0;
}
.switch .track {
  position: relative;
  flex: none;
  width: 40px; height: 23px;
  margin-top: .1rem;
  border-radius: var(--radius-pill);
  background: var(--panel-3);
  border: 1px solid var(--border);
  transition: background var(--step) var(--ease), border-color var(--step) var(--ease);
}
.switch .track::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 17px; height: 17px;
  border-radius: 50%;
  background: var(--fg-dim);
  box-shadow: var(--shadow-sm);
  transition: transform var(--step) var(--ease-spring), background var(--step) var(--ease);
}
.switch input:checked + .track {
  background: var(--grad-brand);
  border-color: transparent;
}
.switch input:checked + .track::after {
  transform: translateX(17px);
  background: #fff;
}
.switch input:focus-visible + .track { box-shadow: var(--ring); }
.switch-text { display: flex; flex-direction: column; gap: .1rem; }
.switch-text > span:first-child { font-weight: 540; }
.switch-hint { font-size: var(--t-xs); color: var(--muted); line-height: 1.5; }

/* Chip — multi-select pill. Same trick: the checkbox is real and named. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .38rem .8rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--panel-2);
  font-size: var(--t-sm);
  font-weight: 520;
  cursor: pointer;
  user-select: none;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease),
              color var(--fast) var(--ease);
}
.chip:hover { border-color: var(--accent-line); }
.chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.chip .chip-mark {
  width: 14px; height: 14px;
  border-radius: 4px;
  border: 1.5px solid var(--border);
  background: var(--bg-soft);
  flex: none;
  position: relative;
  transition: background var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.chip .chip-mark::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='8' viewBox='0 0 10 8' fill='none'%3E%3Cpath d='M1 4.2 3.4 6.6 9 1' stroke='white' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 10px 8px no-repeat;
  opacity: 0;
  transform: scale(.6);
  transition: opacity var(--fast) var(--ease), transform var(--fast) var(--ease-spring);
}
.chip:has(input:checked) {
  border-color: var(--accent-line);
  background: var(--accent-soft);
  color: var(--accent);
}
.chip input:checked + .chip-mark { background: var(--accent); border-color: var(--accent); }
.chip input:checked + .chip-mark::after { opacity: 1; transform: scale(1); }
.chip:has(input:focus-visible) { box-shadow: var(--ring); }

.chips { display: flex; flex-wrap: wrap; gap: .5rem; }

/* ==========================================================================
   Feedback
   ========================================================================== */

.notice {
  display: flex;
  gap: .7rem;
  padding: .8rem 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--panel-2);
  font-size: var(--t-sm);
  line-height: 1.55;
}
.notice-warn { border-color: transparent; background: var(--warn-soft); color: var(--warn); }
.notice-error { border-color: transparent; background: var(--error-soft); color: var(--error); }
.notice-ok { border-color: transparent; background: var(--ok-soft); color: var(--ok); }
.notice-accent { border-color: var(--accent-line); background: var(--accent-soft); }

.error { color: var(--error); font-size: var(--t-sm); }
.warn { color: var(--warn); }

/* Toast, bottom-centre on phones and bottom-right on desktop. */
.toast {
  position: fixed;
  z-index: 300;
  left: 50%;
  bottom: 1.25rem;
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: .6rem;
  max-width: min(420px, calc(100vw - 2rem));
  padding: .7rem 1rem;
  border-radius: var(--radius-sm);
  background: var(--overlay);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  font-size: var(--t-sm);
  font-weight: 520;
  animation: toast-in var(--step) var(--ease-out);
}
.toast.error { border-color: var(--error); color: var(--error); }
.toast.ok { border-color: var(--ok-soft); }
.toast::before {
  content: "";
  width: 3px;
  align-self: stretch;
  border-radius: var(--radius-pill);
  background: var(--ok);
  flex: none;
}
.toast.error::before { background: var(--error); }

@media (min-width: 720px) {
  .toast { left: auto; right: 1.5rem; translate: none; bottom: 1.5rem; }
}

/* Loading skeleton — used while a surface fetches, so the layout does not
   jump when the data lands. */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--panel-2);
  border-radius: var(--radius-xs);
  color: transparent !important;
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--hairline), transparent);
  animation: shimmer 1.4s infinite;
}

.spinner {
  width: 16px; height: 16px;
  border-radius: 50%;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  animation: spin .7s linear infinite;
  flex: none;
}

/* ==========================================================================
   Animation
   ========================================================================== */

@keyframes spin { to { transform: rotate(360deg); } }
@keyframes shimmer { 100% { transform: translateX(100%); } }
@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px) scale(.98); }
  to { opacity: 1; transform: none; }
}
@keyframes ping {
  0% { transform: scale(.9); opacity: .6; }
  70%, 100% { transform: scale(2.1); opacity: 0; }
}
@keyframes fade-up {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}
@keyframes float-slow {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-10px); }
}

/* Scroll reveal. Elements start hidden only when JS is present to reveal
   them — .js is set on <html> by the head script, so a no-JS visitor sees
   everything immediately rather than a blank page. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--slow) var(--ease-out), transform var(--slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.js [data-reveal].revealed { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
}
