/* Ad-supported utility page. Priorities, in order:
   1. Answer visible instantly, no layout shift
   2. Ad slots with reserved height so CWV stays green
   3. Readable on a phone in a kitchen, one-handed */

/* Self-hosted so there is no render-blocking request to a third party on a
   site where Core Web Vitals are revenue. Licence in OFL-BricolageGrotesque.txt
   and served at /OFL-BricolageGrotesque.txt, as the OFL requires.

   `optional`, not `swap`. Headings here are large and some wrap, so a late
   swap can change a heading's line count and shift everything below it,
   which is the one thing this stylesheet exists to prevent. `optional` never
   swaps: the font is used if it arrived in time, and otherwise that one page
   view renders in system-ui and never reflows. The <link rel="preload"> in
   the template is what makes "in time" the usual case, and the font is cached
   for every page after the first.

   A metric-adjusted fallback was tried instead and made things worse.
   Measured against the real face, plain system-ui set these headings 2.7%
   narrow; the tuned fallback set them 9.3% narrow, because size-adjust was
   pulling the wrong way and local() resolved to a different face per
   platform. One override cannot match SF Pro, Segoe UI and Roboto at once. */
@font-face {
  font-family: 'Bricolage Grotesque';
  src: url('/bricolage-grotesque-latin.woff2') format('woff2');
  font-weight: 600 800;
  font-display: optional;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2122, U+2212;
}

:root {
  --ink: #1f1c18;
  --muted: #6d665c;
  --line: #e6dfd4;
  --hair: #f0eae1;
  --bg: #f9f6f1;
  --card: #ffffff;
  --ok: #1c6b3c;
  --ok-bg: #e8f4ec;
  --mid: #8a5a00;
  --mid-bg: #fdf1dc;
  --bad: #9b2226;
  --bad-bg: #fbeaea;
  --max: 36rem;
  --display: 'Bricolage Grotesque', system-ui, sans-serif;
  --body: system-ui, -apple-system, 'Segoe UI', sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #ece7df; --muted: #a49c90; --line: #363029; --hair: #2a251f;
    --bg: #17140f; --card: #1e1a15;
    --ok: #7fd4a0; --ok-bg: #16301f; --mid: #e8b35c; --mid-bg: #302410;
    --bad: #f08e91; --bad-bg: #2f1618;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 18px/1.62 var(--body);
  -webkit-text-size-adjust: 100%;
}

main { max-width: var(--max); margin: 0 auto; padding: 0 1.15rem 3rem; }
/* The homepage drops the brand header, so its own top spacing has to stand in
   for the header's. */
main.home { padding-top: 1.5rem; }

header.site, footer.site {
  max-width: var(--max);
  margin: 0 auto;
  padding: 1.15rem 1.15rem .6rem;
}
footer.site {
  border-top: 1px solid var(--line);
  margin-top: 3rem;
  padding: 1.15rem;
  font-size: .9rem;
  color: var(--muted);
}
.brand {
  font: 800 1rem/1 var(--display);
  letter-spacing: -.02em;
  text-decoration: none;
  color: var(--ink);
}

h1 {
  font: 700 2.3rem/1.1 var(--display);
  letter-spacing: -.03em;
  margin: 1.1rem 0;
  text-wrap: pretty;
}
h2 { font: 700 1.3rem/1.2 var(--display); letter-spacing: -.02em; margin: 2.2rem 0 .35rem; }
h3 { font: 700 1.08rem/1.3 var(--display); margin: 0 0 .35rem; }
/* Route names sit under the card's own h2, so they are h3. An h4 there skips
   a level, which is a real screen-reader defect and the one thing Lighthouse
   found on this page. Styled small deliberately; the level is about structure,
   not size. */
.alt h3 { font: 650 .95rem/1.4 var(--body); margin: 0 0 .2rem; letter-spacing: 0; }
a { color: inherit; }
p { text-wrap: pretty; }

