/* ==========================================================================
   LoveLink — layout, rhythm and components
   --------------------------------------------------------------------------
   Two things govern the spacing in this file, and they are the whole reason a
   page here reads as considered rather than assembled:

     1. Sections never set their own padding. A page composes .ll-section and
        .ll-band, and the rhythm in tokens.css holds it consistent.
     2. Gaps come from the flow scale, not from ad-hoc margins. A stack sets
        one gap; the heading-to-body gap is deliberately tighter than
        body-to-body, because a heading belongs to the paragraph under it.

   Carbon's rules are Carbon's and are not negotiable by taste: a 2px grid, a
   real focus ring rather than outline:none, square corners, and 40px controls.

   The one thing Carbon does not supply is the moon, so the moon is drawn.
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--ll-gap-xl);
}

body {
  margin: 0;
  font: var(--cds-type-body-02);
  letter-spacing: var(--cds-type-tracking);
  color: var(--cds-text-primary);
  background: var(--cds-background);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* WebView: never let content hide under a notch or a home indicator. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}

img, svg { max-width: 100%; display: block; }
a { color: var(--cds-link-primary); text-decoration: none; }
a:hover { color: var(--cds-link-primary-hover); text-decoration: underline; }

:focus-visible { outline: 2px solid var(--cds-focus); outline-offset: -2px; }
.ll-band--night :focus-visible { outline-color: var(--ll-moon); }

::selection { background: var(--ll-moon); color: #161616; }

/* ==========================================================================
   1. Layout
   ========================================================================== */

.ll-wrap {
  width: 100%;
  max-width: var(--ll-wrap);
  margin-inline: auto;
  padding-inline: var(--ll-gutter);
}
.ll-wrap--read { max-width: calc(var(--ll-measure-wide) + var(--ll-gutter) * 2); }

/* The vertical rhythm. A section is one idea, and every one of them is spaced
   by the same rule. */
.ll-section { padding-block: var(--ll-y-section); }
.ll-section--tight { padding-block: var(--ll-y-tight); }
.ll-section--flush-top { padding-block-start: 0; }
.ll-section--flush-bottom { padding-block-end: 0; }

/* A full-bleed band. The colour change is the only decoration a band gets. */
.ll-band { position: relative; }
.ll-band--soft {
  background: var(--cds-layer-01);
  /* Re-declared so a soft band sits on its own surface rather than inheriting a
     neighbour's — tiles and inputs inside it step up one layer as Carbon expects. */
  --cds-layer-02: var(--cds-background);
  --cds-field-01: var(--cds-background);
  --cds-layer-hover-01: var(--cds-background-hover);
}

/* The inverse band.
   ------------------------------------------------------------------------
   A night sky should look like a night sky in both themes, so this is not
   "the current theme's background" — it is Carbon's Gray 100, scoped locally
   by re-declaring the tokens on the element. Everything inside it therefore
   reads as though it were in a dark theme, and composes identically to the
   rest of the page: same classes, same rhythm, same measurements.

   This is Carbon's own idea of an inverse surface. The alternative — bands
   that lighten with the Dawn theme — would have meant the moon sitting in a
   white sky, which is nobody's moon. */
.ll-band--night {
  background: #161616;
  color: #f4f4f4;

  --cds-background: #161616;
  --cds-layer-01: #262626;
  --cds-layer-02: #393939;
  --cds-layer-hover-01: #333333;
  --cds-field-01: #262626;
  --cds-border-subtle-01: #393939;
  --cds-border-strong-01: #6f6f6f;
  --cds-text-primary: #f4f4f4;
  --cds-text-secondary: #c6c6c6;
  --cds-text-helper: #8d8d8d;
  --cds-text-placeholder: #6f6f6f;
  --cds-focus: #ffffff;
  --cds-link-primary: #78a9ff;
  --cds-link-primary-hover: #a6c8ff;
  --cds-skeleton-background: #292929;
  --cds-skeleton-element: #393939;

  /* The moon, lifted for a dark field. */
  --ll-moon: #f0c674;
  --ll-moon-soft: rgba(240, 198, 116, 0.16);
  --ll-moon-line: rgba(240, 198, 116, 0.5);
}

