/* css/sea-hero.css — the chart room.

   The page opens on the one thing this man and this course have in common:
   navigation is arithmetic. A sextant is an analog computer, a chart is a
   grid of depth readings, and dead reckoning is a loop with an accumulator.
   So the hero is a sea chart — real depth contours with real soundings
   printed between them — with the officer standing on a torn plate of it and
   the compass rose, the instrument that turns a horizon into a number, behind
   him at full size.

   Everything here is drawn: the rose, the slab, the instruments and the
   crests are all geometry, inked in one brass line weight, because the rest
   of this site is inked and a photographic prop collage would read as pasted
   on. The only photograph is the man. */

.sea-hero {
  --sea-abyss: #06192c;   /* the ground the whole hero is printed on */
  --sea-deep:  #0b2e4f;   /* the plate he stands on */
  --sea-mid:   #14507f;
  --sea-shoal: #2e86c0;   /* the band the crests break in */
  --brass:     #e9b44c;   /* the gold on the uniform, and every drawn line */
  --brass-dim: #a97f2e;
  --foam:      #faf6ee;   /* the site's own paper, up here as spray */

  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* The ground is declared on its own, not left to the shorthand. `background:`
     with only gradients resets background-color to transparent, which left the
     hero with no solid floor under the light it is lit by — and left anything
     reading the page's colours to walk straight past it to the paper below. */
  background-color: var(--sea-abyss);
  background-image:
    linear-gradient(180deg, rgba(3, 12, 22, 0.55), transparent 28%),
    radial-gradient(58% 62% at 28% 40%, rgba(46, 134, 192, 0.26), transparent 72%),
    radial-gradient(70% 34% at 50% 100%, rgba(46, 134, 192, 0.3), transparent 70%),
    linear-gradient(180deg, #0a2947 0%, var(--sea-abyss) 58%, #041322 100%);
  /* Runs edge to edge regardless of what container it was dropped into. */
  margin-inline: calc(50% - 50vw);
  padding-inline: calc(50vw - 50%);
  /* Up under the header, which has no ground of its own until you scroll. The
     page used to open on a band of paper, then a hard rule, then the sea —
     three sheets where there is one. Now the sea is the first thing on the
     page and the wordmark floats on it.

     It is also what makes the chart continuous. The tile is anchored at the
     top of whatever paints it; with the hero starting at the document's own
     origin, the sea's chart and the paper's chart are the same tile counting
     from the same zero, so every contour that leaves the paper arrives in the
     water where it left off. Nothing is measured and nothing is synced. */
  margin-block-start: calc(-1 * var(--header-h));
  padding-block-start: var(--header-h);
}

/* The chart itself: the same tile the whole page is textured with, at the
   same size and counting from the same origin, inked in the light the water
   gives back instead of the dark the paper takes. That is the entire trick —
   one drawing, two inks, and the line that runs off the bottom of the paper
   is the line that runs into the sea. */
.sea-chart {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-color: var(--sea-shoal);
  -webkit-mask-image: var(--chart-mask);
  mask-image: var(--chart-mask);
  -webkit-mask-size: var(--chart-tile, 560px);
  mask-size: var(--chart-tile, 560px);
  -webkit-mask-repeat: repeat;
  mask-repeat: repeat;
  opacity: 0.72;
  pointer-events: none;
}

/* ------------------------------------------------------------------ the row

   Two columns that are not halves: the words get the larger share because
   they are what the page is for, and the portrait gets the smaller one and
   overflows it, which is what makes him read as standing in the picture
   rather than being placed in a box. */
.sea-grid {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  align-items: center;
  gap: clamp(1rem, 3vw, 3.5rem);
  padding-block: clamp(2rem, 4vw, 3.5rem) clamp(5rem, 9vw, 8rem);
}

/* ------------------------------------------------------------------ the copy */

.sea-copy {
  position: relative;
  display: grid;
  justify-items: start;
  gap: var(--spacing-md);
}

.sea-copy::before {
  content: "";
  position: absolute;
  inset: -9% -11%;
  z-index: -1;
  /* A blurred shape rather than a gradient. A radial has to be sized to the
     box it is in, and this box is a wide block on a desktop and a tall one on
     a phone — one set of stops cannot cover both. A soft-edged solid covers
     whatever shape the column happens to be. */
  border-radius: 42%;
  background: rgba(4, 19, 34, 0.9);
  filter: blur(38px);
  pointer-events: none;
}

/* The badge is the one warm mark in a hero that is otherwise all water. It
   used to be the site's orange; with the brand itself now the sea, an orange
   badge was the only thing on the page still speaking the old palette and a
   blue one disappeared into the ground. It takes the gold instead — the same
   gold as the buttons on his coat, which is where this page's warm comes
   from. */
.sea-badge {
  margin-bottom: 0;
  background: var(--brass);
  color: #14100b;
  border-color: #0d0a07;
}

.sea-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2rem, 3.9vw, 3.4rem);
  line-height: 1.18;
  letter-spacing: -0.01em;
  color: var(--foam);
  text-wrap: balance;
  /* Not a glow: a shadow the colour of the deep water, so the type sits *on*
     the chart instead of floating over it. */
  text-shadow: 0 2px 0 rgba(4, 19, 34, 0.55);
}

