/* Resolve Frontier — ink & bone
   (rehashed: two earlier filenames are cached wrong at the edge — see scripts/verify-deploy.mjs)
   Restraint does the work. One cold accent for instruments, one brass signal
   for anything that claims exclusivity, hairlines under 13% opacity, and a lot
   of air. Nothing glows; nothing is pure black or pure white. Prose is set in
   a grotesque, mono is reserved for labels, codes and readouts. */

:root {
  /* Declared so form controls, carets and scrollbars are drawn dark by the UA
     instead of arriving as white boxes on a black page. */
  color-scheme: dark;

  --ink: #08090b;
  --ink-2: #0e1013;

  --bone: #e7e4de;
  --bone-2: #a2a19c;
  /* Carries the fine print, so it is held at 4.6:1 on ink — WCAG AA for body
     text. Any darker and the footer disclaimer fails. */
  --bone-3: #787a81;

  --steel: #8fa8bf;
  --brass: #b08b4f;
  --ice: #9dc0e0;

  --ice-hair: rgba(157, 192, 224, 0.22);
  --ice-hair-2: rgba(157, 192, 224, 0.34);

  --hair: rgba(231, 228, 222, 0.07);
  --hair-2: rgba(231, 228, 222, 0.13);
  --hair-3: rgba(231, 228, 222, 0.22);

  --sans: "Archivo", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --gut: clamp(1.25rem, 5vw, 4.5rem);
  --wide: 84rem;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  font-size: 0.9375rem;
  line-height: 1.6;
  letter-spacing: -0.006em;
  color: var(--bone-2);
  background: var(--ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked {
  overflow: hidden;
}

::selection {
  background: rgba(143, 168, 191, 0.26);
  color: var(--bone);
}

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

:focus-visible {
  outline: 1px solid var(--steel);
  outline-offset: 3px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* Fine tooth of grain — the cheapest way to stop a flat dark page reading as
   a template. Kept at 3.5% so it registers only as texture. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

main,
.foot {
  position: relative;
  z-index: 2;
}

main {
  flex: 1 1 auto;
}

/* ——— micro type ——— */

.micro {
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--bone-3);
}

.micro--signal {
  color: var(--ice);
}

/* Every section shares one inset, so section rules run edge to edge while all
   type starts on the same x. Before this the rail was the only full-bleed
   block: at 1920 the wordmark sat 288px left of the headline it heads. */
.rail,
.beam,
.band,
.units,
.foot {
  max-width: none;
  margin-inline: 0;
  padding-inline: max(var(--gut), calc((100% - var(--wide)) / 2 + var(--gut)));
}

/* ——— rail ——— */

.rail {
  position: sticky;
  top: 0;
  z-index: 20;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 1.1rem;
  background: rgba(8, 9, 11, 0.86);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--hair);
}

.mark {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  color: var(--bone);
}

.mark:hover .mark__name em {
  color: var(--bone);
}

/* Grey and half-there: the mark sits in the rail rather than shouting from it,
   and the phosphor stays with the instruments where it means something. The 2px
   stroke is what carries it at this opacity — at 1.4 the glyph went to mush.
   SVG strokes are currentColor, so the colour on the element is the change. */
.mark__scales {
  width: 2.15rem;
  height: 2.15rem;
  flex: none;
  color: rgba(231, 228, 222, 0.5);
}

.mark__name {
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1;
}

.mark__name em {
  font-style: normal;
  font-weight: 400;
  color: var(--bone-2);
  transition: color 0.25s var(--ease);
}

.rail__status {
  display: flex;
  align-items: center;
  gap: 1.35rem;
}

.tag {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--bone-3);
  white-space: nowrap;
}

.tag--num {
  font-variant-numeric: tabular-nums;
  color: var(--bone-2);
}

/* ——— client access ——— */

.access {
  font: inherit;
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--bone-2);
  background: none;
  border: 1px solid var(--hair-2);
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease);
}

.access:hover {
  color: var(--bone);
  border-color: var(--bone-3);
}

.veil {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(4, 5, 6, 0.72);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  animation: fade 0.3s var(--ease);
}

@keyframes fade {
  from { opacity: 0; }
}

