/* realism.css - wear on the paper and staging on a surface.
 * Two independent layers:
 *   .rc-wear  overlays inside the receipt (fade, yellowing, creases, stains)
 *   .rm-scene wrapper around the receipt (surface, light, camera)
 * Nothing here changes a number, it only changes how the paper looks.
 * Loaded after receipt.css so the ink and paper variables already exist. */

/* ============================ wear on the paper ============================ */
.rc-wear {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  overflow: hidden;
  border-radius: inherit;
}

.rc-wear > i {
  position: absolute;
  inset: 0;
  display: block;
}

/* ---- thermal ink fade: a veil in the paper colour, heavier where a thumb
   ---- and the heat of a car window would have hit it ---- */
.w-fade {
  opacity: var(--fade, 0);
  background-color: color-mix(in srgb, var(--paper) 58%, transparent);
  background-image:
    radial-gradient(ellipse 68% 34% at 76% 24%, color-mix(in srgb, var(--paper) 92%, transparent), transparent 72%),
    radial-gradient(ellipse 52% 26% at 18% 68%, color-mix(in srgb, var(--paper) 78%, transparent), transparent 74%),
    linear-gradient(186deg,
      color-mix(in srgb, var(--paper) 90%, transparent) 0%,
      transparent 19%, transparent 71%,
      color-mix(in srgb, var(--paper) 84%, transparent) 100%);
}

/* ---- yellowing: warm tint that pools at the edges, like every receipt that
   ---- has spent a summer in a drawer ---- */
.w-age {
  opacity: var(--age, 0);
  mix-blend-mode: multiply;
  background-color: rgba(196, 158, 92, .34);
  background-image:
    linear-gradient(90deg, rgba(150, 108, 48, .40) 0%, transparent 14%, transparent 86%, rgba(150, 108, 48, .40) 100%),
    linear-gradient(180deg, rgba(150, 108, 48, .34) 0%, transparent 9%, transparent 91%, rgba(150, 108, 48, .34) 100%),
    radial-gradient(ellipse 60% 30% at 30% 76%, rgba(126, 86, 34, .28), transparent 70%);
}

/* ---- handling: edge grime, soft rub marks, a few random creases ---- */
.w-handle {
  opacity: var(--wear, 0);
  mix-blend-mode: multiply;
  background-image:
    linear-gradient(90deg, rgba(58, 48, 34, .30) 0, transparent 5%, transparent 95%, rgba(58, 48, 34, .30) 100%),
    linear-gradient(180deg, rgba(58, 48, 34, .26) 0, transparent 3%, transparent 97%, rgba(58, 48, 34, .26) 100%),
    radial-gradient(ellipse 22% 12% at 88% 8%, rgba(52, 44, 32, .22), transparent 70%),
    radial-gradient(ellipse 26% 9% at 12% 94%, rgba(52, 44, 32, .20), transparent 72%);
}

/* Creases are drawn as light/dark pairs: a fold catches light on one side and
   shadows on the other, a single grey line reads as a printed rule instead. */
.w-crease {
  opacity: calc(var(--crumple, 0) * .85);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='560'%3E%3Cfilter id='c' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.013 0.021' numOctaves='4' seed='7' result='t'/%3E%3CfeDiffuseLighting in='t' lighting-color='%23ffffff' surfaceScale='3.2'%3E%3CfeDistantLight azimuth='128' elevation='56'/%3E%3C/feDiffuseLighting%3E%3C/filter%3E%3Crect width='420' height='560' filter='url(%23c)'/%3E%3C/svg%3E");
  background-size: 100% auto;
  filter: contrast(1.45);
}

/* ---- folds ---- */
.w-fold { opacity: 0; }

.fold-half .w-fold,
.fold-thirds .w-fold,
.fold-quarters .w-fold,
.fold-wallet .w-fold { opacity: .85; }