/* A hairline between two bands of the same colour, so the seam is deliberate. */
.ll-seam { border-block-start: 1px solid var(--cds-border-subtle-01); }

/* Flow: one gap for a stack, inherited by everything inside it. */
.ll-flow > * + * { margin-block-start: var(--flow, var(--ll-gap-md)); }
.ll-flow--tight { --flow: var(--ll-gap-sm); }
.ll-flow--loose { --flow: var(--ll-gap-lg); }
.ll-flow--airy { --flow: var(--ll-gap-xl); }

/* A heading belongs to the text beneath it, so it sits closer to it than the
   paragraph above does. This single rule is most of what makes prose look
   set rather than piled. */
.ll-flow > h1 + *,
.ll-flow > h2 + *,
.ll-flow > h3 + * { margin-block-start: var(--ll-gap-sm); }
.ll-flow > * + h2,
.ll-flow > * + h3 { margin-block-start: var(--ll-gap-lg); }

.ll-grid {
  display: grid;
  gap: var(--grid-gap, var(--ll-gap-md));
  grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min, 17rem), 100%), 1fr));
}
.ll-grid--2 { --grid-min: 19rem; }
.ll-grid--3 { --grid-min: 15rem; }
.ll-grid--wide-gap { --grid-gap: var(--ll-gap-lg); }
.ll-grid--airy-gap { --grid-gap: var(--ll-gap-xl); }

.ll-split {
  display: grid;
  gap: var(--ll-gap-xl);
  align-items: center;
}
@media (min-width: 62rem) {
  .ll-split { grid-template-columns: 1fr 1fr; gap: var(--ll-gap-2xl); }
  .ll-split--moon-first { grid-template-columns: 1fr 1.15fr; }
}
.ll-center { text-align: center; }
.ll-center .ll-flow { margin-inline: auto; }

/* ==========================================================================
   2. Type
   ========================================================================== */

.ll-eyebrow {
  font: var(--cds-type-label-01);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cds-text-helper);
  margin: 0;
}
.ll-band--night .ll-eyebrow { color: var(--ll-moon); }

/* A display line can carry an unbreakable run: a handle page prints
   `lovelink.to/<handle>`, and a handle may be 24 characters. With no break
   opportunity that one token sets the containing grid track's min-content width,
   so the whole column — moon, tile, footer and all — is stretched to fit it, and
   the page scrolls sideways on a phone. `anywhere` and not `break-word`: only
   `anywhere` also shrinks min-content, which is the part the layout needs. It
   engages only when a word genuinely cannot fit. */
.ll-display {
  font: var(--cds-type-display-02);
  letter-spacing: -0.015em;
  margin: 0;
  overflow-wrap: anywhere;
}
.ll-display--xl { font: var(--cds-type-display-03); letter-spacing: -0.02em; }
@media (max-width: 41.99rem) {
  .ll-display { font: var(--cds-type-heading-06); }
  .ll-display--xl { font: 300 2.75rem/1.12 var(--cds-font-sans); }
}

.ll-h1 { font: var(--cds-type-heading-05); letter-spacing: -0.005em; margin: 0; }
.ll-h2 { font: var(--cds-type-heading-04); letter-spacing: -0.005em; margin: 0; }
.ll-h3 { font: var(--cds-type-heading-03); margin: 0; }

.ll-lede {
  font: var(--cds-type-heading-03);
  color: var(--cds-text-secondary);
  max-width: var(--ll-measure-wide);
  margin: 0;
}
.ll-body { max-width: var(--ll-measure); }
.ll-helper-text { font: var(--cds-type-helper-01); color: var(--cds-text-helper); margin: 0; }
.ll-muted { color: var(--cds-text-secondary); }
.ll-mono { font: var(--cds-type-code-02); letter-spacing: 0.02em; }