/* Flex + `margin: auto` on the panel rather than grid centring: when the panel
   is taller than a short viewport, auto margins collapse to zero and the top
   stays scrollable. Centred grid would clip it above the scroll origin. */
.sheet {
  position: fixed;
  inset: 0;
  z-index: 41;
  display: flex;
  padding: 1.25rem;
  overflow-y: auto;
}

.sheet[hidden] {
  display: none;
}

.sheet__panel {
  width: min(28rem, 100%);
  margin: auto;
  padding: 1.75rem;
  background: #0b0d10;
  border: 1px solid var(--hair-2);
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.7);
  animation: lift 0.38s var(--ease);
}

@keyframes lift {
  from { opacity: 0; transform: translateY(12px); }
}

.sheet__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--hair);
}

.sheet__close {
  width: 1.75rem;
  height: 1.75rem;
  display: grid;
  place-items: center;
  color: var(--bone-3);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color 0.25s var(--ease);
}

.sheet__close svg {
  width: 0.85rem;
  height: 0.85rem;
}

.sheet__close:hover {
  color: var(--bone);
}

.sheet__title {
  margin-top: 1.35rem;
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: -0.026em;
  color: var(--bone);
}

.sheet__lede {
  margin-top: 0.6rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--bone-3);
}

.seg {
  display: flex;
  gap: 0;
  margin-top: 1.5rem;
  background: var(--ink-2);
  border: 1px solid var(--hair);
}

.seg__opt {
  flex: 1 1 0;
  padding: 0.6rem 0.5rem;
  font: inherit;
  font-family: var(--mono);
  font-size: 0.5625rem;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--bone-3);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color 0.25s var(--ease), background 0.25s var(--ease);
}

.seg__opt + .seg__opt {
  border-left: 1px solid var(--hair);
}

.seg__opt.is-on {
  color: var(--bone);
  background: rgba(231, 228, 222, 0.06);
  box-shadow: inset 0 -1px 0 var(--ice);
}

.sheet__pane {
  display: grid;
  gap: 0.9rem;
  margin-top: 1.35rem;
}

.sheet__pane[hidden] {
  display: none;
}

.field {
  display: grid;
  gap: 0.45rem;
}

.field label {
  font-family: var(--mono);
  font-size: 0.5625rem;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--bone-3);
}

/* A reference and a passphrase are read back character by character, so both
   are set in mono — and the control is stripped of its UA shell so it reads as
   a ruled field rather than a browser widget. */
.field input {
  width: 100%;
  padding: 0.65rem 0.75rem;
  font: inherit;
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  color: var(--bone);
  background: var(--ink-2);
  border: 1px solid var(--hair);
  border-radius: 0;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 0.25s var(--ease);
}

.field input::placeholder {
  color: var(--bone-3);
  opacity: 1;
}

.field input:hover,
.field input:focus {
  border-color: var(--hair-3);
}

.keys {
  display: grid;
  gap: 0.4rem;
  list-style: none;
}

.keyopt {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  padding: 0.7rem 0.85rem;
  font: inherit;
  font-size: 0.875rem;
  text-align: left;
  color: var(--bone-2);
  background: var(--ink-2);
  border: 1px solid var(--hair);
  cursor: pointer;
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease);
}

.keyopt span {
  font-family: var(--mono);
  font-size: 0.5625rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--bone-3);
}

.keyopt:hover,
.keyopt.is-on {
  color: var(--bone);
  border-color: var(--hair-3);
}

/* Chosen, not merely pointed at: the ice edge outlasts the cursor. */
.keyopt.is-on {
  border-color: var(--ice-hair-2);
}

.sheet__status {
  min-height: 1.4em;
  margin-top: 1.1rem;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brass);
}

.sheet__go {
  width: 100%;
  margin-top: 0.35rem;
  font: inherit;
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--bone);
  background: transparent;
  border: 1px solid var(--hair-3);
  padding: 0.8rem 1.5rem;
  cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease), border-color 0.25s var(--ease);
}

.sheet__go:hover {
  color: var(--ink);
  background: var(--bone);
  border-color: var(--bone);
}

.sheet__fine {
  margin-top: 1.25rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--hair);
  font-size: 0.6875rem;
  line-height: 1.55;
  color: var(--bone-3);
}