/* NumPy is a library, not a word, and this site already sets code in Plex
   Mono. The yellow chip is the site's own highlight, squared off and given
   the ink rule everything else on the page is held down by. */
/* The slab under the phrase the headline turns on.

   It was the code chip — mono, tight-tracked — because what it used to hold
   was a library name, and a library name set in the code face is the chip
   saying what kind of thing it is. The headline is Arabic now, and the mono
   has no Arabic to set it in: the fallback came out carrying the mono's
   negative tracking and pulled the joined letters apart. Same slab, same gold,
   same tilt, set in the face the rest of the headline is set in — so it reads
   as the headline with a marker run through it, which is what it is. */
.sea-mark {
  display: inline-block;
  padding: 0.04em 0.34em;
  border: 2.5px solid #0d0a07;
  border-radius: var(--radius-xs);
  background: var(--accent-yellow-fill);
  box-shadow: 3px 3px 0 #0d0a07;
  color: #14100b;
  font-weight: 900;
  transform: rotate(-1.4deg);
}

.sea-lede {
  margin: 0;
  max-width: 46ch;
  font-family: var(--font-body);
  font-size: clamp(0.98rem, 1.15vw, 1.1rem);
  line-height: 1.9;
  color: #c9dcea;
}

/* ------------------------------------------------------------------ actions */

.sea-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-md);
  margin-block-start: var(--spacing-xs);
}