/* A statement — one sentence given the room to land. */
.ll-statement {
  font: var(--cds-type-heading-05);
  letter-spacing: -0.01em;
  max-width: 30ch;
  margin: 0;
}
@media (max-width: 41.99rem) { .ll-statement { font: var(--cds-type-heading-04); } }

.ll-rule { border: 0; border-block-start: 1px solid var(--cds-border-subtle-01); margin: 0; }

.ll-list { margin: 0; padding-inline-start: 1.15rem; max-width: var(--ll-measure); }
.ll-list li + li { margin-block-start: var(--ll-gap-xs); }
.ll-list--plain { list-style: none; padding-inline-start: 0; }

/* Numbered, for the laws. */
.ll-list--ruled { list-style: none; padding: 0; }
.ll-list--ruled li {
  display: grid;
  grid-template-columns: 2.25rem 1fr;
  gap: var(--ll-gap-sm);
  padding-block: var(--ll-gap-md);
  border-block-start: 1px solid var(--cds-border-subtle-01);
}
.ll-list--ruled li:last-child { border-block-end: 1px solid var(--cds-border-subtle-01); }
.ll-list--ruled li::before {
  content: counter(law, decimal-leading-zero);
}
.ll-list--ruled { counter-reset: law; }
.ll-list--ruled li::before { counter-increment: law; }
.ll-list--ruled li::before {
  font: var(--cds-type-label-02);
  color: var(--ll-moon);
  padding-block-start: 0.15rem;
}

/* ==========================================================================
   3. Header and footer
   ========================================================================== */

.ll-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--cds-background) 92%, transparent);
  backdrop-filter: blur(12px);
  border-block-end: 1px solid var(--cds-border-subtle-01);
}
.ll-header__inner {
  display: flex;
  align-items: flex-start;
  gap: var(--ll-gap-md);
  min-height: 4.25rem;
  padding-block: var(--ll-gap-xs);
}

/* The wordmark and its attribution, stacked — which mirrors the way the nav
   stacks on the other side, so the header reads as two columns rather than
   four things floating in a row.

   align-items: flex-start on the row above is what puts the logo level with the
   button. Centred as a block, the two brand lines straddle the nav's first row
   and the wordmark lands low; anchored to the top and given the button's own
   height, the two centres coincide exactly — which is what the eye reads as
   "aligned", and it holds whichever control happens to be at the top of the
   nav. */
.ll-brand-block { display: flex; flex-direction: column; gap: 0.4rem; }

.ll-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  min-height: 2.25rem;           /* the height of a .ll-btn--sm */
  font: 600 1.0625rem/1 var(--cds-font-sans);
  color: var(--cds-text-primary);
  white-space: nowrap;
}
.ll-brand:hover { text-decoration: none; color: var(--cds-text-primary); }
.ll-brand__tm {
  align-self: flex-start;
  margin-block-start: 0.3em;
  font: var(--cds-type-label-01);
  color: var(--cds-text-helper);
}
.ll-brand__by {
  font: var(--cds-type-label-01);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cds-text-helper);
  white-space: nowrap;
}

/* The nav: the primary action on top, the small controls beneath it, the whole
   stack right-aligned. Leading with the button is the point — the theme and the
   way in are secondary, and stacking them also costs less width than a row did,
   which is what used to overflow a narrow phone. */
.ll-header__nav {
  margin-inline-start: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.4rem;
}
.ll-header__meta {
  display: flex;
  align-items: center;
  gap: var(--ll-gap-sm);
  font: var(--cds-type-label-02);
}
/* :not(.ll-btn) is load-bearing. `.ll-header__meta a` outranks `.ll-btn--primary`
   on specificity, so without the exclusion the nav repaints a button's label in
   the secondary grey — white-on-blue becomes grey-on-blue, which measures 1.56:1
   and is unreadable. The same trap catches the footer. */