/* ——— beam ——— */

.beam {
  padding-block: clamp(2rem, 6vh, 4rem) clamp(1.5rem, 3vh, 2.5rem);
}

.kicker {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.1rem;
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.21em;
  text-transform: uppercase;
  color: var(--ice);
}

.kicker span + span {
  padding-left: 1.1rem;
  border-left: 1px solid rgba(157, 192, 224, 0.28);
}

/* The headline rotates, so its box is reserved up front — a line of type that
   reflows every few seconds would drag the whole page with it. Every line is
   set in the grotesque at full size, so the reserve is three of those. It is
   anchored to --h1 rather than to `em` so it cannot drift with a variant. */
.beam__line {
  --h1: clamp(2.35rem, 7.2vw, 5.75rem);
  margin-top: 2rem;
  min-height: calc(3 * 1.02 * var(--h1));
  font-size: var(--h1);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -0.038em;
  color: var(--bone);
  text-wrap: balance;
  transition: color 0.5s var(--ease);
}

/* Each line takes a colour and, one time in four, the terminal face. Fixed
   cycles rather than random: the mix should read as chosen, not as flicker. */
.beam__line--ice {
  color: var(--ice);
}

.beam__line--mute {
  color: var(--bone-2);
}

/* Mono runs ~0.6em to the character against Archivo's ~0.5, so it takes a
   smaller size to hold the same measure. Verified per line in a real browser. */
.beam__line--mono {
  font-family: var(--mono);
  font-size: calc(var(--h1) * 0.7);
  font-weight: 400;
  letter-spacing: -0.03em;
}

.beam__line--ice .beam__caret {
  background: var(--ice);
}

.beam__line--mute .beam__caret {
  background: var(--bone-2);
}

.beam__caret {
  display: inline-block;
  width: 0.07em;
  height: 0.72em;
  margin-left: 0.08em;
  vertical-align: -0.05em;
  background: var(--steel);
  animation: pulse 1.05s steps(1, end) infinite;
}

.beam__caret.is-held {
  animation: none;
  opacity: 1;
}

@keyframes pulse {
  0%, 52% { opacity: 1; }
  53%, 100% { opacity: 0; }
}

/* ——— manifesto band ——— */

.band {
  padding-block: clamp(2.5rem, 7vh, 4rem);
  border-top: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  background: linear-gradient(180deg, rgba(231, 228, 222, 0.014), transparent);
}

.band__text {
  /* Measure, not container: at full width this ran 115 characters a line. */
  max-width: 62ch;
  font-size: clamp(1.0625rem, 2.1vw, 1.75rem);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: -0.019em;
  color: var(--bone-2);
  text-wrap: pretty;
}

.band__text em {
  font-style: normal;
  color: var(--bone);
}

/* ——— depth: the scope sits behind everything below the headline ——— */

.depth {
  position: relative;
  isolation: isolate;
}

/* Reaches a third of a screen above its own act, so the instrument is already
   under the headline before the work act arrives — and stops before the units
   start. Once the act grew to hold five cards, a full-height scope ran the
   whole way down and the copy was read through a radar. The mask does the
   joining at both ends: a hard edge crossing an act boundary reads as a seam. */
