/* ============================================================
   Our Meals
   ============================================================ */

:root {
  /* Paper is the good part — a touch warmer and brighter than before. */
  --paper:      #f8f2e6;
  --paper-deep: #ece0ca;

  /* The table it all sits on: back to the warm near-black. */
  --bg:         #171613;
  --bg-lift:    #201e19;

  /* Eucalyptus, not rust. Cooking, herbs, cream paper — and decidedly not
     the orange-on-black it was. */
  --accent:      #5d8367;
  --accent-deep: #456450;
  --accent-wash: rgba(93,131,103,.13);

  /* A quieter warm note, for the few places that want to be picked out. */
  --plum:       #8a5f6d;

  /* Something has gone wrong. Deliberately not the accent — an error in the
     same colour as the buttons reads as success and gets skimmed past. */
  --warn:       #a24552;
  --warn-wash:  rgba(162,69,82,.1);

  --ink:        #33302a;
  --ink-soft:   #71695b;
  --rule:       rgba(51,48,42,.16);

  --note-yellow: #f3d768;
  --note-pink:   #f2a9ab;
  --note-blue:   #a9c9d6;

  --hand:    'Caveat', 'Bradley Hand', cursive;
  /* Fraunces is soft and slightly wonky — it sits with handwriting far better
     than a slab or a monospace does. */
  --display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --body:    'Karla', ui-sans-serif, system-ui, sans-serif;

  --lift:    0 2px 4px rgba(0,0,0,.3), 0 8px 22px rgba(0,0,0,.34);
  --lift-lg: 0 6px 12px rgba(0,0,0,.36), 0 26px 60px rgba(0,0,0,.5);
}

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

html, body { margin: 0; min-height: 100%; }

body {
  font-family: var(--body);
  color: var(--ink);
  background: var(--bg);
  -webkit-tap-highlight-color: transparent;
}

.table {
  min-height: 100vh;
  min-height: 100dvh;
  padding: 0 0 2rem;
  background:
    radial-gradient(120% 90% at 50% 0%, var(--bg-lift), var(--bg) 68%);
  display: flex;
  flex-direction: column;
}

/* --- Header + view tabs --------------------------------------- */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem clamp(1rem, 4vw, 2.5rem) .9rem;
}

.brand {
  display: inline-flex;
  align-items: baseline;
  gap: .5rem;
  text-decoration: none;
  color: var(--paper);
}
.brand-text {
  font-family: var(--hand);
  font-size: clamp(1.7rem, 4vw, 2.4rem);
  font-weight: 700;
  line-height: 1;
}

.tabs { display: flex; gap: .4rem; }

.tab {
  font-family: var(--display);
  font-weight: 500;
  font-size: .9rem;
  letter-spacing: .005em;
  text-decoration: none;
  color: rgba(248,242,230,.58);
  background: rgba(248,242,230,.07);
  padding: .46rem 1.05rem;
  border-radius: 999px;
  transition: background .16s ease, color .16s ease;
}
.tab:hover { background: rgba(248,242,230,.14); color: rgba(248,242,230,.88); }

.tab.is-active {
  background: var(--paper);
  color: var(--ink);
  font-weight: 700;
}

.view { flex: 1; display: flex; flex-direction: column; }

/* ============================================================
   SCRAP VIEW
   ============================================================ */

.scrap {
  flex: 1;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(.4rem, 2vw, 1.4rem);
  padding: 0 clamp(.5rem, 2vw, 2rem);
}

.book-wrap { display: flex; flex-direction: column; align-items: center; gap: 1.1rem; width: 100%; }

.book {
  position: relative;
  width: min(96vw, 1020px);
  aspect-ratio: 3 / 2;
  perspective: 2200px;
  perspective-origin: 50% 45%;
  /* let vertical scrolling through, keep horizontal swipes for page turns */
  touch-action: pan-y;
}

.spread {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-radius: 4px;
  box-shadow: var(--lift-lg);
  overflow: hidden;
}

/* --- Paper ---------------------------------------------------- */

.paper, .page {
  background-color: var(--paper);
  background-image:
    radial-gradient(circle at 18% 22%, rgba(180,150,105,.10), transparent 42%),
    radial-gradient(circle at 82% 78%, rgba(150,120,80,.09), transparent 46%);
}

.page {
  position: relative;
  padding: clamp(1rem, 3.2vw, 2.2rem);
  overflow: hidden;
  /* A column, so the recipe can claim the leftover height and be clipped by
     the page rather than growing past it. */
  display: flex;
  flex-direction: column;
  /* the whole page is a writing surface */
  cursor: text;
}

.page-left  { box-shadow: inset -26px 0 34px -26px rgba(46,42,36,.5); }
.page-right { box-shadow: inset  26px 0 34px -26px rgba(46,42,36,.5); }

.page.is-placing { cursor: crosshair; }

/* --- Photo, title, date --------------------------------------- */

/* The frame is clipped to a torn edge, and clip-path clips descendants — so
   the tape and the resize grip live on this wrapper, outside the clip. */
