/* ============================================================
   pipfind.com — the static front door
   C2 PR-1. Implemented from design/app-comps/pipfind/colors_and_type.css

   TWO THINGS THIS FILE MUST NEVER ACQUIRE, both CSP-fatal:
     * an @import of fonts.googleapis.com — the token file carries one and it
       is deliberately NOT copied here. `default-src 'none'` blocks it, and the
       page would render entirely in Georgia while every test still passed.
     * a url() to any host but our own. font-src/img-src are 'self'.
   ============================================================ */

/* ---- self-hosted faces (brief §3 C3) --------------------------------------
   SIL OFL 1.1, redistributed under their original names and NOT re-subset by
   us: subsetting produces a Modified Version and both families carry Reserved
   Font Names. Each family's OFL.txt ships beside its file.
   A build check asserts every file referenced here exists and that its licence
   travels with it — without that, a missing font is a silent fallback to a system
   serif. */
@font-face {
  font-family: 'Fraunces';
  src: url('fonts/fraunces/Fraunces--latin_basic.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Fraunces';
  src: url('fonts/fraunces/Fraunces-Italic--latin_basic.woff2') format('woff2');
  font-weight: 400 600;
  font-style: italic;
  font-display: swap;
}
@font-face {
  /* Full charset, and deliberately so: the Inter project publishes no latin
     subset — only this variable build and per-weight statics. Fraunces above
     DOES publish latin subsets, which is why the two are asymmetric. Neither
     file is re-subset by us — doing so would make us a modifier under the
     licence's reserved-name terms. */
  font-family: 'Inter';
  src: url('fonts/inter/InterVariable.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

:root {
  /* palette — every ratio measured against --pip-paper (tokens v1.2) */
  --pip-paper: #F7F2EA;
  --pip-ink: #1C1614;
  --pip-oxblood: #8F2E1F;
  --pip-garnet: #A3331F;
  /* 5.20:1 (AA). NOT #7A7062, which is 4.36:1 and fails — DR-004. */
  --pip-bone-dark: #6E6457;
  --pip-bone: #A6998A;            /* NOT A TEXT COLOR — 2.69:1 */
  --pip-hair: #D4CCBD;            /* decorative dividers only — 1.43:1, exempt */
  --pip-hair-strong: #8E8171;     /* boundary of ANY interactive control — 3.41:1 */

  --bg: var(--pip-paper);
  --fg: var(--pip-ink);
  --fg-2: var(--pip-bone-dark);
  --fg-on-ink: var(--pip-paper);
  --accent: var(--pip-oxblood);
  --rule: var(--pip-hair);
  --control-edge: var(--pip-hair-strong);
  --btn-bg: var(--pip-ink);
  --btn-fg: var(--pip-paper);
  --btn-bg-hover: #2A211E;

  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
  --font-mono: ui-monospace, Menlo, monospace;

  --fs-body: 1rem;
  --fs-caption: 0.875rem;
  --fs-micro: 0.75rem;
  --lh-body: 1.5;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 14px;
  /* the brand uses NO shadows and NO gradients on content. The card's lift and
     the photo-caption scrim are the comp's own two exceptions and stop there. */

  --ease-pip: cubic-bezier(0.4, 0, 0.2, 1);
  /* The frame is 20px wider than the 300px phone, which leaves 10px of air on
     each side. That was load-bearing while a transform positioned a strip of
     frames — it absorbed any rounding before the phone's black border could be
     shaved. There is no transform now, so it is breathing room rather than
     tolerance, and it is kept because the phone should not touch its own mask. */
  --frame-w: 320px;
  --phone-min: 300px;
  --hover-fade: 160ms;
  --frame-in: 220ms;
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 400;
}

img, svg { max-width: 100%; }

a { color: inherit; }

/* Every interactive control gets a visible, non-colour-only focus ring. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
label:focus-visible {
  outline: 2px solid var(--pip-ink);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   the card — the page is one bordered sheet, as the comp draws it
   ============================================================ */
main {
  display: block;
}

.page {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-4);
}

.card {
  width: 100%;
  max-width: 1180px;
  /* `frame-in` starts the shown frame 18px to the right of its resting place.
     The viewport's own clip was deleted (it was vestigial and was clipping the
     phone), `html`/`body` set no `overflow-x`, and below ~356px the carousel has
     already shrunk to the available width — so for the 220ms of the entry
     animation the frame's right edge crossed the viewport and the page could
     scroll sideways. `clip` and not `hidden`: `hidden` would make this a scroll
     container and break the sticky masthead, and `clip` is the one overflow
     value that may pair with `visible` on the other axis without forcing it to
     `auto`. */
  overflow-x: clip;
  background: var(--pip-paper);
  border: 1px solid var(--rule);
  box-shadow: 0 1px 2px rgba(28, 22, 20, 0.04), 0 14px 36px -14px rgba(28, 22, 20, 0.13);
}

/* ---- sticky header ---- */
.masthead {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 14px var(--space-5);
  background: rgba(247, 242, 234, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--rule);
}

.masthead-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  /* It is an <a> now, so the anchor defaults have to be undone deliberately
     rather than left to inherit — a brand that underlines on hover reads as body
     copy, not as a mark. */
  text-decoration: none;
  color: inherit;
}

.masthead-brand:hover .masthead-domain {
  color: var(--fg);
}

.masthead-mark {
  width: 24px;
  height: 24px;
  object-fit: contain;
  display: block;
}

.masthead-domain {
  font-size: var(--fs-caption);
  color: var(--fg-2);
}

.masthead-actions {
  display: flex;
  align-items: center;
  gap: 18px;
}

/* ---- the two link shapes, used everywhere ---- */
.btn-solid {
  display: inline-block;
  font-family: inherit;
  font-size: 17px;
  font-weight: 500;
  color: var(--btn-fg);
  background: var(--btn-bg);
  border: 1px solid var(--btn-bg);
  border-radius: var(--radius-md);
  padding: 16px 36px;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--hover-fade) var(--ease-pip);
}
.btn-solid:hover { background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); }