.depth__scope {
  position: absolute;
  top: -34svh;
  left: 0;
  right: 0;
  height: 108svh;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  mask-image: linear-gradient(180deg, transparent 0%, #000 26%, #000 62%, transparent 96%);
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 26%, #000 62%, transparent 96%);
}

/* Terminal scope — braille glyph art, Homebrew phosphor green. */
.scope__term {
  position: absolute;
  top: 40%;
  left: 58%;
  margin: 0;
  transform: translate(-50%, -50%);
  font-family: var(--mono);
  font-size: clamp(13px, 2.1vw, 26px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: 0;
  white-space: pre;
  /* Classic Homebrew terminal green, held translucent so copy stays readable. */
  color: rgba(51, 255, 51, 0.38);
  text-shadow: 0 0 1px rgba(51, 255, 51, 0.15);
  user-select: none;
  -webkit-user-select: none;
}

.depth__content {
  position: relative;
}

/* ——— units: five names, one open at a time ——— */

.units {
  padding-block: clamp(1rem, 2.4vh, 1.6rem) 0;
}

.units__lede {
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--hair);
}

.unit {
  border-bottom: 1px solid var(--hair);
}

.unit__head {
  margin: 0;
  font-weight: inherit;
}

/* The name is the control. Full-bleed row so the whole line is the target —
   a 4rem word with a 40px hit area would be a joke on a phone. */
.unit__name {
  display: flex;
  align-items: baseline;
  gap: clamp(0.9rem, 2.2vw, 2rem);
  width: 100%;
  padding-block: clamp(0.85rem, 2.2vh, 1.5rem);
  font: inherit;
  font-family: var(--mono);
  font-size: clamp(1.6rem, 4.6vw, 3.5rem);
  font-weight: 500;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  text-align: left;
  color: var(--bone-3);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color 0.3s var(--ease);
}

.unit__name:hover {
  color: var(--bone-2);
}

.unit.is-open .unit__name {
  color: var(--bone);
}

.unit__idx {
  flex: none;
  font-size: 0.625rem;
  letter-spacing: 0.19em;
  color: var(--ice);
}

.unit__latin {
  flex: 1 1 auto;
}

/* A rule that grows into a cross when the unit opens: the only affordance,
   and it says "this closes" without a word or an icon font. */
.unit__mark {
  position: relative;
  flex: none;
  width: 0.9em;
  height: 1px;
  background: currentColor;
  align-self: center;
}

.unit__mark::after {
  content: "";
  position: absolute;
  inset: 0;
  background: currentColor;
  transform: rotate(90deg);
  transition: transform 0.35s var(--ease), opacity 0.35s var(--ease);
}

.unit.is-open .unit__mark::after {
  transform: rotate(0deg);
  opacity: 0;
}

/* Height is auto at rest, not 0: the script sets a pixel height only for the
   duration of the animation and then clears it. With `height: 0` in the base
   rule, clearing the inline value collapsed an open panel back to nothing —
   and a panel that is open but empty looks like broken content, not a bug. */
.unit__panel {
  position: relative;
  overflow: hidden;
  transition: height 0.42s var(--ease);
}

.unit__panel[hidden] {
  display: none;
}

/* The figure is printed large behind the copy and never competes with it:
   a tenth of full strength, and it fades up with the panel rather than
   arriving already lit. */
.unit__glyph {
  position: absolute;
  right: -0.5rem;
  top: 50%;
  margin: 0;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: clamp(11px, 1.5vw, 19px);
  line-height: 1.05;
  letter-spacing: 0;
  white-space: pre;
  color: rgba(51, 255, 51, 0.11);
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}

/* Two columns, explicitly placed. The pitch runs down the left, the supporting
   detail down the right, and the maxim closes across both — the panel is
   1200px wide and a single 612px column left the other half to the watermark.
   Explicit rows rather than auto-placement: the prose has to span both
   supporting blocks, and auto-flow would give it one. */
.unit__body {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  column-gap: clamp(2rem, 4vw, 4.5rem);
  row-gap: clamp(0.9rem, 2vh, 1.4rem);
  padding-bottom: clamp(1.2rem, 3vh, 2.2rem);
}

.unit__what { grid-column: 1 / -1; grid-row: 1; }
.unit__text { grid-column: 1; grid-row: 2 / span 2; }
.unit__gives { grid-column: 2; grid-row: 2; }
.unit__prec { grid-column: 2; grid-row: 3; }
.unit__maxim { grid-column: 1; grid-row: 4; }
.unit__rule { grid-column: 2; grid-row: 4; }

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

  .unit__what,
  .unit__text,
  .unit__gives,
  .unit__prec,
  .unit__maxim,
  .unit__rule {
    grid-column: 1;
    grid-row: auto;
  }

  .unit__rule {
    border-top: 0;
    padding-top: 0;
  }
}

/* Second loudest thing on the page after the name it sits under. The old
     21.6px against a 56px name was not a step, it was a drop. */
.unit__what {
  font-size: clamp(1.35rem, 2.2vw, 1.9rem);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.022em;
  color: var(--bone);
}

.unit__text {
  text-wrap: pretty;
  margin-top: 0;
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--bone);
}

