/* Starship Rescue — starship-rescue.com
   Vector-display palette: everything is line work on near-black, lit by a
   phosphor bloom. Colour never carries meaning on its own. */

/* ---------------------------------------------------------------- fonts -- */

@font-face {
  font-family: 'Archivo';
  src: url('fonts/Archivo-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('fonts/JetBrainsMono-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('fonts/JetBrainsMono-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

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

:root {
  --bg: #04060b;
  --ink: #e6ebff;      /* default text */
  --ink-bright: #eafbff; /* headings and the wordmark */
  --lead: #c9d3f5;     /* opening paragraphs, card headings */
  --prose: #8e97b8;    /* body copy                     7.02:1 */
  --soft: #7c839e;     /* small print, nav, card copy   5.40:1 */
  --label: #6e7899;    /* eyebrow labels, captions      4.64:1 */

  /* --soft and --label are lifted from the designs' #6A7290 and #5E6786,
     which came to 4.27:1 and 3.63:1 on --bg against the 4.5:1 WCAG AA needs
     at the sizes they are used. Hue and saturation are unchanged, and the
     three text tiers stay a visible step apart. */

  --cyan: #22e8ff;
  --amber: #ffb020;
  --mint: #2bf5c4;
  --violet: #8a5cff;

  --rule-strong: rgba(91, 60, 216, 0.35);
  --rule-soft: rgba(91, 60, 216, 0.22);
  --hair-cyan: rgba(34, 232, 255, 0.24);
  --hair-violet: rgba(91, 60, 216, 0.35);
  --edge-cyan: rgba(34, 232, 255, 0.3);

  --display: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --measure: 1080px;
  --gutter: 24px;
}

/* ---------------------------------------------------------------- reset -- */

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

html {
  scroll-behavior: smooth;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 15px;
  line-height: 1.85;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img {
  max-width: 100%;
}

picture {
  display: block;
}

a {
  color: var(--cyan);
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}

a:hover {
  color: var(--amber);
}

:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 3px;
}

::selection {
  background: rgba(34, 232, 255, 0.28);
  color: var(--ink-bright);
}

/* --------------------------------------------------------------- layout -- */

.wrap {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.section {
  padding: 86px 0;
  border-bottom: 1px solid var(--rule-soft);
}

.section--tight {
  padding: 76px 0 66px;
}

.section--last {
  border-bottom: 0;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  padding: 12px 18px;
  background: var(--cyan);
  color: var(--bg);
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
}

.skip:focus {
  left: 0;
}

/* Visually hidden, still read aloud and still indexed.

   The hero h1 is a picture — the mark carries a gradient, an inline and a glow
   no webfont reproduces — so the element's own text content is empty. Alt text
   covers assistive technology, but a crawler reading <h1> sees nothing, which
   leaves the page's strongest on-page signal blank. This puts the real heading
   text back inside the h1 without touching the artwork. It is the same words
   the mark shows, so it is a description of the image, not a hidden keyword
   list. Do not repurpose it as one. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------ site head -- */

/* The masthead is lit by one piece of artwork — the ship climbing through the
   colour rain — sitting under the drifting rocks and the type. It is a
   background rather than an <img> because none of it is information: the
   header's meaning is carried by the wordmark, the mark and the lead, and the
   picture only has to set the light they are read in.

   Two background-image declarations rather than one. The first names the JPEG
   that every browser understands; the second swaps in the far smaller WebP
   wherever image-set() is supported, and is thrown away as unparseable
   everywhere else. A background cannot be a <picture>, so this is the only way
   to offer both formats.

   The artwork is meant to be seen at full strength rather than pushed back
   behind a wash, so the scrim over it is a vertical gradient with a hole in
   the middle: near-solid across the bar and the eyebrow at the top, open from
   roughly a quarter to a half where the ship and its plume are, then closing
   hard from 63% down to --bg at the foot.

   That closing ramp is doing accessibility work rather than art. The exhaust
   plume runs the full height of the picture and is the brightest thing in it,
   and the hero's reading matter sits directly under it. Measured off a render
   at 1440px, an even scrim left the lead at 3.1:1 and the note beneath the
   store buttons — set in --soft, which is only picked because it clears 4.5:1
   on --bg — at 3.8:1. Steepening the bottom of the gradient puts them at
   8.9:1 and 5.2:1. The eyebrow is the reason .hero__mark carries the headroom
   rather than .hero: left in the gap between the ship and the mark it sat on
   the brightest part of the plume at 2.6:1, and moving it up above the ship
   puts it in the dark band at 10.3:1.

   The crop is held below centre so the ship clears the mark instead of sitting
   behind it. */
.sitehead {
  position: relative;
  border-bottom: 1px solid var(--rule-strong);
  overflow: hidden;
  background-color: var(--bg);
  background-image:
    linear-gradient(
      to bottom,
      rgba(4, 6, 11, 0.86) 0%,
      rgba(4, 6, 11, 0.8) 10%,
      rgba(4, 6, 11, 0.06) 25%,
      rgba(4, 6, 11, 0.03) 48%,
      rgba(4, 6, 11, 0.44) 63%,
      rgba(4, 6, 11, 0.86) 80%,
      rgba(4, 6, 11, 0.97) 100%
    ),
    url('hero/masthead.jpg');
  background-image:
    linear-gradient(
      to bottom,
      rgba(4, 6, 11, 0.86) 0%,
      rgba(4, 6, 11, 0.8) 10%,
      rgba(4, 6, 11, 0.06) 25%,
      rgba(4, 6, 11, 0.03) 48%,
      rgba(4, 6, 11, 0.44) 63%,
      rgba(4, 6, 11, 0.86) 80%,
      rgba(4, 6, 11, 0.97) 100%
    ),
    image-set(
      url('hero/masthead.webp') type('image/webp'),
      url('hero/masthead.jpg') type('image/jpeg')
    );
  background-repeat: no-repeat;
  background-size: cover;
  background-position: 50% 60%;
}

/* Below about 1000px the header is taller than it is wide against the
   picture's own proportions, so cover starts scaling to fit the height rather
   than the width: the whole picture is in frame, cropped at the sides, and
   background-position stops having anything to move. The ship lands at a fixed
   27–50% of the header whatever is done to it, and the plume runs edge to edge
   through every line below. So the crop is left alone and the scrim closes
   earlier and harder instead — the lead measures 5.0:1 at 390px, where the
   desktop ramp left it at 2.6:1. */
@media (max-width: 1000px) {
  .sitehead {
    background-image:
      linear-gradient(
        to bottom,
        rgba(4, 6, 11, 0.86) 0%,
        rgba(4, 6, 11, 0.8) 8%,
        rgba(4, 6, 11, 0.06) 16%,
        rgba(4, 6, 11, 0.08) 36%,
        rgba(4, 6, 11, 0.45) 46%,
        rgba(4, 6, 11, 0.8) 58%,
        rgba(4, 6, 11, 0.93) 74%,
        rgba(4, 6, 11, 0.97) 100%
      ),
      url('hero/masthead.jpg');
    background-image:
      linear-gradient(
        to bottom,
        rgba(4, 6, 11, 0.86) 0%,
        rgba(4, 6, 11, 0.8) 8%,
        rgba(4, 6, 11, 0.06) 16%,
        rgba(4, 6, 11, 0.08) 36%,
        rgba(4, 6, 11, 0.45) 46%,
        rgba(4, 6, 11, 0.8) 58%,
        rgba(4, 6, 11, 0.93) 74%,
        rgba(4, 6, 11, 0.97) 100%
      ),
      image-set(
        url('hero/masthead.webp') type('image/webp'),
        url('hero/masthead.jpg') type('image/jpeg')
      );
  }
}

.sitehead__bar {
  position: relative;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 22px var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

.wordmark {
  font-family: var(--display);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.22em;
  color: var(--ink-bright);
  text-decoration: none;
  text-shadow: 0 0 18px rgba(34, 232, 255, 0.55);
}

.wordmark:hover {
  color: var(--ink-bright);
  text-shadow: 0 0 22px rgba(34, 232, 255, 0.9);
}

.nav {
  display: flex;
  gap: 26px;
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}

.nav a {
  color: var(--soft);
  text-decoration: none;
}

.nav a:hover {
  color: var(--cyan);
}

.nav a[aria-current='page'] {
  color: var(--cyan);
}

/* Drifting wireframe rocks behind the masthead. */
#rocks {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* ----------------------------------------------------------------- hero -- */

.hero {
  position: relative;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 30px var(--gutter) 84px;
  text-align: center;
}

/* The radial darkener that used to sit here is gone. It existed to keep the
   drifting rocks from fighting the wordmark, and against line work on black it
   could afford to be nearly opaque at the centre. Over the artwork it punched
   a black hole through the middle of the picture and swallowed the ship whole,
   and with the scrim on .sitehead now shaped around the type it was no longer
   earning the contrast it cost. .hero > * keeps its stacking context. */

.hero > * {
  position: relative;
}

/* The h1 is a single image, so it gets no type properties at all — line-height
   0 stops the inline box adding a descender's worth of space under it. */
/* The headroom for the ship hangs off the mark rather than off .hero's top
   padding, so that the eyebrow is pushed up above the artwork instead of being
   stranded in the gap between the ship and the mark, which is the brightest
   part of the plume and the one place on the page small amber type cannot be
   read. Everything below the mark keeps the spacing it had. */
.hero__mark {
  margin: 340px 0 0;
  line-height: 0;
}

.hero__mark img {
  width: clamp(240px, 82vw, 620px);
  height: auto;
  /* The mark brings its own outer glow, so the cyan text-shadow the wordmark
     used to carry would sit under it as a second, wrong-coloured halo. This is
     the same bloom in the mark's own green, only enough to keep it in the same
     light as the rule and the eyebrow. */
  filter: drop-shadow(0 0 30px rgba(140, 220, 40, 0.32));
}

/* .rule, .lead and .note carry their own auto margins now, so the hero no
   longer needs to override them. Only the tighter spacing under the buttons is
   still hero-specific. */
.hero .note {
  margin: 18px auto 0;
}

/* ------------------------------------------------------------ typography -- */

/* Section headings meet the hero in the middle. The hero was the only centred
   thing on a long left-aligned page, which read as a mistake rather than as a
   title card. Centring the label-and-heading pair carries that axis down the
   page; the reading matter below stays left-aligned, because centred prose is
   hard to read and centred lists are worse. Those blocks are measure-limited,
   so auto margins sit the column under the heading rather than against the
   gutter. That is why .rule, .lead and .note carry auto margins in their base
   rules rather than only inside the hero. */

.eyebrow {
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.34em;
  color: var(--amber);
  text-transform: uppercase;
  text-shadow: 0 0 12px rgba(255, 176, 32, 0.8);
}

.kicker {
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.24em;
  color: var(--label);
  text-transform: uppercase;
}

.kicker--amber {
  color: var(--amber);
}

.rule {
  width: 150px;
  height: 1px;
  background: var(--cyan);
  box-shadow: 0 0 12px var(--cyan);
  margin: 26px auto 0;
  border: 0;
}

.page-title {
  text-align: center;
  font-family: var(--display);
  font-weight: 700;
  margin: 16px 0 0;
  font-size: clamp(32px, 6vw, 54px);
  letter-spacing: 0.1em;
  line-height: 1.04;
  color: var(--ink-bright);
  text-shadow: 0 0 6px var(--cyan), 0 0 34px rgba(34, 232, 255, 0.5);
}

.page-title--wide {
  font-size: clamp(34px, 7vw, 64px);
  letter-spacing: 0.08em;
  line-height: 1;
}

h2.heading {
  text-align: center;
  font-family: var(--display);
  font-weight: 700;
  margin: 14px 0 16px;
  font-size: clamp(22px, 3.4vw, 32px);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-bright);
}

h2.heading--flush {
  margin-bottom: 0;
}

.lead {
  max-width: 34em;
  margin: 26px auto 0;
  font-size: 15px;
  line-height: 1.85;
  color: var(--lead);
  text-wrap: pretty;
}

.lead--wide {
  max-width: 36em;
}

.prose {
  max-width: 46em;
  margin-left: auto;
  margin-right: auto;
  font-size: 15px;
  line-height: 1.9;
  color: var(--prose);
  text-wrap: pretty;
}

.prose em {
  color: var(--lead);
  font-style: normal;
}

.prose--spaced {
  margin-top: 34px;
}

.prose--intro {
  margin: 16px auto 0;
}

.note {
  max-width: 36em;
  margin: 22px auto 0;
  font-size: 13px;
  line-height: 2;
  color: var(--prose);
}

/* ---------------------------------------------------------------- grids -- */

/* Hairline grids: a 1px gap over a coloured backdrop draws the rules, so the
   cells stay flush and the lines never double up at the seams. */
.grid {
  display: grid;
  gap: 1px;
  background: var(--hair-cyan);
  margin-top: 44px;
}

.grid--violet {
  background: var(--hair-violet);
}

/* Column counts are explicit rather than auto-fit: the hairlines are the
   container's background showing through the 1px gaps, so a part-filled last
   row would leak that colour across the empty tracks. Every count below
   divides its item count exactly. */

/* Three cells: how-it-works, support contacts. */
.grid--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* Six cells: the fact table, the accessibility settings. */
.grid--6 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* Four cells: the privacy summary, the storyboard specs. */
.grid--4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

@media (max-width: 860px) {
  .grid--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 760px) {
  .grid--3 {
    grid-template-columns: minmax(0, 1fr);
  }

  .grid--6 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 480px) {
  .grid--6,
  .grid--4 {
    grid-template-columns: minmax(0, 1fr);
  }
}

.stack {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--hair-violet);
  margin-top: 42px;
}

.stack--cyan {
  background: var(--hair-cyan);
}

.cell {
  background: var(--bg);
  padding: 28px 24px;
}

.cell--sm {
  padding: 26px 24px;
}

.cell--row {
  padding: 30px 26px;
  display: grid;
  gap: 14px;
}

.cell--fact {
  padding: 20px 18px;
}

.cell--stat {
  padding: 22px 20px;
}

.cell__num {
  font-size: 22px;
  color: var(--amber);
  text-shadow: 0 0 12px rgba(255, 176, 32, 0.7);
}

.cell h3 {
  margin: 14px 0 10px;
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--lead);
}

.cell--row h2,
.cell--row h3 {
  margin: 0;
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--lead);
}

.cell--sm h3 {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--lead);
}

