/* partyx-guide
 *
 * Geometry benchmarked against airbnb.com/help on 2026-09-09 by computed-style
 * extraction, then translated to the PartyX dark palette. What was measured:
 *
 *   shell gutter        24 at every width (the one Airbnb constant)
 *   content container   1176 max, 24 below 744, 56 at/above
 *   reading column      632 max  (Manrope metrics match Airbnb Cereal to 0.6%,
 *                       so the pixel column transfers 1:1 = 64.8ch)
 *   rail                308 fixed, 124 gutter, appears at 1128, NOT sticky
 *   rhythm              16 inside a section, 48 between sections
 *   type ramp           32 / 22 / 18 / 16 / 14 / 12, tracking goes negative
 *                       strictly above 16, leading tightens as size grows
 *
 * DESIGN.md 199-201 claims "Inset is 24, at every width, measured on
 * airbnb.com". The measurement falsifies it: 24 is the outermost shell only.
 * The real rule is a ladder. Recorded on the tracker rather than silently
 * followed or silently broken.
 *
 * Two things measured on Airbnb are deliberately NOT copied: its 89ch reading
 * column between 744 and 1128, and its 34px desk controls. Both fail this
 * project's own rubric. Match the grid, not the mistakes.
 *
 * Token values are copied from partyx-web/packages/ui/tokens.css. Four are
 * PROPOSED additions, marked below: the canonical ramp has no 18 or 32 and no
 * tracking beyond zero, and the Airbnb relationship cannot be expressed without
 * them. They are additions, never redefinitions of a shared name.
 */

:root {
  color-scheme: dark;

  /* ---- canonical, from tokens.css ---- */
  --color-canvas: #050505;
  --color-content: #f2f2ef;
  --color-muted: #8c8c88;
  --color-muted-strong: #c5c5bf;
  --color-structure: rgb(255 255 255 / 13%);
  --color-structure-subtle: rgb(255 255 255 / 8%);
  --color-on-accent: var(--color-canvas);
  --focus-ring: color-mix(in srgb, var(--color-content) 72%, transparent);
  --shadow-skip-focus: 0 0 0 3px var(--color-canvas), 0 0 0 6px var(--focus-ring);

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;

  --radius-sm: 8px;
  --radius-md: 16px;
  --radius-pill: 9999px;

  --text-caption: 12px;
  --text-body: 14px;
  --text-emphasis: 16px;
  --text-title: 22px;
  --text-display: 36px;

  --leading-caption: 1.4;
  --leading-body: 1.45;
  --leading-title: 1.16;
  --leading-tight: 1.15;

  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;

  --control-height-sm: 36px;
  --control-height-md: 44px;
  --control-height-lg: 52px;
  --hit-target-size-md: 44px;

  --ease-airbnb: cubic-bezier(0.2, 0, 0, 1);
  --duration-fast: 100ms;

  /* ---- PROPOSED additions to tokens.css. See the tracker before reusing. ----
     The canonical ramp jumps 16 -> 22 -> 36 and has no tracking below zero.
     Airbnb's long-form ramp needs a step at 18 (block title) and one at 32
     (page title), and negative tracking strictly above 16. Without these the
     guide h1 and its own h2 are forced to the same size, which is the single
     largest hierarchy defect on the current surface. */
  --text-block: 18px;
  --text-page-title: 32px;
  --tracking-title: -0.02em;
  --tracking-display: -0.03em;

  /* ---- layout, derived from the measured ladder ---- */
  --gutter: var(--space-6);
  --shell-width: 1176px;
  --read-width: 632px;
  --rail-width: 308px;
  --rail-gutter: 124px;
  --row-gap: var(--space-4);
  --section-gap: 48px;

  --font-sans: Manrope, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

/* Self-hosted so the first paint owes nothing to a third party, and so the
   page can ship a CSP that forbids every origin but its own. Manrope v20
   latin subset, the same face partyx-web renders. */
@font-face {
  font-family: Manrope;
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/manrope-v20-latin-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--color-canvas);
  color: var(--color-content);
  font-family: var(--font-sans);
  font-size: var(--text-emphasis);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, p, dl, dd, figure { margin: 0; }
ul, ol { margin: 0; padding: 0; }
a { color: inherit; }
img, svg { display: block; max-width: 100%; }

/* One focus treatment for the whole surface. The previous stylesheet styled the
   wordmark and nothing else, so every link in the body, the lists and the
   footer fell back to the user agent default. */
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Fixed, not absolute: an absolutely positioned skip link paints off-screen
   when focus lands on it partway down a long page. */
.px-skip {
  position: fixed;
  inset-block-start: var(--space-4);
  inset-inline-start: var(--space-4);
  z-index: 10;
  display: inline-flex;
  align-items: center;
  min-height: var(--control-height-md);
  padding: 0 var(--space-4);
  color: var(--color-on-accent);
  background: var(--color-content);
  border-radius: var(--radius-sm);
  font-size: var(--text-body);
  font-weight: var(--font-weight-semibold);
  transform: translateY(calc(-100% - var(--space-8)));
}
.px-skip:focus-visible {
  transform: none;
  box-shadow: var(--shadow-skip-focus);
}

/* ── One shell. Header, content and footer share a single optical axis; the
      three-container drift measured on two of the three design boards is what
      this single class exists to prevent. ─────────────────────────────────── */
.px-shell {
  width: 100%;
  max-width: var(--shell-width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ── Header ───────────────────────────────────────────────────────────────── */
.px-header {
  padding-block: var(--space-3);
  padding-block-start: calc(var(--space-3) + env(safe-area-inset-top));
  border-block-end: 1px solid var(--color-structure-subtle);
}
.px-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: var(--hit-target-size-md);
}
.px-brand {
  display: inline-flex;
  align-items: center;
  min-height: var(--hit-target-size-md);
  font-size: var(--text-emphasis);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-title);
  text-decoration: none;
}

/* ── Record: one reading column. No rail; a city is one page ───────── */
.px-main { flex: 1 1 auto; }
.px-record {
  padding-block: var(--space-8) 64px;
}
.px-read { max-width: var(--read-width); }

/* ── Hero: question, answer, provenance, verb ─────────────────────────────── */
.px-hero { display: grid; gap: var(--space-4); }
.px-hero h1 {
  font-size: var(--text-page-title);
  font-weight: var(--font-weight-semibold);
  line-height: 1.125;
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
}
.px-hero__lede {
  font-size: var(--text-title);
  font-weight: var(--font-weight-normal);
  line-height: 1.32;
  letter-spacing: var(--tracking-title);
  color: var(--color-muted-strong);
}
.px-hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  color: var(--color-muted);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
}
.px-hero__meta > * + *::before {
  content: "·";
  margin-inline-end: var(--space-3);
}

