/* =====================================================================
   fx.css  —  Brian Brixon
   The styles for the Amendment 1 effects. Each effect's JavaScript is in
   /assets/js/fx/ and only loads on pages that use it (data-fx="…");
   these few rules are shared by every page so nothing flashes while a
   script arrives. Colors and timings come from tokens.css.

     1. Rune decode            data-fx="runes"
     2. Raking light           data-fx="raking"
     3. The laser              data-fx="laser"
     4. Design your keepsake   data-fx="keepsake"
     5. The thread             data-fx="thread"
     6. Blueprint mode         html.blueprint
     7. The monogram retraces  .bb-brand--retrace
     8. Burn-in page change    html[data-fx-on~="burn"]

   Rule for every effect: the content is there without JavaScript, and
   with "reduce motion" each one simply shows its finished state.
   ===================================================================== */


/* ---- 1. Rune decode ------------------------------------------------------
   Each letter is its own span, held at its own width while it flickers. */
.bb-runes--line { white-space: nowrap; }                /* it was one line: it stays one line */
.bb-runes__word { display: inline-block; white-space: nowrap; }   /* wraps only between words */
.bb-runes__word > span {
  display: inline-block;
  text-align: center;
}
.bb-runes .is-rune { color: var(--bb-accent-text); }


/* ---- 2. Raking light -------------------------------------------------------
   fx/raking.js sets --mx/--my (where the pointer is), --rx/--ry (the tilt)
   and --sx/--sy (the shadow, on the far side from the light). */
.fx-rake {
  transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 220ms var(--bb-ease-out), box-shadow 220ms var(--bb-ease-out);
}
.fx-rake.is-lit {
  box-shadow: var(--sx, 0) var(--sy, 6px) 28px rgba(0, 0, 0, 0.42);
}
.bb-rake {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(circle at var(--mx, 50%) var(--my, 50%),
    rgba(255, 226, 182, 0.6), rgba(255, 226, 182, 0.12) 35%, rgba(255, 226, 182, 0) 62%);
  mix-blend-mode: soft-light;
  opacity: 0;
  transition: opacity 300ms var(--bb-ease-out);
}
.fx-rake.is-lit .bb-rake { opacity: 1; }


/* ---- 3. The laser ---------------------------------------------------------
   While a picture waits for the laser it's dimmed to a flat dark tone
   (still painted, so it still counts as the page's main picture). A
   picture at the top of the page (data-laser-hero) is dimmed before the
   page paints, and shown anyway after 6 seconds if fx/laser.js never
   arrives; any other one only once fx/laser.js has taken it on. */
[data-fx~="laser"] { position: relative; }
.bb-laser {
  position: absolute;
  z-index: 1;               /* under the corner brackets (z-index 2) */
  pointer-events: none;
}
.bb-laser__art.is-fading {
  opacity: 0;
  transition: opacity 400ms ease;
}
@media (prefers-reduced-motion: no-preference) {
  html.js:not([data-fx-off~="laser"]) [data-fx~="laser"][data-laser-hero]:not(.fx-laser-done) img,
  html.js [data-fx~="laser"].fx-laser-armed:not(.fx-laser-done) img {
    filter: contrast(0) brightness(0.19);
  }
  html.js:not([data-fx-off~="laser"]) [data-fx~="laser"][data-laser-hero]:not(.fx-laser-armed):not(.fx-laser-done) img {
    animation: bb-fx-show-img 0s 6s forwards;
  }
}
@keyframes bb-fx-show-img { to { filter: none; } }


/* ---- 4. Design your keepsake -----------------------------------------------------
   The preview (a canvas drawn by fx/keepsake.js) beside its form; one
   above the other on phones. */
.bb-keepsake {
  display: grid;
  gap: var(--space-l) var(--space-xl);
  align-items: start;
}
@media (min-width: 992px) {
  .bb-keepsake { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); }
}
.bb-keepsake__stage {
  position: relative;
  aspect-ratio: 3 / 2;
  border-radius: var(--bb-radius-card);
  background-color: var(--bb-bog-oak);
  overflow: hidden;
}
.bb-keepsake__canvas,
.bb-keepsake__head {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}
.bb-keepsake__head { pointer-events: none; }
.bb-keepsake__nojs {
  position: absolute;
  inset: auto var(--space-m) var(--space-m);
  margin: 0;
  font-family: var(--bb-font-ui);
  font-size: var(--step--1);
  color: var(--bb-lichen);
  text-align: center;
}
.bb-keepsake.is-live .bb-keepsake__nojs { display: none; }
.bb-keepsake__group {
  margin: 0 0 var(--space-m);
  padding: 0;
  border: 0;
}
.bb-keepsake__note {
  margin: var(--space-s) 0 0;
  font-family: var(--bb-font-ui);
  font-size: var(--step--1);
  color: var(--bb-text-muted);
}

