/* 60 Countdown. A launch sequencer. A vertical ladder of T minus times runs
   down the page, each capability is a sequence event pegged to the rail, and a
   status column calls GO or STANDBY. Deep blue-black, pale ice text and a bright signal blue, the comet palette.

   The capabilities are five full-width sequence rows stacked down the page. At
   rest a row is a compact strip: T minus time, event title, status lamp. Hover
   or keyboard focus arms the row and the drawer under the title opens on a
   grid-template-rows transition, revealing the description and the event
   diagram. Because the drawer is a grid track and not an overlay, opening a row
   pushes the rows below it down and nothing is ever covered.

   One small script, and only for the comet cursor. Delete it and every
   cursor rule below goes unused and nothing else changes. The open state is
   the default: if a reader has asked for reduced
   motion, or the viewport is narrow, every drawer renders open and the whole
   sequence reads as a plain document. */

:root {
  --bg: #000000;
  --surface: #0a1425;
  --surface-2: #0f1a33;
  --ink: #eef4f9;
  --ink-soft: #8797ad;
  --ink-body: #c3ccd4;
  --brand: #4da6ff;
  --on-brand: #000000;
  --border: #1e2d4a;
  --rule: #4da6ff;
  --rule-2: #2e4060;
  --ph-ink: #eef4f9; --ph-bg: #0d1a33; --ph-border: #4da6ff;
  --fig-thin: #2e4060; --fig-traj: #4da6ff; --fig-stroke: #eef4f9;
  --fig-fill: #000000; --fig-axis: #7889a0; --fig-label: #8797ad;
}

html { scroll-behavior: smooth; }

body { margin: 0; background: var(--bg); color: var(--ink-body);
  font: 15.5px/1.65 Helvetica, Arial, sans-serif; }

.bar { position: sticky; top: 0; z-index: 5; display: flex; align-items: center;
  gap: 20px; padding: 13px 5vw; background: rgba(0, 0, 0, 0.92);
  border-bottom: 1px solid var(--border); }
.mark { display: inline-flex; align-items: center; gap: 11px;
  font-size: 12.5px; font-weight: 700; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink); text-decoration: none; }
/* The ring wordmark, white ink, because the bar behind it is black. Height is
   fixed and width follows the 1.306:1 artwork, so the mark never distorts. */
.marklogo { flex: none; height: 30px; width: auto; display: block; }
.mark span { color: var(--ink-soft); }
/* auto margin on the left, so the nav is pushed to the far right of the bar */
.bar nav { margin-left: auto; }
.bar nav a { margin-left: 26px; font-size: 15px; color: var(--ink);
  text-decoration: none; }
.bar nav a:hover, .bar nav a:focus-visible { color: var(--brand); }

/* v5. The flagged nav entry.

   One item in the bar has to be louder than the rest for as long as the
   congress is ahead of us, and then go quietly back to being an ordinary link
   by deleting one class from the markup and this block from here.

   A ring and a slow breath rather than a filled chip, so the bar keeps its
   balance: nothing changes except that one item is circled. Only transform and
   box-shadow are animated. Neither takes part in layout, so the items either
   side never move -- which is the difference between a nav that draws the eye
   and one that makes the page feel unstable.

   Ten treatments were drawn. This is 01, ring and breathe; the other nine are
   in finalproximity/navbutton/ and each is a drop-in replacement for this
   block alone.

   Amplitude raised 11 August 2026: the swell went from 3.5% to 7.5%, the ring
   from 1px to 1.5px and the glow from a hint to a flare. The first draft was
   tuned not to be noticed, which is the wrong target for an entry whose whole
   job is to be noticed. */
.bar nav a.navflag {
  position: relative;
  display: inline-block;
  padding: 5px 14px;
  border: 1.5px solid var(--brand);
  border-radius: 999px;
  color: var(--brand);
  font-weight: 600;
  animation: navflag-breathe 2.6s ease-in-out infinite;
}
@keyframes navflag-breathe {
  0%, 100% { transform: scale(1);
             border-color: #4da6ff;
             box-shadow: 0 0 0 0 rgba(77, 166, 255, 0.60),
                         0 0 8px rgba(77, 166, 255, 0.30); }
  50%      { transform: scale(1.075);
             border-color: #a8d8ff;
             box-shadow: 0 0 0 10px rgba(77, 166, 255, 0),
                         0 0 30px 4px rgba(77, 166, 255, 0.75); }
}
/* Hover stops the movement rather than adding to it: the reader has found the
   thing the animation was for, so the animation has done its job. */
