/* ==========================================================================
   Blackmarker — Atmosphere & Graphics
   Everything here is pure CSS and inline SVG. No image assets, so the whole
   system stays portable into whatever CMS the client's team picks.
   ========================================================================== */

/* --- Page texture ---------------------------------------------------------
   Applied ONCE to the sheet rather than per section. Two layers: a coarse
   watercolour blotch and a fine paper tooth. Doing it per section is what
   made the texture stop abruptly at the top of the page.                 */

.sheet::before,
.sheet::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* Mid-scale fibre. This is the layer that reads as paper: irregular pigment
   catching on tooth. Tile is 420px so the repeat never resolves as a grid. */
.sheet::before {
  opacity: var(--mottle-opacity);
  mix-blend-mode: multiply;
  background-size: 420px 420px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='420'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.05' numOctaves='5' seed='17' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='1.3' intercept='-.1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='420' height='420' filter='url(%23m)'/%3E%3C/svg%3E");
}

/* Fine tooth on top of the fibre. */
.sheet::after {
  opacity: var(--grain-opacity);
  mix-blend-mode: multiply;
  background-size: 130px 130px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='130' height='130'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.2' numOctaves='3' seed='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='130' height='130' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* Everything in the sheet sits above both texture layers. */
.sheet > * { position: relative; z-index: 1; }

/* --- Watercolour wash -----------------------------------------------------
   Colour only. The edges are feathered with a mask so a section's wash melts
   into the next instead of ending on a hard line.                        */

.wash, .atmos { position: relative; isolation: isolate; }

.wash::before,
.atmos::before {
  content: "";
  position: absolute;
  inset: -14% -6%;
  z-index: -1;
  pointer-events: none;
  filter: blur(var(--wash-blur));
  background:
    radial-gradient(46% 40% at 18% 22%, var(--wash-mint), transparent 70%),
    radial-gradient(40% 36% at 82% 14%, var(--wash-warm), transparent 72%),
    radial-gradient(52% 44% at 62% 86%, var(--wash-cool), transparent 74%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 16%, #000 84%, transparent 100%);
}

.wash-warm::before {
  background:
    radial-gradient(52% 46% at 24% 16%, var(--wash-warm), transparent 72%),
    radial-gradient(44% 38% at 78% 28%, var(--wash-mint), transparent 72%);
}
.wash-cool::before {
  background:
    radial-gradient(54% 46% at 76% 18%, var(--wash-cool), transparent 74%),
    radial-gradient(40% 34% at 16% 72%, var(--wash-mint), transparent 72%);
}

/* The hero is the top of the page, so its wash must not fade in from nothing
   at the very top — only out at the bottom. */
.atmos-top::before {
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 76%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 76%, transparent 100%);
}

/* --- Icon chip ------------------------------------------------------------
   A circle with a soft radial fill, so the icon sits in light rather than
   on a flat disc. Straight from the reference.                           */

.icon-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  flex: none;
  border-radius: 50%;
  color: var(--ink);
  /* A plain white disc with a barely-there lift, straight off the frame:
     0/8/8 at -20 spread and 3% opacity. It reads as a soft hole in the page
     rather than a button, which the old two-gradient chip did not. */
  background: var(--surface);
  box-shadow: 0 8px 8px -20px rgba(15, 30, 60, 0.03);
}
.icon-chip svg { width: 1.35rem; height: 1.35rem; display: block; overflow: visible; }

/* The small chip sits on a card rather than the page, so it takes the paper
   colour and no lift at all. */
.icon-chip-sm { width: 2.5rem; height: 2.5rem; background: var(--paper); box-shadow: none; }
.icon-chip-sm svg { width: 1.1rem; height: 1.1rem; }

/* Chips are used inside centred columns as often as inline, so give them a
   reliable way to centre without every caller writing the same rule. */
.icon-chip-center { display: flex; margin-inline: auto; }


/* --- Panel ----------------------------------------------------------------
   The big rounded container that groups a section. One treatment, used
   everywhere: a flat 3% black wash on the paper. It was three different
   gradients (cool grey, mint, warm) until the frame showed every panel on
   the same neutral wash — the tints were reading as meaning that wasn't
   there.                                                                 */

.panel {
  border-radius: var(--radius-outer);
  padding: clamp(var(--s-8), 4vw, var(--s-16));
  background: var(--wash);
}

/* --- Supporting graphics --------------------------------------------------
   Small compositions that carry an idea. Each one is a diagram of a claim
   the copy makes, not decoration.                                        */

.g-frame {
  background: var(--surface);
  border-radius: var(--radius-outer);
  padding: var(--s-6);
  box-shadow: var(--shadow);
}

/* Detection: text scanned, flagged, then covered. The highlight sweeps in from
   the left like a scan head passing over the line, then the bars land the same
   way. Loops, because it is describing what happens to every page. */
.g-detect { font-family: var(--font-display); font-size: var(--text-sm); line-height: 2; }

.g-detect .redact-pending {
  background-color: transparent;
  background-image: linear-gradient(var(--highlight), var(--highlight));
  background-repeat: no-repeat;
  background-size: 0% 100%;
  transition: background-size var(--dur-slow) var(--ease);
  /* No padding where the SSN breaks, so the highlight takes the same room at
     the end of a line as the bar's flush halves below. */
  -webkit-box-decoration-break: slice;
          box-decoration-break: slice;
}
.g-detect.is-scanned .redact-pending { background-size: 100% 100%; }

