/* ============================================================
   oitoana — cozy handmade homepage
   Single cream desk. Handwritten voice. Two fonts only.
   ============================================================ */

:root {
  --cream:        #f3ecdd;
  --cream-soft:   #f8f2e4;

  --ink:          #2a1f3d;
  --ink-soft:     #4a3a62;
  --ink-faint:    #8a7a9e;

  --plum:         #6b4a8a;
  --plum-dusk:    #8d6fb0;
  --plum-haze:    #c9b8dd;

  --ember:        #c9765a;
  --ember-warm:   #f2c9a6;

  --sheet:        #f8f1dc;
  --red-margin:   #c56b6b;
  --line-blue:    rgba(107, 74, 138, 0.07);

  --rule:      rgba(42, 31, 61, 0.18);
  --rule-soft: rgba(42, 31, 61, 0.09);

  --body: 'Nunito', 'Avenir Next', system-ui, sans-serif;
  --hand: 'Caveat', 'Bradley Hand', cursive;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background:
    /* Peach "aged-paper" stains removed site-wide - we rely on the
       lavender-to-cream linear gradient alone. */
    linear-gradient(to bottom,
      #b8a3d0 0%,
      #c0b0d6 6%,
      #c9bcdc 14%,
      #d3c9e2 24%,
      #dcd6e7 36%,
      #e6e2ec 50%,
      #efecf1 66%,
      #f6f3f5 82%,
      #fbf8fa 100%);
  /* background-attachment: fixed was causing Safari to redraw the
     complex radial-gradient stack one frame behind the scroll position,
     which appeared as a jittering cream stripe at the top of the
     viewport when scrolling upward (the bigger the scroll velocity,
     the taller the stripe). Let the gradient scroll with the page. */
  background-attachment: scroll;
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  min-height: 100vh;
  position: relative;
  overflow-x: hidden;
  overscroll-behavior-x: none;
}

/* Fixed full-viewport pseudo-element. Required for iOS Safari to
   render the URL bars in translucent/glass mode — without a fixed
   element covering the viewport, iOS draws the URL bars solid in the
   theme-color. The grain texture is invisible (opacity 0.015) but
   structurally present. Mirrors the body::after rule in style.css. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  opacity: 0.015;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  z-index: 9999;
}

/* Overscroll: match the top of the gradient so the iOS rubber-band /
   Android elastic-scroll area stays warm cream instead of flashing
   white. `overscroll-behavior: none` suppresses Chrome's pull-to-refresh
   indicator (the spinning circle). Must come AFTER the `html, body`
   rule above — the `background` shorthand there wipes background-color
   back to transparent, so this has to win the cascade. */
html {
  background-color: #b8a3d0;
  background-image: none;
  overscroll-behavior-x: none;
  /* iPad Safari lets you pan horizontally into any overflow even when
     <body> has overflow-x: hidden — the html element is its own
     scroll container. Lock the html box to viewport width and forbid
     horizontal scroll explicitly. width: 100% (rather than just
     overflow-x:hidden alone) prevents off-screen children from
     widening the layout in the first place. */
  width: 100%;
  max-width: 100vw;
  overflow-x: hidden;
}

@media (prefers-color-scheme: dark) {
  /* Match the top of the body's cool→warm gradient so the iOS
     rubber-band / Android elastic-scroll overscroll area stays in the
     same cool indigo as the header. */
  html { background-color: #0a0a20; }
}

a { color: inherit; }

/* ---------- Paper grain + lamp ---------- */

.paper {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 1;
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.16  0 0 0 0 0.12  0 0 0 0 0.24  0 0 0 0.05 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 240px 240px;
  mix-blend-mode: multiply;
  opacity: 0.85;
}

.lamp { display: none; }

/* ---------- Frame ---------- */

.frame {
  position: relative;
  z-index: 2;
  max-width: 1280px;
  margin: 0 auto;
  padding: calc(28px + env(safe-area-inset-top)) clamp(22px, 4vw, 56px) calc(36px + env(safe-area-inset-bottom));
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: clamp(20px, 3vh, 40px);
}

.foot {
  padding: 32px 0 12px;
  text-align: center;
  font-family: var(--body);
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
}
.foot-line { opacity: 1; }

/* ---------- Top bar ---------- */

.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

/* Home page: no dashed line under the header in either mode (Rowmate
   already strips its own; matching treatment here keeps the lavender
   gradient under the nav clean). */
body.home-page .top { border-bottom: 0 !important; }

.top-left {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

.mark {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--ink);
}
.mark-word {
  font-family: var(--hand);
  font-size: 30px;
  line-height: 1;
  color: var(--ink);
}

.tagline {
  font-family: var(--hand);
  font-size: 22px;
  color: var(--ember);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  line-height: 1;
}
.tagline .dash {
  display: inline-block;
  width: 26px;
  height: 2px;
  background: var(--ember);
  border-radius: 2px;
}

.nav {
  font-family: var(--hand);
  font-size: 26px;
  color: var(--ink);
  display: inline-flex;
  gap: 10px;
  align-items: baseline;
}
.nav a,
.nav a span {
  font-family: var(--hand);
  text-decoration: none;
  position: relative;
  padding: 0 2px;
  transition: color .2s;
}
.nav a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 2px;
  background: var(--ember);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .35s cubic-bezier(.2,.8,.2,1);
  border-radius: 2px;
}
.nav a:hover { color: var(--ink); }
.nav a:hover::after { transform: scaleX(1); }
.nav-sep { color: var(--ink-faint); }

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

.stage {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
  padding: 8px 0 0;
}

@keyframes rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- Intro (left) ---------- */

.intro {
  max-width: 520px;
  animation: rise 1s cubic-bezier(.2,.8,.2,1) both;
}

.headline {
  font-family: var(--hand);
  font-weight: 600;
  font-size: clamp(56px, 7.5vw, 92px);
  line-height: 0.95;
  letter-spacing: 0.005em;
  margin: 0 0 24px;
  color: var(--ink);
}
.headline .stamp {
  position: relative;
  display: inline-block;
  color: var(--ember);
}
.headline .stamp::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.04em;
  height: 10px;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 10' preserveAspectRatio='none'><path d='M2 6 Q 40 1, 80 5 T 160 5 T 198 6' fill='none' stroke='%23c9765a' stroke-width='2.2' stroke-linecap='round'/></svg>") center/100% 100% no-repeat;
}
.headline .dot { color: var(--ink); }

