@font-face {
  font-family: Archivo;
  src: url('/shared/archivo-variable.ttf') format('truetype');
  font-weight: 100 900;
  font-display: swap;
}
/* By day the plate, ink, line and focus colours are the app's theme tokens (src/app/styles.css). By night
   the cover is black with neutral greys, at the owner's wish; the app's own night theme is dark violet. The
   box is one typeface and one ink colour in both modes; the only warm light on the page is in the windows. */
:root {
  font-family: Archivo, Arial, sans-serif;
  font-synthesis: none;
  --scene: #98978f;
  --plate: #f7f7f5;
  --ink: #1b191f;
  --quiet: rgba(27, 25, 31, 0.72);
  --line: #d8d5de;
  --focus: #5624bb;
  --track: rgba(27, 25, 31, 0.06);
  --track-line: rgba(27, 25, 31, 0.26);
  --dim: rgba(27, 25, 31, 0.5);
  --thumb: #1b191f;
  --thumb-ink: #f7f7f5;
  --ok: #34c759;
  --ok-ink: #fff;
  --fade: 0.9s cubic-bezier(0.4, 0, 0.2, 1);
  --gutter: clamp(16px, 3.2vw, 44px);
  --pad: clamp(22px, 2.8vw, 32px);
  --lift: 0 10px 30px rgba(12, 10, 18, 0.22);
  background: var(--scene);
  color-scheme: light;
}
:root[data-theme='dark'] {
  --scene: #313033;
  --plate: #000;
  --ink: #f7f7f5;
  --quiet: rgba(247, 247, 245, 0.72);
  --line: #333;
  --focus: rgba(247, 247, 245, 0.72);
  --track: rgba(247, 247, 245, 0.08);
  --track-line: rgba(247, 247, 245, 0.3);
  --dim: rgba(247, 247, 245, 0.5);
  --thumb: #f7f7f5;
  --thumb-ink: #000;
  --lift: 0 10px 30px rgba(0, 0, 0, 0.45);
  --ok: #30d158;
  --ok-ink: #fff;
  color-scheme: dark;
}
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  min-width: 320px;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  padding: var(--gutter);
  padding-right: max(var(--gutter), env(safe-area-inset-right));
  padding-bottom: max(var(--gutter), env(safe-area-inset-bottom));
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}
p,
h1 {
  margin: 0;
}
.scene {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100lvh;
  overflow: hidden;
  background: var(--scene);
}
/* Both layers share one geometry; a different crop on either would ghost during the fade. */
.scene img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 56% 50%;
}
/* The opaque backdrop keeps the day photo from showing through while the night photo loads. */
.scene-night {
  background: #313033;
  opacity: 0;
  transition: opacity var(--fade);
}
[data-theme='dark'] .scene-night {
  opacity: 1;
}

/* ---- The parts. Where they sit is decided by the layout further down. ---- */
.plaque {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--plate);
  box-shadow: var(--lift);
  color: var(--ink);
  transition:
    background-color var(--fade),
    border-color var(--fade);
}
/* Text fades are set on leaves only. Chromium restarts a colour transition on every frame while an
   ancestor is fading its own colour, so no element that fades its colour may contain another that does. */
.wordmark,
.line,
.sub,
.lights-label,
.lights-track svg,
.signup-track svg,
.contact a {
  transition: color var(--fade);
}
.wordmark {
  display: block;
  flex-shrink: 0;
  width: 140px;
  height: auto;
}
h1 {
  font-size: clamp(27px, 4vw, 38px);
  line-height: 1.1;
  font-weight: 480;
  letter-spacing: -0.04em;
}
/* One left rule for the whole box. A glyph's ink starts a little inside its own box, more at larger sizes,
   so each text line is pulled back by its first letter's side bearing (P in the headline, K below). */
.line {
  display: block;
  text-indent: -0.08em;
}
h1 .after,
[data-late] h1 .before {
  display: none;
}
[data-late] h1 .after {
  display: block;
}
.sub {
  margin-top: 10px;
  text-indent: -0.083em;
  font-size: 15px;
  line-height: 1.5;
  letter-spacing: -0.005em;
  color: var(--quiet);
}
/* E-mail sign-up: a field in the shape of the switch track, confirmed with the same switch. The thumb
   carries an arrow and slides onto the tick once the address is stored. The only colour in the box is the
   green of that tick. */
.signup {
  display: none;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
}
.js .signup {
  display: flex;
}
.signup-field {
  flex: 1;
  min-width: 0;
  height: 34px;
  padding: 0 14px;
  border: 1px solid var(--track-line);
  border-radius: 999px;
  background: var(--track);
  color: var(--ink);
  font: inherit;
  font-size: 16px;
  letter-spacing: -0.01em;
  -webkit-appearance: none;
  appearance: none;
  transition:
    background-color var(--fade),
    border-color var(--fade),
    color var(--fade);
}
.signup-field::placeholder {
  color: inherit;
  opacity: 0.72;
}
.signup-field:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}
/* A browser's autofill tint would break the single ink colour. */
.signup-field:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  box-shadow: 0 0 0 100px var(--plate) inset;
  caret-color: var(--ink);
}
/* Stored: the thumb turns Apple's system green (light #34c759, dark #30d158) with a white tick, and the
   field carries the thank-you. */