.bar nav a.navflag:hover, .bar nav a.navflag:focus-visible {
  animation-play-state: paused;
  background: rgba(77, 166, 255, 0.18);
  color: var(--ink);
}
/* The ring survives, the movement does not. A reader who has asked for less
   motion still needs to see which entry is being pointed at. */
@media (prefers-reduced-motion: reduce) {
  .bar nav a.navflag { animation: none;
    box-shadow: 0 0 14px rgba(77, 166, 255, 0.45); }
}

/* v5. The news hero figure, pulled up under the standfirst.

   The default gap there is four separate spaces stacked on top of each other:
   the standfirst's own bottom margin, the hero's bottom padding, the section's
   top padding and the figure's top margin. Each is defensible alone and
   together they leave the picture stranded half a screen below the sentence it
   belongs to.

   All four are zeroed and one 24px space is put back, which is one line of body
   text at this size. Both classes are only ever used on /news/, so nothing else
   in the template can be moved by this.

   Specificity, not order: lts.css loads after this file, so these have to
   out-specify .lts-hero, .sec and .lts-fig rather than merely follow them. */
   The same treatment then carries on down: figure to stat band, stat band to
   the first real section. Each of those joins is two 6vh paddings meeting,
   which is most of a screen of nothing between four blocks that are one
   introduction. Every join in the run is a single 24px space, and normal
   spacing resumes below the ladder. */
.lts-hero.hero-tight { padding-bottom: 0; }
.lts-hero.hero-tight .sub { margin-bottom: 0; }
.sec.sec-hero-fig { padding-top: 24px; padding-bottom: 0; }
.sec.sec-hero-fig .lts-fig { margin-top: 0; }
.sec.sec-stats { padding-top: 24px; padding-bottom: 0; }
.sec.sec-after-stats { padding-top: 24px; }

/* v5. Partner marks inside a chronology entry.

   A logobox is a figbox that holds affiliations rather than a photograph, so
   it copies the figbox's job of continuing the card: same surface, same
   border, no border where the two cells meet, and it lifts with the rest of
   the band on hover. It is a <figure> and not a <div> on purpose -- the band
   rules in lts.css are written against div, so a figure sits outside them and
   does not have to fight for specificity.

   The marks themselves follow the same rule as the homepage marquee: they are
   supplied on white, they are not ours to restyle, so each keeps its own chip
   and is only dimmed until hovered. Stacked, not scrolled -- these are the
   affiliations on one paper and the reader is checking a list, not watching a
   band go past. */