.lede {
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0 0 22px;
  max-width: 46ch;
}
.lede strong {
  font-family: var(--hand);
  font-weight: 700;
  font-size: 1.3em;
  color: var(--ink);
  font-style: italic;
  letter-spacing: 0.01em;
  margin: 0 0.05em;
}

.values {
  list-style: none;
  padding: 0;
  margin: 0 0 28px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  font-size: 15px;
  color: var(--ink-soft);
}
.values li { display: inline-flex; align-items: center; gap: 6px; }
.values .heart { width: 16px; height: 16px; color: var(--ember); flex-shrink: 0; }

/* "Currently on the shelf" — small bold label lead-in for the app list. */
.apps-label {
  font-family: var(--body);
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
  margin: 4px 0 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
/* App pill row: small icon + name, links to each product page. */
.apps-list {
  list-style: none;
  padding: 0;
  margin: 0 0 28px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 12px;
}
.app-pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 14px 6px 8px;
  border: 1px dashed var(--rule);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.35);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--hand);
  font-size: 22px;
  line-height: 1;
  transition: transform .25s cubic-bezier(.2,.8,.2,1), border-color .25s, background .25s;
}
.app-pill:hover {
  transform: translateY(-2px) rotate(-0.4deg);
  border-color: var(--ember);
  background: rgba(255, 255, 255, 0.6);
  color: var(--ember);
}
.app-pill img {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  display: block;
  flex-shrink: 0;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.55) inset,
    0 2px 6px rgba(42, 31, 61, 0.15);
}
@media (prefers-color-scheme: dark) {
  .apps-label { color: var(--ink-soft) !important; }
  .app-pill {
    border-color: rgba(201, 184, 221, 0.22) !important;
    background: rgba(255, 255, 255, 0.04) !important;
    color: var(--ink) !important;
  }
  .app-pill:hover {
    border-color: var(--ember) !important;
    background: rgba(232, 152, 120, 0.08) !important;
    color: var(--ember) !important;
  }
}