/* The SSN bar comes in two halves so it can wrap after "***-" the way the
   highlighted line above does. The halves sit flush and their bleeds overlap,
   so on one line they read as a single bar. Each bar takes the same side room
   as the highlight's padding, so both lines are the same width and always
   break in the same place. Kerning is off on both lines because the font
   tucks "*" under "-", which the unbroken highlight gets and the split bar
   can't, leaving the bar line 1.5px wider. */
.g-detect { font-kerning: none; }
.g-detect .redact { margin-inline: 0.16em; }
.g-detect .ssn-split .redact:first-child { margin-inline-end: 0; }
.g-detect .ssn-split .redact:last-child { margin-inline-start: 0; }

/* During the intro the bars sweep on from the left. */
.g-detect .redact { --redact-origin: left center; }
.g-detect .redact::after { transform: scaleX(0); }
.g-detect.is-redacted .redact::after { transform: scaleX(1); }
/* Once the intro has run, hand the origin back so hover lifts to the right. */
.g-detect.is-armed .redact { --redact-origin: right center; }

@media (prefers-reduced-motion: reduce) {
  .g-detect .redact-pending { background-size: 100% 100%; }
  .g-detect .redact::after { transform: scaleX(1); }
}

/* Metadata stripping ------------------------------------------------------
   A property list that empties out. Rows arrive on a stagger, then each value
   is struck through by a line drawn left to right — the same left-to-right
   erasure the redaction bars use, at a smaller scale. It loops, because the
   claim is that this happens on every document, not once. */

.g-meta-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4); padding: var(--s-2) 0;
  border-bottom: 1px solid var(--hairline);
  font-size: var(--text-sm);
  opacity: 0;
  transform: translateY(0.35em);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.g-meta-row:last-child { border-bottom: 0; }
.g-meta.is-in .g-meta-row { opacity: 1; transform: none; }

.g-meta-key { color: var(--ink-3); }
.g-meta-val { font-variant-numeric: tabular-nums; }

/* The strike is a drawn line, not text-decoration, so it can be animated. */
.g-meta-stripped {
  position: relative;
  color: var(--ink-3);
  transition: color var(--dur-slow) var(--ease);
}
.g-meta-stripped::after {
  content: "";
  position: absolute;
  left: -0.16em; right: -0.16em;
  top: 54%;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-slow) var(--ease);
}
.g-meta-row.is-struck .g-meta-stripped { color: var(--ink-4); }
.g-meta-row.is-struck .g-meta-stripped::after { transform: scaleX(1); }

/* The surviving row resolves rather than disappears. */
.g-meta-out { color: var(--ink-4); transition: color var(--dur-slow) var(--ease); }
.g-meta.is-done .g-meta-out {
  color: var(--mint-deep);
  font-weight: var(--weight-semi);
}

@media (prefers-reduced-motion: reduce) {
  .g-meta-row { opacity: 1; transform: none; }
  .g-meta-stripped::after { transform: scaleX(1); }
}

/* Throughput gate ---------------------------------------------------------
   Pages stream left to right through a redaction gate: they arrive with their
   content readable and leave with bars over it. Shows the product working, not
   just a quantity. Replaced a tile grid that went solid black once it filled,
   which read as a rectangle rather than as scale. */

.gate {
  position: relative;
  height: 190px;
  overflow: hidden;
  border-radius: var(--radius-outer);
  background: var(--surface-2);
  border: 1px solid var(--hairline);
}

.gate-line {
  position: absolute;
  left: 50%; top: 0; bottom: 0;
  width: 2px;
  background: var(--ink);
  z-index: 3;
}

.gate-label {
  position: absolute;
  left: 50%; top: 10px;
  transform: translateX(-50%);
  z-index: 4;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  background: var(--ink);
  color: var(--surface);
  font-size: var(--text-xs);
  font-weight: var(--weight-semi);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  white-space: nowrap;
}

/* A single page in the stream. */
.gate-pg {
  position: absolute;
  width: 52px; height: 66px;
  padding: 6px 5px;
  border-radius: 3px;
  background: var(--surface);
  border: 1px solid var(--hairline-2);
  box-shadow: var(--shadow);
  left: 0;
}
.gate-pg i {
  display: block;
  height: 3px;
  margin-bottom: 4px;
  border-radius: 1px;
  background: var(--surface-3);
}
.gate-pg i.r { background: var(--ink); }

/* Full-size layers: clipping changes visibility, never page coordinates. */
.gate-before, .gate-after {position:absolute;inset:0;pointer-events:none;}
.gate-before {clip-path:inset(0 50% 0 0);}
.gate-after {clip-path:inset(0 0 0 50%);z-index:2;}

@media (prefers-reduced-motion: reduce) {
  .gate-pg { animation: none; }
}

/* Static capture mode: no motion anywhere, everything in its resolved state. */
html[data-static] .gate-pg { animation: none !important; }
html[data-static] *, html[data-static] *::before, html[data-static] *::after {
  animation-play-state: paused !important;
  transition: none !important;
}

/* Coverage list, the flag-row pattern from the reference. */
.g-cover-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4); padding: var(--s-3) 0;
  border-bottom: 1px solid var(--hairline);
}
.g-cover-row:last-child { border-bottom: 0; }