/* Same size as the prose it sits beside. Rank is carried by colour from here
   down — the label takes the accent, the body stays at bone-3 — because four
   sizes inside one panel is what made the last version read as fine print. */
.unit__gives {
  text-wrap: pretty;
  margin-top: 0;
  font-size: 1.125rem;
  line-height: 1.55;
  color: var(--bone-3);
}

.unit__gives b {
  font-weight: 500;
  color: var(--ice);
}

.unit__prec {
  text-wrap: pretty;
  margin-top: 0.9rem;
  font-size: 1.125rem;
  line-height: 1.55;
  color: var(--bone-3);
}

/* Brass, like the maxim below it: both blocks are the classical register, and
   the colour says so before the words do. */
.unit__prec b {
  font-weight: 500;
  color: var(--brass);
}

.unit__prec em {
  font-style: normal;
  color: var(--bone-2);
}

/* The maxim closes the unit. Set apart by a rule and the brass the boundary
   line already uses, so a lawyer's eye lands on the Latin first and the gloss
   second — and nobody has to be told it is a quotation. */
.unit__maxim {
  margin: 1.4rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px solid var(--hair-2);
}

.unit__lat {
  margin: 0;
  font-family: var(--mono);
  font-size: 1.125rem;
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--brass);
  text-wrap: pretty;
}

.unit__gloss {
  margin-top: 0.45rem;
  font-size: 1.125rem;
  line-height: 1.45;
  color: var(--bone-3);
  text-wrap: pretty;
}

.unit__cite {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--bone-2);
  white-space: nowrap;
}

.unit__cite::before {
  content: "— ";
}

.unit__rule {
  text-wrap: pretty;
  margin: 0;
  padding: 0.85rem 0 0 1rem;
  border-top: 1px solid var(--hair-2);
  border-left: 1px solid rgba(176, 139, 79, 0.6);
  font-size: 1.125rem;
  line-height: 1.5;
  color: var(--bone-2);
}

/* Narrow: the figure would sit under the text rather than beside it, so it
   goes quieter still. */
@media (max-width: 760px) {
  .unit__glyph {
    font-size: clamp(9px, 2.6vw, 13px);
    color: rgba(51, 255, 51, 0.08);
  }
}

/* ——— closed channel (lives in the footer, third column) ——— */

.closed__title {
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.006em;
  color: var(--bone);
}

/* Reads as the heading it sits in; behaves as a control. The dotted rule is the
   only affordance that anything is under it. */
.closed__reveal {
  position: relative;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: help;
  /* Padded out to a 46px tap target and pulled back by the same amount, so the
     finger gets a box the line does not have to grow for. The rule is drawn as
     a pseudo-element pinned to the text, not as a border on the padded box —
     a border would sit 11px adrift once the padding was added. */
  padding-block: 0.85rem;
  margin-block: -0.85rem;
}

.closed__reveal::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.85rem;
  border-bottom: 1px dotted var(--hair-3);
  transition: border-color 0.25s var(--ease);
}

.closed__reveal:hover::after {
  border-bottom-color: var(--bone-3);
}

/* Sits above the line, never below: the band is the last thing before the
   footer, and a note dropping downward would open under the fold on a laptop. */
.closed__note {
  position: absolute;
  bottom: 100%;
  left: 0;
  z-index: 5;
  width: max(100%, min(42ch, 88vw));
  margin-bottom: 0.5rem;
  padding: 0.85rem 1rem;
  background: #14171b;
  border: 1px solid var(--hair-2);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
  font-size: 0.8125rem;
  line-height: 1.55;
  text-wrap: pretty;
  opacity: 0;
  visibility: hidden;
  transform: translateY(4px);
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s;
}

