/* Wiseman Residential — shared base. Token-agnostic: every colour here comes from a
   custom property a direction must define. See CONVENTIONS.md. */

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

:root {
  --vh100: 100vh;
  --ease: cubic-bezier(.22,.61,.36,1);
  --pad: clamp(20px, 5vw, 92px);

  /* ---- quiet ink: two AA-safe stops below --ink -------------------------
     The shared sheets used to set secondary text as a raw percentage of the
     ink — 46% to 68% — and the SAME percentage lands in a different place in
     every direction, because the headroom between ink and ground is not the
     same twice: deep teal on cream is 8.68:1 end to end, near-black on white
     is 17.65:1, cream on near-black is 15.84:1. At 58% that is 3.07:1 on
     Clerestory's cream and 5.80:1 on Nocturne's black — one fails AA, the
     other is barely quiet at all. So the percentage is not the token: the
     COLOUR is, and each direction sets the pair against its own ground.

       --ink-quiet  secondary body text — the card facts, an empty-state
                    paragraph, an editorial standfirst.  AA >= 4.5:1.
       --ink-mute   the quietest stop that is still text — facet labels,
                    counts, addresses, tags, the rail readout, placeholders.
                    Also AA >= 4.5:1; small text gets no discount.

     The defaults below are measured for the WORST case (Clerestory's cream:
     76% = 4.73:1, 82% = 5.51:1) so an un-tuned direction still passes.
     --paper-quiet / --paper-mute are the same pair for light type on a dark
     band, where a percentage of a LIGHT ink behaves the other way round. */
  --ink-quiet:   color-mix(in srgb, var(--ink) 82%, transparent);
  --ink-mute:    color-mix(in srgb, var(--ink) 76%, transparent);
  --paper-quiet: color-mix(in srgb, var(--paper) 88%, transparent);
  --paper-mute:  color-mix(in srgb, var(--paper) 80%, transparent);
}
@supports (height: 100svh) { :root { --vh100: 100svh; } }

html {
  /* clip, never hidden — hidden creates a scroll container and kills position:sticky */
  overflow-x: clip;
  -webkit-text-size-adjust: 100%;
  scrollbar-width: thin;
}
body {
  overflow-x: clip;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
::selection { background: color-mix(in srgb, var(--ink) 88%, transparent); color: var(--paper); }

/* ---- gutter. LONGHAND only on anything that also carries .wrap ---- */
.wrap { width: 100%; padding-left: var(--pad); padding-right: var(--pad); }
.wrap-n { max-width: 1560px; margin-left: auto; margin-right: auto; }
.measure { max-width: 62ch; }

/* ---- a11y ---- */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 99999;
  background: var(--ink); color: var(--paper);
  padding: 12px 18px; font-size: .82rem; letter-spacing: .08em; text-transform: uppercase;
}
.skip-link:focus { left: 12px; top: 12px; }
/* The ring follows the control's OWN shape. This rule used to set
   `border-radius: 1px` on the focused element, which out-specified
   `.rail-btn{border-radius:50%}` and squared off every circular rail arrow the
   moment the keyboard reached it — the ring announcing focus also changed the
   thing it was pointing at. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--focus, var(--ink)); outline-offset: 3px;
}
.vh {
  position: absolute !important; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
[hidden] { display: none !important; }

/* ---- reveals. Content is visible unless JS confirms itself. ---- */
.js .rv { opacity: 0; transform: translateY(18px); }
.js .rv.in { opacity: 1; transform: none; transition: opacity .9s var(--ease), transform .9s var(--ease); }
.js .rv-d1.in { transition-delay: .08s; }
.js .rv-d2.in { transition-delay: .16s; }
.js .rv-d3.in { transition-delay: .24s; }
/* image reveals paint a beat earlier than text so nothing pops in empty */
.js .rvi { clip-path: inset(0 0 8% 0); opacity: 0; }
.js .rvi.in { clip-path: inset(0 0 0 0); opacity: 1; transition: clip-path 1.1s var(--ease), opacity .7s var(--ease); }

