/* Fernweh.
 *
 * Type and layout follow the editorial travel style the project is modelled
 * on: a single grotesque used for everything, headings set enormous at
 * regular weight with very tight leading, near-black on near-white, and all
 * colour carried by photography rather than by the palette.
 *
 * Archivo stands in for the reference site's licensed face. It is OFL, so it
 * can ship in a public repository, and it matches the brief: squarish
 * grotesque, true italics, variable width and weight.
 */

@font-face {
  font-family: "Archivo";
  src: url("/fonts/Archivo.woff2") format("woff2");
  font-weight: 100 900; font-stretch: 62% 125%; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("/fonts/Archivo-Italic.woff2") format("woff2");
  font-weight: 100 900; font-stretch: 62% 125%; font-style: italic; font-display: swap;
}

:root {
  --paper: #f1f1f1;
  --ink: #010101;
  /* Secondary and tertiary ink are set by contrast against the paper rather
     than by eye. On #f1f1f1 the previous .6 and .4 alphas measured about
     5.3:1 and 3.0:1; body copy at 3:1 is unreadable, so both are darker. */
  --ink-60: rgba(1, 1, 1, .74);
  --ink-40: rgba(1, 1, 1, .58);
  --ink-12: rgba(1, 1, 1, .16);
  --paper-80: rgba(241, 241, 241, .8);
  --card: #e8e8e6;
  --accent: #010101;
  --good: #1f6f45;
  --warn: #8a6a12;
  --bad: #a3341f;
  --r: 6px;
  --gutter: clamp(18px, 3.2vw, 46px);
  --shell: 1560px;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 17px;
  line-height: 1.45;
  letter-spacing: .01em;
  font-stretch: 88%;
  overflow-x: hidden;
}
.shell { max-width: var(--shell); margin: 0 auto; padding: 0 var(--gutter); }
.hidden { display: none !important; }
img { max-width: 100%; display: block; }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- display type ---------- */
/* Headings are set in em so a section can scale its whole type block by
   changing one font-size, which is how the reference site is built. */
.d1, .d2, .d3 {
  margin: 0;
  font-weight: 500;
  font-stretch: 82%;
  line-height: .86;
  letter-spacing: -.015em;
  text-wrap: balance;
}
.d1 { font-size: clamp(3.4rem, 8.6vw, 9.5rem); }
.d2 { font-size: clamp(2.6rem, 6.4vw, 6.6rem); }
.d3 { font-size: clamp(1.7rem, 3.2vw, 3.1rem); line-height: .95; }
.d1 em, .d2 em, .d3 em { font-style: italic; }

.label {
  font-size: 11px; letter-spacing: .17em; text-transform: uppercase;
  font-weight: 600; font-stretch: 100%;
}
.lede { font-size: clamp(17px, 1.35vw, 20px); line-height: 1.5; max-width: 52ch; }
.muted { color: var(--ink-60); }

/* ---------- header ---------- */
.top {
  position: fixed; inset: 0 0 auto; z-index: 60;
  padding: 18px var(--gutter);
  display: flex; align-items: flex-start; gap: 40px;
  color: #fff; text-shadow: 0 1px 14px rgba(0, 0, 0, .35);
}
/* Over the pale sections below the hero the header has to flip to ink. */
body.scrolled .top { color: var(--ink); text-shadow: none; background: var(--paper-80); backdrop-filter: blur(10px); }
.top a { text-decoration: none; }
.wordmark { font-size: 13px; line-height: 1.15; letter-spacing: .12em; font-weight: 600; text-transform: uppercase; }
.top nav { display: flex; gap: 34px; }
.top nav a { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; opacity: .85; }
.top nav a:hover, .top nav a[aria-current="page"] { opacity: 1; text-decoration: underline; text-underline-offset: 3px; }
.top .right { margin-left: auto; display: flex; gap: 26px; }

/* ---------- portal: pinned door sequence ----------
   The container is tall; the stage inside it is sticky. Scroll distance
   through the container is the timeline: the door opens, then the scene
   rushes past the camera and the products are already there behind it. */
/* Height is the sequence's duration, and it is deliberately short. At 200vh
   the door finished opening with most of a screen of empty scrolling still
   between it and the products; one extra viewport of travel is enough for the
   whole sequence, so the list arrives as the door does. */
.portal { position: relative; height: 150vh; }
/* The stage sits on paper, so as the scene fades out at the end of the fly
   through the viewer lands on the same surface the products are laid out on
   and there is no seam between the sequence and the page. */
