/* ============================================================
   localhost.mv — page layout.

   One screen, no scroll. Every vertical dimension is a
   clamp(min, <vh>, max): on a tall viewport the page renders at the
   original design sizes, and on a short one it compresses to fit
   rather than pushing the footer below the fold. The mins are the
   floor of legibility — below ~560px of viewport height the page
   scrolls instead of shrinking further.

   Desktop and mobile variants of the original design are one
   document here, split at 1100 / 900 / 620 / 380px.
   ============================================================ */

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

html {
  background: var(--bg-0);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg-0);
  color: var(--fg-1);
  font-family: var(--mono);
  font-size: var(--fs-body);
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
}

/* main takes the slack; space-between shares it out between the sections so a
   tall viewport breathes evenly instead of pooling one gap above the footer.
   When content exceeds the fold this degrades to flex-start. */
.page {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

a {
  color: var(--blue-bright);
  text-decoration: none;
  border-bottom: 1px dotted var(--slate);
  transition: color 100ms ease-in-out, border-color 100ms ease-in-out;
}
a:hover,
a:focus-visible {
  color: var(--phthalo-vivid);
  border-bottom-color: var(--phthalo-bright);
}
:focus-visible {
  outline: 1px solid var(--phthalo-vivid);
  outline-offset: 2px;
}

/* Every dither surface. Backing store is small; upscale without smoothing. */
canvas[data-dither] {
  display: block;
  image-rendering: pixelated;
}

.shell {
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 var(--s-8);
}

/* ---------- masthead: flowing dither band + wordmark plate ---------- */

.masthead {
  position: relative;
  overflow: hidden;
  width: 100%;
  flex: none;
}
.masthead__band {
  width: 100%;
  height: clamp(84px, 12vh, 168px);
}
.masthead__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
}
.masthead__overlay .shell {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-6);
}
/* Text never sits directly on a dither field — always on a solid plate. */
.masthead__plate {
  background: var(--bg-1);
  border: 1px solid #000;
  padding: clamp(8px, 1.4vh, 12px) var(--s-5);
  display: flex;
  flex-direction: column;
  gap: clamp(2px, 0.6vh, 5px);
}
/* Credential marks — a bare left-aligned row beneath the profile. No plate, no
   border, no captions: the badge silhouette is filled with page black under the
   dither (see `inShape` in dither.js) so each mark reads on its own. */
.marks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(2px, 0.5vh, 5px);
  margin-top: clamp(10px, 2vh, 20px);
}
.marks canvas {
  width: clamp(72px, 11.2vh, 115px);
  height: clamp(72px, 11.2vh, 115px);
  flex: none;
}

.masthead__name {
  font-size: clamp(19px, 3vh, 26px);
  font-weight: 700;
  color: var(--fg-0);
  letter-spacing: var(--tracking-tight);
  line-height: 1.1;
  margin: 0;
}
.masthead__role {
  font-size: clamp(11px, 1.4vh, 12px);
  color: var(--fg-2);
  letter-spacing: 0.06em;
}

/* ---------- sections ---------- */

.section {
  padding-top: clamp(10px, 2.4vh, 36px);
  flex: none;
}
/* ---------- profile + globe ---------- */

.profile {
  display: grid;
  grid-template-columns: 1.9fr 1fr;
  gap: var(--s-5);
}
.profile__lead {
  margin: clamp(7px, 1.4vh, 14px) 0 clamp(7px, 1.2vh, 12px);
  max-width: 92ch;
  font-size: clamp(14px, 2.1vh, 18px);
  line-height: 1.45;
  text-wrap: pretty;
}
.profile__list {
  display: grid;
  gap: clamp(4px, 1vh, 10px);
  max-width: 108ch;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: clamp(12px, 1.6vh, 14px);
}
.profile__list li {
  display: grid;
  grid-template-columns: 14px 1fr;
  gap: 10px;
  line-height: 1.5;
}
.profile__list li::before {
  content: "\25B8"; /* ▸ — the brand's hire-list bullet */
  color: var(--phthalo-vivid);
}
.profile__globe {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  padding: clamp(2px, 0.8vh, 6px) 0;
}
.profile__globe canvas {
  width: clamp(150px, 30vh, 320px);
  height: clamp(150px, 30vh, 320px);
}