.photo-slot {
  position: relative;
  width: 85%;
  margin: 0 auto .9rem;
  transform: rotate(-1.6deg);
  transition: transform .18s ease;
}
.photo-slot:hover { transform: rotate(-0.6deg) translateY(-3px); }

.photo-frame {
  position: relative;
  width: 100%;
  padding: 12px 12px 42px;
  background: #fffdf7;
  box-shadow: var(--lift);
  cursor: pointer;
  transition: box-shadow .18s ease;
  clip-path: polygon(
    1% 2%, 12% .6%, 24% 2.4%, 37% .4%, 51% 2.2%, 64% .5%, 78% 2.6%, 90% .8%, 99% 2.3%,
    98.5% 14%, 99.6% 27%, 98.2% 41%, 99.5% 55%, 98.4% 68%, 99.4% 82%, 98% 96%,
    88% 98.4%, 74% 99.6%, 61% 97.8%, 47% 99.5%, 33% 97.6%, 20% 99.4%, 8% 97.7%, 1.5% 98.6%,
    2% 85%, .6% 71%, 2.2% 57%, .5% 43%, 2.4% 29%, .8% 16%
  );
}

.photo-slot:hover .photo-frame { box-shadow: var(--lift-lg); }

/* No forced aspect: the crop dialog already decided the shape, so re-framing it
   here would throw that choice away. The height cap stops a tall crop shoving
   the title off the page — `contain` so it letterboxes rather than re-crops. */
.photo-frame img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 38vh;
  object-fit: contain;
  background: var(--paper-deep);
}

.photo-frame.is-empty {
  display: grid;
  place-items: center;
  min-height: 190px;
  background: repeating-linear-gradient(45deg, #f3ecdc 0 12px, #eee5d1 12px 24px);
}
.photo-frame.is-empty span { font-family: var(--hand); font-size: 1.4rem; color: #b3a68d; }

.tape {
  position: absolute;
  width: 92px; height: 28px;
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,.28) 0 6px, transparent 6px 12px),
    var(--tape-color, var(--note-blue));
  opacity: .82;
  box-shadow: 0 1px 3px rgba(46,42,36,.22);
  clip-path: polygon(3% 6%, 0 32%, 3% 58%, 0 84%, 4% 100%, 96% 96%, 100% 72%, 97% 46%, 100% 20%, 96% 2%);
}
.tape.tl { top: -13px; left: -20px; transform: rotate(-28deg); }
.tape.br { bottom: 20px; right: -22px; transform: rotate(-24deg); --tape-color: var(--note-pink); }

/* corner grip for scaling the cover photo */
.photo-resize {
  position: absolute;
  right: -11px;
  bottom: 30px;
  width: 22px; height: 22px;
  border: none;
  border-radius: 50%;
  background: var(--plum);
  box-shadow: 0 2px 6px rgba(0,0,0,.32);
  cursor: nwse-resize;
  opacity: 0;
  transition: opacity .16s ease;
  touch-action: none;
  z-index: 4;
}
.photo-resize::before {
  content: '';
  position: absolute;
  inset: 7px;
  border-right: 2px solid var(--paper);
  border-bottom: 2px solid var(--paper);
}
.photo-slot:hover .photo-resize,
.photo-slot.is-resizing .photo-resize { opacity: 1; }
.photo-slot.is-resizing { transform: rotate(-1.6deg); }

.meal-title {
  margin: 0;
  font-family: var(--hand);
  font-weight: 700;
  font-size: clamp(1.9rem, 4.2vw, 2.9rem);
  line-height: 1.02;
  transform: rotate(-.7deg);
  cursor: text;
}

.meal-date {
  margin: .4rem 0 0;
  font-family: var(--body);
  font-size: .88rem;
  letter-spacing: .02em;
  color: var(--accent);
}

.meal-tags { margin-top: .6rem; display: flex; flex-wrap: wrap; gap: .35rem; }
.tag {
  font-family: var(--body);
  font-size: .8rem;
  letter-spacing: .01em;
  color: #4f5c42;
  background: rgba(124,139,107,.2);
  border: 1px solid rgba(124,139,107,.42);
  border-radius: 2px;
  padding: .18rem .42rem;
}

/* --- Recipe card, tucked under the photo ----------------------- */

/* Just writing on the paper — no frame, no tint. It fills whatever room is
   left under the title and stops at the foot of the page. */
.recipe-card {
  position: relative;
  /* basis 0 with min-height 0 so it shrinks to the space left rather than
     being floored at its content height — that floor is what killed the
     ellipsis and let a long recipe overrun the page. */
  flex: 1 1 0;
  min-height: 0;
  margin-top: .9rem;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  text-align: left;
  width: 100%;
  color: var(--ink);
  font: inherit;
  overflow: hidden;
  cursor: pointer;
}

