/* ==========================================================================
   Yapped — base + the desk surface + the receipt object
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  font-family: var(--f-mono);
  font-size: var(--t-body);
  line-height: var(--line);
  color: var(--ink);
  background: var(--desk);
  /* A single soft pool of light above the receipt, then vignette. Not decoration —
     it makes the paper read as a lit physical object. */
  background-image:
    radial-gradient(100% 55% at 50% 0%, var(--desk-lift) 0%, transparent 62%);
  background-attachment: fixed;
  font-variant-numeric: tabular-nums;
  overflow-x: hidden;
}

/* Desk grain — inline SVG turbulence, no network request */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.28'/%3E%3C/svg%3E");
}

h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
button { font: inherit; color: inherit; border: 0; background: none; cursor: pointer; }
img, canvas { max-width: 100%; display: block; }

:focus-visible {
  outline: 2px solid var(--highlighter);
  outline-offset: 3px;
  border-radius: 1px;
}

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

/* ---- Stage ------------------------------------------------------------- */

.stage {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: start center;
  min-height: 100dvh;
  padding: var(--s-5) var(--s-3) var(--s-6);
}

/* ---- The receipt: a physical object on the desk ------------------------ */

/* The shell carries the shadow as a FILTER so it follows the torn edges.
   box-shadow would draw a rectangle behind the perforations and kill the effect. */
.receipt-shell {
  width: 100%;
  max-width: var(--receipt-w);
  filter:
    drop-shadow(0 1px 1px oklch(0% 0 0 / 0.12))
    drop-shadow(0 8px 16px oklch(0% 0 0 / 0.24))
    drop-shadow(0 26px 44px oklch(0% 0 0 / 0.28));
}

.receipt {
  --scallop: 7px;
  --scallop-h: 9px;
  position: relative;
  container-type: inline-size;   /* display type scales to the receipt, not the viewport */
  width: 100%;
  background: var(--paper);
  color: var(--ink);
  transition: background var(--d-calm) var(--ease), color var(--d-calm) var(--ease);

  /* Punch half-circles out of the top and bottom edges: torn receipt stock. */
  --tear-top:    radial-gradient(circle at 50% 0,    transparent 0 var(--scallop), #000 calc(var(--scallop) + 0.5px));
  --tear-bottom: radial-gradient(circle at 50% 100%, transparent 0 var(--scallop), #000 calc(var(--scallop) + 0.5px));
  mask-image: var(--tear-top), linear-gradient(#000 0 0), var(--tear-bottom);
  mask-size:
    calc(var(--scallop) * 2) var(--scallop-h),
    100% calc(100% - var(--scallop-h) * 2),
    calc(var(--scallop) * 2) var(--scallop-h);
  mask-position: top left, left var(--scallop-h), bottom left;
  mask-repeat: repeat-x, no-repeat, repeat-x;
}

/* Thermal paper texture + the faint vertical sheen of a printed roll */
.receipt::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
  opacity: 0.55;
  background-image:
    linear-gradient(90deg,
      oklch(0% 0 0 / 0.05) 0%, transparent 6%,
      transparent 94%, oklch(0% 0 0 / 0.05) 100%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23p)' opacity='0.14'/%3E%3C/svg%3E");
}

/* Spacers that reserve the torn-edge band; the mask on .receipt does the cutting. */
.receipt-tear { height: var(--scallop-h); }

.receipt-body { padding: var(--s-4) var(--s-3) var(--s-4); }

/* ---- Receipt primitives ------------------------------------------------ */

.rule {
  border: 0;
  border-top: 1px dashed var(--rule);
  margin: var(--s-3) 0;
}
.rule--solid { border-top-style: solid; }
.rule--heavy { border-top: 2px solid var(--ink); opacity: 0.8; }

.meta {
  font-size: var(--t-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--fade);
}

.row {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
  font-size: var(--t-sm);
}
/* Labels must not wrap — a wrapped label breaks the dot-leader alignment,
   which is the whole typographic conceit of a receipt. */
.row > span:first-child { white-space: nowrap; }
/* Dot leaders — the receipt's defining typographic move */
.row__dots {
  flex: 1;
  border-bottom: 1px dotted var(--rule);
  transform: translateY(-3px);
  min-width: var(--s-3);
}
.row__val { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* A pencilled underline, not a highlighter swipe. Quieter, more deliberate. */
.mark {
  background: linear-gradient(to bottom, var(--accent-wash) 0 100%) no-repeat;
  background-size: 100% 0.42em;
  background-position: 0 88%;
  padding-inline: 0.1em;
  box-decoration-break: clone;
}

.stamp-txt { color: var(--stamp); }

/* ---- Print-in animation ------------------------------------------------ */
/* Each line is revealed with a mechanical downward wipe + a micro jitter,
   staggered by --i. This is the product's signature moment. */

.print > * {
  animation: print-line var(--d-base) var(--ease-mech) both;
  animation-delay: calc(var(--i, 0) * var(--print-line));
}

@keyframes print-line {
  from { opacity: 0; clip-path: inset(0 0 100% 0);            transform: translateY(-2px); }
  60%  { opacity: 1; }
  /* Ends OUTSIDE the box on every side so tall glyphs (a 6.5rem serif numeral
     on a 0.82 line-height) are never sheared by the wipe once it completes. */
  to   { opacity: 1; clip-path: inset(-50% -50% -50% -50%);   transform: translateY(0); }
}

/* The print head sweeping across the paper */
.printhead {
  position: absolute;
  left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--ink-soft) 20%, var(--ink-soft) 80%, transparent);
  opacity: 0.55;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .print > * { animation: none; }
  .printhead { display: none; }
}

/* Belt and braces: nothing may widen the page horizontally. A single overflowing
   child otherwise drags the entire receipt out of frame. */
html { overflow-x: clip; }

/* ══════════════════════════ DESKTOP ═══════════════════════════════════════
   The receipt stays 26rem at every width — it IS the share artifact, and what
   you see has to be what you screenshot. Widening it would desync the share
   card and break the metaphor.

   So the desktop work is FRAMING, not redesign. Everything below sits behind
   a min-width query; the phone layout is byte-identical to before.
   ════════════════════════════════════════════════════════════════════════ */

@media (min-width: 64rem) {
  /* The receipt grows a little, but nowhere near the viewport. */
  :root { --receipt-w: 30rem; }

  /*
   * Landing: two columns. The export guide used to sit far below the fold,
   * and export friction is the biggest drop-off in the funnel — desktop has
   * the room to show the pitch and the instructions at the same time.
   */
  .receipt-shell:has(.deck) { max-width: 62rem; }

  .deck {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0 var(--s-4);
    align-items: start;
  }

  /* A printed gutter between the columns, in keeping with the paper. */
  .deck__do {
    border-left: 1px dashed var(--rule-c, currentColor);
    padding-left: var(--s-4);
  }

  /* The hook can breathe at this width. */
  .deck__ask .hook { font-size: clamp(3rem, 5.5vw, 4.5rem); }

  /* Drop the rule that only existed to separate stacked sections. */
  .deck__ask > .rule:last-child,
  .deck__do  > .rule:last-child { display: none; }
}

@media (min-width: 64rem) and (prefers-reduced-motion: no-preference) {
  .deck__do { animation: deck-in 420ms cubic-bezier(0.16, 1, 0.3, 1) both 120ms; }
  @keyframes deck-in { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; } }
}