/* Body copy inside a cell. Scoped to unclassed paragraphs so the modifier
   classes below (.tag, .cell__value, .stat__value, .beat__meta) are not
   outranked by this rule's extra type selector. */
.cell p:not([class]) {
  margin: 0;
  font-size: 12px;
  line-height: 1.95;
  color: var(--soft);
}

.cell--row p:not([class]) {
  max-width: 52em;
  font-size: 13px;
  line-height: 2;
  color: var(--prose);
  text-wrap: pretty;
}

.cell--sm {
  display: grid;
  gap: 10px;
}

.tag {
  font-size: 9px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--label);
}

.tag--amber {
  color: var(--amber);
}

.tag--mint {
  color: var(--mint);
}

.tag--violet {
  color: var(--violet);
}

.cell__value {
  margin-top: 12px;
  font-size: 16px;
  color: var(--ink);
}

.cell__value a,
.stat__value a {
  text-decoration: none;
  word-break: break-all;
}

.cell__aside {
  margin-top: 8px;
  font-size: 11px;
  line-height: 1.9;
  color: var(--soft);
}

.cell__note {
  margin-top: 12px;
  font-size: 11px;
  line-height: 1.9;
  color: var(--soft);
}

.stat__value {
  margin: 10px 0 0;
  font-size: 14px;
  color: var(--mint);
}