.recipe-peek {
  font-family: var(--hand);
  font-size: 1.12rem;
  line-height: 1.3;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.recipe-peek > *:first-child { margin-top: 0; }
.recipe-peek p { margin: 0 0 .5em; }
.recipe-peek h1, .recipe-peek h2, .recipe-peek h3 {
  margin: .5em 0 .2em;
  font-size: 1.18em;
  font-weight: 700;
  line-height: 1.1;
}
.recipe-peek ul, .recipe-peek ol { margin: 0 0 .5em; padding-left: 1.1em; }
.recipe-peek strong { font-weight: 700; }
.recipe-peek em { font-style: italic; }

/* The ellipsis only appears when the writing actually runs past the page. */
.recipe-card.is-clipped::after {
  content: '…';
  position: absolute;
  right: 0;
  bottom: 0;
  padding-left: 2.2rem;
  font-family: var(--hand);
  font-size: 1.3rem;
  line-height: 1;
  color: var(--ink);
  background: linear-gradient(90deg, transparent, var(--paper) 45%);
}

.recipe-card.is-empty .recipe-peek { color: #b3a68d; }

/* --- The recipe sheet ------------------------------------------ */

.sheet {
  display: flex;
  flex-direction: column;
  width: min(100%, 760px);
  /* dvh, not vh: iOS doesn't shrink vh when the keyboard opens, which would
     leave the bottom of the recipe hidden behind it. */
  height: min(88vh, 900px);
  height: min(88dvh, 900px);
  border-radius: 3px;
  box-shadow: var(--lift-lg);
  overflow: hidden;
}

.sheet-head {
  display: flex;
  align-items: baseline;
  gap: .8rem;
  padding: 1.1rem clamp(1rem, 3vw, 1.8rem) .8rem;
  border-bottom: 1px solid rgba(46,42,36,.14);
}
.sheet-title {
  margin: 0;
  font-family: var(--hand);
  font-size: 2rem;
  font-weight: 700;
}
.sheet-for {
  flex: 1;
  font-family: var(--body);
  font-size: .82rem;
  letter-spacing: .02em;
  color: var(--ink-soft);
}

.sheet-body {
  flex: 1;
  width: 100%;
  padding: clamp(1rem, 3vw, 1.8rem);
  font-family: var(--hand);
  font-size: 1.32rem;
  line-height: 1.45;
  color: var(--ink);
  background: transparent;
  border: none;
  resize: none;
  outline: none;
  overflow-y: auto;
}
.sheet-body.writing { white-space: pre-wrap; }
.sheet-body::placeholder { color: #b3a68d; }
.sheet-body[hidden] { display: none; }

/* --- rendered recipe --- */

.sheet-body.reading > *:first-child { margin-top: 0; }
.sheet-body.reading p { margin: 0 0 .75em; }
.sheet-body.reading h1,
.sheet-body.reading h2,
.sheet-body.reading h3 {
  margin: 1.2em 0 .4em;
  font-weight: 700;
  line-height: 1.1;
  color: var(--accent);
}
.sheet-body.reading h1 { font-size: 1.9rem; }
.sheet-body.reading h2 { font-size: 1.6rem; }
.sheet-body.reading h3 { font-size: 1.4rem; }
.sheet-body.reading ul,
.sheet-body.reading ol { margin: 0 0 .8em; padding-left: 1.4em; }
.sheet-body.reading li { margin-bottom: .18em; }
.sheet-body.reading ul { list-style: none; padding-left: 1.1em; }
.sheet-body.reading ul li::before {
  content: '·';
  margin-left: -.8em;
  margin-right: .45em;
  color: var(--accent);
  font-weight: 700;
}
.sheet-body.reading strong { font-weight: 700; }
.sheet-body.reading em { font-style: italic; }
.sheet-body.reading del { opacity: .55; }
.sheet-body.reading code {
  font-family: var(--body);
  font-size: .78em;
  background: rgba(46,42,36,.07);
  padding: .1em .3em;
  border-radius: 2px;
}
.sheet-body.reading:empty::before {
  content: 'Nothing written down yet — hit Edit.';
  color: #b3a68d;
}

.sheet-hint {
  font-family: var(--body);
  font-size: .78rem;
  letter-spacing: .05em;
  color: #b3a68d;
}

/* --- The cropper ---------------------------------------------- */

.cropper {
  width: min(100%, 620px);
  padding: clamp(1.1rem, 3vw, 1.6rem);
  border-radius: 3px;
  box-shadow: var(--lift-lg);
}

.crop-stage {
  position: relative;
  /* Shrink to the image exactly: the crop box is positioned against this box,
     so any letterboxing here would offset every coordinate. */
  width: fit-content;
  max-width: 100%;
  margin: 0 auto .9rem;
  /* Contains the huge spread shadow the crop box uses to dim the surroundings. */
  overflow: hidden;
  background: rgba(46,42,36,.12);
  touch-action: none;
  user-select: none;
}
.crop-stage img {
  display: block;
  max-width: 100%;
  max-height: min(56vh, 460px);
  object-fit: contain;
  pointer-events: none;
}

.crop-box {
  position: absolute;
  border: 1px solid rgba(255,255,255,.95);
  box-shadow: 0 0 0 9999px rgba(20,17,12,.5);
  cursor: move;
}
/* rule-of-thirds guides */
.crop-box::before,
.crop-box::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, transparent 33.3%, rgba(255,255,255,.3) 33.3% 33.5%,
      transparent 33.5% 66.6%, rgba(255,255,255,.3) 66.6% 66.8%, transparent 66.8%);
}
.crop-box::after {
  background:
    linear-gradient(180deg, transparent 33.3%, rgba(255,255,255,.3) 33.3% 33.5%,
      transparent 33.5% 66.6%, rgba(255,255,255,.3) 66.6% 66.8%, transparent 66.8%);
}

.crop-handle {
  position: absolute;
  width: 18px; height: 18px;
  background: var(--paper);
  border: 1px solid rgba(46,42,36,.5);
  border-radius: 2px;
  z-index: 2;
}
/* Invisible 44px hit area around each handle — the visible square stays small,
   but a thumb can actually land on it. Pseudo-elements aren't event targets,
   so `event.target.dataset.handle` still resolves to the handle itself. */
.crop-handle::after {
  content: '';
  position: absolute;
  inset: -13px;
}
.crop-handle.nw { top: -9px;    left: -9px;   cursor: nwse-resize; }
.crop-handle.ne { top: -9px;    right: -9px;  cursor: nesw-resize; }
.crop-handle.sw { bottom: -9px; left: -9px;   cursor: nesw-resize; }
.crop-handle.se { bottom: -9px; right: -9px;  cursor: nwse-resize; }

.crop-ratios { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: 1rem; }
.crop-ratio {
  font-family: var(--body);
  font-size: .8rem;
  letter-spacing: .01em;
  color: var(--ink-soft);
  background: rgba(46,42,36,.07);
  border: 1px solid rgba(46,42,36,.16);
  border-radius: 2px;
  padding: .38rem .6rem;
  cursor: pointer;
}
.crop-ratio.is-on {
  color: var(--paper);
  background: var(--accent);
  border-color: var(--accent);
}

.sheet-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: .8rem;
  padding: .8rem clamp(1rem, 3vw, 1.8rem) 1rem;
  border-top: 1px solid rgba(46,42,36,.14);
}
.sheet-status {
  margin-right: auto;
  font-family: var(--body);
  font-size: .8rem;
  letter-spacing: .01em;
  color: var(--ink-soft);
}

