/* Casual Code — holding page. One HTML file, one stylesheet, one photograph:
   it has to stand on its own, with no build step and nothing fetched.

   The two faces in `fonts/` are cut down to the characters this page sets, by
   `ops/subset-fonts.sh`. ⚠️ The `unicode-range` below must stay equal to the
   range that script passes: promising more here than the file carries draws
   tofu, promising less skips the face silently. */

/* ⚠️ ONE FILE, BOTH WEIGHTS. This was two @font-face rules pointing at
   `Manrope-400-latin.woff2` and `Manrope-800-latin.woff2`, which were
   byte-identical — one variable font (wght 200-800) shipped under two names
   and preloaded twice, so 24 KB was fetched twice for one typeface. A weight
   *range* on a single rule lets the browser instance it for the lede at 400
   and the headline at 800 from one download. */
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("fonts/Manrope-var-latin.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00B0, U+2013-2014, U+2018-201A, U+201C-201E, U+2026;
}

/* the studio's own hand, used on its site to write on photographs. Caveat is
   variable too and exactly one weight is used, so it is pinned to 600 and the
   variation data goes with it. */
@font-face {
  font-family: "Caveat";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/Caveat-600-latin.woff2") format("woff2");
  unicode-range: U+0020-007E, U+00B0, U+2013-2014, U+2018-201A, U+201C-201E, U+2026;
}

:root {
  --void: #0a0806;
  --ink: #f8f4ee;
  --dim: #cdc4b7;
  --gold: #e9a63b;
  --gold-lit: #ffca79;
  color-scheme: dark;
}

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

html,
body {
  margin: 0;
  height: 100%;
}

body {
  background: var(--void);
  color: var(--ink);
  font-family: "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}

.page {
  /* how much of the window the words keep to themselves before the photograph
     begins; nothing on a phone, a column of it on a desktop */
  --split: 0px;
  position: relative;
  isolation: isolate;
  display: grid;
  align-content: center;
  min-height: 100dvh;
  padding: clamp(1.5rem, 5vw, 5.5rem);
  padding-top: max(clamp(1.5rem, 5vw, 5.5rem), env(safe-area-inset-top));
  padding-bottom: max(clamp(1.5rem, 5vw, 5.5rem), env(safe-area-inset-bottom));
  overflow: hidden;
}

/* ⚠️ The photograph is portrait and the studio's lit sign sits near its top.
   Cropped from the centre on a wide screen the sign is the first thing lost,
   so the crop is held high and only eases down as the viewport gets taller. */
/* ⚠️ `sizes` in the markup describes the RENDERED width, which for a `cover`
   image is max(box width, box height x 2/3) — not the window. In the column it
   is exactly 67vh, because the box is sized to the height; full-bleed it is
   whichever of the window's width and 67vh is larger. */
.shot {
  position: absolute;
  inset: 0 0 0 var(--split);
  z-index: -2;
  width: calc(100% - var(--split));
  height: 100%;
  object-fit: cover;
  object-position: 50% 18%;
}

/* the wall behind the words is dark, but the crop moves: this keeps the
   contrast the text needs wherever the photograph lands */
.page::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to right, rgb(10 8 6 / 0.88) 0%, rgb(10 8 6 / 0.72) 38%, rgb(10 8 6 / 0.25) 70%, rgb(10 8 6 / 0.1) 100%),
    linear-gradient(to bottom, rgb(10 8 6 / 0.45) 0%, rgb(10 8 6 / 0) 35%);
}

/* ⚠️ The measure belongs on the text, not the wrapper: `ch` on the wrapper is
   read at 16px while the headline sets at 88px, so the box was far narrower
   than the words and they simply overflowed it. `em` tracks the type. */
.say {
  max-width: 100%;
}

/* ⚠️ No `text-wrap: balance` here. The `<br>` in the markup is what decides
   the break, and asking the browser to rebalance around a break it is not
   allowed to move is two rules arguing over one line. */
.title {
  margin: 0;
  max-width: 6.5em;
  font-size: clamp(2.75rem, 1.4rem + 6.4vw, 5.5rem);
  font-variant-numeric: lining-nums;
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -0.035em;
  text-shadow: 0 2px 30px rgb(0 0 0 / 0.55);
}

/* ⚠️ Three lines of precise type finished by hand — the studio's promise is
   "serious software, casually done", and this is that sentence as a type
   treatment rather than one word tinted a different colour. */
.title em {
  font-family: "Caveat", ui-rounded, cursive;
  font-style: normal;
  font-weight: 600;
  font-size: 1.28em;
  line-height: 0.82;
  letter-spacing: 0;
  color: var(--gold);
}

.lede {
  max-width: 27ch;
  margin: clamp(1.25rem, 2.5vw, 2rem) 0 0;
  font-size: clamp(1rem, 0.92rem + 0.35vw, 1.25rem);
  font-weight: 400;
  line-height: 1.6;
  color: var(--dim);
  text-shadow: 0 1px 18px rgb(0 0 0 / 0.6);
}