.fold-half .w-fold {
  background-image: linear-gradient(180deg,
    transparent calc(50% - 4px), rgba(0, 0, 0, .10) calc(50% - 4px),
    rgba(0, 0, 0, .16) 50%, rgba(255, 255, 255, .55) calc(50% + 1px),
    rgba(0, 0, 0, .06) calc(50% + 3px), transparent calc(50% + 5px));
}

.fold-thirds .w-fold {
  background-image:
    linear-gradient(180deg, transparent calc(33.33% - 4px), rgba(0, 0, 0, .10) calc(33.33% - 4px),
      rgba(0, 0, 0, .15) 33.33%, rgba(255, 255, 255, .50) calc(33.33% + 1px), transparent calc(33.33% + 4px)),
    linear-gradient(180deg, transparent calc(66.66% - 4px), rgba(0, 0, 0, .09) calc(66.66% - 4px),
      rgba(0, 0, 0, .14) 66.66%, rgba(255, 255, 255, .46) calc(66.66% + 1px), transparent calc(66.66% + 4px));
}

.fold-quarters .w-fold {
  background-image:
    linear-gradient(180deg, transparent calc(25% - 3px), rgba(0, 0, 0, .09) calc(25% - 3px),
      rgba(0, 0, 0, .13) 25%, rgba(255, 255, 255, .44) calc(25% + 1px), transparent calc(25% + 3px)),
    linear-gradient(180deg, transparent calc(50% - 4px), rgba(0, 0, 0, .11) calc(50% - 4px),
      rgba(0, 0, 0, .17) 50%, rgba(255, 255, 255, .56) calc(50% + 1px), transparent calc(50% + 4px)),
    linear-gradient(180deg, transparent calc(75% - 3px), rgba(0, 0, 0, .09) calc(75% - 3px),
      rgba(0, 0, 0, .13) 75%, rgba(255, 255, 255, .44) calc(75% + 1px), transparent calc(75% + 3px));
}

/* A wallet fold creases the short way as well. */
.fold-wallet .w-fold {
  background-image:
    linear-gradient(180deg, transparent calc(50% - 4px), rgba(0, 0, 0, .11) calc(50% - 4px),
      rgba(0, 0, 0, .17) 50%, rgba(255, 255, 255, .55) calc(50% + 1px), transparent calc(50% + 4px)),
    linear-gradient(90deg, transparent calc(50% - 3px), rgba(0, 0, 0, .08) calc(50% - 3px),
      rgba(0, 0, 0, .13) 50%, rgba(255, 255, 255, .42) calc(50% + 1px), transparent calc(50% + 3px));
}

/* ---- stains ---- */
.w-stain {
  opacity: 0;
  mix-blend-mode: multiply;
  background-repeat: no-repeat;
  background-position: 68% 56%;
  background-size: var(--stain-px, 160px) var(--stain-px, 160px);
}

.stain-coffeeRing .w-stain,
.stain-coffeeSplash .w-stain,
.stain-grease .w-stain,
.stain-water .w-stain,
.stain-ink .w-stain { opacity: 1; }

/* The dark rim is the whole trick: coffee dries from the outside in. */
.stain-coffeeRing .w-stain {
  background-image:
    radial-gradient(circle at 50% 50%,
      rgba(150, 110, 60, .05) 0 35%,
      rgba(146, 102, 52, .09) 35% 43%,
      rgba(120, 74, 30, .20) 43% 46.5%,
      rgba(84, 44, 12, .52) 46.5% 48.8%,
      rgba(84, 44, 12, .18) 48.8% 50%,
      transparent 50.5%);
}

.stain-coffeeSplash .w-stain {
  background-image:
    radial-gradient(circle at 46% 48%, rgba(112, 66, 26, .30) 0 26%, rgba(112, 66, 26, .12) 26% 33%, transparent 34%),
    radial-gradient(circle at 74% 30%, rgba(112, 66, 26, .26) 0 8%, transparent 9%),
    radial-gradient(circle at 22% 70%, rgba(112, 66, 26, .22) 0 6%, transparent 7%),
    radial-gradient(circle at 80% 72%, rgba(112, 66, 26, .18) 0 4%, transparent 5%),
    radial-gradient(circle at 34% 22%, rgba(112, 66, 26, .16) 0 3%, transparent 4%);
}