.sign-off {
  margin: 0;
  border-top: 1px dashed var(--rule);
  padding-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-width: 36ch;
}
.sign-line {
  font-family: var(--hand);
  font-size: 20px;
  color: var(--ink-soft);
  font-style: italic;
}
.sign-name {
  font-family: var(--hand);
  font-size: 30px;
  color: var(--ink);
  line-height: 1;
  margin-left: 4px;
}

/* ---------- Shelf card (right) ---------- */

.shelf {
  position: relative;
  max-width: 840px;
  justify-self: end;
  width: 100%;
  padding: 20px 0 0;
  animation: rise 1s 0.1s cubic-bezier(.2,.8,.2,1) both;
}

/* Paper arrow stickers */
.arrow-sticker {
  position: absolute;
  top: 50%;
  width: 114px;
  height: auto;
  padding: 0;
  background: transparent;
  border: none;
  cursor: pointer;
  z-index: 6;
  display: block;
  filter: drop-shadow(0 4px 6px rgba(42,31,61,0.14));
  transition: transform .18s ease;
}

.arrow-img {
  width: 100%;
  height: auto;
  display: block;
  pointer-events: none;
}

.arrow-sticker:focus-visible { outline: none; }
.arrow-sticker:active { transform: translateY(-50%) scale(0.96) rotate(var(--r, 0)); }

.arrow-prev {
  left: -82px;
  --r: -8deg;
  transform: translateY(-50%) rotate(-8deg) scaleX(-1);
}
.arrow-next {
  right: -82px;
  --r: 7deg;
  transform: translateY(-50%) rotate(7deg);
}

.arrow-prev:hover { transform: translateY(-50%) rotate(-8deg) scaleX(-1) scale(1.05); }
.arrow-next:hover { transform: translateY(-50%) rotate(7deg) scale(1.05); }

.arrow-sticker[hidden] { display: none; }

@media (max-width: 1100px) {
  .arrow-sticker { width: 92px; }
  .arrow-prev { left: -56px; }
  .arrow-next { right: -56px; }
}
@media (max-width: 640px) {
  /* iPhone: shrink the arrow stickers and overlay them at the sheet's
     left/right edges. Both arrows are shifted ~20px above the vertical
     centre so they hover near the top of the card (sits over the
     screenshot area instead of dead-centre over the title block).
     The right arrow is nudged a couple of pixels further right than
     the left one to balance the asymmetric tilt. */
  .shelf { position: relative; }
  .arrow-sticker {
    width: 48px;
    top: 50%;
  }
  .arrow-prev {
    left: 4px;
    transform: translateY(calc(-50% - 32px)) rotate(-8deg) scaleX(-1);
  }
  .arrow-next {
    left: auto;
    right: 0;
    transform: translateY(calc(-50% - 32px)) rotate(7deg);
  }
  .arrow-prev:active { transform: translateY(calc(-50% - 32px)) rotate(-8deg) scaleX(-1) scale(0.96); }
  .arrow-next:active { transform: translateY(calc(-50% - 32px)) rotate(7deg) scale(0.96); }
}

/* Notebook sheet wrapping the app tile */
.sheet {
  position: relative;
  background-color: #fbf4df;
  background-image:
    /* very faint horizontal ruled lines */
    repeating-linear-gradient(
      to bottom,
      transparent 0,
      transparent 31px,
      rgba(107, 74, 138, 0.06) 31px,
      rgba(107, 74, 138, 0.06) 32px
    ),
    /* soft paper fiber grain */
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='260' height='260'><filter id='p'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.55  0 0 0 0 0.45  0 0 0 0 0.28  0 0 0 0.06 0'/></filter><rect width='100%' height='100%' filter='url(%23p)'/></svg>"),
    /* subtle warm vignette across the sheet */
    radial-gradient(ellipse at 50% 40%, #fdf8e6 0%, #f8efd6 65%, #f2e6c7 100%);
  background-size: auto, 260px 260px, cover;
  background-repeat: repeat, repeat, no-repeat;
  border-radius: 3px;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.6) inset,
    0 2px 8px rgba(42,31,61,0.10),
    0 22px 54px -14px rgba(42,31,61,0.28);
  padding: 32px clamp(26px, 4vw, 44px) 24px;
  transform: rotate(-1.3deg);
  transform-origin: top center;
  transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.3, 1);
}

.shelf:hover .sheet {
  transform: rotate(-0.3deg) translateX(3px);
}