.btn-outline {
  display: inline-block;
  font-family: inherit;
  font-size: 15px;
  font-weight: 500;
  color: var(--fg);
  background: none;
  border: 1px solid var(--control-edge);
  border-radius: var(--radius-md);
  padding: 15px 28px;
  text-decoration: none;
  cursor: pointer;
}
.btn-outline:hover { background: var(--pip-ink); color: var(--fg-on-ink); border-color: var(--pip-ink); }

.btn-outline-sm {
  font-size: var(--fs-caption);
  padding: 8px 16px;
}

/* the understated text link — bone-dark, hair underline, ink on hover */
.link-quiet {
  font-size: var(--fs-caption);
  color: var(--fg-2);
  text-decoration: underline;
  text-decoration-color: var(--rule);
  text-underline-offset: 4px;
}
.link-quiet:hover { color: var(--fg); }

.link-emphatic {
  font-size: 15px;
  font-weight: 500;
  color: var(--fg);
  text-decoration: underline;
  text-decoration-color: var(--control-edge);
  text-underline-offset: 5px;
}
.link-emphatic:hover { color: var(--accent); }

/* ============================================================
   hero
   ============================================================ */
.hero {
  min-height: 760px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 72px var(--space-5);
}

.hero-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 28px;
  text-align: center;
  max-width: 760px;
}

.hero-mark {
  width: 104px;
  height: 104px;
  object-fit: contain;
}

.hero-wordmark {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(84px, 13vw, 168px);
  line-height: 0.9;
  letter-spacing: -0.03em;
  margin: 0;
}

.hero-lines {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.hero-line {
  font-family: var(--font-display);
  font-size: clamp(30px, 6.4vw, 72px);
  line-height: 1.05;
  letter-spacing: -0.015em;
}

/* the locked positioning accent — line 2 only */
.hero-line-accent { color: var(--accent); }

.hero-blurb {
  font-size: 17px;
  line-height: 1.55;
  color: var(--fg);
  max-width: 520px;
  margin: var(--space-2) 0 0;
}

.hero-doors {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-top: var(--space-2);
}

.door-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
}

.hero-note {
  font-size: var(--fs-caption);
  color: var(--fg-2);
  line-height: var(--lh-body);
}

/* ============================================================
   section shells
   ============================================================ */
.section { padding: 104px var(--space-5); }
.section-closer { padding: 160px var(--space-5); }

.section-inner {
  max-width: 1100px;
  margin: 0 auto;
}

.split {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 64px;
}

.split-copy {
  flex: 1 1 420px;
  min-width: 0;
  max-width: 560px;
}