/* The one primary verb. This surface answers, then points at tonight; on the
   page it replaces was a 12px underlined caption. */
.px-verb {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 48px;
  padding-inline: var(--space-6);
  margin-block-start: var(--space-2);
  color: var(--color-on-accent);
  background: var(--color-content);
  border-radius: var(--radius-sm);
  font-size: var(--text-emphasis);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
  justify-self: start;
  transition: transform var(--duration-fast) var(--ease-airbnb);
}
.px-verb:hover { transform: translateY(-1px); }
.px-verb:active { transform: none; }
.px-verb__mark { font-size: var(--text-body); }

/* Live strip under the verb. Inventory, not prose: short cache, own KV. */
.px-strip {
  display: grid;
  gap: var(--space-3);
  justify-self: stretch;
  margin-block-start: var(--space-2);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--color-structure-subtle);
}
.px-strip__count {
  font-size: var(--text-body);
  font-weight: var(--font-weight-medium);
  color: var(--color-muted-strong);
}
.px-strip__nights { list-style: none; display: grid; gap: var(--space-2); }
.px-strip__night {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  align-items: center;
  min-height: var(--hit-target-size-md);
  color: inherit;
  text-decoration: none;
}
.px-strip__night:has(.px-strip__poster) { grid-template-columns: 44px 1fr; }
.px-strip__night:hover .px-strip__title {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.px-strip__poster {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--color-structure-subtle);
}
.px-strip__copy { display: grid; gap: 2px; min-width: 0; }
.px-strip__title {
  font-size: var(--text-body);
  font-weight: var(--font-weight-medium);
  line-height: 1.25;
}
.px-strip__meta {
  color: var(--color-muted);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
}
/* #tonight when no night survives the window: a link to the app's Tonight
   page, never a claim that nothing is on. */