.stat__value--link {
  color: var(--ink);
}

/* ----------------------------------------------------------------- dl -- */

.facts {
  margin: 40px 0 0;
}

.facts dt {
  font-size: 9px;
  letter-spacing: 0.2em;
  color: var(--label);
  text-transform: uppercase;
}

.facts dd {
  margin: 9px 0 0;
  font-size: 14px;
  color: var(--ink);
}

.facts .sub {
  font-size: 10px;
  letter-spacing: 0.24em;
  color: var(--label);
  text-transform: uppercase;
}

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

.actions {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 38px;
}

/* The store row sits above the secondary action, so it takes the full top
   margin and the one below it tightens up. */
.actions--stores {
  gap: 16px;
}

.actions--stores + .actions {
  margin-top: 18px;
}

/* ------------------------------------------------------- store buttons -- */

/* Deliberately NOT reproductions of Apple's and Google's official badges.
   Both stores supply badge artwork and require it be used unaltered, at their
   own minimum sizes and clear space — and neither badge may be shown for an
   app that is not on the store. So these are the site's own buttons, in the
   site's own palette, carrying the store names as plain text. Swap in the
   official assets when the listings go live and the links become real.

   The glyphs are generic on purpose: a download arrow and a play triangle,
   not the Apple mark or the Play four-colour device, which are trademarks. */