.h2-display {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(36px, 5vw, 56px);
  line-height: 1.05;
  letter-spacing: -0.01em;
  margin: 0;
}

.h2-display-centred {
  font-size: clamp(30px, 5vw, 56px);
  text-align: center;
}

.lede {
  font-size: 20px;
  line-height: 1.55;
  margin: var(--space-6) 0 0;
}

.body-lg {
  font-size: 18px;
  line-height: 1.6;
  color: var(--fg);
  margin: 20px 0 0;
}
.body-lg p { margin: 0; }

.pull {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 26px;
  line-height: 1.25;
  color: var(--accent);
  margin: 40px 0 0;
}

.section-lede {
  font-size: 17px;
  line-height: 1.55;
  color: var(--fg);
  max-width: 560px;
  margin: 22px auto 0;
  text-align: center;
}

.frames-row {
  margin-top: 56px;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: 48px;
}

/* ============================================================
   the phone frame — one component, five instances
   ============================================================ */
.phone-figure {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin: 0;
}

.phone {
  width: 300px;
  flex: 0 0 auto;
  background: var(--pip-paper);
  border: 10px solid var(--pip-ink);
  border-radius: 42px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 600px;
}

.phone-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 18px 10px;
  border-bottom: 1px solid var(--rule);
  flex: 0 0 auto;
}

.phone-head-mark {
  /* 24px is a hard floor for the mark, not a preference: the design handoff says
     "do not use it below ~24px" because the mark's counters fill in below that.
     The comp draws these six at 20px; production already reads the floor as law. */
  width: 24px;
  height: 24px;
  object-fit: contain;
}

.icon-search {
  display: block;
  color: var(--fg-2);
}

.phone-body {
  flex: 1 1 auto;
  overflow: hidden;
  padding: 16px 18px;
}
.phone-body-tight { padding: 14px 18px; }

.phone-caption {
  font-size: 12.5px;
  line-height: var(--lh-body);
  color: var(--fg-2);
  max-width: 300px;
  text-align: center;
}
.phone-caption strong { font-weight: 600; color: var(--fg); }
.phone-caption code { font-family: var(--font-mono); }

/* ---- the tab bar ---- */
.phone-nav {
  flex: 0 0 auto;
  display: flex;
  justify-content: space-around;
  align-items: center;
  padding: 11px var(--space-2) 15px;
  border-top: 1px solid var(--rule);
  background: var(--pip-paper);
}

.nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  color: var(--fg-2);
}
.nav-item-on { color: var(--fg); }

.nav-icon { display: block; }

.nav-label {
  font-size: 10.5px;
  font-weight: 400;
}
.nav-item-on .nav-label { font-weight: 600; }

/* ============================================================
   the pick screen (the moment)
   ============================================================ */
.pick-back { font-size: 13px; color: var(--fg-2); }

.pick-reason {
  margin-top: 14px;
  font-family: var(--font-display);
  font-style: italic;
  font-size: var(--fs-caption);
  color: var(--accent);
}

.pick-photo {
  margin-top: var(--space-3);
  height: 142px;
  border-radius: var(--radius-md);
  overflow: hidden;
  position: relative;
}

.pick-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pick-credit {
  position: absolute;
  left: 0;
  bottom: 0;
  right: 0;
  padding: 6px var(--space-2);
  /* 12px and weight 500, not the comp's 9.5px. The token file records this exact
     failure by name — an 11px photo credit in Bone, "a legal attribution nobody
     could read" — and 12px is the stated absolute floor of the type scale. An
     attribution that cannot be read is not an attribution. */
  font-size: var(--fs-micro);
  font-weight: var(--w-medium);
  line-height: var(--lh-micro);
  /* A FLAT scrim, not a gradient. The brand rule is no gradients, and a gradient
     also makes the contrast ratio a function of vertical position — it clears the
     floor at the bottom and fails near the top, which is precisely the kind of
     "safe on average" claim the token file's DR-004 note exists to refuse.
     #F7F2EA on rgba(28,22,20,0.72) over a mid photo clears 6.4:1. */
  background: rgba(28, 22, 20, 0.72);
  color: var(--pip-paper);
}

