/* ==========================================================================
   LUMEN · holo — holographic foil card for the detail viewer
   --------------------------------------------------------------------------
   Ported from the standalone 全息工坊 page: a card wrapped in a 3D pose with
   four layers (art / foil / glare / glass border), a ground caustic under it,
   and a control console that lives on the detail page itself.

   Layout, matching the reference:
     .viewer__stage
       .viewer__frame            (zoom/pan transform — untouched)
         .holo-card              (the 3D tilt + layers)
           .holo__image > img
           .holo__shine
           .holo__glare
           .holo__border
       .holo__ground             (the caustic under the card)
     .holo-console               (right column, inline controls)
   ========================================================================== */

/* The card sizes itself from the picture, but the picture is capped so the
   print stays modest next to the console (a 4K wallpaper used to swallow the
   whole sheet). */
.holo-card {
  position: relative;
  display: inline-block;
  border-radius: 16px;
  overflow: hidden;
  transform-style: preserve-3d;
  will-change: transform;
  touch-action: none;
  cursor: grab;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.85);
  line-height: 0;
}
.holo-card:active {
  cursor: grabbing;
}

.holo__image {
  position: relative;
  display: block;
  border-radius: inherit;
  overflow: hidden;
  background: #000;
}
.holo__image img,
.holo__image video {
  display: block;
  width: auto;
  height: auto;
  max-width: min(430px, 34vw);
  max-height: min(470px, 58vh);
  object-fit: contain;
  pointer-events: none;
  border-radius: inherit;
}

/* the foil sheet: color-dodge over the art, so it needs the art to be a
   photograph rather than flat colour */
.holo__shine {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  mix-blend-mode: color-dodge;
  opacity: calc(var(--holo-brightness) * 0.9);
  pointer-events: none;
  transition: opacity 150ms ease;
}

.holo__glare {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    circle 320px at var(--holo-spec-x) var(--holo-spec-y),
    rgba(255, 255, 255, 0.3) 0%,
    rgba(255, 255, 255, 0.05) 35%,
    transparent 70%
  );
  mix-blend-mode: screen;
  opacity: calc(var(--holo-brightness) * 0.6);
  pointer-events: none;
}

/* ---- acrylic / glass border -------------------------------------------- */
.holo__border {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  transition: all 250ms ease;
  display: block;
}
.holo-card[data-border="none"] .holo__border {
  display: none;
}
.holo-card[data-border="diamond"] .holo__border {
  border: 2px solid rgba(255, 255, 255, 0.7);
  box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.4),
    inset 2px 2px 4px rgba(255, 255, 255, 0.9),
    inset -2px -2px 5px rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(0.4px);
}
.holo-card[data-border="prism"] .holo__border {
  border: 3px solid transparent;
  background: linear-gradient(
      calc(var(--holo-caustic) + var(--holo-tilt-x) * 1.5),
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 60, 100, 0.7) 15%,
      rgba(255, 220, 80, 0.6) 30%,
      rgba(100, 255, 200, 0.7) 45%,
      rgba(80, 180, 255, 0.75) 60%,
      rgba(180, 80, 255, 0.65) 75%,
      rgba(255, 255, 255, 0.95) 90%
    )
    border-box;
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
  mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  box-shadow: 0 0 12px rgba(255, 255, 255, 0.35);
}
.holo-card[data-border="ice"] .holo__border {
  border: 1.5px solid rgba(255, 255, 255, 0.45);
  box-shadow: inset 0 0 14px rgba(255, 255, 255, 0.25),
    inset 1px 1px 2px rgba(255, 255, 255, 0.85);
}
.holo-card[data-border="gold"] .holo__border {
  border: 2px solid rgba(255, 215, 0, 0.7);
  box-shadow: inset 0 0 12px rgba(218, 165, 32, 0.4),
    inset 1.5px 1.5px 3px rgba(255, 255, 230, 0.9),
    0 0 10px rgba(255, 215, 0, 0.2);
}

