/* onlyfees.apocresistance.com — the OnlyFees palette over the site's own chrome.

   Same job as adri.css: loaded after styles.css, it reassigns the palette so
   every component already defined — windows, bevels, title bars, buttons,
   .pledge, .social, the status bar — comes out in azure without one of them
   being redefined. Adri's page is teal on purple-black; this one is azure on
   steel navy, so the two drops are instantly distinguishable in a screenshot
   while still obviously being the same site.

   Two things live only here: the drop-component remap (styles.css hardcodes
   Adri's teal/purple as literals rather than routing them through custom
   properties, so this page cannot inherit them for free), and the payout
   labyrinth at the bottom. */

:root {
  --paper:     #071a28;   /* desktop, steel navy */
  --panel:     #0d2436;   /* window body */
  --panel-2:   #123044;
  --chrome:    #16384f;   /* button face, menu bar */
  --bevel-hi:  #3d7fa5;
  --bevel-lo:  #03090f;
  --rule:      #020609;

  --ink:       #e9f4fb;
  --ink-dim:   #a8c6da;
  --ink-faint: #6d8da2;

  --navy:      #002d45;   /* title bars */
  --navy-2:    #004a70;

  /* the accent: everything that was ember on the main site is azure here */
  --ember:     #00aff0;
  --ember-hot: #5fdcff;
}

/* The mark glows ember on the main site; here it should agree with the page. */
@media (prefers-reduced-motion: no-preference) {
  .brand img { animation: none; }
}