.pick-dish {
  margin-top: 14px;
  font-family: var(--font-display);
  font-size: 24px;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.pick-venue {
  margin-top: var(--space-1);
  font-size: 13px;
  color: var(--fg-2);
}

.pick-ingredients {
  font-size: var(--fs-micro);
  line-height: 1.45;
  color: var(--fg-2);
  margin: var(--space-2) 0 0;
}

.pick-quote {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 14.5px;
  line-height: 1.45;
  margin: 10px 0 0;
}

.pick-actions {
  display: flex;
  gap: 9px;
  margin-top: 20px;
}

.chip-solid {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-on-ink);
  background: var(--pip-ink);
  border: 1px solid var(--pip-ink);
  border-radius: 7px;
  padding: 11px 18px;
  white-space: nowrap;
}

.chip-outline {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg);
  border: 1px solid var(--control-edge);
  border-radius: 7px;
  padding: 11px 15px;
  white-space: nowrap;
}

/* ============================================================
   the group-planning frame (who/what/when/where/send)
   ============================================================ */
.steps {
  display: flex;
  align-items: center;
  gap: 7px;
  border-bottom: 1px solid var(--rule);
  padding-bottom: var(--space-2);
}

.step {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  padding-bottom: 7px;
  margin-bottom: -8px;
  border-bottom: 2px solid transparent;
  color: var(--fg-2);
}
.step-on { border-bottom-color: var(--pip-ink); color: var(--fg); }

.step-n {
  font-family: var(--font-body);
  font-size: 9.5px;
  margin-right: var(--space-1);
}

.step-of {
  font-size: 10px;
  color: var(--fg-2);
  margin-top: 5px;
}

.frame-h {
  margin-top: 11px;
  font-family: var(--font-display);
  font-size: 21px;
  line-height: 1.1;
}

.frame-p {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--fg-2);
  margin: 6px 0 0;
}
.frame-p-loose { margin: 10px 0 0; font-size: 11px; }
.frame-p-wide { margin: 12px 0 0; line-height: var(--lh-body); }

/* the segmented control — a pill of mutually-exclusive options */
.segmented {
  margin-top: 11px;
  display: flex;
  border: 1px solid var(--control-edge);
  border-radius: 999px;
  width: fit-content;
  max-width: 100%;
  font-size: 9.5px;
  overflow: hidden;
}
.segmented-lg { font-size: 11px; }
.segmented-md { font-size: var(--fs-micro); }

.segment {
  padding: 7px var(--space-2);
  color: var(--fg-2);
  white-space: nowrap;
}
.segment-on { background: var(--pip-ink); color: var(--fg-on-ink); }
.segmented-lg .segment { padding: 6px 14px; }
.segmented-md .segment { padding: 8px 13px; }
.segment-count { opacity: 0.62; }

/* the map: a STATIC image, not an embed (brief D1). An <iframe> would be
   blocked outright — the target CSP grants no frame-src. */
.radius-map {
  width: 100%;
  height: 160px;
  object-fit: cover;
  border: 1px solid var(--rule);
  border-radius: 2px;
  display: block;
  margin-top: 11px;
}

.radius-chips {
  margin-top: 11px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.pill {
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--fg);
  border-radius: 999px;
  padding: 6px var(--space-3);
  font-size: var(--fs-micro);
  white-space: nowrap;
}
.pill-on { border-color: var(--pip-ink); background: var(--pip-ink); color: var(--fg-on-ink); }
.pill-sm { padding: 7px 13px; font-size: 12.5px; }
.pill-ink { border-color: var(--pip-ink); }

/* ============================================================
   possibilities / pick / log / you — the carousel frames
   ============================================================ */
.tabstrip {
  display: flex;
  gap: 13px;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 9px;
  font-family: var(--font-display);
  font-size: 13px;
  white-space: nowrap;
}

.tabstrip-item { color: var(--fg-2); }
.tabstrip-item-on {
  color: var(--fg);
  border-bottom: 2px solid var(--pip-ink);
  padding-bottom: 9px;
  margin-bottom: -11px;
}
.tabstrip-count {
  font-family: var(--font-body);
  font-size: 10.5px;
}

.group-label {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: 10.5px;
  color: var(--fg-2);
  margin: 11px 0 6px;
}

