/* ═══════════════════════════════════════════════════════════════
   LaikaSuite — the hub, as a printed index.

   Everything here derives from packages/design-system/tokens.css. This
   file adds no colour, no radius, no easing and no shadow of its own; it
   composes the ones the identity already owns.

   Three rules govern the whole sheet, and every declaration below obeys
   one of them:

     1  NO ROUND CORNER, ANYWHERE. astralaika.com contains the string
        "border-radius" zero times and so does this file. Elevation is the
        company's hard offset square of ink and never a soft shadow.

     2  COLOUR IS RESERVED FOR IDENTIFICATION. Paper, ink and one cosmic
        red carry the entire page. The fourteen product hues appear in
        exactly two places — the glyph at the head of an entry, and that
        entry's step on the scale — and mean exactly one thing: which
        application this is. Pointing at a row *inks* it; it never tints
        it.

     3  THE VOID IS A MATERIAL. The left column is mostly empty on
        purpose, and what fills it is a readout that only exists when
        something is being pointed at.
   ═══════════════════════════════════════════════════════════════ */

/* Boot guard. The markup carries English defaults so a crawler that runs
   no script still reads a page; a human should not watch them being
   replaced. The head sets data-ready after 2500 ms whatever happens, so a
   script that fails to load costs a delay rather than a blank page.

   No fade: this page's whole argument is that nothing is waited for. */
html:not([data-ready]) body { visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
  html:not([data-ready]) body { visibility: visible; }
}

:root {
  /* The page's one horizontal margin. Everything on the sheet starts on
     it: the bar, the spread and the bulletin all share the value, so the
     left edge of the page is a single unbroken vertical. */
  /* astralaika.com's gutter, to the value. It used to be eight pixels
     narrower at full width — a gap that had no written reason, and the
     left margin is the first measure an eye compares between two pages
     of the same house. */
  --pad: clamp(20px, 4.5vw, 64px);
  /* The figure from the identity, and astralaika.com's: sixty-eight
     pixels, borders included — the six-pixel band and the three-pixel
     rule are *inside* the measure, not on top of it. */
  --bar-h: 68px;
  /* Which way a leader is drawn — towards the arrow, which is towards the
     application. In an RTL page that is the other way. */
  --lead-origin: left;

  /* ══ THE PAINT BOX ══════════════════════════════════════════
     Five inks, one single measure, and it is a system: they are declared
     together, numbered in the order the press lays them down, and no
     other colour value is written anywhere else in this file. The
     reference is nineteen-seventies screen printing — the printed
     rainbow, one colour per pass — held at the level of the cosmic red,
     which is a *knocked-back* red: not a screen red, an ink-on-paper
     red.

     THE MEASURE. #C8321E is, in OKLCH, L 0.549 · C 0.190 · h 31°. That
     is the standard: every ink in the box aims at that lightness and
     that chroma, and keeps of its own nothing but its hue.

     THREE OBEY. Blue and magenta did not exist as house colours: they
     are taken from the product wheel — Write's azure, Photo's fuchsia —
     then knocked back *exactly* onto the standard. The wheel's raw
     values are tuned to tell one another apart at sixteen pixels in a
     launcher, which is the inverse of the problem here: the azure
     #4B6FFF climbed to L 0.599 / C 0.217 and the fuchsia #C21F98 to
     L 0.558 / C 0.223 — both brighter than the red, so both would have
     shouted louder than it in the same band.

     TWO DO NOT OBEY, and sRGB is the cause in both cases. The compromise
     is written down here rather than guessed at later.

       THE GOLD ended up obeying, and it took two round trips to work out
       why. #C89B3C is at L 0.714 — 0.165 above the red — and it was long
       kept as it was, with an exception written for it: the only segment
       of the bulletin to carry ink instead of paper, because paper only
       measures 2.39:1 on it while ink climbs to 7.24 there.
       The exception was right segment by segment and wrong for the whole
       band: five assertions of which one changes text colour halfway
       through read as a defect, whatever the reason.

       So it is knocked back as blue and magenta were, to the standard's
       lightness: L 0.549, h 83°, chroma at the maximum sRGB allows
       there — 0.114. #916A00, paper 4.60:1. It carries at last the same
       text as its four neighbours.

       WHAT THAT COSTS, AND IT IS WRITTEN HERE BECAUSE IT IS REAL. This
       file used to call #916900 "a bronze, not a gold", and it was
       right: at that lightness the colour is a dark mustard, not the
       light gold of the identity. What was asked for — five inks, one
       single text — was not compatible with the light gold, and it is
       the gold that moved rather than the text, because an isolated text
       is seen and a darkened hue is compared with nothing.

       The identity's `--gold` does not move: #C89B3C stays what it is
       everywhere the house uses it. The paint box is not the identity,
       it is a measured derivation of the identity.

       THE GREEN falls outside on chroma, and by a hair on lightness. It
       is taken from Calendar (#109E6A, h 161°), the only true green ink
       on the product wheel — Sheets is an olive at h 118°. At L 0.549
       and h 161°, the maximum chroma sRGB contains is 0.123, that is two
       thirds of the standard: first departure, and it is endured.

       The second is chosen. At the standard's lightness, this green gave
       #008759, which carries neither paper (4.26:1) nor ink (4.07:1) —
       the worst possible lightness, the one that misses both thresholds
       through the middle. So it is taken down to L 0.530, that is
       nineteen thousandths below the red: #008054, paper 4.65:1.
       Nineteen thousandths are not visible in a band; illegibility is.

     THE ORDER: 268° → 342° → 31° → 83° → 161°. It is not a filing order,
     it is a path — a continuous sector of the hue wheel, which is the
     definition of a rainbow. The green closes the loop. */
  /* The five inks are the tile colours themselves, taken as they stand
     from `PRODUCTS`. They had been knocked back in OKLCH onto the cosmic
     red to form a homogeneous series; the owner wants them raw, and he
     is right on the substance: those hues are ones everybody already
     recognises on the tiles in the list. Knocked back, they became five
     more colours that nothing tied to anything at all — and the gold
     lost its shine there and turned into a mustard.

     The price is legibility: they no longer share a lightness, so the
     text they carry does not have the same comfort everywhere. It is an
     owned choice, not an oversight. */
  --press-1: #4b6fff;   /* blue    — Write   */
  --press-2: #c21f98;   /* magenta — Photo   */
  --press-3: #e23b33;   /* red     — Slides  */
  --press-4: #d9a017;   /* yellow  — Vector  */
  --press-5: #3e9c2e;   /* green   — Toolbox */
  --press-6: #00b8d9;   /* cyan    — Whiteboard */

  /* There was a second series here: the same five hues lightened to
     L 0.66, calculated so that the creed bulletin could carry black
     text. It has been removed, and that is a gain rather than a
     surrender.

     The page carried ten inks for five colours — a dark series on the
     band at the top, a light series on the bulletin at the bottom — and
     nobody could see that they were the same hues. Two series that
     vaguely resemble each other do not make a system, they make a doubt.
     One single series used at both ends of the first screen makes one.

     What that costs is written where it is paid for, on the bulletin:
     the text there goes back to paper, and the gold takes up its ink
     exception again. */

  /* Five clean flats, and not one pixel of interpolation: every stop is
     doubled, so that no pass melts into the next. A smooth gradient
     would betray both registers at once. */
  --press: linear-gradient(to right,
    var(--press-1) 0 16.667%, var(--press-2) 16.667% 33.333%,
    var(--press-3) 33.333% 50%, var(--press-4) 50% 66.667%,
    var(--press-5) 66.667% 83.333%, var(--press-6) 83.333% 100%);

  /* The duration of one pass, and it is shared. The page's two inked
     objects — the opening band and the creed bulletin — both read it, so
     that the blue pass at the top and the blue promise at the bottom are
     laid down in the same frame. That is what makes the correspondence
     visible instead of leaving it to be guessed at. Five passes at the
     top, five promises at the bottom, the same clock: the last ink falls
     at the same time as the last thing the page has to say. */
  --press-pass: 140ms;
}
[dir="rtl"] {
  --lead-origin: right;
  /* The band reads in the direction of reading: in a right-to-left
     script the first pass is the one on the right. */
  --press: linear-gradient(to left,
    var(--press-1) 0 20%, var(--press-2) 20% 40%,
    var(--press-3) 40% 60%, var(--press-4) 60% 80%,
    var(--press-5) 80% 100%);
}