/* --- Things written on the page ------------------------------- */

/* The holder carries position and size; the body inside is the editable. The
   delete handle is a sibling of the body, never a child of it. */
.jot-holder {
  position: absolute;
  touch-action: none;
}
.jot-holder.scrawl { width: 44%; }
.jot-holder.sticky { width: 33%; }
.jot-holder.photo  { width: 42%; }   /* overridden inline from note.width */

/* a picture stuck onto the page, with an optional caption underneath */
.jot-photo {
  position: relative;
  display: block;
  padding: 8px 8px 6px;
  background: #fffdf7;
  box-shadow: var(--lift);
  cursor: grab;
}
.jot-photo img {
  display: block;
  width: 100%;
  height: auto;
  background: var(--paper-deep);
}
.jot-holder.photo .tape {
  width: 70px; height: 22px;
  top: -11px; left: 50%;
  margin-left: -35px;
  transform: rotate(-3deg);
}
.jot.photo {
  min-height: 0;
  padding: .3rem .1rem 0;
  font-size: 1.05rem;
  text-align: center;
  color: var(--ink-soft);
  cursor: text;
}

/* corner grip for resizing a picture on the page */
.jot-resize {
  position: absolute;
  right: -9px;
  bottom: 14px;
  width: 20px; height: 20px;
  border: none;
  border-radius: 50%;
  background: var(--plum);
  box-shadow: 0 2px 6px rgba(0,0,0,.32);
  cursor: nwse-resize;
  opacity: 0;
  transition: opacity .16s ease;
  touch-action: none;
  z-index: 3;
}
.jot-resize::before {
  content: '';
  position: absolute;
  inset: 6px;
  border-right: 2px solid var(--paper);
  border-bottom: 2px solid var(--paper);
}
.jot-holder.photo:hover .jot-resize,
.jot-holder.photo.is-editing .jot-resize,
.jot-holder.photo.is-resizing .jot-resize { opacity: 1; }
.jot-holder.is-resizing { z-index: 30; }

.jot {
  position: relative;
  width: 100%;
  font-family: var(--hand);
  line-height: 1.16;
  color: var(--ink);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  outline: none;
}
/* Not :empty — browsers park a stray <br> in an emptied contenteditable. */
.jot.is-empty::before {
  content: attr(data-placeholder);
  color: #bcb09a;
  pointer-events: none;
}

/* free handwriting, straight onto the paper */
.jot.scrawl {
  min-height: 1.4em;
  padding: .1rem .15rem;
  font-size: clamp(1.15rem, 1.7vw, 1.55rem);
  cursor: text;
  border-radius: 2px;
}
.jot-holder.scrawl:hover:not(.is-editing) .jot { background: rgba(46,42,36,.045); }

/* sticky note */
.jot.sticky {
  min-height: 74px;
  padding: .6rem .65rem;
  font-size: clamp(1.05rem, 1.5vw, 1.35rem);
  background: var(--note-yellow);
  box-shadow: 0 1px 2px rgba(46,42,36,.16), 0 7px 16px rgba(46,42,36,.2);
  cursor: grab;
}
.jot.sticky[data-color="pink"] { background: var(--note-pink); }
.jot.sticky[data-color="blue"] { background: var(--note-blue); }
.jot.sticky::after {
  content: '';
  position: absolute;
  right: 0; bottom: 0;
  border-width: 0 16px 16px 0;
  border-style: solid;
  border-color: transparent rgba(0,0,0,.09) transparent transparent;
}