.portal-stage {
  position: sticky; top: 0; height: 100vh; min-height: 560px;
  overflow: hidden; background: var(--paper);
}
.scene {
  position: absolute; inset: 0;
  transform: scale(var(--zoom, 1));
  transform-origin: 50% 54%;
  opacity: var(--scene-opacity, 1);
  will-change: transform, opacity;
}
/* ---------- product rows ----------
   Alternating sides, with the copy on a panel beside the photograph rather
   than burned into it, so the text sits on paper at full contrast. */
.prow {
  display: grid; grid-template-columns: 1.15fr .85fr;
  gap: clamp(18px, 3vw, 52px); align-items: center;
  margin-bottom: clamp(40px, 7vh, 96px);
}
.prow.reverse { grid-template-columns: .85fr 1.15fr; }
.prow.reverse .prow-media { order: 2; }
.prow.reverse .prow-panel { order: 1; }
.prow-media { overflow: hidden; border-radius: var(--r); background: var(--card); }
.prow-media img {
  width: 100%; height: clamp(260px, 46vh, 470px); object-fit: cover;
  transition: transform 1s var(--ease);
}
.prow:hover .prow-media img { transform: scale(1.04); }
.prow-panel { padding: clamp(16px, 2vw, 30px) 0; }
.prow-panel .label { color: var(--ink-40); margin: 0 0 14px; }
.prow-panel p { color: var(--ink-60); margin: 16px 0 22px; max-width: 48ch; font-size: 17px; line-height: 1.55; }

/* The panel fades and rises into place as its row is reached. */
.reveal-on-scroll .prow-panel,
.reveal-on-scroll .prow-media {
  opacity: 0; transform: translateY(22px);
  transition: opacity .75s var(--ease), transform .75s var(--ease);
}
.reveal-on-scroll .prow-panel { transition-delay: .1s; }
.reveal-on-scroll.in .prow-panel,
.reveal-on-scroll.in .prow-media { opacity: 1; transform: none; }

.hero {
  position: relative; height: 100vh; min-height: 620px;
  overflow: hidden; background: #9dbdd8;
}
.hero-bg {
  position: absolute; inset: 0;
  background: url("/img/sky.jpg") center 62% / cover no-repeat;
}
/* Headline upper-left, supporting copy lower-left, door centred between the
   two. Type never crosses the door. */
.hero-top {
  position: absolute; left: 0; right: 0; top: clamp(76px, 11vh, 128px); z-index: 3;
  padding: 0 var(--gutter); max-width: var(--shell); margin: 0 auto;
  color: #fff; text-shadow: 0 2px 34px rgba(0, 0, 0, .22);
  pointer-events: none;
}
.hero-top .label { margin: 0 0 14px; opacity: .9; }
.hero-top .d1 { max-width: 11ch; }
.hero-copy {
  position: absolute; inset: auto 0 0; z-index: 3;
  padding: 0 var(--gutter) clamp(46px, 8vh, 86px);
  max-width: var(--shell); margin: 0 auto;
  color: #fff; text-shadow: 0 1px 24px rgba(0, 0, 0, .3);
}
.hero-copy .lede { margin: 0 0 20px; color: rgba(255, 255, 255, .94); max-width: 38ch; }
.hero-copy .btn { text-shadow: none; }

/* The door. A real element with 3D transforms rather than a rendered
   sequence: it can be driven directly from scroll progress, needs no assets,
   and stays sharp at any size. */
.door-stage {
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
  perspective: 1700px; perspective-origin: 50% 46%;
}
/* Sized and dropped so the door stands on the waterline of the photograph
   rather than floating in the sky. */