/* The hub is a document, so it gets a document's text selection and a
   document's scroll. Nothing here hijacks either. */
body {
  min-height: 100vh;
  min-height: 100dvh;
}

/* An anchor followed under a fixed bar lands under the bar. The company's
   site settles that in one line and it is the same one here. */
html {
  scroll-padding-top: calc(var(--bar-h) + 16px);
}

/* ═══════════════════════════════════════════════════════════════
   THE SHEET — the first screen, and the whole selector
   Three rows: the masthead, the spread, the bulletin. `min-height`
   rather than `height`, so a short window or a long language grows the
   page instead of clipping it.
   ═══════════════════════════════════════════════════════════════ */
.sheet {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  min-height: 100vh;
  min-height: 100dvh;
  /* The room the masthead took up when it was a row of this grid. It is
     fixed now, therefore out of flow: without this padding the first row
     would pass underneath it. `box-sizing: border-box` makes the padding
     sit *inside* the 100dvh — so the first screen keeps exactly the
     height it had, to the pixel. */
  padding-block-start: var(--bar-h);
  /* No sunburst. --field-rays is the company's hero device and the suite
     is allowed exactly one place to draw it, which would be here — but it
     was tried and it lost: at the alpha the company uses it read as a
     starburst wallpaper behind the headline and became the second idea on
     a page whose whole argument is that there is one. The wash underneath
     (the 45° stock hatch and the four warm halos) is the texture this
     sheet gets, and it is quiet enough to stay underneath. */
}

/* ═══ THE BAR ═════════════════════════════════════════════════
   astralaika.com's own, taken over and not imitated. Its height, its
   six-pixel band, its three-pixel rule, its gap of twenty-two, its
   navigation pushed to the right by an automatic margin, its red plate:
   the values are the site's, and the only substitution is the mark.

   It is fixed. That is *its* scroll behaviour, and the only one the site
   gives it — no appearing, no hiding away, no shrinking: it is there, all
   the time, and the page passes underneath. A bar that hides is a bar
   that has to be gone looking for.

   It costs the first screen nothing: what it occupied as a grid row, it
   now occupies as padding on the sheet. */
.bar {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 1000;
  height: var(--bar-h);
  display: flex;
  align-items: center;
  gap: 22px;
  padding-inline: var(--pad);
  /* A flat, and nothing else: astralaika.com's `background: var(--paper)`,
     that is to say #F3EDE0 laid down clean.

     It once carried `var(--field)` in `background-attachment: fixed`, so
     that the bar's wash continued the body's exactly. The idea is
     defensible and the result misses what a bar must do: the site's is a
     flat that *separates* the page from its header, ours melted into it.
     A fixed bar is an object laid on the sheet, not a cut-out in it. */
  background: var(--ls-sand-50);
  /* The opening band is no longer a border but a padding: it is painted
     by ::before just below, and it keeps exactly the six pixels of the
     identity. `box-sizing: border-box` leaves them *inside* the
     sixty-eight. */
  padding-block-start: var(--band);
  border-block-end: var(--rule-section) solid var(--border-ink);
}

/* ══ THE BAND — the paint box, printed ═════════════════════════
   The six pixels of red that used to open the page now carry five. They
   cost nothing: it is the same band, at the same height, in the same
   place — the inks are brought into it instead of an object being added.

   And it says something. Its five passes are, in that exact order, those
   of the five promises of the creed bulletin at the bottom of the first
   screen: the band at the top is the legend for the band at the bottom,
   and the legend is complete — one pass, one promise, no remainder.

   It was not always so. The green entered the box before it had anything
   to name, and the fifth pass stayed silent for as long as it took to
   find what it was saying. What it was saying was already true and
   already written nowhere: these applications install.

   The movement says the same thing once only: `steps(5)`, so the band
   does not reveal itself, it *lays itself down* — one pass, then the
   next, five clean states and nothing in between. It is a press, not a
   wipe, and it is what holds together Patagonia's screen printing and the
   Soviet poster: neither of them blends its colours.
   It runs once, on opening, and never starts again. */
.bar::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: var(--band);
  background: var(--press);
  /* Decoration: in forced colours it keeps its five passes rather than
     collapsing into a single system flat, like the bulletin and the
     colophon further down. */
  forced-color-adjust: none;
}
/* `html[data-ready]`, and it is not a precaution: `html:not([data-ready])
   body` is in `visibility: hidden` at the very top of this file. An
   animation triggered when the CSS is parsed therefore plays while the
   page is still invisible, and on a slightly slow load it is over before
   having been seen — which is the definition of an animation that serves
   no purpose. Hooked onto the attribute, it starts the second the sheet
   appears. */
@media (prefers-reduced-motion: no-preference) {
  html[data-ready] .bar::before {
    animation: press-lay calc(var(--press-pass) * 5) steps(5, jump-start) both;
  }
}
@keyframes press-lay {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}
[dir="rtl"] .bar::before { animation-name: press-lay-rtl; }
@keyframes press-lay-rtl {
  from { clip-path: inset(0 0 0 100%); }
  to { clip-path: inset(0 0 0 0); }
}

/* The mark, and it is the suite's. Forty pixels in a forty-pixel box,
   like the site's `.logo-slot` — and the width is *declared* on the
   image: the file is 180 px on a side, and laid down with no dimension it
   had already pushed this masthead to 189 px tall and stolen 121 px from
   the first screen. An image with no declared width is an image that
   decides the layout. */