.storebtn {
  display: inline-flex;
  align-items: center;
  gap: 13px;
  padding: 12px 22px 12px 18px;
  border: 1px solid var(--cyan);
  background: var(--cyan);
  color: var(--bg);
  text-decoration: none;
  box-shadow: 0 0 26px rgba(34, 232, 255, 0.45);
}

.storebtn:hover {
  background: #7cf3ff;
  border-color: #7cf3ff;
  box-shadow: 0 0 34px rgba(34, 232, 255, 0.7);
}

.storebtn:focus-visible {
  outline: 2px solid var(--ink-bright);
  outline-offset: 3px;
}

.storebtn__glyph {
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The play triangle is a solid shape, not an outline. */
.storebtn[data-store-link="google"] .storebtn__glyph {
  fill: currentColor;
  stroke-width: 1.2;
}

.storebtn__text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.15;
}

.storebtn__kicker {
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.72;
}

.storebtn__name {
  font-family: 'Archivo', system-ui, sans-serif;
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.02em;
}

/* Stacked, the two buttons size to their own text and the shorter one reads as
   a mistake. Fix the width so the column has one edge. */
@media (max-width: 560px) {
  .actions--stores {
    flex-direction: column;
    align-items: center;
  }

  .storebtn {
    width: min(268px, 100%);
  }
}

