/* flipfolio - default stylesheet
 * Themeable via the custom properties on .fg-root. Light and dark are both
 * first-class: `prefers-color-scheme` picks the default, and an explicit
 * `data-fg-theme="light" | "dark"` on .fg-root always wins.
 * Scoped to .fg-* classes; ships no global selectors. */

.fg-root {
  /* ── structural tokens ── */
  --fg-radius: 18px;
  --fg-perspective: 1200px;
  --fg-ease: cubic-bezier(0.2, 0, 0, 1);
  --fg-transition-transform: 700ms;
  --fg-transition-fade: 300ms;
  --fg-active-blur: 12px;
  --fg-scene-height: 440px;   /* stack canvas height; grid/carousel size in JS */
  --fg-gap: 1rem;             /* space between the scene and the dots row */
  /* label typography */
  --fg-label-size: 0.95rem;
  --fg-label-weight: 600;
  --fg-label-tracking: 0.01em;
  /* gradient front strength (item.gradient / setGradient) */
  --fg-gradient-opacity: 0.6;

  /* ── surface tokens (LIGHT is the base; dark overrides below) ──
     --fg-front / --fg-front-solid are normally set PER CARD by the engine,
     derived from each item's color. These are the no-color fallbacks. */
  --fg-folder-bg: #e8c96a;
  --fg-front: rgba(255, 255, 255, 0.55);
  --fg-front-solid: rgb(240, 236, 224);
  --fg-label: #1c1c1a;
  --fg-dot: #8a8a86;
  --fg-dot-active: #1c1c1a;
  --fg-shadow: 0 12px 32px rgba(30, 30, 30, 0.16), 0 4px 12px rgba(30, 30, 30, 0.08);
  --fg-folder-shadow: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.22));
  --fg-inset-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.35);
  --fg-inset-highlight-active: inset 0 1px 0 rgba(255, 255, 255, 0.45);
  /* peek: how far contents slide out of the folder */
  --fg-peek-shift: -46%;

  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--fg-gap);
}

/* Dark is the default only when the media query says so AND light isn't forced.
   Scoping with :not([data-fg-theme='light']) lets the one dark block below
   serve both "OS dark" and "forced dark", so no light block needs repeating. */
@media (prefers-color-scheme: dark) {
  .fg-root:not([data-fg-theme='light']) {
    --fg-folder-bg: #2a3a3a;
    --fg-front: rgba(90, 90, 90, 0.55);
    --fg-front-solid: rgb(115, 115, 115);
    --fg-label: #ffffff;
    --fg-dot: #9a9a9a;
    --fg-dot-active: #f4f4f2;
    --fg-shadow: 0 12px 32px rgba(0, 0, 0, 0.28), 0 4px 12px rgba(0, 0, 0, 0.12);
    --fg-inset-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.12);
    --fg-inset-highlight-active: inset 0 1px 0 rgba(255, 255, 255, 0.15);
  }
}
/* Forced dark, regardless of OS preference. */
.fg-root[data-fg-theme='dark'] {
  --fg-folder-bg: #2a3a3a;
  --fg-front: rgba(90, 90, 90, 0.55);
  --fg-front-solid: rgb(115, 115, 115);
  --fg-label: #ffffff;
  --fg-dot: #9a9a9a;
  --fg-dot-active: #f4f4f2;
  --fg-shadow: 0 12px 32px rgba(0, 0, 0, 0.28), 0 4px 12px rgba(0, 0, 0, 0.12);
  --fg-inset-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.12);
  --fg-inset-highlight-active: inset 0 1px 0 rgba(255, 255, 255, 0.15);
}

.fg-scene {
  position: relative;
  width: min(480px, 92vw); /* JS overrides per mode; this is the stack default */
  height: var(--fg-scene-height, 440px); /* stack default; grid/carousel set it in JS */
  perspective: var(--fg-perspective);
  transform-style: preserve-3d;
}

.fg-card {
  position: absolute;
  inset: 0 0 auto 0;
  width: 100%;
  /* 3/2 matches the engine's layout math (cardH = cardW * 2/3); the folder
     SVG stretches to fit via preserveAspectRatio="none". */
  aspect-ratio: 3 / 2;
  transition:
    transform var(--fg-transition-transform) var(--fg-ease),
    opacity var(--fg-transition-fade) var(--fg-ease);
  transform-origin: center bottom;
  backface-visibility: hidden;
  will-change: transform;
  cursor: pointer;
  contain: layout;
  outline: none;
}
.fg-card.is-active { cursor: default; }

/* ── drag: grab the active folder and throw it (stack mode) ── */
[data-fg-drag='fling'][data-fg-mode='stack'] .fg-card.is-active {
  cursor: grab;
  /* the gesture owns the pointer; without this, touch drags scroll the page */
  touch-action: none;
}
.fg-card--dragging,
[data-fg-drag='fling'][data-fg-mode='stack'] .fg-card--dragging {
  transition: none;
  cursor: grabbing;
}
/* One-frame teleport for a thrown folder rejoining the back of the pile
   (see the fling handler): transitioning that move would slide the card
   through the other folders' planes. */
.fg-card--snap { transition: none; }
/* While flying off, the fade must FINISH before the relayout snaps the
   card to its staging point: snapping a still-visible card mid-flight
   reads as a flicker. Opacity completes inside the 400ms timer; the
   transform launches hard and glides (a throw keeps its momentum). */
.fg-card--flung {
  transition:
    transform 560ms cubic-bezier(0.16, 1, 0.3, 1),
    opacity 340ms ease-out;
}
/* Dropping back into the pile: a quicker, softer settle than the default
   700ms shuffle, so the landing reads as its own beat. */
