:root {
  --cobalt: #0b3d91;
  --cobalt-deep: #062659;
  --cream: #faf6ee;
  --ink: #1b2a4a;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "Cormorant Garamond", Georgia, serif;
  background: var(--cream);
  color: var(--ink);
}

.hidden { display: none !important; }

.hero {
  text-align: center;
  padding: 2.5rem 1rem 1.5rem;
  background: linear-gradient(180deg, var(--cobalt-deep), var(--cobalt));
  color: var(--cream);
}

.hero h1 {
  font-family: "Playfair Display", Georgia, serif;
  font-size: clamp(2.2rem, 6vw, 3.2rem);
  margin: 0;
  letter-spacing: 0.02em;
}

/* Line drawings of Lisbon landmarks either side of the title (white on
   transparent, from public/images/). Hidden on narrow screens, where
   there's no room beside the title. */
.hero-title {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 1.5rem;
}

.hero-art {
  height: 6rem;
  width: auto;
  opacity: 0.9;
}

@media (max-width: 760px) {
  .hero-art { display: none; }
}

.hero h1 a { color: inherit; text-decoration: none; }

.hero .tagline {
  margin: 0.4rem 0 0;
  font-size: 1.1rem;
  opacity: 0.9;
}

.wizard {
  max-width: 720px;
  margin: 0 auto;
  padding: 1.5rem 1rem 4rem;
}

.step {
  background: #fff;
  border: 1px solid #e4dcca;
  border-radius: 10px;
  padding: 1.25rem 1.25rem 1.5rem;
  margin-bottom: 1.25rem;
  box-shadow: 0 2px 10px rgba(11, 61, 145, 0.06);
}

.step h2 {
  font-family: "Playfair Display", Georgia, serif;
  font-size: 1.3rem;
  color: var(--cobalt);
  margin-top: 0;
}

.choice-row {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.ground-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

.ground-swatch {
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  border: 1px solid #b9ad92;
  cursor: pointer;
  padding: 0;
  box-shadow: inset 0 -3px 6px rgba(0, 0, 0, 0.08);
}

.ground-swatch {
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.ground-swatch:hover,
.ground-swatch:focus-visible {
  transform: translateY(-2px) scale(1.12);
  box-shadow: inset 0 -3px 6px rgba(0, 0, 0, 0.08), 0 3px 8px rgba(11, 61, 145, 0.25);
}

.ground-swatch.selected {
  outline: 2px solid var(--cobalt);
  outline-offset: 2px;
}

.ground-name {
  font-style: italic;
  color: var(--ink);
  min-width: 7.5rem;
}

/* Hovering a swatch other than the selected one: show its name, dimmed,
   so it doesn't read as already chosen. */
.ground-name.previewing { opacity: 0.6; }

/* "What should we paint?" — beside the crop box. */
.paint-mode {
  margin: 1rem 0;
  padding: 0.75rem 1rem;
  border: 1px solid #e4dcca;
  border-radius: 8px;
}

.paint-mode legend {
  padding: 0 0.3rem;
  font-weight: 600;
  color: var(--cobalt);
}

.paint-mode label {
  display: flex;
  gap: 0.55rem;
  align-items: baseline;
  margin: 0.35rem 0;
  cursor: pointer;
  font-size: 1.05rem;
}

.paint-mode-note {
  margin: 0.4rem 0 0;
  font-style: italic;
  color: #6b6253;
  min-height: 1.3em;
}

/* Upload area: click to choose, or drag a photo onto it. */
.drop-zone {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.6rem 1rem;
  border: 2px dashed #cbbfa0;
  border-radius: 10px;
  background: var(--cream);
  text-align: center;
  font-size: 1.1rem;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.drop-zone input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.drop-zone:hover,
.drop-zone:focus-within {
  border-color: var(--cobalt);
  background: #eef2fa;
}

/* While a photo is dragged over a drop target (the upload box, or the
   photo being cropped): a bold cobalt outline, a tint, and a big
   "Drop to…" label from the element's data-drop-label. */
.drop-zone,
#cropper-wrap { position: relative; }

.drop-zone.dragging,
#cropper-wrap.dragging {
  outline: 4px solid var(--cobalt);
  outline-offset: 3px;
}

.drop-zone.dragging::after,
#cropper-wrap.dragging::after {
  content: attr(data-drop-label);
  position: absolute;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: inherit;
  background: rgba(11, 61, 145, 0.78);
  color: #fff;
  font-family: "Playfair Display", Georgia, serif;
  font-size: 1.5rem;
  pointer-events: none;
}

.choice-group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  flex: 1 1 200px;
}