.btn {
  display: inline-block;
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 16px 26px;
  text-decoration: none;
  border: 1px solid var(--cyan);
}

.btn--solid {
  background: var(--cyan);
  color: var(--bg);
  box-shadow: 0 0 26px rgba(34, 232, 255, 0.45);
}

.btn--solid:hover {
  background: #7cf3ff;
  border-color: #7cf3ff;
  color: var(--bg);
  box-shadow: 0 0 34px rgba(34, 232, 255, 0.7);
}

.btn--ghost {
  border-color: rgba(34, 232, 255, 0.45);
  color: var(--cyan);
}

.btn--ghost:hover {
  background: rgba(34, 232, 255, 0.14);
  border-color: var(--cyan);
  color: var(--cyan);
}

/* Currently unused: the hero's "in development" strip was removed. Kept
   because the launch badge is the same component with different words --
   "Now on the App Store" wants exactly this treatment. Delete it if that
   never happens. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-top: 34px;
  border: 1px solid rgba(255, 176, 32, 0.4);
  padding: 11px 18px;
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--amber);
  text-transform: uppercase;
}

.badge::before {
  content: '';
  width: 7px;
  height: 7px;
  background: var(--amber);
  box-shadow: 0 0 10px var(--amber);
  transform: rotate(45deg);
  flex: 0 0 auto;
}

/* ---------------------------------------------------------------- shots -- */

.shots {
  display: flex;
  gap: 22px;
  overflow-x: auto;
  padding: 44px 0 8px;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  scrollbar-color: var(--edge-cyan) transparent;
}

.shots::-webkit-scrollbar {
  height: 6px;
}

.shots::-webkit-scrollbar-thumb {
  background: var(--edge-cyan);
}

.shot {
  flex: 0 0 auto;
  width: 246px;
  margin: 0;
  scroll-snap-align: start;
}

.shot img {
  width: 100%;
  height: auto;
  display: block;
  border: 1px solid var(--edge-cyan);
  background: #000;
}

.shot figcaption {
  margin-top: 12px;
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--label);
  text-transform: uppercase;
}

/* --------------------------------------------------------------- footer -- */

.sitefoot {
  padding: 56px 0 76px;
  font-size: 11px;
  line-height: 2.1;
  color: var(--label);
}

.sitefoot__links {
  display: flex;
  gap: 26px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}

.sitefoot__links a {
  color: var(--soft);
  text-decoration: none;
}

.sitefoot__links a:hover {
  color: var(--cyan);
}

.sitefoot p {
  max-width: 52em;
}

.sitefoot strong {
  color: var(--soft);
  font-weight: 400;
}

/* ------------------------------------------------------------ storyboard -- */

.beat {
  background: var(--bg);
  padding: 26px 24px;
  display: grid;
  gap: 22px;
}

.beat__head {
  display: flex;
  gap: 18px;
  align-items: baseline;
  flex-wrap: wrap;
}