.signup[data-state='done'] .signup-thumb {
  background: var(--ok);
}
.signup[data-state='done'] .signup-track .signup-check {
  color: var(--ok-ink);
  stroke-width: 2.1;
}
/* One piece of the emoji burst that celebrates a stored address; placed and animated from cover.js. */
.burst {
  position: fixed;
  z-index: 5;
  opacity: 0;
  line-height: 1;
  pointer-events: none;
  user-select: none;
}
.signup[data-state='invalid'] .signup-field,
.signup[data-state='error'] .signup-field {
  border-color: var(--ink);
  animation: refuse 0.3s;
}
@keyframes refuse {
  25% {
    transform: translateX(-3px);
  }
  75% {
    transform: translateX(3px);
  }
}
/* Never shown to people; see worker.js. */
.signup-trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}
.signup-send {
  display: flex;
  flex-shrink: 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.signup-send:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 4px;
}
.signup[data-state='sending'] .signup-send {
  cursor: progress;
}
.signup[data-state='done'] .signup-send {
  cursor: default;
}
.lights {
  display: none;
  align-items: center;
  gap: 13px;
  min-height: 48px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 16px;
  font-weight: 520;
  letter-spacing: -0.01em;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.js .lights {
  display: inline-flex;
}
.lights:hover .lights-label {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.lights:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 4px;
}
.lights-track,
.signup-track {
  position: relative;
  flex-shrink: 0;
  width: 60px;
  height: 34px;
  border: 1px solid var(--track-line);
  border-radius: 999px;
  background: var(--track);
  transition:
    background-color var(--fade),
    border-color var(--fade);
}
.lights-thumb,
.signup-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--thumb);
  transition:
    transform 0.45s cubic-bezier(0.5, 0, 0.2, 1),
    background-color var(--fade);
}
[data-theme='dark'] .lights-thumb,
.signup[data-state='done'] .signup-thumb {
  transform: translateX(26px);
}
/* Sun and moon sit at the two ends above the thumb; whichever the thumb is under takes its contrast colour. */
.lights-track svg,
.signup-track svg {
  position: absolute;
  top: 8px;
  width: 16px;
  height: 16px;
}
.lights-sun,
.signup-arrow {
  left: 8px;
  color: var(--thumb-ink);
}
.lights-moon,
.signup-check {
  right: 8px;
  color: var(--dim);
}
[data-theme='dark'] .lights-sun,
.signup[data-state='done'] .signup-arrow {
  color: var(--dim);
}
[data-theme='dark'] .lights-moon,
.signup[data-state='done'] .signup-check {
  color: var(--thumb-ink);
}
.lights-label {
  white-space: nowrap;
}
[data-theme='dark'] .when-day,
:root:not([data-theme='dark']) .when-night {
  display: none;
}
/* The last digit and letter end 0.04em inside their boxes; the negative margin puts their ink on the right
   rule. */
.contact {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  margin-right: -0.04em;
  font-size: 13px;
  font-style: normal;
  font-variant-numeric: tabular-nums;
  line-height: 24px;
  white-space: nowrap;
}
.contact a {
  color: var(--quiet);
  text-decoration: none;
}
.contact a:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.contact a:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}
/* Phone, X and LinkedIn as icon links, in the ink of the contact text (the same 72 %, here as opacity so
   that hover can lift it at once while the colour keeps the slow day/night fade). Each mark is 14 px inside
   a 32 px touch area; the negative margin keeps that padding out of the layout. */
.icons {
  display: flex;
  gap: 18px;
}
.icons a {
  display: flex;
  margin: -9px;
  padding: 9px;
  color: var(--ink);
  opacity: 0.72;
  transition:
    color var(--fade),
    opacity 0.15s;
}
.icons a:hover,
.icons a:focus-visible {
  opacity: 1;
}
.icons a:focus-visible {
  outline-offset: -3px;
  border-radius: 6px;
}
.icons svg {
  display: block;
  width: 14px;
  height: 14px;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
@media (max-width: 360px) {
  /* room for the thank-you on the narrowest phones */
  .signup[data-state='done'] .signup-field {
    padding: 0 10px;
    font-size: 14px;
    letter-spacing: -0.02em;
  }
}

/* ---- Arrangement: one card bottom-left; the light switch on a small plate of its own, top-right, with no
   text. The attribute on <html> lets the local layout lab (cover/lab/, never published) swap in others. ---- */
[data-layout='card'] .plaque {
  width: min(100%, 464px);
  padding: var(--pad);
}
[data-layout='card'] .core {
  margin-top: 28px;
}
/* The bottom line: the e-mail address from the left rule; phone, X and LinkedIn as icons on the right rule,
   all centred on one line. The stem of the "j" sits 0.058em inside its box (its hook is left to hang over
   the rule), and the row's box reaches 5 px below the lowest ink (the marks and the descenders). */
[data-layout='card'] .contact {
  flex-direction: row;
  align-items: center;
  margin-top: 20px;
  margin-right: 0;
  margin-bottom: -5px;
}
[data-layout='card'] .contact > a:first-child {
  margin-left: -0.058em;
}
[data-layout='card'] .icons {
  margin-left: auto;
}
[data-layout='card'] .lights {
  position: fixed;
  top: max(var(--gutter), env(safe-area-inset-top));
  right: max(var(--gutter), env(safe-area-inset-right));
  min-height: 52px;
  padding: 0 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--plate);
  box-shadow: var(--lift);
  transition:
    background-color var(--fade),
    border-color var(--fade);
}
/* The switch shows no words; its name stays for screen readers. */
[data-layout='card'] .lights-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}
/* In a window both narrow and short (a small phone held sideways) the card would reach under the plate.
   There the switch sits in the card's own top-right corner, on the right rule and level with the wordmark. */
@media (max-width: 599px) and (max-height: 399px) {
  [data-layout='card'] .lights {
    position: absolute;
    top: calc(var(--pad) - 12px);
    right: var(--pad);
    min-height: 48px;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}
