/* Page backdrop: faint grid, accent bloom, oversized brand watermarks.
 *
 * This used to live inside backtotop.js and get injected at runtime, which meant
 * the whole backdrop could not paint until the script had downloaded and run.
 * On a page it showed up as: text first, then grid, then logos, arriving in
 * three visible steps. As a stylesheet in <head> it is render-blocking, so it
 * paints in the same frame as the content.
 *
 * Uses var(--accent), so it turns orange by itself on TB pages.
 */

.stage { position: relative; }

/* Keep the centred top-bar logo at the TRUE viewport centre on every page.
 * The marketing pages scroll the <body>, so a page tall enough to need a
 * scrollbar loses ~10px of width on the right, which shifted the `1fr auto 1fr`
 * logo ~5px left versus a short page (and versus the app home, which scrolls an
 * inner pane and never loses header width). `stable both-edges` reserves a
 * matching gutter on the opposite side, so the content box stays symmetric and
 * the logo lands dead centre whether or not a scrollbar is present.
 * Scoped off the app (`.stage.app` = home / workspace) so the tool itself, which
 * already centres correctly and sits flush to the edge, gets no side gutters.
 * UPDATE: `both-edges` reserved a matching strip on the LEFT too, which reads as
 * an empty gap on any page with a full-bleed background. Plain `stable` reserves
 * the gutter only where the scrollbar actually is, and reserves it ALWAYS (even
 * on short pages), so the width stays constant page to page and the logo still
 * never shifts. Same fix, no gap. */
/* scrollbar-gutter removed: reserving a gutter left a visible bare strip beside
   the stage background (left edge with both-edges, right edge with stable).
   Not worth it for a ~7px logo shift on short pages. */

/* ---- one scrollbar for the whole site ----
   Every page used to set its own near-black track (#0a0e18), which reads as a
   hard black bar against the lighter footer. Transparent track + a soft rounded
   thumb blends everywhere and warms to the accent on hover. This file loads
   after each page's own <style>, so it overrides them all from one place. */
/* Matched to the app (arthur-ui-v2 uses --line2 #343d4a on a transparent track). White at 20%
   sat noticeably brighter than the page and read as a light bar down the side; the app looks
   like part of the page and the site did not. */