.px-strip__link {
  color: var(--color-muted-strong);
  font-size: var(--text-body);
  line-height: var(--leading-body);
}
.px-strip__link a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: inherit;
  font-weight: var(--font-weight-medium);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ── Prose ────────────────────────────────────────────────────────────────── */
.px-prose {
  margin-block-start: var(--section-gap);
  font-size: var(--text-emphasis);
  line-height: 1.5;
}
.px-prose > * + * { margin-block-start: var(--row-gap); }
.px-prose h2 {
  margin-block-start: var(--section-gap);
  font-size: var(--text-title);
  font-weight: var(--font-weight-semibold);
  line-height: 1.18;
  letter-spacing: var(--tracking-title);
  scroll-margin-block-start: var(--space-8);
}
.px-prose h3 {
  margin-block-start: var(--space-8);
  font-size: var(--text-block);
  font-weight: var(--font-weight-semibold);
  line-height: 1.33;
  letter-spacing: -0.01em;
  scroll-margin-block-start: var(--space-8);
}
.px-prose ul, .px-prose ol { padding-inline-start: var(--space-5); }
.px-prose li + li { margin-block-start: var(--space-2); }
.px-prose li::marker { color: var(--color-muted); }
.px-prose blockquote {
  padding-inline-start: var(--space-4);
  border-inline-start: 2px solid var(--color-structure);
  color: var(--color-muted-strong);
}
.px-prose strong { font-weight: var(--font-weight-semibold); }
/* Body weight 400, link weight 500. On a dark canvas the weight step is what
   makes a link findable when scanning, more than the underline is. */
.px-prose a {
  font-weight: var(--font-weight-medium);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--color-muted);
}
.px-prose a:hover { text-decoration-color: currentColor; }

/* ── Section, used by FAQ, related, hub lists ─────────────────────────────── */
.px-section { margin-block-start: var(--section-gap); }
.px-section > h2 {
  margin-block-end: var(--space-4);
  font-size: var(--text-block);
  font-weight: var(--font-weight-semibold);
  line-height: 1.33;
  letter-spacing: -0.01em;
}

/* ── City page blocks. One section per typed block (src/blocks.ts), each an
      anchor the retired article URLs 301 to. A block is a heading, a few
      lines, and its sources. ──────────────────────────────────────────────── */
.px-block {
  margin-block-start: var(--section-gap);
  scroll-margin-block-start: var(--space-8);
}
.px-block > h2 {
  margin-block-end: var(--space-4);
  font-size: var(--text-title);
  font-weight: var(--font-weight-semibold);
  line-height: 1.18;
  letter-spacing: var(--tracking-title);
}
.px-block > .px-prose { margin-block-start: 0; }
.px-block__data {
  margin-block-end: var(--space-3);
  font-size: var(--text-body);
  font-weight: var(--font-weight-medium);
  color: var(--color-content);
}
.px-block__sources { margin-block-start: var(--space-4); }
.px-block__sources .px-sources { margin-block-start: var(--space-1); }
.px-sources__label {
  color: var(--color-muted);
  font-size: var(--text-caption);
  line-height: var(--leading-caption);
}
.px-hero.px-hero { scroll-margin-block-start: var(--space-8); }
.px-answer { margin-block-start: 0; }
.px-answer > p:first-child {
  font-size: var(--text-title);
  line-height: 1.32;
  letter-spacing: var(--tracking-title);
  color: var(--color-muted-strong);
}
/* #tonight is a block now, not a strip under the verb: no rule above it. */
.px-block.px-strip {
  margin-block-start: var(--section-gap);
  padding-block-start: 0;
  border-block-start: 0;
}

/* ── Rows. One anatomy for FAQ answers, related guides, hub cards and the
      unanswered questions on a city nobody has walked. The padding lives on
      the row, not on a link inside it, because an unwalked city's rows have
      no link and the previous stylesheet rendered them with no padding at
      all. ──────────────────────────────────────────────────────────────────── */