.choice-label {
  font-weight: 600;
  color: var(--cobalt);
}

.choice-btn {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.6rem 0.9rem;
  border: 1px solid #cbbfa0;
  border-radius: 6px;
  background: var(--cream);
  cursor: pointer;
  font-size: 1rem;
  font-family: inherit;
  color: var(--ink);
}

/* "We're happy to help" links and dialog. */
.help-link {
  margin: 0.8rem 0 0;
  font-size: 1.05rem;
}
.link-btn {
  font: inherit;
  padding: 0;
  border: none;
  background: none;
  color: var(--cobalt);
  text-decoration: underline;
  cursor: pointer;
}

.help-dialog {
  width: min(32rem, calc(100vw - 2rem));
  border: none;
  border-radius: 10px;
  padding: 1.5rem;
  background: #fff;
  color: var(--ink);
  font-family: inherit;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}
.help-dialog::backdrop { background: rgba(10, 10, 12, 0.6); }
.help-dialog h2 { margin: 0 0 0.5rem; color: var(--cobalt); font-family: "Playfair Display", Georgia, serif; }
.help-intro { margin: 0 0 1rem; font-size: 1.1rem; line-height: 1.4; }
.help-dialog label { display: block; margin-bottom: 0.8rem; font-size: 1.05rem; }
.help-dialog input[type="email"],
.help-dialog input[type="text"],
.help-dialog textarea {
  display: block;
  width: 100%;
  margin-top: 0.25rem;
  padding: 0.5rem 0.6rem;
  border: 1px solid #cbbfa0;
  border-radius: 6px;
  font: inherit;
  font-size: 1.05rem;
  background: var(--cream);
  color: var(--ink);
}
.help-dialog .optional { opacity: 0.7; }
.help-dialog .help-include { display: flex; gap: 0.5rem; align-items: flex-start; line-height: 1.35; }
.help-include input { margin-top: 0.3rem; }
.help-error { color: #a33; margin: 0 0 0.8rem; }
.help-actions { display: flex; justify-content: flex-end; gap: 0.6rem; }

.shape-tip {
  margin: 0.2rem 0 0;
  font-size: 1rem;
  line-height: 1.35;
  color: var(--cobalt);
}

.choice-btn.selected {
  border-color: var(--cobalt);
  background: #e8edf8;
  box-shadow: inset 0 0 0 1px var(--cobalt);
}

#photo-input { margin-bottom: 1rem; }

#cropper-wrap {
  max-height: 420px;
  margin-bottom: 1rem;
  background: #222;
}

#crop-image { max-width: 100%; display: block; }

/* Visually curve the crop preview for round/oval tiles — official
   Cropper.js recipe. border-radius:50% on a non-square box renders as an
   ellipse inscribed in it (a circle is just the square special case), so
   the same rule covers both round (locked 1:1 box) and oval (free-form
   box, whatever ratio the customer drags). Purely a preview aid — the
   underlying crop selection is a plain bounding box either way; round's
   die-cut / oval's die-cut trims it after printing. */
.curved-crop .cropper-view-box,
.curved-crop .cropper-face {
  border-radius: 50%;
}

/* Grayed out until style, shape and photo are chosen. The .btn prefix
   makes these outrank `.btn:hover` (declared later), which otherwise lit
   the button up on hover. */
