/* ============================================================
   Saaph — ASCII decoration system
   Pairs with js/ascii-decor.js. Opt in per page; nothing here
   applies until a [data-decor] host or a .decor-* class exists.
   ============================================================ */

/* The canvas fills its host and can never be interacted with. Hosts are
   expected to be position:relative; the rule below enforces it rather than
   trusting every call site to remember. */
[data-decor] {
  position: absolute;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
}
.decor-canvas {
  display: block;
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* A section that hosts decoration has to establish a stacking context, or the
   canvas will ride over a sibling. isolation:isolate keeps it local — the same
   fix .section-header needed when #redacted-canvas started winning fights. */
.decor-host {
  position: relative;
  isolation: isolate;
}
.decor-host > *:not([data-decor]) {
  position: relative;
  z-index: 1;
}

/* ------------------------------------------------------------
   Edge bands — texture in the margin, never behind body copy.
   They deliberately bleed off the viewport so the page reads as
   a window onto something larger.
   ------------------------------------------------------------ */
.decor-left,
.decor-right {
  top: 0;
  bottom: 0;
  width: clamp(90px, 17vw, 260px);
  /* Fades toward the content column so there is no hard cut line. */
  -webkit-mask-image: linear-gradient(to right, #000 0%, #000 45%, transparent 100%);
          mask-image: linear-gradient(to right, #000 0%, #000 45%, transparent 100%);
}
.decor-left  { left: 0; }
.decor-right {
  right: 0;
  -webkit-mask-image: linear-gradient(to left, #000 0%, #000 45%, transparent 100%);
          mask-image: linear-gradient(to left, #000 0%, #000 45%, transparent 100%);
}

/* Below the content column there is no margin left to put anything in, so the
   bands come off rather than shrinking into an unreadable sliver. */
@media (max-width: 1080px) {
  .decor-left, .decor-right { display: none; }
}

/* ------------------------------------------------------------
   Corner tags — [ DPDP s.12 ] and friends.
   Firecrawl runs these at 12% black; the same weight works here
   because they are a watermark, not a label anyone must read.
   ------------------------------------------------------------ */
.decor-tags {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.decor-tag {
  position: absolute;
  font-family: var(--font-mono, 'JetBrains Mono', ui-monospace, monospace);
  font-size: 11px;
  letter-spacing: 0.08em;
  white-space: nowrap;
  color: var(--text-primary, #fff);
  opacity: 0.14;
  user-select: none;
}
.decor-tag--tl { top: 14px;    left: 16px; }
.decor-tag--tr { top: 14px;    right: 16px; }
.decor-tag--bl { bottom: 14px; left: 16px; }
.decor-tag--br { bottom: 14px; right: 16px; }
.decor-tag--accent { color: var(--color-primary, #FF6B00); opacity: 0.36; }

/* Same trap as data-decor-ink in the JS: a band that is dark in BOTH themes
   (.leak-band, #0B0E14) turns these tags black-on-black the moment a visitor
   switches to light, because --text-primary follows the theme and the band
   does not. Containers on such a band declare their ink instead of inheriting. */
.decor-tags[data-on-dark] .decor-tag { color: #FFFFFF; }
.decor-tags[data-on-dark] .decor-tag--accent { color: var(--color-primary, #FF6B00); }

@media (max-width: 720px) {
  /* At phone width the tags sit on top of real content. */
  .decor-tag { display: none; }
}

/* ------------------------------------------------------------
   The identity film — the one place the decoration is allowed
   to be the subject rather than the texture.
   ------------------------------------------------------------ */
.decor-film {
  position: relative;
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  /* 3:2, not 16:9. The face is drawn in rows and its width works out to about
     0.72x the box HEIGHT, so a wide-short box leaves it stranded in the middle
     of a lot of nothing. At 3:2 it fills roughly half the width and the tags
     take it to three quarters. */
  aspect-ratio: 3 / 2;
  isolation: isolate;
}
.decor-film [data-decor] {
  position: absolute;
  inset: 0;
  /* The mesh fades out at the edges by MASKING the canvas, not by painting a
     vignette over it. An overlay has to pick a colour, and any colour it picks
     is wrong the moment something sits behind it — the first attempt painted
     flat #0B0E14 across .leak-band::before's orange glow and stamped a visible
     dark rectangle onto the band. A mask has no colour to get wrong. */
  -webkit-mask-image: radial-gradient(ellipse 78% 76% at 50% 50%, #000 50%, transparent 100%);
          mask-image: radial-gradient(ellipse 78% 76% at 50% 50%, #000 50%, transparent 100%);
}
@media (max-width: 720px) {
  .decor-film { aspect-ratio: 4 / 3; }
}

/* Screen readers get the sentence the animation is drawing; the canvas itself
   is aria-hidden, so without this the whole beat is silent. */
.decor-film-alt {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