.lts-tick .logobox {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 8px;
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: none;
  padding: 30px 32px 30px 0;
  transition: transform 0.2s ease, border-color 0.2s linear, background 0.2s linear;
}
.lts-tick:hover .logobox {
  border-color: var(--brand);
  background: var(--surface-2, #141a22);
  transform: translateX(6px);
}
.lts-tick .logobox img {
  display: block;
  /* 46px, not 34. A partner mark at 34px is a footnote; the collaboration is
     the substance of these entries, so the marks are sized to be read rather
     than merely acknowledged. The widest of them, DLR at 455:154, comes to
     158px inside a 210px column, so the tallest still fits without wrapping
     mid-row. */
  height: 46px;
  width: auto;
  padding: 7px 13px;
  background: #ffffff;
  border-radius: 3px;
  opacity: 0.86;
  transition: opacity 0.2s linear;
  /* Every mark opens in the zoom overlay, the same as the photographs, so the
     pointer has to say so. A logo at 34px is exactly the case where a reader
     wants a closer look. */
  cursor: zoom-in;
}
.lts-tick .logobox img:hover { opacity: 1; }
.lts-tick .logobox img:focus-visible {
  opacity: 1;
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}
/* Marks drawn in light ink for a dark ground, ours among them. A white chip
   would mean recolouring them, so they keep the ground they were designed for
   and take a hairline instead, or a black chip on a black page has no edge. */
.lts-tick .logobox img.pdark {
  background: #000000;
  box-shadow: inset 0 0 0 1px var(--rule-2);
}
.lts-tick .logobox figcaption {
  flex-basis: 100%;
  margin: 2px 0 0;
  font-size: 11.5px;
  line-height: 1.5;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
/* A centimetre of clear air above a call to action that follows a dense block.
   The four-entry ladder above this one ends in a bordered band, and a button
   sitting straight underneath it reads as part of the last entry rather than as
   the answer to all four.

   1cm literally: CSS knows the unit, it resolves to 37.8px at the reference
   pixel ratio, and writing what was asked for is clearer here than converting
   it to a number nobody can check against the request. */
.cta-row.cta-gap { margin-top: 1cm; }

/* The one-line fact strip under a session title: day, time, room, format,
   separated by bullets. A line rather than the papmeta grid, because four
   short facts read faster across than down and the entry stays compact enough
   to sit above a disclosure. */
.lts-tick .papline {
  margin: 0 0 14px !important;
  font-size: 13.5px !important;
  line-height: 1.7;
  color: var(--ink-soft) !important;
}
.lts-tick .papline b { color: var(--ink-body); font-weight: 600; }
.lts-tick .papline span { color: var(--rule-2); margin: 0 4px; }

/* Read more. A native <details>, so it works with the script blocked, is in
   the accessibility tree either way, and is found by the browser's own
   find-on-page, which no JavaScript accordion manages. */
.lts-tick .pdetail { margin: 0; }
.lts-tick .pdetail > summary {
  display: inline-block;
  cursor: pointer;
  font-size: 13.5px;
  color: var(--brand);
  list-style: none;
}
.lts-tick .pdetail > summary::-webkit-details-marker { display: none; }
.lts-tick .pdetail > summary::after { content: " \2026"; }
.lts-tick .pdetail[open] > summary::after { content: ""; }
.lts-tick .pdetail[open] > summary { margin-bottom: 10px; }
.lts-tick .pdetail > summary:hover { text-decoration: underline; }
.lts-tick .pdetail > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* A logo column carrying two marks rather than five, so each can be half as
   tall again and still fit the width. Magdrive at 305:154 comes to 135px and
   ours at 900:689 to 89px, both inside the column. */
.lts-tick .logobox-lg img { height: 68px; padding: 10px 16px; }

/* An enlarged mark keeps the chip it wears on the page. The overlay in lts.css
   backs every image with black, which is right for a photograph and fatal for
   a logo drawn in dark ink on a transparent ground: it would open to nothing.
   Two classes rather than one, because the marks drawn in light ink need the
   opposite treatment and would disappear on white.

   Specificity, not order: lts.css loads after this file, so these carry an
   extra class each to out-rank .zoombox img rather than merely follow it. */
.zoombox.zoom-mark img {
  background: #ffffff;
  padding: 5vmin;
  max-width: 70vw;
  max-height: 60vh;
  border-color: var(--rule-2);
}
.zoombox.zoom-mark.zoom-dark img {
  background: #000000;
}

/* The session facts under a paper: label and value, tight, monospaced labels
   so the four rows line up as a block rather than reading as prose. */
.papmeta {
  display: grid;
  grid-template-columns: 104px minmax(0, 1fr);
  gap: 3px 16px;
  margin: 14px 0 0;
  font-size: 13px;
}
.papmeta dt {
  font: 700 11px/1.55 "Courier New", Courier, monospace;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.papmeta dd { margin: 0; color: var(--ink-body); line-height: 1.55; }
@media (max-width: 700px) {
  /* The logo column drops under the text and keeps continuing the card, the
     same move the photo column makes. */
  .lts-tick .logobox {
    border-left: 1px solid var(--border);
    padding: 0 22px 22px;
  }
  .lts-tick:hover .logobox { transform: none; }
  .papmeta { grid-template-columns: 1fr; gap: 0 0; }
  .papmeta dd { margin-bottom: 8px; }
}

/* v4. The hero is a single centred block again. The demo moved down to sit
   beside the overview, which is where the claim is actually made, so the
   headline no longer shares its row with anything and gets the full width and
   the full 60px back.

   Centred rather than ranged left because with nothing beside it an off-centre
   column reads as though something is missing from the other half. */
/* 4vh above rather than 11vh: the eyebrow now sits close under the bar instead
   of a screenful below it, so the headline is in view on load rather than
   scrolled to. Not zero, which would have it touching the sticky bar. */
.hero { max-width: 1100px; margin: 0 auto; padding: 4vh 5vw 3vh; text-align: center; }
/* The auto margins have to live on the same rules that set max-width, further
   down. Setting them here did nothing: .hero h1 and .sub are restated below at
   equal or higher specificity with margin shorthands that reset the sides back
   to zero, so the capped boxes sat at the left edge while only their text
   centred. */
/* Centred, and closer together. The standfirst, the rule, the count and its
   note were carrying 36px + 22px of air between them; at 20px + 14px they read
   as one group rather than three separate things. */
.hero .sub { margin: 0 auto 20px; }
.hero .heads { justify-content: center; padding-top: 14px; }

.eyebrow { margin: 0 0 16px; font-size: 11px; letter-spacing: 0.26em;
  text-transform: uppercase; color: var(--brand); }
.hero h1 { margin: 0 auto 16px; color: var(--ink); font-size: clamp(29px, 4.6vw, 53px);
  line-height: 1.04; letter-spacing: -0.025em; max-width: 21em; }
/* 21em, matched byte for byte by .lts-hero h1 in lts.css. The page mark is
   pinned to this box, so the two must agree or the logo sits in a different
   place on Let's Talk Space. 18em also wrapped the longer LTS headlines to
   three lines once .fp started rendering at 1.7em. */
/* Left as it was: .sub is also the standfirst on About, Capabilities, Careers
   and Let's Talk Space, and those heroes are ranged left. The centring and the
   tighter gap below belong to this page's hero only, and are set there. */
.sub { margin: 0 0 20px; max-width: 40em; font-size: 18.5px; color: var(--ink-soft); }
/* One measure, one gap, every hero. 40em is what the sixteen Let's Talk Space
   heroes already used and it suits the longer standfirsts; 20px is the tighter
   gap this page adopted so the eyebrow, headline and standfirst read as one
   group. Both were deliberate, and neither had reached the other page type. */

.heads { display: flex; align-items: baseline; gap: 26px; flex-wrap: wrap;
  padding-top: 22px; border-top: 2px solid var(--rule); }
.tbig { margin: 0; font: 700 clamp(22px, 3.2vw, 35px)/1 "Courier New", Courier, monospace;
  letter-spacing: 0.02em; color: var(--brand); }
.hint { margin: 0; font-size: 13px; color: var(--ink-soft); }

/* The overview row: brief on the left, demo on the right. Below 1040px they
   stack, because side by side on a phone gives each half nothing usable. */
.ov-copy, .ov-media { min-width: 0; }
.ov-media { margin-top: 30px; }
@media (min-width: 1040px) {
  .ov { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(32px, 4vw, 64px); align-items: center; }
  .ov-media { margin-top: 0; }
}

.vid-item { margin: 0; }

/* No rule, no corner, no panel. The footage carries its own hard edges against
   black, so a border round it only competed with them. */
.hero-vid { display: block; width: 100%; height: auto; background: transparent; }

/* v5. Both demos are meant to read as moving stills, not as films: they start
   on their own and show no chrome at any point. The script strips `controls`
   and sets controlsList, which covers standards-compliant browsers; these rules
   close the WebKit and Blink shadow-DOM routes by which a control bar or a
   centred play triangle can still be painted over the frame.

   The pointer says the frame is live: one click stops it, the next carries on.
   Pointer only, by decision -- the frame is not focusable and there is no key
   handler. What covers the motion-sensitivity case instead is the reduced-motion
   branch in the script, which holds both demos on their first frame rather than
   playing them at all.

   They do not loop. Each runs once and then holds its last frame, which is the
   end of the manoeuvre and the most informative single image in the clip; a
   click runs it again from the start. A demo that repeats forever asks to be
   watched for as long as it is on screen, and the page has other things to
   say. */
.hero-vid, .capvid { cursor: pointer; }
.hero-vid::-webkit-media-controls,
.capvid::-webkit-media-controls,
.hero-vid::-webkit-media-controls-enclosure,
.capvid::-webkit-media-controls-enclosure,
.hero-vid::-webkit-media-controls-panel,
.capvid::-webkit-media-controls-panel,
.hero-vid::-webkit-media-controls-start-playback-button,
.capvid::-webkit-media-controls-start-playback-button,
.hero-vid::-webkit-media-controls-overlay-play-button,
.capvid::-webkit-media-controls-overlay-play-button {
  display: none !important;
  -webkit-appearance: none;
  appearance: none;
}

/* The capability drawer video. This began as a comparison against the drawn
   figure it replaced; the video won and the drawn version has been removed, so
   this is now the permanent treatment for Proximity Operations on the homepage.
   Full width of the figure column, which shared/capfig.css caps at 750px and
   every drawn figure also obeys, so it lines up with the figures in the other
   drawers. Note that capabilities/index.html still draws this event as an SVG:
   the two pages disagree, and that is worth settling. */
.capvid { display: block; width: 100%; height: auto; margin: 0 auto;
  background: #05080f; }
.capvid-cap { display: block; margin: 10px 0 0; text-align: center;
  font: 400 11px/1.5 "Courier New", Courier, monospace;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink); }

/* The caption is the status voice the rest of the sequencer uses, so the panel
   reads as instrumentation rather than as a promotional video. Centred under
   the frame and in the full ink rather than the soft grey: it is the only
   label the demo has, and at 11px the soft grey was doing too little work. */
.vid-cap { margin: 12px 0 0; text-align: center;
  font: 400 11px/1.5 "Courier New", Courier, monospace;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink); }

.sec { max-width: 1488px; margin: 0 auto; padding: 6vh 5vw; }
.sec.wide { max-width: 1488px; }
.sec h2 { margin: 0 0 20px; color: var(--ink); font-size: 12px;
  letter-spacing: 0.26em; text-transform: uppercase; }
.rung { margin: 0 0 8px; font: 12px/1 "Courier New", Courier, monospace;
  letter-spacing: 0.14em; color: var(--brand); }

.prose { max-width: 52em; }
.prose p { margin: 0 0 14px; ; font-size:15px}

.plate { margin: 34px 0 0; padding: 20px; max-width: 1088px;
  background: var(--surface); border: 1px solid var(--border); }
figcaption { margin-top: 12px; font-size: 12.5px; color: var(--ink-soft); }

svg.fig { display: block; width: 100%; height: auto; }
svg .thin { stroke: var(--fig-thin); stroke-width: 1; }
svg .traj { stroke: var(--fig-traj); stroke-width: 1.5; }
svg .craft { fill: var(--fig-fill); stroke: var(--fig-stroke); stroke-width: 1.5; }
svg .axis { stroke: var(--fig-axis); stroke-width: 1; fill: var(--fig-axis); }
svg .label text { fill: var(--fig-label); stroke: none;
  font: 11px Helvetica, Arial, sans-serif; }

/* The ladder. Four columns: the clock, the rail with its node lamp, the event
   itself, and the status call. The drawer takes a second row under the event
   and runs out to the right edge. */
.lhead, .evt { display: grid; grid-template-columns: 150px 30px 1fr 120px;
  gap: 0 11px; align-items: start; }
.lhead { padding-bottom: 10px; border-bottom: 1px solid var(--rule-2);
  font: 10.5px/1 "Courier New", Courier, monospace; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-soft); margin: 0 0 4px; }
.lhead .lh-mid { grid-column: 3; }

.evt { position: relative; cursor: pointer; padding: 22px 0 24px;
  border-bottom: 1px solid var(--border); outline-offset: 4px; }
.evt:hover, .evt:focus-within { background: var(--surface); }
.evt:focus-visible { outline: 2px solid var(--brand); }

/* The rail, drawn at the centre line of the node column. */
.evt::before { content: ""; position: absolute; top: 0; bottom: 0; left: 186px;
  width: 2px; background: var(--rule-2); }
.evt:first-of-type::before { top: 22px; }
.evt:last-of-type::before { bottom: auto; height: 56px; }

.t { grid-column: 1; grid-row: 1; margin: 0; text-align: right;
  font: 11px/1.4 "Courier New", Courier, monospace; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-soft); }