.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  color: var(--text);
  text-decoration: none;
}
.brand:hover { color: var(--text); text-decoration: none; }
.logo-slot {
  display: grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
}
.logo-slot img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: transform 0.3s var(--ease-out);
}
.brand:hover .logo-slot img { transform: rotate(-10deg) scale(1.1); }
.brand-name {
  font-size: 18px;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

/* Two links, and two real destinations. The three-pixel underline that
   inks itself on hover is the site's. */
.bar-nav {
  display: flex;
  margin-inline-start: auto;
  min-width: 0;
}
.bar-nav a {
  padding: 8px 12px;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  border-block-end: var(--rule-section) solid transparent;
  transition: border-color 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.bar-nav a:hover {
  color: var(--ls-ember-700);
  border-block-end-color: var(--ls-ember-600);
  text-decoration: none;
}
.bar-nav a:focus-visible {
  outline: var(--rule-strong) solid var(--accent);
  outline-offset: 2px;
}

.bar-cta { flex: none; }

/* The knob — astralaika.com's own notched button, kept transparent until
   it is pointed at. The notch belongs here: it is what the company clips
   off its buttons, and a clip-path costs nothing on a control that has no
   shadow to lose. */
.knob {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap-target);
  padding: 6px 12px;
  color: var(--text-secondary);
  background: none;
  border: var(--rule-strong) solid transparent;
  clip-path: var(--notch);
  cursor: pointer;
  transition: var(--transition-control);
}
.knob:hover {
  color: var(--text);
  border-color: var(--border-ink);
}
.knob:focus-visible {
  outline: var(--rule-strong) solid var(--accent);
  outline-offset: 2px;
}
.knob .ls-icon { flex: none; }
.knob__value { white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════
   THE SPREAD — the poster on the left, the index on the right
   ═══════════════════════════════════════════════════════════════ */
.spread {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(24px, 3.4vw, 68px);
  min-width: 0;
  padding: clamp(20px, 3vh, 44px) var(--pad);
}

/* ═══ THE POSTER ══════════════════════════════════════════════
   Three rows: the kicker, the headline, the readout — and the fourth,
   which has nothing in it, is the reserve. The scale occupied it; it went
   with the count it measured, and the void it leaves is the one this
   stance has claimed since its first line: "the void in the left-hand
   column is not a lack, it is the material".

   The last row is `minmax(0, 1fr)` and never `auto`: an `auto` row lets
   the intrinsic height of what it contains rise into that of the column,
   and a German headline laid on a 258-pixel figure had then pushed the
   whole spread out of the window and sent the bulletin below the fold.
   The reserve takes what is left, and never one pixel more. */
.poster {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto minmax(0, 1fr);
  min-width: 0;
}

/* The kicker, and it is the site's `hero-kicker`: PT Mono in caps and
   tracked out, preceded by the four-pointed star, laid above the
   headline. The count lives there now. It used to be the largest type on
   the page, it is now its smallest line; that is the only thing phase 2
   does to it, and it is enough — it is still written from APPS.length, it
   is still right, it is simply no longer the argument. */
.poster-kicker {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  /* The site's `hero-kicker` lays clamp(20px, 4vh, 40px) beneath itself;
     we were laying half of that, and the kicker read as stuck to the
     headline instead of preparing it. A service line above a poster needs
     its silence, otherwise it becomes part of it. */
  margin-block-end: clamp(20px, 4vh, 40px);
  color: var(--text-muted);
}
.poster-kicker .ls-star { --form-size: 0.8em; flex: none; color: var(--brand-red); }

.poster-head {
  margin: 0;
  font-size: clamp(2.35rem, 6.2vw, 5.1rem);
  /* 1.14, not the token's 1.02, and the difference is measured rather
     than felt. Anton stacks its accents at about one em above the
     baseline — higher than its own cap height — so at 0.95 the acute of
     CRÉER printed a red wedge through APPLICATIONS, at 1.02 the umlaut of
     ÖFFNEN sat on the digits of 14 ANWENDUNGEN, and at 1.08 it cleared
     them by two pixels at 81px, which is nothing at 36px. A display
     leading is set for the alphabet it is going to carry, and this one
     carries 23 of them: Czech, Polish, Vietnamese and Turkish all stack
     higher than German. The block still reads as one dense mass, which is
     what a poster wants; it simply no longer touches. */
  line-height: 1.14;
  letter-spacing: var(--tracking-display);
  /* A poster is ranged left and ragged right. `balance` evens the lines
     out, which is what a centred deck wants and the opposite of what this
     wants: here the first line should run the full measure. */
  text-wrap: initial;
  /* Hyphenation is not a fallback here, it is the craft: a German or
     Finnish compound is *meant* to break, and a poster that refuses to
     break is a poster that overflows. `lang` is on <html>, so the
     dictionary is the reader's own. */
  hyphens: auto;
  overflow-wrap: break-word;
}
.poster-claim,
.poster-verb { display: block; }
/* The guarantee, in ink. It is the page's assertion, and it is the only
   one it makes above the fold. */
.poster-claim { color: var(--text); }
/* The second line in the company's red — its own hero does exactly this,
   and --brand-red is solved per theme so it clears AA on both sheets. */
.poster-verb { color: var(--brand-red); }

/* ═══ THE READOUT ═════════════════════════════════════════════
   The left column is the display for the column beside it. Its height is
   reserved rather than fluid: a block that grew when an entry was pointed
   at would move the whole page under the pointer. */
.readout {
  min-height: clamp(132px, 19vh, 196px);
  margin-block-start: clamp(18px, 3vh, 36px);
  padding-block-start: var(--space-3);
  /* The rule runs the full width of the column, not the width of the text
     under it: a two-pixel rule that stops in the middle of a column is a
     rule that has been cut, and this identity draws rules that close
     sections. The measure is set on the text instead. */
  border-block-start: var(--rule-strong) solid var(--border-ink);
}
.readout-name {
  font-size: var(--display-sm);
  color: var(--text);
}
.readout[data-on="false"] .readout-name { display: none; }
.readout-line {
  max-width: 34ch;
  font-family: var(--font-serif);
  font-size: var(--text-md);
  line-height: var(--leading-loose);
  color: var(--text-secondary);
}

/* The scale has been removed, and with it its eighty lines of style
   sheet. Fourteen ink steps dimensioned "01 —— 14": it measured the count
   of applications, that is to say the very thing phase 2 stopped wanting
   to say. It had been kept because it *said* something; the moment the
   headline stopped counting, all it said was a repetition — and it needed
   its dimension to be read at all, which is the admission of an object
   that decorates. Removed for good rather than hidden: the history keeps
   everything.

   What it leaves is the empty last row of the left-hand column, and that
   is rule number three of this file. */

/* ═══════════════════════════════════════════════════════════════
   THE INDEX — fourteen numbered entries

   A glass plate in a brutalist frame: two pixels of ink, a hard offset
   square of shadow, and the suite's own lensed material inside. No
   clip-path: the notch would take the shadow with it, and a filtered
   wrapper would open a backdrop root and leave the glass nothing to
   refract. The notch stays on the buttons and on the colophon plate,
   which is where the company puts it.
   ═══════════════════════════════════════════════════════════════ */
.register {
  /* The floor is what decides whether fourteen entries are one screen or
     two. 5.2vh puts them at 47px on a 900-tall window and 40px on a
     768-tall one, which is the height at which a 28px plate, a 12.5px
     numeral and an Anton name still sit on one line without touching.
     Below the floor the plate simply grows taller than the viewport and
     the page scrolls, which is honest; it never crushes a row. */
  --row-min: clamp(42px, 5.2vh, 64px);
  display: grid;
  grid-template-rows: repeat(var(--rows, 14), minmax(var(--row-min), 1fr));
  min-width: 0;
  background: var(--glass);
  -webkit-backdrop-filter: var(--glass-filter);
  backdrop-filter: var(--glass-filter);
  border: var(--rule-strong) solid var(--border-ink);
  box-shadow: var(--shadow-sm), var(--shadow-sheen);
}

.entry {
  /* Reference frame for the red edge below, and nothing else: the row
     stays a grid and none of its children has left the flow. */
  position: relative;
  display: grid;
  grid-template-columns: auto auto minmax(0, auto) minmax(0, 1fr) auto;
  grid-template-areas: "no mark name lead go";
  align-items: center;
  gap: clamp(10px, 1.2vw, 20px);
  min-width: 0;
  padding-inline: clamp(12px, 1.6vw, 26px);
  color: var(--text);
  text-decoration: none;
  border-block-end: var(--rule) solid var(--line);
  transition: background-color var(--duration-fast) var(--ease-out);
}
.entry:last-child { border-block-end: 0; }
.entry:hover {
  /* Ink at five and a half percent — not the product hue. On this page a
     hue names an application and does nothing else. */
  background-color: var(--hover);
  color: var(--text);
  text-decoration: none;
}
.entry:focus-visible {
  outline: var(--rule-strong) solid var(--accent);
  outline-offset: calc(var(--rule-strong) * -1);
}

/* ── THE RED EDGE ─────────────────────────────────────────────
   Eight pixels of cosmic red on the leading edge of the row being pointed
   at, and it is astralaika.com's material taken as it stands: the site
   gives a `border-left: 8px solid var(--red)` to its directives and to
   its manifesto, that is to say to the blocks it designates as the ones
   being read. Neither the stamp's shape nor the card's has been taken
   over — five substitutions of the selector have already been refused,
   and the numbered list stays a numbered list. It is the ink that
   travels.

   It is painted by a pseudo-element and not by a border, because an
   eight-pixel border would shift the fourteen rows by eight pixels when
   any one of them is hovered. `inset-inline-start` puts it on the side
   the reading comes from, therefore on the right in a right-to-left
   script, without one more rule. */
.entry::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 0;
  background: var(--ls-ember-600);
  transition: width var(--duration-fast) var(--ease-out);
}
.entry:hover::before,
.entry:focus-visible::before { width: 8px; }

/* ── THE NUMBER ───────────────────────────────────────────────
   It used to turn red; it becomes a plate.

   It is astralaika.com's `.section-tag b` to the value — `padding: 3px
   9px`, paper knocked out of the house red, and the weight left at 400
   because the site takes the trouble to bring it back there after having
   chosen a `<b>`. The site numbers its sections in exactly that way, and
   this page is a table of contents: it is the same gesture.

   The padding is laid down permanently and only the ground arrives,
   otherwise the row rearranges itself under the pointer. Tabular figures,
   because a column of figures that changes width depending on the figure
   is not a column — and centred, because a figure in a plate is centred.

   Measured: #FBF7EC on #C8321E gives 4.99:1, which holds AA for these
   12.5 px. The ink is `--ls-ember-600`, that is to say astralaika.com's
   `--red`: this page's red has one single source, and it is not the paint
   box — that one serves the two bands and nothing else. */
.entry-no {
  grid-area: no;
  padding: 3px 9px;
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  text-align: center;
  color: var(--text-faint);
  transition: color var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out);
}
.entry:hover .entry-no,
.entry:focus-visible .entry-no {
  color: var(--ls-sand-0);
  background: var(--ls-ember-600);
}