.ll-header__meta a { color: var(--cds-text-secondary); }
.ll-header__meta a:not(.ll-btn):hover { color: var(--cds-text-primary); text-decoration: none; }

.ll-footer {
  border-block-start: 1px solid var(--cds-border-subtle-01);
  padding-block: var(--ll-y-tight) var(--ll-gap-xl);
  font: var(--cds-type-body-01);
  color: var(--cds-text-helper);
}
.ll-footer a:not(.ll-btn) { color: var(--cds-text-secondary); }
.ll-footer__links { display: flex; flex-wrap: wrap; gap: var(--ll-gap-sm) var(--ll-gap-md); }
.ll-footer__legal { max-width: var(--ll-measure-wide); }

/* ==========================================================================
   4. Carbon: button
   ========================================================================== */

.ll-btn {
  font: var(--cds-type-body-01);
  letter-spacing: var(--cds-type-tracking);
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ll-gap-md);
  min-height: 3rem;
  padding-inline: var(--ll-gap-md);
  border: 1px solid transparent;
  border-radius: 0;
  cursor: pointer;
  text-decoration: none;
  transition: background var(--cds-duration-fast-02) var(--cds-ease-productive),
              border-color var(--cds-duration-fast-02) var(--cds-ease-productive),
              color var(--cds-duration-fast-02) var(--cds-ease-productive);
  width: 100%;
}
.ll-btn:hover { text-decoration: none; }
.ll-btn--auto { width: auto; }
.ll-btn--sm { min-height: 2.25rem; padding-inline: var(--ll-gap-sm); }
.ll-btn--lg { min-height: 3.5rem; padding-inline: var(--ll-gap-lg); font-size: 1rem; }

.ll-btn--primary { background: var(--cds-button-primary); color: var(--cds-text-on-color); }
.ll-btn--primary:hover { background: var(--cds-button-primary-hover); color: var(--cds-text-on-color); }
.ll-btn--primary:active { background: var(--cds-button-primary-active); }

.ll-btn--secondary { background: var(--cds-button-secondary); color: var(--cds-text-on-color); }
.ll-btn--secondary:hover { background: var(--cds-button-secondary-hover); color: var(--cds-text-on-color); }

.ll-btn--tertiary { background: transparent; color: var(--cds-button-tertiary); border-color: var(--cds-button-tertiary); }
.ll-btn--tertiary:hover { background: var(--cds-button-tertiary); color: var(--cds-text-on-color); }