/* The answer block. Everything else on the page is optional reading. */
.answer {
  display: flex;
  gap: 1.1rem;
  align-items: flex-start;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 1.3rem 1.4rem;
}
.answer-icon {
  flex-shrink: 0;
  width: 56px; height: 56px;
  border-radius: 999px;
  display: grid;
  place-items: center;
}
.answer-icon svg { width: 28px; height: 28px; }
.answer .verdict {
  font: 700 1.85rem/1.1 var(--display);
  letter-spacing: -.025em;
  margin: .1rem 0 .45rem;
}
.answer .short { margin: 0; font-size: 1.02rem; line-height: 1.5; }

.v-yes .answer-icon, .v-usually-yes .answer-icon { background: var(--ok-bg); }
.v-yes .verdict, .v-usually-yes .verdict { color: var(--ok); }
.v-conditional .answer-icon { background: var(--mid-bg); }
.v-conditional .verdict { color: var(--mid); }
.v-usually-no .answer-icon, .v-no .answer-icon { background: var(--bad-bg); }
.v-usually-no .verdict, .v-no .verdict { color: var(--bad); }

/* The three question layers, as one continuous rail split into per-layer
   segments. The fourth layer, alternatives, is not a question and renders as a
   card below rather than on this rail.
   Each layer owns its own color, because a gradient between two similar tones
   says nothing and most items have two adjacent layers at the same status.
   Padding rather than margin between layers, so the rail stays unbroken. */
.layers { margin-top: .4rem; }
.layer {
  position: relative;
  padding: 0 0 1.6rem 1.6rem;
}
.layer:last-child { padding-bottom: .25rem; }

/* The rail is a pseudo-element rather than a border-left so its top edge can
   start at the first dot's center. As a border it began at the layer's top,
   and a circle cannot cover a 3px rectangle at its own apex, so the rail
   poked out either side of the first dot. */
.layer::after {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--muted);
}
.layer:first-child::after { top: 10px; }

.layer::before {
  content: '';
  position: absolute;
  left: -9px; top: 0;
  width: 21px; height: 21px;
  border-radius: 999px;
  background: var(--muted);
  border: 4px solid var(--bg);
}
.layer.ok::after,  .layer.ok::before  { background: var(--ok); }
.layer.mid::after, .layer.mid::before { background: var(--mid); }
.layer.bad::after, .layer.bad::before { background: var(--bad); }

.eyebrow {
  font: 700 .72rem/1 var(--display);
  letter-spacing: .1em;
  text-transform: uppercase;
  margin: 0 0 .3rem;
  color: var(--muted);
}
.layer.ok  .eyebrow { color: var(--ok); }
.layer.mid .eyebrow { color: var(--mid); }
.layer.bad .eyebrow { color: var(--bad); }

.blurb { color: var(--muted); font-size: .95rem; margin: 0 0 .55rem; }
.src { font-size: .85rem; color: var(--muted); margin: .5rem 0 0; }
.caveat { font-size: .88rem; color: var(--muted); margin: .15rem 0 0; }

/* Practical sections sit in cards so they read as things to act on rather
   than more prose. */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 1.3rem 1.4rem;
  margin-top: 2rem;
}
.card > h2 { margin: 0 0 .8rem; font-size: 1.15rem; }
.card ul { margin: 0; padding-left: 1.05rem; }
.card ul li { margin: 0 0 .35rem; }
.card ul li:last-child { margin-bottom: 0; }

.routes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .9rem 1.25rem; }
.alt { margin: 0; }
.alt p { margin: 0; color: var(--muted); font-size: .89rem; line-height: 1.45; }

ul.checks, ul.mistakes { padding-left: 1.05rem; }
ul.checks li, ul.mistakes li { margin: .35rem 0; }

.verified {
  margin-top: 2.2rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
  font-size: .88rem;
  color: var(--muted);
}
.verified p { margin: 0; }

.related { margin-top: 1.6rem; display: flex; gap: .55rem; flex-wrap: wrap; align-items: center; }
.related h2 {
  font: 700 .72rem/1 var(--display);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 .2rem 0 0;
}
.related a {
  font-size: .9rem;
  padding: .38rem .8rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 999px;
  text-decoration: none;
}