.t b { font-size: 24px; line-height: 1.3; letter-spacing: 0.01em; color: var(--ink); }
.evt:hover .t b, .evt:focus-within .t b { color: var(--brand); }

.node { grid-column: 2; grid-row: 1; position: relative; z-index: 1;
  justify-self: center; width: 16px; height: 16px; margin-top: 14px;
  border: 2px solid var(--rule-2); border-radius: 50%; background: var(--bg); }
.evt:hover .node, .evt:focus-within .node {
  border-color: var(--brand); background: var(--brand); }

.body { grid-column: 3; grid-row: 1; }
.num { margin: 0 0 8px; font: 11px/1 "Courier New", Courier, monospace;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--brand); }
.body h3 { margin: 0; color: var(--ink); font-size: 19px; line-height: 1.25; }

.st { grid-column: 4; grid-row: 1; margin: 0; justify-self: end; align-self: start;
  padding: 7px 14px; font: 700 13.5px/1.3 "Courier New", Courier, monospace;
  letter-spacing: 0.18em; }
.st.go { color: var(--on-brand); background: var(--brand); }
.st.hold { color: var(--ink-soft); border: 1px solid var(--rule-2); }

/* The drawer. Open by default, so nothing here depends on animation being
   available. The inner wrapper carries the clip, which is what lets the outer
   track animate from 0fr to 1fr. */