.jot-holder.is-editing { z-index: 20; }
.jot-holder.is-editing .jot {
  cursor: text;
  box-shadow: 0 0 0 1.5px rgba(181,87,63,.45), 0 8px 20px rgba(46,42,36,.22);
}
.jot-holder.is-dragging { z-index: 30; }
.jot-holder.is-dragging .jot {
  cursor: grabbing;
  box-shadow: 0 10px 20px rgba(46,42,36,.24), 0 26px 46px rgba(46,42,36,.3);
}

/* delete handle, shown on the note being edited */
.jot-remove {
  position: absolute;
  top: -10px; right: -10px;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  font-family: var(--body);
  font-size: .7rem;
  line-height: 1;
  color: var(--paper);
  background: var(--accent);
  border: none;
  border-radius: 50%;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0,0,0,.3);
}

.page-hint {
  position: absolute;
  left: 0; right: 0; bottom: 9%;
  text-align: center;
  font-family: var(--hand);
  font-size: 1.3rem;
  color: #c3b8a3;
  pointer-events: none;
}

/* ============================================================
   THE PAGE TURN
   ============================================================ */

.flipper {
  position: absolute;
  top: 0;
  height: 100%;
  z-index: 5;
  transform-style: preserve-3d;
  will-change: transform;
  pointer-events: none;
  backface-visibility: visible;
}

/* a single leaf, half the spread, hinged at the spine — the same everywhere,
   since both pages stay visible at every size */
.flipper.leaf { width: 50%; }
.flipper.leaf.forward  { left: 50%; transform-origin: left center; }
.flipper.leaf.backward { left: 0;   transform-origin: right center; }

.flipper .face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translateZ(0);
}
.flipper .face.back { transform: rotateY(180deg) translateZ(0); }

/* A face has to lay its page out exactly as the spread does, or the content
   jumps the moment the leaf lands. */
.flipper.leaf .face > .page { height: 100%; }

/* the leaf reads as a curved surface via a shade that deepens as it lifts */
.flipper .face > .shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  z-index: 9;
}
.flipper .face.front > .shade {
  background: linear-gradient(90deg, rgba(20,17,12,.55), rgba(20,17,12,0) 55%);
}
.flipper .face.back > .shade {
  background: linear-gradient(270deg, rgba(20,17,12,.55), rgba(20,17,12,0) 55%);
}

/* --- One page at a time (narrow screens) ----------------------
   Driven by `.book.single`, which scrap.mjs sets from the same breakpoint it
   uses for the turn logic — so layout and behaviour can't disagree. */

.book.single { aspect-ratio: 0.70; }
.book.single .spread { grid-template-columns: 1fr; }

/* The leaf is now the whole page, hinged on the edge it swings away from. */
.book.single .flipper.leaf { width: 100%; left: 0; }
.book.single .flipper.leaf.forward  { transform-origin: left center; }
.book.single .flipper.leaf.backward { transform-origin: right center; }

/* Only shown where the book isn't the landing view. */
.shelf-add { display: none; }

/* the leaf underneath sits in the turning page's shadow */
.spread > .under-shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  z-index: 8;
  background: linear-gradient(90deg, rgba(20,17,12,.4), rgba(20,17,12,0) 45%);
}

@media (prefers-reduced-motion: reduce) {
  .flipper .face > .shade, .spread > .under-shade { display: none; }
}

/* --- Arrows + footer ------------------------------------------ */

.flip-arrow {
  width: 50px; height: 50px;
  display: grid; place-items: center;
  font-size: 1.3rem;
  color: var(--paper);
  background: rgba(248,242,230,.09);
  border: 1px solid rgba(248,242,230,.16);
  border-radius: 50%;
  cursor: pointer;
  transition: background .16s ease, transform .16s ease;
}
.flip-arrow:hover:not(:disabled) { background: rgba(248,242,230,.18); transform: scale(1.06); }
.flip-arrow:disabled { opacity: .22; cursor: default; }

.book-foot {
  display: flex;
  align-items: center;
  gap: clamp(.5rem, 2vw, 1.1rem);
  flex-wrap: wrap;
  justify-content: center;
}

.pageno {
  font-family: var(--body);
  font-size: .88rem;
  letter-spacing: .12em;
  color: rgba(248,242,230,.45);
}

.palette { display: flex; align-items: center; gap: .45rem; }
.palette-label {
  font-family: var(--body);
  font-size: .8rem;
  letter-spacing: .02em;
  color: rgba(248,242,230,.4);
}
.swatch {
  width: 28px; height: 28px;
  border: 2px solid transparent;
  border-radius: 2px;
  cursor: pointer;
  box-shadow: var(--lift);
  transition: transform .16s ease, border-color .16s ease;
}
.swatch:hover { transform: translateY(-3px) rotate(-3deg); }
.swatch.is-armed { border-color: var(--paper); transform: translateY(-4px) rotate(3deg); }
.swatch[data-color="yellow"] { background: var(--note-yellow); }
.swatch[data-color="pink"]   { background: var(--note-pink); }
.swatch[data-color="blue"]   { background: var(--note-blue); }