.door-frame {
  position: relative;
  width: clamp(150px, 15vw, 236px);
  height: clamp(250px, 34vh, 400px);
  transform: translateY(11vh);
}
/* What lies beyond, revealed as the panel swings away. */
.door-inner {
  position: absolute; inset: 0;
  background: url("/img/sea.jpg") center / cover no-repeat;
  box-shadow: inset 0 0 60px rgba(0, 0, 0, .35);
}
.door-panel {
  position: absolute; inset: 0;
  transform-origin: left center;
  transform: rotateY(calc(var(--door, 0) * -78deg));
  transition: transform .1s linear;
  background: linear-gradient(105deg, #fbfbfa 0%, #eceae6 52%, #dedbd5 100%);
  box-shadow: 2px 0 40px rgba(0, 0, 0, .22);
  backface-visibility: hidden;
}
.door-panel::before,
.door-panel::after {
  content: ""; position: absolute; left: 12%; right: 12%;
  border: 1.5px solid rgba(0, 0, 0, .11); border-radius: 2px;
}
.door-panel::before { top: 7%; height: 44%; border-radius: 50% 50% 3px 3px / 26% 26% 3px 3px; }
.door-panel::after { top: 57%; height: 34%; }
.door-knob {
  position: absolute; right: 9%; top: 51%; width: 13px; height: 13px;
  border-radius: 50%; background: #b08d5a; box-shadow: 0 1px 3px rgba(0,0,0,.4);
}
.door-frame::after {
  content: ""; position: absolute; inset: -10px -12px -10px -12px;
  border: 10px solid #f7f7f5; border-radius: 3px; pointer-events: none;
  box-shadow: 0 30px 60px rgba(0, 0, 0, .18);
}
.scroll-cue {
  position: absolute; left: var(--gutter); bottom: 22px; z-index: 4;
  color: #fff; display: flex; align-items: center; gap: 9px;
}

/* ---------- product page hero ---------- */
/* A shallow photographic band rather than a full screen: these pages exist
   to be used, so the working part should be close to the fold. */
.page-hero { position: relative; height: clamp(300px, 46vh, 460px); overflow: hidden; background: #24303a; }
.page-hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.page-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(0,0,0,.42) 0%, rgba(0,0,0,.12) 45%, rgba(0,0,0,.55) 100%); }
.page-hero-copy { position: absolute; inset: auto 0 0; z-index: 2; padding-bottom: clamp(22px, 4vh, 44px); color: #fff; text-shadow: 0 2px 26px rgba(0,0,0,.3); }
.page-hero-copy .label { margin: 0 0 10px; opacity: .9; }

/* ---------- generic section ---------- */
/* padding-block, not the shorthand: an element carrying both .section and
   .shell would otherwise have its horizontal gutter reset to zero and bleed
   to the viewport edge. */
.section { padding-block: clamp(58px, 9vh, 118px); }
.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 30px; margin-bottom: clamp(22px, 4vh, 46px); }
.rule { border: 0; border-top: 1px solid var(--ink-12); margin: 0; }

/* ---------- product cards ---------- */
.products { display: grid; grid-template-columns: repeat(auto-fit, minmax(288px, 1fr)); gap: 14px; }
.product {
  position: relative; display: block; text-decoration: none; color: #fff;
  aspect-ratio: 3 / 3.6; overflow: hidden; border-radius: var(--r);
  background: #444;
}
.product img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: transform .9s var(--ease);
}
.product:hover img { transform: scale(1.045); }
.product::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,.34) 0%, rgba(0,0,0,.05) 38%, rgba(0,0,0,.62) 100%);
}
.product-body { position: absolute; inset: auto 0 0; z-index: 2; padding: 20px; }
.product .label { opacity: .9; }
.product h3 { margin: 8px 0 6px; font-size: clamp(1.35rem, 2vw, 1.9rem); font-weight: 500; font-stretch: 82%; line-height: .98; letter-spacing: -.01em; }
.product p { margin: 0; font-size: 13.5px; line-height: 1.36; color: rgba(255,255,255,.86); max-width: 34ch; }
.product .go { display: inline-block; margin-top: 12px; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; border-bottom: 1px solid rgba(255,255,255,.7); padding-bottom: 2px; }
.product .corner { position: absolute; top: 18px; left: 20px; z-index: 2; }

/* ---------- facts / stack ---------- */
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 1px; background: var(--ink-12); border: 1px solid var(--ink-12); }
.facts > div { background: var(--paper); padding: 20px; }
.facts dt { font-size: 11px; letter-spacing: .15em; text-transform: uppercase; color: var(--ink-40); margin: 0 0 8px; }
.facts dd { margin: 0; font-size: clamp(1.5rem, 2.4vw, 2.3rem); font-weight: 500; font-stretch: 82%; line-height: 1; letter-spacing: -.01em; }
.facts dd small { display: block; font-size: 15px; font-weight: 400; letter-spacing: 0; color: var(--ink-60); margin-top: 7px; line-height: 1.35; }

.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); gap: clamp(20px, 3vw, 44px); }
.cols h4 { margin: 0 0 8px; font-size: 15px; font-weight: 600; }
.cols p { margin: 0; font-size: 16px; color: var(--ink-60); line-height: 1.45; }