/* Segmented choices: real radio buttons, drawn as a row of chips. */
.bb-segments {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.bb-segments__input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.bb-segments__label {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  min-height: 44px;
  padding: 0.45rem 0.95rem;
  border: 1px solid var(--bb-field-line);
  border-radius: var(--bb-radius-control);
  font-family: var(--bb-font-ui);
  font-weight: var(--bb-weight-ui);
  font-size: var(--step--1);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bb-text);
  cursor: pointer;
  transition: border-color var(--bb-dur-hover), background-color var(--bb-dur-hover), color var(--bb-dur-hover);
}
.bb-segments__label:hover { border-color: var(--bb-accent); }
.bb-segments__input:checked + .bb-segments__label {
  background-color: var(--bb-accent);
  border-color: var(--bb-accent);
  color: var(--bb-accent-ink);
}
.bb-segments__input:checked + .bb-segments__label::before {   /* not by color alone */
  content: "";
  width: 0.45em;
  height: 0.45em;
  background-color: currentColor;
  transform: rotate(45deg);
}
.bb-segments__input:focus-visible + .bb-segments__label {
  outline: 2px solid var(--bb-focus);
  outline-offset: 2px;
}
/* High contrast: the chosen one in the theme's highlight color (brand.css, section 27). */
@media (forced-colors: active) {
  .bb-segments__input:checked + .bb-segments__label { border-color: Highlight; }
  .bb-segments__input:checked + .bb-segments__label::before { background-color: Highlight; }
}

/* The small preview on the contact page. */
.bb-keepsake--preview { display: block; max-width: 26rem; }
.bb-keepsake--preview .bb-keepsake__stage { margin-bottom: var(--space-s); }


/* ---- 5. The thread -----------------------------------------------------------
   One SVG over the whole page, drawn by fx/thread.js (wide screens only).
   It fades in once the hero monogram has drawn itself. */
.bb-thread {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 600ms var(--bb-ease-out);
}
.bb-thread.is-on { opacity: 1; }
.bb-thread path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
}
.bb-thread__line {
  stroke: var(--bb-verdigris);
  stroke-opacity: 0.7;
  stroke-width: 1.5;
}
.bb-thread__band {                 /* the knots: a band with a bronze groove, like the monogram */
  stroke: var(--bb-verdigris);
  stroke-opacity: 0.9;
  stroke-width: 3.4;
}
.bb-thread__groove {
  stroke: var(--bb-bronze);
  stroke-width: 1;
}
@media print { .bb-thread { display: none; } }


/* ---- 7. The monogram retraces ------------------------------------------------
   Hovering (or focusing) the header's home link sends a light once along
   the knot's unbroken line, in 600ms. Needs the knot's line paths:
   bb_knot(['draw' => true]) and .bb-brand--retrace on the link. */
@media (prefers-reduced-motion: no-preference) {
  .bb-brand--retrace .bb-knot__draw {
    opacity: 0;
    color: #FFF1D6;            /* a warm white light, brighter than the bronze */
  }
  html:not([data-fx-off~="retrace"]) .bb-brand--retrace:hover .bb-knot__draw,
  html:not([data-fx-off~="retrace"]) .bb-brand--retrace:focus-visible .bb-knot__draw { opacity: 1; }
  html:not([data-fx-off~="retrace"]) .bb-brand--retrace:hover .bb-knot__draw path,
  html:not([data-fx-off~="retrace"]) .bb-brand--retrace:focus-visible .bb-knot__draw path {
    stroke-dasharray: 0.16 1.2;
    stroke-dashoffset: 0.16;
    animation: bb-retrace 600ms var(--bb-ease-draw) forwards;
  }
}
@keyframes bb-retrace { to { stroke-dashoffset: -1.04; } }


/* ---- 8. Burn-in page change ----------------------------------------------------
   Instead of the plain 250ms fade, the new page is revealed from the top
   behind a thin glowing laser line, in about 450ms. The line is added by
   the small script in <head> (inc/head.php). Same-site links only, and
   only in browsers with cross-document view transitions. */