/* Peeled-bottom cast shadow so the sheet looks slightly bent at its base */
.sheet::after {
  content: "";
  position: absolute;
  left: 8%;
  right: 8%;
  bottom: -22px;
  height: 30px;
  background: radial-gradient(ellipse at center top,
    rgba(42, 31, 61, 0.30) 0%,
    rgba(42, 31, 61, 0.16) 40%,
    transparent 75%);
  filter: blur(6px);
  pointer-events: none;
  z-index: -1;
  border-radius: 50%;
}

@media (prefers-reduced-motion: reduce) {
  .shelf:hover .sheet { transform: none; }
}

/* Washi tape pinning the sheet */
.tape {
  position: absolute;
  top: -18px; /* ~half of the tape extends above the sheet */
  width: 116px;
  height: 32px;
  background: linear-gradient(180deg,
    rgba(201, 118, 90, 0.92),
    rgba(178, 100, 75, 0.78));
  border-left: 1px dashed rgba(255,255,255,0.4);
  border-right: 1px dashed rgba(255,255,255,0.4);
  box-shadow: 0 3px 7px rgba(42,31,61,0.16);
  z-index: 3;
}
.tape-tl { left: 10%; transform: rotate(-14deg); }
.tape-tr { right: 10%; transform: rotate(12deg); }

.card-visual {
  margin: -4px -20px 8px;
  position: relative;
  display: grid;
  place-items: center;
  padding: 0;
}

.halo {
  position: absolute;
  inset: 6% 8% 18%;
  border-radius: 50%;
  background: radial-gradient(ellipse at center,
    rgba(242, 201, 166, 0.55),
    rgba(201, 184, 221, 0.25) 45%,
    transparent 72%);
  filter: blur(12px);
  z-index: 0;
}

.macbook {
  position: relative;
  width: 100%;
  max-width: 620px;
  margin: 0 auto;
  aspect-ratio: 1277 / 832;
  z-index: 1;
}
.macbook:focus { outline: none; }
.macbook:focus-visible { outline: none; }

.mb-anim {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  z-index: 1;
  pointer-events: none;
  filter: drop-shadow(0 12px 16px rgba(42,31,61,0.18));
}

.expand-hint {
  position: absolute;
  top: 8px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  background: rgba(243, 236, 222, 0.88);
  color: var(--ink);
  border-radius: 100px;
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  backdrop-filter: blur(4px);
  opacity: 0;
  transition: opacity 0.3s;
  z-index: 3;
}
.macbook:hover .expand-hint,
.macbook:focus-visible .expand-hint { opacity: 1; }

/* Card body */
.card-body { position: relative; z-index: 2; }

.card-title {
  font-family: var(--hand);
  font-weight: 700;
  font-size: 48px;
  margin: 0 0 8px;
  line-height: 0.95;
  letter-spacing: 0.005em;
}
.card-title a {
  text-decoration: none;
  color: var(--plum);
  background-image: linear-gradient(to right, var(--plum), var(--plum));
  background-repeat: no-repeat;
  background-size: 0% 2px;
  background-position: 0 100%;
  padding-bottom: 3px;
  transition: background-size .35s cubic-bezier(.2,.8,.2,1);
}
.card-title a:hover { background-size: 100% 2px; }

.card-blurb {
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0 0 20px;
  max-width: 64ch;
}

.specs {
  margin: 0 0 22px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px 16px;
  border-top: 1px dashed var(--rule);
  border-bottom: 1px dashed var(--rule);
  padding: 12px 0;
}
.specs div {
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: center;
  text-align: center;
}
.specs dt {
  font-family: var(--hand);
  font-size: 17px;
  color: var(--ink-faint);
  font-weight: 700;
  letter-spacing: 0.02em;
  font-style: italic;
}
.specs dd {
  margin: 0;
  font-size: 14px;
  color: var(--ink);
  font-weight: 400;
}

