/* ==========================================================================
   BONDEE — DUAL READ
   One DOM, two renderings. The machine layer is a stylesheet, not a second
   copy of the content — that constraint is what keeps it honest.
   ========================================================================== */

/* --------------------------------------------------------------------------
   ANNOTATIONS
   Authored inline next to the content they describe, aria-hidden (they restate
   structure a screen reader already has from the real semantics), and inert
   until machine mode. No layout cost while hidden: absolute + zero opacity.
   -------------------------------------------------------------------------- */
.anno {
  position: absolute;
  left: 0;
  top: -1.5rem;
  font-family: var(--f-label);
  font-weight: 300;
  font-size: var(--t-micro);
  line-height: var(--t-micro-lh);
  letter-spacing: var(--t-micro-ls);
  text-transform: uppercase;
  color: var(--c-anno);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  translate: 0 0.4rem;
}

.anno--right { left: auto; right: 0; }
.anno--below { top: auto; bottom: -1.35rem; }

html[data-read-mode="machine"] .anno { pointer-events: auto; }

/* Confidence ladder — the model's certainty, expressed as opacity, never as a
   second hue. Keeps the machine layer monochromatically indigo. */
.anno[data-conf="high"]   { --anno-a: 1; }
.anno[data-conf="mid"]    { --anno-a: 0.64; }
.anno[data-conf="low"]    { --anno-a: 0.36; }
.anno                     { --anno-a: 0.82; }

/* --------------------------------------------------------------------------
   BLOCK BOUNDS — every semantic block declares itself in machine mode
   -------------------------------------------------------------------------- */
[data-anno] { position: relative; }

[data-anno]::after {
  content: "";
  position: absolute;
  inset: -0.75rem -1rem;
  border: 1px solid var(--c-machine-rule);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-ui) var(--e-soft);
}

html[data-read-mode="machine"] [data-anno]::after { opacity: 1; }

/* Corner ticks read as a bounding box rather than a card. */
html[data-read-mode="machine"] [data-anno]::before {
  content: "";
  position: absolute;
  inset: -0.75rem -1rem;
  pointer-events: none;
  background:
    linear-gradient(var(--c-anno), var(--c-anno)) left  top    / 8px 1px no-repeat,
    linear-gradient(var(--c-anno), var(--c-anno)) left  top    / 1px 8px no-repeat,
    linear-gradient(var(--c-anno), var(--c-anno)) right bottom / 8px 1px no-repeat,
    linear-gradient(var(--c-anno), var(--c-anno)) right bottom / 1px 8px no-repeat;
  opacity: 0.55;
}

/* --------------------------------------------------------------------------
   MACHINE VOICE
   Layout is preserved; the voice changes. Display type holds its position and
   scale so Flip has something stable to animate, while prose switches to mono
   and the serif accent hardens into a bracketed token.
   -------------------------------------------------------------------------- */
html[data-read-mode="machine"] .lead,
html[data-read-mode="machine"] .body,
html[data-read-mode="machine"] p {
  font-family: var(--f-mono);
  font-weight: 300;
  letter-spacing: -0.01em;
}

html[data-read-mode="machine"] .accent {
  font-family: var(--f-label);
  font-style: normal;
  font-weight: 300;
  font-size: 0.52em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  vertical-align: 0.28em;
  color: var(--c-anno);
}
html[data-read-mode="machine"] .accent::before { content: "["; opacity: 0.5; }
html[data-read-mode="machine"] .accent::after  { content: "]"; opacity: 0.5; }

/* Redaction blocks resolve into their alt text, not their image. */
html[data-read-mode="machine"] .redact__mark { opacity: 0; }
html[data-read-mode="machine"] .redact__alt { opacity: 1; }

/* --------------------------------------------------------------------------
   OUTLINE TREE — the rail resolves into the document outline
   -------------------------------------------------------------------------- */
/* JetBrains rather than Martian Mono here: Martian is too wide to fit a slug
   inside a 72px rail without dropping under the 10px floor. */