/* ---- numbers ---- */
.tnum { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

/* ---- header shell (each direction skins it) ---- */
.hd {
  position: fixed; inset: 0 0 auto 0; z-index: 900;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding-top: 18px; padding-bottom: 18px;
  transition: transform .42s var(--ease), background-color .3s var(--ease),
              backdrop-filter .3s var(--ease), box-shadow .3s var(--ease);
}
.hd.up { transform: translateY(-102%); }
.hd.frost {
  background: color-mix(in srgb, var(--paper) 84%, transparent);
  backdrop-filter: blur(14px) saturate(1.1);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--ink) 12%, transparent);
}
.hd:focus-within { transform: none !important; }
.brand { display: inline-flex; align-items: center; gap: 12px; flex: 0 0 auto; }
.brand svg { width: 26px; height: 26px; flex: 0 0 auto; }
.brand b { font-weight: 500; letter-spacing: .26em; font-size: .74rem; text-transform: uppercase; white-space: nowrap; }
.hnav { display: flex; align-items: center; gap: clamp(14px, 2vw, 34px); }
.hnav a { font-size: .76rem; letter-spacing: .14em; text-transform: uppercase; position: relative; padding: 6px 0; white-space: nowrap; }
.hnav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform .4s var(--ease);
}
.hnav a:hover::after, .hnav a:focus-visible::after, .hnav a[aria-current]::after { transform: scaleX(1); }
@media (max-width: 900px) { .hnav { display: none; } }

/* ---- mobile menu ---- */
.mbtn { display: none; width: 42px; height: 42px; align-items: center; justify-content: center; }
.mbtn span { display: block; width: 22px; height: 1px; background: currentColor; position: relative; transition: background .2s; }
.mbtn span::before, .mbtn span::after {
  content: ""; position: absolute; left: 0; width: 22px; height: 1px; background: currentColor;
  transition: transform .38s var(--ease);
}
.mbtn span::before { top: -6px; } .mbtn span::after { top: 6px; }
.mbtn[aria-expanded="true"] span { background: transparent; }
.mbtn[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.mbtn[aria-expanded="true"] span::after { transform: translateY(-6px) rotate(-45deg); }
@media (max-width: 900px) { .mbtn { display: inline-flex; } }
.mnav {
  position: fixed; inset: 0; z-index: 950; background: var(--deep, var(--ink)); color: var(--paper);
  display: flex; flex-direction: column; justify-content: center;
  padding-left: var(--pad); padding-right: var(--pad);
  opacity: 0; visibility: hidden; transition: opacity .42s var(--ease), visibility .42s;
}
.mnav.open { opacity: 1; visibility: visible; }
.mnav a { display: block; font-family: var(--serif, var(--sans)); font-size: clamp(1.9rem, 8vw, 3.2rem); line-height: 1.18; padding: 6px 0; opacity: 0; transform: translateY(16px); }
.mnav.open a { opacity: 1; transform: none; transition: opacity .5s var(--ease), transform .5s var(--ease); }
.mnav .mfoot { margin-top: 40px; font-size: .82rem; letter-spacing: .1em; opacity: .72; }

/* ---- page-transition curtain ---- */
.pt {
  position: fixed; inset: 0; z-index: 100000; background: var(--deep, var(--ink));
  transform: translateY(100%); pointer-events: none;
  display: grid; place-items: center;
}
.js-pt .pt { transform: translateY(0); }
.js-pt .pt.reveal { transform: translateY(-100%); transition: transform .8s var(--ease) .35s; }
.pt.cover { transform: translateY(0); transition: transform .55s var(--ease); }
.pt .ptmark { color: var(--paper); display: grid; justify-items: center; gap: 14px; opacity: 0; }
.pt.cover .ptmark, .js-pt .pt:not(.reveal) .ptmark { opacity: 1; transition: opacity .45s var(--ease) .14s; }

/* ---- footer floor ---- */
.eho { display: inline-flex; align-items: center; gap: 10px; }
.eho svg { width: 26px; height: auto; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .rv, .js .rvi { opacity: 1 !important; transform: none !important; clip-path: none !important; transition: none !important; }
  .hd { transition: background-color .3s linear; }
  .hd.up { transform: none; }
  .pt, .pt.cover, .pt.reveal { transition: none; }
  .js-pt .pt { transform: translateY(-100%); }
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; }
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