.drawer { grid-column: 3 / -1; grid-row: 2; display: grid; grid-template-rows: 1fr; }
.drawer-in { min-height: 0; overflow: hidden; }

/* Shut, and opening on hover, on focus, or on the .open class a tap toggles.

   Gated on .js-rows, a class the head script adds to <html>. Without JavaScript
   there is no tap trigger and no way to reopen anything, so the rows stay open
   and the page is still readable -- the default above is 1fr for exactly that
   reason. The class is set in the head rather than by the controller at the end
   of the body, or every row would paint open and then snap shut.

   Deliberately outside the reduced-motion query: a reader who has asked for
   less movement should still get rows that open, just without the animation. */
.js-rows .drawer { grid-template-rows: 0fr; }
.js-rows .evt:hover .drawer,
.js-rows .evt:focus-within .drawer,
.js-rows .evt.open .drawer { grid-template-rows: 1fr; }

.desc { margin: 14px 0 0; max-width: 52em; font-size: 15px; line-height: 1.65;
  color: var(--ink-body); }
/* 15 per cent off each side, so the figure sits at 70 per cent width and
   centred, and half the previous 18px gap to the text above it. Applies to
   the five capability figures wherever the ladder appears: the landing page
   and the capabilities page. */
.evt .capfig { display: block; width: 70%; max-width: none;
  margin: 9px auto 6px; }