.poss {
  padding: 11px 0;
  border-bottom: 1px solid var(--rule);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.poss-when { font-size: 11px; color: var(--fg-2); }

.poss-what {
  font-family: var(--font-display);
  font-size: 15px;
  line-height: 1.2;
  margin-top: 2px;
}

.poss-where {
  font-size: 11.5px;
  color: var(--fg-2);
  margin-top: 3px;
}

.poss-tag {
  flex: none;
  font-size: 10px;
  color: var(--fg-2);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 3px 7px;
  white-space: nowrap;
}

.min-0 { min-width: 0; }

/* ---- the ask screen ---- */
.ask-h {
  margin-top: 18px;
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1.1;
}

.ask-p {
  font-size: 13px;
  line-height: var(--lh-body);
  color: var(--fg-2);
  margin: 9px 0 0;
}

.ask-field {
  margin-top: 20px;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border-bottom: 1.5px solid var(--pip-ink);
  padding-bottom: var(--space-2);
}

.ask-placeholder {
  flex: 1;
  font-size: var(--fs-caption);
  color: var(--fg-2);
}

.ask-go {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--fg-on-ink);
  background: var(--pip-ink);
  border-radius: 6px;
  padding: 7px 15px;
}

.ask-chips {
  margin-top: var(--space-4);
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.ask-alt {
  margin-top: 18px;
  font-size: 12.5px;
  color: var(--fg-2);
  text-decoration: underline;
  text-decoration-color: var(--rule);
  text-underline-offset: 3px;
}

/* ---- the saved list ---- */
.saved-list {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.saved-row {
  display: flex;
  gap: var(--space-3);
  align-items: center;
}

.saved-thumb {
  width: 64px;
  flex: 0 0 64px;
  height: 56px;
  border-radius: var(--radius-md);
  overflow: hidden;
}
.saved-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.saved-dish {
  font-family: var(--font-display);
  font-size: var(--fs-body);
  line-height: 1.2;
}

.saved-venue {
  font-size: var(--fs-micro);
  color: var(--fg-2);
  margin-top: 3px;
}

.saved-more {
  margin-top: 15px;
  font-size: 11.5px;
  color: var(--fg-2);
  line-height: 1.45;
}

/* ---- the you screen ---- */
.you-h {
  font-family: var(--font-display);
  font-size: 24px;
  line-height: 1.15;
}
.you-h em { color: var(--accent); }

.you-label {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: 11px;
  color: var(--fg-2);
  margin-top: 22px;
}
.you-label-first { margin-top: 20px; }

.you-p {
  font-size: var(--fs-caption);
  line-height: var(--lh-body);
  color: var(--fg);
  margin: var(--space-2) 0 0;
}
.you-p-sm { font-size: 11.5px; color: var(--fg-2); }

.calibration {
  margin-top: 13px;
  display: flex;
  gap: 5px;
}

.calibration-step { flex: 1; }

.calibration-bar {
  height: 4px;
  border-radius: 2px;
  background: var(--pip-ink);
}
.calibration-bar-off { background: var(--rule); }

.calibration-label {
  font-size: 9.5px;
  margin-top: 6px;
  color: var(--fg-2);
  text-align: center;
}
.calibration-label-on { font-weight: 600; color: var(--fg); }
.calibration-label-todo { color: var(--control-edge); }

.you-chips {
  margin-top: 10px;
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.avoid-chips {
  margin-top: 11px;
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

/* an avoidance is never colour alone — the ring glyph carries it too */
.avoid {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 7px 13px;
  font-size: 12.5px;
  white-space: nowrap;
}
.avoid-tier1 { border-color: var(--accent); color: var(--accent); }
.avoid-glyph { display: block; flex: none; }

/* ============================================================
   the carousel — four frames, zero JavaScript (brief §5)

   Four same-named radios are a native radio group, so arrow-key navigation,
   roving focus and aria-checked all come from the platform. `:checked` on one of
   them displays exactly one frame and hides the other three; there is no strip
   and no offset to compute.

   It WAS a strip, moved by `translateX(-N * frame-width)`, and that is the part
   worth remembering: the arithmetic read correctly in the stylesheet, the
   variable was in scope, the indices were right, and it still landed between
   stops in the browser. Four rounds of review failed to find where the model and
   the rendering parted company. Displaying one frame removes the question rather
   than answering it — and removes the intermediate state the strip could be
   caught in, which is what three separate reviews reported as a broken layout.
   ============================================================ */
.carousel {
  /* Never narrower than the phone it contains. `min-width: 0` was here to let a
     flex item shrink past its content — correct for text, wrong for a fixed-size
     illustration, and it is what let this column come out at 272px. */
  flex: 1 1 var(--frame-w);
  max-width: var(--frame-w);
  min-width: var(--phone-min);
}

.carousel-viewport {
  /* NO `overflow: hidden`, and that is the point. The clip existed to crop a
     STRIP of four frames down to the one on show. Since the frames became
     `display: none`, only one is ever in the layout — there is nothing left to
     clip, and the only thing the rule could still do was cut the 300px phone
     whenever this box came out narrower than it. Which it did: left border
     present, right border gone, content running off the edge.

     Vestigial machinery is worse than no machinery. It cannot help, it is not
     read as suspicious, and it goes on doing the one harmful thing it is still
     capable of. Three rounds of this session were spent adjusting the widths
     feeding a clip that should not have survived the mechanism it served. */
  width: 100%;
}

.carousel-track {
  /* NOT a strip any more. The frames used to sit in a row and the row was moved
     by `translateX(-N * frame-width)`; with the animation gone that arithmetic
     bought nothing and was the only thing that could be — and repeatedly was —
     off by a frame. Now exactly one frame is displayed and the rest are not, so
     there is no offset to compute and nothing to land between stops.

     It also fixes an accessibility trade-off the brief had accepted as a cost:
     the three inactive frames used to stay in the accessibility tree because CSS
     could not set `aria-hidden`. `display: none` removes them from it. */
  display: block;
}

.carousel-frame {
  /* `margin: 0` is load-bearing and its absence was a real defect. This is a
     <figure>, and the UA default is `margin: 1em 40px` — so the column sat 16px
     lower than the phone beside it, and its content box was 80px narrower than
     the frame, which is what made the phone look clipped and undersized at every
     width. `.phone-figure` reset it; this one did not, and the two being the same
     element type with different styling is precisely how that went unnoticed. */
  margin: 0;
  width: 100%;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

/* Motion is back, but as an ENTRY animation on the one frame being shown — not
   as a strip being moved. The distinction is the whole point: a transform across
   four frames has an offset that can be wrong, and when it was wrong the mask sat
   between two stops and showed two half-phones. An animation that only fades and
   lifts the frame that is already displayed has no position to get wrong; its
   worst failure is that it does not run. */
@keyframes frame-in {
  from {
    opacity: 0;
    transform: translateX(18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

#tab-possibilities:checked ~ .carousel-viewport .carousel-frame-possibilities {
  display: flex;
  animation: frame-in var(--frame-in) var(--ease-pip);
}
#tab-plan:checked ~ .carousel-viewport .carousel-frame-plan {
  display: flex;
  animation: frame-in var(--frame-in) var(--ease-pip);
}
#tab-log:checked ~ .carousel-viewport .carousel-frame-log {
  display: flex;
  animation: frame-in var(--frame-in) var(--ease-pip);
}
#tab-you:checked ~ .carousel-viewport .carousel-frame-you {
  display: flex;
  animation: frame-in var(--frame-in) var(--ease-pip);
}

.carousel-controls {
  margin-top: var(--space-6);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

/* the labels are the visible controls; hit target ≥44px */
.tab-label {
  font-family: inherit;
  font-size: 13px;
  padding: var(--space-2) var(--space-3);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  color: var(--fg-2);
  font-weight: 400;
  border-bottom: 1.5px solid transparent;
}
.tab-label:hover { color: var(--fg); }

#tab-possibilities:checked ~ .carousel-controls .tab-label-possibilities,
#tab-plan:checked ~ .carousel-controls .tab-label-plan,
#tab-log:checked ~ .carousel-controls .tab-label-log,
#tab-you:checked ~ .carousel-controls .tab-label-you {
  color: var(--fg);
  font-weight: 500;
  border-bottom-color: var(--pip-ink);
}

/* the radios stay focusable — never display:none, which would remove them
   from the tab order and take the arrow keys with it */
.tab-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* PAIRED, one selector per control. The first version put the generic
   `.tab-input:focus-visible` on the left of all four, so focusing any single
   radio ringed all four labels at once — which tells a keyboard user nothing,
   and telling them which control has focus is the indicator's entire job. */
#tab-possibilities:focus-visible ~ .carousel-controls .tab-label-possibilities,
#tab-plan:focus-visible ~ .carousel-controls .tab-label-plan,
#tab-log:focus-visible ~ .carousel-controls .tab-label-log,
#tab-you:focus-visible ~ .carousel-controls .tab-label-you {
  outline: 2px solid var(--pip-ink);
  outline-offset: 3px;
}

/* ============================================================
   closer + footer
   ============================================================ */
.closer-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
  text-align: center;
}

.closer-lines {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.closer-line {
  font-family: var(--font-display);
  font-size: clamp(32px, 4vw, 48px);
  line-height: 1.05;
  letter-spacing: -0.015em;
}
.closer-line-accent { color: var(--accent); }

.site-footer {
  border-top: 1px solid var(--rule);
  padding: 40px var(--space-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  font-size: var(--fs-caption);
  color: var(--fg-2);
}

.footer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2) 28px;
}

/* one line credits all six venues (brief D5): nothing legible fits on a
   64x56 thumbnail, and the copy law wants each named. */
.footer-credit {
  font-size: var(--fs-micro);
  line-height: 1.45;
  color: var(--fg-2);
  text-align: center;
  max-width: 620px;
}

/* The map credit sits on its own line with air above it, rather than a bare <br>.
   A second <p> would have taken the footer's own 18px flex gap — too much
   separation for two credits that belong together; 8px reads as one block with a
   break in it. */
.footer-credit-map {
  display: block;
  margin-top: var(--space-2);
}

.footer-legal {
  font-size: 9px;
  line-height: 1.4;
  color: var(--fg-2);
  text-align: center;
}

/* ============================================================
   narrow viewports — the card's fixed 300px frames must not push the
   body into a horizontal scroll
   ============================================================ */
@media (max-width: 720px) {
  .page { padding: 0; }
  .card { border-left: 0; border-right: 0; box-shadow: none; }
  .section { padding: 64px var(--space-4); }
  .section-closer { padding: 96px var(--space-4); }
  .hero { min-height: 0; padding: 56px var(--space-4); }
  .split { gap: 40px; }
  .frames-row { gap: 40px; }
  /* The phone does NOT go fluid. Its interior is laid out for exactly 300px —
     segmented controls, chips and tab labels are all `white-space: nowrap`, so
     they cannot reflow — and shrinking the frame does not shrink them: it slices
     them off at the device edge, because `.phone` clips its own overflow. It is a
     picture of a fixed-size device, not a responsive component, and the fix for a
     narrow viewport is to give it room rather than to squeeze it. */
}

/* Phones narrower than ~360 CSS px are rare now (an iPhone SE is 375), but the
   card must not force a horizontal scroll on one. The section's side padding
   gives way so the 300px device frame still fits inside 320. */
@media (max-width: 359px) {
  .section,
  .section-closer,
  .hero {
    padding-left: var(--space-1);
    padding-right: var(--space-1);
  }
}

@media (prefers-reduced-motion: reduce) {
  /* The four selectors are repeated VERBATIM here rather than reset once on
     `.carousel-frame`, and that is what this comment is for. The animation is
     declared on `#tab-log:checked ~ .carousel-viewport .carousel-frame-log` —
     one id and three classes, specificity (1,3,0). A media query adds NO
     specificity, so `.carousel-frame { animation: none }` at (0,1,0) lost to it
     and this block was DEAD for the page's only animation: a reader who had
     asked their OS to reduce motion got the fade and the 18px slide anyway, on
     first paint and on every tab change. The bug arrived when the moving strip
     became a per-frame animation — the old reset targeted `.carousel-track`'s
     transition at EQUAL specificity and won on source order, so the
     replacement read as a like-for-like swap. Match the selector, or the reset
     does not exist. */
  #tab-possibilities:checked ~ .carousel-viewport .carousel-frame-possibilities,
  #tab-plan:checked ~ .carousel-viewport .carousel-frame-plan,
  #tab-log:checked ~ .carousel-viewport .carousel-frame-log,
  #tab-you:checked ~ .carousel-viewport .carousel-frame-you {
    animation: none;
  }

  .btn-solid {
    transition: none;
  }
}

/* the sprite arrows, inheriting colour from the control they sit in */
.btn-arrow,
.inline-arrow {
  display: inline-block;
  vertical-align: -0.15em;
  color: currentColor;
}
