/* =====================================================================
   dashofblum — the personal hub's own skin, loaded on top of the shared
   site.css it borrows from lightly-salted.com.

   Everything below is a darkroom: film grain over the whole viewport, a
   warm safelight bloom behind the hero, a vignette pulling the corners
   in, and the section bands cut like frames of film. The studio's gold
   shifts to a print-developer rust so this reads as Matthew's own place
   rather than a second Lightly-Salted page.

   Three rules make that safe:

   1. TOKENS GO ON body.site, NOT :root. site.css owns :root; overriding
      there would leak into carshowbingo/, which loads after this file
      and defines its own world. (It touches none of --accent/--paper/
      --ink/--line/--surface — every token there is --csb- prefixed — so
      scoping to body.site keeps the bingo card exactly as it was.)
   2. SKINS HANG OFF EXISTING CLASSES. Every *skin* selector here hangs
      off a class the hub's page files already emit, so restyling never
      forces a page edit. The one exception is .wall-label at the bottom,
      a component that arrived with its own markup in
      archive-collection-item.php — keep new components down there, and
      keep the skin above honest.
   3. TWO PLACES IN site.css HARDCODE THE GOLD (.btn's `color: #17130a`
      and .btn:hover's `#ecc154`). They can't inherit the new accent, so
      they're restated below. Grep for #ecc154 before adding a component.

   Reset, box-sizing, layout, .reveal and the lightbox all come from
   site.css — not repeated here.
   ===================================================================== */

/* ---- Hub tokens ----------------------------------------------------- */
body.site {
  /* Print-developer rust, off the studio gold.
     --accent-ink on --paper is 8.1:1; --btn-ink on --accent is 5.4:1. */
  --accent:      #c2703d;
  --accent-ink:  #e59a63;
  --accent-hot:  #d98a55;   /* the lift .btn:hover used to get from #ecc154 */
  --btn-ink:     #1a0f07;   /* dark text on the accent fill */

  /* Darkroom layers. Swapped wholesale by .hub-darkroom below. */
  /* .1 is about the floor where the grain actually reads as texture on a
     dark field rather than as a slightly noisy JPEG; much past .14 and it
     starts sanding the edges off body text. */
  --hub-grain-opacity: .1;
  --hub-safelight: radial-gradient(
      55rem 40rem at 18% -8%,
      color-mix(in srgb, var(--accent) 26%, transparent),
      transparent 68%);
  --hub-vignette: radial-gradient(
      130% 105% at 50% 38%,
      transparent 42%,
      color-mix(in srgb, var(--dark) 82%, transparent) 100%);
}

/* ---- The lighting: safelight + vignette, behind the content --------- */
/* Fixed rather than background-attachment: fixed, which janks on iOS. */
body.site::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--hub-vignette), var(--hub-safelight);
}

/* ---- The grain: over everything, including photographs -------------- */
/* A tiling feTurbulence data-URI (the vhost CSP allows img-src data:).
   On top rather than behind so cards and images get grained too — that's
   what makes it read as film instead of a patterned wallpaper. Dialogs
   live in the top layer, so the lightbox still opens above this. */
body.site::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: var(--hub-grain-opacity);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}

/* The bands paint over the fixed lighting layer, so let it bleed back
   through. Cards stay opaque on purpose — they're objects on the page. */
body.site .section--alt { background: color-mix(in srgb, var(--paper-2) 86%, transparent); }
body.site .site-footer  { background: color-mix(in srgb, var(--dark) 90%, transparent); }

/* Two columns, not site.css's three: the "Elsewhere" column was retired when the
   Salt Line took over that job, and the grid was left holding an empty third. */
@media (min-width: 720px) { body.site .footer-grid { grid-template-columns: 1.4fr 1fr; } }

/* ---- Section bands as frames of film -------------------------------- */
/* A near-black strip with lit perforations, so the band edges read as film
   on a lightbox. Two tiled gradient layers, so the whole run is one paint.
   Punching *transparent* holes in the strip was the obvious way round and
   the wrong one — hole and band are both dark, so it vanished; the holes
   have to carry the light. */
body.site .section--alt { position: relative; }
body.site .section--alt::before,
body.site .section--alt::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 14px;
  pointer-events: none;
  background-image:
      radial-gradient(circle at 11px 50%,
          color-mix(in srgb, var(--ink) 20%, transparent) 0 3.4px,
          transparent 4px),
      linear-gradient(var(--dark), var(--dark));
  background-size: 22px 100%, 100% 100%;
  background-repeat: repeat-x, no-repeat;
}
body.site .section--alt::before { top: 0; }
body.site .section--alt::after  { bottom: 0; }

/* ---- Hero: a bloom that follows the pointer ------------------------- */
/* hub.js writes --hub-x/--hub-y; the fallbacks below are the resting
   position, so this looks deliberate with JS off or on a touch screen. */
