/* ─── Polish layer ───────────────────────────────────────────────────────────
   Defect fixes only. Refinement, not redesign: nothing here changes the
   design's visual world, copy, layout, or behaviour — it fixes what was
   incomplete. Creative changes (hero phrase motion, scroll-driven graph,
   deep-linked pricing) are deliberately NOT here; those are redesign and
   belong in their own pass.

   Kept in its own file so the design's verbatim CSS (site.css) stays diffable
   against the source, and so every fix below is auditable as an addition.

   Findings sourced from: Vercel Web Interface Guidelines (vendored in
   niro-studio/skills/web-guidelines) + a live-DOM audit of the rendered page.
   ─────────────────────────────────────────────────────────────────────────── */

/* ── 1. Keyboard access — 37 of 45 interactive elements had no visible focus.
      The page was fully mouse-dependent, which the design system's own 4.5:1
      contrast floor implies it must not be. One rule, every control. ── */
:where(a, button, input, select, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  box-shadow: var(--focus-ring);
  border-radius: 6px;
}
/* Dark sections (#graph, #beta) sit on --ink; the teal ring holds contrast on
   both, so only the offset needs to grow where controls sit flush to an edge. */
#graph :where(a, button):focus-visible,
#beta :where(a, button, input):focus-visible { outline-offset: 3px; }

/* The email field replaced its outline with nothing. Restore a real focus
   affordance rather than removing the author's resting-state intent. */
#beta input[type="email"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  box-shadow: var(--focus-ring);
}

/* ── 2. Tabular figures — 44 metric nodes animate their values. Proportional
      digits change width per frame, so every counter visibly wobbles while
      counting. This is the single highest-value fix on the page. ── */
[data-bt-text] { font-variant-numeric: tabular-nums; }

/* ── 3. Anchor offset — the nav is sticky, so every in-page link scrolled its
      own heading underneath the bar. The 16px is breathing room, not chrome. ── */
section[id] { scroll-margin-top: calc(var(--nav-h) + 16px); }

/* ── 4. Touch — expand hit areas to 44px without moving a single pixel
      visually. Nav links render 33-40px tall; the pseudo-element grows the
      target, not the layout. ── */
@media (pointer: coarse) {
  nav a, nav button { position: relative; }
  nav a::after, nav button::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    top: 50%;
    transform: translateY(-50%);
    min-height: 44px;
    height: 100%;
  }
}

/* Kill the 300ms double-tap delay and make the tap flash intentional
   rather than the platform default blue. */
html { touch-action: manipulation; -webkit-tap-highlight-color: var(--accent-soft); }

/* ── 5. Screen-reader parity for the two async confirmations. The button
      labels swap to "copied" / "On the list ✓" with no announcement. ── */
.sr-live {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── 6. Press feedback (DS: press = scale .98, icon buttons .94; Emil: every
      pressable element confirms the press). Scale replaces the hover lift for
      the press duration — deliberate, the press is the response. ── */
button:active,
.hv-7:active, .hv-9:active, .hv-18:active, .hv-19:active, .n-ghost:active, .n-band-cta:active {
  transform: scale(var(--scale-press));
  transition-duration: var(--dur-instant);
}
.n-burger:active, .n-burgerx:active, .n-burger-close:active { transform: scale(var(--scale-press-hard)); }
/* Nav and menu links answer the press too. Their hover tint is gated on a fine
   pointer, so on touch they had no feedback at all; the tint on :active is the
   same one hover uses, applied the instant the pointer goes down. */
.hv-1:active, .hv-4:active, .hv-5:active { background: var(--surface-alpha-md); transition-duration: var(--dur-instant); }


/* ── 8. Icon-button hover parity — burger/close were the only controls with
      no hover affordance. DS: hover = lift + accent border. ── */
.n-burger:hover, .n-burgerx:hover, .n-burger-close:hover { border-color: var(--accent); transform: translateY(var(--lift-hover)); transition: border-color var(--dur-fast) var(--ease-niro), transform var(--dur-fast) var(--ease-niro); }

/* glass nav fallbacks: the inline style sets the translucent material, so these
   need !important to win. Reduced transparency gets a solid surface; more
   contrast gets a solid surface plus a defined edge. */
@media (prefers-reduced-transparency: reduce) {
  nav[aria-label="Main"] { background: var(--surface-page) !important; -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }
}
/* the HUMAN | MACHINE pill is the same glass material (machine.js injects it);
   the id outranks its class rule, so no !important is needed here */
@media (prefers-reduced-transparency: reduce) {
  #niro-mode-pill { background: var(--surface-card); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
@media (prefers-contrast: more) {
  #niro-mode-pill { background: var(--surface-card); -webkit-backdrop-filter: none; backdrop-filter: none; border-color: var(--border-strong); }
}
@media (prefers-contrast: more) {
  nav[aria-label="Main"] { background: var(--surface-page) !important; -webkit-backdrop-filter: none !important; backdrop-filter: none !important; border-bottom: 1px solid var(--border-strong); }
}

/* ── 9. Nav wayfinding and menu craft. The nav markup is duplicated across
      every page and parity-tested, so all of this is CSS over it. ── */

/* Peers look like peers: the two dropdown triggers rendered 600/primary
   beside 500/muted links, so the row read as two kinds of thing. Triggers
   take the links' weight and ink; hover, open and "current section" lift
   them back to primary. !important because the weights are inline. */
.n-navlinks [data-menu-btn] { font-weight: 500 !important; color: var(--text-muted) !important; }
.n-navlinks [data-menu-btn]:hover,
.n-navlinks [data-menu-btn][aria-expanded="true"],
.n-navlinks [data-menu]:has([aria-current="page"]) [data-menu-btn] { color: var(--text-primary) !important; }

/* Where am I: every page already stamps aria-current, but nothing showed it. */
.n-navlinks > a[aria-current="page"] { color: var(--text-primary) !important; }
[data-menu-drop] a[aria-current="page"] { background: var(--surface-alpha-md); }
.n-mdrawer a[aria-current="page"]:not([data-niro-book]) { color: var(--accent) !important; }

/* The chevron states open vs closed instead of sitting still. */
[data-menu-btn] svg { transition: transform var(--dur-fast) var(--ease-niro); }
[data-menu-btn][aria-expanded="true"] svg { transform: rotate(180deg); }

/* Hover bridge: the panel sits 8px below its trigger, and crossing that gap
   left the wrapper and fired mouseleave. The bridge is part of the panel, so
   the pointer never leaves the menu on the way down. */
[data-menu-drop]::before { content: ''; position: absolute; left: 0; right: 0; top: -8px; height: 8px; }

/* The mobile drawer appeared with no transition. It now arrives from the bar
   it hangs off, on the same path and timing as the desktop dropdowns. */
@keyframes nDrawerIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.n-mdrawer:target { animation: nDrawerIn var(--dur-fast) var(--ease-niro); }

/* Footer links answer the press like every other link. */
.n-flink:active { color: var(--text-primary); }