/* The mark, replated.

   The application's own geometry is untouched — it belongs to the
   application — but its *presentation* here is not the tile it wears in a
   dock. A tile is a rounded square carrying a three-stop gradient and a
   specular sheen, and this identity contains no rounded square anywhere.
   So the glyph is knocked out of a flat square of the product's own ink:
   one colour, four right angles, the way a stamp is cut.

   Both the plate and the glyph are solved per theme rather than taken
   from `mid`, because `mid` fails at both ends — Vector's #D9A017 leaves
   paper at 2.0:1 and Packets' #205C93 leaves the dark sheet at 1.4:1.
   Light takes the dark step of the product's ramp with a paper glyph on
   it; dark takes the light step with an ink glyph. Every one of the
   fourteen clears 3.4:1 inside the plate and reads as a square against
   its own sheet. */
.entry-mark {
  grid-area: mark;
  display: block;
  width: clamp(22px, 2.2vw, 28px);
  aspect-ratio: 1;
  /* No ground: the mark carries its own. The box used to paint a square
     plate behind the SVG — a leftover from the time when the entry showed
     a monochrome glyph that had to be laid on something. Since the mark
     has been cropped to a disc, that square squared it straight back up,
     and the cropping was visible nowhere. */
}
/* The drawn box the house gives anything that is an object rather than a
   surface: ink outline, rounded corners, hard offset shadow. Same
   treatment as the plates on astralaika.com, scaled to a mark that stands
   in a line of text rather than on a card — 1.5 px of rule, not 2. At this
   size the proportion carries, not the value: a 2 px rule on a 22 px mark
   is a mark that is one seventh outline.

   The frame is on the BOX and the artwork is pushed out to meet it. The
   tile's rounded rect is drawn 60 wide inside a 64 viewBox — inset by two
   units on every side — so a rule placed at the element's edge stood a
   whisker away from the drawing and left the pale gap the owner saw. The
   scale of 64/60 closes it exactly, and `overflow: hidden` on the rounded
   box trims what that push sends past the corners.

   The radius is a percentage for the same reason: the tile's own corner is
   16 of its 60, so 27 % of the box lands on the drawn corner at any size
   this mark is ever shown at. */
.entry-mark {
  overflow: hidden;
  border: 1.5px solid var(--border-ink);
  border-radius: 27%;
  box-shadow: 2px 2px 0 var(--border-ink);
}
.entry-mark svg {
  display: block;
  width: 100%;
  height: auto;
  transform: scale(1.0667);
}

/* The name. A wordmark, so it keeps Anton in all 23 locales — a product
   name is not translated. */
.entry-name {
  grid-area: name;
  font-size: clamp(1.02rem, 1.5vw, 1.5rem);
  line-height: 1;
  white-space: nowrap;
}

/* The leader — the dotted rule of a printed table of contents, and the
   one thing on this page that moves.

   Two background layers on one box: a dashed hairline that is always
   there, and a solid two-pixel rule sized to nothing until the entry is
   pointed at, when it draws from the name towards the arrow. Animating
   `background-size` touches no layout and repaints one strip. */
.entry-lead {
  grid-area: lead;
  align-self: center;
  min-width: var(--space-4);
  height: 2px;
  background-image:
    linear-gradient(var(--ink-solid), var(--ink-solid)),
    repeating-linear-gradient(90deg, var(--border-strong) 0 2px, transparent 2px 7px);
  background-size: 0% 2px, 100% 1px;
  background-position: var(--lead-origin) center, left center;
  background-repeat: no-repeat, repeat-x;
  transition: background-size var(--duration-normal) var(--ease-out);
}
.entry:hover .entry-lead,
.entry:focus-visible .entry-lead { background-size: 100% 2px, 100% 1px; }

.entry-go {
  grid-area: go;
  display: flex;
  color: var(--text-faint);
  transition: color var(--duration-fast) var(--ease-out),
    translate var(--duration-fast) var(--ease-out);
}
.entry:hover .entry-go,
.entry:focus-visible .entry-go {
  color: var(--brand-red);
  /* --shadow-x is +1 in an LTR page and -1 in an RTL one, so the arrow
     always steps towards the edge it points at. */
  translate: calc(5px * var(--shadow-x)) 0;
}

/* The sentence. It lives in the readout on a wide screen and inside the
   entry on a narrow one, because a phone has no pointer to put on a row
   and therefore no readout to fill. Nothing is truncated either way. */
.entry-line {
  grid-area: line;
  display: none;
  min-width: 0;
  font-family: var(--font-serif);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--text-muted);
}

/* ═══ THE CREED BULLETIN ══════════════════════════════════════
   The company's band, which closes the first screen as the bar opens it —
   and it now carries the four inks of the same paint box, one per
   promise. The inks are printed: they are worth the same thing on both
   sheets, because an ink does not know what time it is.

   The height does not move. The vertical padding that was on the band has
   passed as it stands onto the segments — `clamp(9px, 1.2vh, 15px)` — and
   the grid shares the measure out into equal tracks, so the band does
   what it did: 45 px at 1440×900, as before.

   No white between two passes: `gap: 0`, doubled stops in the gradient of
   the band at the top, and here four abutting grounds. Two inks touching
   on a clean edge is what a screen print does; a blend would betray both
   registers at once. */
