/* ============================================================
   Objects — the photograph rendered onto real things.
   Everything is sized in cqw against the .stage container, so a
   mockup scales identically from a 74px chip to a full stage.
   One light source, upper left, for every object.
   ============================================================ */

.o { position: relative; }
/* max-width:100% from the base sheet would clamp the mug strips and the canvas
   wrap edge, both of which are deliberately far wider than their box. */
.o img { max-width: none; }
.o img, .o .fill {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.o__shadow {
  position: absolute; left: 50%; translate: -50% 0;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0,0,0,.55), transparent 72%);
  pointer-events: none;
}

/* ---------------- canvas: gallery wrap ---------------- */
.o-canvas { width: var(--w); aspect-ratio: var(--ar); filter: drop-shadow(1.2cqw 1.8cqw 2.4cqw rgba(0,0,0,.5)); }
.o-canvas__face { position: relative; width: 100%; height: 100%; overflow: hidden; }
/* the weave is what says "canvas" — a fine cross-hatch, barely there */
.o-canvas__face::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    repeating-linear-gradient(0deg,   rgba(255,255,255,.05) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg,  rgba(0,0,0,.10)       0 1px, transparent 1px 3px);
  mix-blend-mode: overlay;
  opacity: .8;
}
/* the wrapped right edge: the photo continues around the stretcher bar.
   A trapezoid, not a skew — this is the side of a box seen from slightly left,
   so the far edge foreshortens top and bottom. */
.o-canvas__side {
  position: absolute; top: 0; left: 100%; height: 100%; width: var(--d);
  overflow: hidden;
  clip-path: polygon(0 0, 100% 2.5%, 100% 97.5%, 0 100%);
  /* the photo, rendered at the face's width, showing only its rightmost slice —
     which is exactly what wraps around the stretcher bar */
  background-image: var(--img);
  background-size: var(--w) 100%;
  background-position: right center;
  background-repeat: no-repeat;
}
.o-canvas__side::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(0,0,0,.30), rgba(0,0,0,.68));
}

/* ---------------- framed print ---------------- */
.o-framed {
  width: var(--w);
  padding: var(--fw);
  background: linear-gradient(145deg, #2A2118 0%, #17120C 48%, #241C13 100%);
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.07),
    inset 0 0 0 var(--fw) rgba(0,0,0,.28),
    1.2cqw 2cqw 3cqw rgba(0,0,0,.55);
}
.o-framed__mat {
  padding: var(--mat);
  background: linear-gradient(160deg, #EFE8DA, #D9D0BE);
  /* the bevel cut in the mat board */
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.10);
  position: relative;
}
.o-framed__win {
  position: relative; aspect-ratio: var(--ar); overflow: hidden;
  box-shadow:
    0 0 0 .28cqw #FBF7EE,                 /* the white bevel edge */
    inset .3cqw .3cqw .7cqw rgba(0,0,0,.42);
}
/* glass: one soft raking reflection, nothing more */
.o-framed__glass {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(112deg,
    rgba(255,255,255,.11) 0%, rgba(255,255,255,.03) 22%,
    transparent 44%, transparent 100%);
  mix-blend-mode: screen;
}

/* ---------------- metal print (float mounted) ---------------- */
.o-metal {
  width: var(--w); aspect-ratio: var(--ar);
  position: relative;
  box-shadow: 1.4cqw 2.2cqw 2.6cqw rgba(0,0,0,.62);
}
.o-metal img { filter: saturate(1.14) contrast(1.07) brightness(1.03); }
.o-metal__sheen {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(118deg,
    transparent 30%, rgba(255,255,255,.16) 44%,
    rgba(255,255,255,.05) 52%, transparent 62%);
  mix-blend-mode: screen;
}
.o-metal__edge {
  position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.22);
}