.site-nav a {
  font-size: 0.68rem; color: var(--ink-dim);
  border-bottom: 1px solid transparent;
}
.site-nav a:hover { background: var(--navy-2); color: #fff; }

/* ---------- one column, generous on a phone ---------- */



.onlyfees .socials { margin-bottom: 1.25rem; }
.onlyfees .footnote { max-width: 62ch; }
.site-footer { margin-top: 0; }


/* ---------- the payout labyrinth ----------

   Drawn in the same idiom as the window it sits in: raised faces, 1px light
   edge top-left, 1px dark edge bottom-right, hard drop shadow, no curves
   anywhere. `crispEdges` everywhere, because antialiasing is what turns a
   crisp 1px bevel into grey mush.

   Two strokes per trace. The dim one is the wire; the bright one is a short
   dash travelling along it, normalised by pathLength="100" so a long detour and
   a short hop move at the same apparent speed. The severed stubs get neither —
   a dead route should look dead. */

.lab-scroll {
  overflow-x: auto;
  overflow-y: hidden;
  background: #05141f;
  border: 1px solid var(--rule);
  box-shadow: inset 1px 1px 0 var(--bevel-lo), inset -1px -1px 0 var(--bevel-hi);
  padding: 0.5rem;
  margin-bottom: 0.5rem;
}
.lab-scroll::-webkit-scrollbar { height: 14px; }
.lab-scroll::-webkit-scrollbar-track { background: var(--panel-2); }
.lab-scroll::-webkit-scrollbar-thumb {
  background: var(--chrome);
  border: 1px solid var(--rule);
  box-shadow: inset 1px 1px 0 var(--bevel-hi), inset -1px -1px 0 var(--bevel-lo);
}

.lab {
  display: block;
  width: 100%;
  min-width: 820px;
  height: auto;
  shape-rendering: crispEdges;
}

/* wires */
.lab-trace { fill: none; stroke: var(--ember); opacity: 0.32; stroke-width: 3; }
.lab-pulse {
  fill: none;
  stroke: var(--ember-hot);
  stroke-width: 5;
  stroke-linecap: butt;
  stroke-dasharray: 3 97;
  animation: lab-flow 2.8s linear infinite;
  animation-delay: var(--d, 0s);
}
@keyframes lab-flow {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}

/* routes that do not exist */
.lab-dead { fill: none; stroke: var(--ink-faint); opacity: 0.5; stroke-width: 3; stroke-dasharray: 3 5; }
.lab-cut { stroke: #ff5f5f; stroke-width: 3; fill: none; }
.lab-dead-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  fill: var(--ink-faint);
}

/* the controls */
.lab-shadow { fill: rgba(0, 0, 0, 0.45); }
.lab-face   { fill: var(--chrome); }
.lab-hi     { stroke: var(--bevel-hi); stroke-width: 2; fill: none; }
.lab-lo     { stroke: var(--bevel-lo); stroke-width: 2; fill: none; }

/* The sources are quieter than the destinations: the story of this diagram is
   where the money ENDS UP, so the model wallets carry the accent — the same
   relationship .btn has to .btn-primary — and the traders do not compete. */
.face-src   { fill: var(--panel-2); }
.face-split { fill: var(--navy-2); }
.face-out   { fill: var(--ember); }

.lab-title {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  fill: var(--ink);
  text-anchor: middle;
}
.lab-out .lab-title { fill: #042231; }
.lab-src .lab-title { fill: var(--ink-dim); }
.lab-cap {
  font-family: var(--mono);
  font-size: 11px;
  fill: var(--ink-faint);
  text-anchor: middle;
}

.lab-node:hover .lab-face { fill: var(--panel-2); }
.lab-node:hover .face-out { fill: var(--ember-hot); }

.lab-hint {
  display: none;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-faint);
  margin: 0 0 1rem;
}
@media (max-width: 54rem) { .lab-hint { display: block; } }

/* ---------- the numbered steps, in the same window ---------- */

.flow { list-style: none; margin: 1.25rem 0 0; padding: 0; }
.step {
  display: grid; grid-template-columns: auto 1fr; gap: 0.9rem;
  align-items: start;
  padding: 0.85rem 0;
  border-top: 1px solid #143f5c;
}
.step:first-child { border-top: 0; padding-top: 0; }

/* The number is a raised control, same as everything else on the page. */
.step-n {
  font-family: var(--mono); font-weight: 600; font-size: 0.72rem;
  width: 1.9rem; height: 1.9rem;
  display: grid; place-items: center;
  background: var(--chrome); color: var(--ember);
  border: 1px solid var(--rule);
  box-shadow: inset 1px 1px 0 var(--bevel-hi), inset -1px -1px 0 var(--bevel-lo);
}

.step-body h3 { margin: 0.1rem 0 0.3rem; font-size: 0.95rem; }
.step-body p { margin: 0; color: var(--ink-dim); font-size: 0.92rem; }
.step-body em { color: var(--ink); font-style: normal; font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .lab-pulse { animation: none; stroke-dasharray: none; opacity: 0.8; }
}

/* One nav link, so it has no business wrapping onto its own row and making a
   sticky header two lines tall on the phones this page is actually read on. */
@media (max-width: 40rem) {
  .site-nav { width: auto; margin-left: auto; }
  .site-header .wrap { flex-wrap: nowrap; gap: 0.5rem; }
  .brand-unit { display: none; }
}


/* A raised control needs its highlight lighter than its own face and its shadow
   darker. The shared --bevel-hi is tuned for the chrome face and is DARKER than
   azure, so on the accent nodes it read as a second shadow and flattened them.
   Each accent face gets its own pair. */

.lab-out .lab-hi   { stroke: #a9e7ff; }
.lab-out .lab-lo   { stroke: #00587d; }
.lab-split .lab-hi { stroke: #2f80ad; }
.lab-split .lab-lo { stroke: #00172a; }


/* ---------- everything breathes ----------

   A slow edge glow on every raised surface. It is deliberately slow and low
   contrast: this runs on every box at once, and anything faster or brighter
   stops being atmosphere and starts being a hazard. Staggered so the page
   ripples rather than throbbing as one block, and off entirely for anyone who
   has asked for reduced motion. */

@keyframes edge-pulse {
  0%, 100% {
    box-shadow:
      inset 1px 1px 0 var(--bevel-hi), inset -1px -1px 0 var(--bevel-lo),
      3px 3px 0 rgba(0, 0, 0, 0.45),
      0 0 0 1px rgba(0, 175, 240, 0.14), 0 0 12px -3px rgba(0, 175, 240, 0.25);
  }
  50% {
    box-shadow:
      inset 1px 1px 0 var(--bevel-hi), inset -1px -1px 0 var(--bevel-lo),
      3px 3px 0 rgba(0, 0, 0, 0.45),
      0 0 0 1px rgba(0, 175, 240, 0.5), 0 0 24px -2px rgba(0, 175, 240, 0.55);
  }
}

@keyframes edge-pulse-flat {
  0%, 100% { box-shadow: 0 0 0 1px rgba(0, 175, 240, 0.12), 0 0 12px -4px rgba(0, 175, 240, 0.25); }
  50%      { box-shadow: 0 0 0 1px rgba(0, 175, 240, 0.45), 0 0 22px -3px rgba(0, 175, 240, 0.5); }
}

@media (prefers-reduced-motion: no-preference) {
  .onlyfees .win     { animation: edge-pulse 4.2s ease-in-out infinite; }
  .onlyfees .lab-scroll { animation: edge-pulse-flat 4.2s ease-in-out infinite 1s; }
  .onlyfees .social    { animation: edge-pulse 4.2s ease-in-out infinite; animation-delay: 2s; }

  /* SVG cannot take a box-shadow, so the nodes glow with a filter instead.
     --n comes off each group, so the ripple runs left to right with the flow. */
  .lab-face { animation: node-pulse 3.6s ease-in-out infinite; animation-delay: calc(var(--n, 0) * 0.16s); }
}

@keyframes node-pulse {
  0%, 100% { filter: drop-shadow(0 0 1px rgba(0, 175, 240, 0.25)); }
  50%      { filter: drop-shadow(0 0 7px rgba(0, 175, 240, 0.75)); }
}

@media (prefers-reduced-motion: reduce) {
  .lab-node { animation: none; }
}


/* ---------- the ticker tape ----------

   A market tape: symbol, value, arrow, movement since load. Monospace does the
   aligning -- an earlier version gave every digit its own min-width, which
   fought the grid the font already provides and left the numbers visibly out of
   line. Tabular figures and nothing else.

   The track carries two copies of the entries and translates by exactly -50%,
   so the instant the first copy leaves, the second is where it began and the
   loop has no seam. */

.tape {
  position: relative;
  overflow: hidden;
  background: #03101a;
  border: 1px solid var(--rule);
  box-shadow: inset 1px 1px 0 var(--bevel-lo), inset -1px -1px 0 var(--bevel-hi);
  padding: 0.6rem 0;
}

/* Entries should arrive and leave, not pop in at a hard edge. */
.tape::before, .tape::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 3.5rem;
  z-index: 2; pointer-events: none;
}
.tape::before { left: 0;  background: linear-gradient(90deg, #03101a, rgba(3, 16, 26, 0)); }
.tape::after  { right: 0; background: linear-gradient(270deg, #03101a, rgba(3, 16, 26, 0)); }

.tape-track {
  display: flex;
  width: max-content;
  animation: tape-roll 54s linear infinite;
}
/* Hovering holds it still, so a number can actually be read. */
.tape:hover .tape-track { animation-play-state: paused; }

@keyframes tape-roll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.tick {
  display: inline-flex; align-items: baseline; gap: 0.55rem;
  padding: 0 1.3rem;
  font-family: var(--mono);
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  border-right: 1px solid rgba(157, 180, 200, 0.1);
}
.tick .sym {
  color: var(--ink-faint); font-weight: 600;
  font-size: 0.74rem; letter-spacing: 0.16em;
}
.tick .val { font-weight: 600; }
.tick .chg { font-size: 0.76rem; }
.tick .delta { font-style: normal; margin-left: 0.2rem; }

.tick.up   .val, .tick.up   .chg { color: #3ef08a; }
.tick.down .val, .tick.down .chg { color: #ff5f5f; }
.tick.flat .val { color: var(--ember-hot); }

/* The flash on movement. Green and red keep their own, so a tick that means a
   token died never lights up the same colour as one that means it was caught. */
.tick.hit { animation: tape-hit 0.85s ease-out 1; }
.tick.down.hit { animation-name: tape-hit-down; }

@keyframes tape-hit {
  0%   { background: rgba(62, 240, 138, 0.32); }
  100% { background: transparent; }
}
@keyframes tape-hit-down {
  0%   { background: rgba(255, 95, 95, 0.32); }
  100% { background: transparent; }
}


@media (prefers-reduced-motion: reduce) {
  /* No scroll, no flash, and the duplicate copy hidden -- it exists only to
     make the loop seamless, and a static tape would just show everything twice. */
  .tape-track { animation: none; flex-wrap: wrap; width: auto; }
  .tape-track > [aria-hidden] { display: none; }
  .tape::before, .tape::after { display: none; }
  .tick.hit { animation: none; }
}

/* ================= the terminal layout =================

   Three tracks: a vertical tape down each edge, content between them. The rails
   are sticky for the full viewport height, so the instrumentation never leaves
   the screen — the claim this page is making is that the coin comes out of a
   desk already watching the chain, and that should be visible the whole time
   someone is reading, not once in a strip they scroll past.

   Below 68rem there is no room for three tracks, so the rails go and the
   horizontal tape inside the content carries the same numbers on its own. */

:root { --rail: 3.4rem; }

.shell {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr) var(--rail);
  align-items: start;
  max-width: 108rem;
  margin: 0 auto;
}

.onlyfees {
  min-width: 0;
  padding: 0 clamp(1.15rem, 4vw, 3.25rem) clamp(2rem, 5vw, 4rem);
}
.onlyfees section { padding-bottom: clamp(2rem, 5vw, 3.75rem); }

/* Wider than the old 46rem column: the labyrinth stops being cramped, the desk
   cards get a real grid, and the page reads as a workspace instead of a leaflet.
   Prose still gets a measure — `max-width` on the text, not on the container. */
.onlyfees-hero { padding-top: clamp(1.5rem, 5vw, 3rem); }
.onlyfees-hero h1 { max-width: 18ch; font-size: clamp(1.9rem, 5.2vw, 3.4rem); }
.onlyfees-hero .lede { max-width: 56ch; font-size: clamp(1rem, 1.6vw, 1.14rem); }

.sec-head { margin-bottom: clamp(1.1rem, 2.5vw, 1.6rem); }
.sec-sub { max-width: 68ch; color: var(--ink-dim); margin: 0; }
.sec-sub em { color: var(--ink); font-style: normal; font-weight: 600; }
.sec-sub a { color: var(--ember-hot); border-bottom: 1px solid currentColor; }

@media (max-width: 68rem) {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .rail { display: none; }
}

/* ---------- the rails ---------- */

.rail {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: #03101a;
  box-shadow: inset 1px 0 0 var(--bevel-lo), inset -1px 0 0 var(--bevel-lo);
}
.rail-l { border-right: 1px solid var(--rule); }
.rail-r { border-left: 1px solid var(--rule); }

/* Both ends fade, so entries arrive and leave instead of being guillotined. */
.rail::before, .rail::after {
  content: ""; position: absolute; left: 0; right: 0; height: 5rem;
  z-index: 2; pointer-events: none;
}
.rail::before { top: 0;    background: linear-gradient(180deg, #03101a, rgba(3, 16, 26, 0)); }
.rail::after  { bottom: 0; background: linear-gradient(0deg,   #03101a, rgba(3, 16, 26, 0)); }

.rail-track {
  display: flex;
  flex-direction: column;
  animation: rail-roll 70s linear infinite;
}
/* Opposed directions. Two identical columns in lockstep read as wallpaper; run
   them against each other and it reads as a machine. */
.rail-l .rail-track { animation-direction: reverse; }
.rail:hover .rail-track { animation-play-state: paused; }

@keyframes rail-roll {
  from { transform: translateY(0); }
  to   { transform: translateY(-50%); }
}

/* Sideways text: the rail is 3.4rem and a ticker entry is not. */
.rail .tick {
  writing-mode: vertical-rl;
  display: flex; align-items: center; justify-content: flex-start;
  gap: 0.6rem;
  padding: 1.35rem 0;
  border-right: 0;
  border-bottom: 1px solid rgba(157, 180, 200, 0.1);
  font-size: 0.82rem;
}
.rail .tick .sym { font-size: 0.68rem; }

/* ---------- the desk ---------- */

.desk { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
@media (min-width: 46rem) { .desk { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 76rem) { .desk { grid-template-columns: repeat(3, 1fr); } }

.desk-card {
  background: var(--panel);
  padding: clamp(1rem, 2.2vw, 1.4rem);
  transition: background 0.3s ease;
}
.desk-card:hover { background: var(--panel-2); }
.desk-cmd {
  display: block;
  font-family: var(--mono); font-size: 0.92rem; font-weight: 600;
  color: var(--ember); letter-spacing: 0.04em;
  margin-bottom: 0.55rem;
}
.desk-card p { margin: 0 0 0.6rem; color: var(--ink-dim); font-size: 0.9rem; }
/* The limit line is the reason each of these is worth trusting, so it is set
   apart rather than tucked into the paragraph above it. */
.desk-limit {
  margin: 0 !important;
  padding-top: 0.6rem;
  border-top: 1px solid rgba(157, 180, 200, 0.14);
  font-family: var(--mono); font-size: 0.74rem; line-height: 1.55;
  color: var(--ink-faint) !important;
}
.desk-limit::before { content: "LIMITS: "; color: var(--ember); }

/* ---------- scroll-driven reveals ----------

   Native scroll timelines: no observer, no scroll listener, no layout thrash,
   and nothing to clean up. Guarded twice — browsers without support simply never
   match, so the content is visible by default and enhancement is the only thing
   that can be lost. */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: reveal-rise linear both;
      animation-timeline: view();
      animation-range: entry 2% entry 42%;
    }
    .desk-card {
      animation: reveal-fade linear both;
      animation-timeline: view();
      animation-range: entry 4% entry 46%;
    }
  }
}

@keyframes reveal-rise {
  from { opacity: 0; transform: translateY(34px); }
  to   { opacity: 1; transform: none; }
}
@keyframes reveal-fade {
  from { opacity: 0; transform: translateY(18px) scale(0.99); }
  to   { opacity: 1; transform: none; }
}


@media (prefers-reduced-motion: reduce) {
  /* Not "stop scrolling" — that left two 2,260px columns of the same numbers
     repeated four times down the edges. They are decoration; the tape carries
     the labelled copy. */
  .rail { display: none; }
}

/* Section titles are h2 for structure, but they are still the small mono label
   visually — h2's own size, family and margin would otherwise override .label
   on the properties .label does not set. */
.onlyfees h2.label {
  font-family: var(--mono);
  font-size: clamp(0.62rem, 1.4vw, 0.7rem);
  font-weight: 600;
  line-height: 1.5;
  margin: 0 0 1rem;
}
.onlyfees .sec-head h2.label { margin-bottom: 0.7rem; }

/* ================= review fixes ================= */

/* A2 — styles.css `a:hover` (0,1,1) sets an azure BACKGROUND and `.sec-sub a`
   (0,1,1) sets an azure-hi COLOUR. Equal specificity, so each property came
   from a different rule and the result was azure-on-azure at 1.57:1: the link
   vanished on hover. Same remap .btn-primary already uses. */
.onlyfees a:hover,
.sec-sub a:hover,
.footnote a:hover,
.onlyfees .social:hover { color: #042231; }
.onlyfees .social:hover .social-handle { color: rgba(4, 34, 49, 0.75); }

/* Measure. Widening the shell stretched the flow prose to ~152 characters a
   line — roughly double what is readable, on the page's core explanation.
   The container got wider; the text should not have. */
.step-body p { max-width: 72ch; }
.onlyfees .footnote { max-width: 76ch; }
.desk-card p { max-width: 46ch; }

/* The limit line carries this page's credibility and was the palest text on it,
   at 4.88:1 — passing AA by a hair at ~12px. */
.desk-limit { color: #82a3b8 !important; }

/* Section headings had no mid-level voice: one 54px h1, then everything
   announced by an 11px chip that disappears in a 1200px column. The chip stays
   as an eyebrow above a heading that is actually sized. */
.onlyfees .sec-head h2.label,
.onlyfees section > h2.label {
  font-family: var(--sans);
  font-size: clamp(1.2rem, 1.9vw, 1.55rem);
  font-weight: 600;
  letter-spacing: -0.012em;
  text-transform: none;
  color: var(--ink);
  margin: 0 0 0.65rem;
}

/* The diagram was being upscaled to 1143px against a 1000-unit viewBox — a
   1.143x non-integer scale under crispEdges, which snaps 1px bevels unevenly.
   The pixel idiom only works at or below 1:1. */
.lab { max-width: 1000px; }

/* A6 — the header and status bar sit in a 74rem .wrap while the shell runs to
   108rem, so the brand floated 54px inside the h1 and the chrome read as
   mis-registered. Align them to the same gutter the content uses. */
@media (min-width: 68rem) {
  .site-header .wrap,
  .statusbar .wrap {
    max-width: 108rem;
    padding-left: calc(var(--rail) + clamp(1.15rem, 4vw, 3.25rem));
    padding-right: calc(var(--rail) + clamp(1.15rem, 4vw, 3.25rem));
  }
}

/* The sticky header (z-index 50) was painting over the rails' top 47px,
   including the whole top fade, so entries were guillotined at its edge. */
.rail { top: var(--header-h, 47px); height: calc(100svh - var(--header-h, 47px)); z-index: 1; }

/* Opposed directions only read as opposed if the two sides are out of phase.
   `animation-direction: reverse` starts the left rail at -50%, which on
   duplicated content is pixel-identical to 0 — so at load both rails were
   perfectly mirrored, which is the exact "repeated texture" the split was meant
   to avoid. Different durations keep them from ever settling into a beat. */
.rail-l .rail-track { animation-duration: 83s; animation-delay: -41s; }
.rail-r .rail-track { animation-duration: 70s; }

/* vertical-rl rotates glyphs head-right, which is the correct spine direction
   on a right-hand edge and the wrong one on a left-hand edge. */
.rail-l .tick { writing-mode: sideways-lr; }

/* The left rail lists what the screener looks at, not a number, so it is set
   quieter than the counters opposite it. */
.rail .tick.check .val { color: var(--ink-dim); font-weight: 500; letter-spacing: 0.1em; }
.rail .tick.check .sym { color: var(--ember); opacity: 0.75; }

/* A7 — .lab-scroll actually overflows until ~945px, because the window body and
   scroll padding eat ~90px on top of the page gutter. The hint was keyed to
   864px and left a dead band where it scrolls with no affordance. */
@media (max-width: 60rem) { .lab-hint { display: block; } }

/* ---------- the motion switch ---------- */

.motion-toggle {
  font-family: var(--mono); font-size: 0.62rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  background: var(--chrome); color: var(--ink-dim);
  border: 1px solid var(--rule);
  box-shadow: inset 1px 1px 0 var(--bevel-hi), inset -1px -1px 0 var(--bevel-lo);
  padding: 0.15rem 0.55rem;
  cursor: pointer;
}
.motion-toggle b { color: var(--ember); font-weight: 600; }
.motion-toggle:hover { background: var(--panel-2); color: var(--ink); }
.motion-toggle:active { box-shadow: inset 1px 1px 0 var(--bevel-lo); transform: translate(1px, 1px); }

/* One switch, everything it governs. !important because several of these are
   set inside @supports/@media blocks that would otherwise out-cascade it. */
html[data-motion="off"] .rail { display: none; }
html[data-motion="off"] .tape-track,
html[data-motion="off"] .rail-track,
html[data-motion="off"] .lab-pulse,
html[data-motion="off"] .lab-node,
html[data-motion="off"] .onlyfees .win,
html[data-motion="off"] .onlyfees .social,
html[data-motion="off"] .onlyfees .lab-scroll,
html[data-motion="off"] .reveal,
html[data-motion="off"] .desk-card,
html[data-motion="off"] .tick,
html[data-motion="off"] .dot,
html[data-motion="off"] .caret { animation: none !important; }
/* A reveal that never runs must not be left at its from-state. */
html[data-motion="off"] .reveal,
html[data-motion="off"] .desk-card { opacity: 1 !important; transform: none !important; }
html[data-motion="off"] .lab-pulse { stroke-dasharray: none; opacity: 0.8; }
html[data-motion="off"] .tape-track { flex-wrap: wrap; width: auto; }
html[data-motion="off"] .tape-track > [aria-hidden] { display: none; }

/* ================= the modern pole =================

   The retro objects don't change; the frame around them does. Big type, a lot
   of air, and sections that assemble as you scroll — so the contrast is between
   a cinematic modern stage and hard 1995 objects standing on it, rather than a
   single costume worn evenly across the whole page. */

.onlyfees section { padding-bottom: clamp(3.5rem, 11vh, 9rem); }
.onlyfees-hero { padding-top: clamp(3rem, 14vh, 10rem); padding-bottom: clamp(3rem, 12vh, 8rem); }

.onlyfees-hero h1 {
  font-size: clamp(2.4rem, 7.2vw, 5.6rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  max-width: 15ch;
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
}
.onlyfees-hero .lede {
  font-size: clamp(1.05rem, 1.9vw, 1.35rem);
  max-width: 52ch;
  line-height: 1.6;
}

.onlyfees .sec-head h2.label,
.onlyfees section > h2.label {
  font-size: clamp(1.45rem, 3vw, 2.4rem);
  letter-spacing: -0.025em;
  margin-bottom: 0.8rem;
}
.sec-sub { font-size: clamp(0.95rem, 1.5vw, 1.08rem); }

/* The diagram assembles node by node on scroll. --n already carries flow order,
   so the circuit builds itself left to right as it comes into view. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .lab-node {
      animation: node-assemble linear both;
      animation-timeline: view();
      animation-range: entry calc(6% + var(--n, 0) * 2.6%) entry calc(34% + var(--n, 0) * 2.6%);
    }
  }
}
@keyframes node-assemble {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
html[data-motion="off"] .lab-node { animation: none !important; opacity: 1 !important; transform: none !important; }

/* ================= period furniture ================= */

.sysreq th { width: 14rem; }
.sysreq td { color: var(--ink); }
.sysreq-note {
  margin: 1rem 0 0; font-size: 0.82rem; color: var(--ink-faint); max-width: 64ch;
}

/* ---- licence agreement ---- */

.eula[hidden] { display: none; }
.eula {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
}
.eula .modal-shade { position: absolute; inset: 0; background: rgba(2, 8, 14, 0.78); }
.eula-win { position: relative; width: min(46rem, 100%); max-height: 86vh; display: flex; flex-direction: column; }
.eula-win .win-body { overflow: hidden; display: flex; flex-direction: column; }
.eula-scroll {
  overflow-y: auto;
  max-height: 52vh;
  padding: 1rem 1.15rem;
}
.eula-scroll h3 {
  font-family: var(--mono); font-size: 0.76rem; letter-spacing: 0.1em;
  color: var(--ember); margin: 1.2rem 0 0.35rem;
}
.eula-scroll h3:first-child { margin-top: 0; }
.eula-scroll p { margin: 0; color: var(--ink-dim); font-size: 0.88rem; }
.eula-foot { margin: 0.9rem 0 1rem; font-size: 0.8rem; color: var(--ink-faint); }
.eula-cta { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin: 0 0 1.25rem; }
.eula-cta span { font-size: 0.78rem; color: var(--ink-faint); font-family: var(--mono); }

/* ---- the assistant ---- */

.clippy[hidden] { display: none; }
.clippy {
  position: fixed; right: clamp(0.75rem, 2vw, 1.5rem); bottom: clamp(0.75rem, 2vw, 1.5rem);
  z-index: 180;
  display: flex; align-items: flex-end; gap: 0.5rem;
  max-width: min(23rem, calc(100vw - 2rem));
}
.clippy-bubble {
  background: #f6f4d8;              /* the only warm surface on the page, on purpose */
  color: #14202b;
  border: 1px solid #020609;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.5);
  padding: 0.75rem 0.85rem;
  font-size: 0.85rem;
  position: relative;
}
.clippy-bubble p { margin: 0 0 0.6rem; }
.clippy-bubble::after {
  content: ""; position: absolute; right: -7px; bottom: 14px;
  width: 0; height: 0;
  border-left: 7px solid #f6f4d8;
  border-top: 6px solid transparent; border-bottom: 6px solid transparent;
}
.clippy-actions { display: flex; gap: 0.4rem; }
.clippy-actions .btn {
  background: #d6d2b4; color: #14202b; border-color: #020609;
  box-shadow: inset 1px 1px 0 #fffdf0, inset -1px -1px 0 #8d8a72;
  padding: 0.3rem 0.65rem; font-size: 0.66rem;
}
.clippy-actions .btn:hover { background: #e4e0c4; color: #14202b; }
.clippy-art { width: 34px; height: 52px; flex: none; }
.clippy-art .clip { fill: none; stroke: #cfd8de; stroke-width: 4.5; stroke-linecap: round; }
.clippy-art .eyes ellipse { fill: #f6f8fa; stroke: #14202b; stroke-width: 1.5; }
.clippy-art .pupil { fill: #14202b; }

/* ---- blue screen ---- */

.bsod[hidden] { display: none; }
.bsod {
  position: fixed; inset: 0; z-index: 300;
  background: #0000aa;
  color: #fff;
  font-family: var(--mono);
  display: grid; place-items: center;
  padding: clamp(1rem, 6vw, 4rem);
  cursor: pointer;
}
.bsod-inner { max-width: 46rem; font-size: clamp(0.78rem, 1.6vw, 0.95rem); line-height: 1.8; }
.bsod-head {
  background: #aaa; color: #0000aa;
  display: inline-block; padding: 0 0.6rem; margin: 0 0 1.5rem;
  font-weight: 700; letter-spacing: 0.1em;
}
.bsod ul { list-style: none; padding: 0; margin: 1.2rem 0; }
.bsod-foot { margin-top: 2rem; }
html[data-bsod="on"] { overflow: hidden; }

@media (max-width: 34rem) {
  .clippy-art { display: none; }
  .clippy-bubble::after { display: none; }
}