/* ---------- contact ---------- */

/* Contact + footer form one flex child of .page, so the page's space-between
   leaves its gap above the pair rather than between them. */
.tail {
  flex: none;
}

/* Marker on the left, marks on the right, sitting directly on the footer rule. */
.reach-row {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  padding-bottom: clamp(8px, 1.4vh, 14px);
}

.reach {
  display: flex;
  align-items: flex-end;
  gap: clamp(10px, 1.6vh, 18px);
  list-style: none;
  margin: 0;
  padding: 0;
}
.reach__link {
  position: relative;
  display: block;
  color: var(--fg-2);
  border-bottom: 0;
}
/* Hover is a colour swap only — no motion, per the brand's link state. */
.reach__link:hover,
.reach__link:focus-visible {
  color: var(--phthalo-vivid);
  border-bottom: 0;
}

.reach__icon {
  width: clamp(26px, 3.6vh, 34px);
  height: clamp(26px, 3.6vh, 34px);
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: square;
  stroke-linejoin: miter;
  transition: color 120ms ease-in-out;
}

/* The address reveals above the icon and out of flow, so it costs no layout
   height and the marks stay tight to the footer rule. */
.reach__label {
  position: absolute;
  right: 0;
  bottom: calc(100% + 6px);
  white-space: nowrap;
  font-size: var(--fs-tiny);
  letter-spacing: 0.04em;
  color: var(--fg-2);
  background: var(--bg-1);
  border: 1px solid #000;
  padding: 3px 7px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease-in-out;
}
.reach__link:hover .reach__label,
.reach__link:focus-visible .reach__label {
  opacity: 1;
}

/* No hover to reveal them: lay the addresses out for real on touch devices. */
@media (hover: none) {
  .reach-row {
    justify-content: flex-start;
  }
  .reach {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-3);
  }
  .reach__link {
    display: flex;
    align-items: center;
    gap: var(--s-3);
  }
  .reach__label {
    position: static;
    opacity: 1;
    background: none;
    border: 0;
    padding: 0;
  }
}

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

.footer {
  border-top: var(--bd);
  /* Padding, not margin — the footer is the last thing on the page and this
     is the breathing room beneath the signoff line. */
  padding: clamp(8px, 1.5vh, 14px) 0 clamp(20px, 3.2vh, 40px);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) 18px;
  font-size: var(--fs-tiny);
  color: var(--fg-3);
  letter-spacing: 0.06em;
}
.footer__sep {
  color: var(--fg-4);
}
.footer__spacer {
  flex: 1;
}

/* ---------- height budget ---------- */


/* ---------- breakpoints ---------- */

@media (max-width: 900px) {
  .profile {
    grid-template-columns: 1fr;
    gap: clamp(10px, 2vh, 24px);
  }
  .profile__globe {
    padding: clamp(4px, 1vh, 10px) 0 var(--s-1);
  }
  .profile__globe canvas {
    width: clamp(120px, 17vh, 200px);
    height: clamp(120px, 17vh, 200px);
  }
  .footer__spacer {
    display: none;
  }
}

@media (max-width: 620px) {
  .shell {
    padding: 0 18px;
  }
  .masthead__overlay .shell {
    max-width: 100%;
  }
}

/* A phone in portrait cannot hold the whole page at a legible size —
   below this the layout gives up on the single fold and scrolls. */
@media (max-width: 620px) and (max-aspect-ratio: 3 / 5) {
  body {
    min-height: 0;
  }
  .masthead__band {
    height: 118px;
  }
  .profile__globe canvas {
    width: 200px;
    height: 200px;
  }
}

/* Motion is opt-out: the dither engine paints one static frame instead. */
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

/* ---------- 404 ---------- */

.notfound {
  padding-top: 22vh;
  display: grid;
  gap: var(--s-4);
  justify-items: start;
}
.notfound__lead {
  margin: 0;
}
.notfound__note {
  color: var(--fg-2);
}