.fg-card--entering {
  transition:
    transform 620ms cubic-bezier(0.16, 1, 0.3, 1),
    opacity 320ms ease-out;
}
.fg-card:focus-visible {
  outline: 2px solid var(--fg-dot-active);
  outline-offset: 4px;
  border-radius: var(--fg-radius);
}

.fg-folder {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  filter: var(--fg-folder-shadow, drop-shadow(0 8px 24px rgba(0, 0, 0, 0.22)));
}

.fg-content {
  position: absolute;
  left: 5%;
  right: 5%;
  top: 12%;
  bottom: 30%;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: calc(var(--fg-radius) - 6px);
  transition:
    transform var(--fg-transition-fade) var(--fg-ease),
    opacity var(--fg-transition-fade) var(--fg-ease),
    box-shadow var(--fg-transition-fade) var(--fg-ease);
  z-index: 1;
}
.fg-image { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── peek: contents slide out of the folder ──
   data-fg-peek on the root: 'hover' (default), 'always', or 'off'.
   'off' keeps a subtle lift so hover still gives feedback. */
/* Empty interiors are inert: no box to lift, no shadow to cast. */
.fg-content:empty { display: none; }

[data-fg-peek='off'] .fg-card.is-active:hover .fg-content { transform: translateY(-8px); }
/* Peek moves the ACTIVE card's contents only. In 'hover' mode the pointer
   anywhere over the scene peeks the active folder (grid peeks the hovered
   card instead), and the slide-out is delayed a beat while the retract is
   instant, so navigating reads as retract, cycle, peek. No shadow on the
   content box itself: the box is transparent around whatever it holds, so a
   box shadow reads as a floating empty sheet. Contents bring their own. */
[data-fg-peek='hover']:not([data-fg-mode='grid']) .fg-scene:hover .fg-card.is-active .fg-content,
[data-fg-peek='hover'][data-fg-mode='grid'] .fg-card:hover .fg-content,
[data-fg-peek='always'] .fg-card.is-active .fg-content {
  transform: translateY(var(--fg-peek-shift));
  opacity: 1; /* decal cards hide their contents at rest; peek reveals them */
  transition-delay: 180ms;
}

/* Front panel - the folder's face. Sits over the lower 3/4 like the original
   (top 25%, hairline inset), radius 18. */
.fg-front {
  position: absolute;
  top: 25%;
  left: 4px;
  right: 4px;
  bottom: 4px;
  border-radius: var(--fg-radius);
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  padding: 0.9rem 1.1rem;
  z-index: 2;
  transition:
    background var(--fg-transition-fade) var(--fg-ease),
    box-shadow var(--fg-transition-fade) var(--fg-ease);
}

/* Behind folders: SOLID opaque front panel - no frosted glass off the active
   card (both a design rule and a perf rule: backdrop-filter never stacks). */
.fg-card:not(.is-active) .fg-front {
  background: var(--fg-front-solid);
  box-shadow: var(--fg-inset-highlight);
}
.fg-card.is-active .fg-front {
  background: var(--fg-front);
  backdrop-filter: blur(var(--fg-active-blur));
  -webkit-backdrop-filter: blur(var(--fg-active-blur));
  box-shadow: var(--fg-shadow), var(--fg-inset-highlight-active);
}

/* ── decal: the photo prints on the folder's front panel ──
   The back and tab keep their color, so the stack still reads as folders.
   The print carries its own lighting: a lip hairline where the front edge
   catches the light, a soft lamination sheen from the top left, and a label
   scrim along the bottom. */
.fg-card--decal .fg-front,
.fg-card--decal:not(.is-active) .fg-front,
.fg-card--decal.is-active .fg-front {
  background: var(--fg-front-solid);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.30);
}
.fg-card--decal.is-active .fg-front {
  box-shadow: var(--fg-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.30);
}
.fg-decal {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.fg-card--decal .fg-front::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    linear-gradient(115deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.04) 34%, rgba(255, 255, 255, 0) 52%),
    linear-gradient(to top, rgba(12, 12, 14, 0.62), rgba(12, 12, 14, 0) 42%);
}
.fg-card--decal .fg-label { color: #ffffff; position: relative; z-index: 1; }

/* ── gradient front: item.gradient (or setGradient) paints a CSS gradient
   across the front panel, over the frosted/solid surface but under the label
   and any peek contents. The frosted backdrop-filter still reads through. ── */
.fg-gradient {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  opacity: var(--fg-gradient-opacity, 0.6);
  pointer-events: none;
}
.fg-card--gradient .fg-label { position: relative; z-index: 1; }

.fg-label {
  /* Falls back to the theme label color when the card has no item.color;
     otherwise the engine sets --fg-label-on-color per card so the label
     stays readable against that folder's own front-panel brightness. */
  color: var(--fg-label-on-color, var(--fg-label));
  font-weight: var(--fg-label-weight, 600);
  font-size: var(--fg-label-size, 0.95rem);
  letter-spacing: var(--fg-label-tracking, 0.01em);
}

.fg-dots { display: flex; gap: 0.5rem; }
.fg-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 0;
  padding: 0;
  cursor: pointer;
  background: var(--fg-dot);
  opacity: 0.5;
  transition:
    opacity var(--fg-transition-fade) var(--fg-ease),
    transform var(--fg-transition-fade) var(--fg-ease),
    background var(--fg-transition-fade) var(--fg-ease);
}
.fg-dot:hover { opacity: 0.85; }
.fg-dot.is-active { background: var(--fg-dot-active); opacity: 1; transform: scale(1.35); }

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

@media (prefers-reduced-motion: reduce) {
  .fg-card, .fg-content, .fg-front, .fg-dot { transition-duration: 1ms; }
}
