/* =============================================================================
   AVEN — Journal shelf → tactile magazine rack
   -----------------------------------------------------------------------------
   Restyle + motion for the EXISTING journal markup. Targets only:
       .shelf                     (the rack)
       .issue                     (a cover)   — an <a> (readable) or .soon <div>
       .issue.soon                (wrapped / not-yet-readable cover)
       .kick  .read  .fmt         (cover parts, unchanged in the HTML)
   No markup changes. Paste AFTER the site's base CSS (later = wins; and every
   rule here is scoped `.shelf …` so it out-specifies the base `.issue` rules).
   Colours read the site tokens with literal fallbacks, so this file also
   renders standalone (see demo.html). journal.js is an OPTIONAL enhancement —
   reveal already works from the site's own `.reveal` observer.
   ============================================================================= */

/* ---- Shelf: shared 3D space + local token fallbacks ------------------------ */
.shelf{
  perspective: 1500px;                 /* covers tilt inside one depth field   */
  perspective-origin: 50% 22%;
  gap: clamp(1rem, 2.2vw, 1.5rem);

  /* If the site defines these, the site wins; else the literals render. */
  --j-ink:    var(--ink,    #0b171e);
  --j-ink2:   var(--ink2,   #06121a);
  --j-panel:  var(--panel,  #102630);
  --j-panel2: var(--panel2, #16323c);
  --j-bone:   var(--bone,   #f3ecde);
  --j-gold:   var(--gold,   #e7ab5c);
  --j-golds:  var(--gold-soft, #f3c886);
  --j-sig:    var(--sig,    #d3f227);
  --j-haze:   var(--haze,   #9eb4bd);
  --j-line:   var(--line,   rgba(243,236,222,.12));
  --j-ease:   cubic-bezier(.2,.8,.2,1);

  /* cover stock, as a variable so :active can re-assert it (see note below) */
  --j-cover-bg:
    linear-gradient(90deg,
      var(--j-golds) 0, var(--j-gold) 4px,
      rgba(0,0,0,.34) 5px, rgba(0,0,0,0) 16px) left / 16px 100% no-repeat,
    linear-gradient(157deg, var(--j-panel2) 0%, var(--j-panel) 47%, var(--j-ink2) 100%);
}

/* ---- The cover ------------------------------------------------------------- */
.shelf .issue{
  position: relative;
  isolation: isolate;                  /* local stacking for sheen/peel/content */
  overflow: hidden;                    /* clip sheen + dog-ear to rounded cover  */
  min-height: 13rem;
  border-radius: 16px;
  border: 1px solid var(--j-line);
  padding: 1.55rem 1.5rem 1.35rem;
  text-decoration: none;

  /* cover stock: a gold foil spine down the binding edge + a teal gradient body */
  background: var(--j-cover-bg);

  box-shadow:
    inset 0 1px 0 rgba(243,236,222,.06),
    0 8px 22px rgba(0,0,0,.34);

  transform: translateZ(0);            /* resting plane */
  transition:
    transform   .42s var(--j-ease),
    box-shadow  .42s var(--j-ease),
    border-color .3s ease,
    opacity     .5s  ease;
  will-change: transform;
}
/* content sits above the sheen */
.shelf .issue > *{ position: relative; z-index: 2; }

/* ---- Cover type ------------------------------------------------------------ */
/* Issue line (kick): mono, signal lime, with a small lit tick. */
.shelf .issue .kick{
  display: inline-block;
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: .62rem; letter-spacing: .24em; text-transform: uppercase;
  color: var(--j-sig);
  padding: .1rem 0 .2rem;
}
.shelf .issue .kick::before{
  content: ""; display: inline-block;
  width: .46rem; height: .46rem; margin-right: .5rem;
  border-radius: 1px; vertical-align: baseline; transform: translateY(.01rem);
  background: var(--j-sig);
  box-shadow: 0 0 10px rgba(211,242,39,.6);
}

/* Cover title — the big newsstand line. */
.shelf .issue h3{
  margin: .42rem 0 .55rem;
  /* Newsstand masthead. RESOLVED 2026-08-21: the site now self-hosts its
     faces from /assets/fonts.css, which carries Archivo Black on every page,
     so this stack finally gets the intended heavy grotesque instead of
     falling back to Fraunces. The Fraunces/Georgia tail stays as the
     fallback path for a browser that cannot load the woff2. */
  font-family: "Archivo Black", "Fraunces", Georgia, serif;
  font-weight: 400;                    /* the face is already black */
  font-style: normal;
  font-size: clamp(1.28rem, 1.06rem + .95vw, 1.7rem);
  line-height: 1.05; letter-spacing: -.012em;
  color: var(--j-bone);
  text-shadow: 0 1px 0 rgba(0,0,0,.28);
  transition: color .3s var(--j-ease);
}
.shelf .issue:hover h3,
.shelf .issue:focus-visible h3{ color: var(--j-golds); }

/* Teaser */
.shelf .issue p{
  font-size: .9rem; line-height: 1.5;
  color: #c8d2d6;
}

/* Call to action */
.shelf .issue .read{
  display: flex; align-items: center; flex-wrap: wrap; gap: .55rem;
  margin-top: 1.15rem;
  font-family: "Hanken Grotesk", system-ui, sans-serif;
  font-size: .72rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--j-bone);
  transition: color .3s var(--j-ease), letter-spacing .3s var(--j-ease);
}
.shelf .issue:hover .read,
.shelf .issue:focus-visible .read{ color: var(--j-golds); letter-spacing: .17em; }

/* Format badge → chip. Base is neutral; journal.js adds .fmt-pdf / .fmt-live
   for tint, but the chip already reads correctly with no JS. */
.shelf .issue .fmt{
  display: inline-flex; align-items: center; gap: .4ch;
  margin: 0; padding: .28rem .62rem;
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: .58rem; font-weight: 400; letter-spacing: .16em; text-transform: uppercase;
  line-height: 1; white-space: nowrap;
  color: var(--j-haze);
  background: rgba(243,236,222,.05);
  border: 1px solid var(--j-line);
  border-radius: 999px;
}
.shelf .issue .fmt.fmt-pdf{ color: var(--j-golds); border-color: rgba(231,171,92,.42); }
.shelf .issue .fmt.fmt-live{
  color: var(--j-ink); font-weight: 700; border-color: transparent;
  background: var(--j-sig);
  box-shadow: 0 0 0 1px rgba(211,242,39,.5), 0 4px 14px rgba(211,242,39,.28);
}

/* ---- Sheen sweep (readable covers only) ------------------------------------ */
.shelf .issue:not(.soon)::before{
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(115deg,
    transparent 30%,
    rgba(243,236,222,.10) 46%, rgba(243,236,222,.17) 50%, rgba(243,236,222,.10) 54%,
    transparent 70%);
  transform: translateX(-120%);
  opacity: 0;
  transition: transform .7s var(--j-ease), opacity .5s ease;
}
.shelf .issue:not(.soon):hover::before,
.shelf .issue:not(.soon):focus-visible::before{
  transform: translateX(120%); opacity: 1;
}

/* ---- Page-corner peel (readable covers only) ------------------------------- */
.shelf .issue:not(.soon)::after{
  content: ""; position: absolute; right: 0; bottom: 0; z-index: 3;
  width: 0; height: 0; pointer-events: none;
  border-style: solid; border-width: 0 0 22px 22px;   /* a folded corner        */
  border-color: transparent transparent var(--j-golds) transparent;
  filter: drop-shadow(-2px -2px 3px rgba(0,0,0,.35));
  opacity: 0; transform-origin: 100% 100%; transform: scale(.35) translate(4px,4px);
  transition: transform .34s var(--j-ease), opacity .3s ease;
}
.shelf .issue:not(.soon):hover::after,
.shelf .issue:not(.soon):focus-visible::after{
  opacity: 1; transform: scale(1) translate(0,0);
}

/* ---- Lift + tilt on hover (pointer devices) -------------------------------- */
@media (hover: hover){
  .shelf .issue:not(.soon):hover{
    transform:
      translateY(-9px)
      rotateX(var(--rx, 4.5deg))         /* JS sets --rx/--ry to track the      */
      rotateY(var(--ry, -5deg))          /* cursor; these are the no-JS defaults */
      scale(1.021);
    border-color: var(--j-gold);
    box-shadow:
      inset 0 1px 0 rgba(243,236,222,.10),
      0 26px 60px rgba(0,0,0,.5),
      0 0 0 1px rgba(231,171,92,.18),
      0 14px 34px rgba(231,171,92,.12);   /* warm gold glow blooms */
  }
}

/* Keyboard focus: same tactile lift + a clear gold ring. */
.shelf .issue:not(.soon):focus-visible{
  transform: translateY(-9px) rotateX(4deg) rotateY(-4deg) scale(1.02);
  border-color: var(--j-gold);
  outline: 3px solid var(--j-golds); outline-offset: 3px;
  box-shadow:
    0 26px 60px rgba(0,0,0,.5),
    0 0 0 1px rgba(231,171,92,.2),
    0 14px 34px rgba(231,171,92,.14);
}

/* Press: it settles. Re-assert the cover stock so the live site's
   `.issue:not(.soon):active{background:#08161e}` can't flatten it on press.
   (Transform is left un-!important on purpose: the site's active transform
   carries !important, and matching it here would leak past the reduced-motion
   guard — either settle value reads fine, so we don't fight it.) */
.shelf .issue:not(.soon):active{
  background: var(--j-cover-bg);
  transform: translateY(-3px) scale(.992);
  border-color: var(--j-gold);
  box-shadow: 0 10px 24px rgba(0,0,0,.42);
  transition-duration: .1s;
}

/* ---- .soon — the wrapped, not-yet-readable cover --------------------------- */
.shelf .issue.soon{
  cursor: default;
  filter: saturate(.6) brightness(.9);
  border-style: dashed;
  border-color: rgba(243,236,222,.2);
}
/* glassine shrink-wrap film */
.shelf .issue.soon::before{
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  opacity: .55; mix-blend-mode: screen;
  background:
    repeating-linear-gradient(125deg, rgba(243,236,222,.06) 0 9px, rgba(243,236,222,0) 9px 20px),
    linear-gradient(135deg, rgba(201,212,217,.12), rgba(11,23,30,.04));
}
/* wax seal, bottom-right: a gold disc with an embossed padlock */
.shelf .issue.soon::after{
  content: ""; position: absolute; right: .9rem; bottom: .9rem; z-index: 3;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--j-gold)
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M7%2011V8a5%205%200%200%201%2010%200v3'%20fill='none'%20stroke='%230b171e'%20stroke-width='2.6'/%3E%3Crect%20x='5'%20y='11'%20width='14'%20height='9'%20rx='2'%20fill='%230b171e'/%3E%3C/svg%3E")
    center / 16px no-repeat;
  box-shadow: 0 4px 12px rgba(0,0,0,.4), inset 0 0 0 2px rgba(11,23,30,.32);
}
.shelf .issue.soon .kick{ color: var(--j-golds); opacity: .92; }
/* the "Coming …" line becomes a locked ribbon */
.shelf .issue.soon .read{
  display: inline-flex; align-items: center; gap: .45rem;
  margin-top: 1.1rem; padding: .34rem .72rem;
  color: var(--j-ink); background: var(--j-golds);
  border-radius: 999px;
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: .6rem; font-weight: 400; letter-spacing: .1em; text-transform: uppercase;
}
.shelf .issue.soon .read::before{
  content: ""; display: inline-block; width: 11px; height: 12px;
  background:
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M7%2011V8a5%205%200%200%201%2010%200v3'%20fill='none'%20stroke='%230b171e'%20stroke-width='2.6'/%3E%3Crect%20x='5'%20y='11'%20width='14'%20height='9'%20rx='2'%20fill='%230b171e'/%3E%3C/svg%3E")
    center / contain no-repeat;
}
/* present but clearly locked: a soft acknowledgement, no lift, no open */
.shelf .issue.soon:hover{
  transform: none;
  filter: saturate(.72) brightness(.97);
  box-shadow: 0 10px 26px rgba(0,0,0,.4), 0 0 0 1px rgba(231,171,92,.25);
}

/* ---- Reveal + stagger (coexists with the site's `.reveal` observer) --------
   Only opacity is staggered — never transform — so the entrance can never
   fight the hover lift. Gated on `html.js`; with no JS the covers just show. */
.js .shelf .issue{ opacity: 0; }
.js .shelf.in .issue{ opacity: 1; }
/* delay list maps to (transform, box-shadow, border-color, opacity) — only the
   4th value is delayed, keeping hover/press instant. */
.js .shelf.in .issue:nth-child(1){ transition-delay: 0s,0s,0s,.03s; }
.js .shelf.in .issue:nth-child(2){ transition-delay: 0s,0s,0s,.09s; }
.js .shelf.in .issue:nth-child(3){ transition-delay: 0s,0s,0s,.15s; }
.js .shelf.in .issue:nth-child(4){ transition-delay: 0s,0s,0s,.21s; }
.js .shelf.in .issue:nth-child(5){ transition-delay: 0s,0s,0s,.27s; }
.js .shelf.in .issue:nth-child(n+6){ transition-delay: 0s,0s,0s,.33s; }

/* ---- Touch: no sticky hover, but tactile on tap ---------------------------- */
@media (hover: none){
  .shelf .issue:not(.soon)::before{ display: none; }   /* no sheen sweep on tap */
  .shelf .issue:not(.soon):active{
    transform: scale(.985);
    border-color: var(--j-gold);
    box-shadow: 0 8px 20px rgba(0,0,0,.4), 0 0 0 1px rgba(231,171,92,.22);
  }
}

/* ---- Reduced motion: keep the glow + shadow, drop tilt/parallax/sheen ------ */
@media (prefers-reduced-motion: reduce){
  .shelf{ perspective: none; }
  .js .shelf .issue{ opacity: 1; }                     /* never hide */
  .shelf .issue,
  .shelf .issue:hover,
  .shelf .issue:focus-visible,
  .shelf .issue:active{
    transform: none !important;
    transition: box-shadow .25s ease, border-color .25s ease, color .25s ease !important;
  }
  .shelf .issue:not(.soon)::before,
  .shelf .issue:not(.soon)::after{ display: none !important; }   /* no sheen/peel motion */
  .shelf .issue:not(.soon):hover,
  .shelf .issue:not(.soon):focus-visible{               /* glow + shadow stay */
    border-color: var(--j-gold);
    box-shadow: 0 12px 30px rgba(0,0,0,.45), 0 0 0 1px rgba(231,171,92,.28);
  }
}

/* ---- High-contrast / forced-colors: honour system colours ------------------ */
@media (forced-colors: active){
  .shelf .issue{ border-color: CanvasText; }
  .shelf .issue:not(.soon):focus-visible{ outline: 3px solid Highlight; outline-offset: 2px; }
}