html { scrollbar-color: #343d4a transparent; scrollbar-width: thin; }
/* The same faint grid on <html> as on .stage::before below, so it CONTINUES under the
   scrollbar gutter. .stage is only as wide as the content box, so the ~10px the scrollbar
   occupies fell outside it and showed flat page colour: a plain strip down the right with
   no grid lines in it. background-attachment:fixed anchors this to the viewport exactly
   like the fixed pseudo-element, so the two line up cell for cell. */
html {
  background-image:
    linear-gradient(rgba(255,255,255,.075) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.075) 1px, transparent 1px);
  background-size: 52px 52px;
  background-attachment: fixed;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: #343d4a;
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
  background: rgba(59,130,246,.62);
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:active { background: rgba(59,130,246,.85); background-clip: padding-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* Faint grid, fixed and non-interactive.
   The mask used to reach transparent at 90%, which killed the grid entirely
   across the bottom of the screen and left the lower half looking bare. It now
   bottoms out at 22% instead of 0, so the grid thins but never vanishes. */
.stage::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(rgba(255,255,255,.075) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.075) 1px, transparent 1px);
  background-size: 52px 52px;
  -webkit-mask-image: radial-gradient(1600px 1500px at 50% 4%, #000 0%, rgba(0,0,0,.62) 58%, rgba(0,0,0,.22) 100%);
  mask-image: radial-gradient(1600px 1500px at 50% 4%, #000 0%, rgba(0,0,0,.62) 58%, rgba(0,0,0,.22) 100%);
}

/* Soft accent bloom.
   inset:-220px, NOT 0. This layer is animated sideways; at exactly viewport size
   its own edge slides into view and slices the gradient off mid-fade, which
   showed up as a hard vertical line down the screen. Oversizing it keeps every
   edge well outside the viewport for the whole travel. */
.stage::after {
  content: ""; position: fixed; inset: -220px; pointer-events: none; z-index: 0; opacity: .20;
  background:
    radial-gradient(760px 680px at 86% 4%, var(--accent), transparent 62%),
    radial-gradient(620px 580px at 8% 88%, var(--accent), transparent 62%),
    /* a third, wider and dimmer pool through the middle so the centre of the
       screen is not dead space between two corner glows */
    radial-gradient(1100px 900px at 50% 50%, var(--accent), transparent 70%);
}

/* TB keeps Arthur's grid (his call). It stays distinct via the orange accent,
   the TB monogram watermark, and different bloom placement. */
.stage.tb::after {
  opacity: .22;
  background:
    radial-gradient(720px 660px at 10% 2%, var(--accent), transparent 62%),
    radial-gradient(600px 560px at 92% 70%, var(--accent), transparent 62%),
    radial-gradient(1100px 900px at 50% 50%, var(--accent), transparent 70%);
}

/* Vignette. Sits above the glow and below the content, and darkens the outer
   frame so the middle of the screen reads as lit rather than as empty space.
   Uses body::after because .stage's own ::before and ::after are already the
   grid and the glow, and this needs no extra markup on 19 pages. */
body::after {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(125% 90% at 50% 42%, transparent 48%, rgba(0, 0, 0, .55) 100%);
}
/* Much lighter on a light ground: the same 55% black would look like grime. */
body:has(.stage[data-mode="light"])::after {
  background: radial-gradient(125% 90% at 50% 42%, transparent 52%, rgba(18, 26, 42, .16) 100%);
}

/* ===================== LIGHT MODE =====================
   The grid, the watermark and the wordmark are all WHITE, so on a light ground
   they vanish. Swap them to dark ink. Only the app toggles data-mode; the
   marketing pages stay dark, so this never touches them. */
.stage[data-mode="light"]::before {
  background-image:
    linear-gradient(rgba(28, 42, 72, .055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(28, 42, 72, .055) 1px, transparent 1px);
}
.stage[data-mode="light"] #bgart,
.stage[data-mode="light"] #bgart2,
.stage[data-mode="light"] .overlay.fs .fsart,
.stage[data-mode="light"] .overlay.fs .fsart2 { background-image: url(arthur-a-dark.png); }
/* the black-letter wordmark (blue A kept) replaces the white one wherever it is
   used, in one rule, by matching the src */
.stage[data-mode="light"] img[src="arthur-word.png"] { content: url(arthur-word-light.png); }

/* ===================== BATTERY SAVER =====================
   Settings > Background motion = Off sets html[data-motion="off"]. Drop the
   drifting brand marks and stop every backdrop animation. The grid and the
   static glow cost nothing to keep, so they stay. */
html[data-motion="off"] #bgart,
html[data-motion="off"] #bgart2,
html[data-motion="off"] .overlay.fs .fsart,
html[data-motion="off"] .overlay.fs .fsart2 { display: none; }
html[data-motion="off"] .stage::after { animation: none; }

/* oversized brand mark as background art, bottom right */
#bgart {
  position: fixed; right: -120px; bottom: -140px; width: 560px; height: 560px;
  pointer-events: none; z-index: 0; opacity: .055;
  background: url(arthur-a-lg.png) no-repeat center/contain;
}
/* TB swaps the image and nothing else: same box, same position, same drift as the
   Arthur mark, because Panos wants the TB pages to carry a watermark of exactly the
   same weight as every other page. tb-icon.png is only 311px against the Arthur A's
   1024px, so it is upscaled ~1.8x here; a 1px blur takes the hard edge off that
   without shrinking the mark. */
.stage.tb #bgart { background-image: url(tb-icon.png); filter: blur(1px); }

/* a second, smaller mark top left for balance */
#bgart2 {
  position: fixed; left: -90px; top: -60px; width: 320px; height: 320px;
  pointer-events: none; z-index: 0; opacity: .035;
  background: url(arthur-a-lg.png) no-repeat center/contain;
  transform: rotate(-14deg);
}
.stage.tb #bgart2 { background-image: url(tb-icon.png); filter: blur(1px); }

/* One shared backdrop everywhere: the app pages (home / workspace) show the SAME
   #bgart marks as the marketing pages, so moving between surfaces only swaps the
   content, never the background. */

/* ===================== AMBIENT MOTION =====================
   The backdrop drifts. Slowly enough that you never catch it moving, only
   notice the page is not a still image.
     - Only `transform` and `opacity` are animated, so the compositor handles it
       and nothing ever reflows.
     - The two marks run on 53s and 71s. Deliberately not multiples of each
       other, so the pair never falls into a visible repeating pattern.
     - The GRID stays perfectly still. A moving grid reads as cheap and makes
       some people queasy; it is the fixed reference the drift is measured
       against, so it has to stay put.
     - the app shares this exact motion now, so nothing jumps when you move
       between the home page, a workspace and the marketing pages. */

/* Amplitudes and speeds are what make this visible at all. The first attempt
   drifted 26px over 53s — under 1px per second, on a shape at 5% opacity, which
   is below the threshold of perception. These travel ~90px in 15s (about 6px/s)
   AND pulse in opacity, because at this contrast a brightness change registers
   far more than a positional one. */
/* 4-point orbits so the marks WANDER around the space (his call) rather than
   sliding to one spot and back. ~110px of travel, in the corners where there is
   room for it. */
/* 2026-07-26 — opacity FLOOR raised.
   These marks are positioned by a NEGATIVE wall-clock delay, so every page load
   starts at a random point in the 24s / 33s cycle. The old ranges (.05–.11 and
   .032–.078) meant a refresh landing near the trough rendered them essentially
   invisible against the near-black page, while one landing near the peak showed
   them clearly — which read as "sometimes the icons load, sometimes they don't".
   They were always loaded; only the phase differed. The pulse is kept (same shape,
   same timing) but now swings between "clearly there" and "a little brighter". */
@keyframes bgDriftA {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg);            opacity: .085; }
  25%      { transform: translate3d(-104px, -70px, 0) rotate(-9deg);  opacity: .125; }
  50%      { transform: translate3d(-44px, -118px, 0) rotate(5deg);   opacity: .1; }
  75%      { transform: translate3d(-112px, -22px, 0) rotate(-13deg); opacity: .115; }
}
@keyframes bgDriftB {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(-14deg);         opacity: .06; }
  25%      { transform: translate3d(92px, 64px, 0) rotate(-6deg);    opacity: .092; }
  50%      { transform: translate3d(40px, 112px, 0) rotate(-20deg);  opacity: .072; }
  75%      { transform: translate3d(104px, 26px, 0) rotate(-9deg);   opacity: .088; }
}
/* TB used to have its own bgDriftBtb pair (different base angle, dimmer pulse). It
   is gone: he wants the TB marks moving exactly like the Arthur ones, so both
   surfaces now share bgDriftA / bgDriftB. */