.placeholder { display: inline-block; color: var(--ph-ink); background: var(--ph-bg);
  border: 1px dashed var(--ph-border); padding: 5px 10px; font-size: 14px; }

.pair { display: flex; gap: 16px; align-items: center; }
.pair > span:first-child { flex: 0 0 110px; font-size: 11px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-soft); }

footer { display: flex; justify-content: space-between; max-width: 1100px;
  margin: 0 auto; padding: 18px 5vw 40px; border-top: 1px solid var(--border);
  font-size: 12.5px; color: var(--ink-soft); }
footer p { margin: 0; }

@media (prefers-reduced-motion: no-preference) {
  /* Only the movement lives in here now. Whether a row is open or shut is not a
     motion question, and while it was inside this query a reader with Reduce
     Motion switched on got five permanently expanded rows and nothing to tap.

     0.52s, half the speed this opened at originally. The four durations are
     deliberately one number: the drawer, the row background, the clock and the
     lamp are one gesture, and slowing only the drawer would leave the other
     three snapping while it glides. Change them together or not at all. */
  .js-rows .drawer { transition: grid-template-rows 0.52s cubic-bezier(0.32, 0, 0.24, 1); }
  .evt { transition: background 0.52s linear; }
  .t b { transition: color 0.52s linear; }
  .node { transition: background 0.52s linear, border-color 0.52s linear; }

  .node { animation: fp-arm 6s steps(1, end) infinite; }
  .evt:nth-of-type(2) .node { animation-delay: 0.5s; }
  .evt:nth-of-type(3) .node { animation-delay: 1s; }
  .evt:nth-of-type(4) .node { animation-delay: 1.5s; }
  .evt:nth-of-type(5) .node { animation-delay: 2s; }
  /* The armed row holds its lamp lit rather than blinking with the ladder. */
  .evt:hover .node, .evt:focus-within .node { animation: none; }

  .st.go, .tbig { animation: fp-lamp 2.4s ease-in-out infinite; }
}
@keyframes fp-arm {
  0%, 45% { border-color: var(--brand); background: var(--brand); }
  46%, 100% { border-color: var(--rule-2); background: var(--bg); }
}
/* 0.78, not 0.6. The GO badge is black text on the brand blue, and at 0.6 the
   composite against the page dropped the pair to 3.4:1 -- under the 4.5:1 AA
   floor for 13.5px text, twice every 2.4 seconds. 0.78 holds about 5.2:1 and
   still reads as a pulse. */
@keyframes fp-lamp { 0%, 100% { opacity: 1; } 55% { opacity: 0.78; } }

/* Narrow screens: one column. The rows still open and close here -- a tap does
   what a hover does on a pointer device, driven by the .open class the ladder
   script toggles. This block used to force every drawer open instead, because
   :hover was the only trigger and a touch screen has none; that left a phone
   with five permanently expanded rows and no animation to see. */
@media (max-width: 700px) {
  .bar { flex-wrap: wrap; gap: 6px 16px; }
  .marklogo { height: 24px; }
  .bar nav { margin-left: 0; }
  .bar nav a { margin: 0 14px 0 0; }
  /* Tighter on a phone, where the bar wraps and the ring is competing with the
     wordmark for the width. The scale is dropped too: 3.5% of a wrapped nav is
     enough to nudge the line below it. */
  .bar nav a.navflag { padding: 3px 10px; animation-name: navflag-breathe-sm; }
  @keyframes navflag-breathe-sm {
    0%, 100% { transform: scale(1);
               box-shadow: 0 0 0 0 rgba(77, 166, 255, 0.55); }
    50%      { transform: scale(1.045);
               box-shadow: 0 0 0 7px rgba(77, 166, 255, 0),
                           0 0 20px rgba(77, 166, 255, 0.65); }
  }
  .hero { padding: 7vh 20px 4vh; }
  .sec, footer { padding-left: 20px; padding-right: 20px; }
  .lhead { display: none; }
  .evt { grid-template-columns: 1fr; gap: 10px; padding: 22px 0; }
  .evt::before { display: none; }
  .t, .node, .body, .st, .drawer { grid-column: 1; grid-row: auto; }
  .t { text-align: left; }
  .t b { display: inline; margin-left: 10px; }
  .t br { display: none; }
  .node { justify-self: start; margin: 0; }
  .st { justify-self: start; }
  /* the 70 per cent base is a desktop measure; on a phone the drawer is
     already narrow, so the figure takes the full width again */
  .evt .capfig { width: 100%; max-width: 100%; }
  .pair { display: block; }
  .pair > span:first-child { display: block; margin-bottom: 4px; }
  footer { flex-direction: column; gap: 4px; }
}