/* ============================================================
   SHELF VIEW
   ============================================================ */

.shelf { padding: .5rem clamp(1rem, 4vw, 2.5rem) 2rem; }

.shelf-controls {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
  margin-bottom: 1.4rem;
}

.search {
  font-family: var(--body);
  font-size: .95rem;
  color: var(--paper);
  background: rgba(248,242,230,.08);
  border: 1px solid rgba(248,242,230,.14);
  border-radius: 3px;
  padding: .6rem .85rem;
  min-width: 200px;
}
.search::placeholder { color: rgba(248,242,230,.35); }
.search:focus { outline: none; border-color: rgba(248,242,230,.35); }

.select {
  font-family: var(--body);
  font-size: .7rem;
  letter-spacing: .01em;
  color: rgba(248,242,230,.72);
  background: rgba(248,242,230,.08);
  border: 1px solid rgba(248,242,230,.14);
  border-radius: 3px;
  padding: .62rem .7rem;
  cursor: pointer;
}

.shelf-count {
  font-family: var(--display);
  font-size: .85rem;
  letter-spacing: .02em;
  color: rgba(248,242,230,.4);
  margin-left: auto;
}

.shelf-grid {
  display: grid;
  /* auto-fill wraps only when the next card genuinely won't fit */
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: clamp(1rem, 2.4vw, 1.8rem);
  align-items: start;
}

/* The "nothing matched" panel is a grid item, so it has to span every column
   or it gets squeezed into the width of one card. */
.shelf-empty { grid-column: 1 / -1; }

.card {
  position: relative;
  display: block;
  width: 100%;
  text-align: left;
  padding: 11px 11px 14px;
  background: #fffdf7;
  border: none;
  box-shadow: var(--lift);
  cursor: pointer;
  transform: rotate(var(--tilt, -1deg));
  transition: transform .2s ease, box-shadow .2s ease;
}
.card:hover, .card:focus-visible {
  transform: rotate(0deg) translateY(-7px);
  box-shadow: var(--lift-lg);
  outline: none;
}

.card-photo {
  display: block;
  width: 100%;
  height: auto;
  background: repeating-linear-gradient(45deg, #f3ecdc 0 10px, #eee5d1 10px 20px);
}
/* only the placeholder needs a shape of its own */
.card-photo.is-empty { aspect-ratio: 1 / 1; }

.card-title {
  margin: .5rem 0 0;
  font-family: var(--hand);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1.05;
  color: var(--ink);
}

.card-date {
  font-family: var(--body);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .005em;
  color: var(--accent);
}

.card-peek {
  position: absolute;
  top: -12px; right: -10px;
  width: 62px;
  padding: .3rem .35rem;
  font-family: var(--hand);
  font-size: .84rem;
  line-height: 1.05;
  color: var(--ink);
  background: var(--note-yellow);
  box-shadow: 0 3px 7px rgba(0,0,0,.3);
  transform: rotate(7deg);
  overflow: hidden;
  max-height: 46px;
  z-index: -1;
}
.card-peek[data-color="pink"] { background: var(--note-pink); }
.card-peek[data-color="blue"] { background: var(--note-blue); }

/* ============================================================
   MODAL, BUTTONS, TOAST
   ============================================================ */

.btn {
  font-family: var(--display);
  font-weight: 500;
  font-size: .92rem;
  letter-spacing: .005em;
  color: var(--paper);
  background: var(--accent);
  border: none;
  border-radius: 999px;
  padding: .58rem 1.25rem;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0,0,0,.18);
  transition: transform .16s ease, background .16s ease, box-shadow .16s ease;
}
.btn:hover {
  transform: translateY(-1px);
  background: var(--accent-deep);
  box-shadow: 0 4px 12px rgba(0,0,0,.22);
}
.btn:active { transform: translateY(0); }
.btn:focus-visible { outline: 2px solid var(--accent-deep); outline-offset: 2px; }

.btn.ghost {
  background: transparent;
  color: var(--ink-soft);
  border: 1px solid var(--rule);
  box-shadow: none;
}
.btn.ghost:hover { background: var(--accent-wash); color: var(--ink); }
.btn.on-dark { background: rgba(248,242,230,.1); border: 1px solid rgba(248,242,230,.16); }

.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgba(10,9,7,.72);
  backdrop-filter: blur(3px);
  overflow-y: auto;
}
.modal-backdrop[hidden] { display: none; }

.modal {
  width: min(100%, 460px);
  padding: clamp(1.3rem, 4vw, 2rem);
  border-radius: 3px;
  box-shadow: var(--lift-lg);
}

.modal-title {
  margin: 0 0 1.1rem;
  font-family: var(--hand);
  font-size: 2.1rem;
  font-weight: 700;
}

.field { display: block; margin-bottom: 1rem; }
.field-label {
  display: block;
  font-family: var(--body);
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .005em;
  color: var(--ink-soft);
  margin-bottom: .38rem;
}
.field-label em { text-transform: none; letter-spacing: 0; opacity: .7; }