/* The only thing on the page anyone can act on, so it is the only thing that
   looks actionable. The rule under it is the gold hairline the coordinate
   stamp already uses — a device the page owns, rather than a new one.
   `min-height` rather than vertical padding: the target reaches the platform
   minimum without the box pushing the stamp down. */
.reach {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: clamp(0.5rem, 1.5vw, 1rem);
  font-size: clamp(1rem, 0.92rem + 0.35vw, 1.25rem);
  font-weight: 500;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--gold);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35em;
  text-shadow: 0 1px 18px rgb(0 0 0 / 0.6);
  transition: text-decoration-thickness 120ms ease, color 120ms ease;
}

@media (hover: hover) {
  .reach:hover {
    color: var(--gold-lit);
    text-decoration-thickness: 2px;
  }
}

/* Ink rather than the brand gold: a focus ring has to be seen against a
   photograph, and a saturated accent halo reads as decoration at the moment
   it most needs to read as position. */
.reach:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 5px;
  border-radius: 3px;
  text-decoration-thickness: 2px;
}

/* ⚠️ The studio writes on its photographs this way — a line in its own hand on
   a blurred chip, tilted, signed with a heart. Set bare instead, it depended on
   finding a dark patch of picture to sit on; the chip carries its own ground.
   That is also what lets it appear on a phone: it makes its own contrast
   wherever the crop puts it, so it no longer has to be hidden below 46rem. */
.note {
  position: absolute;
  top: 8%;
  right: 6%;
  z-index: 1;
  display: grid;
  justify-items: center;
  margin: 0;
  /* ⚠️ `em`, so the measure tracks the type rather than the root. At `11ch`
     this was read against Caveat's narrow digit and `Good products` wrapped,
     turning a two-line note into a four-line column tall enough to reach the
     headline on a 320px screen. The `<br>` in the markup is the only break
     this is supposed to have. */
  max-width: 9em;
  rotate: -6deg;
  padding: 0.8rem 1.1rem 0.9rem;
  border-radius: 1.1rem;
  background: rgb(10 8 6 / 0.52);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  font-family: "Caveat", ui-rounded, cursive;
  font-weight: 600;
  font-size: clamp(1.05rem, 0.7rem + 1.05vw, 2rem);
  line-height: 1.26;
  text-align: center;
  color: rgb(248 244 238 / 0.94);
  text-shadow: 0 2px 14px rgb(0 0 0 / 0.75);
}

.note svg {
  margin-top: 0.4rem;
  color: rgb(248 244 238 / 0.8);
}

/* ⚠️ Closes the column rather than sitting on the photograph: over the lit
   floor and the toolbox, 11px of mono could not be read at all. */
/* Set in Manrope, not a fourth typeface. This was DM Mono — 8.8 KB and a whole
   family for three lines — and `tabular-nums` is the only part of a monospace
   the stamp actually needed, so that the two bearings keep a column. */
.where {
  /* as wide as it reads, not as wide as the column */
  width: max-content;
  max-width: 100%;
  margin: clamp(2.5rem, 7vh, 4.5rem) 0 0;
  display: grid;
  justify-items: start;
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums lining-nums;
  line-height: 1.9;
  letter-spacing: 0.1em;
  color: rgb(205 196 183 / 0.72);
}

/* was an empty `<i>` in the markup; a rule with no content is a pseudo-element */
.where span:first-child::after {
  content: "";
  display: inline-block;
  width: 2.5rem;
  height: 1px;
  margin-left: 0.75rem;
  vertical-align: middle;
  background: var(--gold);
}

/* ⚠️ A window wider than it is tall is served the landscape render, which
   fills it edge to edge — no column, no dissolve, no panel. The upright
   picture could never do this: shown whole it is only 38% of a 16:9 window,
   and cropped to 16:9 it keeps 37% of its height, which is less than the
   distance from the sign to the dog. */
@media (min-width: 46rem) and (min-aspect-ratio: 1 / 1) and (min-height: 34rem) {
  .page {
    align-content: center;
    background: var(--void);
  }

  .shot {
    inset: 0;
    width: 100%;
    height: 100%;
    -webkit-mask-image: none;
    mask-image: none;
    /* the wall and the sign are the left of the frame, and that is where the
       words go, so the crop holds that edge */
    object-position: 0% 50%;
  }

  /* the wall is lit; the words need it darker where they sit, and nowhere else */
  .page::before {
    background:
      linear-gradient(
        to right,
        rgb(10 8 6 / 0.93) 0,
        rgb(10 8 6 / 0.88) 26%,
        rgb(10 8 6 / 0.62) 42%,
        rgb(10 8 6 / 0.2) 60%,
        rgb(10 8 6 / 0) 76%
      ),
      linear-gradient(to bottom, rgb(10 8 6 / 0.32) 0%, rgb(10 8 6 / 0) 24%);
  }

  /* ⚠️ Kept inside the dark wall the photograph gives it. At 7em the last
     line ran onto the lit pillar behind it and measured 2.9:1. */
  .title {
    font-size: clamp(3rem, 0.5rem + 4.6vw, 5.75rem);
    max-width: 5.9em;
  }

  .lede {
    max-width: 30ch;
    font-size: clamp(1.0625rem, 0.85rem + 0.5vw, 1.3rem);
  }

  .say {
    margin-left: clamp(0rem, 3vw, 4.5rem);
  }

  /* over the view, where the studio puts it on its own hero — the chip is what
     makes that possible, and it clears the framed mark in the corner */
  .note {
    top: 15%;
    right: 16%;
    padding: 0.95rem 1.35rem 1.1rem;
    border-radius: 1.25rem;
  }

  /* it closes the page, so it sits at the foot of it */
  .where {
    position: absolute;
    left: clamp(1.5rem, 5vw, 5.5rem);
    bottom: clamp(1.5rem, 5vh, 3.5rem);
    margin: 0;
  }
}

