/* ============================================================
   Kelpie — hero section

   The plate is a crescent moon over a still lake, a blossom
   tree on an islet, and the whole thing again in the water.
   Measured over the loop, as the contrast a #EAF0FF white
   keeps against the brightest frame of each cell:

     upper left, left of the arc   x 0.03-0.22  y 0.04-0.46  7.0-13.6:1
     right flank, right of the tree x 0.78-0.97 y 0.04-0.46  6.4-14.0:1
     the arc, its reflection, the tree            0.9-2.5:1
     dark ink, anywhere                           0.8-2.4:1

   So the type is white and it keeps to the upper-left wedge:
   the copy left of the arc, and everything else — the arc,
   the tree, the water — left alone. Nothing is laid over the
   footage; the button carries its own ground.

   Phones get an upright plate of the same scene, composed for
   the frame rather than cropped out of the wide one. Its arc
   comes across about a quarter of the way down, so the copy
   is sized to end above the crest; see the upright block near
   the foot of this file.

   Both clips play forward only. Each is nearly a round trip
   already, so the last 24 frames dissolve into the first on a
   smoothstep and the wrap closes under the median frame step.

   Instrument Serif sets the headline — a high-contrast face
   for a high-contrast plate. IBM Plex Mono sets the rest: a
   swimming club's own notices, typed rather than designed.
   ============================================================ */

:root {
  --night:  #060911;   /* the sky in the corners: the page's own ground */
  --moon:   #EAF0FF;   /* type */
  --rim:    #BFD4FF;   /* the cold edge of the crescent: mark, focus ring */
  --dim:    rgba(234, 240, 255, .82);   /* the lede, where the sky is open */

  --serif:  "Instrument Serif", "Iowan Old Style", Georgia, serif;
  --mono:   "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --gutter: clamp(1.25rem, 3vw, 2.75rem);
  --ease:   cubic-bezier(.22, .61, .36, 1);
}

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

html, body { margin: 0; }

body {
  background: var(--night);
  color: var(--moon);
  font-family: var(--mono);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

:focus-visible { outline: 2px solid var(--rim); outline-offset: 4px; }

/* ---------- stage ---------- */

.hero {
  position: relative;
  min-height: 100svh;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  padding: 0 var(--gutter) clamp(1.5rem, 4vh, 3rem);
}

.hero__media { position: absolute; inset: 0; }

.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the plate is symmetrical about the moon, so it is framed on its own
     centre; cover takes its trim off both flanks evenly */
  object-position: center;
  display: block;
}

/* ---------- top bar ---------- */

.topbar {
  grid-column: 1 / -1;
  grid-row: 1;
  position: relative;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: clamp(1rem, 2.6vh, 1.8rem);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: .7rem;
  font-family: var(--serif);
  font-size: clamp(1.35rem, 1.7vw, 1.6rem);
  letter-spacing: .01em;
}

.brand__moon { width: 17px; height: 21px; flex: none; color: var(--rim); }
.brand__word { white-space: nowrap; }

/* ---------- nav ---------- */

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.4vw, 2.1rem);
}

.nav__link {
  font-size: .74rem;
  letter-spacing: .02em;
  color: var(--dim);
  padding-bottom: 3px;
  border-bottom: 1px solid transparent;
  white-space: nowrap;
  transition: color .3s var(--ease), border-color .3s var(--ease);
}
.nav__link:hover, .nav__link:focus-visible { color: var(--moon); border-color: var(--rim); }

/* ---------- burger (narrow only) ---------- */

.burger {
  display: none;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
}
.burger span {
  display: block;
  width: 22px;
  height: 1px;
  margin: 5px auto;
  background: currentColor;
  transition: transform .3s var(--ease);
}
.burger[aria-expanded="true"] span:first-child { transform: translateY(3px) rotate(45deg); }
.burger[aria-expanded="true"] span:last-child  { transform: translateY(-3px) rotate(-45deg); }

/* ---------- copy, left of the arc ---------- */

.hero__copy {
  grid-column: 1;
  grid-row: 2;
  position: relative;
  z-index: 2;
  justify-self: start;
  align-self: start;
  margin-top: clamp(.5rem, 3vh, 2.2rem);
  /* The arc closes this column in as it descends — it crosses x 0.25 at 0.29
     of the height and x 0.19 by 0.38 — so the copy is sized to stay inside
     that wedge rather than run under the moon. */
  max-width: min(19rem, 22vw);
}

.title {
  margin: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.85rem, 2.85vw, 2.7rem);
  line-height: 1.09;
  letter-spacing: -.005em;
}

.title__line { display: block; }

.lede {
  margin: 1rem 0 0;
  max-width: 15rem;
  font-size: .74rem;
  line-height: 1.7;
  color: var(--dim);
}

.btn {
  display: inline-flex;
  align-items: center;
  min-height: 42px;
  margin-top: 1.3rem;
  padding: .6rem 1.5rem;
  /* opaque, so it stands on its own ground rather than on a scrim over the
     footage; the plate keeps its contrast everywhere around it */
  background: var(--moon);
  color: var(--night);
  /* a night-coloured hairline on the button itself, so its edge still reads
     where the plate goes bright (the water, the mist) — the fill carries the
     edge over dark sky, the hairline carries it over light. No scrim either way. */
  box-shadow: 0 0 0 1px var(--night);
  font-size: .78rem;
  letter-spacing: .01em;
  /* the label is the action's name and it never breaks: a narrow column
     should push the button past its edge, not split "Take a place" */
  white-space: nowrap;
  transition: background .3s var(--ease), color .3s var(--ease);
}
.btn:hover, .btn:focus-visible { background: var(--rim); }