/* Proper fields on card stock, rather than a flat box with a rule under it:
   a soft inset so they read as pressed into the paper, and a real focus ring. */
.input {
  width: 100%;
  font-family: var(--body);
  font-size: 1rem;
  color: var(--ink);
  background: #fffdf8;
  border: 1px solid var(--rule);
  border-radius: 9px;
  padding: .62rem .75rem;
  box-shadow: inset 0 1px 2px rgba(51,48,42,.07);
  transition: border-color .16s ease, box-shadow .16s ease;
}
.input::placeholder { color: rgba(113,105,91,.62); }
.input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: inset 0 1px 2px rgba(51,48,42,.05), 0 0 0 3px var(--accent-wash);
}
.input.hand { font-family: var(--hand); font-size: 1.4rem; }
.input.mono { font-family: var(--body); font-size: .95rem; }
textarea.input { resize: vertical; }

/* contain, so the preview shows the crop you just chose rather than a
   centre-cut of it */
.photo-preview {
  margin-top: .6rem;
  width: 100%;
  max-height: 190px;
  object-fit: contain;
  background: rgba(46,42,36,.08);
  box-shadow: var(--lift);
}

.modal-actions { display: flex; align-items: center; gap: .5rem; justify-content: flex-end; }
.modal-error {
  margin: 0 0 .9rem;
  padding: .55rem .7rem;
  font-size: .88rem;
  color: var(--warn);
  background: var(--warn-wash);
  border: 1px solid rgba(162,69,82,.25);
  border-radius: 8px;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 1.6rem;
  transform: translateX(-50%);
  z-index: 200;
  font-family: var(--body);
  font-size: .88rem;
  color: var(--paper);
  background: rgba(10,9,7,.94);
  border: 1px solid rgba(248,242,230,.14);
  padding: .7rem 1.1rem;
  border-radius: 3px;
}
.toast[hidden] { display: none; }

.empty {
  margin: auto;
  text-align: center;
  color: rgba(248,242,230,.8);
  padding: 3rem 1rem;
}
.empty h2 { font-family: var(--hand); font-size: 2.6rem; margin: 0 0 .3rem; }
.empty p  { font-size: .95rem; margin: 0 0 1.3rem; opacity: .65; }

/* ============================================================
   RESPONSIVE
   ============================================================ */

/* Phones show one page at a time — half a scrapbook page is too small to
   write on or place anything in. The shelf is the only top-level view; the
   book is what you get when you open a card, so its tab is redundant. */
@media (max-width: 760px) {
  .bar { padding: .75rem .9rem .5rem; }
  .brand-text { font-size: 1.55rem; }
  .tab { padding: .5rem .7rem; font-size: .82rem; }
  .tab[data-view="scrapbook"] { display: none; }

  /* the book's footer is out of reach from the shelf, so adding a meal needs
     a way in from here */
  .shelf-add { display: inline-flex; }

  .scrap { grid-template-columns: 1fr; padding: 0 .4rem; }
  .book { width: 96vw; aspect-ratio: 0.80; perspective: 1500px; }
  .page { padding: .65rem .55rem; }

  .meal-title { font-size: 1.4rem; }
  .meal-date { font-size: .78rem; letter-spacing: .06em; }
  .meal-tags { display: none; }        /* no room; they still show on the shelf */

  /* width still comes from the meal's stored coverWidth */
  .photo-frame { padding: 6px 6px 18px; }
  .photo-frame img { max-height: 21vh; }
  .tape { width: 54px; height: 17px; }
  .tape.tl { top: -8px;  left: -12px; }
  .tape.br { bottom: 11px; right: -13px; }

  .recipe-peek { font-size: .9rem; line-height: 1.22; }
  .recipe-card.is-clipped::after { font-size: 1rem; }

  .jot-holder.sticky { width: 58%; }
  .jot-holder.scrawl { width: 74%; }
  .jot.sticky { min-height: 52px; padding: .4rem .45rem; font-size: .95rem; }
  .jot.scrawl { font-size: .95rem; }
  .jot.photo  { font-size: .88rem; }

  /* touch targets: no hover to reveal them, and thumbs need the room */
  .photo-resize, .jot-resize { opacity: 1; width: 26px; height: 26px; }
  .jot-remove { width: 26px; height: 26px; top: -13px; right: -13px; font-size: .8rem; }

  .flip-arrow { position: fixed; bottom: .9rem; z-index: 40; width: 46px; height: 46px; }
  .flip-arrow.prev { left: .7rem; }
  .flip-arrow.next { right: .7rem; }
  /* keep the footer's controls out from under the fixed arrows */
  .book-foot { padding: 0 3.6rem; gap: .5rem; }
  .table { padding-bottom: 3.4rem; }

  .shelf { padding: .4rem .9rem 2rem; }
  .shelf-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }

  .sheet { height: 92dvh; }
  .sheet-body { font-size: 1.2rem; padding: .9rem; }
  .sheet-hint { display: none; }
  .cropper { padding: .9rem; }
  .crop-ratio { padding: .5rem .7rem; }
}