/* Comet cursor, carried over from template 100.

   A bright nucleus with a tapering tail that lags behind and points back along
   the track, plus a dust trail that fades in about half a second. The script
   builds this layer itself and appends it to the body, so there is no markup
   for it in the page; delete the script and every rule here goes unused and
   the sequencer is untouched.

   The rgba values are literal rather than var(--brand) because they need an
   alpha channel. They are #4da6ff, which is this template's brand colour, so
   the cursor already matches the palette.

   z-index 60 puts it over the sticky bar at z-index 5, which is what you want
   of a pointer. */
.comet { position:fixed; inset:0; pointer-events:none; z-index:60; }
.nuc { position:fixed; left:0; top:0; width:14px; height:14px; margin:-7px 0 0 -7px;
  border-radius:50%; background:radial-gradient(circle,#ffffff 0 26%,
    var(--brand) 54%,rgba(77,166,255,0) 74%); }
.tail { position:fixed; left:0; top:0; height:18px; margin:-9px 0 0; opacity:0;
  transform-origin:0 50%; border-radius:0 9px 9px 0;
  background:linear-gradient(90deg,rgba(255,255,255,.9),rgba(77,166,255,.55) 34%,
    rgba(77,166,255,0)); clip-path:polygon(0 0,100% 42%,100% 58%,0 100%); }
.dust { position:fixed; display:block; width:3px; height:3px; margin:-1.5px 0 0 -1.5px;
  border-radius:50%; background:var(--brand); opacity:.5; }

@media (prefers-reduced-motion: no-preference) {
  .dust { animation:fp-dust .54s linear forwards; }
  @keyframes fp-dust {
    from { opacity:.55; transform:scale(1); }
    to { opacity:0; transform:scale(.3); }
  }
}
/* Starfield.

   Radial gradients rather than an image file, so the template still makes no
   external requests. Declared after the body rule above, which uses the
   `background` shorthand and would otherwise reset background-image.

   Forty-four layers against four tile sizes. The sizes cycle against the layer
   list, so the four grids repeat on different periods and drift out of phase
   across the viewport; that is what stops a tiled field reading as one
   repeating stamp. The sizes also stand in for distance, the tightest grid
   being the densest and dimmest.

   Three magnitudes: 1.6px for the few bright foreground stars, 1.2px for the
   middle, 0.9px for the faint background dust. Opacity tracks size, so the
   field has genuine depth rather than one brightness at several positions.

   Fixed attachment holds the field still while the page scrolls, so it reads
   as sky rather than as texture printed on the page. */
