/* ==========================================================================
   GLOAM 5702
   Palette pulled from the frame artwork: near-black void, charcoal wall,
   amber/gold gilding, ember. Nothing outside that world.
   ========================================================================== */

:root {
  /* Frame photograph geometry (832 x 1248). Change these if the art changes. */
  --frame-aspect: 832 / 1248;

  /* The inner glass opening, as % of the frame image. Measured from the art.
     Anything placed in .glass uses these; tweak to re-seat the opening. */
  --glass-left: 26.5%;
  --glass-top: 27%;
  --glass-width: 47%;
  --glass-height: 44%;

  /* Colour world */
  --void:      #060504;
  --wall-0:    #0c0a08;
  --wall-1:    #050403;
  --charcoal:  #14110d;
  --gild:      #b4863f;
  --gild-dim:  #7a5a2c;
  --ember:     #d98a3e;
  --ash:       #b7ab97;   /* dim warm text */

  /* Motion tuning (idle drift / flicker). */
  --ease-slow: cubic-bezier(.4, .0, .2, 1);
}

* { box-sizing: border-box; }

/* The [hidden] attribute must win over component `display` values below
   (e.g. .sequence / .fragment-view use display:grid). Without this they stay
   laid out at opacity 0 and swallow every click/tap across the page. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--wall-1);
  color: var(--ash);
  font-family: "Iowan Old Style", "Palatino Linotype", Palatino, "Times New Roman", Georgia, serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overscroll-behavior: none;
}

body { overflow: hidden; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   Stage + atmosphere
   -------------------------------------------------------------------------- */
.stage {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--wall-1);
  isolation: isolate;
}

