/* ==========================================================================
   MOP Buddy — mopbuddy.sg
   Design system. Palette is taken from the MOP Buddy mark; layout follows the
   approved hero composition. Type: Nunito throughout — 700/800 for display,
   400/600/700 for body, UI and data. One family, three roles, separated by
   weight rather than by typeface.
   ========================================================================== */

/* Self-hosted so the page renders in one round trip, offline included.
   Latin subsets only; ~64 KB for the whole type system.
   Nunito is SIL Open Font License 1.1 — see fonts/Nunito-OFL.txt. */
@font-face { font-family: "Nunito"; font-style: normal; font-weight: 400;
  font-display: swap; src: url("../fonts/nunito-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-style: normal; font-weight: 600;
  font-display: swap; src: url("../fonts/nunito-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-style: normal; font-weight: 700;
  font-display: swap; src: url("../fonts/nunito-latin-700-normal.woff2") format("woff2"); }
@font-face { font-family: "Nunito"; font-style: normal; font-weight: 800;
  font-display: swap; src: url("../fonts/nunito-latin-800-normal.woff2") format("woff2"); }

:root {
  /* Brand greens, sampled from the logo artwork */
  --forest:        #0B4820;
  --forest-deep:   #072F15;
  --forest-mid:    #135428;
  --leaf:          #66993D;
  --olive:         #5A6B22;   /* EC route title: 5.90:1 on white, clear of forest and amber */
  --leaf-deep:     #4E7A2C;

  /* Surfaces. --paper is the overall base and is matched by the white the hero
     photograph fades out into, so the photo has no visible edge against it. */
  --paper:         #FFFEFF;
  --white:         #FFFFFF;
  --mist:          #F4F7F1;
  --leaf-soft:     #EAF2E1;
  --line:          #E3E8DF;
  --line-strong:   #CFD8C9;

  /* Ink */
  --ink:           #14201A;
  --ink-70:        #46534C;
  --ink-50:        #6C7872;
  --ink-35:        #98A19B;

  /* Functional accents — used once each, never decoratively */
  --amber:         #A96A24;
  --amber-soft:    #FBF3E7;
  --slate:         #3E5878;
  --slate-soft:    #EDF2F8;
  --violet:        #55488A;
  --violet-soft:   #F0EEF8;
  --rose:          #A03B48;

  /* Geometry */
  --r-sm:  8px;
  --r-md:  14px;
  --r-lg:  20px;
  --r-xl:  28px;
  --r-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(20, 32, 26, .05);
  --shadow-md: 0 2px 8px rgba(20, 32, 26, .05), 0 1px 2px rgba(20, 32, 26, .04);
  --shadow-lg: 0 18px 48px -22px rgba(11, 72, 32, .28), 0 2px 8px rgba(20, 32, 26, .04);
  --shadow-cta: 0 10px 24px -12px rgba(11, 72, 32, .55);

  /* One family. Display and body are kept as separate tokens so a future
     change can split them again without touching every rule. */
  --display: "Nunito", "Segoe UI", system-ui, -apple-system, sans-serif;
  --body: "Nunito", "Segoe UI", system-ui, -apple-system, sans-serif;

  --wrap: 1180px;
  --gutter: 24px;
}

/* --------------------------------------------------------------- reset --- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; background: var(--paper); }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; }
a { color: var(--forest); text-decoration-color: color-mix(in srgb, var(--forest) 30%, transparent); text-underline-offset: 3px; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -.014em;
  line-height: 1.1;
  margin: 0;
  color: var(--ink);
}

:focus-visible {
  outline: 3px solid var(--leaf);
  outline-offset: 2px;
  border-radius: 4px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }

.num { font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------------- header --- */

.mast {
  position: relative;
  z-index: 40;
  padding-block: 22px 0;
}
.mast__row { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.mast__logo { display: inline-flex; align-items: center; }
.mast__logo img { width: 218px; height: auto; }

.badge-free {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 18px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
  font-size: 15px; font-weight: 600; color: var(--ink-70);
  white-space: nowrap;
}
.badge-free svg { color: var(--leaf); flex: none; }

/* ---------------------------------------------------------------- hero --- */

.hero { position: relative; padding-block: 42px 0; }

/* The artwork already fades out to the page base on its left, top and bottom
   edges, so it needs no gradient mask of its own — a second fade would only
   eat into the buildings. It is pulled up past the masthead (--mast-drop) so
   its top edge sits at the very top of the page: an edge that lands part-way
   down the page reads as a hard band behind the header, which is the gap this
   replaces. The short top fade is belt-and-braces against that first pixel
   row differing from --paper by a shade. */
.hero__photo {
  --mast-drop: 113px;
  position: absolute;
  top: calc(var(--mast-drop) * -1); right: 0;
  width: 68%;
  max-width: 1120px;
  z-index: 0;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 7%, #000 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 7%, #000 100%);
}
.hero__photo img { width: 100%; height: auto; }

.hero__inner { position: relative; z-index: 1; max-width: 640px; padding-block: 46px 0; }

.hero__title {
  font-size: clamp(2.6rem, 5.4vw, 4.15rem);
  line-height: 1.04;
  letter-spacing: -.02em;
}
.hero__title em { font-style: normal; color: var(--leaf); }

.hero__sub {
  margin: 20px 0 0;
  font-size: 1.2rem;
  color: var(--ink-70);
  max-width: 44ch;
}

/* --------------------------------------------------------- search form --- */

.finder { margin-top: 40px; max-width: 760px; }
.finder__label {
  display: block;
  font-family: var(--display);
  font-weight: 700; font-size: 1.05rem;
  margin-bottom: 12px;
}

.finder__bar { display: flex; gap: 12px; align-items: stretch; }

.field {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex; align-items: center;
  background: var(--white);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  transition: border-color .15s, box-shadow .15s;
}
.field:focus-within { border-color: var(--leaf); box-shadow: 0 0 0 4px var(--leaf-soft); }
.field__icon { flex: none; margin-inline: 18px 0; color: var(--ink-35); display: flex; }
.field input {
  flex: 1 1 auto; min-width: 0;
  padding: 20px 18px;
  border: 0; background: none; outline: none;
  font-size: 1.06rem;
}
.field input::placeholder { color: var(--ink-35); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--display); font-weight: 700; font-size: 1.02rem;
  padding: 20px 28px;
  border-radius: var(--r-md);
  transition: transform .12s ease, box-shadow .18s ease, background-color .18s ease;
  white-space: nowrap;
}
.btn--primary { background: var(--forest); color: #fff; box-shadow: var(--shadow-cta); }
.btn--primary:hover { background: var(--forest-mid); transform: translateY(-1px); }
.btn--primary:active { transform: translateY(0); }
.btn--ghost {
  background: var(--white); color: var(--ink);
  border: 1px solid var(--line-strong); box-shadow: var(--shadow-sm);
  padding: 13px 20px; font-size: .95rem;
}
.btn--ghost:hover { border-color: var(--ink-35); }
.btn--block { width: 100%; }
.btn[disabled] { opacity: .5; cursor: not-allowed; transform: none; }

.finder__hint { margin: 14px 0 0; font-size: .96rem; color: var(--ink-50); }
.finder__error { margin: 14px 0 0; font-size: .96rem; color: var(--rose); font-weight: 600; }

/* autocomplete */
.ac {
  position: absolute; z-index: 30; top: calc(100% + 8px); left: 0; right: 0;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  max-height: 340px; overflow-y: auto;
}
.ac__item {
  display: flex; align-items: baseline; gap: 10px; width: 100%;
  padding: 13px 18px; text-align: left;
  border-bottom: 1px solid var(--mist);
}
.ac__item:last-child { border-bottom: 0; }
.ac__item:hover, .ac__item[aria-selected="true"] { background: var(--mist); }
.ac__addr { font-weight: 600; }
.ac__addr mark { background: var(--leaf-soft); color: inherit; border-radius: 3px; padding: 0 1px; }
.ac__meta { font-size: .88rem; color: var(--ink-50); margin-left: auto; white-space: nowrap; }
.ac__empty { padding: 18px; color: var(--ink-50); font-size: .96rem; }

/* --------------------------------------------------------- trust strip --- */

.trust { display: flex; flex-wrap: wrap; gap: 34px; margin-top: 34px; }
.trust__item { display: flex; align-items: center; gap: 13px; }
.trust__ico {
  flex: none; width: 42px; height: 42px; border-radius: var(--r-pill);
  background: var(--leaf-soft); color: var(--forest);
  display: grid; place-items: center;
}
.trust__t { font-weight: 700; font-size: .98rem; line-height: 1.3; }
.trust__d { font-size: .92rem; color: var(--ink-50); line-height: 1.3; }

/* ----------------------------------------------------- reassurance bar --- */

.assure {
  margin: 58px 0 72px;
  background: var(--mist);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr) 218px 218px;
  align-items: center;
  gap: 28px;
  padding: 18px 34px 18px 18px;
}
.assure__art { width: 190px; border-radius: var(--r-lg); overflow: hidden; background: var(--white); }
.assure__art img { width: 100%; aspect-ratio: 76 / 53; object-fit: cover; }
.assure__line { font-family: var(--display); font-weight: 700; font-size: 1.2rem; line-height: 1.28; max-width: 23ch; }
.assure__fact { padding-left: 26px; border-left: 1px solid var(--line-strong); }
.assure__fact b { display: block; font-family: var(--display); font-size: 1.02rem; color: var(--forest); }
.assure__fact span { font-size: .92rem; color: var(--ink-50); }

/* ------------------------------------------------------- details panel --- */

.panel {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 26px 28px;
  animation: rise .28s cubic-bezier(.2, .7, .3, 1) both;
}
@keyframes rise { from { opacity: 0; transform: translateY(10px); } }

.panel__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 22px; }
.panel__addr { font-family: var(--display); font-weight: 800; font-size: 1.3rem; }
.panel__town { font-size: .95rem; color: var(--ink-50); margin-top: 3px; }
.linkbtn { font-size: .95rem; font-weight: 600; color: var(--forest); text-decoration: underline; text-underline-offset: 3px; }

.qgrid { display: grid; gap: 20px; }
.q__label { display: block; font-weight: 700; font-size: .95rem; margin-bottom: 9px; }
.q__note { font-size: .88rem; color: var(--ink-50); margin-top: 7px; }

.seg { display: flex; flex-wrap: wrap; gap: 8px; }
.seg__opt {
  padding: 11px 18px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--white);
  font-weight: 600; font-size: .96rem;
  transition: all .14s;
}
.seg__opt:hover { border-color: var(--leaf); }
.seg__opt[aria-pressed="true"] { background: var(--forest); border-color: var(--forest); color: #fff; }
/* A flat type the block has no record of, revealed by "My flat type isn't
   listed". Dashed so the difference is visible without a second label, and
   without implying the option is disabled. */
.seg__opt--declared { border-style: dashed; color: var(--ink-70); }
.seg__opt--declared[aria-pressed="true"] { border-style: solid; color: #fff; }

.inp, select.inp {
  width: 100%;
  padding: 13px 15px;
  background: var(--white);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.inp:focus { border-color: var(--leaf); box-shadow: 0 0 0 4px var(--leaf-soft); }
select.inp { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236C7872' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; padding-right: 38px; }

.money-inp { position: relative; }
.money-inp::before { content: "$"; position: absolute; left: 15px; top: 50%; transform: translateY(-50%); color: var(--ink-50); font-weight: 600; }
.money-inp .inp { padding-left: 30px; font-variant-numeric: tabular-nums; }

.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

/* ------------------------------------------------------------- loading --- */

.loading { min-height: 62vh; display: grid; place-items: center; text-align: center; padding-block: 60px; }
.loading__mark { width: 74px; margin: 0 auto 26px; animation: bob 1.6s ease-in-out infinite; }
@keyframes bob { 50% { transform: translateY(-9px); } }
.loading h2 { font-size: 1.9rem; }
.loading__steps { margin: 26px auto 0; display: grid; gap: 11px; justify-items: start; width: max-content; }
.loading__step { display: flex; align-items: center; gap: 11px; color: var(--ink-35); font-size: 1.02rem; transition: color .3s; }
.loading__step.is-on { color: var(--ink); }
.loading__step .dot {
  width: 19px; height: 19px; border-radius: 50%;
  border: 2px solid currentColor; display: grid; place-items: center; flex: none;
}
.loading__step.is-on .dot { background: var(--leaf); border-color: var(--leaf); color: #fff; }
.loading__bar { width: min(340px, 80vw); height: 4px; border-radius: 2px; background: var(--line); overflow: hidden; margin: 30px auto 0; }
.loading__bar i { display: block; height: 100%; background: var(--leaf); width: 0; }

/* -------------------------------------------------------------- result --- */

.rail { border-block: 1px solid var(--line); background: var(--white); }
.rail__row { display: flex; align-items: center; justify-content: center; gap: 12px; padding-block: 16px; flex-wrap: wrap; }
.rail__step { display: flex; align-items: center; gap: 10px; color: var(--ink-35); font-weight: 600; font-size: .97rem; }
.rail__step.is-done { color: var(--ink-70); }
.rail__step.is-now { color: var(--ink); }
.rail__pip {
  width: 27px; height: 27px; border-radius: 50%; display: grid; place-items: center;
  border: 1.5px solid currentColor; font-size: .84rem; flex: none;
}
.rail__step.is-now .rail__pip { background: var(--forest); border-color: var(--forest); color: #fff; }
.rail__step.is-done .rail__pip { border-color: var(--leaf); color: var(--leaf); }
.rail__arrow { color: var(--line-strong); }

.result { padding-block: 40px 90px; }
.result__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; margin-bottom: 26px; }
.result__head h1 { font-size: clamp(1.8rem, 3.4vw, 2.35rem); }
.result__head p { margin: 8px 0 0; color: var(--ink-50); }

.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.card--pad { padding: 26px 28px; }

.section-h { font-size: 1.42rem; margin-bottom: 6px; }
.section-p { margin: 0 0 20px; color: var(--ink-50); }

/* property summary */
.psum { display: grid; grid-template-columns: 216px 1fr; gap: 26px; align-items: center; padding: 18px; }
.psum__img { border-radius: var(--r-md); overflow: hidden; aspect-ratio: 4 / 3; }
.psum__img img { width: 100%; height: 100%; object-fit: cover; }
.psum__addr { font-family: var(--display); font-weight: 800; font-size: 1.6rem; letter-spacing: -.012em; }
.psum__sub { font-size: .98rem; color: var(--ink-50); margin-top: 5px; }
.psum__facts { display: flex; flex-wrap: wrap; gap: 10px 24px; margin-top: 12px; color: var(--ink-70); }
.psum__fact { display: flex; align-items: center; gap: 8px; font-size: .99rem; }
.psum__fact svg { color: var(--ink-35); flex: none; }

.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 15px; border-radius: var(--r-pill);
  font-weight: 700; font-size: .92rem;
}
.chip--ok { background: var(--leaf-soft); color: var(--forest); }
.chip--wait { background: var(--amber-soft); color: var(--amber); }
.chip--soft { background: var(--mist); color: var(--ink-70); font-weight: 600; }

/* valuation */
.val { display: grid; grid-template-columns: minmax(240px, 340px) 1fr; gap: 34px; align-items: center; }
.val__eyebrow { font-size: .93rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-50); }
.val__big {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(2.7rem, 5.2vw, 3.6rem); letter-spacing: -.022em;
  color: var(--forest); line-height: 1.02; margin-top: 8px;
  font-variant-numeric: tabular-nums;
}
.val__range { margin-top: 10px; color: var(--ink-70); }
.val__why { margin-top: 6px; font-size: .9rem; line-height: 1.5; color: var(--ink-50); max-width: 46ch; }
.val__asof { margin-top: 14px; font-size: .9rem; line-height: 1.55; color: var(--ink-50); }
.val__chart { min-width: 0; }

.spark { width: 100%; height: 168px; display: block; overflow: visible; }
.spark__ends { display: flex; justify-content: space-between; margin-top: 10px; font-size: .88rem; color: var(--ink-50); }
.spark__ends b { display: block; font-family: var(--display); font-size: 1rem; color: var(--ink); font-variant-numeric: tabular-nums; }

/* metrics */
.metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 18px; }
.metric { padding: 20px 22px; }
.metric__k { display: flex; align-items: center; gap: 6px; font-size: .93rem; font-weight: 700; color: var(--ink-70); }
.metric__v { font-family: var(--display); font-weight: 800; font-size: 1.85rem; letter-spacing: -.018em; margin-top: 8px; font-variant-numeric: tabular-nums; }
.metric__v--up { color: var(--leaf-deep); }
.metric__d { font-size: .92rem; color: var(--ink-50); margin-top: 5px; }

/* Explanations that used to hide inside a `title` attribute. A tap cannot open
   a title, and ~90% of this site's traffic is a tap, so they are printed. */
.why {
  margin: 12px 0 0; padding-top: 11px; border-top: 1px solid var(--line);
  font-size: .84rem; line-height: 1.5; color: var(--ink-50);
}

/* ---------------------------------------------- the ledger (signature) --- */

.ledger { display: grid; grid-template-columns: 320px 1fr; gap: 0; overflow: hidden; }
.ledger__inputs { background: var(--mist); padding: 26px 26px 28px; border-right: 1px solid var(--line); }
.ledger__inputs h3 { font-size: 1.08rem; }
.ledger__inputs p { margin: 8px 0 20px; font-size: .93rem; color: var(--ink-50); }
.ledger__body { padding: 26px 28px 28px; min-width: 0; }

.stack { display: flex; height: 62px; border-radius: var(--r-sm); overflow: hidden; border: 1px solid var(--line); background: var(--mist); }
.stack__seg {
  position: relative;
  display: grid; place-items: center;
  min-width: 3px;
  transition: flex-basis .45s cubic-bezier(.3,.8,.3,1);
  overflow: hidden;
}
.stack__seg > span {
  font-size: .8rem; font-weight: 700; color: #fff;
  padding-inline: 6px; white-space: nowrap;
  opacity: .95;
}
.stack__seg--loan  { background: #7C8B84; }
.stack__seg--cpf   { background: var(--leaf); }
.stack__seg--cost  { background: #C3A66B; }
.stack__seg--cash  { background: var(--forest); }
/* the one flourish: the money you keep is drawn with an HDB façade grid */
.stack__seg--cash::before {
  content: ""; position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, rgba(255,255,255,.14) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.14) 1px, transparent 1px);
  background-size: 13px 13px;
  pointer-events: none;
}

.stack__key { display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 16px; }
.stack__keyitem { display: flex; align-items: center; gap: 8px; font-size: .92rem; color: var(--ink-70); }
.stack__sw { width: 12px; height: 12px; border-radius: 3px; flex: none; }
.stack__sw--loan { background: #7C8B84; }
.stack__sw--cpf  { background: var(--leaf); }
.stack__sw--cost { background: #C3A66B; }
.stack__sw--cash { background: var(--forest); }
.stack__keyv { color: var(--ink); }

/* On a phone the segments are too narrow to label, so the key becomes the
   readout: one row per segment, name left, amount right. */
@media (max-width: 860px) {
  .stack__key { display: grid; grid-template-columns: 1fr; gap: 0; margin-top: 14px; }
  .stack__keyitem { padding: 9px 0; border-bottom: 1px solid var(--line); }
  .stack__keyitem:last-child { border-bottom: 0; }
  .stack__keyt { flex: 1 1 auto; }
  .stack__keyv { margin-left: auto; }
}

.sum {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 18px;
  margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--line);
}
.sum__cell { min-width: 108px; }
.sum__k { font-size: .84rem; color: var(--ink-50); }
.sum__pre { display: none; }
.sum__v { font-family: var(--display); font-weight: 700; font-size: 1.14rem; margin-top: 4px; font-variant-numeric: tabular-nums; }
.sum__op { font-size: 1.2rem; color: var(--ink-35); padding-bottom: 4px; }
.sum__cell--out .sum__k { color: var(--forest); font-weight: 700; }
.sum__cell--out .sum__v { color: var(--forest); font-size: 1.5rem; font-weight: 800; }

.note {
  margin-top: 20px; padding: 16px 18px;
  background: var(--leaf-soft); border-radius: var(--r-md);
  font-size: .96rem; color: var(--forest-deep);
  display: flex; gap: 12px; align-items: flex-start;
}
.note svg { flex: none; margin-top: 2px; }
.note b { font-variant-numeric: tabular-nums; }
.note--plain { background: var(--mist); color: var(--ink-70); }
.note__sub { display: block; margin-top: 6px; font-size: .88em; color: var(--ink-50); }

.tiny { font-size: .85rem; color: var(--ink-50); margin-top: 14px; }

/* --------------------------------------------------------- next moves --- */

.moves { display: block; }
.move { padding: 20px 20px 22px; border-radius: var(--r-lg); border: 1px solid var(--line); position: relative; overflow: hidden; }
.move--resale { background: var(--slate-soft); border-color: #DDE6F0; }
.move--launch { background: var(--violet-soft); border-color: #E3DFF2; }
.move--ec     { background: var(--leaf-soft); border-color: #DCE9CE; }
.move--hdb    { background: var(--amber-soft); border-color: #F2E6D2; }
.move__art { position: absolute; right: -22px; bottom: -6px; width: 96px; opacity: .34; pointer-events: none; }
.move__t { font-family: var(--display); font-weight: 800; font-size: 1.06rem; }
.move--resale .move__t { color: var(--slate); }
.move--launch .move__t { color: var(--violet); }
.move--ec .move__t     { color: var(--forest); }
.move--hdb .move__t    { color: var(--amber); }
.move__k { font-size: .86rem; color: var(--ink-50); margin-top: 14px; }
.move__v { font-family: var(--display); font-weight: 800; font-size: 1.3rem; margin-top: 3px; font-variant-numeric: tabular-nums; letter-spacing: -.012em; }
.move__d { font-size: .88rem; color: var(--ink-70); margin-top: 12px; position: relative; line-height: 1.45; }

/* ------------------------------------------------------- the report gate --- */

/* The gated state. The blurred layer holds masked glyphs, never a real figure,
   so removing the blur reveals nothing — the numbers are simply not rendered
   until the report is unlocked. */
.locked { position: relative; isolation: isolate; }
.locked__blur {
  filter: blur(7px) saturate(.72);
  opacity: .5;
  pointer-events: none;
  user-select: none;
  transform: scale(1.008);          /* hides the soft edge the blur leaves */
}
.locked__over {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 40px 28px;
  background: linear-gradient(to bottom,
    rgba(255,254,255,.55) 0%, rgba(255,254,255,.9) 26%, rgba(255,254,255,.97) 100%);
  border-radius: var(--r-lg);
}
.locked__ico {
  width: 58px; height: 58px; border-radius: var(--r-pill);
  display: grid; place-items: center; margin-bottom: 18px;
  background: var(--leaf-soft); color: var(--forest);
}
.locked__over h2 { font-size: clamp(1.4rem, 2.6vw, 1.8rem); }
.locked__over > p { margin: 12px 0 0; color: var(--ink-70); max-width: 46ch; }
/* Six short lines, left-aligned inside a centred block. Prose here meant six
   items arriving as one sixty-word sentence, which nobody reads standing at a
   bus stop. The list is text-align:left because centred list items with
   ragged left edges are harder to scan than the paragraph they replaced. */
.locked__list {
  list-style: none; margin: 16px 0 0; padding: 0;
  display: grid; gap: 8px; text-align: left;
}
.locked__list li {
  display: flex; align-items: center; gap: 9px;
  color: var(--ink-70); font-size: .95rem; line-height: 1.35;
}
.locked__list li svg { flex: 0 0 auto; color: var(--forest); }
.locked__here { margin: 16px 0 0; color: var(--ink-70); }
/* The overlay teases; the unlock card below carries the contents list. Two
   copies of the same three bullets, one blurred and one not, read as padding. */
.locked__over .btn { margin-top: 24px; }
.locked__fine { margin: 14px 0 0; font-size: .85rem; color: var(--ink-50); }

/* Masked placeholders. Deliberately not a plausible number. */
.mask { color: var(--ink-35); letter-spacing: .06em; }
.sum--preview { margin-top: 22px; }
.sum--preview .sum__cell { padding: 10px 0; }

#report.is-revealed > * { animation: reveal .45s ease both; }
@keyframes reveal { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ------------------------------------------------- nearby transactions --- */

.txn {
  display: grid;
  grid-template-columns: minmax(0, 2.3fr) .9fr 1fr 1.1fr 1.2fr;
  gap: 14px; align-items: baseline;
  padding: 13px 0; border-bottom: 1px solid var(--mist);
  font-size: .95rem;
}
.txn:last-of-type { border-bottom: 0; }
.txn--head {
  border-bottom: 1px solid var(--line-strong); padding-top: 0;
  font-size: .78rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-50);
}
.txn--own { background: var(--mist); border-radius: var(--r-sm); }
.txn--own .txn__c:first-child { padding-left: 12px; }
.txn--own .txn__c:last-child { padding-right: 12px; }
.txn__c { min-width: 0; }
.txn__c--addr { font-weight: 600; }
.txn__c--idx { font-weight: 700; color: var(--forest); }
.txn__n { color: var(--ink-50); font-weight: 400; font-size: .85em; }
.txn__tag { margin-left: 8px; padding: 3px 9px; font-size: .72rem; vertical-align: 2px; }

/* --------------------------------------------------------- report unlock --- */
/*
   The gate's ask, rebuilt light.

   It used to be a solid forest panel, which made the one moment the product
   asks for something look like the one moment it stops being a tool. The
   surface is now the same paper the report sits on, the form is an ordinary
   white card, and the only saturated green left on the whole block is the
   button. The eye has exactly one place to go.

   Four grid children rather than a left column and a right column, so the
   phone order can put the value ahead of the ask — headline, benefits, form,
   privacy — without a second copy of the markup. */

.capture {
  margin-top: 44px;
  padding: 40px 44px;
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-sm);
  background:
    radial-gradient(115% 80% at 0% 0%, var(--leaf-soft) 0%, rgba(234, 242, 225, 0) 56%),
    linear-gradient(180deg, var(--mist) 0%, var(--white) 40%);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(340px, 424px);
  grid-template-areas:
    "head  form"
    "bens  form"
    "guard form";
  grid-template-rows: auto auto 1fr;
  align-content: start;
  column-gap: 46px;
}
.capture__head  { grid-area: head; }
.capture__bens  { grid-area: bens; }
.capture__form  { grid-area: form; align-self: start; }
.capture__guard { grid-area: guard; align-self: start; }

/* ---- the pitch --- */

.capture__eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--leaf-soft); color: var(--forest);
  border-radius: var(--r-pill); padding: 7px 14px;
  font-size: .78rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
}
.capture__eyebrow svg { flex: none; }

/* The headline is a two-beat sentence: the half the owner has already read,
   then the half still behind the gate. The second beat carries the colour. */
.capture h2 {
  margin: 18px 0 0;
  font-size: clamp(1.6rem, 2.9vw, 2.2rem);
  line-height: 1.14;
  letter-spacing: -.028em;
  color: var(--forest-deep);
  text-wrap: balance;
}
/* Each beat holds its own line: the half already read, then the half still
   closed. Breaking mid-clause loses the whole point of the sentence. */
.capture h2 span { display: block; }
.capture h2 .hl { color: var(--leaf-deep); }
.capture__sub {
  margin: 16px 0 0;
  color: var(--ink-70);
  font-size: 1.04rem;
  line-height: 1.55;
  max-width: 44ch;
}
.capture__sub b { color: var(--ink); font-weight: 700; }

/* ---- what is actually behind the gate --- */
/* One row per closed section, in the order they appear once it opens, with the
   same icon each section carries in the report. The list is a contents page,
   not a feature list. */

.capture__bens { list-style: none; padding: 0; margin: 28px 0 0; }
.ben {
  display: grid; grid-template-columns: 40px minmax(0, 1fr);
  gap: 14px; align-items: start;
  padding: 15px 0;
  border-top: 1px solid var(--line);
}
.capture__bens .ben:first-child { border-top: 0; padding-top: 4px; }
.ben__ico {
  width: 40px; height: 40px; border-radius: var(--r-pill);
  display: grid; place-items: center;
  background: var(--white); color: var(--forest);
  border: 1px solid var(--line); box-shadow: var(--shadow-sm);
}
.ben__t { font-family: var(--display); font-weight: 700; color: var(--ink); line-height: 1.3; }
.ben__d { margin: 3px 0 0; font-size: .92rem; color: var(--ink-50); line-height: 1.45; }

/* ---- privacy --- */

.capture__guard {
  display: grid; grid-template-columns: 38px minmax(0, 1fr);
  gap: 13px; align-items: start;
  margin-top: 26px; padding: 16px 18px;
  background: var(--leaf-soft);
  border-radius: var(--r-md);
}
.capture__guard svg { color: var(--forest); margin-top: 1px; }
.capture__guard .ben__ico { background: transparent; border: 0; box-shadow: none; width: 38px; height: 38px; }
.guard__t { font-family: var(--display); font-weight: 700; color: var(--forest); font-size: .98rem; }
.guard__d { margin: 3px 0 0; font-size: .87rem; color: var(--ink-70); line-height: 1.5; }
.guard__d a { color: var(--forest); text-decoration: underline; }

/* ---- the form card --- */

.capture__form {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  padding: 26px;
}
.capture__form label { display: block; font-weight: 700; font-size: .92rem; color: var(--ink); margin-bottom: 8px; }

.fhead { display: flex; align-items: center; gap: 12px; margin-bottom: 22px; }
/* WhatsApp keeps its own green here and nowhere else on the page. It is a
   destination the owner recognises by colour; every other green is ours. */
.fhead__ico { color: #25D366; flex: none; display: grid; place-items: center; }
.fhead h3 { font-size: 1.14rem; color: var(--forest-deep); letter-spacing: -.02em; }
.fhead p { margin: 2px 0 0; font-size: .84rem; color: var(--ink-50); }

/* Five fields, so they pair up where there is room and stack where there is
   not. Name and email sit together; the rest run full width because a phone
   number, an address and a floor area all read badly when cramped. */
.capture__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.cap-field--wide { grid-column: 1 / -1; }
.cap-field > input,
.wa-field, .suffix-field {
  width: 100%; background: var(--white);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
}
.cap-field > input { outline: none; color: var(--ink); padding: 13px 14px; font: inherit; }
.cap-field > input::placeholder { color: var(--ink-35); }
.cap-field > input:focus-visible,
.wa-field:focus-within, .suffix-field:focus-within {
  outline: 3px solid var(--leaf); outline-offset: 1px; border-color: var(--leaf);
}
.cap-field.is-bad > input,
.cap-field.is-bad .wa-field,
.cap-field.is-bad .suffix-field { border-color: var(--rose); box-shadow: 0 0 0 2px rgba(160, 59, 72, .14); }
/* A field-shaped row that holds a value the owner cannot change. It sits in
   the grid alongside the real inputs so it reads as part of the form, and it
   is deliberately recessed rather than white: an input-white box that refuses
   the cursor is the most annoying control on any form. Tinted, borderless on
   focus, no tab stop — it looks like something to read, which is what it is. */
.cap-field__l {
  display: block; font-weight: 700; font-size: .92rem; color: var(--ink); margin-bottom: 8px;
}
.cap-fixed {
  display: flex; align-items: center; gap: 11px;
  width: 100%; padding: 12px 14px;
  background: var(--mist); border: 1px solid var(--line); border-radius: var(--r-sm);
}
.cap-fixed__ico { flex: none; color: var(--forest); display: grid; place-items: center; }
.cap-fixed__b { min-width: 0; flex: 1; }
.cap-fixed__b b { display: block; font-size: .95rem; color: var(--ink); line-height: 1.35; }
.cap-fixed__b span { display: block; margin-top: 2px; font-size: .81rem; color: var(--ink-50); }
.cap-fixed__tag {
  flex: none; align-self: flex-start;
  padding: 3px 8px; border-radius: 999px;
  background: var(--white); border: 1px solid var(--line);
  font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-50);
}
.cap-hint { margin: 7px 0 0; font-size: .81rem; color: var(--ink-50); line-height: 1.45; }
/* One message per field. Showing the hint and the error together makes the
   owner read two lines to find the one that matters. */
.cap-field.is-bad .cap-hint { display: none; }
.cap-err { margin: 7px 0 0; font-size: .83rem; color: var(--rose); font-weight: 700; }
/* A look-again line, not an error: the size is accepted either way, and amber
   rather than rose says so. */
.cap-note { margin: 7px 0 0; font-size: .83rem; color: var(--amber); font-weight: 700; }

/* Composite fields: the border lives on the wrapper, so the inner input has
   none of its own and must be told its colour explicitly — it once inherited
   white from the forest panel and typed digits vanished. */
.suffix-field, .wa-field { display: flex; overflow: hidden; }
.suffix-field input, .wa-field input {
  flex: 1; min-width: 0; border: 0; outline: none; background: transparent;
  padding: 13px 14px; font: inherit; color: var(--ink);
}
.wa-field input { font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.suffix-field__s, .wa-field__cc {
  display: grid; place-items: center; padding-inline: 14px;
  background: var(--mist); color: var(--ink-70); font-weight: 700;
}
.suffix-field__s { border-left: 1px solid var(--line); }
.wa-field__cc { border-right: 1px solid var(--line); }

/* Consent has to be readable and has to stay out of the button's way. A
   recessed tint does both: present, legible, visibly not the thing to click. */
.consent {
  display: flex; gap: 11px; align-items: flex-start;
  margin-top: 18px; padding: 13px 14px;
  background: var(--mist); border: 1px solid var(--line); border-radius: var(--r-md);
  font-size: .79rem; color: var(--ink-70); line-height: 1.46;
}
.consent input { margin-top: 2px; accent-color: var(--forest); width: 17px; height: 17px; flex: none; }
.consent a { color: var(--forest); text-decoration: underline; }

.btn--wa { background: var(--forest); color: #fff; width: 100%; margin-top: 16px; box-shadow: var(--shadow-cta); }
.btn--wa:hover { background: var(--forest-mid); transform: translateY(-1px); }
.btn--wa:active { transform: translateY(0); }
.capture__fine {
  display: flex; gap: 8px; align-items: flex-start; justify-content: center;
  margin: 13px 4px 0; font-size: .82rem; color: var(--ink-50); line-height: 1.45; text-align: center;
}
.capture__fine svg { flex: none; margin-top: 2px; color: var(--ink-35); }
.capture__err { margin-top: 12px; font-size: .9rem; color: var(--rose); font-weight: 700; }

/* ---- after submit --- */
/* The report is already open above by the time this renders, so the panel's
   job is confirmation, not celebration. One column, no second card. */

.capture--done {
  grid-template-columns: 1fr;
  grid-template-areas: "head" "form";
  text-align: center;
  justify-items: center;
  padding: 34px;
}
/* `text-align: center` on the panel centres the text INSIDE each box; it does
   not centre the box. Both of these are capped blocks narrower than the
   column, so without auto side margins they sat flush left inside a centred
   panel and read as misaligned. */
.capture--done h2 { max-width: 22ch; margin: 14px auto 0; }
.capture--done .capture__sub { max-width: 52ch; margin-inline: auto; }
.sent { margin-top: 22px; padding: 18px 22px; max-width: 460px; }
.sent__ico {
  width: 52px; height: 52px; border-radius: var(--r-pill);
  background: var(--leaf-soft); color: var(--forest);
  display: grid; place-items: center; margin: 0 auto 14px;
}
.sent h3 { font-size: 1.15rem; color: var(--forest-deep); }
.sent p { margin-top: 8px; font-size: .9rem; color: var(--ink-70); }
.sent code { background: var(--mist); border-radius: 4px; padding: 1px 6px; font-size: .86em; }

/* Privacy: what we collect, and why. */
.ptab { width: 100%; border-collapse: collapse; margin: 0 0 22px; font-size: .96rem; }
.ptab th, .ptab td { text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--line); vertical-align: top; }
.ptab th { font-size: .78rem; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-50); border-bottom-color: var(--line-strong); }
.ptab td:first-child { font-weight: 600; white-space: nowrap; }
.ptab tr:last-child td { border-bottom: 0; }
@media (max-width: 640px) {
  .ptab, .ptab tbody, .ptab tr, .ptab td { display: block; width: 100%; }
  .ptab thead { display: none; }
  .ptab tr { padding: 12px 0; border-bottom: 1px solid var(--line); }
  .ptab td { border-bottom: 0; padding: 2px 0; }
  .ptab td:first-child { white-space: normal; }
}

/* --------------------------------------------------------------- debug --- */

.dbg { padding-block: 40px 80px; }
.dbg__state { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 18px; }
.dbg__btns { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
.dbg__pre {
  background: var(--mist); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 16px; overflow: auto; max-height: 420px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .82rem; line-height: 1.6; white-space: pre; margin: 0;
}
.dbg code { background: var(--mist); border-radius: 4px; padding: 1px 6px; font-size: .9em; }

/* the written report generator */
.rpt-lab { display: block; font-size: .86rem; font-weight: 700; color: var(--ink-50); margin-bottom: 6px; }
/* The three ledger boxes on the report builder. A payload is captured before
   the owner touches the loan and CPF fields, so these are the only way a real
   balance reaches a report — editing the JSON by hand leaves the derived
   figures behind and the build refuses. Wraps to one per line on a phone,
   which is where this screen is most often opened. */
.rpt-ledger { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.rpt-ledger__row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.rpt-ledger__row label {
  flex: 1 1 150px; display: flex; flex-direction: column; gap: 5px;
  font-size: .8rem; font-weight: 600; color: var(--ink-50);
}
.rpt-ledger__row .inp { width: 100%; }
.rpt-json {
  width: 100%; resize: vertical; padding: 14px 16px; border-radius: var(--r-md);
  border: 1px solid var(--line); background: var(--mist); color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .8rem; line-height: 1.6; white-space: pre; overflow-wrap: normal;
}
.rpt-json:focus { outline: 2px solid var(--leaf); outline-offset: 1px; background: #fff; }
.rpt-note {
  border: 1px solid var(--line); border-left-width: 4px; border-radius: var(--r-md);
  padding: 14px 16px; margin: 14px 0; background: var(--mist);
}
.rpt-note--bad { border-left-color: #A03B48; background: #FCF3F4; }
.rpt-note--warn { border-left-color: var(--amber); background: #FBF3E7; }
.rpt-note--ok { border-left-color: var(--leaf); background: var(--leaf-soft); }
.rpt-note ul { margin: 10px 0 0 18px; padding: 0; }
.rpt-note li { font-size: .92rem; line-height: 1.6; color: var(--ink-70); }

/* the preview: the report in a document of its own, so printing prints it alone */
body.is-locked { overflow: hidden; }
.rpt-overlay {
  position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column;
  background: #E7EBE4;
}
.rpt-overlay__bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 18px; background: var(--forest); color: #fff;
  font-family: var(--display); font-size: .88rem;
}
.rpt-overlay__sub { opacity: .74; }
.rpt-overlay__sp { flex: 1; }
.rpt-overlay__hint { font-size: .76rem; opacity: .72; font-weight: 400; }
.rpt-overlay .btn { padding: 9px 16px; font-size: .86rem; }
.rpt-overlay .btn--ghost { border-color: rgba(255,255,255,.4); color: #fff; background: transparent; }
.rpt-frame { flex: 1; width: 100%; border: 0; background: #E7EBE4; }

@media (max-width: 720px) {
  .rpt-overlay__hint, .rpt-overlay__sub { display: none; }
}

/* -------------------------------------------------------------- guides --- */

.guides { padding-block: 46px 80px; }
.guide-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 30px; }
.guide-card { text-decoration: none; color: inherit; padding: 24px; display: flex; flex-direction: column; gap: 10px; text-align: left; align-items: flex-start; transition: box-shadow .18s, transform .18s; }
.guide-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-2px); }
.guide-card__tag { font-size: .78rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--leaf-deep); }
.guide-card__t { font-family: var(--display); font-weight: 800; font-size: 1.16rem; letter-spacing: -.012em; }
.guide-card__d { font-size: .96rem; color: var(--ink-50); }

.article { max-width: 720px; margin-inline: auto; padding-block: 40px 90px; }
.article h1 { font-size: clamp(2rem, 4vw, 2.7rem); margin-bottom: 14px; }
.article__meta { color: var(--ink-50); font-size: .95rem; margin-bottom: 34px; }
.article h2 { font-size: 1.42rem; margin-top: 40px; margin-bottom: 12px; }
.article p { margin: 0 0 18px; }
.article ul { margin: 0 0 18px; padding-left: 22px; }
.article li { margin-bottom: 8px; }
.article__box { background: var(--mist); border-left: 3px solid var(--leaf); border-radius: 0 var(--r-md) var(--r-md) 0; padding: 18px 22px; margin: 0 0 22px; }
.article__box p:last-child { margin-bottom: 0; }

/* -------------------------------------------------------------- footer --- */

.foot { border-top: 1px solid var(--line); background: var(--white); padding-block: 38px 44px; }
.foot__cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }
.foot__item { display: flex; gap: 13px; align-items: flex-start; }
.foot__item svg { flex: none; margin-top: 2px; color: var(--ink-35); }
.foot__t { font-weight: 700; font-size: .98rem; }
.foot__d { font-size: .92rem; color: var(--ink-50); margin-top: 3px; }
.foot__legal { margin-top: 34px; padding-top: 24px; border-top: 1px solid var(--line); font-size: .85rem; color: var(--ink-50); display: flex; flex-wrap: wrap; gap: 8px 20px; justify-content: space-between; }
.foot__legal p { margin: 0; max-width: 74ch; }
.foot__nav { display: flex; gap: 18px; }

/* --------------------------------------------------------------- misc --- */

/* `.info` is retired. It rendered a circled "i" whose only explanation lived
   in a `title` attribute, which iOS Safari ignores on tap and Android Chrome
   handles inconsistently — so the text existed for screen readers and desktop
   pointers and for nobody else. Explanations are printed now; see `.why`. */

.stack-gap > * + * { margin-top: 16px; }
.stack-gap-lg > * + * { margin-top: 26px; }

/* The report's sections used to be direct children of `.stack-gap-lg` and got
   their spacing from it. The gate put them inside `#report`, which left the
   ledger card butting straight up against the next heading. Spacing belongs to
   whichever element actually holds the sections. */
#report > * + * { margin-top: 34px; }
#report > section + section { margin-top: 40px; }

/* ---------------------------------------------------------- responsive --- */

@media (max-width: 1024px) {
  .hero__photo { width: 62%; }
  .metrics { grid-template-columns: repeat(3, 1fr); }
  .ledger { grid-template-columns: 1fr; }
  .ledger__inputs { border-right: 0; border-bottom: 1px solid var(--line); }
  .guide-grid { grid-template-columns: repeat(2, 1fr); }
  /* Single column: value first, then the ask, then the reassurance that
     follows it. The privacy panel deliberately sits under the button here —
     it is the last doubt before submitting, not a footnote to the benefits. */
  .capture {
    /* minmax(0, 1fr), not 1fr: an auto minimum lets the widest field inside the
       form set the track width, which pushes the whole block past a 360px
       viewport. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "head" "bens" "form" "guard";
    padding: 34px;
  }
  .capture__form { margin-top: 30px; }
  .capture__guard { margin-top: 20px; }
}

@media (max-width: 860px) {
  body { font-size: 16px; }
  .mast__logo img { width: 178px; }
  .badge-free { font-size: 13px; padding: 9px 13px; }

  .hero { padding-top: 26px; }
  .hero__inner { max-width: none; padding-top: 8px; }
  /* On a phone the photo returns to the document flow, after the trust points,
     per the fixed mobile stacking order. It keeps its baked-in fade and gets no
     rounded frame — a card edge would reintroduce exactly the hard boundary the
     artwork exists to avoid. Bled to the full viewport width, past the gutter. */
  .hero__photo {
    position: relative; top: 0; right: auto;
    width: calc(100% + var(--gutter) * 2);
    max-width: none;
    margin: 30px calc(var(--gutter) * -1) 0;
    overflow: hidden;
    /* The artwork's first pixel row sits a shade off --paper, which shows as a
       faint rule where the photo starts. A short fade dissolves it. */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 9%, #000 100%);
    mask-image: linear-gradient(to bottom, transparent 0, #000 9%, #000 100%);
  }
  /* The left half of the artwork is empty sky, which at 390px leaves the towers
     too small to read. Oversize the image and pull it left so the phone shows
     the building side of the frame. The slice that lands at the left edge is
     already faded to the page base, so no new hard edge is introduced. */
  /* max-width must be released explicitly — the global `img { max-width: 100% }`
     would otherwise silently cap this back to the container width. */
  .hero__photo img { width: 178%; max-width: none; margin-left: -78%; }
  .hero__sub { max-width: none; }

  .finder__bar { flex-direction: column; }
  .field input { padding: 17px 16px; }
  .btn { padding: 17px 24px; }

  .trust { gap: 16px; flex-direction: column; }

  .assure { grid-template-columns: 1fr; text-align: left; padding: 20px; gap: 18px; margin-block: 40px 56px; }
  .assure__art { width: 150px; }
  .assure__fact { padding-left: 0; border-left: 0; border-top: 1px solid var(--line-strong); padding-top: 14px; max-width: none; }

  .val { grid-template-columns: 1fr; gap: 22px; }
  .metrics { grid-template-columns: 1fr; }
  .psum { grid-template-columns: 1fr; }
  .psum__img { aspect-ratio: 16 / 9; }
  .pair { grid-template-columns: 1fr; }
  .guide-grid { grid-template-columns: 1fr; }
  .foot__cols { grid-template-columns: 1fr; gap: 18px; }
  .card--pad, .ledger__body, .ledger__inputs, .panel { padding: 20px; }
  .capture { padding: 26px 20px; }
  .capture__sub { font-size: 1rem; }
  .capture__bens { margin-top: 22px; }
  .ben { grid-template-columns: 34px minmax(0, 1fr); gap: 12px; padding: 13px 0; }
  .ben__ico { width: 34px; height: 34px; }
  .ben__ico svg { width: 17px; height: 17px; }
  .ben__t { font-size: .98rem; }
  .ben__d { font-size: .88rem; }
  .capture__form { padding: 18px; margin-top: 26px; }
  .capture__grid { grid-template-columns: 1fr; gap: 14px; }
  .capture--done { padding: 26px 20px; }

  .locked__over { padding: 30px 18px; }
  .locked__over > p { font-size: .95rem; }

  /* Five columns is unreadable at 390px. Each row becomes a small card and the
     column headings move inline as labels. */
  .txn--head { display: none; }
  .txn {
    grid-template-columns: 1fr; gap: 5px;
    padding: 16px 0; border-bottom: 1px solid var(--line);
  }
  .txn__c { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
  .txn__c::before {
    content: attr(data-l);
    font-size: .82rem; color: var(--ink-50); font-weight: 600;
    font-variant-numeric: normal;
  }
  .txn__c--addr { grid-column: 1 / -1; flex-direction: column; align-items: flex-start; gap: 2px; }
  .txn__c--addr::before { order: -1; }
  .txn__tag { margin-left: 0; }
  .txn--own .txn__c:first-child { padding-left: 0; }
  .txn--own .txn__c:last-child { padding-right: 0; }
  .txn--own { background: none; }
  .txn--own .txn__c--addr { border-left: 3px solid var(--leaf); padding-left: 10px; }
  .rail__row { gap: 6px; font-size: .85rem; }
  .rail__step span:not(.rail__pip) { display: none; }
  .rail__step.is-now span:not(.rail__pip) { display: inline; }
  .result { padding-block: 26px 60px; }
  .move__art { display: none; }

  /* The arithmetic reads better as a stacked statement on a narrow screen. */
  .sum { display: grid; grid-template-columns: 1fr; gap: 0; margin-top: 22px; }
  .sum__op { display: none; }
  .sum__pre { display: inline; }
  .sum__cell {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 14px; min-width: 0; padding: 10px 0; border-bottom: 1px solid var(--mist);
  }
  .sum__cell:last-child { border-bottom: 0; padding-bottom: 0; }
  .sum__v { margin-top: 0; }
  .sum__cell--out { margin-top: 4px; padding-top: 14px; border-top: 1px solid var(--line); }

  .stack__seg > span { display: none; }
}


/* ---------------------------------------------------- total resources --- *
 * A recessed summary of the bar above it, so the two read as one thought.
 * The cash and CPF cells borrow their colours from the ledger segments they
 * correspond to — that is the whole reason the split is legible at a glance.
 */

.res {
  margin-top: 22px; padding: 22px 24px;
  background: var(--mist); border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.res__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 18px; flex-wrap: wrap;
}
.res__k { font-size: .95rem; font-weight: 600; color: var(--ink-70); }
.res__v {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.9rem, 4.4vw, 2.5rem); letter-spacing: -.022em;
  color: var(--forest); line-height: 1.05;
}
.res__split {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 18px;
}
.res__cell {
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 14px 16px; border-left-width: 3px;
}
.res__cell--cash { border-left-color: var(--forest); }
.res__cell--cpf  { border-left-color: var(--leaf); }
.res__ck { font-size: .82rem; font-weight: 600; color: var(--ink-50); }
.res__cv {
  font-family: var(--display); font-weight: 700;
  font-size: 1.35rem; margin-top: 3px; color: var(--ink);
}
.res__cell--cash .res__cv { color: var(--forest); }
.res__cell--cpf  .res__cv { color: var(--leaf-deep); }
.res__cd { font-size: .8rem; color: var(--ink-50); margin-top: 4px; }
.res__note { font-size: .88rem; color: var(--ink-70); margin-top: 16px; line-height: 1.6; }

/* --------------------------------------------------------- readiness --- *
 * Five rows, each carrying the figure it judged. The verdict chip is the
 * only coloured element: the row itself stays on paper, because a row tinted
 * amber reads as an alarm rather than an observation.
 */

.ready__row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 18px; align-items: start;
  padding: 18px 0; border-bottom: 1px solid var(--mist);
}
.ready__row:first-child { padding-top: 0; }
.ready__row:last-child { border-bottom: 0; padding-bottom: 0; }
.ready__label {
  font-family: var(--display); font-weight: 700;
  font-size: 1rem; color: var(--ink);
}
.ready__live {
  margin-left: 8px; padding: 2px 7px; border-radius: var(--r-pill);
  background: var(--leaf-soft); color: var(--leaf-deep);
  font-family: var(--body);
  font-size: .68rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; vertical-align: 2px;
}
/* The question the row is a check of. It reads before the figure, because the
   figure is the answer and an answer arriving before its question is a fact
   the reader has to find a use for. */
.ready__q { font-size: .88rem; color: var(--ink-50); margin-top: 3px; font-style: italic; }
.ready__input { font-size: .95rem; color: var(--ink-70); margin-top: 5px; }
.ready__note { font-size: .88rem; color: var(--ink-50); margin-top: 7px; line-height: 1.6; max-width: 62ch; }
/* Says out loud what the pill's `title` used to whisper. A title attribute
   does nothing on a tap, so on a phone the two live rows gave no sign at all
   that they answer to the ledger inputs. */
.ready__live-note { font-size: .82rem; color: var(--ink-40, var(--ink-50)); margin-top: 5px; font-style: italic; }
.ready__chip {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 7px 13px; border-radius: var(--r-pill);
  font-size: .85rem; font-weight: 700;
  border: 1px solid var(--line); background: var(--white); color: var(--ink-70);
}
.ready__chip--strong   { background: var(--leaf-soft); border-color: #CFE0BC; color: var(--forest); }
.ready__chip--moderate { background: var(--mist); border-color: var(--line-strong); color: var(--ink-70); }
.ready__chip--watch    { background: #FBF2E6; border-color: #E8D3B4; color: var(--amber); }
.ready__chip--none     { background: var(--white); border-color: var(--line-strong); color: var(--ink-50); }

/* ---------------------------------------------------------- handover --- *
 * The one place a person appears. Paper, not a green panel: the same lesson
 * the unlock card learned, for the same reason. The WhatsApp button is the
 * only saturated colour in the block.
 */

.hand {
  margin-top: 44px; padding: 36px 40px;
  border: 1px solid var(--line); border-radius: var(--r-xl);
  box-shadow: var(--shadow-sm);
  background:
    radial-gradient(110% 75% at 100% 0%, var(--leaf-soft) 0%, rgba(234, 242, 225, 0) 58%),
    var(--white);
  display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: 36px; align-items: start;
}
.hand__photo { border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow-sm); }
/* Desktop shows the portrait whole — no crop, so the figure reads full length
 * beside the greeting. The aspect-ratio holds the box before the file lands,
 * so the text column does not jump when it does. */
.hand__photo img { width: 100%; height: auto; aspect-ratio: 720 / 1160; object-fit: cover; }
.hand__eyebrow {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .78rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--leaf-deep);
}
.hand__h {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(1.5rem, 3.4vw, 1.95rem); letter-spacing: -.022em;
  color: var(--ink); margin: 10px 0 14px;
}
.hand__p { font-size: .97rem; color: var(--ink-70); line-height: 1.65; margin-bottom: 12px; max-width: 62ch; }
.hand__promise {
  display: flex; gap: 12px; align-items: flex-start;
  margin: 18px 0; padding: 14px 16px;
  background: var(--mist); border: 1px solid var(--line); border-radius: var(--r-md);
  font-size: .92rem; color: var(--ink-70); line-height: 1.55;
}
.hand__promise > svg { color: #25D366; flex: 0 0 auto; margin-top: 1px; }
.hand__cmts { list-style: none; margin: 18px 0 24px; display: grid; gap: 12px; }
.hand__cmts li { display: flex; gap: 11px; align-items: flex-start; }
.hand__cmts b { display: block; font-size: .93rem; color: var(--ink); font-weight: 700; }
.hand__cmts span { display: block; font-size: .87rem; color: var(--ink-50); line-height: 1.55; margin-top: 2px; }
.hand__tick {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; margin-top: 1px;
  background: var(--leaf-soft); color: var(--forest);
}
.hand__cta { display: inline-flex; text-decoration: none; }
.hand__cea {
  margin-top: 16px; font-size: .78rem; color: var(--ink-50); line-height: 1.5;
}

/* ------------------------------------------------------- chapter nav --- *
 * Three chapters, not twelve steps. A twelve-item breadcrumb is unreadable
 * on a phone by the fifth item, and this report has three movements anyway:
 * the numbers, the options, the plan.
 */

.chapters {
  position: sticky; top: 0; z-index: 20;
  margin: 0 0 8px; padding: 10px 0;
  background: rgba(252, 252, 250, .92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
.chapters__row { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
.chapters__row::-webkit-scrollbar { display: none; }
.chapters a {
  flex: 0 0 auto; padding: 8px 15px; border-radius: var(--r-pill);
  border: 1px solid var(--line); background: var(--white);
  font-size: .87rem; font-weight: 600; color: var(--ink-70); text-decoration: none;
  white-space: nowrap;
}
.chapters a:hover { border-color: var(--line-strong); color: var(--ink); }
.chapters a.is-here { background: var(--forest); border-color: var(--forest); color: #fff; }

@media (max-width: 860px) {
  .res { padding: 18px; }
  .res__split { grid-template-columns: 1fr; }
  .ready__row { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .ready__verdict { order: -1; }
  .hand { grid-template-columns: minmax(0, 1fr); gap: 24px; padding: 26px; }
  /* Stacked on a phone a full-length figure would push the copy off the fold,
   * so mobile keeps a cropped band framed on the head and torso. */
  .hand__photo img { aspect-ratio: auto; height: 300px; object-position: 50% 12%; }
  .hand__cta { width: 100%; justify-content: center; }
}

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

/* ------------------------------------------------- ten-year cluster trend ---
   One chart, three lines, drawn as inline SVG against the tokens above.

   The palette is not extended here. The owner's own cluster is the only
   saturated stroke on the block, the town is ink-35 and the national line is
   a hairline dash — the same discipline the unlock card uses to give the eye
   exactly one place to go. No fourth colour, and no second flourish: the
   ledger keeps that job.                                                    */

.tr__card { margin-top: 4px; }

/* Clears the sticky chapter bar when a section is reached from the nav.
   `scrollIntoView({block: 'start'})` puts the section top at y = 0, which is
   underneath a 60px sticky bar — so tapping "Where you stand" landed the
   reader mid-sentence in the summary, with the heading hidden. Only the trend
   carried this rule; the other four targets need it too. */
#sec-ledger,
#sec-trend,
#sec-readiness,
#sec-moves,
#sec-handover { scroll-margin-top: 76px; }

.tr__bar {
  display: flex; flex-wrap: wrap; gap: 14px;
  align-items: flex-start; justify-content: space-between;
  margin-bottom: 18px;
}
.tr__meta { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.tr__meta b { font-family: var(--display); font-size: 1.06rem; letter-spacing: -.018em; }
.tr__meta span { font-size: .88rem; color: var(--ink-50); }

.seg--sm .seg__opt { padding: 8px 14px; font-size: .88rem; }
.seg__opt.is-on { background: var(--forest); border-color: var(--forest); color: #fff; }

.tr__plot { position: relative; }
.tr__svg {
  /* Width and height come from the markup, sized to the measured plot in
     js/trends.js, so the drawing is 1:1 with CSS pixels. `height: auto` is
     required here: the global img/svg rule would otherwise hold the attribute
     height while width was constrained, which is the same trap the family
     illustration fell into. */
  display: block; max-width: 100%; height: auto;
  overflow: visible; touch-action: pan-y;
}

.tr__grid   { stroke: var(--line); stroke-width: 1; vector-effect: non-scaling-stroke; }
.tr__base   { stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 2 3; vector-effect: non-scaling-stroke; }
.tr__cursor { stroke: var(--line-strong); stroke-width: 1; vector-effect: non-scaling-stroke; transition: opacity .12s; }
.tr__tick   { fill: var(--ink-35); font-size: 11px; font-variant-numeric: tabular-nums; }

.tr__line { fill: none; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.tr__line--cluster { stroke: var(--forest);     stroke-width: 2.6; }
.tr__line--town    { stroke: var(--ink-35);     stroke-width: 1.6; }
.tr__line--nat     { stroke: var(--line-strong); stroke-width: 1.6; stroke-dasharray: 5 4; }
.tr__dot--cluster  { fill: var(--forest); }
.tr__dot--town     { fill: var(--ink-35); }
.tr__dot--nat      { fill: var(--line-strong); }
.tr__hit           { fill: transparent; cursor: crosshair; }

/* The readout is a strip under the chart, not a floating card over it. A
   floating card sat on the y-axis at some cursor positions and under the
   thumb that summoned it at others; a strip cannot collide with anything and
   reads the same on a phone as on a desktop. */
.tr__read {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 20px;
  margin-top: 14px; padding: 12px 14px;
  background: var(--mist); border-radius: var(--r-md);
  min-height: 62px;
}
.tr__rt { flex: 1 0 100%; font-size: .82rem; color: var(--ink-50); }
.tr__rg { display: flex; flex-wrap: wrap; gap: 4px 20px; }
.tr__r { display: inline-flex; align-items: baseline; gap: 7px; position: relative; padding-left: 17px; }
.tr__r::before {
  content: ''; position: absolute; left: 0; top: .5em; width: 12px; height: 2px; border-radius: 2px;
}
/* A key is only a key if the mark in it is the mark on the chart. All HDB is
   drawn dashed (5 4) and its swatch was a solid bar, so the one line a reader
   most needed to identify was the one the key mis-described. The gradient
   reproduces the dash at the swatch's scale; the widths track the stroke
   weights, 2.6 / 1.6 / 1.6. */
.tr__r--cluster::before { background: var(--forest); height: 3px; }
.tr__r--town::before    { background: var(--ink-35); }
.tr__r--nat::before     {
  background: repeating-linear-gradient(to right,
    var(--line-strong) 0 3.5px, transparent 3.5px 6px);
  border-radius: 0;
}
.tr__rk { font-size: .86rem; color: var(--ink-70); }
.tr__rv { font-size: .95rem; font-weight: 700; }

.tr__rp { font-weight: 400; color: var(--ink-50); font-size: .86em; }

/* The chart's own instructions. It carries three lines, two views and a
   rebased axis, and every one of those was left to be worked out from the
   shapes. Cheap to print, and it sits directly under the thing it explains. */
.tr__how {
  margin-top: 12px; padding: 13px 15px;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-md);
}
.tr__how > b { display: block; font-size: .84rem; letter-spacing: .01em; color: var(--forest-deep); margin-bottom: 5px; }
.tr__how p { margin: 0; font-size: .87rem; line-height: 1.6; color: var(--ink-70); }
.tr__how-tip { margin-top: 7px !important; color: var(--ink-50) !important; font-size: .82rem !important; }

.tr__cap {
  margin: 12px 0 0; font-size: .87rem; line-height: 1.55; color: var(--ink-50);
}

.tr__verdict {
  margin: 16px 0 0;
  padding: 14px 16px;
  background: var(--mist);
  border-radius: var(--r-md);
  font-size: .97rem; line-height: 1.55;
}

.tr__pick { margin-top: 18px; }
.tr__pick-l { display: block; font-size: .86rem; color: var(--ink-50); margin-bottom: 9px; }
.tr__chips { display: flex; flex-wrap: wrap; gap: 7px; }
.chip--pick {
  border: 1px solid var(--line-strong); background: var(--white);
  color: var(--ink-70); cursor: pointer; transition: all .14s;
  display: inline-flex; align-items: center; gap: 6px;
}
.chip--pick:hover { border-color: var(--leaf); color: var(--ink); }
.chip--pick.is-on { background: var(--forest); border-color: var(--forest); color: #fff; }
.chip__you {
  font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  background: var(--leaf-soft); color: var(--forest); border-radius: var(--r-pill); padding: 1px 6px;
}
.chip--pick.is-on .chip__you { background: rgba(255,255,255,.22); color: #fff; }

/* The masked stand-in behind the gate. No axis labels, no plotted points and
   no numbers of any kind — a shape that reads as "a chart lives here" and
   leaks nothing if the blur is lifted. */
.tr__skel {
  height: 150px; border-radius: var(--r-sm);
  background:
    linear-gradient(var(--line) 1px, transparent 1px) 0 0 / 100% 37.5px,
    linear-gradient(100deg, var(--mist) 0 42%, var(--leaf-soft) 42% 100%);
}

@media (max-width: 640px) {
  .tr__skel { height: 120px; background-size: 100% 30px, auto; }
  .tr__bar { flex-direction: column; gap: 12px; }
  .tr__modes { width: 100%; }
  .seg--sm .seg__opt { flex: 1; text-align: center; }
  .tr__read { gap: 4px 14px; }
  .tr__rg { gap: 4px 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .tr__read, .tr__cursor, .chip--pick, .seg--sm .seg__opt { transition: none; }
}

/* --- What you could buy next: one band, then the routes ------------------ */
/* Replaces the four-card grid. The grid printed one funds figure four times
   over — the band is derived from funds alone, so three of the four cards were
   always identical and the fourth differed only above a cap that has since been
   removed. The value was never in the numbers but in what separates the routes,
   so the number is stated once and the routes carry the differences. */
/* One tint for every price, never two. A second colour would read as a second
   meaning — an owner would take the capped figure for a warning rather than
   simply a lower price. Same tint twice says they are both prices. */
.nh-band { margin-top: 4px; padding: 16px 18px; background: var(--mist);
  border-radius: var(--r-lg); }
.nh-band__k { font-size: .86rem; color: var(--ink-50); }
.nh-band__v { font-family: var(--display); font-weight: 800; font-size: 2rem; margin-top: 2px;
  font-variant-numeric: tabular-nums; letter-spacing: -.014em; }
.nh-band__note { font-size: .88rem; color: var(--ink-70); line-height: 1.5; margin: 8px 0 0;
  max-width: 54ch; }
/* An aside on the number above, marked by italics alone. It carries no rule,
   because the rule now means one thing only: the cash constraint. */
.nh-caution { font-size: .88rem; color: var(--ink-70); line-height: 1.5; margin: 14px 0 0;
  max-width: 56ch; font-style: italic; }
.routes { margin-top: 20px; border-top: 1px solid var(--line); }
.route { display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto auto;
  gap: 2px 16px; align-items: baseline; padding: 14px 0; border-bottom: 1px solid var(--line); }
.route__h { grid-column: 1; grid-row: 1; display: flex; align-items: baseline; gap: 10px;
  flex-wrap: wrap; }
.route__t { font-family: var(--display); font-weight: 800; font-size: 1rem; }
.route--resale .route__t { color: var(--slate); }
.route--launch .route__t { color: var(--violet); }
/* Four distinct hues, none of them amber — amber belongs to the cash
   constraint alone. The EC keeps the forest it always had; Resale HDB takes
   olive, which clears contrast at 5.90:1 and sits ΔE 27 from forest. */
.route--ec     .route__t { color: var(--forest); }
.route--hdb    .route__t { color: var(--olive); }
.route__fig { font-weight: 700; font-size: .92rem; font-variant-numeric: tabular-nums;
  background: var(--amber-soft); color: var(--amber); border-radius: 6px; padding: 2px 8px; }
.route__d { grid-column: 1; grid-row: 2; font-size: .88rem; color: var(--ink-70);
  line-height: 1.45; max-width: 52ch; }
.route__s { grid-column: 2; grid-row: 1 / span 2; align-self: center; font-size: .82rem;
  color: var(--amber); white-space: nowrap; text-align: right; }
/* The tick marks a route with no cash constraint. --leaf is a fill colour, not
   a text colour, which is fine here: graphics need 3:1 and it clears at 3.39:1
   where text would need 4.5:1. */
.route__ok { width: 20px; height: 20px; color: var(--leaf); display: block;
  margin-left: auto; }
/* Dim the route itself, never its status. The label carries the link to the
   explanation below and has to stay legible — fading it defeats the cue. */
.route.is-shut .route__h,
.route.is-shut .route__d { opacity: .5; }
.nh-why { font-size: .88rem; color: var(--ink-70); line-height: 1.5; margin: 16px 0 0;
  max-width: 60ch; padding-left: 14px; border-left: 3px solid var(--amber); }
.nh-why b { color: var(--amber); font-weight: 700; }
.nh-close { margin-top: 22px; padding: 16px 18px; background: var(--mist);
  border-radius: var(--r-lg); }
.nh-close__h { font-family: var(--display); font-weight: 800; font-size: 1.02rem; }
.nh-close__p { font-size: .9rem; color: var(--ink-70); line-height: 1.55; margin: 6px 0 0;
  max-width: 62ch; }
.nh-why + .nh-why { margin-top: 10px; }
@media (max-width: 560px) {
  .route { grid-template-columns: 1fr; grid-template-rows: auto auto auto; }
  .route__s { grid-column: 1; grid-row: 3; margin-top: 4px; text-align: left; }
}

/* The commitments are a description of how a sale would be run, not of anything
   happening today. Without a heading they land straight after the WhatsApp line
   and read as though the reader has already engaged an agent. The PDF has
   carried this framing since page 7; the site had none. */
.hand__cmts-h {
  margin: 18px 0 2px; font-family: Figtree, sans-serif; font-weight: 700;
  font-size: .95rem; color: var(--ink);
}
.hand__cmts-note { margin-top: 12px; font-size: .82rem; color: var(--ink-50); line-height: 1.55; }
