* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
}

body {
  background: var(--ink);
  color: var(--paper);
  font-family:
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
    sans-serif;
}

a {
  color: inherit;
}

/* Turnstile's interaction-only widget renders nothing at all for a visitor
   Cloudflare is happy about, so the container must take no room until it
   actually holds a challenge — otherwise every signup form carries a gap
   for something that is usually not there. */
.turnstile:not(:empty) {
  margin: 0.75rem 0;
}

/* The Google entry point is an <a> wearing button styling, so it needs the
   underline off; the wrapper is `hidden` until GET /api/config says the
   route exists, which is what keeps a switched-off deploy from showing a
   button that 404s. */
.google-btn {
  text-decoration: none;
}

/* ── Skip link ──────────────────────────────────────────────────────────
   First in tab order on every page (each page's HTML carries the anchor).
   Visually hidden until focused, so sighted screenshots never change. */

.skip-link {
  position: absolute;
  top: -100px;
  left: 1rem;
  z-index: 200;
  padding: 0.7rem 1.1rem;
  border-radius: 999px;
  background: var(--paper, #fff);
  color: var(--ink, #16130f);
  font-weight: 700;
  font-size: 0.85rem;
  text-decoration: none;
  box-shadow: 0 12px 32px -8px rgba(11, 11, 12, 0.35);
}

.skip-link:focus-visible {
  top: 1rem;
  outline: 2px solid var(--focus-ring, currentColor);
  outline-offset: 2px;
}

/* A shared visually-hidden utility. landing.css keeps its own copy for
   the pages that never load the app sheets; both spell the same thing. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ── Accessible tooltip bubble ──────────────────────────────────────────
   One style for both canvases: a near-black pill with paper text and a
   hairline edge reads on the dark marketing ground and on the warm app
   ground alike, which is what keeps one `#nt-tip` element cohesive
   across all four front doors. Hidden by default — no layout, no
   screenshot diff — until `tooltip.js` fills and places it. */

#nt-tip {
  position: fixed;
  z-index: 150;
  max-width: 16rem;
  padding: 0.55rem 0.7rem;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: #16130f;
  color: #fdfcf9;
  font-size: 0.8rem;
  font-weight: 500;
  line-height: 1.45;
  box-shadow: 0 12px 32px -8px rgba(11, 11, 12, 0.5);
  pointer-events: none;
  animation: nt-tip-in 120ms ease;
}

#nt-tip[hidden] {
  display: none;
}

#nt-tip::before {
  content: "";
  position: absolute;
  width: 10px;
  height: 10px;
  background: inherit;
  border: inherit;
  transform: rotate(45deg);
}

#nt-tip[data-placement="top"]::before {
  bottom: -6px;
  left: calc(50% - 5px);
  border-top: none;
  border-left: none;
}

#nt-tip[data-placement="bottom"]::before {
  top: -6px;
  left: calc(50% - 5px);
  border-bottom: none;
  border-right: none;
}

#nt-tip[data-placement="left"]::before {
  right: -6px;
  top: calc(50% - 5px);
  border-bottom: none;
  border-left: none;
}

#nt-tip[data-placement="right"]::before {
  left: -6px;
  top: calc(50% - 5px);
  border-top: none;
  border-right: none;
}

@keyframes nt-tip-in {
  from {
    opacity: 0;
    transform: translateY(3px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Triggers that wrap static text show a dotted underline on hover/focus
   so the tooltip is discoverable without adding chrome. Applied with
   `class="tip-trigger"` beside `data-tip` — the attribute alone stays
   invisible for tight rows (chips, pills) where even a dotted line is
   noise. */
.tip-trigger {
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  border-radius: 2px;
}

.tip-trigger:focus-visible {
  outline: 2px solid var(--focus-ring, currentColor);
  outline-offset: 2px;
}

/* Inline "i" affordance for sections that need a visible hint (checkout,
   admin, dispatch, business — never the baseline-captured landing/order
   browse heroes). A real <button>, 24px, keyboard- and touch-ready. */
.info-dot {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  min-width: 24px;
  min-height: 24px;
  margin-left: 0.35rem;
  padding: 0;
  border-radius: 999px;
  border: 1px solid var(--paper-line, var(--line, #ddd2c3));
  background: var(--paper, #fff);
  color: var(--ink-faint, #6f6659);
  font: inherit;
  font-size: 0.75rem;
  font-weight: 800;
  font-style: normal;
  line-height: 1;
  cursor: help;
  vertical-align: 2px;
}

.info-dot:hover {
  color: var(--ink, #16130f);
  border-color: var(--ink, #16130f);
}

.info-dot:focus-visible {
  outline: 2px solid var(--focus-ring, currentColor);
  outline-offset: 2px;
  color: var(--ink, #16130f);
}

/* Keyboard-hint key cap, e.g. "Press / to search". */
kbd {
  display: inline-block;
  min-width: 1.4em;
  padding: 0.1em 0.4em;
  border-radius: 6px;
  border: 1px solid var(--paper-line, var(--line, #ddd2c3));
  border-bottom-width: 2px;
  background: var(--paper, #fff);
  color: var(--ink-muted, inherit);
  font: inherit;
  font-size: 0.78em;
  font-weight: 700;
  line-height: 1.4;
  text-align: center;
}

/* Anchor/scroll foundations: sticky top bars (3.5rem everywhere) must
   never cover a heading jumped to by a skip link or an in-page anchor. */
main :is(h1, h2, h3)[id],
main [id]:target {
  scroll-margin-top: 4.5rem;
}

@media (prefers-reduced-motion: reduce) {
  #nt-tip,
  .pop-in {
    animation: none;
  }
}

/* ── Celebration pop ────────────────────────────────────────────────────
   Level-ups, first votes, placed orders: a 200ms scale-in that reads as
   Noah cheering. Applied to elements rendered hidden (dashboard
   level-up, shortlist) so first paint — and every baseline — is
   unchanged. Scope-agnostic: opacity and transform only. */

.pop-in {
  animation: pop-in 200ms ease;
}

@keyframes pop-in {
  from {
    opacity: 0;
    transform: scale(0.97) translateY(4px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