.rail__tree {
  display: none;
  flex-direction: column;
  gap: 0.5rem;
  width: 100%;
  margin-top: 0.5rem;
  padding-inline: 0.375rem;
  font-family: var(--f-mono);
  font-weight: 300;
  font-size: var(--t-micro);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--c-anno);
}
html[data-read-mode="machine"] .rail__tree { display: flex; }
html[data-read-mode="machine"] .rail__slug { display: none; }
.rail__tree li { opacity: 0.5; }
.rail__tree li[data-current="true"] { opacity: 1; }

/* --------------------------------------------------------------------------
   THE LEGIBILITY LENS
   A circular window onto the machine layer. CSS mask + pointer tracking — no
   WebGL, no second scroll context, no LCP cost.
   -------------------------------------------------------------------------- */
.lens {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--d-ui) var(--e-soft);

  /* Mask centre, in px, written once per frame by the lens ticker. Declared in
     px (not %) so the JS never fights a unit change mid-animation. */
  --lx: 0px;
  --ly: 0px;
  -webkit-mask-image: radial-gradient(circle var(--lens-r) at var(--lx) var(--ly), #000 62%, transparent 100%);
          mask-image: radial-gradient(circle var(--lens-r) at var(--lx) var(--ly), #000 62%, transparent 100%);
}

.lens[data-active="true"] { opacity: 1; }

.lens__fill {
  position: absolute;
  inset: 0;
  background: var(--c-machine-bg);
}

/* Duplicate of the headline, aria-hidden. This is a rendering of content that
   already exists above it — the one place duplication is warranted, because
   the effect is "the same words, read differently". Typography is identical to
   .d1 so tokens land exactly over the words beneath. */
.lens__type {
  position: absolute;
  inset: 0;
  padding: inherit;
}

.tok {
  position: relative;
  display: inline-block;
  font-family: var(--f-display);
  font-weight: 500;
  color: var(--c-machine-fg);
  outline: 1px solid color-mix(in srgb, var(--c-anno) 45%, transparent);
  outline-offset: 0.06em;
  background: color-mix(in srgb, var(--c-anno) 8%, transparent);
}

.tok__meta {
  position: absolute;
  left: 0;
  bottom: calc(100% + 0.1em);
  font-family: var(--f-label);
  font-weight: 300;
  font-size: var(--t-micro); /* 10px is the floor and it applies here too */
  letter-spacing: 0.06em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--c-anno);
  white-space: nowrap;
}

/* The ring — the physical edge of the lens. Sits above the mask, unmasked. */
.lens-ring {
  position: absolute;
  z-index: 4;
  top: 0; left: 0;
  width: calc(var(--lens-r) * 2);
  height: calc(var(--lens-r) * 2);
  margin: calc(var(--lens-r) * -1) 0 0 calc(var(--lens-r) * -1);
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--c-anno) 70%, transparent);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--d-ui) var(--e-soft);
  will-change: transform;
}
.lens-ring[data-active="true"] { opacity: 1; }

.lens-ring__cap {
  position: absolute;
  bottom: -1.75rem;
  left: 50%;
  translate: -50% 0;
  font-family: var(--f-label);
  font-size: var(--t-micro);
  letter-spacing: var(--t-micro-ls);
  text-transform: uppercase;
  color: var(--c-anno);
  white-space: nowrap;
}

/* The lens is a way *into* machine mode. Once you are already there it has
   nothing left to reveal, so it stands down. */
html[data-read-mode="machine"] .lens,
html[data-read-mode="machine"] .lens-ring { display: none; }

/* 180px is a third of a phone's width — it stops reading as a lens and starts
   reading as a wipe. 88px keeps the ring fully inside the frame at both ends of
   the scroll sweep (see sweepTo: inset === r), so it never looks clipped. */
@media (max-width: 899px) {
  :root { --lens-r: 88px; }
  .lens-ring__cap { bottom: -1.4rem; font-size: var(--t-micro); }
}

/* Keep the serif accent's exact metrics inside the lens: the token boxes are
   measured from the real words, and a width change here would desync them.
   Specificity has to beat html[data-read-mode="machine"] .accent. */
html .lens .accent {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-size: 1.08em;
  letter-spacing: -0.01em;
  vertical-align: baseline;
  color: var(--c-machine-fg);
}
html .lens .accent::before,
html .lens .accent::after { content: none; }

@media (prefers-reduced-motion: reduce) {
  .lens, .lens-ring { transition: none; }
}