/* ---------- buttons + search ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 9px; border: 0; cursor: pointer;
  background: var(--ink); color: var(--paper); font: inherit; font-size: 13px;
  letter-spacing: .09em; text-transform: uppercase; font-weight: 600;
  padding: 15px 26px; border-radius: var(--r); min-height: 46px;
  text-decoration: none; transition: opacity .18s var(--ease);
}
.btn:hover { opacity: .82; }
.btn.light { background: var(--paper); color: var(--ink); }
.btn:disabled { opacity: .45; cursor: wait; }

.searchbar { display: flex; gap: 8px; max-width: 720px; }
.searchbar input {
  flex: 1; min-width: 0; border: 1px solid var(--ink); background: transparent;
  color: var(--ink); font: inherit; font-size: 16px; padding: 13px 16px;
  border-radius: var(--r);
}
.searchbar input::placeholder { color: var(--ink-40); }
.searchbar input:focus { outline: 0; box-shadow: inset 0 0 0 1px var(--ink); }
.chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
.chip {
  border: 1px solid var(--ink-12); background: transparent; color: var(--ink-60);
  font: inherit; font-size: 12.5px; padding: 8px 13px; border-radius: var(--r);
  cursor: pointer; min-height: 36px; transition: all .16s var(--ease);
}
.chip:hover { border-color: var(--ink); color: var(--ink); }

/* ---------- results ---------- */
.meta { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin: 22px 0 0; font-size: 14px; }
.pill { border: 1px solid var(--ink-12); border-radius: var(--r); padding: 5px 10px; color: var(--ink-60); }
.pill b { color: var(--ink); font-weight: 600; }
.badge { display: inline-flex; align-items: center; gap: 7px; border-radius: var(--r); padding: 5px 11px; font-weight: 600; background: var(--ink); color: var(--paper); }
.badge::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.badge.rules { background: transparent; color: var(--ink); border: 1px solid var(--ink); }
.badge.cache { background: transparent; color: var(--warn); border: 1px solid var(--warn); }
.meta a { color: var(--ink); }
.notice { border-left: 3px solid var(--ink); background: var(--card); padding: 15px 18px; margin: 16px 0 0; font-size: 15.5px; }
/* Saying "we do not go there" is a stronger signal than a relaxation note,
   so it is coloured as a limit rather than as an adjustment. */
.notice.coverage { border-left-color: var(--bad); }
.notice.coverage strong { color: var(--bad); }