.closed__title:hover + .closed__note,
.closed__title:focus-within + .closed__note {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.closed__text {
  text-wrap: pretty;
  margin-top: 0.5rem;
  max-width: 76ch;
  font-size: 1.0625rem;
  line-height: 1.55;
}

.closed__line {
  display: inline-block;
  margin-top: 0.35rem;
  font-family: var(--mono);
  letter-spacing: -0.01em;
  color: var(--bone);
  border-bottom: 1px solid var(--hair-3);
  padding-bottom: 0.2rem;
  transition: border-color 0.25s var(--ease);
}

.closed__line:hover {
  border-bottom-color: var(--bone);
}

/* ——— foot ——— */

.foot {
  flex: none;
  display: grid;
  gap: 0.4rem;
  width: 100%;
  padding-block: 0.45rem 0.6rem;
  border-top: 1px solid var(--hair);
}

/* Three blocks on one level: the two disclaimers and the channel. The channel
   column is narrower — it carries three short lines, not a paragraph. */
.foot__fine {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 22rem);
  gap: 0.35rem clamp(1.5rem, 3vw, 3rem);
}

.foot__channel {
  position: relative;
}

.foot__fine p {
  font-size: 0.6875rem;
  line-height: 1.45;
  color: var(--bone-3);
}

.foot__fine b {
  font-weight: 500;
  color: var(--bone-2);
}

.foot__sig {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--bone-3);
  white-space: nowrap;
}


/* ——— reel: three acts, one screen each ——— */

/* No scroll-snap. Measured before removing it: acts stood at 64% of the
   viewport, so snap points never lined up with what was on screen, and the
   whole page came to 2.02 screens of scroll for three acts — past the second
   one there was nothing left to scroll and the snap kept pulling back. That is
   what read as sticking. Plain scrolling with a crossfade behaves. */
html {
  scroll-padding-top: 4.5rem;
}

/* The statement and the terms hold a screen each. The work act is as tall as
   its five units need — forcing it to a screen would crush them. */
.act {
  min-height: 88svh;
}

.depth.act {
  min-height: 0;
  padding-block: clamp(3rem, 9vh, 6rem);
}