@keyframes bgBloom {
  0%, 100% { transform: translate3d(0, 0, 0);       opacity: .15; }
  50%      { transform: translate3d(54px, -40px, 0); opacity: .34; }
}
@keyframes bgBloomTb {
  0%, 100% { transform: translate3d(0, 0, 0);        opacity: .16; }
  50%      { transform: translate3d(-48px, 42px, 0); opacity: .35; }
}

/* animation-delay is driven by backtotop.js from the wall clock (--wm-*), so the
   drift is continuous across page loads instead of restarting each navigation. */
.stage #bgart  { animation: bgDriftA 24s ease-in-out infinite; animation-delay: var(--wm-a, 0s); }
.stage #bgart2 { animation: bgDriftB 33s ease-in-out infinite; animation-delay: var(--wm-b, 0s); }
.stage::after  { animation: bgBloom 23s ease-in-out infinite; animation-delay: var(--wm-bloom, 0s); }
.stage.tb::after         { animation-name: bgBloomTb; }
/* 2026-07-26: the drift is BACK ON. It was switched off on 07-25 while hunting a
   stutter, but the real cause turned out to be screens fetching their data on click
   and background polls redrawing mid-animation — nothing to do with the backdrop.
   These layers only animate transform/opacity, so the compositor handles them. */

@media (prefers-reduced-motion: reduce) {
  #bgart, #bgart2, .stage::after { animation: none !important; }
}

/* Keep real content above the backdrop.
   .abar is NOT in this list: it is position:sticky in the pages, and setting
   position:relative here silently un-stuck every marketing top bar so they
   scrolled away. It already carries z-index:10 of its own, which is well clear
   of the backdrop, so it needs nothing from us. */
.awrap, .hfoot, .hbar, .shell { position: relative; z-index: 1; }

@media (max-width: 640px) {
  /* .stage.tb is repeated on each selector because `.stage.tb #bgart` outscores a
     bare `#bgart`; without it the TB pages kept the desktop size on a phone. */
  #bgart, .stage.tb #bgart { width: 340px; height: 340px; right: -90px; bottom: -90px; }
  #bgart2, .stage.tb #bgart2 { display: none; }
  .stage::after { width: 420px; height: 420px; top: -180px; right: -160px; }
}


/* ---- 2026-07-27 fixes from Panos's review -------------------------------
   The site's top bar is `1fr auto 1fr`. The Greek labels are far longer than the
   English ones, so the right-hand nav grew into the centred wordmark and clipped
   it to "Arthı". Below 1150px the middle links step aside; back arrow, wordmark
   and the CTA are what matter.

   The TB marks used to be shrunk here (300/210px, blur 2px) on the theory that the
   311px monogram would read as a grey box at full size. Panos looked at it and said
   the opposite: too small, make them the same as the Arthur ones. Removed — the
   sizing now lives in one place, with #bgart / #bgart2 above. */
/* TB pages are orange: the Arthur wordmark in their top bar follows */
.stage.tb .abrand img { content: url(arthur-word-orange.png); }
.abar { gap: 10px; }
.abar .abrand { min-width: 0; }
.abar .abrand img { max-width: 100%; }
@media (max-width: 1150px) { .abar .anav { display: none; } }


/* ============================================================================
   GRID OFF — Panos, 2026-08-03. He never liked the lines: "they didn't match
   with the icons, they didn't match with the stars". The starfield and the
   accent bloom carry the background on their own now.
   The original rules are untouched above; this block simply switches them off.
   ★ TO RESTORE THE GRID EVERYWHERE: delete this block. Nothing else to undo.
   ============================================================================ */
html { background-image: none !important; }
.stage::before { background-image: none !important; }