/* Grease makes paper translucent rather than darker, so it stays very soft. */
.stain-grease .w-stain {
  background-image:
    radial-gradient(ellipse 46% 38% at 48% 52%, rgba(92, 74, 44, .17), rgba(92, 74, 44, .07) 62%, transparent 78%),
    radial-gradient(ellipse 22% 20% at 68% 38%, rgba(92, 74, 44, .13), transparent 74%);
}

.stain-water .w-stain {
  background-image:
    radial-gradient(ellipse 44% 40% at 50% 52%, rgba(146, 118, 68, .10) 0 62%, rgba(120, 92, 46, .26) 74%, rgba(120, 92, 46, .05) 80%, transparent 84%),
    radial-gradient(ellipse 26% 30% at 34% 40%, rgba(146, 118, 68, .12) 0 70%, rgba(120, 92, 46, .20) 82%, transparent 88%);
}

.stain-ink .w-stain {
  background-image:
    radial-gradient(ellipse 40% 12% at 50% 50%, rgba(28, 34, 78, .40), rgba(28, 34, 78, .12) 60%, transparent 78%),
    radial-gradient(ellipse 8% 5% at 78% 58%, rgba(28, 34, 78, .30), transparent 72%);
}

/* ---- print defects ---- */
.w-defect { opacity: 0; }

/* A cooling print head drops horizontal bands out of the image. */
.defect-lowInk .w-defect {
  opacity: 1;
  background-image:
    repeating-linear-gradient(180deg,
      transparent 0 7px,
      color-mix(in srgb, var(--paper) 62%, transparent) 7px 9px,
      transparent 9px 19px),
    linear-gradient(180deg, transparent 38%, color-mix(in srgb, var(--paper) 55%, transparent) 46%, transparent 54%);
}

/* Dead dots on the head leave vertical white tracks down the whole roll. */
.defect-streaks .w-defect {
  opacity: 1;
  background-image:
    repeating-linear-gradient(90deg,
      transparent 0 41px,
      color-mix(in srgb, var(--paper) 86%, transparent) 41px 42.2px,
      transparent 42.2px 97px),
    repeating-linear-gradient(90deg,
      transparent 0 133px,
      color-mix(in srgb, var(--paper) 70%, transparent) 133px 135px,
      transparent 135px 268px);
}

.defect-skew .rc-inner { transform: rotate(.5deg) translateX(1px); }
.defect-doubleStrike .rc-inner { text-shadow: .6px 0 0 currentColor, -.4px .4px 0 color-mix(in srgb, currentColor 55%, transparent); }
.defect-bleed .rc-inner { filter: blur(.4px) contrast(1.16); }