.px-rows { list-style: none; }
.px-rows > li { border-block-start: 1px solid var(--color-structure-subtle); }
.px-rows > li:last-child { border-block-end: 1px solid var(--color-structure-subtle); }
.px-row {
  display: grid;
  gap: var(--space-1);
  padding-block: var(--space-6);
  text-decoration: none;
  color: inherit;
}
a.px-row { transition: opacity var(--duration-fast) var(--ease-airbnb); }
a.px-row:hover .px-row__title { text-decoration: underline; text-underline-offset: 3px; }
.px-row__title {
  font-size: var(--text-emphasis);
  font-weight: var(--font-weight-medium);
  line-height: 1.25;
}
.px-row__meta {
  color: var(--color-muted);
  font-size: var(--text-body);
  line-height: var(--leading-body);
}
.px-row__note {
  color: var(--color-muted);
  font-size: var(--text-caption);
}

/* FAQ uses the same row rhythm in a definition list, because it is a list of
   questions and answers and not a set of cards. */
.px-faq { list-style: none; }
.px-faq > div { border-block-start: 1px solid var(--color-structure-subtle); padding-block: var(--space-6); }
.px-faq > div:last-child { border-block-end: 1px solid var(--color-structure-subtle); }
.px-faq dt {
  font-size: var(--text-emphasis);
  font-weight: var(--font-weight-medium);
  line-height: 1.25;
}
.px-faq dd {
  margin-block-start: var(--space-2);
  color: var(--color-muted-strong);
  font-size: var(--text-emphasis);
  line-height: 1.5;
}

/* ── Empty, for a city nobody has walked ──────────────────────────────────── */
.px-empty__note a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  font-weight: var(--font-weight-medium);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.px-empty__note {
  margin-block-start: var(--space-4);
  color: var(--color-muted);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  max-width: var(--read-width);
}

/* Named sources on a researched (not walked) guide. Markers off, role=list
   kept, same rule as every other chrome list on this surface. */
.px-sources {
  list-style: none;
  display: grid;
  gap: var(--space-2);
  margin-block-start: var(--space-4);
}
.px-sources a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: var(--color-muted-strong);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  word-break: break-all;
}

/* ── Footer ───────────────────────────────────────────────────────────────── */
.px-footer {
  margin-block-start: 64px;
  padding-block: var(--space-8);
  padding-block-end: calc(var(--space-8) + env(safe-area-inset-bottom));
  border-block-start: 1px solid var(--color-structure-subtle);
}
.px-footer__inner { display: grid; gap: var(--space-8); }
.px-footer__brand { display: grid; gap: var(--space-1); align-content: start; }
.px-footer__brand p { color: var(--color-muted); font-size: var(--text-body); }
.px-footer__cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-6) var(--space-4);
}
.px-footer__col h2 {
  margin-block-end: var(--space-2);
  font-size: var(--text-body);
  font-weight: var(--font-weight-semibold);
}
.px-footer__col ul { list-style: none; display: grid; }
.px-footer__col a {
  display: inline-flex;
  align-items: center;
  min-height: var(--control-height-sm);
  color: var(--color-muted);
  font-size: var(--text-body);
  text-decoration: none;
}
.px-footer__col a:hover { color: var(--color-content); }
.px-footer__legal {
  display: grid;
  gap: var(--space-3);
  padding-block-start: var(--space-6);
  border-block-start: 1px solid var(--color-structure-subtle);
  color: var(--color-muted);
  font-size: var(--text-caption);
}
.px-footer__legal ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  list-style: none;
}
/* WCAG 2.5.8 wants 24x24 for a target that is not inline in a sentence. These
   sit in a list, so the inline exception does not cover them. */
.px-footer__legal a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: var(--color-muted);
  text-decoration: none;
}
.px-footer__legal a:hover { color: var(--color-content); text-decoration: underline; }

/* ── 744: the container opens up. Airbnb's first breakpoint. ──────────────── */
@media (min-width: 744px) {
  :root { --gutter: 56px; }
  .px-footer__inner {
    grid-template-columns: minmax(200px, 0.7fr) minmax(0, 1.6fr);
  }
  .px-footer__cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .px-footer__legal {
    grid-column: 1 / -1;
    grid-template-columns: auto 1fr;
    align-items: center;
    justify-content: space-between;
  }
  .px-footer__legal ul { justify-self: end; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