body {
  background-color: var(--bg);
  background-image:
    radial-gradient(1.6px 1.6px at 14% 21%, rgba(255,255,255,.95), transparent),
    radial-gradient(0.9px 0.9px at 63% 12%, rgba(255,255,255,.42), transparent),
    radial-gradient(1.2px 1.2px at 32% 47%, rgba(255,255,255,.72), transparent),
    radial-gradient(1.6px 1.6px at 87% 34%, rgba(255,255,255,.90), transparent),
    radial-gradient(1.2px 1.2px at 51% 68%, rgba(255,255,255,.66), transparent),
    radial-gradient(0.9px 0.9px at  9% 76%, rgba(255,255,255,.38), transparent),
    radial-gradient(1.6px 1.6px at 74% 83%, rgba(255,255,255,.88), transparent),
    radial-gradient(0.9px 0.9px at 41% 91%, rgba(255,255,255,.45), transparent),
    radial-gradient(1.2px 1.2px at 96% 58%, rgba(255,255,255,.70), transparent),
    radial-gradient(0.9px 0.9px at 23% 63%, rgba(255,255,255,.36), transparent),
    radial-gradient(1.6px 1.6px at 57% 38%, rgba(255,255,255,.92), transparent),
    radial-gradient(0.9px 0.9px at  6% 44%, rgba(255,255,255,.48), transparent),
    radial-gradient(1.2px 1.2px at 79% 17%, rgba(255,255,255,.74), transparent),
    radial-gradient(0.9px 0.9px at 37% 27%, rgba(255,255,255,.40), transparent),
    radial-gradient(1.6px 1.6px at 91% 88%, rgba(255,255,255,.85), transparent),
    radial-gradient(1.2px 1.2px at 66% 55%, rgba(255,255,255,.62), transparent),
    radial-gradient(0.9px 0.9px at 17% 92%, rgba(255,255,255,.44), transparent),
    radial-gradient(1.2px 1.2px at 47% 79%, rgba(255,255,255,.68), transparent),
    radial-gradient(0.9px 0.9px at 28%  8%, rgba(255,255,255,.35), transparent),
    radial-gradient(1.2px 1.2px at 71% 66%, rgba(255,255,255,.64), transparent),
    radial-gradient(1.6px 1.6px at  4% 31%, rgba(255,255,255,.86), transparent),
    radial-gradient(0.9px 0.9px at 55% 24%, rgba(255,255,255,.39), transparent),
    radial-gradient(1.2px 1.2px at 84% 49%, rgba(255,255,255,.71), transparent),
    radial-gradient(0.9px 0.9px at 12% 57%, rgba(255,255,255,.33), transparent),
    radial-gradient(1.6px 1.6px at 39% 72%, rgba(255,255,255,.89), transparent),
    radial-gradient(0.9px 0.9px at 93%  9%, rgba(255,255,255,.46), transparent),
    radial-gradient(1.2px 1.2px at 60% 95%, rgba(255,255,255,.67), transparent),
    radial-gradient(0.9px 0.9px at 26% 35%, rgba(255,255,255,.37), transparent),
    radial-gradient(1.2px 1.2px at 77% 41%, rgba(255,255,255,.73), transparent),
    radial-gradient(0.9px 0.9px at 49%  5%, rgba(255,255,255,.41), transparent),
    radial-gradient(1.6px 1.6px at 21% 84%, rgba(255,255,255,.87), transparent),
    radial-gradient(0.9px 0.9px at 88% 74%, rgba(255,255,255,.43), transparent),
    radial-gradient(1.2px 1.2px at 34% 15%, rgba(255,255,255,.69), transparent),
    radial-gradient(0.9px 0.9px at 64% 45%, rgba(255,255,255,.34), transparent),
    radial-gradient(1.2px 1.2px at  2% 67%, rgba(255,255,255,.65), transparent),
    radial-gradient(0.9px 0.9px at 44% 58%, rgba(255,255,255,.47), transparent),
    radial-gradient(1.6px 1.6px at 69%  3%, rgba(255,255,255,.84), transparent),
    radial-gradient(0.9px 0.9px at 98% 27%, rgba(255,255,255,.36), transparent),
    /* a handful in the accent, so the field belongs to this palette */
    radial-gradient(1.2px 1.2px at 68% 29%, rgba( 77,166,255,.66), transparent),
    radial-gradient(0.9px 0.9px at 19% 38%, rgba( 77,166,255,.42), transparent),
    radial-gradient(1.2px 1.2px at 82% 71%, rgba( 77,166,255,.58), transparent),
    radial-gradient(0.9px 0.9px at 45% 16%, rgba( 77,166,255,.36), transparent),
    radial-gradient(1.2px 1.2px at 31% 86%, rgba( 77,166,255,.54), transparent),
    radial-gradient(0.9px 0.9px at 59% 51%, rgba( 77,166,255,.38), transparent);
  background-size: 620px 620px, 880px 880px, 1140px 1140px, 1460px 1460px;
  background-repeat: repeat;
  background-attachment: fixed;
}
/* Intro headline, option 01 from edits/index.html: the sentence walks the
   reader to the name, and the name is set in serif small caps at 1.7 times the
   line so it reads as the thing being named rather than as more sentence.
   Georgia is a system face, so this still downloads no fonts. */
/* .lts-hero included: the accent was scoped to .hero only, so on Let’s Talk
   Space the .fp span rendered as plain body text at the same size as the rest
   of the headline, with none of the serif small-caps treatment. */
.hero h1 .fp, .lts-hero h1 .fp { font-family: Georgia, "Times New Roman", serif; font-size: 1.7em;
  font-variant: small-caps; letter-spacing: 0.01em; }
/* The brand runs at 1.7em of a line that itself reaches 60px, so FINAL
   PROXIMITY needs roughly 1000px and was breaking against the old 15em cap.
   Widened to 18em; the .hero max-width of 1100px is the real ceiling above
   that. Above 900px the name is held on one line outright, since that is the
   whole point of the treatment. Below it the name is allowed to wrap, because
   on a narrow phone nowrap would push the page into a sideways scroll. */
@media (min-width: 900px) {
  .hero h1 .fp, .lts-hero h1 .fp { white-space: nowrap; }
}