@media (prefers-reduced-motion: no-preference) {
  html[data-fx-on~="burn"]::view-transition-old(root) { animation: none; }
  html[data-fx-on~="burn"]::view-transition-new(root) {
    animation: bb-burn-in 450ms linear both;
  }
  .bb-burnline {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2147483647;
    height: 2px;
    margin-top: -3px;
    background: linear-gradient(90deg, rgba(255, 150, 60, 0), #FFE2B6 12%, #FFFFFF 50%, #FFE2B6 88%, rgba(255, 150, 60, 0));
    box-shadow: 0 0 10px 2px rgba(255, 138, 42, 0.75), 0 0 28px 6px rgba(255, 110, 30, 0.35);
    pointer-events: none;
    animation: bb-burnline 450ms linear forwards;
  }
}
@keyframes bb-burn-in  { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes bb-burnline { from { transform: translateY(0); } to { transform: translateY(100vh); opacity: 0.6; } }


/* ---- 6. Blueprint mode ---------------------------------------------------------------
   html.blueprint: the Bootstrap grid over the page, a dashed bronze
   outline on every component marked data-bp="Name" with its label, and
   the readout in the corner (fx/blueprint.js). */
.no-js [data-blueprint-toggle] { display: none; }
html.blueprint [data-bp] {
  outline: 1px dashed color-mix(in srgb, var(--bb-bronze) 85%, transparent);
  outline-offset: -1px;
}
.bb-bp-grid {
  position: fixed;
  inset: 0;
  z-index: 1015;
  pointer-events: none;
}
.bb-bp-grid .container,
.bb-bp-grid .row { height: 100%; }
.bb-bp-grid .col-1 span {
  display: block;
  height: 100%;
  background-color: color-mix(in srgb, var(--bb-bronze) 7%, transparent);
  border-inline: 1px solid color-mix(in srgb, var(--bb-bronze) 22%, transparent);
}
.bb-bp-labels {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1016;
  overflow-x: clip;          /* a long label is cut at the screen's edge, so the page never scrolls sideways */
  pointer-events: none;
}
.bb-bp-label {
  position: absolute;
  display: grid;
  max-width: 34rem;
  padding: 0.15rem 0.4rem;
  background-color: var(--bb-bronze);
  color: var(--bb-forest);
  font-family: var(--bb-font-ui);
  font-size: 0.6875rem;
  line-height: 1.3;
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bb-bp-label b { font-weight: var(--bb-weight-ui); text-transform: uppercase; letter-spacing: 0.08em; }
.bb-bp-label i { font-style: normal; font-family: var(--bb-font-code); font-size: 0.625rem; }
.bb-bp-readout {
  position: fixed;
  left: var(--space-m);
  bottom: var(--space-m);
  z-index: 1025;
  width: min(22rem, calc(100vw - 2 * var(--space-m) - 60px));
  padding: var(--space-s) var(--space-m);
  background-color: color-mix(in srgb, var(--bb-bog-oak) 94%, transparent);
  border: 1px dashed var(--bb-bronze);
  border-radius: var(--bb-radius-card);
  color: var(--bb-bone);
  font-family: var(--bb-font-ui);
  font-size: var(--step--1);
}
.bb-bp-readout__title {
  margin: 0 0 var(--space-2xs);
  font-weight: var(--bb-weight-ui);
  letter-spacing: var(--bb-tracking-label);
  text-transform: uppercase;
  color: var(--bb-bronze);
}
.bb-bp-readout dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.2rem 0.8rem;
  margin: 0;
}
.bb-bp-readout dt { color: var(--bb-lichen); }
.bb-bp-readout dd { margin: 0; font-family: var(--bb-font-code); font-size: 0.8125rem; }
.bb-bp-readout__sig { margin: var(--space-2xs) 0; color: var(--bb-lichen); }
@media print { .bb-bp-grid, .bb-bp-labels, .bb-bp-readout { display: none; } }

/* The design as it arrives on the contact page. */
.bb-keepsake-sent {
  display: grid;
  gap: var(--space-m);
  align-items: start;
  margin-bottom: var(--space-s);
}
@media (min-width: 768px) { .bb-keepsake-sent { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); } }
.bb-keepsake-sent__title {
  margin: 0 0 var(--space-2xs);
  font-family: var(--bb-font-ui);
  font-weight: var(--bb-weight-ui);
  font-size: var(--step--1);
  letter-spacing: var(--bb-tracking-label);
  text-transform: uppercase;
  color: var(--bb-heading);
}
.bb-keepsake-sent__list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.9rem;
  margin: 0;
}
.bb-keepsake-sent__list dt { font-family: var(--bb-font-ui); font-size: var(--step--1); color: var(--bb-text-muted); }
.bb-keepsake-sent__list dd { margin: 0; }