.results-layout { display: grid; grid-template-columns: minmax(0, 1fr) 288px; gap: 26px; align-items: start; margin-top: 26px; }
.grid-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 12px; }
.card { position: relative; overflow: hidden; border-radius: var(--r); background: #ccc; aspect-ratio: 3 / 4; color: #fff; text-decoration: none; display: block; }
.card .thumb { position: absolute; inset: 0; background-size: cover; background-position: center; }
.card::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(0,0,0,.3) 0%, rgba(0,0,0,.02) 34%, rgba(0,0,0,.72) 100%); }
.card .body { position: absolute; inset: auto 0 0; z-index: 2; padding: 15px; }
.card .top-label { position: absolute; top: 14px; left: 15px; z-index: 2; }
.card h3 { margin: 0 0 3px; font-size: 1.12rem; font-weight: 500; font-stretch: 82%; line-height: 1.02; }
.card .where { font-size: 11px; letter-spacing: .12em; text-transform: uppercase; opacity: .8; }
.card .rowline { display: flex; justify-content: space-between; align-items: baseline; margin-top: 9px; font-size: 13px; }
.card .price { font-weight: 600; }
.card .tagrow { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.card .tag {
  font-size: 10.5px; letter-spacing: .04em; line-height: 1;
  border: 1px solid rgba(255, 255, 255, .4); color: rgba(255, 255, 255, .9);
  padding: 4px 7px; border-radius: 3px; white-space: nowrap;
}
.whyrow { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 9px; }
.why { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; border: 1px solid rgba(255,255,255,.55); padding: 3px 7px; border-radius: 3px; }
.ribbon { position: absolute; top: 14px; right: 15px; z-index: 2; background: var(--paper); color: var(--ink); font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase; font-weight: 600; padding: 4px 9px; border-radius: 3px; }
.book { margin-top: 11px; width: 100%; border: 1px solid rgba(255,255,255,.6); background: transparent; color: #fff; font: inherit; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; padding: 9px; border-radius: var(--r); cursor: pointer; min-height: 40px; }
.book:hover { background: #fff; color: var(--ink); }
.booked { background: #fff; color: var(--ink); }

/* ---------- side panel ---------- */
.panel { border: 1px solid var(--ink-12); padding: 20px; position: sticky; top: 92px; }
.panel h3 { margin: 0 0 6px; font-size: 14px; font-weight: 600; }
.fine { font-size: 14px; color: var(--ink-40); margin: 0 0 14px; line-height: 1.4; }
.aff { margin: 10px 0; }
.aff .lbl { display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 4px; }
.bar { height: 3px; background: var(--ink-12); }
.bar i { display: block; height: 100%; background: var(--ink); transition: width .5s var(--ease); }
.pstat { display: flex; justify-content: space-between; font-size: 12.5px; padding: 4px 0; color: var(--ink-60); }
.pstat b { color: var(--ink); font-weight: 600; }
.ghost { width: 100%; margin-top: 14px; border: 1px solid var(--ink-12); background: transparent; color: var(--ink-60); font: inherit; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; padding: 11px; border-radius: var(--r); cursor: pointer; min-height: 42px; }
.ghost:hover { border-color: var(--ink); color: var(--ink); }

/* ---------- ops ---------- */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 1px; background: var(--ink-12); border: 1px solid var(--ink-12); margin-bottom: 26px; }
.tile { background: var(--paper); padding: 18px; }
.tile .n { font-size: clamp(1.7rem, 3vw, 2.6rem); font-weight: 500; font-stretch: 82%; line-height: 1; }
.tile .l { font-size: 12px; letter-spacing: .13em; text-transform: uppercase; color: var(--ink-40); margin-top: 7px; }
.ops-tables { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; }
.rows { display: flex; flex-direction: column; gap: 8px; }
.rowc { border: 1px solid var(--ink-12); padding: 14px 16px; font-size: 15px; cursor: pointer; }
.rowc:hover { border-color: var(--ink); }
.rowc .t { font-weight: 600; display: flex; justify-content: space-between; gap: 10px; }
.rowc .d { color: var(--ink-60); margin-top: 4px; line-height: 1.4; }
.status { font-size: 10px; letter-spacing: .11em; text-transform: uppercase; font-weight: 600; white-space: nowrap; }
.status.needs_enrichment { color: var(--warn); }
.status.enriching { color: var(--ink-60); }
.status.enriched { color: var(--good); }
.status.failed { color: var(--bad); }
.diff { margin-top: 10px; border-top: 1px solid var(--ink-12); padding-top: 10px; display: grid; gap: 7px; }
.diff .before { color: var(--ink-40); text-decoration: line-through; }
.diff .src { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-40); }
.live-dot::after { content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--good); margin-left: 7px; animation: pulse 1.8s infinite; }
@keyframes pulse { 50% { opacity: .2; } }

/* ---------- ambient background ----------
   Fixed behind everything at low contrast. Content sits on translucent
   surfaces so the field shows through without ever competing with type. */
/* Percentages, not viewport units. 100vw measures the viewport including the
   scrollbar, so the canvas sat wider than the page it covered and every
   product page could be dragged sideways. A canvas is a replaced element, so
   the size cannot simply be dropped in favour of inset:0 either: with width
   auto it falls back to its intrinsic pixel size and stops covering anything.
   100% of a fixed element resolves against the viewport, scrollbar excluded. */
#bg {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: -1; pointer-events: none;
}
.has-bg body, body:has(#bg) { background: var(--paper); }
.has-bg .top { background: color-mix(in srgb, var(--paper) 72%, transparent); backdrop-filter: blur(14px) saturate(1.3); }
.has-bg .facts > div,
.has-bg .tile,
.has-bg .stage,
.has-bg .flow-node,
.has-bg .compare-card,
.has-bg .panel,
.has-bg .rowc,
.has-bg .honesty { background: color-mix(in srgb, var(--paper) 78%, transparent); backdrop-filter: blur(10px); }

/* ---------- search, laid out as an engine ----------
   Centred field, action beneath it, suggestions balanced around the centre
   rather than ragged to one side. */
.engine { min-height: calc(100vh - 68px); display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; padding: clamp(70px, 12vh, 130px) var(--gutter) clamp(40px, 7vh, 80px); }
.engine-inner { width: 100%; max-width: 780px; }
.engine .d2 { margin-bottom: 14px; }
.engine .lede { margin: 0 auto clamp(28px, 5vh, 52px); text-align: center; max-width: 58ch; }
.engine .searchbar { flex-direction: column; gap: 14px; max-width: 680px; margin: 0 auto; }
.engine .searchbar input {
  width: 100%; text-align: center; font-size: clamp(17px, 1.6vw, 21px);
  padding: 18px 22px; border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: blur(10px);
}
.engine .searchbar .btn { align-self: center; padding: 15px 44px; border-radius: 999px; }
.engine .chips { justify-content: center; margin-top: 22px; max-width: 760px; margin-inline: auto; }
.engine .chip { background: color-mix(in srgb, var(--paper) 74%, transparent); backdrop-filter: blur(8px); }

/* With the hero band above it the engine must not also claim a full screen,
   or the search box lands below the fold and the page opens on nothing. */
.page-hero + .engine {
  min-height: 0;
  padding-top: clamp(44px, 7vh, 84px);
  padding-bottom: clamp(36px, 6vh, 72px);
}

/* Once results exist the engine stops owning the viewport and behaves like a
   results page. */
body.has-results .engine { min-height: 0; padding-top: clamp(96px, 14vh, 150px); padding-bottom: clamp(20px, 3vh, 36px); }

/* ---------- pill labels and centred blocks ---------- */
.pill-label {
  display: inline-block; margin: 0 0 14px; padding: 6px 15px;
  border: 1px solid var(--ink-12); border-radius: 999px;
  font-size: 11px; letter-spacing: .17em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-60); background: var(--surface, #fff);
}
.centred { text-align: center; }
.centred .pill-label { margin-inline: auto; }
.centred .lede { margin-inline: auto; }
.centred-lede { margin-inline: auto; }
/* Pages built around a centred spine: headings and intros centre, and the
   blocks beneath them keep a comfortable measure instead of stretching. */
.centred-page .tiles,
.centred-page .honesty { max-width: 1000px; margin-inline: auto; }
.centred-page #eval-meta { text-align: center; }
.centred-page .rule { max-width: 1000px; margin-inline: auto; }

/* ---------- flow chart ----------
   A read-at-a-glance diagram rather than an animation: boxes joined by
   labelled arrows, with the failure path drawn as a separate branch so it is
   visible without having to wait for a sequence to play. */
/* Centred column with the connector running down the middle, and each stage
   carrying its own accent so the four steps are distinguishable at a glance
   instead of reading as four identical grey boxes. */
.flow { margin: 8px auto 0; display: grid; gap: 0; max-width: 760px; text-align: left; }
.flow-node {
  border: 1px solid var(--ink-12); padding: 16px 20px; background: var(--card);
  border-radius: var(--r);
}
/* Terminals and the failure branch carry accents too. Left grey they read as
   unfinished boxes next to four coloured stages. */
.flow-node.terminal {
  border-style: dashed; background: transparent;
  border-color: color-mix(in srgb, var(--rose, #c9647f) 45%, var(--ink-12));
}
.flow-node.terminal .flow-kind { color: #a8577a; }
.flow-node strong { display: block; font-size: 16px; font-weight: 600; }
.flow-kind {
  display: block; font-size: 11px; letter-spacing: .15em; text-transform: uppercase;
  color: var(--ink-40); font-weight: 600; margin-bottom: 5px;
}
/* The connector: a vertical rule with an arrowhead and an inline label. */
.flow-arrow {
  position: relative; height: 56px; display: grid; place-items: center;
}
.flow-arrow::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 50%;
  border-left: 2px solid var(--ink-12);
}
.flow-arrow::after {
  content: ""; position: absolute; bottom: -1px; left: calc(50% - 5px);
  border: 5px solid transparent; border-top-color: var(--ink-12);
}
.flow-arrow span {
  position: relative; z-index: 1; font-size: 13px; color: var(--ink-60);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--paper); padding: 3px 12px; border-radius: 999px;
  border: 1px solid var(--ink-12);
}
.flow-branch {
  margin: 18px auto 0; padding: 16px 20px; max-width: 92%;
  border: 1px dashed color-mix(in srgb, var(--warn) 40%, var(--ink-12));
  border-left: 3px solid var(--warn);
  border-radius: var(--r);
}
.flow-branch .flow-kind { color: var(--warn); }

/* ---------- cold against warm ----------
   Two columns of the same listings, one ranked with an empty profile and one
   with a persona's. They must line up row for row, or the movement between
   them is impossible to read. */
.cmp-controls {
  max-width: 980px; margin: clamp(18px, 3vh, 32px) auto clamp(20px, 3vh, 34px);
  text-align: center;
}
.cmp-legend {
  margin: 0 0 12px; font-size: 11px; letter-spacing: .15em;
  text-transform: uppercase; color: var(--ink-40); font-weight: 600;
}
.cmp-controls .chips { justify-content: center; }
.cmp-controls .chip.on {
  background: var(--ink); color: var(--paper); border-color: var(--ink);
}
.cmp-query {
  display: flex; gap: 10px; justify-content: center; margin-top: 18px;
  flex-wrap: wrap;
}
.cmp-query input {
  flex: 1 1 340px; max-width: 460px; font: inherit; font-size: 15px;
  padding: 12px 18px; border-radius: 999px; border: 1px solid var(--ink-12);
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  color: var(--ink);
}
.cmp-query .btn { padding: 12px 30px; border-radius: 999px; }

.cmp {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(14px, 2vw, 28px);
  max-width: 1080px; margin: 0 auto; align-items: start;
}
.cmp.busy { opacity: .55; transition: opacity .2s; }
.cmp-col { border: 1px solid var(--ink-12); border-radius: var(--r); padding: 18px; }
/* The warm column is the one making the claim, so it is the one that looks
   different. */
.cmp-col.warm {
  border-color: color-mix(in srgb, #a86fe0 40%, var(--ink-12));
  background: color-mix(in srgb, #a86fe0 5%, transparent);
}
.cmp-head { margin-bottom: 14px; }
.cmp-head h4 { margin: 0 0 4px; font-size: 17px; font-weight: 600; }
.cmp-head .fine { margin: 0; min-height: 2.6em; }
.cmp-list { list-style: none; margin: 0; padding: 0; }
.cmp-card {
  display: grid; grid-template-columns: 28px 1fr auto; gap: 12px;
  align-items: start; padding: 11px 0; border-top: 1px solid var(--ink-12);
  background: var(--paper);
}
.cmp-card.moving { z-index: 2; box-shadow: 0 8px 30px rgba(1,1,1,.10); }
/* Departures slide out to the right and fade. Pinned out of flow first, so
   the column below them can rebuild without waiting for the exit. */
.cmp-card.leaving {
  opacity: 0; transform: translateX(26px);
  transition: opacity .5s ease, transform .6s cubic-bezier(.4,0,.7,.2);
  pointer-events: none; z-index: 3;
}
/* Arrivals were never on the cold page: they come from deeper in the candidate
   set, so they appear rather than travel. */
.cmp-card.arriving { animation: cardIn .55s cubic-bezier(.2,.85,.25,1) both; }
@keyframes cardIn {
  from { opacity: 0; transform: translateY(10px); background: rgba(168,111,224,.16); }
  to   { opacity: 1; transform: none; }
}
.cmp-rank {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; color: var(--ink-40); padding-top: 2px;
}
.cmp-body strong { display: block; font-size: 15px; font-weight: 600; line-height: 1.35; }
.cmp-facts { margin: 3px 0 0; font-size: 13px; color: var(--ink-60); }
.cmp-why { margin: 5px 0 0; font-size: 12.5px; color: #7a4fb0; line-height: 1.45; }
.cmp-delta {
  font-size: 12px; font-weight: 600; padding: 3px 8px; border-radius: 999px;
  white-space: nowrap; margin-top: 2px; text-align: center; line-height: 1.35;
}
.cmp-delta em {
  display: block; font-style: normal; font-weight: 500; font-size: 10.5px;
  opacity: .8;
}
.cmp-delta.up { color: #1f7a52; background: rgba(31,122,82,.12); }
.cmp-delta.down { color: #9a5520; background: rgba(154,85,32,.12); }
.cmp-delta.flat { color: var(--ink-40); background: rgba(1,1,1,.05); font-weight: 500; }

@media (max-width: 760px) {
  /* Stacked, the two columns stop being comparable at a glance, but the delta
     badges still carry the movement. */
  .cmp { grid-template-columns: 1fr; }
}

/* ---------- page entrance ----------
   Opening a product page from the catalogue used to snap. Sections rise in
   sequence instead, which is short enough not to delay reading. */
@media (prefers-reduced-motion: no-preference) {
  header.top { animation: fade .5s ease both; }
  /* The scale goes on the image, not the band. Scaling a full-width element
     pushes it past both edges of the viewport for the length of the
     animation, and on a phone that is a page you can drag sideways while it
     plays. The band clips its own overflow, so the image inside it gives the
     same push-in with nothing escaping. */
  .page-hero { animation: fade .5s ease both; }
  .page-hero img { animation: heroIn .9s cubic-bezier(.16,.84,.3,1) both; }
  /* The hero copy trails its own image so the band resolves before the words
     land on it, which is what makes the open read as deliberate. */
  .page-hero-copy { animation: rise .7s cubic-bezier(.16,.84,.3,1) .16s both; }
  .engine, main > section:first-of-type, main.shell > *:first-child {
    animation: rise .7s cubic-bezier(.16,.84,.3,1) .1s both;
  }
}
@keyframes rise {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
/* Scale, not slide: the band grows into place, so arriving from the catalogue
   card feels like the card expanding rather than a new document loading. */
@keyframes heroIn {
  from { opacity: 0; transform: scale(1.06); }
  to   { opacity: 1; transform: none; }
}
.flow-branch strong { display: block; font-size: 15.5px; font-weight: 600; margin-bottom: 6px; }
.flow-branch p { margin: 0; font-size: 15px; color: var(--ink-60); line-height: 1.5; }
.flow-branch code { font-size: 13.5px; background: var(--card); padding: 2px 6px; border-radius: 3px; }

.stages { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.stage {
  position: relative; border: 1px solid var(--ink-12); border-radius: var(--r);
  padding: 20px 22px 20px 68px; background: var(--paper);
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s var(--ease);
  overflow: hidden;
}
/* Accent rail per stage, so the sequence is followable by colour as well as
   by number. */
.stage::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--accent-stage, var(--ink-12));
}
.stage:nth-child(1) { --accent-stage: #c9647f; }
.stage:nth-child(2) { --accent-stage: #b07fc4; }
.stage:nth-child(3) { --accent-stage: #4f93b8; }
.stage:nth-child(4) { --accent-stage: #2f8f6a; }
.stage:hover { transform: translateY(-2px); border-color: var(--accent-stage); box-shadow: var(--shadow-lift, 0 16px 40px rgba(0,0,0,.10)); }
.stage-n {
  position: absolute; left: 22px; top: 20px;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: #fff; background: var(--accent-stage);
}
.stage h4 { margin: 0 0 6px; font-size: 15.5px; font-weight: 700; }
.stage p { margin: 0 0 12px; font-size: 16px; color: var(--ink-60); line-height: 1.45; max-width: 66ch; }
.stage code { font-size: 14px;
  display: inline-block; font-size: 12px; background: var(--card);
  padding: 5px 10px; border-radius: 4px; color: var(--ink-60);
}
.stage.active { border-color: var(--ink); border-left-color: var(--ink); background: var(--card); transform: translateX(4px); }
.stage.active .stage-n { color: var(--ink); }
.stage.done { border-left-color: var(--good); }
.src {
  display: inline-block; margin-top: 10px; font-size: 12px; letter-spacing: .04em;
  color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--ink-12);
  padding-bottom: 2px;
}
.src:hover { border-bottom-color: var(--ink); }
.src::after { content: " ↗"; color: var(--ink-40); }
.src.inline { margin: 0; }

/* ---------- honesty note ---------- */
.honesty { border: 1px solid var(--ink-12); border-left: 3px solid var(--warn); padding: 20px 22px; margin-top: 26px; }
.honesty h4 { margin: 0 0 12px; font-size: 14px; font-weight: 700; }
.honesty ul { margin: 0; padding-left: 18px; }
.honesty li { font-size: 16px; color: var(--ink-60); line-height: 1.5; margin-bottom: 9px; }
.honesty strong { color: var(--ink); }

/* ---------- before / after comparison ---------- */
.compare { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: clamp(24px, 4vh, 44px); }
.compare-card { border: 1px solid var(--ink-12); border-radius: var(--r); padding: 20px; background: var(--paper); display: flex; flex-direction: column; }
.compare-card.bad { border-color: rgba(163, 52, 31, .28); }
.compare-card.good { border-color: rgba(31, 111, 69, .3); }
.compare-card header { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.compare-card header h4 { margin: 0; font-size: 15.5px; font-weight: 700; }
.compare-card header .fine { margin: 2px 0 0; }
.mark { width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; font-size: 13px; flex: none; }
.mark-sm { display: inline-block; width: 15px; font-size: 11px; }
.bad-mark { color: var(--bad); background: rgba(163, 52, 31, .1); }
.good-mark { color: var(--good); background: rgba(31, 111, 69, .1); }
.mark-sm.bad-mark, .mark-sm.good-mark { background: none; }
.field { border: 1px solid var(--ink-12); border-radius: var(--r); padding: 13px 15px; margin-bottom: 10px; }
.field-label { margin: 0 0 7px; font-size: 11px; letter-spacing: .13em; text-transform: uppercase; font-weight: 600; color: var(--ink-40); }
.field-body { margin: 0; font-size: 15.5px; line-height: 1.5; color: var(--ink-60); }
.amenities { display: flex; flex-wrap: wrap; gap: 5px; }
.amenity { font-size: 13px; border: 1px solid var(--ink-12); border-radius: 3px; padding: 4px 8px; color: var(--ink-60); }
.compare-card footer { margin-top: auto; padding-top: 14px; font-size: 15px; color: var(--ink-60); line-height: 1.45; }

@media (max-width: 860px) { .compare { grid-template-columns: 1fr; } }

/* ---------- footer ---------- */
.foot { border-top: 1px solid var(--ink-12); padding: 26px 0 40px; margin-top: 40px; }
.foot-inner { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; font-size: 12px; color: var(--ink-40); }

/* ---------- states ---------- */
.skeleton { background: var(--card); aspect-ratio: 3 / 4; border-radius: var(--r); animation: sk 1.2s infinite; }
@keyframes sk { 50% { opacity: .55; } }
.error-note { border-left: 3px solid var(--bad); background: var(--card); color: var(--bad); padding: 13px 16px; }

@media (max-width: 1000px) {
  .results-layout { grid-template-columns: 1fr; }
  .panel { position: static; order: -1; }
  .ops-tables { grid-template-columns: 1fr; }
  .top nav { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  .door-panel { transform: rotateY(-62deg); }
}