.beat__time {
  font-size: 22px;
  color: var(--amber);
  text-shadow: 0 0 12px rgba(255, 176, 32, 0.7);
}

.beat__head h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-bright);
}

.beat__body {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  gap: 24px;
  align-items: start;
}

.beat__body > div:last-child {
  display: grid;
  gap: 14px;
}

.beat__body p:not([class]) {
  margin: 0;
  font-size: 13px;
  line-height: 2;
  color: var(--prose);
  text-wrap: pretty;
}

.beat__body img {
  width: 100%;
  height: auto;
  display: block;
  border: 1px solid var(--edge-cyan);
  background: #000;
}

.beat__meta {
  font-size: 11px;
  line-height: 1.9;
  color: var(--label);
}

.beat__meta span {
  color: var(--lead);
}

/* Placeholder for a frame that has to be captured on a device. */
.beat__todo {
  width: 100%;
  aspect-ratio: 402 / 874;
  border: 1px solid var(--edge-cyan);
  background: repeating-linear-gradient(135deg, #04060b 0 7px, #0a0e1a 7px 14px);
  display: grid;
  place-items: center;
  padding: 10px;
  text-align: center;
  font-size: 9px;
  line-height: 1.8;
  letter-spacing: 0.14em;
  color: var(--label);
  text-transform: uppercase;
}

.beat__endcard {
  width: 100%;
  aspect-ratio: 402 / 874;
  border: 1px solid var(--edge-cyan);
  background: var(--bg);
  display: grid;
  place-items: center;
  padding: 14px;
  text-align: center;
}

.beat__endcard b {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.16em;
  color: var(--ink-bright);
  text-shadow: 0 0 18px rgba(34, 232, 255, 0.6);
  line-height: 1.4;
}

.beat__endcard span {
  display: block;
  margin-top: 10px;
  font-size: 8px;
  letter-spacing: 0.2em;
  color: var(--amber);
  text-transform: uppercase;
}

.callout {
  border: 1px solid rgba(255, 176, 32, 0.4);
  padding: 26px 24px;
  display: grid;
  gap: 12px;
}

.callout p:not([class]) {
  margin: 0;
  max-width: 52em;
  font-size: 13px;
  line-height: 2;
  color: var(--prose);
  text-wrap: pretty;
}

@media (max-width: 560px) {
  .beat__body {
    grid-template-columns: minmax(0, 1fr);
  }

  .beat__body picture,
  .beat__todo,
  .beat__endcard {
    max-width: 180px;
  }
}

/* ------------------------------------------------------------------ 404 -- */

.oops {
  min-height: 72vh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 80px var(--gutter);
}

.oops .rule {
  margin: 26px auto 0;
}

.oops .lead {
  margin-left: auto;
  margin-right: auto;
}

code {
  font-family: var(--mono);
  font-size: 0.92em;
  color: var(--cyan);
  background: rgba(34, 232, 255, 0.08);
  padding: 1px 5px;
}

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

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  #rocks {
    display: none;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Bloom is decoration; when the reader has asked for contrast, drop it. The
   masthead artwork goes with it — it is the loudest thing on the page and the
   header's text has to be read over the top of it. The headroom goes with the
   picture: it is there to clear a ship that is no longer being drawn, and left
   behind it is just a hole above the mark. */
@media (prefers-contrast: more) {
  .sitehead {
    background-image: none;
  }

  .hero__mark {
    margin-top: 14px;
  }

  .hero__mark img {
    filter: none;
  }

  .page-title,
  .wordmark,
  .eyebrow,
  .cell__num,
  .beat__time {
    text-shadow: none;
  }

  .rule {
    box-shadow: none;
  }

  body {
    color: #f2f5ff;
  }

  :root {
    --prose: #b6bedd;
    --soft: #9aa2c0;
    --label: #8a92b0;
  }
}

/* --------------------------------------------------------------- print -- */

@media print {
  body {
    background: #fff;
    color: #000;
  }

  #rocks,
  .actions,
  .skip {
    display: none;
  }

  .sitehead {
    background-image: none;
  }

  /* Same as the contrast block: no ship to clear, so no headroom to keep. */
  .hero__mark {
    margin-top: 14px;
  }

  .hero__mark img {
    filter: none;
  }

  .page-title,
  .wordmark {
    color: #000;
    text-shadow: none;
  }

  .prose,
  .lead,
  .cell p {
    color: #222;
  }
}