/* On the night bands, a bordered button picks up the moon. */
.ll-band--night .ll-btn--tertiary { color: var(--ll-moon); border-color: var(--ll-moon-line); }
.ll-band--night .ll-btn--tertiary:hover { background: var(--ll-moon); color: #161616; }

.ll-btn--ghost { background: transparent; color: var(--cds-link-primary); padding-inline: 0; width: auto; }
.ll-btn--ghost:hover { color: var(--cds-link-primary-hover); text-decoration: underline; }
.ll-band--night .ll-btn--ghost { color: var(--ll-moon); }

.ll-btn--danger { background: var(--cds-button-danger-primary); color: var(--cds-text-on-color); }
.ll-btn--danger:hover { background: var(--cds-button-danger-hover); color: var(--cds-text-on-color); }

.ll-btn:disabled, .ll-btn[aria-disabled='true'] {
  background: var(--cds-button-disabled);
  color: var(--cds-text-helper);
  cursor: not-allowed;
  border-color: transparent;
}

.ll-actions { display: flex; flex-wrap: wrap; gap: var(--ll-gap-sm); align-items: center; }

/* ==========================================================================
   5. Carbon: forms
   ========================================================================== */

.ll-field { margin-block-end: var(--ll-gap-lg); }
.ll-label {
  display: block;
  font: var(--cds-type-label-02);
  letter-spacing: var(--cds-type-tracking);
  color: var(--cds-text-secondary);
  margin-block-end: var(--ll-gap-2xs);
}
.ll-input, .ll-textarea, .ll-select {
  width: 100%;
  font: var(--cds-type-body-02);
  letter-spacing: var(--cds-type-tracking);
  color: var(--cds-text-primary);
  background: var(--cds-field-01);
  border: 0;
  border-block-end: 1px solid var(--cds-border-strong-01);
  min-height: 2.75rem;
  padding: var(--ll-gap-sm) var(--ll-gap-md);
  transition: background var(--cds-duration-fast-02) var(--cds-ease-productive);
}
.ll-textarea { min-height: 13rem; resize: vertical; line-height: 1.65; }
.ll-input:hover, .ll-textarea:hover { background: var(--cds-layer-hover-01); }
.ll-input:focus, .ll-textarea:focus { outline: 2px solid var(--cds-focus); outline-offset: -2px; }
.ll-input::placeholder, .ll-textarea::placeholder { color: var(--cds-text-placeholder); }
.ll-input[aria-invalid='true'], .ll-textarea[aria-invalid='true'] {
  outline: 2px solid var(--cds-support-error);
  outline-offset: -2px;
}
.ll-helper { font: var(--cds-type-helper-01); color: var(--cds-text-helper); margin-block-start: var(--ll-gap-2xs); }
.ll-error { font: var(--cds-type-helper-01); color: var(--cds-text-error); margin-block-start: var(--ll-gap-2xs); }

/* An input that shares a row with a button, so it needs a width of its own. */
.ll-handle-input { max-width: 18rem; }

/* A letter card, stacked in a list. */
.ll-letter-card { margin-block-end: var(--ll-gap-md); }
.ll-letter-card__foot {
  margin-block-start: var(--ll-gap-md);
  padding-block-start: var(--ll-gap-sm);
  border-block-start: 1px solid var(--cds-border-subtle-01);
}
.ll-letter-card__stamp { margin-block-end: var(--ll-gap-sm); }
.ll-empty {
  border: 1px dashed var(--cds-border-strong-01);
  background: var(--cds-layer-01);
  padding: var(--ll-gap-lg);
  text-align: center;
  color: var(--cds-text-secondary);
  font: var(--cds-type-body-01);
  max-width: var(--ll-measure-wide);
}

/* ==========================================================================
   6. Carbon: tiles, tags, notices, crumbs
   ========================================================================== */

.ll-tile {
  background: var(--cds-layer-01);
  padding: var(--ll-tile-pad);
  border: 1px solid transparent;
}
.ll-tile--outlined { background: var(--cds-layer-02); border-color: var(--cds-border-subtle-01); }
.ll-tile--raised { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06); }
.ll-tile--link { transition: background var(--cds-duration-fast-02) var(--cds-ease-productive); }
.ll-tile--link:hover { background: var(--cds-layer-hover-01); }