.card-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 26px 10px;
  background: transparent;
  color: var(--plum);
  text-decoration: none;
  border: 0;
  font-family: 'Caveat', cursive;
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: 0.005em;
  line-height: 1.1;
  transform: rotate(-2deg);
  filter: drop-shadow(0 4px 8px rgba(42, 31, 61, 0.14));
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 60' preserveAspectRatio='none'><path d='M14 12 Q5 14 4 26 Q2 38 6 48 Q15 56 32 55 Q88 57 128 54 Q172 56 191 49 Q198 42 196 28 Q199 13 187 7 Q168 3 128 6 Q80 3 42 7 Q19 6 14 12 Z' fill='%23fef3d9' stroke='%236b4a8a' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round' stroke-dasharray='4 3' /></svg>");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-position: center;
  /* Transform stays synced to the .sheet rotation (0.4s) so the button
     and sheet move in lockstep. The glow (filter) lights up almost
     instantly so the hover feels responsive. */
  transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.3, 1),
              filter 0.12s ease-out;
}
.btn-primary:hover,
.shelf:hover .btn-primary {
  transform: rotate(-2deg) translateY(-3px);
  filter: drop-shadow(0 8px 14px rgba(42, 31, 61, 0.22));
}
.btn-primary:hover .btn-arrow,
.shelf:hover .btn-primary .btn-arrow { transform: translateX(3px); }
.btn-arrow {
  display: inline-block;
  width: 28px;
  height: 14px;
  color: var(--plum);
  transition: transform 0.4s cubic-bezier(0.25, 0.8, 0.3, 1);
  position: relative;
  top: 1px;
  overflow: visible;
}

/* Mac App Store badge wrapper — official Apple artwork stands alone,
   no frame/background, just spacing and a subtle hover. */
.mas-link {
  display: inline-block;
  line-height: 0;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.mas-link:hover { opacity: 0.85; transform: translateY(-1px); }
.mas-link img {
  display: block;
  /* Sits inside a smaller product card next to the "learn more"
     arrow, so we use Apple's 40px minimum to keep the badge from
     visually dominating the card. The ManiShelf landing page hero
     uses 44px because it has more breathing room around it. */
  height: 40px;
  width: auto;
}

/* Rowmate "coming soon to the App Store" placeholder pill — used
   on the homepage product carousel until Rowmate ships and gets
   its real Mac App Store badge. Disabled-looking dashed border. */
.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px 8px 14px;
  border: 1px dashed var(--rule);
  border-radius: 100px;
  color: var(--ink-soft);
  font-size: 13px;
  opacity: 0.9;
}
.btn-ghost .apple { width: 14px; height: 17px; color: var(--ink-soft); }
.ghost-text { display: flex; flex-direction: column; line-height: 1.15; }
.ghost-text small { font-size: 10px; letter-spacing: 0.04em; opacity: 0.85; }
.ghost-text strong { font-weight: 600; font-size: 14px; color: var(--ink); }