/* Homepage. The list is the product, so it gets the space; the filter exists
   because 13 items is scannable and 300 is not. */
.finder { margin: 1.4rem 0 .2rem; }
.filter {
  width: 100%;
  font: 1rem/1.4 var(--body);
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: .8rem 1rem;
  -webkit-appearance: none;
  appearance: none;
}
.filter::placeholder { color: var(--muted); }
.filter:focus-visible { outline: 2px solid var(--ok); outline-offset: 2px; }
.count { font-size: .82rem; color: var(--muted); margin: .5rem 0 0; }
.nomatch { color: var(--muted); font-size: .95rem; margin: 1.2rem 0 0; }

/* Screen-reader-only label: the placeholder is a hint, not a name. */
.vh {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* Sits above the list, so it has to be small. Two sentences naming the three
   things that can disagree, which is what the tag on each row resolves.
   The left edge is a 3px accent in --mid, quoting the status rail on the item
   pages: same width, same color the rail uses for "it depends". The kicker
   takes that color too, so the one word the box is really there to deliver,
   disagree, is set in the site's own color for disagreement.
   Corners are near-square on the accent side so the bar reads as a straight
   rail rather than a curved sliver. */
.how {
  margin: 1.1rem 0 .3rem;
  padding: .9rem 1.15rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-left: 3px solid var(--mid);
  border-radius: 4px 12px 12px 4px;
}
.how p { margin: 0; font-size: .95rem; line-height: 1.5; color: var(--muted); }
/* The three nouns carry the meaning, so they get the ink while the connective
   tissue stays muted. This is what the numbered list used to do, without
   numbering a sequence the page never refers to again. */
.how b { font-weight: 600; color: var(--ink); }
.how .how-kicker {
  margin-top: .45rem;
  color: var(--mid);
  font-weight: 600;
}
ul.index li[hidden] { display: none; }
ul.index { list-style: none; padding: 0; margin: 1.2rem 0 0; }
ul.index li {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  padding: .85rem 0; border-bottom: 1px solid var(--hair);
}
ul.index a { text-decoration: none; font-weight: 600; }
.lede { color: var(--muted); margin-top: -.4rem; }

.pill {
  font: 700 .68rem/1 var(--display);
  letter-spacing: .08em; text-transform: uppercase;
  padding: .3rem .55rem; border-radius: 999px;
}
.pill.ok  { background: var(--ok-bg);  color: var(--ok); }
.pill.mid { background: var(--mid-bg); color: var(--mid); }
.pill.bad { background: var(--bad-bg); color: var(--bad); }

.prose h2 { font-size: 1.2rem; }

/* Reserved height stops cumulative layout shift when the ad loads.
   Never let an ad slot size itself from its content. */
.ad {
  min-height: 280px;
  margin: 2rem 0;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--hair);
}
@media (min-width: 700px) { .ad { min-height: 250px; } }
.ad-note {
  font: 700 .7rem/1 var(--display);
  letter-spacing: .12em; text-transform: uppercase; color: var(--muted);
}

/* Phone. The rail costs less of a narrow column, and the practical cards
   stack rather than sitting two-up. */
@media (max-width: 34rem) {
  body { font-size: 17px; }
  h1 { font-size: 1.75rem; margin: .8rem 0 1rem; }
  .answer { flex-direction: column; gap: .8rem; padding: 1.15rem; }
  .answer-icon { width: 44px; height: 44px; }
  .answer-icon svg { width: 22px; height: 22px; }
  .answer .verdict { font-size: 1.6rem; margin: 0 0 .4rem; }
  .layer { padding-left: 1.35rem; padding-bottom: 1.4rem; }
  .layer::before { left: -7.5px; top: 0; width: 18px; height: 18px; border-width: 3px; }
  .layer:first-child::after { top: 9px; }
  .routes { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .routes .alt + .alt { border-top: 1px solid var(--hair); margin-top: .8rem; padding-top: .8rem; }
  .related a { padding: .65rem 1rem; }
}