/* Landscape phones are short, so drive the book off height instead of width. */
@media (max-width: 950px) and (orientation: landscape) and (max-height: 540px) {
  .book { height: 64dvh; width: auto; aspect-ratio: 3 / 2; }
  .book.single { height: 64dvh; width: auto; aspect-ratio: 0.70; }
  .bar { padding: .45rem .9rem .35rem; }
  .brand-text { font-size: 1.3rem; }
  .table { padding-bottom: 1rem; }
  .flip-arrow { bottom: .5rem; }
  .photo-frame img { max-height: 26dvh; }
}

/* --- Signing in ----------------------------------------------- */

/* Signed out there is no book to switch views on, so the tabs go away. */
body.signed-out .tabs { display: none; }

.auth {
  width: min(100%, 380px);
  margin: clamp(1.5rem, 8vh, 5rem) auto;
  padding: 2.4rem 2rem 2rem;
  border-radius: 3px;
  box-shadow: var(--lift-lg);
  transform: rotate(-.5deg);
}

.auth .field { margin-bottom: 1.25rem; }

.auth-title {
  margin: 0 0 1.7rem;
  font-family: var(--hand);
  font-weight: 700;
  font-size: 2.1rem;
  line-height: 1;
  text-align: center;
}

.auth-hint {
  margin: -.85rem 0 1.25rem;
  font-family: var(--body);
  font-size: .78rem;
  letter-spacing: .01em;
  color: var(--ink-soft);
}

.auth-body {
  margin: 0 0 1.4rem;
  font-size: .95rem;
  line-height: 1.5;
  color: var(--ink-soft);
  text-align: center;
}

.auth-submit { width: 100%; margin-top: .25rem; }

/* Belongs to the password field above it, not to the button below — so it
   tucks up against the field and leaves the button plenty of room. */
.auth-aside {
  display: block;
  margin: -.55rem 0 1.75rem;
  text-align: right;
  font-family: var(--body);
  font-size: .82rem;
  color: var(--ink-soft);
  text-decoration: none;
}
.auth-aside:hover { color: var(--accent); text-decoration: underline; }

/* The confirm-your-email panel stacks a button, a status line and a way out. */
.auth .link-btn { display: block; margin: .9rem auto 0; }
.auth .auth-hint { text-align: center; margin: .7rem 0 0; }

/* The way to the other door: set below a hairline so it reads as a footer
   rather than as another control competing with the button. */
.auth-swap {
  display: block;
  margin-top: 1.6rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
  text-align: center;
  font-family: var(--display);
  font-size: .88rem;
  letter-spacing: .005em;
  color: var(--ink-soft);
  text-decoration: none;
}
.auth-swap:hover { color: var(--accent); }

/* --- Account menu --------------------------------------------- */

.account { position: relative; }

.account-btn {
  font-family: var(--display);
  font-size: .84rem;
  letter-spacing: .01em;
  color: rgba(248,242,230,.72);
  background: rgba(248,242,230,.1);
  border: 1px solid rgba(248,242,230,.16);
  border-radius: 2px;
  padding: .5rem .8rem;
  cursor: pointer;
}
.account-btn:hover { color: var(--paper); }

.account-menu {
  position: absolute;
  right: 0;
  top: calc(100% + .5rem);
  z-index: 40;
  width: min(84vw, 300px);
  padding: 1rem;
  border-radius: 3px;
  background-color: var(--paper);
  box-shadow: var(--lift-lg);
}

.account-email {
  margin: 0 0 .8rem;
  font-family: var(--body);
  font-size: .78rem;
  letter-spacing: .01em;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
}

.book-list { list-style: none; margin: 0 0 .7rem; padding: 0; }

.book-pick {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--hand);
  font-size: 1.25rem;
  color: var(--ink);
  background: none;
  border: none;
  border-radius: 2px;
  padding: .25rem .4rem;
  cursor: pointer;
}
.book-pick:hover { background: rgba(46,42,36,.07); }
.book-pick.is-current { color: var(--accent); }
.book-pick.is-current::before { content: '· '; }

.book-new { display: flex; gap: .4rem; margin-bottom: .9rem; }
.book-new .input { font-size: .85rem; padding: .35rem .45rem; }

.btn.small { font-size: .78rem; padding: .4rem .6rem; }

.share-panel { border-top: 1px solid rgba(46,42,36,.14); padding-top: .8rem; }

.share-heading, .share-note {
  margin: 0 0 .5rem;
  font-family: var(--body);
  font-size: .76rem;
  letter-spacing: .01em;
  color: var(--ink-soft);
}
.share-note { text-transform: none; letter-spacing: .04em; opacity: .8; }

.member-list { list-style: none; margin: 0 0 .6rem; padding: 0; }

.member {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem;
}
.member-name { font-family: var(--hand); font-size: 1.15rem; }

.link-btn {
  font-family: var(--display);
  font-size: .6rem;
  letter-spacing: .01em;
  color: var(--ink-soft);
  background: none;
  border: none;
  padding: .2rem 0;
  cursor: pointer;
}
.link-btn:hover { color: var(--accent); }
.link-btn.small { font-size: .74rem; }