/* Charcoal wall with a heavy vignette, plus a static grain via SVG noise. */
.wall {
  position: absolute; inset: -5%;
  z-index: 0;
  background:
    radial-gradient(120% 90% at 50% 38%, #17130e 0%, #0a0806 46%, #040302 100%);
}
.wall::after {
  /* film grain */
  content: "";
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: .05;
  mix-blend-mode: overlay;
  pointer-events: none;
}

/* Cold shaft of light falling from above, echoing the photograph. */
.beam {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(60% 44% at 50% -6%, rgba(190,180,150,.10), rgba(190,180,150,0) 60%);
  opacity: .8;
}

/* --------------------------------------------------------------------------
   The frame
   -------------------------------------------------------------------------- */
.frame-wrap {
  position: relative;
  z-index: 2;
  /* Fit the portrait frame within the viewport, leaving room below for the
     placard; camera never reframes. Height-driven so the signature never clips.
     128vw caps the width to ~85vw on narrow screens. */
  height: min(80vh, 128vw);
  width: auto;
  aspect-ratio: var(--frame-aspect);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.frame {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: var(--frame-aspect);
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  /* Base transform target for idle drift. */
  transform: translate3d(0,0,0);
  transition: filter 1.2s var(--ease-slow);
}
.frame:focus-visible {
  outline: 1px solid rgba(180,134,63,.5);
  outline-offset: 6px;
}

.frame-art {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  z-index: 3;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  filter: brightness(1);
  transition: filter 1.6s var(--ease-slow), transform 3.4s var(--ease-slow);
  will-change: filter, transform;
}

/* --------------------------------------------------------------------------
   Behind the glass
   -------------------------------------------------------------------------- */
.glass {
  position: absolute;
  left: var(--glass-left);
  top: var(--glass-top);
  width: var(--glass-width);
  height: var(--glass-height);
  /* Above the frame photo: its interior is opaque, so anything meant to live
     'behind the glass' must sit over it, contained within the opening. */
  z-index: 5;
  overflow: hidden;
}

/* Just an edge-shadow to seat content; the photograph's own painted interior
   remains the backdrop, so its cracked texture is preserved. */
.glass-void {
  position: absolute; inset: 0;
  background: radial-gradient(120% 120% at 50% 42%, transparent 42%, rgba(3,2,1,.55) 100%);
  pointer-events: none;
}

/* The watcher: an eye that surfaces out of the dark. Screen blend so only the
   light of it emerges from the void — never a hard cut-in. */
.watcher {
  position: absolute;
  inset: -8%;
  width: 116%; height: 116%;
  object-fit: cover;
  mix-blend-mode: screen;
  opacity: 0;
  filter: brightness(.55) saturate(.68) contrast(1.02) blur(1.3px);
  transform: scale(1.04);
  transition: opacity 2.8s var(--ease-slow), transform 6s var(--ease-slow), filter 2.8s var(--ease-slow);
  pointer-events: none;
}

/* Faint reflection on the glass surface. */
.glass-sheen {
  position: absolute; inset: 0;
  background: linear-gradient(150deg, rgba(200,190,160,.05) 0%, rgba(200,190,160,0) 30%);
  mix-blend-mode: screen;
  opacity: .5;
  pointer-events: none;
}

/* The ambient stirrings (watcher surfacing, light flicker, drift) are driven
   as one-shot Web Animations from gloam.js, so nothing loops here. These
   elements just define the still baseline they return to. */

/* --------------------------------------------------------------------------
   Placard signature
   -------------------------------------------------------------------------- */
.placard {
  position: absolute;
  top: calc(100% + clamp(14px, 3vh, 30px));
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  text-align: center;
  line-height: 1.9;
  white-space: nowrap;
  transition: opacity 1.2s var(--ease-slow);
}
.wordmark {
  display: block;
  font-size: clamp(10px, 1.5vw, 13px);
  letter-spacing: .62em;
  text-indent: .62em;      /* balance the trailing letter-space */
  text-transform: lowercase;
  font-weight: 400;
  color: rgba(183,171,151,.42);
}
.sig {
  display: block;
  font-size: clamp(9px, 1.2vw, 11px);
  letter-spacing: .16em;
  font-style: italic;
  color: rgba(183,171,151,.24);
}

/* --------------------------------------------------------------------------
   The sequence takeover (deliberate; motion allowed)
   -------------------------------------------------------------------------- */
.sequence {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: #000;
  display: grid;
  place-items: center;
  opacity: 0;
  transition: opacity 1.1s ease;
}
.sequence.on { opacity: 1; }
.sequence-video {
  width: 100%;
  height: 100%;
  object-fit: contain;   /* letterbox in black; never crop the source of truth */
  background: #000;
}

/* Frame recedes as the sequence takes over. */
.stage[data-state="sequence"] .frame-wrap,
.stage[data-state="sequence"] .beam { opacity: 0; }
.frame-wrap { transition: opacity 1s ease; }

/* --------------------------------------------------------------------------
   Replay affordance (returning visitors only)
   -------------------------------------------------------------------------- */
.replay {
  position: fixed;
  right: clamp(12px, 3vw, 26px);
  bottom: clamp(12px, 3vh, 26px);
  z-index: 45;
  border: 0;
  background: transparent;
  color: rgba(183,171,151,.22);
  font: inherit;
  font-size: 10px;
  letter-spacing: .34em;
  text-transform: lowercase;
  cursor: pointer;
  transition: color .8s ease;
  -webkit-tap-highlight-color: transparent;
}
.replay:hover, .replay:focus-visible { color: rgba(217,138,62,.7); outline: none; }

/* --------------------------------------------------------------------------
   Fragments — post-sequence entry points. No labels, no grid.
   Faint embers adrift in the glass; each one is a way in.
   -------------------------------------------------------------------------- */
.fragments {
  position: absolute; inset: 0;
  z-index: 4;             /* above the void, still under the frame lip */
  opacity: 0;
  transition: opacity 2.4s var(--ease-slow);
  pointer-events: none;
}
.stage[data-state="threshold"] .fragments { opacity: 1; pointer-events: auto; }

.fragment {
  position: absolute;
  width: clamp(7px, 1.4vw, 12px);
  height: clamp(7px, 1.4vw, 12px);
  margin: calc(clamp(7px, 1.4vw, 12px) / -2) 0 0 calc(clamp(7px, 1.4vw, 12px) / -2);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(233,158,80,.98) 0%, rgba(190,140,66,.55) 42%, rgba(180,134,63,0) 74%);
  box-shadow: 0 0 8px 1px rgba(217,138,62,.35);
  cursor: pointer;
  opacity: .42;
  -webkit-tap-highlight-color: transparent;
  transition: transform .9s var(--ease-slow), opacity 1.6s var(--ease-slow), filter .9s ease;
}
@media (prefers-reduced-motion: no-preference) {
  .fragment { animation: ember calc(6s + var(--drift, 0s)) ease-in-out infinite; }
}
.fragment:hover, .fragment:focus-visible {
  outline: none;
  transform: scale(1.9);
  filter: drop-shadow(0 0 10px rgba(217,138,62,.85)) brightness(1.3);
}
@keyframes ember {
  0%, 100% { opacity: .38; transform: translate(0, 0) scale(1); }
  50%      { opacity: .72; transform: translate(0, -6%) scale(1.06); }
}

/* --------------------------------------------------------------------------
   Fragment view — what you find is that there is nothing yet.
   -------------------------------------------------------------------------- */
.fragment-view {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: clamp(20px, 6vh, 54px);
  background: radial-gradient(80% 80% at 50% 50%, #070605 0%, #010101 100%);
  text-align: center;
  opacity: 0;
  transition: opacity 1.4s ease;
}
.fragment-view.on { opacity: 1; }
.fragment-name {
  margin: 0;
  font-size: clamp(11px, 1.7vw, 15px);
  letter-spacing: .5em;
  text-indent: .5em;
  text-transform: lowercase;
  color: rgba(183,171,151,.5);
}
.fragment-body {
  margin: 0;
  font-style: italic;
  font-size: clamp(13px, 2.1vw, 18px);
  letter-spacing: .05em;
  color: rgba(183,171,151,.32);
}
.fragment-back {
  margin-top: clamp(10px, 4vh, 40px);
  border: 0;
  background: transparent;
  color: rgba(183,171,151,.28);
  font: inherit;
  font-size: 10px;
  letter-spacing: .34em;
  text-transform: lowercase;
  cursor: pointer;
  transition: color .8s ease;
}
.fragment-back:hover, .fragment-back:focus-visible { color: rgba(217,138,62,.72); outline: none; }

/* --------------------------------------------------------------------------
   Reduced motion: hold everything still. Dread from stillness, not effects.
   The deliberate click-sequence video is exempt (handled inline).
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .wall::after { opacity: .04; }
  .frame-art, .beam, .fragment { animation: none !important; }
  /* The ambient stirrings still fade the watcher in and out (opacity only,
     no movement — handled in gloam.js), which reads as presence, not motion. */
}