body.site .page-hero {
  position: relative;
  isolation: isolate;
}
body.site .page-hero::before {
  content: "";
  position: absolute;
  inset: -30% -10% -25%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
      34rem 24rem at var(--hub-x, 24%) var(--hub-y, 34%),
      color-mix(in srgb, var(--accent) 20%, transparent),
      transparent 66%);
}

/* Kickers become typewriter captions. Special Elite ships 400 only, and
   it's wider than Plex Mono, so it needs the size up and tracking down. */
body.site .kicker {
  font-family: var(--font-type);
  font-size: .92rem;
  font-weight: 400;
  letter-spacing: .14em;
}

/* ---- Header hairline ------------------------------------------------ */
/* .site-header is already sticky (positioned), so this anchors to it.
   Its backdrop-filter now blurs the grain and safelight behind the bar. */
body.site .site-header::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg,
      transparent,
      color-mix(in srgb, var(--accent) 60%, transparent) 20%,
      color-mix(in srgb, var(--accent) 60%, transparent) 80%,
      transparent);
}

/* ---- Cards as photo prints ------------------------------------------ */
/* Adds a hair of rotation to the lift site.css already animates, so the
   card settles like a print dropped on the page. Transition comes from
   site.css (transform var(--speed) var(--ease)) — don't restate it. */
body.site .card:hover {
  transform: translateY(-4px) rotate(-.35deg);
  box-shadow:
      var(--shadow-lg),
      0 18px 44px color-mix(in srgb, var(--accent) 16%, transparent);
}
body.site .card__media { position: relative; }
body.site .card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ink) 12%, transparent);
}

/* ---- Buttons: the two hardcoded golds, restated --------------------- */
body.site .btn { color: var(--btn-ink); }
body.site .btn:hover { background: var(--accent-hot); border-color: var(--accent-hot); }

/* ---- Chips: inert in site.css, given a hover here ------------------- */
body.site .chip {
  transition: color var(--speed), border-color var(--speed), background var(--speed);
}
body.site .chip:hover {
  color: var(--accent-ink);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

/* ---- Darkroom mode -------------------------------------------------- */
/* Type "darkroom" (hub.js). Kills the white light, drops a red safelight
   over everything and pushes the photographs through the developer. */
html.hub-darkroom body.site {
  --accent:      #c4342a;
  --accent-ink:  #ff8f79;
  --accent-hot:  #e04b3c;
  --hub-grain-opacity: .16;
  --hub-safelight: radial-gradient(
      60rem 46rem at 50% -10%,
      color-mix(in srgb, #c4342a 34%, transparent),
      transparent 72%);
  --hub-vignette: radial-gradient(
      120% 100% at 50% 34%,
      transparent 26%,
      color-mix(in srgb, #070304 92%, transparent) 100%);
}
html.hub-darkroom body.site .card__media img,
html.hub-darkroom body.site figure.framed img {
  filter: sepia(1) hue-rotate(-42deg) saturate(3.2) brightness(.72);
}

/* The mode's only piece of injected markup (hub.js builds it). */
.hub-darkroom__badge {
  position: fixed;
  z-index: 10000;
  right: 1rem;
  bottom: 1rem;
  font-family: var(--font-mono);
  font-size: .68rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: #ff8f79;
  background: rgba(10, 3, 4, .78);
  border: 1px solid rgba(255, 143, 121, .35);
  border-radius: 999px;
  padding: .45em 1em;
  pointer-events: none;
}

/* ---- The wall label -------------------------------------------------- */
/* A museum placard for archive-collection-item.php: maker, dates and spec
   rows ruled off from each other, with the interpretive prose kept below.
   This is the file's one piece of component CSS — see rule 2 up top. */
.wall-label {
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) 1fr;
  max-width: 68ch;              /* matches .prose, so label and text align */
  margin: 0;
  border-top: 1px solid var(--line);
}
.wall-label > dt,
.wall-label > dd {
  margin: 0;
  padding: .7rem 0;
  border-bottom: 1px solid var(--line);
}
.wall-label > dt {
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  padding-right: 1.5rem;
  align-self: baseline;
}
.wall-label > dd { color: var(--ink); }

/* Stacked: the label sits on its own line above its value, and only the
   value row carries the rule so the pair still reads as one entry. */
@media (max-width: 560px) {
  .wall-label { grid-template-columns: 1fr; }
  .wall-label > dt { padding: .7rem 0 .1rem; border-bottom: 0; }
  .wall-label > dd { padding-top: 0; }
}

/* ---- Reduced motion -------------------------------------------------- */
/* The texture is static, so it stays — only the movement goes. */
@media (prefers-reduced-motion: reduce) {
  body.site .card:hover { transform: translateY(-4px); }
}