.bulletin {
  display: grid;
  /* Six equal tracks for six promises, one per pass of the band at the
     top and in the same order. The count is not a layout choice: every
     colour pass carries an assertion, and an ink is only added when there
     is something true left to say. */
  grid-template-columns: repeat(6, minmax(0, 1fr));
  border-block-start: var(--rule-section) solid var(--border-ink);

  /* Six DRAWN cells, in the rule of the application selector.
     The promises were six abutting flats: the band read as a gradient of
     bands, not as a plate. The selector, just above, is framed by a
     two-pixel rule of ink and it is that which gives the page its air of
     a printed thing; the band had to carry it too.

     The rule is not a border on each cell but the INK OF THE GROUND
     showing through the gutters. A border per cell would have doubled in
     thickness at every join and would have had to be removed on the last
     one — then on the last of each row, which is not the same below
     1024 px, where the grid goes to two columns. Here there is nothing to
     remove: the gutter is regular whatever the number of columns, in both
     directions.

     And a rule at the bottom, which the band did not have: without it, it
     ended in the paper of the next section, and a plate open on one side
     is no longer a plate. */
  gap: var(--rule-strong);
  background: var(--border-ink);
  border-block-end: var(--rule-section) solid var(--border-ink);
}
.creed {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-width: 0;
  padding: clamp(9px, 1.2vh, 15px) var(--space-2);
  text-align: center;
  /* Six promises instead of four, in twenty-three languages German among
     them: the room per segment has been cut by a third while the
     sentences stayed the same. Rather than shortening them — which would
     have meant retranslating twenty-three times and losing precision —
     the type size follows the room available and the tracking closes up.
     `text-wrap: balance` shares the two lines out evenly instead of
     leaving one word alone underneath, which is the real cause of the
     impression of clutter. */
  font-size: clamp(0.62rem, 0.52rem + 0.34vw, 0.78rem);
  letter-spacing: 0.06em;
  line-height: 1.3;
  text-wrap: balance;
  hyphens: auto;
  /* Ink, on all five. The band carried paper on three of its segments and
     ink on the fourth — the gold, the only one light enough for that —
     and that exception showed: a band of four promises one of which is
     written the other way round. It is the anomaly that ended up
     delivering the right rule — then the rule reversed.

     The bulletin carried black ink on five lightened inks. It carries
     paper again on the five inks of the band at the top, because the
     unity of the two objects is worth more than the uniformity of the
     text: at L 0.549 these inks carry paper at 4.65 / 4.77 / 4.99 / 5.06
     and do not carry black, which tops out at 3.6. One does not choose
     the colour of the text and then the colour of the ground; it is the
     ground that decides.

     All five carry paper, without exception, and that is the last rule
     this bulletin has learned. Measured, #FBF7EC on the five passes:
       blue 4.77:1   magenta 5.06:1   red   4.99:1
       gold 4.60:1   green   4.65:1
     The worst is at 4.60, above the threshold. */
  color: var(--ls-sand-0);
  background: var(--creed-ink);
  /* Background decoration declared by the page: in forced colours it
     keeps its five passes rather than collapsing into a system flat. */
  forced-color-adjust: none;
}
.creed:nth-child(1) { --creed-ink: var(--press-1); }
.creed:nth-child(2) { --creed-ink: var(--press-2); }
.creed:nth-child(3) { --creed-ink: var(--press-3); }
/* No more exception. The gold carried ink when the four others carried
   paper; it is the pass that has been darkened, not the text that has
   been left alone in its colour. See the paint box. */
.creed:nth-child(4) { --creed-ink: var(--press-4); }
.creed:nth-child(5) { --creed-ink: var(--press-5); }
.creed:nth-child(6) { --creed-ink: var(--press-6); }

/* ── THE FIFTH PASS ────────────────────────────────────────────
   At first it carried nothing but a star, on the grounds that there were
   five inks for four promises and that manufacturing a fifth one to
   occupy a colour would have been decoration. The reasoning held; the
   result did not. A lone character on a flat colour does not read as the
   margin of a press — it reads as a string that failed to arrive, the
   exact state a page whose argument is that it makes nobody wait cannot
   afford to mimic.

   There was nothing to manufacture: installation was true, verifiable and
   written nowhere, while the whole suite depends on it. It was a link to
   the section for the length of one round trip, then brought back to an
   inert segment like its four neighbours; the rules that dressed it as a
   link were removed with it rather than left lying about. Its ink is the
   fifth light pass, laid down with the four others above. */

.creed .ls-star { --form-size: 0.7em; opacity: 0.75; }

/* The five promises ink themselves one after the other, in the order they
   are read, and on the same clock as the band at the top: `--press-pass`
   is shared, `steps(1, jump-start)` drops each promise in one go at the
   start of its pass, so that the bar's blue pass and the bulletin's blue
   promise are laid down in the same frame. That is where the code reads:
   one colour, one promise, one pass.

   Nothing moves and nothing is resized — the four boxes are in place from
   the first frame, only the ink arrives. */