/* tall and narrow: the whole composition is close to the photograph's own
   shape, so the crop can sit where the picture was framed */
@media (max-aspect-ratio: 3 / 4) {
  .shot {
    object-position: 38% 50%;
  }

  .page {
    align-content: end;
    padding-bottom: clamp(3rem, 12vh, 8rem);
  }

  /* ⚠️ Reaches further up the frame than it used to. The stops were
     `0.94 12%, 0.7 42%, 0.15 72%`, which left the top of the headline sitting
     on an untinted band — at 320x568 that is exactly where `We’re` meets the
     lit sign, and one pixel of it measured 2.4:1 against a 3:1 bar. The sign
     itself is above 88% and still reads. */
  .page::before {
    background: linear-gradient(
      to top,
      rgb(10 8 6 / 0.95) 10%,
      rgb(10 8 6 / 0.84) 38%,
      rgb(10 8 6 / 0.58) 60%,
      rgb(10 8 6 / 0.22) 80%,
      rgb(10 8 6 / 0.06) 92%
    );
  }
}

/* ⚠️ THE SMALLEST PHONE STILL IN USE IS 320px WIDE, AND THE LIT SIGN IS FIXED
   THERE. At 320x568 the photograph is already narrower than the frame, so
   `cover` scales it by height and crops sideways — `object-position`'s vertical
   half does nothing, and the sign cannot be moved out from behind the words.
   The only two levers left are how big the headline is and how much veil sits
   over that band, so both are used here rather than either one hard enough to
   hurt. At the 2.75rem floor the top line landed on the sign's glow and
   measured 1.8:1 against a 3:1 bar. */
@media (max-aspect-ratio: 3 / 4) and (max-width: 22.5rem) {
  .title {
    font-size: 2.5rem;
  }

  .page::before {
    background: linear-gradient(
      to top,
      rgb(10 8 6 / 0.95) 10%,
      rgb(10 8 6 / 0.88) 38%,
      rgb(10 8 6 / 0.74) 58%,
      rgb(10 8 6 / 0.52) 74%,
      rgb(10 8 6 / 0.2) 88%,
      rgb(10 8 6 / 0.06) 95%
    );
  }
}

/* ⚠️ A phone held sideways is 390px tall. The headline is sized from the
   width, which is generous there, and four lines of it plus the paragraph ran
   off the bottom of the screen. */
@media (orientation: landscape) and (max-height: 34rem) {
  /* the sign is the only branding on the page, so it is not cropped away */
  .shot {
    object-position: 50% 15%;
  }

  .page {
    align-content: center;
    padding-block: clamp(1rem, 4vh, 2rem);
  }

  .title {
    font-size: clamp(1.5rem, 1rem + 4.5vh, 2.5rem);
    /* short and wide: the headline has room across, not down */
    max-width: none;
  }

  .lede {
    margin-top: 0.75rem;
    font-size: 0.9375rem;
    line-height: 1.5;
  }

  .reach {
    min-height: 36px;
    margin-top: 0.25rem;
    font-size: 0.9375rem;
  }

  .where {
    margin-top: 1rem;
  }

  /* no room over the picture next to four lines of type and an address */
  .note {
    display: none;
  }
}

/* below the split the words sit on the photograph rather than beside it, so
   the stamp closes the column instead of the page */
@media (max-width: 46rem), (max-aspect-ratio: 1 / 1) {
  .where {
    margin-top: clamp(1.5rem, 4vh, 2.5rem);
  }
}

/* one moment, once: the words settle, and a beat later the line on the wall
   appears, as though it were written after them */
@media (prefers-reduced-motion: no-preference) {
  .say {
    animation: rise 700ms cubic-bezier(0.2, 0.6, 0.2, 1) both;
  }

  .note {
    animation: written 900ms cubic-bezier(0.2, 0.6, 0.2, 1) 620ms both;
  }

  @keyframes rise {
    from {
      opacity: 0;
      transform: translateY(0.75rem);
    }
  }

  @keyframes written {
    from {
      opacity: 0;
      rotate: -5deg;
      scale: 0.97;
    }
  }
}
