/*
 * Styles for the parked page at /.
 *
 * The idea, in one line: an engraved nameplate. A deep ink field, one warm light falling across it
 * from off-canvas, fine grain over everything, and the domain cut into it in a high-contrast
 * old-style serif with the suffix picked out in brass. Nothing else is on the page, so the only
 * things that can carry it are the letterforms, the spacing and the light — which is why all three
 * are specified precisely and nothing is decorated.
 *
 * Committed to a single dark look on purpose, not by omission: a nameplate is an object with one
 * finish. A light inversion of this would be a second, weaker design maintained for no one, so
 * `color-scheme` is pinned to dark and the browser's own chrome is told to match.
 *
 * Structure: tokens, element defaults, atmosphere, composition, type, motion.
 */

/* ---------------------------------------------------------------- tokens */

:root {
  /* Near-black with a faint green cast. A true #000 would sit flat under the grain. */
  --ink: #0b0c0b;
  /* Warm off-white — paper, not screen white, so it belongs to the same light as the brass. */
  --bone: #ece5d8;
  --bone-dim: #8b877c;
  --brass: #c08b3e;
  --hairline: rgba(236, 229, 216, 0.14);

  --gutter: clamp(1.5rem, 7vw, 8rem);
  --font-display: "Fraunces", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --font-ui: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

  color-scheme: dark;
}

/* ------------------------------------------------------- element defaults */

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

html {
  /* The atmosphere is painted here rather than on body so it covers the viewport even when the
     content is shorter than it, without needing a height on either element. */
  background-color: var(--ink);
  background-image:
    radial-gradient(70rem 55rem at 88% 6%, rgba(192, 139, 62, 0.16), transparent 62%),
    radial-gradient(58rem 48rem at 4% 96%, rgba(52, 92, 88, 0.14), transparent 66%);
  background-attachment: fixed;
}

body {
  margin: 0;
  min-height: 100svh;
  color: var(--bone);
  font-family: var(--font-ui);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
p {
  margin: 0;
}

::selection {
  background: var(--brass);
  color: var(--ink);
}

/* ------------------------------------------------------------ atmosphere */

/*
 * Grain. A real noise tile rather than a gradient fake, because the whole page is one flat field
 * and a flat field is where banding and screen-door flatness show most. `overlay` lets it lift the
 * lit corner and leave the dark corner alone, which is how film grain actually behaves.
 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background-image: url("/static/grain.svg");
  background-size: 180px 180px;
  opacity: 0.13;
  mix-blend-mode: overlay;
  pointer-events: none;
}

/* Vignette. Pulls the eye back to the plate and stops the two corner glows from feeling like a
   gradient wash. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 50%, transparent 42%, rgba(4, 5, 4, 0.72));
  pointer-events: none;
}

/* ----------------------------------------------------------- composition */

/*
 * Left-anchored and set a little above centre, not centred in both axes: the wordmark is the
 * subject, and a subject placed off the exact middle is the difference between a composition and a
 * default. The bottom padding does the optical lift.
 */
.landing {
  display: grid;
  align-content: center;
  justify-items: start;
  min-height: 100svh;
  padding: var(--gutter);
  padding-bottom: calc(var(--gutter) + 6vh);
}

.plate {
  position: relative;
  max-width: 100%;
}

/*
 * The margin hairline, run the full height of the viewport rather than the height of the text.
 * Fixed positioning is what lets it break the content box; it lands on the plate's left edge
 * because both are offset from the viewport by --gutter.
 */
.plate::before {
  content: "";
  position: fixed;
  top: 0;
  bottom: 0;
  left: var(--gutter);
  width: 1px;
  margin-left: -1.75rem;
  background: linear-gradient(to bottom, transparent, var(--hairline) 22%, var(--hairline) 78%, transparent);
}

/* Below the hairline's own margin there is no room for it to sit outside the text, and a rule
   crossing the wordmark would be noise rather than structure. */
@media (max-width: 30rem) {
  .plate::before {
    display: none;
  }
}

/* ------------------------------------------------------------------ type */

.wordmark {
  font-family: var(--font-display);
  font-weight: 400;
  /* Largest optical size: the display cut with the fine hairlines and open apertures. SOFT rounds
     the terminals just off the mechanical, WONK swaps in the single-storey g of "bestcarfor". */
  font-variation-settings: "opsz" 144, "SOFT" 40, "WONK" 1;
  font-size: clamp(2.5rem, 10.5vw, 8.5rem);
  line-height: 0.92;
  /* Display sizes need the tracking taken out that a text size needs left in. */
  letter-spacing: -0.028em;
  white-space: nowrap;
}

.wordmark-tld {
  color: var(--brass);
}

.status {
  /* The display serif's left side bearing pushes its first glyph in from the box edge; the caption
     is nudged the same way so the two line up optically rather than mathematically. */
  margin-left: clamp(0.15rem, 0.45vw, 0.4rem);
  margin-top: clamp(1.5rem, 3.5vw, 2.5rem);
  display: flex;
  align-items: center;
  gap: 1.25rem;
  color: var(--bone-dim);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.34em;
  text-transform: uppercase;
}

/* The rule reads as the underline of the plate rather than as a separator, so it belongs to this
   line and grows out of it. */
.status::after {
  content: "";
  flex: 1;
  height: 1px;
  min-width: 2rem;
  max-width: 14rem;
  background: linear-gradient(to right, var(--hairline), transparent);
}

/* ---------------------------------------------------------------- motion */

/*
 * One orchestrated page load, then stillness. Nothing loops: a nameplate that shimmered would be a
 * different, cheaper object, and a permanent animation on a page nobody needs to read is a repaint
 * every frame for as long as the tab stays open.
 *
 * The wordmark is wiped in from the baseline upward rather than faded or slid, so the letters look
 * cut into the plate rather than dropped onto it. It has to be a clip animation rather than a
 * translate behind a clip, because a transform moves an element's own clip region with it and
 * would reveal nothing.
 */
.wordmark {
  animation: cut 0.9s cubic-bezier(0.22, 0.68, 0.16, 1) 0.08s backwards;
}

@keyframes cut {
  from {
    /* Top inset past the bottom inset: an empty region, so the wordmark starts fully hidden. */
    clip-path: inset(100% -0.3em -0.06em -0.3em);
  }

  to {
    /* Slack on every side so overshooting glyph edges — and the descender space the negative
       line-height pulls inside the box — are never shaved off once the wipe has finished. */
    clip-path: inset(-0.3em -0.3em -0.06em -0.3em);
  }
}

.status {
  animation: rise 0.8s cubic-bezier(0.22, 0.68, 0.16, 1) 0.62s backwards;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(0.6em);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* Reduced motion drops the choreography entirely rather than shortening it: the page has no state
   to explain, so nothing is lost by arriving finished. */
@media (prefers-reduced-motion: reduce) {
  .wordmark,
  .status {
    animation: none;
  }
}