/* ---------------- paper print ---------------- */
.o-print {
  width: var(--w);
  padding: var(--bord);
  background: linear-gradient(168deg, #F6F1E6 0%, #E7DFD0 100%);
  box-shadow: .8cqw 1.4cqw 2.2cqw rgba(0,0,0,.45);
  position: relative;
}
.o-print__win { aspect-ratio: var(--ar); overflow: hidden; box-shadow: 0 0 0 1px rgba(0,0,0,.12); }
.o-print::after {   /* the sheet lifts very slightly at the corner */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(200deg, transparent 82%, rgba(0,0,0,.10) 100%);
}

/* ---------------- mug: a real cylinder ---------------- */
.o-mug { width: 56cqw; height: 46cqw; position: relative; }
.o-mug__handle {
  position: absolute; right: 1cqw; top: 12cqw;
  width: 13cqw; height: 20cqw;
  border: 3.6cqw solid #E9E4DB;
  border-radius: 0 50% 50% 0 / 0 50% 50% 0;
  border-left-color: transparent;
  box-shadow: .5cqw .5cqw 1cqw rgba(0,0,0,.35), inset -.3cqw 0 .6cqw rgba(0,0,0,.20);
}
.o-mug__body {
  position: absolute; left: 4cqw; top: 4cqw;
  width: 42cqw; height: 38cqw;
  border-radius: 0 0 1.4cqw 1.4cqw;
  background: #EDE8E0;
  overflow: hidden;
  box-shadow: 0 1.6cqw 2.4cqw rgba(0,0,0,.42);
}
.o-mug__band {          /* the printable wrap area — starts below the rim */
  position: absolute; inset: 7.4cqw 0 2.4cqw 0;
  overflow: hidden;
}
.o-mug__strip { position: absolute; top: 0; height: 100%; overflow: hidden; }
.o-mug__strip img { position: absolute; top: 0; }
/* cylinder shading: darkening as the surface turns away, one specular band */
.o-mug__shade {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg,
    rgba(0,0,0,.58) 0%, rgba(0,0,0,.30) 8%, rgba(0,0,0,.05) 20%,
    rgba(255,255,255,.16) 32%, rgba(255,255,255,.03) 44%,
    rgba(0,0,0,.06) 60%, rgba(0,0,0,.32) 84%, rgba(0,0,0,.62) 100%);
}
.o-mug__rim {           /* the lip, seen slightly from above */
  position: absolute; left: 0; top: -.1cqw;
  width: 42cqw; height: 7cqw;
  border-radius: 50%;
  background: linear-gradient(180deg, #FBF8F3, #D6CFC4);
  box-shadow: inset 0 -.4cqw .8cqw rgba(0,0,0,.18);
}
.o-mug__well {          /* the dark interior */
  position: absolute; left: 1.6cqw; top: .9cqw;
  width: 38.8cqw; height: 5.2cqw;
  border-radius: 50%;
  background: radial-gradient(60% 130% at 50% 0%, #4A423A, #241F19 70%);
}
.o-mug__foot {
  position: absolute; left: 0; bottom: -.4cqw;
  width: 42cqw; height: 3.4cqw;
  border-radius: 50%;
  background: linear-gradient(180deg, rgba(0,0,0,.25), rgba(0,0,0,.05));
}

/* ---------------- cloth goods: tote, tee, pillow ---------------- */
.o-cloth { width: var(--w); }
.o-cloth svg { width: 100%; height: auto; display: block;
  filter: drop-shadow(1cqw 1.6cqw 2cqw rgba(0,0,0,.5)); }

/* ---------------- phone case ---------------- */
.o-case {
  width: 24cqw; aspect-ratio: 1 / 2.03;
  position: relative;
  border-radius: 3.2cqw;
  overflow: hidden;
  background: #0D0B09;
  box-shadow: 1cqw 1.8cqw 2.6cqw rgba(0,0,0,.6), inset 0 0 0 .35cqw rgba(255,255,255,.14);
}
.o-case__cam {
  position: absolute; left: 1.6cqw; top: 1.6cqw;
  width: 9cqw; height: 9cqw;
  border-radius: 2.2cqw;
  background: rgba(18,16,14,.82);
  box-shadow: inset 0 0 0 .2cqw rgba(255,255,255,.16);
  display: grid; grid-template-columns: 1fr 1fr; gap: .5cqw;
  padding: 1cqw;
}
.o-case__lens {
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #5C5A57, #131211 62%);
  box-shadow: inset 0 0 0 .18cqw rgba(255,255,255,.22);
}
.o-case__gloss {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(120deg, rgba(255,255,255,.18) 0%, transparent 34%);
  mix-blend-mode: screen;
}

/* ---------------- notebook ---------------- */
.o-notebook { width: 40cqw; aspect-ratio: 1 / 1.36; position: relative;
  filter: drop-shadow(1.2cqw 1.8cqw 2.4cqw rgba(0,0,0,.55)); }
.o-notebook__pages {   /* the page block peeking out on the right */
  position: absolute; right: -1cqw; top: 1.2cqw; bottom: .8cqw; width: 1.4cqw;
  border-radius: 0 .4cqw .4cqw 0;
  background: repeating-linear-gradient(180deg, #D8D2C6 0 .2cqw, #ADA595 .2cqw .4cqw);
  box-shadow: inset -.2cqw 0 .4cqw rgba(0,0,0,.28);
}
.o-notebook__cover {
  position: absolute; inset: 0; overflow: hidden;
  border-radius: .4cqw 1cqw 1cqw .4cqw;
}
.o-notebook__spine {
  position: absolute; left: 0; top: 0; bottom: 0; width: 3.4cqw;
  background: linear-gradient(90deg, rgba(0,0,0,.55), rgba(0,0,0,.16) 55%, rgba(255,255,255,.06));
}
.o-notebook__gloss {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, rgba(255,255,255,.10) 0%, transparent 38%);
  mix-blend-mode: screen;
}
.o-notebook__band {    /* elastic closure, sitting proud of the cover */
  position: absolute; right: 4.5cqw; top: -.8cqw; bottom: -.8cqw; width: 1.3cqw;
  background: linear-gradient(90deg, #1B1815, #3E3830 45%, #1B1815);
  box-shadow: -.35cqw 0 .6cqw rgba(0,0,0,.45);
  border-radius: .2cqw;
}

/* ---------------- puzzle ---------------- */
.o-puzzle { width: var(--w); aspect-ratio: var(--ar); position: relative;
  filter: drop-shadow(1cqw 1.6cqw 2.2cqw rgba(0,0,0,.5)); }
.o-puzzle__img { position: absolute; inset: 0; overflow: hidden; }
.o-puzzle__cut { position: absolute; inset: 0; }
.o-puzzle__cut path {
  fill: none; stroke: rgba(0,0,0,.34); stroke-width: .55;
  vector-effect: non-scaling-stroke;
}
.o-puzzle__loose {     /* one piece lifted off the board */
  position: absolute; overflow: hidden;
  filter: drop-shadow(.5cqw .9cqw 1cqw rgba(0,0,0,.6));
}

/* ---------------- coasters ---------------- */
.o-coasters { width: 62cqw; height: 46cqw; position: relative; }
.o-coaster {
  position: absolute; width: 26cqw; aspect-ratio: 1;
  border-radius: .8cqw;
  overflow: hidden;
  background: #C8B79A;
  box-shadow: 0 1.2cqw 1.8cqw rgba(0,0,0,.5), inset 0 0 0 .5cqw #C8B79A;
}
.o-coaster img { border-radius: .3cqw; }
.o-coaster::after {    /* cork edge + a little sheen */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(125deg, rgba(255,255,255,.12), transparent 40%);
  mix-blend-mode: screen;
}