/* ---- crumple: the content is displaced, the shading is painted above it ---- */
.crumple-1 .rc-inner { filter: url(#rm-crumple1); }
.crumple-2 .rc-inner { filter: url(#rm-crumple2); }
.crumple-3 .rc-inner { filter: url(#rm-crumple3); }
.crumple-4 .rc-inner { filter: url(#rm-crumple4); }

/* Heavy handling rounds the corners and takes the hard edge off the sheet. */
.receipt.rm-worn { border-radius: calc(var(--wear, 0) * 5px); }

/* ============================ staging on a surface ============================ */
.rm-scene {
  --angle: 0deg;
  --tilt: 0deg;
  --shadow: .5;
  --grain: .2;
  --vignette: .3;
  --dof: 0px;
  --pad: 40px;

  position: relative;
  display: inline-block;
  padding: var(--pad) calc(var(--pad) * 1.15);
  perspective: 1400px;
  overflow: hidden;
  border-radius: 10px;
  isolation: isolate;
}

.rm-surface {
  position: absolute;
  inset: calc(var(--dof) * -3 - 20px);
  z-index: 0;
  filter: blur(var(--dof));
}

.rm-scene .rm-paper {
  position: relative;
  z-index: 1;
  transform: rotate(var(--angle)) rotateX(var(--tilt));
  transform-style: preserve-3d;
  filter:
    drop-shadow(0 calc(var(--shadow) * 3px) calc(var(--shadow) * 5px) rgba(0, 0, 0, calc(var(--shadow) * .55)))
    drop-shadow(0 calc(var(--shadow) * 22px) calc(var(--shadow) * 34px) rgba(0, 0, 0, calc(var(--shadow) * .42)));
}

/* The receipt already carries a CSS box shadow for the plain preview. Inside a
   scene the drop-shadow above does that job, and both together read as fog. */
.rm-scene .receipt { box-shadow: none; margin-bottom: 0; }

.rm-light {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(ellipse 78% 62% at 50% 44%, transparent 42%, rgba(0, 0, 0, calc(var(--vignette) * .95)) 100%);
}

.rm-grain {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: var(--grain);
  mix-blend-mode: overlay;
  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='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.62'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}

/* ---- surfaces ----
   Photographs, not gradients. Three of them, cropped square and reused for
   both the preview and the canvas export so the two agree. They are loaded on
   demand rather than precached: nobody who only wants a printed receipt should
   pay half a megabyte for tabletops they never open. */
.rm-surface {
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

.surf-wood-dark .rm-surface { background-image: url("/receipt-maker/assets/surfaces/wood-dark.jpg"); }
.surf-wood-light .rm-surface { background-image: url("/receipt-maker/assets/surfaces/wood-light.jpg"); }
.surf-marble .rm-surface { background-image: url("/receipt-maker/assets/surfaces/marble.jpg"); }

/* Something to look at while the photograph decodes. */
.surf-wood-dark .rm-surface { background-color: #4a3526; }
.surf-wood-light .rm-surface { background-color: #cbab84; }
.surf-marble .rm-surface { background-color: #e8e6e2; }

/* ---- light ----
   The photographs already carry their own light, so these only add the part
   that belongs to the receipt: where the sun comes from and how hard it is. */
.light-soft .rm-light {
  background:
    linear-gradient(118deg, rgba(255, 250, 238, .22) 0%, rgba(255, 250, 238, .03) 32%, transparent 52%),
    linear-gradient(298deg, rgba(12, 16, 26, .20) 0%, transparent 44%),
    radial-gradient(ellipse 80% 64% at 46% 40%, transparent 44%, rgba(0, 0, 0, calc(var(--vignette) * .9)) 100%);
}

.light-warm .rm-light {
  background:
    radial-gradient(ellipse 58% 46% at 26% 20%, rgba(255, 196, 118, .26), transparent 72%),
    linear-gradient(202deg, transparent 42%, rgba(58, 28, 6, .24) 100%),
    radial-gradient(ellipse 80% 64% at 46% 44%, transparent 40%, rgba(22, 10, 0, calc(var(--vignette) * 1.05)) 100%);
}

.light-flash .rm-light {
  background:
    radial-gradient(ellipse 42% 36% at 50% 42%, rgba(255, 255, 255, .30), rgba(255, 255, 255, .04) 58%, transparent 70%),
    radial-gradient(ellipse 72% 58% at 50% 44%, transparent 32%, rgba(0, 0, 0, calc(var(--vignette) * 1.45)) 100%);
}

@media (max-width: 900px) {
  .rm-scene { padding: calc(var(--pad) * .55) calc(var(--pad) * .6); }
}

@media print {
  .rm-scene { padding: 0 !important; overflow: visible; perspective: none; }
  .rm-surface, .rm-light, .rm-grain { display: none !important; }
  .rm-scene .rm-paper { transform: none !important; filter: none !important; }
}