/* ---------- the page arriving ----------
   One sequence, once, in the order the eye reads it. */

@media (prefers-reduced-motion: no-preference) {
  .brand, .nav, .title__line, .lede, .btn {
    animation: rise .9s var(--ease) both;
  }
  .nav          { animation-delay: .05s; }
  .title__line:nth-child(1) { animation-delay: .15s; }
  .title__line:nth-child(2) { animation-delay: .23s; }
  .title__line:nth-child(3) { animation-delay: .31s; }
  .lede         { animation-delay: .45s; }
  .btn          { animation-delay: .55s; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(.6rem); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================
   Narrow. The plate stays the whole screen and the two flanks
   become one column, with the copy under the top bar and the
   water left alone. Anything held upright also swaps to the
   upright plate; the block below handles what that costs.
   ============================================================ */

@media (max-width: 900px), (max-height: 560px) {

  .hero {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto 1fr;
    padding-bottom: clamp(1.25rem, 3vh, 2rem);
  }

  .hero__copy {
    grid-column: 1;
    grid-row: 2;
    max-width: min(21rem, 76%);
    margin-top: .25rem;
  }

  .burger { display: block; position: relative; z-index: 4; }

  .nav {
    position: fixed;
    inset: 0;
    z-index: 3;
    flex-direction: column;
    justify-content: center;
    gap: 1.7rem;
    /* only while the menu is open, and it replaces the view rather than
       tinting it — the footage never sits under a permanent scrim */
    background: var(--night);
    opacity: 0;
    visibility: hidden;
    transition: opacity .3s var(--ease), visibility .3s var(--ease);
  }
  .nav[data-open] { opacity: 1; visibility: visible; }
  .nav__link { font-size: .95rem; color: var(--moon); }

  .title { font-size: clamp(1.5rem, 6.1vw, 2.2rem); }
  .lede  { margin-top: .7rem; font-size: .72rem; max-width: 18rem; color: var(--moon); }
  .btn   { margin-top: .9rem; min-height: 40px; }

  .topbar { padding-block: clamp(.8rem, 2vh, 1.3rem); }
}

/* ---------- held upright ----------
   The upright plate is its own composition, and the moon's arc cuts across it
   from about a quarter of the way down, sweeping left as it falls. That leaves
   one clear block — the top quarter, full width — and the headline takes all
   of it. So the lede goes here, and the button follows straight on, ending
   above the crest rather than on it. */

@media (max-width: 900px) and (orientation: portrait) {
  .lede { display: none; }
  /* The block rides as high as the top bar allows, and the headline is sized
     off the PLATE rather than the screen. The crest sits at a fixed fraction
     of the plate (about 0.24 down), and cover renders the plate at
     max(vw/404, vh/720) — so the room above the crest, in CSS pixels, is
     max(42.6vw, 24vh). Take the top bar, the gap and the button out of that
     and what is left is three lines of headline. Size the type off vh alone
     and a small phone, which shows the same crest higher up the screen, puts
     the button on the moon. */
  .hero__copy { margin-top: 0; }
  .topbar     { padding-block: clamp(.55rem, 1.3vh, 1rem); }
  .title      { font-size: clamp(1.15rem, calc((max(42.6vw, 24vh) - 116px) / 3.27), 1.65rem); }
  .btn        { margin-top: .5rem; min-height: 34px; }
}

/* ---------- short phones ----------
   Less height, the same band to stay inside, so the type steps down. */

@media (max-width: 900px) and (orientation: portrait) and (max-height: 700px) {
  .btn { padding: .5rem 1.3rem; }
}

/* ---------- held sideways ----------
   Landscape under 900px: cover's trim comes off the flanks or the bottom
   depending on the aspect, and either way a centred plate slides the arc
   across the copy. Anchoring the plate left and top puts the clear wedge
   under the type and keeps the sky, so the copy reads at any of these
   shapes without the column having to shrink to a slot. */

@media (orientation: landscape) and (max-width: 900px),
       (orientation: landscape) and (max-height: 560px) {
  .hero__video { object-position: left top; }

  /* Same rule as upright, on the other axis: the wedge ends at 0.24 of the
     plate's width and cover renders the plate at max(vw/320, vh/180), so the
     column is max(24vw, 42.7vh) wide in CSS pixels, less the gutter it starts
     at. The headline is sized to that column rather than to the screen —
     a 16:9 window crops nothing, which makes the wedge smallest of all. */
  .hero__copy  { grid-row: 2; max-width: calc(max(24vw, 42.7vh) - var(--gutter)); }
  .title       { font-size: clamp(1rem, calc(max(24vw, 42.7vh) / 8.6), 1.85rem); }
  .lede        { max-width: none; color: var(--moon); }
}

/* Phones sideways: no height to spend, so the whole block tightens. */

@media (max-height: 560px) and (min-width: 561px) {
  .hero {
    grid-template-rows: auto 1fr;
    padding-bottom: clamp(.5rem, 3vh, 1rem);
  }

  .topbar     { padding-block: clamp(.5rem, 2.5vh, 1rem); }

  .hero__copy { margin-top: clamp(.25rem, 2vh, 1rem); }
  .lede       { margin-top: .5rem; font-size: .68rem; }
  .btn        { margin-top: .9rem; min-height: 38px; }
}

/* Under roughly 190px of column the lede has nowhere to set — it breaks into
   four or five lines and walks the button down onto the water. The headline
   carries the page on its own at these shapes. */

@media (orientation: landscape) and (max-width: 860px) and (max-height: 500px) {
  .lede { display: none; }
  .btn  { margin-top: 1.1rem; }
}