.btn.btn-not-ready,
.btn.btn-not-ready:hover {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn {
  font-family: inherit;
  font-size: 1.05rem;
  padding: 0.65rem 1.4rem;
  border-radius: 6px;
  border: 1px solid var(--cobalt);
  background: #fff;
  color: var(--cobalt);
  cursor: pointer;
}

.btn.primary {
  background: var(--cobalt);
  color: #fff;
}

.btn:hover { opacity: 0.9; }

.loading-msg {
  text-align: center;
  font-size: 1.1rem;
  color: var(--cobalt);
}

.spinner {
  width: 3rem;
  height: 3rem;
  margin: 0.5rem auto 1.25rem;
  border: 5px solid #e4dcca;
  border-top-color: var(--cobalt);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* One row per render of the current photo, newest on top. */

/* Per-row finishing controls (border + background color), between the
   row label and its tiles. */
.row-finishing {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  align-items: flex-start;
  margin: 0 0 0.9rem;
}

.finish-group {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.finish-label {
  font-weight: 600;
  color: var(--cobalt);
}

.size-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.size-btn {
  padding: 0.35rem 0.7rem;
  border: 1px solid #cbbfa0;
  border-radius: 6px;
  background: var(--cream);
  cursor: pointer;
  font: inherit;
  color: var(--ink);
  white-space: nowrap;
}

.size-btn:hover,
.size-btn:focus-visible { border-color: var(--cobalt); }

.size-btn.selected {
  border-color: var(--cobalt);
  background: #e8edf8;
  box-shadow: inset 0 0 0 1px var(--cobalt);
}

.border-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.border-thumb {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0.25rem;
  border: 2px solid transparent;
  border-radius: 8px;
  background: none;
  cursor: pointer;
  font: inherit;
  color: var(--ink);
  transition: transform 0.12s ease, border-color 0.12s ease;
}

.border-thumb img {
  display: block;
  height: 64px;
  width: auto;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}

/* Thumbnails take their tile's outline. */
.border-thumb.shape-square img,
.border-thumb.shape-rectangular img { border-radius: 3px; }
.border-thumb.shape-round img,
.border-thumb.shape-oval img { border-radius: 50%; }

.border-thumb-name { font-size: 0.85rem; }

.border-thumb:hover,
.border-thumb:focus-visible { transform: translateY(-2px); border-color: #cbbfa0; }

.border-thumb.selected { border-color: var(--cobalt); }
.results-row + .results-row { margin-top: 1.75rem; }

.results-row-label {
  font-family: "Playfair Display", Georgia, serif;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--cobalt);
  margin: 0 0 0.6rem;
}

.results-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1.5rem;
  padding: 1.5rem;
  background: radial-gradient(ellipse at center, #2a2a2a 0%, #0d0d0d 100%);
  border-radius: 10px;
}

.tile-card {
  text-align: center;
  color: #f2f2f2;
}

.tile-image-wrap {
  position: relative;
  cursor: zoom-in;
}

/* While a tile's new mockup loads (setMockupSrc in app.js): dim it and
   show a spinner. Both fade in after a short delay, so mockups that are
   already cached — which load instantly — don't flicker. */
.tile-image-wrap::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.6rem;
  height: 2.6rem;
  margin: -1.3rem 0 0 -1.3rem;
  border: 4px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  animation: spin 0.9s linear infinite;
}

.tile-image-wrap.loading::after {
  opacity: 1;
  transition: opacity 0.2s ease 0.15s;
}

.tile-image-wrap.loading img {
  filter: brightness(0.6);
  transition: filter 0.2s ease 0.15s;
}

/* The lightbox image isn't inside a .tile-image-wrap; it gets the same
   treatment via its own .loading wrapper (#lightbox-stage). */
.lightbox-stage.loading::after {
  z-index: 2;
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 3.2rem;
  height: 3.2rem;
  margin: -1.6rem 0 0 -1.6rem;
  border: 4px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
  pointer-events: none;
}

.magnifier-btn {
  position: absolute;
  bottom: 0.9rem;
  right: 0.4rem;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.9);
  color: var(--cobalt);
  font-size: 1.1rem;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}
.magnifier-btn:hover { background: #fff; }

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(10, 10, 12, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 2rem;
}
.lightbox img {
  max-width: 100%;
  max-height: 100%;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
}

.lightbox-close {
  position: absolute;
  top: 1rem;
  right: 1.5rem;
  font-size: 2.2rem;
  line-height: 1;
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
}

.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  font-size: 1.3rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox-nav:hover { background: rgba(255, 255, 255, 0.3); }
.lightbox-prev { left: 1rem; }
.lightbox-next { right: 1rem; }

.lightbox-label {
  position: absolute;
  bottom: 3rem;
  right: 2rem;
  margin: 0;
  padding: 0.35rem 1.1rem;
  border-radius: 999px;
  /* Light pill + dark text — a dark pill nearly disappeared against the
     lightbox's own near-black backdrop (rgba(10,10,12,0.92)); this way it
     always contrasts regardless of how dark the artwork underneath is. */
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  font-size: 1.1rem;
  letter-spacing: 0.02em;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

/* Mockups are square scenes (tile on velvet, with its own cast shadow),
   whatever the tile's shape — see lib/tileMockup.js. */
.tile-mockup {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 6px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.55);
  margin-bottom: 0.6rem;
}

.lightbox-stage {
  position: relative;
  width: min(100%, calc(100vh - 4rem), 1200px);
  aspect-ratio: 1 / 1;
  /* Dragging a finger tilts the tile instead of scrolling. */
  touch-action: none;
}

.lightbox img.tile-mockup-large {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 8px;
}

/* Tilt effect (public/app.js): the same scene as the image underneath,
   split into the velvet and the tile, so only the tile moves. At rest it
   matches the plain mockup exactly; the glaze's gloss shows only while
   the tile is tilted. */
.tilt-layers {
  position: absolute;
  inset: 0;
  border-radius: 8px;
  overflow: hidden;
  perspective: 1400px;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.tilt-layers.ready { opacity: 1; }

.lightbox .tilt-layers img,
.tilt-tile,
.tilt-gloss {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  box-shadow: none;
}

.tilt-tile {
  transform-origin: 50% 48%;
  transition: transform 0.25s ease-out;
  will-change: transform;
}

/* A soft window reflection plus a broad sheen, clipped to the tile's own
   outline (the tile layer is its mask). */
.tilt-gloss {
  --gx: 50%;
  --gy: 40%;
  --band: 50%;
  -webkit-mask-image: var(--tile-mask);
  mask-image: var(--tile-mask);
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  background:
    linear-gradient(115deg, transparent calc(var(--band) - 7%), rgba(255, 255, 255, 0.55) calc(var(--band) - 1.5%), rgba(255, 255, 255, 0.55) calc(var(--band) + 1.5%), transparent calc(var(--band) + 7%)),
    radial-gradient(ellipse 45% 30% at var(--gx) var(--gy), rgba(255, 255, 255, 0.3), transparent 70%);
  mix-blend-mode: screen;
  opacity: var(--gloss, 0);
  transition: opacity 0.25s ease-out;
  pointer-events: none;
}

.lightbox-hint {
  position: absolute;
  top: 0.35rem;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  color: rgba(255, 255, 255, 0.75);
  font-size: 1rem;
  white-space: nowrap;
}

/* "Try again" under each tile, with a customer-facing explanation that
   appears on hover or keyboard focus. */
.try-again {
  position: relative;
  display: flex;
  justify-content: center;
  margin-top: 0.35rem;
}

.try-again-btn {
  padding: 0.25rem 0.8rem;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  background: transparent;
  color: #f2f2f2;
  font: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}

.try-again-btn:hover:not(:disabled),
.try-again-btn:focus-visible { background: rgba(255, 255, 255, 0.12); }

.try-again-btn:disabled { opacity: 0.6; cursor: progress; }

.try-again-help {
  position: absolute;
  bottom: calc(100% + 0.5rem);
  left: 50%;
  transform: translateX(-50%);
  width: min(17rem, 80vw);
  padding: 0.6rem 0.8rem;
  border-radius: 8px;
  background: var(--cream);
  color: var(--ink);
  font-size: 0.95rem;
  line-height: 1.35;
  text-align: left;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  z-index: 5;
  transition: opacity 0.15s ease 0.25s;
}

.try-again-btn:hover + .try-again-help,
.try-again-btn:focus-visible + .try-again-help {
  opacity: 1;
  visibility: visible;
}

/* While repainting (15–20 seconds), show the spinner right away rather
   than after the usual short delay. */
.tile-image-wrap.repainting::after { transition-delay: 0s; }
.tile-image-wrap.repainting img { transition-delay: 0s; }

.tile-card label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  font-size: 1rem;
}

.error {
  color: #a12020;
  text-align: center;
  font-weight: 600;
}

@media (max-width: 480px) {
  .choice-row { flex-direction: column; }
}