@media (prefers-reduced-motion: no-preference) {
  html[data-ready] .creed {
    animation: creed-ink var(--press-pass) steps(1, jump-start)
      calc(var(--i) * var(--press-pass)) both;
  }
}
@keyframes creed-ink {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Below 1024 the measure no longer holds four labels of tracked-out PT
   Mono on one line: two tracks, and two all the way down. A single track
   was measured and set aside — four stacked colour bands came to 164 px
   tall on a phone against 99 before, and a phone page ended on a flag.
   Two tracks come to 132, which is the original order of magnitude.

   The colours follow the promises, never the cells: the blue stays on
   "Instant" whatever the number of rows, because it is the child's rank
   that distributes them and not its position on screen. */
@media (max-width: 1023px) {
  /* Six divides by two: three full rows, no hole, and therefore no more
     need for a segment to span. Five did not divide, which forced the
     last one to occupy the full width so as not to leave an empty cell
     beside it. */
  .bulletin { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ═══════════════════════════════════════════════════════════════
   THE INSTALL SECTION — the third destination

   astralaika.com's section template, taken over and not imitated: the
   1180 px measure, the monospace tag with its number knocked out of the
   red, the poster title, the standfirst, then the grid of cards with two
   pixels of ink and eight pixels of red on the leading edge.

   Nothing is drawn here. It is the form the site uses for three short
   blocks that explain something, and that is exactly what this section
   is.
   ═══════════════════════════════════════════════════════════════ */
.setup {
  /* NO centred 1180 px rail, and it is the one place where we depart from
     the site's template — in order to obey a rule this page wrote before
     it. The gutter is the first line of this file: "everything on the
     sheet starts on it, so that the left edge of the page is a single
     unbroken vertical". A 1180 rail centred in a 1440 window starts its
     content at 194 px, when the bar, the poster and the selector all
     start at 64. Measured: three different verticals on the same sheet of
     paper, and it is exactly the sort of gap that shows without one being
     able to name it.

     The site can afford it: its pages are single-column and nothing above
     a section gives the scale. Here, the selector is just above and it
     gives the scale. The colophon keeps its centred rail because it is
     another plate — ink, not paper — and a change of support is entitled
     to change measure.

     The vertical measures of the site's `.section`, for their part, are
     taken over as they stand. We were holding
     a third tighter everywhere — 104 px of breathing room instead of 150,
     a section head at 48 instead of 60 — and a section is no denser for
     it: it is simply less finished. */
  padding: clamp(80px, 12vh, 150px) var(--pad);

  /* The site's greyer beige — `--paper-2`. The section thereby stands out
     from the page's paper without changing family: it is the shade
     astralaika.com reserves for what it wants to set back, and not one
     more colour. A section that explains a gesture is not on the same
     plane as the one that gives access to the applications. */
  background: var(--ls-sand-100);
}
.setup-head { margin-block-end: clamp(36px, 6vh, 60px); }

/* The site's `.section-tag`, including its number knocked out of the red
   — the same object as the selector's number plate, at the same measure.
   The table of contents numbers its entries, the page numbers its
   sections. */
.setup-tag {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-block-end: 18px;
  color: var(--text-muted);
}
.setup-tag b {
  padding: 3px 9px;
  font-weight: 400;
  color: var(--ls-sand-0);
  background: var(--ls-ember-600);
}
.setup-title {
  max-width: 22ch;
  /* The site's clamp(32px, 5.4vw, 68px), in rem. The section title
     climbed to 54 px where the site goes to 68: between an 82 px poster
     above and a 16 body below, fifty-four did not open the gap wide
     enough for the hierarchy to be seen without looking for it. */
  font-size: clamp(2rem, 5.4vw, 4.25rem);
  line-height: 1.14;
  letter-spacing: var(--tracking-display);
  text-wrap: initial;
  hyphens: auto;
  overflow-wrap: break-word;
}
.setup-lead {
  max-width: 62ch;
  margin-block-start: 18px;
  font-family: var(--font-serif);
  /* One notch above the body, like the site's `.section-sub` which holds
     16.5 px when its cards hold 15. The standfirst and the cards were at
     the same size: two levels of reading written at the same size are one
     single level. */
  font-size: var(--text-xl);
  line-height: var(--leading-body);
  color: var(--text-secondary);
}

/* ── THE TWO STEPS ────────────────────────────────────────────
   Before the gestures, and numbered, because the order was what was
   missing: one does not install from this page, one installs from the
   application. An ordered list, therefore an <ol> — the rank is the
   information. */
.setup-steps {
  display: grid;
  gap: var(--space-4);
  margin-block-end: clamp(32px, 5vh, 52px);
  padding: 0;
  list-style: none;
}
.setup-step {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  gap: var(--space-4);
  min-width: 0;
  max-width: 68ch;
}
.setup-step-no {
  min-width: 2.2ch;
  padding: 3px 9px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--ls-sand-0);
  background: var(--ls-ember-600);
}
.setup-step-body {
  min-width: 0;
  font-family: var(--font-serif);
  font-size: var(--text-md);
  line-height: var(--leading-body);
}

/* ── THE CARDS ────────────────────────────────────────────────
   The site's `.directive`, to the value: `border: 2px solid var(--ink)`,
   `border-left: 8px solid var(--red)`, and the five-pixel lift with its
   hard cast shadow on hover. It is also the material of the selector's
   red edge, and that is deliberate — the red on the leading edge
   designates, on this page as on the site, the block being read. */
.setup-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 20px;
}
.setup-card {
  min-width: 0;
  /* The site's `.directive`: 26px 24px 28px, the bottom heavier than the
     top. A block of text whose foot equals its head looks as if it had
     slipped. */
  padding: 26px 24px 28px;
  background: var(--surface);
  border: var(--rule-strong) solid var(--border-ink);
  border-inline-start: 8px solid var(--ls-ember-600);
  transition: transform var(--duration-normal) var(--ease-out),
    box-shadow var(--duration-normal) var(--ease-out);
}
@media (hover: hover) {
  .setup-card:hover {
    transform: translateY(-5px);
    box-shadow: var(--shadow-sm);
  }
}
/* ── THE CARD THAT SAYS NO ────────────────────────────────────
   Identical to "On a phone", to the character, and one single thing
   changes: the gold in place of the red, on the edge and on the tag — the
   only two places where the red appears in these cards.

   It once carried a star added to its tag, to give the gold a place where
   it would not have to be read. That was one more variation, and a
   variation that has no reason reads as a mistake: the eye goes to the
   difference and looks for what it means. When an element has to resemble
   its neighbour, one copies the neighbour and changes only what has to
   change.

   THE GOLD IS #C89B3C, ASTRALAIKA.COM'S OWN, AND THE OWNER DECIDED IN
   FULL KNOWLEDGE OF THE FACTS. On this card's cream it measures 2.39:1,
   therefore below the legibility threshold — he asked for it "even if it
   is hard to see". It is the house gold, the one on the "write at the
   control centre" label, and its identity mattered more here than its
   reading comfort. The measurement is recorded so that this is a decision
   and not an oversight. */
.setup-card--limit { border-inline-start-color: var(--ls-gold, #C89B3C); }
.setup-card--limit .setup-card-tag { color: var(--ls-gold, #C89B3C); }

.setup-card-tag {
  margin-block-end: 14px;
  color: var(--brand-red);
}
.setup-card-body {
  font-family: var(--font-serif);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
  color: var(--text-secondary);
}
.setup-card-body + .setup-card-body { margin-block-start: var(--space-3); }

/* The reason, in one sentence, and below the cards: fourteen
   applications that install one by one is not a constraint, it is what
   makes it possible to install only the ones you use. */
/* Full measure, and the rule with it. It was held at 68ch and its rule
   therefore stopped in the middle of the page: that is precisely what
   this file reproaches the readout with a few hundred lines above — a
   rule that breaks off halfway is a cut rule, and this identity draws
   them only to close sections. The sentence fits on one line at this
   measure, which is also the good reason for leaving it there. */
.setup-note {
  margin-block-start: clamp(24px, 3.4vh, 40px);
  padding-block-start: var(--space-4);
  font-family: var(--font-serif);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
  color: var(--text-muted);
  border-block-start: var(--rule) solid var(--border);
}

@media (prefers-reduced-motion: reduce) {
  .setup-card { transition-duration: 1ms; }
}
@media (forced-colors: active) {
  .setup-tag b,
  .setup-step-no { color: Canvas; background: CanvasText; }
  .setup-card { box-shadow: none; }
}
@media print {
  .setup { display: none; }
}

/* ═══════════════════════════════════════════════════════════════
   THE COLOPHON — under the fold, and deliberately minor

   The company's ink footer. It inverts itself in both themes by
   construction rather than by two sets of values: --ink-solid is ink on
   the light sheet and paper on the dark one, and --text-inverse is the
   opposite of both. What has to be restated is the ramp *inside* the
   block, because a plate that inverts its own sheet inverts the ink that
   reads on it — which is the note tokens.css leaves for exactly here.
   ═══════════════════════════════════════════════════════════════ */
.colophon {
  --text-secondary: var(--ls-sand-300);
  --text-muted: #9a9079;
  --text-faint: #6b6352;
  --line: rgb(251 247 236 / 0.16);
  --border: var(--line);
  --brand-red: var(--ls-ember-500);
  /* The hover for every link on this plate, solved for the face the plate
     is currently showing. The light theme lays it on ink, where the rose
     reads at 9.90:1 and matches astralaika.com exactly; the dark theme
     inverts to paper, where that same rose falls to 1.76:1 and the ramp's
     muted mirror takes over at 5.22:1. One token, two grounds. */
  --link-hover: var(--ls-ember-200);
  /* astralaika.com's: 40px above, 26px below, measured. This plate opened
     with 47.5 and closed with 38 — more air top and bottom than the studio
     gives, on a footer that already carries more. */
  padding: clamp(24px, 4vh, 40px) var(--pad) clamp(18px, 3vh, 26px);
  color: var(--text-inverse);
  background: var(--ink-solid);
  /* The six pixels of red that used to open this plate are gone.

     They said nothing. The page already counts a band of inks at the top
     and a creed bulletin just above this rule; a third red, laid between
     the two, added no information and cut the bulletin off from what
     follows it. The separation does not rest on it: the bulletin is in
     saturated inks and this plate is in solid ink — the ground is enough,
     and it was looked at rather than assumed. */
}
[data-theme="dark"] .colophon {
  --text-secondary: #57503f;
  --text-muted: #69604f;
  --text-faint: #9a8f78;
  --line: rgb(22 19 14 / 0.16);
  --brand-red: var(--ls-ember-600);
  /* Not the ramp's red: that is the saturated company red, and against
     astralaika.com's rose the two sites would redden differently on the one
     line they share. The muted tint is the rose's mirror for this face. */
  --link-hover: var(--ls-ember-muted);
}

/* The footer's brand line: the site's `.footer-inner` — the mark on the
   left, the links pushed to the right, one single baseline that wraps
   when the measure no longer suffices. The site puts its logo box at
   thirty-four pixels and its name at fifteen in the footer, against forty
   and eighteen in the bar; it is the same graduation here, and it is what
   says that the footer is the reminder and the bar the announcement. */
.colophon-inner {
  display: flex;
  align-items: center;
  gap: 26px;
  flex-wrap: wrap;
  max-width: 1180px;
  margin-inline: auto;
  margin-block-end: clamp(24px, 4vh, 44px);
  padding-block-end: var(--space-5);
  border-block-end: var(--rule) solid var(--line);
}
/* The plate inverts, so the mark's ink does too: `--text` is not
   redefined in the colophon — only the muted ramp is — and a mark in
   `--text` there would be ink on ink. */
/* astralaika.com's paper, rgb(243,237,224) — eight points warmer than the
   ramp's lightest sand, which is what this used. The same eight points were
   wrong on the legal pages' heading plates, and for the same reason: an
   inverted plate wants the studio's paper, not the top of a neutral ramp. */
.colophon .brand { color: var(--ls-sand-50, #f3ede0); }
.colophon .brand:hover { color: var(--ls-sand-50, #f3ede0); }
.colophon .logo-slot { width: 34px; height: 34px; }
.colophon .brand-name { font-size: 15px; }

.colophon-links {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 20px;
  min-width: 0;
  margin-inline-start: auto;
}
.colophon-links a {
  /* astralaika.com's exact recipe, mechanism included: the paper colour at
     three-quarter opacity, not a pre-mixed muted token. Measured side by
     side, the studio's links land on rgb(188,183,172) and these landed on
     rgb(180,170,147) — warmer and darker, the difference the eye caught.
     Same typography on both (mono, 12.5px, 1.5px of tracking, uppercase);
     only the ink was ours. */
  color: var(--ls-sand-50, #f3ede0);
  opacity: 0.75;
  text-decoration: none;
  transition: color 0.2s var(--ease-out);
}
/* The plate's own accent, not the plate's own paper.
   --text-inverse is the ink that reads on this ground at rest, so hovering
   to it moved nothing the eye could name; astralaika.com reddens the same
   line in its footer, and this is that gesture. The token is restated per
   theme a few rules above precisely so it clears AA on both faces of a
   plate that inverts itself: 9.90:1 on the ink sheet, 4.99:1 on the paper
   one. Measured, not assumed. */
.colophon-links a:hover {
  opacity: 1;
  color: var(--link-hover);
  text-decoration: none;
}
.colophon-links a:focus-visible {
  outline: var(--rule-strong) solid var(--text-inverse);
  outline-offset: 2px;
}

/* One column, where there used to be three.

   They were already of unequal width — 1.5fr / 1fr / 1fr — because their
   contents were of unequal length: the argument, a storage gauge, a
   publisher credit. The last two are gone (see the markup: a measurement
   that comes to zero for almost everybody, and a publisher named twice on
   the same plate), and a grid of three tracks for one single child is no
   longer a grid.

   What remains is the reading measure, which is the real subject: a
   paragraph has no right to run across eleven hundred and eighty pixels.
   `62ch` holds it to the line length of a book, whatever the width of the
   window — and that is what replaces, in one declaration, the 1.5fr track
   and its fallback at 760 px. */
.colophon-grid {
  max-width: 1180px;
  margin-inline: auto;
}
.col { min-width: 0; max-width: 62ch; }
.col-tag {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-end: var(--space-3);
  color: var(--text-inverse);
}
.col-tag .ls-star { --form-size: 0.75em; color: var(--ls-ember-500); }
[data-theme="dark"] .col-tag .ls-star { color: var(--ls-ember-600); }
/* The assertion, at the head of the wide column. It is short and it is
   all anybody is asked to read: the paragraph below is there for whoever
   wants to check. */
.col-claim {
  margin-block-end: var(--space-2);
  font-family: var(--font-serif);
  font-size: var(--text-xl);
  line-height: var(--leading-snug);
  color: var(--text-inverse);
}
.col-body {
  font-family: var(--font-serif);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
  color: var(--text-secondary);
}
/* The storage gauge is gone, and its six rules with it: there is only one
   block left in this footer, and it needs neither a fixed-width figure
   nor a fill bar. */

/* The colophon line: the edition facts on one side, the plate on the
   other, on one single baseline. The plate was the last object of the
   third column, where it made an otherwise empty column overflow; here it
   closes the page, which is what a footer link has always done. */
/* The legal link is filed UP AGAINST the edition line, of which it is the
   natural continuation, and not in the middle of the band. The two form
   one block, which gives the colophon line back its two children and its
   symmetry: the product at one edge, its publisher at the other. */
.colophon-house {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(12px, 1.6vw, 24px);
  min-width: 0;
  /* Against the START edge, including when the band wraps — and the reason
     is that it wraps nearly always. This margin used to be
     `margin-inline-start: auto`, on the argument that two blocks aligned on
     the same side would cost the line both of its edges. Measured at 1400,
     the argument does not hold: the edition line runs 110→983 and the group
     549→1290, which is to say they are already on separate rows. The auto
     margin was not balancing a line, it was pushing a wrapped row 439px to
     the right, leaving the publisher's name adrift under a left-aligned
     colophon. Two blocks on two rows want the same edge, not opposite ones. */
  margin-inline-end: auto;
}
/* --text is the one token this plate deliberately does not restate, and
   hovering to it painted the link in the exact colour of the ground behind
   it — rgb(22,19,14) on rgb(22,19,14) in the light theme, and the mirror of
   that in the dark one. Contrast 1.00:1, in both: the words did not become
   hard to read, they stopped existing. Same accent as the links beside it,
   for the same reason. */
.colophon-legal { color: var(--text-muted); }
.colophon-legal:hover { color: var(--link-hover); }

.colophon-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(16px, 2vw, 32px);
  max-width: 1180px;
  margin: clamp(28px, 4vh, 52px) auto 0;
  padding-block-start: var(--space-5);
  border-block-start: var(--rule) solid var(--line);
}

/* `.plate` has been removed. It was the footer's telegram plate, and it
   had already left the markup when captainfork.com's signature replaced
   it; its twenty lines stayed behind, styling a selector that nothing
   carried any more. Dead CSS is CSS that gets resurrected by accident. */

/* The studio's recipe again: paper at 55% rather than a pre-mixed muted
   token. Measured, astralaika's footnote lands on rgb(144,139,128) and this
   line landed on rgb(154,144,121) — warmer and drier. The mechanism matters
   as much as the value: a translucent ink stays right if the plate changes. */
.telemetry {
  color: var(--ls-sand-50, #f3ede0);
  opacity: 0.55;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}
/* Square, and it is rule number one of this file — whose header has
   asserted from the start that it does not contain the string
   "border-radius" a single time, which was wrong by one occurrence. Three
   pixels of solid ink separate two facts; a three-pixel round was the
   only roundness on the page, and an identity that suffers one exception
   is no longer one. */
/* No opacity of its own any more. `.telemetry` now carries 0.55, and an
   opacity on a child MULTIPLIES with its parent's: 0.6 became 0.33, and
   three-pixel dots at a third of an alpha are not a separator, they are
   a rumour. The dot inherits the line's own translucency and stops
   adding its own. */
.telemetry-dot {
  width: 3px;
  height: 3px;
  background: currentColor;
}

/* ═══════════════════════════════════════════════════════════════
   NARROW — one column, and the sentence comes back into the row

   Not a smaller version of the wide layout: a different arrangement of
   the same parts. There is no pointer on a phone, so there is no readout
   to fill; the sentence therefore belongs in the entry, where it can be
   read without one. The leader goes, because it has no void left to
   cross.
   ═══════════════════════════════════════════════════════════════ */
@media (max-width: 899px) {
  .spread { grid-template-columns: minmax(0, 1fr); }

  .poster {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;
    gap: var(--space-4);
  }
  /* No pointer, so no readout: the sentence moves into the entry instead,
     where it can be read without one. */
  .readout { display: none; }

  .register {
    grid-template-rows: repeat(var(--rows, 14), auto);
  }
  .entry {
    grid-template-areas:
      "no mark name go"
      "no mark line line";
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    row-gap: 3px;
    padding-block: clamp(9px, 1.4vh, 14px);
  }
  .entry-lead { display: none; }
  .entry-line { display: block; }
  .entry-name { white-space: normal; }
}

/* The bar's two switch points are astralaika.com's: the navigation goes
   at 1100, the plate at 780. Here the two links do not vanish into the
   void — the selector is the next row and the colophon is the end of the
   page, both within scrolling reach. A full-screen menu for two entries
   would be a chest of drawers for two socks. */
@media (max-width: 1100px) {
  .bar-nav { display: none; }
  #langBox { margin-inline-start: auto; }
}
@media (max-width: 780px) {
  .bar-cta { display: none; }
}
@media (max-width: 599px) {
  .knob { padding: 6px 8px; }
}

/* ═══════════════════════════════════════════════════════════════
   REDUCED MOTION
   The durations already collapse to 1 ms in tokens.css. What is left to
   say is that the leaders are *there*, not drawn: launcher.js reads the
   same query and does not schedule the entrance at all.
   ═══════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  .entry-lead,
  .entry-go,
  .entry-no,
  .entry::before { transition-duration: 1ms; }
}

/* ═══════════════════════════════════════════════════════════════
   FORCED COLOURS
   The glass, the red bulletin and the ink colophon are all decorative
   substrates; the OS palette replaces them and the construction has to
   survive that. What must not survive is a hairline drawn in a colour the
   system has just repainted.
   ═══════════════════════════════════════════════════════════════ */
@media (forced-colors: active) {
  .register { border-color: CanvasText; box-shadow: none; }
  .bulletin, .colophon { forced-color-adjust: none; }
  .entry-lead { background-image: none; border-block-start: 1px solid CanvasText; }
  /* The number plate and the red edge collapse into system flats: they
     would otherwise stay painted red over an imposed palette. */
  .entry:hover .entry-no,
  .entry:focus-visible .entry-no { color: Canvas; background: Highlight; }
  .entry::before { background: Highlight; }
}

/* ═══════════════════════════════════════════════════════════════
   PRINT — the index is the one thing worth printing
   ═══════════════════════════════════════════════════════════════ */
@media print {
  #langBox, .bar-cta, .bar-nav, .colophon { display: none; }
  /* A fixed bar prints on every sheet. It goes back to being a header,
     once, at the top of the first one. */
  .bar { position: static; }
  .sheet { min-height: 0; padding-block-start: 0; }
  .register { background: none; box-shadow: none; backdrop-filter: none; }
  .spread { grid-template-columns: minmax(0, 1fr); }
}

/* The language button, taken over from astralaika.com.
   A two-pixel rectangle of ink that inverts on hover: the company's site
   makes it its only visible control, and the suite IS the site. It
   carries "FR ▾" — the short code says which language you are in, which a
   globe does not. */

/* The publisher's signature, on captainfork.com's model.
   Discreet by construction: the mark at twenty pixels, one line in a
   muted tint, and nothing that claims the eye before the product does. It
   lightens on hover, which is enough to say that it is clickable. */
.signature {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--text-muted);
  font-size: var(--text-xs);
  text-decoration: none;
  transition: color 200ms var(--ease-out);
}
.signature img { display: block; flex: none; }
.signature:hover { color: var(--text-inverse); text-decoration: none; }

/* The footer links carry the departure diagonal, like the selector's
   rows: each of these fourteen names leads to a subdomain, and without
   that sign they read as anchors within the current page. It is more
   discreet than in the full list — a footer announces, it does not
   insist — and it does not flip in a right-to-left script, a rising
   diagonal saying "elsewhere" and not "to the right". */
.colophon-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.colophon-link__go {
  display: inline-flex;
  --form-size: 0.72em;
  opacity: 0.55;
  transition: opacity var(--duration-fast) var(--ease-out);
}
.colophon-link:hover .colophon-link__go,
.colophon-link:focus-visible .colophon-link__go { opacity: 1; }

/* ── The legal group in the colophon ──────────────────────────────
   Five entries where there was one, on a line that already carries the
   signature. They wrap as a block rather than one by one, so the group
   never breaks in a way that leaves a single orphan link beside the
   publisher's name. */
.colophon-legal-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  align-items: center;
}

/* ── The menu panel, on the site surfaces ─────────────────────────
   components.css gives .ls-menu a glass fill, a heavy backdrop blur and a
   soft shadow — and a comment claiming it follows astralaika.com's
   .lang-menu. It does not. The studio's menu is a SOLID card, two pixels
   of ink, and a hard six-pixel offset square with no blur anywhere. The
   comment described an intention the code had drifted away from.

   Corrected here rather than in components.css because that sheet is the
   fourteen applications' as well, and glass is their language: a menu
   floating over a document wants to show the document. The hub and the
   legal pages are not documents — they are the studio's pages, and they
   should look it. */
.ls-menu {
  background: var(--surface);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: var(--rule-strong, 2px) solid var(--ink-solid);
  box-shadow: 6px 6px 0 color-mix(in srgb, var(--ink-solid) 16%, transparent);
}
.ls-menu__item[aria-checked="true"] { color: var(--brand-red); }


/* ── The language picker, shared ──────────────────────────────────
   Loaded by the hub AND by the legal pages, which is the point: the two
   language menus on this site used to be different objects — the house
   menu component here, a hand-written copy of the studio's control there
   — and they looked it. One component now, one sheet, one design.
   packages/ui/lang-picker.js builds it. */
.ls-langpicker { position: relative; }
/* astralaika.com's dropdown, ported. The <select> that stood here was the
   platform's, which meant it was the platform's everywhere: a rounded grey
   pill on one machine, a blue-tinted one on another, and on none of them
   anything this house would have drawn. Two pixels of ink, a hard six-pixel
   shadow, and the current choice in red with a star — the same object the
   studio uses, resolved through this suite's tokens so it inverts with the
   theme, which the studio's never has to. */

.ls-langpicker__current {
  font: inherit;
  font-family: var(--font-mono, monospace);
  font-size: 12px;
  letter-spacing: 0.08em;
  padding: 7px 12px;
  color: var(--text);
  background: var(--surface);
  border: var(--rule-strong, 2px) solid var(--ink-solid);
  cursor: pointer;
  transition: background 150ms, color 150ms;
}
.ls-langpicker__current:hover,
.ls-langpicker.is-open .ls-langpicker__current {
  background: var(--ink-solid);
  color: var(--text-inverse);
}
.ls-langpicker__menu {
  position: absolute;
  top: calc(100% + 8px);
  inset-inline-end: 0;
  z-index: 40;
  min-width: 200px;
  max-height: min(62vh, 460px);
  overflow-y: auto;
  background: var(--surface);
  border: var(--rule-strong, 2px) solid var(--ink-solid);
  box-shadow: 6px 6px 0 color-mix(in srgb, var(--ink-solid) 16%, transparent);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out), visibility 180ms;
}
.ls-langpicker.is-open .ls-langpicker__menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.ls-langpicker__menu button {
  display: block;
  width: 100%;
  text-align: start;
  font: inherit;
  font-family: var(--font-mono, monospace);
  font-size: 12px;
  letter-spacing: 0.08em;
  padding: 10px 14px;
  color: var(--text);
  background: none;
  border: 0;
  border-block-end: var(--rule) solid var(--line);
  cursor: pointer;
  transition: background 120ms;
}
.ls-langpicker__menu button:last-child { border-block-end: 0; }
.ls-langpicker__menu button:hover { background: var(--surface-sunken, transparent); }
.ls-langpicker__menu button[aria-selected="true"] { color: var(--brand-red); }
.ls-langpicker__menu button[aria-selected="true"]::before { content: "★ "; }