.ll-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font: var(--cds-type-label-01);
  letter-spacing: var(--cds-type-tracking);
  padding: var(--ll-gap-2xs) var(--ll-gap-sm);
  background: var(--cds-layer-02);
  border: 1px solid var(--cds-border-subtle-01);
  color: var(--cds-text-secondary);
  border-radius: 1.5rem;
  white-space: nowrap;
}
.ll-tag--moon { background: var(--ll-moon-soft); border-color: var(--ll-moon-line); color: var(--cds-text-primary); }
.ll-tag--success { background: var(--cds-support-success); border-color: transparent; color: #fff; }
.ll-tag--info { background: var(--cds-support-info); border-color: transparent; color: #fff; }
.ll-tag--error { background: var(--cds-support-error); border-color: transparent; color: #fff; }

.ll-notice {
  display: flex;
  gap: var(--ll-gap-md);
  padding: var(--ll-gap-md) var(--ll-gap-md) var(--ll-gap-md) var(--ll-gap-lg);
  border-inline-start: 3px solid var(--cds-support-info);
  background: var(--cds-layer-01);
  margin-block-end: var(--ll-gap-lg);
  font: var(--cds-type-body-01);
}
.ll-notice--error { border-inline-start-color: var(--cds-support-error); }
.ll-notice--success { border-inline-start-color: var(--cds-support-success); }
.ll-notice--warning { border-inline-start-color: var(--cds-support-warning); }
.ll-notice__title { font-weight: 600; margin-block-end: var(--ll-gap-2xs); }

.ll-crumbs { font: var(--cds-type-label-02); }
.ll-crumbs ul { display: flex; flex-wrap: wrap; gap: var(--ll-gap-sm); margin: 0; padding: 0; list-style: none; }
.ll-crumbs li { display: flex; gap: var(--ll-gap-sm); }
.ll-crumbs li + li::before { content: '/'; color: var(--cds-text-helper); }
.ll-crumbs a { color: var(--cds-text-secondary); }
.ll-crumbs [aria-current] { color: var(--cds-text-primary); }

/* ==========================================================================
   7. The moon
   --------------------------------------------------------------------------
   Drawn from the real phase, not an illustration. The disc takes the moon
   colour and the terminator is a path, so it is correct at every moment and
   in both themes. The halo is one hairline, which is as much decoration as
   the system allows itself.
   ========================================================================== */

.ll-disc { display: block; width: var(--disc-size, 5rem); height: var(--disc-size, 5rem); overflow: visible; }
.ll-disc__body { fill: var(--ll-moon); }
/* The unlit limb, faintly visible — earthshine, and enough to read the shape as a
   sphere rather than as a shape. */
.ll-disc__dark { fill: var(--ll-moon); opacity: 0.13; }
.ll-disc__ring { fill: none; stroke: var(--ll-moon-line); stroke-width: 1; }

.ll-moon-figure {
  display: grid;
  place-items: center;
  position: relative;
  padding: var(--ll-gap-lg);
}
/* A soft glow, and the only gradient in the system. */
.ll-moon-figure::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 50%, var(--ll-moon-soft) 0%, transparent 62%);
  pointer-events: none;
}
.ll-moon-figure > * { position: relative; }
.ll-moon-figure--hero { --disc-size: clamp(9rem, 26vw, 17rem); }

.ll-phase-caption { display: grid; gap: var(--ll-gap-2xs); text-align: center; }
.ll-phase-name { font: var(--cds-type-label-02); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ll-moon); }

/* ==========================================================================
   8. The hero
   ========================================================================== */

.ll-hero {
  position: relative;
  overflow: hidden;
  padding-block: var(--ll-y-hero);
}
/* Stars. Sparse, dim, and only here — the rest of the site is a document. */
.ll-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(1.2px 1.2px at 8% 22%, rgba(255, 255, 255, 0.55), transparent),
    radial-gradient(1px 1px at 21% 68%, rgba(255, 255, 255, 0.35), transparent),
    radial-gradient(1.4px 1.4px at 37% 12%, rgba(255, 255, 255, 0.5), transparent),
    radial-gradient(1px 1px at 52% 84%, rgba(255, 255, 255, 0.3), transparent),
    radial-gradient(1.1px 1.1px at 68% 31%, rgba(255, 255, 255, 0.45), transparent),
    radial-gradient(1px 1px at 79% 74%, rgba(255, 255, 255, 0.32), transparent),
    radial-gradient(1.3px 1.3px at 91% 19%, rgba(255, 255, 255, 0.48), transparent),
    radial-gradient(1px 1px at 14% 92%, rgba(255, 255, 255, 0.28), transparent);
}
.ll-hero > * { position: relative; }

/* The countdown: a receipt for the wait, set in the mono face so the numbers
   do not shuffle sideways as they tick. */