/* ---- the caustic on the "floor" under the card ------------------------- */
.holo__ground {
  position: absolute;
  left: 50%;
  bottom: 3%;
  width: 68%;
  height: 44px;
  border-radius: 50%;
  background: radial-gradient(
    ellipse at center,
    rgba(0, 0, 0, 0.95) 0%,
    rgba(255, 51, 102, 0.26) 25%,
    rgba(255, 215, 140, 0.12) 50%,
    transparent 75%
  );
  transform: translateX(-50%) rotateX(85deg);
  filter: blur(12px);
  pointer-events: none;
  opacity: calc(0.35 + var(--holo-brightness) * 0.5);
  transition: opacity 200ms ease;
}

/* ==========================================================================
   14 foil craft presets
   ========================================================================== */
.holo-card[data-theme="classic"] .holo__shine {
  background-image: repeating-linear-gradient(
      125deg,
      rgba(255, 77, 109, 0.38) 0%,
      rgba(255, 183, 3, 0.35) 15%,
      rgba(119, 247, 212, 0.35) 30%,
      rgba(114, 9, 183, 0.35) 45%,
      rgba(255, 77, 109, 0.38) 60%
    ),
    radial-gradient(
      farthest-corner circle at var(--holo-pointer-x) var(--holo-pointer-y),
      rgba(255, 255, 255, 0.85) 0%,
      rgba(255, 107, 157, 0.45) 35%,
      rgba(138, 43, 226, 0.18) 65%,
      transparent 80%
    );
  background-size: 250% 250%, 150% 150%;
  background-position: var(--holo-bg-x) var(--holo-bg-y), center;
  filter: contrast(1.35) brightness(1.1);
}
.holo-card[data-theme="gold"] .holo__shine {
  background-image: repeating-linear-gradient(
      125deg,
      rgba(255, 215, 0, 0.5) 0%,
      rgba(255, 245, 180, 0.85) 12%,
      rgba(184, 134, 11, 0.4) 25%,
      rgba(255, 215, 0, 0.5) 38%
    ),
    radial-gradient(
      circle at var(--holo-spec-x) var(--holo-spec-y),
      rgba(255, 255, 255, 0.9) 0%,
      rgba(255, 215, 0, 0.4) 40%,
      transparent 70%
    );
  background-size: 260% 260%, 150% 150%;
  background-position: var(--holo-spec-x) var(--holo-spec-y), center;
}
.holo-card[data-theme="cracked-ice"] .holo__shine {
  background-image: repeating-linear-gradient(
      60deg,
      rgba(255, 255, 255, 0.45) 0px,
      transparent 14px,
      rgba(255, 90, 140, 0.3) 28px
    ),
    repeating-linear-gradient(
      -60deg,
      rgba(120, 240, 255, 0.45) 0px,
      transparent 14px,
      rgba(255, 255, 255, 0.2) 28px
    ),
    radial-gradient(
      circle at var(--holo-spec-x) var(--holo-spec-y),
      rgba(255, 255, 255, 0.95) 0%,
      transparent 65%
    );
  background-size: 48px 48px, 48px 48px, 160% 160%;
  filter: contrast(1.6);
}
.holo-card[data-theme="spot-uv"] .holo__shine {
  -webkit-mask-image: radial-gradient(
    circle at var(--holo-spec-x) var(--holo-spec-y),
    black 0%,
    black 28%,
    transparent 60%
  );
  mask-image: radial-gradient(
    circle at var(--holo-spec-x) var(--holo-spec-y),
    black 0%,
    black 28%,
    transparent 60%
  );
  background-image: radial-gradient(
    circle at var(--holo-spec-x) var(--holo-spec-y),
    #ffffff 0%,
    #ff1a53 35%,
    #ffd700 70%,
    transparent 90%
  );
  background-size: 160% 160%;
  background-position: center;
  filter: contrast(1.8);
}
.holo-card[data-theme="laser-beam"] .holo__shine {
  background-image: linear-gradient(
    125deg,
    transparent 20%,
    rgba(119, 247, 212, 0.3) 35%,
    rgba(255, 255, 255, 0.95) 48%,
    rgba(255, 77, 109, 0.75) 54%,
    rgba(180, 40, 255, 0.35) 65%,
    transparent 80%
  );
  background-size: 320% 320%;
  background-position: calc(var(--holo-spec-x) * 2 - 50%) center;
}
.holo-card[data-theme="chameleon"] .holo__shine {
  background-image: repeating-linear-gradient(
      var(--holo-tilt-x),
      rgba(255, 30, 80, 0.6) 0%,
      rgba(180, 20, 200, 0.5) 20%,
      rgba(0, 230, 180, 0.6) 40%,
      rgba(255, 30, 80, 0.6) 60%
    ),
    radial-gradient(
      circle at var(--holo-spec-x) var(--holo-spec-y),
      rgba(255, 255, 255, 0.85) 0%,
      transparent 70%
    );
  background-size: 250% 250%, 150% 150%;
  background-position: var(--holo-spec-x) var(--holo-spec-y), center;
}
.holo-card[data-theme="cosmic"] .holo__shine {
  background-image: radial-gradient(2px 2px at 20px 30px, #ffffff, transparent),
    radial-gradient(2px 2px at 45px 80px, #ffb3c1, transparent),
    radial-gradient(1.5px 1.5px at 100px 50px, #ffffff, transparent),
    radial-gradient(2px 2px at 170px 130px, #77f7d4, transparent),
    repeating-linear-gradient(
      65deg,
      rgba(120, 100, 255, 0.4) 0%,
      rgba(255, 100, 200, 0.4) 20%,
      rgba(100, 230, 255, 0.4) 40%,
      rgba(120, 100, 255, 0.4) 60%
    );
  background-size: 70px 70px, 85px 85px, 110px 110px, 130px 130px, 300% 300%;
  background-position: var(--holo-spec-x) var(--holo-spec-y);
  filter: contrast(1.2);
}
.holo-card[data-theme="rainbow"] .holo__shine {
  background-image: repeating-linear-gradient(
      -45deg,
      hsla(340, 100%, 65%, 0.5) 0%,
      hsla(45, 100%, 65%, 0.5) 15%,
      hsla(150, 100%, 65%, 0.5) 30%,
      hsla(210, 100%, 75%, 0.6) 45%,
      hsla(280, 100%, 70%, 0.5) 60%,
      hsla(340, 100%, 65%, 0.5) 75%
    ),
    radial-gradient(
      circle at var(--holo-spec-x) var(--holo-spec-y),
      rgba(255, 255, 255, 0.95) 0%,
      rgba(120, 240, 255, 0.4) 35%,
      transparent 75%
    );
  background-size: 320% 320%, 160% 160%;
  background-position: var(--holo-spec-x) var(--holo-spec-y), center;
  mix-blend-mode: screen;
}
.holo-card[data-theme="obsidian"] .holo__shine {
  background-image: radial-gradient(2px 2px at 30px 40px, #ffd700, transparent),
    radial-gradient(2px 2px at 70px 110px, #ffffff, transparent),
    repeating-linear-gradient(
      110deg,
      rgba(218, 165, 32, 0.5) 0%,
      rgba(255, 255, 255, 0.7) 10%,
      rgba(50, 40, 20, 0.2) 20%,
      rgba(218, 165, 32, 0.5) 30%
    );
  background-size: 80px 80px, 90px 90px, 240% 240%;
  background-position: var(--holo-spec-x) var(--holo-spec-y);
  filter: contrast(1.4);
}
.holo-card[data-theme="sakura"] .holo__shine {
  background-image: repeating-linear-gradient(
      135deg,
      rgba(255, 42, 109, 0.5) 0%,
      rgba(255, 140, 180, 0.7) 15%,
      rgba(180, 20, 80, 0.3) 30%,
      rgba(255, 42, 109, 0.5) 45%
    ),
    radial-gradient(
      circle at var(--holo-spec-x) var(--holo-spec-y),
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 42, 109, 0.5) 30%,
      transparent 70%
    );
  background-size: 260% 260%, 150% 150%;
  background-position: var(--holo-spec-x) var(--holo-spec-y), center;
  filter: contrast(1.3);
}
.holo-card[data-theme="ice"] .holo__shine {
  background-image: linear-gradient(
    118deg,
    transparent 35%,
    rgba(255, 255, 255, 0.3) 46%,
    rgba(255, 255, 255, 0.8) 50%,
    rgba(255, 255, 255, 0.3) 54%,
    transparent 65%
  );
  background-size: 260% 260%;
  background-position: var(--holo-spec-x) var(--holo-spec-y);
  mix-blend-mode: overlay;
}
.holo-card[data-theme="snow"] .holo__shine {
  background-image: radial-gradient(3px 3px at 25px 25px, #ffffff, transparent),
    radial-gradient(2px 2px at 65px 75px, #77f7d4, transparent),
    radial-gradient(3px 3px at 115px 45px, #bde0fe, transparent),
    repeating-linear-gradient(
      45deg,
      rgba(255, 255, 255, 0.3) 0%,
      transparent 8px,
      rgba(162, 210, 255, 0.3) 16px
    );
  background-size: 80px 80px, 90px 90px, 120px 120px, 200% 200%;
  background-position: var(--holo-spec-x) var(--holo-spec-y);
  mix-blend-mode: screen;
  filter: brightness(1.2);
}
.holo-card[data-theme="baroque"] .holo__shine {
  background-image: repeating-conic-gradient(
      from 45deg at var(--holo-spec-x) var(--holo-spec-y),
      #d4af37 0deg,
      #fff275 20deg,
      #8a6a16 40deg,
      #d4af37 60deg
    ),
    radial-gradient(
      circle at var(--holo-spec-x) var(--holo-spec-y),
      rgba(255, 255, 255, 0.95) 0%,
      transparent 60%
    );
  background-size: 100% 100%, 140% 140%;
  mix-blend-mode: overlay;
  filter: contrast(1.5) brightness(1.1);
}
.holo-card[data-theme="nebula"] .holo__shine {
  background-image: radial-gradient(
      circle at var(--holo-spec-x) var(--holo-spec-y),
      #c77dff 0%,
      #7b2cbf 45%,
      #240046 80%,
      transparent 100%
    ),
    repeating-linear-gradient(
      115deg,
      rgba(255, 255, 255, 0.4) 0%,
      transparent 12px,
      rgba(224, 170, 255, 0.35) 24px
    );
  background-size: 150% 150%, 50px 50px;
  mix-blend-mode: color-dodge;
  filter: contrast(1.4);
}

/* ==========================================================================
   the console — lives on the detail page, not in the admin panel
   ========================================================================== */
.holo-console {
  display: flex;
  flex-direction: column;
  gap: 13px;
  min-height: 0;
  padding: 15px 15px 17px;
  overflow-y: auto;
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, calc(var(--glass-alpha, 0.05) + 0.02));
  border: 1px solid rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.holo-console__tag {
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
}
.holo-console__title {
  font-size: var(--fs-h3);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.24;
}
.holo-console__desc {
  font-size: var(--fs-xs);
  line-height: 1.55;
  color: var(--text-3);
}
.holo-console__group {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.holo-console__label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--text-2);
}
.holo-console__label b {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--accent);
  font-weight: 700;
}

.holo-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
}
.holo-grid--scroll {
  max-height: 178px;
  overflow-y: auto;
  padding-right: 4px;
}
.holo-grid--wide {
  grid-column: 1 / -1;
}

.holo-opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 6px 9px;
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  color: var(--text-2);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  cursor: pointer;
  text-align: left;
  transition: background var(--dur-1), border-color var(--dur-1), color var(--dur-1);
}
.holo-opt:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.2);
}
.holo-opt[aria-pressed="true"] {
  background: hsl(var(--accent-h) 90% 60% / 0.22);
  border-color: hsl(var(--accent-h) 90% 72% / 0.55);
  color: var(--text-1);
  box-shadow: 0 0 12px hsl(var(--accent-h) 90% 60% / 0.22);
}
.holo-opt i {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 8.5px;
  color: var(--text-4);
}

.holo-slider {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.holo-slider > span {
  font-size: 9px;
  color: var(--text-4);
  white-space: nowrap;
}
.holo-slider input[type="range"] {
  flex: 1;
  accent-color: hsl(var(--accent-h) 90% 60%);
  cursor: pointer;
}

.holo-check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-xs);
  color: var(--text-2);
  cursor: pointer;
}
.holo-check input {
  accent-color: hsl(var(--accent-h) 90% 60%);
}

/* two columns: the modest card on the left, the console on the right. The
   viewer is the left pane and the console the right one, matching the
   reference layout. */
.viewer--holo {
  flex-direction: row;
  align-items: stretch;
  gap: 16px;
  padding-left: 12px;
}
.viewer--holo .viewer__stage {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  /* the card sits close to the console, like the reference print + panel pair,
     instead of floating in the middle of the empty pane */
  justify-content: flex-end;
  gap: 0;
  padding: 0 36px 0 0;
}
.viewer--holo .viewer__hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 8px;
  justify-content: center;
}
.viewer--holo .viewer__hint span {
  background: rgba(8, 9, 14, 0.55);
  border-radius: var(--r-pill);
  padding: 4px 12px;
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  backdrop-filter: blur(14px) saturate(150%);
}
.viewer--holo .viewer__frame {
  max-width: 100%;
  max-height: 100%;
}
.viewer--holo .holo-console {
  flex: 0 0 310px;
  width: 310px;
  align-self: center;
  max-height: calc(100% - 40px);
  margin: 20px 0;
  overflow-y: auto;
}