.shelf-whisper {
  margin: 22px 4px 0;
  font-family: var(--hand);
  font-size: 20px;
  color: var(--ink-soft);
  font-style: italic;
}
.shelf-whisper a {
  color: var(--ember);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

/* ---------- Lightbox ---------- */

.lightbox {
  border: none;
  background: transparent;
  outline: none;
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  max-width: 100vw;
  max-height: 100vh;
  margin: 0;
  padding: 0;
}
.lightbox[open] {
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox::backdrop {
  background: rgba(26, 19, 37, 0.82);
  backdrop-filter: blur(8px);
}
.lightbox video,
.lightbox-img {
  width: min(960px, 92vw);
  height: auto;
  border-radius: 10px;
  box-shadow: 0 30px 80px rgba(0,0,0,0.5);
  display: block;
}
.lightbox-close {
  position: fixed;
  top: 20px;
  right: 24px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(243, 236, 222, 0.4);
  background: transparent;
  color: var(--cream);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background .2s;
}
.lightbox-close:hover { background: rgba(243, 236, 222, 0.15); }

/* ---------- Responsive ---------- */

/* Nudge the intro column down on desktop so the headline sits a touch
   lower than the product card's top edge — it reads better aligned
   against the card's title rather than its padding. Only applies on
   the two-column desktop layout; on stacked layouts below 900px the
   intro sits on top and doesn't need the offset. */
@media (min-width: 901px) {
  .intro { margin-top: 24px; }
}

@media (max-width: 900px) {
  .stage { grid-template-columns: 1fr; gap: 36px; }
  .shelf { justify-self: stretch; max-width: none; }
  .intro { max-width: none; }
  .headline { font-size: clamp(48px, 11vw, 72px); }
  .headline .desk-br { display: none; }
  .top { flex-wrap: wrap; }
  .top-left { gap: 12px; }
}

/* Keep "one stitch at a time" from breaking across two lines. */
.lede .nowrap { white-space: nowrap; }

/* iPad-only: flatten the headline to one row. On desktop it is split
   into four stacked lines for rhythm; on phones the max-width:900 rule
   above already hides .desk-br (leaves two rows). iPads sit in between,
   so drop the remaining <br> and shrink the font so "Handmade apps for
   Apple devices." fits on a single row. */
@media (hover: none) and (pointer: coarse) and (min-width: 821px) {
  .headline br { display: none; }
  .headline { font-size: clamp(44px, 6.4vw, 72px); line-height: 1.05; }
  /* Let the lede sit on a single line. The desktop rule caps it at 46ch
     to force a comfortable wrap; on iPad there's room for the full
     sentence. */
  .lede { max-width: none; white-space: nowrap; }
}

@media (max-width: 560px) {
  .frame { padding: 22px 18px 24px; }
  .specs { grid-template-columns: 1fr 1fr; gap: 8px 14px; }
  .tape-tl { left: 8%; }
  .tape-tr { right: 8%; }

  /* iPhone wordmark: replace the "oitoana" text with a tiny ember
     pulsing dot + back-arrow. Compact enough that the whole nav
     fits on one row beside it. Acts as a "back home" indicator on
     every page; the pulse signals it's tappable. */
  .mark-word { display: none; }
  .mark { gap: 4px; }
  .mark::before {
    content: '';
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--ember);
    animation: mark-pulse 1.8s ease-in-out infinite;
  }
  .mark::after {
    content: '←';
    font-family: var(--hand);
    font-size: 22px;
    line-height: 1;
    color: var(--ember);
    /* Caveat's ← glyph sits high in its bounding box, so flex
       align-items: center looks too-high. Nudge down by 2px to
       sit on the same optical centre as the dot. */
    transform: translateY(2px);
  }

  /* Smaller nav font + tighter gap so the items fit on a single
     iPhone row beside the icon. */
  .nav { font-size: 18px; gap: 6px; flex-wrap: nowrap; min-width: 0; }
  .nav .nav-sep { opacity: 0.55; }
  .tagline { font-size: 18px; }

  /* iPhone header: keep mark + nav on a SINGLE row across every
     page (including home). justify-content: space-between in the
     base .top rule already pushes them to opposite ends. */
  .top { position: relative; flex-wrap: nowrap; }
  .top-left { flex-wrap: nowrap; gap: 8px; }
}

@keyframes mark-pulse {
  0%, 100% { transform: scale(1);   opacity: 0.85; box-shadow: 0 0 0 0 rgba(201, 118, 90, 0.40); }
  50%      { transform: scale(1.25); opacity: 1;    box-shadow: 0 0 0 5px rgba(201, 118, 90, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .mark::before { animation: none !important; }
}

/* Compact viewport — 13" MacBooks and shorter screens. Trim vertical
   rhythm so the product card's CTA stays above the fold. */
@media (min-width: 901px) and (max-height: 900px) {
  .frame { padding: 14px clamp(22px, 4vw, 56px) 20px; }
  .stage { padding-top: 0; gap: clamp(20px, 3vw, 44px); }
  .headline { font-size: clamp(44px, 5.6vw, 68px); line-height: 0.95; margin-bottom: 14px; }
  .lede { font-size: 15px; line-height: 1.55; margin-bottom: 14px; }
  .values { margin-bottom: 12px; gap: 10px 18px; }
  .sheet { padding: 20px 24px 22px; }
  .card-title { font-size: clamp(28px, 3.2vw, 40px); margin-bottom: 8px; }
  .card-blurb { font-size: 15px; margin-bottom: 14px; }
  .specs { margin-bottom: 14px; padding-top: 10px; padding-bottom: 10px; }
  .card-actions { margin-top: 10px; }
  .macbook { max-width: 520px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ============================================================
   DARK MODE — cozy purple night
   Mirrors the manishelf-cozy palette so both pages flip together
   ============================================================ */

@media (prefers-color-scheme: dark) {
  :root {
    --cream:        #f3ecdd;
    --cream-soft:   #f7f0e2;
    --sheet:        #2a1f3d;
    --ink:          #f3ecdd;
    --ink-soft:     #d8c9ec;
    --ink-faint:    #9e8cb8;
    --plum:         #c9b8dd;
    --plum-dusk:    #a98ec9;
    --plum-haze:    #3a2a52;
    --ember:        #e89878;
    --ember-warm:   #c9765a;
    --rule:         rgba(201, 184, 221, 0.18);
    --rule-soft:    rgba(201, 184, 221, 0.09);
    --red-margin:   #d58888;
    --line-blue:    rgba(201, 184, 221, 0.08);
  }

  html, body {
    /* Cool → warm dark gradient. Every stop sits at the same near-black
       lightness as the header (~6% L) so it never gets eye-hurting
       brighter; only the HUE drifts from cool indigo at the top to
       warm plum at the bottom. A faint fractal-noise grain breaks up
       the flatness so the surface doesn't read as a solid colour. */
    background:
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.85  0 0 0 0 0.78  0 0 0 0 0.95  0 0 0 0.05 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>"),
      linear-gradient(to bottom,
        #0a0a20 0%,
        #0a0a20 25%,
        #0c091c 55%,
        #0e081a 80%,
        #0f0718 100%);
    background-color: #0a0a20;
    background-size: 240px 240px, auto;
    background-repeat: repeat, no-repeat;
    background-attachment: scroll;
    color: var(--ink);
  }

  /* Notebook sheet — deep plum paper with faint lavender rules */
  .sheet {
    background-color: #2a1f3d !important;
    background-image:
      repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent 31px,
        rgba(201, 184, 221, 0.06) 31px,
        rgba(201, 184, 221, 0.06) 32px
      ),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='260' height='260'><filter id='p'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.65  0 0 0 0 0.55  0 0 0 0 0.80  0 0 0 0.06 0'/></filter><rect width='100%' height='100%' filter='url(%23p)'/></svg>"),
      radial-gradient(ellipse at 50% 40%, #352850 0%, #2a1f3d 65%, #231734 100%) !important;
    box-shadow:
      0 1px 0 rgba(201, 184, 221, 0.06) inset,
      0 2px 8px rgba(0, 0, 0, 0.4),
      0 22px 54px -14px rgba(0, 0, 0, 0.55) !important;
  }

  /* Washi tape — slightly glowy plum + peach pair */
  .tape {
    background: linear-gradient(180deg,
      rgba(232, 152, 120, 0.88),
      rgba(201, 118, 90, 0.72)) !important;
    box-shadow: 0 3px 7px rgba(0, 0, 0, 0.5) !important;
  }

  /* Card body copy on the dark sheet */
  .card-body,
  .card-blurb {
    color: var(--ink-soft) !important;
  }
  .card-title a {
    color: var(--plum-dusk) !important;
  }

  /* Specs & labels inside the sheet */
  .specs dt { color: var(--ink-faint) !important; }
  .specs dd { color: var(--ink) !important; }
  .specs div {
    border-bottom: 1px dashed rgba(201, 184, 221, 0.14) !important;
  }

  /* Hero headline */
  .headline { color: var(--ink) !important; }
  .headline .stamp { color: var(--ember) !important; }
  .headline .dot { color: var(--ink) !important; }

  .lede { color: var(--ink-soft) !important; }
  .lede strong { color: var(--ink) !important; }

  .values { color: var(--ink-soft) !important; }
  .values .heart { color: var(--ember) !important; }

  /* Top bar */
  .top { border-bottom: 1px dashed rgba(201, 184, 221, 0.20); }
  .mark-word { color: var(--ink) !important; }
  .nav a { color: var(--ink-soft) !important; }
  .nav a:hover { color: var(--ember) !important; }

  /* Footer */
  .foot { color: var(--ember) !important; }

  /* Arrow-paper stickers — keep PNG, just drop the light-mode filter */
  .arrow-sticker {
    filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5)) !important;
  }

  /* Learn more button — replace the cream sticky-paper SVG with a
     deep-plum fill + ember dashed stroke so it doesn't glow against the
     dark page. Same shape and dashed-line treatment, just dark-mode
     palette. Hover is glow-and-lift only (no background-color swap,
     which would wipe the image and make the button square). */
  .btn-primary {
    color: var(--ember) !important;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 60' preserveAspectRatio='none'><path d='M14 12 Q5 14 4 26 Q2 38 6 48 Q15 56 32 55 Q88 57 128 54 Q172 56 191 49 Q198 42 196 28 Q199 13 187 7 Q168 3 128 6 Q80 3 42 7 Q19 6 14 12 Z' fill='%232a1f3d' stroke='%23e89878' stroke-width='1.6' stroke-linejoin='round' stroke-linecap='round' stroke-dasharray='4 3' /></svg>") !important;
    filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.45)) !important;
  }
  .btn-primary:hover,
  .shelf:hover .btn-primary {
    color: var(--ember) !important;
    filter: drop-shadow(0 8px 16px rgba(232, 152, 120, 0.30)) !important;
  }

  /* Rowmate "coming soon" placeholder on dark */
  .btn-ghost {
    border-color: rgba(201, 184, 221, 0.22) !important;
    color: var(--ink-soft) !important;
  }
  .btn-ghost .apple { color: var(--ink-soft) !important; }
  .ghost-text strong { color: var(--ink) !important; }

  /* MacBook frame shadow pops on dark */
  .macbook { filter: drop-shadow(0 16px 26px rgba(0, 0, 0, 0.55)) !important; }
}

@media (max-width: 560px) {
  .desk-only { display: none !important; }

  /* iPhone product switcher: replace the paper arrow stickers with a
     native horizontal-swipe carousel + dot indicators (like a social
     media gallery). Both sheets sit side-by-side in a scroll-snap
     container; the user swipes to switch. Dots below show progress
     and are clickable. */
  .arrow-sticker { display: none !important; }

  /* Tighten the grid gap on iPhone so the dots sit close to both the
     intro section above and the swipeable cards below — feels like a
     single cohesive carousel block instead of three loosely-stacked
     rows. */
  .stage { gap: 14px !important; }

  .shelf {
    display: flex !important;
    flex-direction: row !important;
    /* Stretch every sheet to the same height (the tallest card's
       natural height). Without this the rowmate card is shorter than
       the manishelf one, leaving a strip of empty space below it. */
    align-items: stretch !important;
    overflow-x: auto !important;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Just enough padding-top to clear the rotated washi-tape stickers
       (tape sits at top: -18px on the sheet, rotated ±12-14° — visible
       top edge ~32px above the sheet). */
    padding: 32px 0 0;
    gap: 0;
  }
  .shelf::-webkit-scrollbar { display: none; }

  .shelf .sheet {
    /* Each card is exactly the .shelf's full width — two cards = 200%
       of scroll width, one always fully in view, the other fully out.
       No gap, no peek: cleaner snap, less "framed" feel. */
    flex: 0 0 100%;
    scroll-snap-align: center;
    scroll-snap-stop: always;
  }
  /* The desktop JS toggles the `hidden` attribute to switch products;
     on iPhone we want both visible to swipe between, so neutralise it. */
  .shelf .sheet[hidden] { display: flex !important; }

  /* The sheet's decorative effects extend beyond its box and get
     clipped by the horizontal scroll container, leaving hard edges
     that read as a frame. Drop them on iPhone — the carousel's swipe
     motion is the primary affordance here, no need for the paper
     paper-bend illusion. */
  .shelf .sheet::after { display: none !important; }
  .shelf .sheet {
    box-shadow: none !important;
    transform: none !important;
  }

  /* Disable the click/hover wobble — `.shelf:hover` fires on tap in
     mobile Safari and makes the card jitter when tapping near it. */
  .shelf:hover .sheet { transform: none !important; }
  .shelf:hover .btn-primary { transform: none !important; filter: none !important; }
  .shelf:hover .btn-primary .btn-arrow { transform: none !important; }

  .shelf-dots {
    display: flex !important;
    justify-content: center;
    gap: 10px;
    /* No vertical margins on the dots themselves — the .stage grid gap
       (overridden below to a tighter value on iPhone) handles all spacing
       between intro / dots / shelf. Keeps the carousel area compact. */
    margin: 0;
  }
  .shelf-dot {
    width: 9px;
    height: 9px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(42, 31, 61, 0.22);
    cursor: pointer;
    transition: background .25s ease, transform .25s ease;
    -webkit-tap-highlight-color: transparent;
  }
  .shelf-dot.is-active {
    background: var(--ember);
    transform: scale(1.25);
  }
}

/* Hide the dots container outside the iPhone breakpoint. */
.shelf-dots { display: none; }