.ll-countdown {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ll-gap-md) var(--ll-gap-lg);
  align-items: baseline;
  font: var(--cds-type-code-02);
  color: var(--cds-text-secondary);
}
.ll-countdown__value {
  font: 500 1.125rem/1.2 var(--cds-font-mono);
  color: var(--ll-moon);
  font-variant-numeric: tabular-nums;
}
.ll-countdown__label {
  display: block;
  font: var(--cds-type-label-01);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cds-text-helper);
  margin-block-start: 0.3rem;
}

/* ==========================================================================
   9. The journey — LunaStamp Logistics
   ========================================================================== */

.ll-journey { list-style: none; margin: 0; padding: 0; counter-reset: stop; }
.ll-journey__stop {
  counter-increment: stop;
  display: grid;
  grid-template-columns: 2.75rem 1fr;
  gap: var(--ll-gap-md);
  padding-block-end: var(--ll-gap-lg);
  position: relative;
}
.ll-journey__stop:not(:last-child)::before {
  content: '';
  position: absolute;
  inset-inline-start: 1.3125rem;
  inset-block-start: 2.5rem;
  inset-block-end: 0;
  width: 1px;
  background: linear-gradient(var(--cds-border-subtle-01), transparent);
}
.ll-journey__marker {
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  border: 1px solid var(--cds-border-strong-01);
  background: var(--cds-background);
  font: var(--cds-type-label-01);
  color: var(--cds-text-helper);
}
.ll-journey__stop--done .ll-journey__marker {
  background: var(--ll-moon);
  border-color: var(--ll-moon);
  color: #161616;
}
.ll-journey__stop--now .ll-journey__marker {
  border-color: var(--ll-moon);
  color: var(--ll-moon);
  box-shadow: 0 0 0 4px var(--ll-moon-soft);
}
.ll-journey__title { font: var(--cds-type-heading-02); margin: 0; }
.ll-journey__note { font: var(--cds-type-body-01); color: var(--cds-text-secondary); margin: var(--ll-gap-2xs) 0 0; max-width: 34ch; }
.ll-journey__stop--next .ll-journey__title,
.ll-journey__stop--next .ll-journey__note { color: var(--cds-text-helper); }

/* The tracking strip on a live letter. */
.ll-track { list-style: none; margin: 0; padding: 0; }
.ll-track--wide { max-width: var(--ll-measure-wide); }
.ll-track__step { display: grid; grid-template-columns: 1.5rem 1fr; gap: var(--ll-gap-sm); padding-block-end: var(--ll-gap-md); position: relative; }
.ll-track__step:not(:last-child)::before {
  content: '';
  position: absolute;
  inset-inline-start: 0.6875rem;
  inset-block-start: 1.375rem;
  inset-block-end: 0;
  width: 1px;
  background: var(--cds-border-subtle-01);
}
.ll-track__dot {
  width: 1.375rem; height: 1.375rem;
  border-radius: 50%;
  border: 1px solid var(--cds-border-strong-01);
  background: var(--cds-background);
  display: grid; place-items: center;
  font: var(--cds-type-label-01);
  color: var(--cds-text-helper);
}
.ll-track__step--done .ll-track__dot { background: var(--ll-moon); border-color: var(--ll-moon); color: #161616; }
.ll-track__step--current .ll-track__dot { border-color: var(--ll-moon); color: var(--ll-moon); box-shadow: 0 0 0 3px var(--ll-moon-soft); }
.ll-track__label { font: var(--cds-type-label-02); }
.ll-track__step--pending .ll-track__label { color: var(--cds-text-helper); }
.ll-track__when { font: var(--cds-type-helper-01); color: var(--cds-text-helper); }

/* ==========================================================================
   10. The letter
   ========================================================================== */

.ll-letter {
  background: var(--cds-layer-02);
  border: 1px solid var(--cds-border-subtle-01);
  padding: clamp(1.75rem, 5vw, 3.5rem);
}
.ll-letter__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ll-gap-sm) var(--ll-gap-md);
  padding-block-end: var(--ll-gap-md);
  margin-block-end: var(--ll-gap-md);
  border-block-end: 1px solid var(--cds-border-subtle-01);
  font: var(--cds-type-label-01);
  color: var(--cds-text-helper);
}
.ll-letter__body {
  font: var(--cds-type-body-02);
  line-height: 1.85;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: var(--ll-measure);
}
.ll-sealed {
  border: 1px dashed var(--cds-border-strong-01);
  background: var(--cds-layer-01);
  padding: var(--ll-gap-lg);
  text-align: center;
  color: var(--cds-text-secondary);
  font: var(--cds-type-body-01);
}