/* master switch off: console hides and the viewer goes back to one column, so
   the picture can use the whole pane again */
.viewer--holo.is-off {
  flex-direction: column;
  padding-left: 0;
}
.viewer--holo.is-off .holo-console {
  display: none;
}
/* switch off means the plain picture: no foil sheet, no rim, no caustic */
.viewer--holo.is-off .holo__shine,
.viewer--holo.is-off .holo__glare,
.viewer--holo.is-off .holo__border,
.viewer--holo.is-off .holo__ground {
  display: none;
}
.viewer--holo.is-off .holo-card {
  box-shadow: none;
  transform: none !important;
  overflow: visible;
}
.viewer--holo.is-off .holo__image img,
.viewer--holo.is-off .holo__image video {
  max-width: 100%;
  max-height: calc(100vh - 220px);
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(255, 255, 255, 0.08);
  border-radius: 14px;
}
.viewer--holo.is-off .viewer__frame {
  max-width: 100%;
}
.viewer--holo.is-off .viewer__media {
  max-width: 100%;
  max-height: calc(100vh - 220px);
}

@media (max-width: 1240px) {
  .viewer--holo .holo-console {
    flex-basis: 268px;
    width: 268px;
  }
  .holo-grid--scroll {
    max-height: 148px;
  }
}
@media (max-width: 980px) {
  .viewer--holo {
    flex-direction: column;
    padding-left: 0;
  }
  /* On a phone the sheet body scrolls, so the stage must size to the card
     instead of splitting a fixed height with the console — otherwise the card
     is taller than its 147px pane and the sheet bar clips it. */
  .viewer--holo {
    flex: 0 0 auto;
    height: auto;
    min-height: 0;
  }
  .viewer--holo .viewer__stage {
    flex: 0 0 auto;
    height: auto;
    min-height: 0;
    justify-content: center;
    padding: 54px 0 10px;
    overflow: visible;
  }
  .viewer--holo .holo-console {
    flex: 0 0 auto;
    width: 100%;
    max-height: 260px;
    margin: 8px 0;
  }
  .holo-grid--scroll {
    max-height: 118px;
  }
  /* no room for a floating hint next to the card on a phone, and the console
     already explains what the card is */
  .viewer--holo .viewer__hint {
    display: none;
  }
  /* 34vw is meant for a side-by-side layout; once the card has the row to
     itself the picture should actually be readable on a phone */
  .holo__image img,
  .holo__image video {
    max-width: min(430px, 78vw);
    max-height: min(470px, 44vh);
  }
}

/* The standalone detail page keeps the console in the rail, outside .viewer,
   so the master switch is expressed on <html data-holo> instead. */
html[data-holo="off"] .holo-console {
  display: none;
}
html[data-holo="off"] .holo__shine,
html[data-holo="off"] .holo__glare,
html[data-holo="off"] .holo__border,
html[data-holo="off"] .holo__ground {
  display: none;
}