.beam.act,
.depth.act {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* No overflow clip here on purpose: the hover note opens upward out of the
   channel column, and hiding the footer's overflow would cut it off on a short
   viewport. The instrument is already clipped by its own well below. */
.foot.act {
  align-content: center;
  position: relative;
  isolation: isolate;
}

.foot__scope {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 78%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 22%, #000 78%, transparent 100%);
}

/* Sits left of centre so it does not stand behind the address column. Twice
   the size of the scope and carrying real weight: the variable mono goes to
   800 and the phosphor to 0.85, on top of strokes drawn three dots wide. */
.scope__term--scales {
  top: 50%;
  left: 34%;
  font-size: clamp(22px, 3vw, 38px);
  font-weight: 800;
  /* Weight comes from the three-dot strokes and the 800 cut, not from opacity:
     at 0.85 the phosphor buried the disclaimer, and the disclaimer is the one
     block on the page that has to stay readable. */
  color: rgba(51, 255, 51, 0.55);
  text-shadow: 0 0 5px rgba(51, 255, 51, 0.22);
}

/* Dimming only exists once the script has run — see the note in rf.js. */
.js-reel .act {
  opacity: 0.14;
  transform: translateY(2vh);
  transition: opacity 0.55s var(--ease), transform 0.55s var(--ease);
}

.js-reel .act.is-on {
  opacity: 1;
  transform: none;
}

/* ——— entrance ——— */

.rise {
  opacity: 0;
  transform: translateY(10px);
  animation: rise 0.9s var(--ease) forwards;
}

.rise[data-rise="0"] { animation-delay: 0.05s; }

@keyframes rise {
  to {
    opacity: 1;
    transform: none;
  }
}

/* ——— narrow ——— */

/* Below this width the render breaks in four specific ways, all verified in a
   real browser rather than reasoned about: the kicker orphans a divider, the
   headline reserves more lines than it uses and opens a void, the unit index
   wraps under its own underline, and the tap targets fall under 44px. */
@media (max-width: 620px) {
  .beam {
    padding-top: clamp(2.5rem, 7vh, 4rem);
    padding-bottom: clamp(1.5rem, 3.5vh, 2.25rem);
  }

  /* Stacked, and without the leading rule a wrapped item would drag with it. */
  .kicker {
    flex-direction: column;
    gap: 0.45rem;
  }

  .kicker span + span {
    padding-left: 0;
    border-left: 0;
  }

  /* Small enough that no line wraps past its own break, so three is exact. */
  .beam__line {
    /* Fluid rather than stepped: the longest line has to clear the measure at
       320 and still grow by 430, and a fixed value cannot do both. Floor and
       ceiling are both measured, not chosen. */
    --h1: clamp(1.6rem, 8vw, 2.15rem);
    margin-top: 1.5rem;
  }

  .closed__line {
    padding-block: 0.35rem 0.45rem;
  }

  /* At phone width the instrument fits on screen and stops being a backdrop.
     Blow it up so only broad arcs pass behind the copy. */
  .scope__term {
    top: 48%;
    left: 68%;
    font-size: clamp(9px, 3.1vw, 13px);
    color: rgba(51, 255, 51, 0.24);
  }

  /* Comes after the scope rule above, which would otherwise take the balance
     down to 13px with it — same base class, later in the file. */
  .scope__term--scales {
    left: 50%;
    font-size: clamp(15px, 5.2vw, 22px);
    color: rgba(51, 255, 51, 0.5);
  }

  .mark {
    padding-block: 0.5rem;
  }
}

/* Three columns need about 1000px between the gutters. Below that they came out
   146px wide and 330px tall on an iPad — measured, which is why the breakpoint
   moved up from 760. */
@media (max-width: 1000px) {
  .foot__fine {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.9rem;
  }
}

@media (max-width: 760px) {

  .rail__status .tag:not(.tag--num) {
    display: none;
  }

  .rail__status {
    gap: 0.9rem;
  }

  .sheet__panel {
    padding: 1.35rem;
  }

  .mark__name {
    font-size: 1.125rem;
  }

  .mark__scales {
    width: 1.75rem;
    height: 1.75rem;
  }


}

/* The rail carries a wordmark, a clock and a button; on a phone they no longer
   fit on one line, and a wrapped wordmark is worse than a missing readout. */
@media (max-width: 480px) {
  .rail {
    gap: 1rem;
  }

  .rail__status .tag--num {
    display: none;
  }

  .mark {
    gap: 0.6rem;
  }

  .mark__name {
    font-size: 1rem;
  }

  .mark__scales {
    width: 1.55rem;
    height: 1.55rem;
  }

  .access {
    padding: 0.5rem 0.7rem;
    letter-spacing: 0.11em;
  }
}

/* An iPhone SE is 667px tall and the panel was 647px plus padding, so the
   closing security note fell past the fold with no scroll cue. */
@media (max-height: 700px) {
  .sheet__panel {
    padding: 1.15rem;
  }

  .sheet__title {
    margin-top: 1rem;
    font-size: 1.3125rem;
  }

  .sheet__lede {
    margin-top: 0.5rem;
  }

  .seg {
    margin-top: 1.1rem;
  }

  .sheet__pane {
    margin-top: 1rem;
  }

  .sheet__status {
    margin-top: 0.8rem;
  }

  .sheet__fine {
    margin-top: 0.9rem;
    padding-top: 0.85rem;
  }
}

/* Touch targets, keyed on the input device rather than the viewport: an iPad in
   portrait is 768px wide and still fingers-only, so a width breakpoint would
   leave it with 29px controls. 44px is the smallest reliable target. */
@media (hover: none) {
  .access,
  .closed__line,
  .mark,
  .seg__opt,
  .keyopt,
  .sheet__close {
    min-height: 44px;
  }

  .access,
  .sheet__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  .mark {
    display: inline-flex;
    align-items: center;
  }

  .closed__line {
    display: inline-flex;
    align-items: flex-end;
  }

  /* Fine print is fine print, but 11px on a phone is a squint. */
  .foot__fine p {
    font-size: 0.75rem;
  }
}

/* ——— motion ——— */

@media (prefers-reduced-motion: reduce) {
  .js-reel .act,
  .js-reel .act.is-on {
    opacity: 1;
    transform: none;
    transition: none;
  }

  html {
    scroll-behavior: auto;
  }

  .scope__term {
    /* Static frame is drawn once by JS when reduced motion is preferred. */
  }

  .beam__caret {
    animation: none;
    opacity: 1;
  }

  .rise {
    opacity: 1;
    transform: none;
    animation: none;
  }

  .veil,
  .sheet__panel {
    animation: none;
  }
}

/* deploy 588088 */