/* The one-time recovery code. Given its own weight because losing it loses the letters. */
.ll-recovery {
  font-size: 1.0625rem;
  line-height: 1.6;
  letter-spacing: 0.08em;
  background: var(--cds-layer-01);
  border: 1px solid var(--cds-border-subtle-01);
  padding: var(--ll-gap-md);
  text-align: center;
  overflow-wrap: anywhere;
}

/* ==========================================================================
   11. Modal, skeleton
   ========================================================================== */

.ll-modal {
  border: 0;
  padding: 0;
  background: var(--cds-layer-02);
  color: var(--cds-text-primary);
  max-width: 40rem;
  width: calc(100% - 2rem);
  max-height: calc(100dvh - 3rem);
}
.ll-modal::backdrop { background: var(--cds-overlay); backdrop-filter: blur(2px); }
.ll-modal__inner { padding: clamp(1.5rem, 4vw, 2.75rem); }
.ll-modal h2 { margin-block-end: var(--ll-gap-sm); }

.ll-skeleton {
  background: var(--cds-skeleton-background);
  animation: ll-skeleton 3s ease-in-out infinite;
  height: 1rem;
}
.ll-skeleton + .ll-skeleton { margin-block-start: var(--ll-gap-sm); }
.ll-skeleton--title { height: 2.5rem; max-width: 26rem; }
.ll-skeleton--short { max-width: 16rem; }
@keyframes ll-skeleton {
  0%, 100% { background: var(--cds-skeleton-background); }
  50% { background: var(--cds-skeleton-element); }
}

/* ==========================================================================
   12. Utilities
   ========================================================================== */

.ll-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ll-gap-md); }
.ll-row--tight { gap: var(--ll-gap-sm); }
.ll-row--baseline { align-items: baseline; }
.ll-right { margin-inline-start: auto; }
.ll-hidden { display: none !important; }
.ll-nowrap { white-space: nowrap; }
.ll-pad-block { padding-block: var(--ll-gap-lg); }
.ll-divider { border: 0; border-block-start: 1px solid var(--cds-border-subtle-01); margin-block: var(--ll-gap-xl); }

/* A header has a fixed budget on a narrow screen. Below 42rem the brand block
   unfolds so the attribution can take a row of its own, which frees the width
   the button and the meta row need — and keeps "A service by Aerial Giant Inc."
   on screen at every size rather than hiding it, since that is the line the
   company is named in. The links that merely repeat the footer do step aside. */
@media (max-width: 41.99rem) {
  .ll-header__inner { flex-wrap: wrap; row-gap: 0.4rem; }
  .ll-brand-block { display: contents; }
  .ll-brand { order: 1; }
  .ll-header__nav { order: 2; }
  .ll-brand__by { order: 3; flex-basis: 100%; }

  .ll-header__meta { gap: var(--ll-gap-sm); }
  .ll-hide-sm { display: none !important; }
  .ll-brand__by { font-size: 0.625rem; letter-spacing: 0.07em; }
}

/* The nav is a column, so it must never be squeezed: at its narrowest the
   primary button would wrap mid-label rather than shrink. */
.ll-header__nav { flex: 0 0 auto; }
.ll-header__nav .ll-btn { white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