.sea-cta {
  padding: 0.78rem 1.7rem;
  border: 3px solid #0d0a07;
  border-radius: var(--radius-sm);
  background: var(--brass);
  box-shadow: 5px 5px 0 #0d0a07;
  color: #14100b;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.02rem;
  text-decoration: none;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.sea-cta:hover,
.sea-cta:focus-visible {
  transform: translate(-2px, -2px);
  box-shadow: 7px 7px 0 #0d0a07;
}

.sea-cta:active {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 #0d0a07;
}

.sea-cta:focus-visible {
  outline: 3px solid var(--foam);
  outline-offset: 3px;
}

/* The chart's margin note. Small, monospaced and spaced out, the way the
   scale and the units are printed along the bottom of a real sheet. */
/* The margin-note register is the hairline rule, the size and the muted ink —
   not the face. Set in the mono, this line was Arabic falling back to whatever
   the system had while still carrying the mono's letter-spacing, which pulled
   the joined script apart letter by letter. Cairo, tracked normally, and the
   note reads as a note instead of as damage. */
.sea-note {
  margin: 0;
  padding-block-start: 0.7rem;
  border-block-start: 1px solid rgba(233, 180, 76, 0.28);
  font-family: var(--font-body);
  font-size: 0.84rem;
  color: #b6cfe2;
}

/* The position named in the note is a place on the page, so it is a link
   to it: the brass rule under it is the same rule the sentence below uses
   for a word that can be pressed. */
.sea-note-go {
  color: var(--foam);
  font-weight: 800;
  text-decoration: none;
  border-block-end: 2px solid var(--brass);
  transition: color var(--transition-fast), border-color var(--transition-fast);
}

.sea-note-go:hover,
.sea-note-go:focus-visible {
  color: var(--brass);
  border-block-end-color: var(--foam);
}

.sea-note-go:focus-visible {
  outline: 3px solid var(--foam);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ------------------------------------------------------------------ the plate

   He does not stand on the chart, he stands on a piece of one: a plate torn
   out of the sheet, two plies deep so the tear has a thickness. The rose is
   inside it and he is in front of it, which is the whole depth of the
   picture — three planes and no more. */
.sea-figure {
  position: relative;
  /* Plate, rose and portrait are three prints of the same cell, stacked. That
     is what keeps them registered on each other: an offset would have to be
     re-guessed for RTL, for every breakpoint, and every time the art changes
     size. */
  display: grid;
  grid-template-areas: "stack";
  place-items: end center;
  min-height: clamp(320px, 38vw, 545px);
}

.sea-figure > * {
  grid-area: stack;
}

.sea-plate {
  position: relative;
  z-index: 0;
  align-self: center;
  width: clamp(285px, 33vw, 470px);
  aspect-ratio: 560 / 660;
  rotate: -2.2deg;
}

.sea-slab {
  width: 100%;
  height: 100%;
  overflow: visible;
}

.slab-back {
  fill: #04121f;
  transform: translate(16px, 18px);
}

.slab-face {
  fill: var(--sea-deep);
  stroke: rgba(233, 180, 76, 0.34);
  stroke-width: 2.5;
}

/* The rose, sized to the plate and set high in it, so it rings his head and
   shoulders instead of being buried behind his chest. It is drawn in two
   shades of the same brass so each point reads as folded, which is what a
   rose on a chart actually is — an engraving, not a star. */
.sea-rose {
  position: absolute;
  /* Centred on his chest, not his head, and wider than he is: what shows of
     it is the graduated ring arcing behind his shoulders, the way an
     instrument dial sits behind the person reading it. Point it at his face
     and the rose turns into a sunburst coming out of his cap. */
  inset-block-start: 22%;
  inset-inline: 0;
  margin-inline: auto;
  width: 96%;
  aspect-ratio: 1;
  opacity: 0.8;
}

/* The points are thin plate, not solid star: enough fill to read as folded
   metal, not enough to compete with the man standing in front of them. */
.rose-lit { fill: var(--brass); fill-opacity: 0.5; }
.rose-dim { fill: var(--brass-dim); fill-opacity: 0.34; }
.rose-hub { fill: #04121f; stroke: var(--brass); stroke-width: 2.5; }

/* The rings carry the weight instead. */
.rose-ring {
  fill: none;
  stroke: var(--brass);
  stroke-opacity: 0.72;
  stroke-width: 2.2;
}

.rose-ring-in { stroke-opacity: 0.34; stroke-width: 1.4; }

.rose-ticks line {
  stroke: var(--brass);
  stroke-opacity: 0.6;
  stroke-width: 1.5;
}

/* ------------------------------------------------------------------ the man */

.sea-portrait {
  position: relative;
  z-index: 1;
  display: block;
  align-self: end;
  width: clamp(240px, 29vw, 425px);
  /* He stands *in* the water: the crests break across his coat rather than
     stopping short of it. */
  margin-block-end: clamp(-5rem, -6vw, -2rem);
}

.sea-portrait img {
  display: block;
  width: 100%;
  height: auto;
  /* The photograph ends where it was taken — a straight cut across his coat —
     and a straight cut is what it looked like: a picture pasted on the sea
     rather than a man standing in it. The last stretch is faded out so the
     white of the coat goes into the water instead of stopping on top of it.
     The fall is long and late: cut it short and the fade reads as a smudge,
     start it early and he loses the buttons. */
  -webkit-mask-image: linear-gradient(to bottom,
                      #000 0%, #000 78%, rgba(0, 0, 0, 0.55) 92%, transparent 100%);
  mask-image: linear-gradient(to bottom,
              #000 0%, #000 78%, rgba(0, 0, 0, 0.55) 92%, transparent 100%);
  /* Two shadows doing different jobs: a tight dark one that cuts him out of
     the plate, and a wide cool one that is the water throwing light back up
     at him. The drop-shadow follows the mask, so the fade takes the shadow
     with it rather than leaving a hard silhouette under a soft edge. */
  filter:
    drop-shadow(0 10px 22px rgba(3, 14, 26, 0.72))
    drop-shadow(0 0 46px rgba(46, 134, 192, 0.28));
}

/* ------------------------------------------------------------- the instruments

   One line weight, one colour, drawn small and set at the edges of the plate
   where a chart prints its instrument marks. They are quiet on purpose: the
   rose is the loud one. */
.sea-tool {
  position: absolute;
  z-index: 2;
  fill: none;
  stroke: var(--brass);
  stroke-width: 3.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.82;
}

.sea-anchor {
  place-self: end start;
  margin: 0 0 16% 2%;
  width: clamp(50px, 6vw, 88px);
  rotate: -13deg;
}

.sea-sextant {
  place-self: start end;
  margin: 4% 2% 0 0;
  width: clamp(58px, 7vw, 104px);
  rotate: 9deg;
}

/* ------------------------------------------------------------------ the waves

   Where the chart stops and the paper starts. Four ranges of swell, the far
   one haze and the near one the page's own colour, so the hero hands off to
   the index rather than ending at a ruled line.

   Drawn, not filled: under each crest run the same line again, thinner and
   fainter, the way a chart steps its soundings down a slope. The near crest
   is ruled in brass — a chart rules the edge of its own sheet — and it is the
   one place the instruments' metal touches the water. */
.sea-waves {
  position: absolute;
  inset-block-end: -1px;
  inset-inline: 0;
  z-index: 3;
  line-height: 0;
  pointer-events: none;
}

/* The light behind the swell: a horizon glow that rises off the far range and
   lights the man's coat from below, so the water reads lit rather than
   painted. */
.sea-waves::before {
  content: "";
  position: absolute;
  inset-inline: -10%;
  inset-block-end: 22%;
  height: 120%;
  background: radial-gradient(60% 70% at 50% 100%,
    rgba(92, 184, 239, 0.28), rgba(46, 134, 192, 0.12) 45%, transparent 75%);
  pointer-events: none;
}

.sea-waves svg {
  position: relative;
  display: block;
  width: 100%;
  height: clamp(110px, 14vw, 200px);
  overflow: visible;
}

.wave-band { stroke: none; }

/* Far to near: haze, then two ranges with a top-lit gradient each so the
   crests have a face and a shadow, then the paper. */
.wave-band-1 { fill: rgba(92, 184, 239, 0.16); }
.wave-band-2 { fill: url(#wg2); }
.wave-band-3 { fill: url(#wg3); }
.wave-band-4 { fill: var(--bg-primary); }

.wg2-a { stop-color: rgba(92, 184, 239, 0.62); }
.wg2-b { stop-color: rgba(31, 110, 166, 0.55); }
.wg3-a { stop-color: #4aa3d9; }
.wg3-b { stop-color: #1b5f8f; }

/* The contours: the crest again, stepped down and thinned, in the spray's
   own paper colour. Each `use` is the closed band path with only its top
   edge inside the picture, so what shows is the line and nothing else. */
.wave-line {
  fill: none;
  stroke: var(--foam);
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.wave-line-a { stroke-width: 1.4; stroke-opacity: 0.42; }
.wave-line-b { stroke-width: 1.1; stroke-opacity: 0.2; }

/* The paper's edge, ruled. */
.wave-edge {
  fill: none;
  stroke: var(--brass);
  stroke-width: 1.6;
  stroke-opacity: 0.55;
  vector-effect: non-scaling-stroke;
}

/* A swell, not a loop of scenery: each range drifts and rises a different
   distance at a different rate, so the crests slide past each other the way
   real ranges do and the pattern never lines back up on itself. The far
   range moves most slowly and least: distance. */
@keyframes sea-swell {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(var(--drift, -3%), var(--bob, 0px), 0); }
}

.wave-range { will-change: transform; }
.wave-range-1 { --drift: -3.5%; --bob:  3px; animation: sea-swell 23s ease-in-out infinite alternate; }
.wave-range-2 { --drift:  3.2%; --bob: -5px; animation: sea-swell 17s ease-in-out infinite alternate; }
.wave-range-3 { --drift: -2.6%; --bob:  6px; animation: sea-swell 12s ease-in-out infinite alternate; }
.wave-range-4 { --drift:  1.8%; --bob: -3px; animation: sea-swell 14s ease-in-out infinite alternate; }

/* ------------------------------------------------------------------ arrival

   One sequence, once, on load: the plate lands, the rose settles onto its
   bearing, the man steps up, and the words come in behind him. Nothing here
   repeats — the only thing still moving after two seconds is the water. */
@keyframes sea-lift {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}

@keyframes sea-plate-in {
  from { opacity: 0; scale: 0.94; }
  to   { opacity: 1; scale: 1; }
}

/* The rose comes to rest the way a card compass does: it swings past the
   bearing and settles back onto it. */
@keyframes sea-rose-settle {
  from { opacity: 0; rotate: -26deg; }
  62%  { opacity: 1; rotate: 5deg; }
  to   { opacity: 0.92; rotate: 0deg; }
}

.sea-plate { animation: sea-plate-in 900ms var(--ease-out) both; }
.sea-rose { animation: sea-rose-settle 1500ms var(--ease-out) 180ms both; }
.sea-portrait { animation: sea-lift 900ms var(--ease-out) 260ms both; }
.sea-tool { animation: sea-lift 700ms var(--ease-out) 620ms both; }
.sea-copy > * { animation: sea-lift 720ms var(--ease-out) both; }
.sea-copy > *:nth-child(1) { animation-delay: 120ms; }
.sea-copy > *:nth-child(2) { animation-delay: 200ms; }
.sea-copy > *:nth-child(3) { animation-delay: 280ms; }
.sea-copy > *:nth-child(4) { animation-delay: 360ms; }
.sea-copy > *:nth-child(5) { animation-delay: 440ms; }

/* ------------------------------------------------------------------- phones

   One column, and the order flips: the man leads, the words follow. On a
   phone the portrait is the thing worth the top of the screen — it is what
   says whose course this is — and the heading reads better underneath it than
   squeezed beside it. */
@media (max-width: 860px) {
  .sea-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-lg);
    padding-block: clamp(1.25rem, 5vw, 2rem) clamp(9rem, 44vw, 12.5rem);
    text-align: center;
    justify-items: center;
  }

  .sea-copy {
    order: 2;
    justify-items: center;
  }

  .sea-lede { max-width: 40ch; }
  .sea-actions { justify-content: center; }

  .sea-figure {
    order: 1;
    min-height: clamp(280px, 66vw, 420px);
  }

  .sea-plate { width: clamp(210px, 52vw, 320px); }

  .sea-portrait {
    width: clamp(200px, 52vw, 330px);
    /* In one column there is nothing beside him to overlap into, so he keeps
       his own space — but he still stands in the water, not on it: the fade
       needs the crests to be breaking across it. */
    margin-block-end: clamp(-2rem, -5vw, -0.75rem);
  }

  /* The pool is a landscape shape; in one column the column is a portrait
     one, and it has to cover the whole of it. */
  .sea-copy::before { inset: -5% -7%; }

  /* The instruments stay. They were dropped here for crowding the plate, but
     they are half of what says whose course this is — and the crowding was
     the desktop's placement, not the objects: hung off the plate's corners at
     desktop size they collide with a portrait that now fills the column. Sized
     down and pushed out to the edges of the figure, clear of him, they read as
     the marks on a chart that they are. */
  .sea-tool {
    width: clamp(38px, 11vw, 62px);
    opacity: 0.9;
  }

  .sea-anchor  { margin: 0 0 22% 0; }
  .sea-sextant { margin: 10% 0 0 0; }

  /* The sea itself. At 14vw the four ranges were a strip a thumb wide under
     a tall column, and 1600 units of coastline squeezed into a phone's width
     is a saw blade rather than a swell. Taller, and drawn wider than the
     screen so each crest keeps its length; the hero clips the overrun. */
  .sea-waves svg {
    height: clamp(170px, 46vw, 220px);
    width: 220%;
    max-width: none; /* css/mobile.css caps every svg at 100%; this one is meant to overrun */
  }
}

/* The page prints the tile smaller on a phone; the sea has to print it at the
   same size or the two stop being one drawing at the only place the join
   shows. Both read their size from --chart-tile, set once in styles.css. */

@media (max-width: 460px) {
  .sea-actions { flex-direction: column; align-items: stretch; width: 100%; }
  .sea-cta { text-align: center; }
}

/* ------------------------------------------------------------------- dark

   The hero is already night water; in dark mode only the handoff changes —
   the near crest has to carry the dark page's colour instead of the paper's,
   or the wave ends on a band of cream above a black list. */
[data-theme="dark"] .sea-hero .wg2-a { stop-color: rgba(92, 184, 239, 0.4); }
[data-theme="dark"] .sea-hero .wg2-b { stop-color: rgba(31, 110, 166, 0.45); }
[data-theme="dark"] .sea-hero .wg3-a { stop-color: #2f80b4; }
[data-theme="dark"] .sea-hero .wg3-b { stop-color: #123f61; }
[data-theme="dark"] .sea-hero .wave-line { stroke-opacity: 0.3; }
[data-theme="dark"] .sea-hero .wave-line-b { stroke-opacity: 0.14; }

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

@media (prefers-reduced-motion: reduce) {
  .sea-plate,
  .sea-rose,
  .sea-portrait,
  .sea-tool,
  .sea-copy > *,
  .wave-range {
    animation: none;
  }

  .sea-plate { opacity: 1; scale: 1; }
  .sea-rose  { opacity: 0.92; rotate: 0deg; }
}

@media print {
  .sea-chart,
  .sea-waves,
  .sea-tool { display: none; }

  .sea-hero { background: none; }
  .sea-title { color: #000; }
  .sea-lede { color: #333; }
}
