/* ==========================================================================
   THE GARAGE — Why Not Sell It's playable front door.
   Authored plates do the visual work; code does light, air and interface.
   ========================================================================== */

.garage {
  position: relative;
  height: 100svh;
  min-height: 560px;
  overflow: hidden;
  background: #05060a;
  color: #fff;
  isolation: isolate;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
}

/* ---------------- stage: the plates ---------------- */
/* overflow hidden because .plate below deliberately sits at inset -2% and
   scales up, so it bleeds a few pixels past every edge on purpose. Unclipped,
   that bleed is real scrollable width, and on a phone the browser answers
   overflow by widening the layout viewport, which is how a decorative 2 percent
   ended up changing how many photos fit across a row. */
.stage { position: absolute; inset: 0; z-index: 0; overflow: hidden; }

.plate {
  position: absolute; inset: -2%;
  background-size: cover;
  background-position: center 58%;
  opacity: 0;
  transform: scale(1.045);
  transition: opacity 900ms cubic-bezier(.4,0,.2,1), transform 2600ms cubic-bezier(.2,.6,.2,1), filter 900ms ease;
  will-change: opacity, transform;
}
.plate.is-on { opacity: 1; transform: scale(1); }
.plate--dark { background-image: url("/assets/img/plate-garage-dark.webp"); filter: brightness(2.05) saturate(1.16) contrast(0.92); }
.plate--lit { background-image: url("/assets/img/plate-garage-lit.webp"); }
.plate--clipboard { background-image: url("/assets/img/plate-clipboard.webp"); background-position: center; }
.plate--phone { background-image: url("/assets/img/plate-phone.webp"); }
.plate--pinboard { background-image: url("/assets/img/plate-pinboard.webp"); }
.plate--driveway { background-image: url("/assets/img/plate-driveway.webp"); }

/* the moment the lights come on */
.garage[data-lights="on"] .plate--lit { filter: brightness(1) saturate(1.04); }
.ambient {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(ellipse 70% 50% at 74% 42%, rgb(120 90 170 / 0.22), transparent 62%),
    radial-gradient(ellipse 55% 40% at 30% 78%, rgb(255 176 84 / 0.10), transparent 70%);
  transition: opacity .8s ease;
}
.garage[data-lights="on"] .ambient { opacity: 0; }
.lamp-bloom {
  position: absolute; z-index: 1; pointer-events: none;
  left: 36%; top: 4%; width: 34%; aspect-ratio: 1;
  background: radial-gradient(circle, rgb(255 200 120 / 0.55) 0%, rgb(255 176 84 / 0.18) 34%, transparent 68%);
  opacity: 0; transition: opacity 700ms ease;
  mix-blend-mode: screen;
}
.garage[data-lights="on"] .ambient {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(ellipse 70% 50% at 74% 42%, rgb(120 90 170 / 0.22), transparent 62%),
    radial-gradient(ellipse 55% 40% at 30% 78%, rgb(255 176 84 / 0.10), transparent 70%);
  transition: opacity .8s ease;
}
.garage[data-lights="on"] .ambient { opacity: 0; }
.lamp-bloom { opacity: 1; animation: lampBreathe 6s ease-in-out infinite; }
@keyframes lampBreathe { 0%,100% { opacity: 1; } 50% { opacity: 0.86; } }
.lamp-bloom.is-flicker { animation: lampFlicker 1.5s steps(1) 1; }
@keyframes lampFlicker {
  0%,12%,26%,44% { opacity: 0; } 8%,20%,36% { opacity: .7; } 60% { opacity: .35; } 100% { opacity: 1; }
}

/* ---------------- the car ---------------- */
.car-layer {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  display: grid; place-items: end center;
  opacity: 0; transition: opacity .5s ease;
}
.garage[data-scene="garage"] .car-layer { opacity: 1; }
.garage[data-act="walk"] .car-layer { opacity: .55; }
.call--ring { display: grid; grid-template-rows: none; gap: 1.2rem; justify-items: center; align-content: center; height: auto; }
.call--ring .btn { justify-self: center; align-self: center; }
.car-holder {
  position: relative;
  width: min(62%, 720px);
  margin-bottom: 9%;
  opacity: 0;
  transform: translateY(14px) scale(0.985);
  transition: opacity 1100ms ease 220ms, transform 1400ms cubic-bezier(.2,.7,.25,1) 220ms;
}
.garage[data-car="in"] .car-holder { opacity: 1; transform: none; }
.car-holder img { width: 100%; filter: drop-shadow(0 22px 26px rgb(0 0 0 / 0.55)); }
.car-shadow {
  position: absolute; left: 6%; right: 6%; bottom: -2%; height: 12%;
  background: radial-gradient(ellipse at center, rgb(0 0 0 / 0.62) 0%, rgb(0 0 0 / 0.28) 45%, transparent 72%);
  filter: blur(6px);
}
.car-warm {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse at 40% 8%, rgb(255 190 110 / 0.30), transparent 62%);
  mix-blend-mode: soft-light;
}
/* body-shape fallback when no render is available */
.car-holder svg { width: 100%; height: auto; filter: drop-shadow(0 20px 24px rgb(0 0 0 / 0.6)); }

/* ---------------- atmosphere ---------------- */
.fx { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.grain {
  position: absolute; inset: -50%; z-index: 4; pointer-events: none; opacity: 0.42;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/><feColorMatrix type='saturate' values='0'/></filter><rect width='140' height='140' filter='url(%23n)' opacity='0.5'/></svg>");
  animation: grainShift 720ms steps(3) infinite;
  mix-blend-mode: overlay;
}
@keyframes grainShift {
  0% { transform: translate(0,0); } 33% { transform: translate(-3%,2%); } 66% { transform: translate(2%,-3%); } 100% { transform: translate(0,0); }
}
.vignette {
  position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background:
    radial-gradient(ellipse 120% 90% at 50% 46%, transparent 44%, rgb(3 5 10 / 0.52) 100%),
    linear-gradient(to top, rgb(3 5 10 / 0.58), transparent 30%);
}

/* ---------------- chrome: top bar + always-there quick lane ---------------- */
.g-chrome {
  position: absolute; inset: 0 0 auto; z-index: 30;
  display: flex; align-items: center; gap: 0.7rem;
  padding: calc(var(--header-h) + env(safe-area-inset-top) + 0.4rem) 1rem 0.85rem;
  background: none;
}
.g-chrome .brandmark { color: #fff; text-decoration: none; font-size: 1rem; }
.g-chrome__right { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; }

.chip-btn {
  display: inline-flex; align-items: center; gap: 0.42rem;
  padding: 0.5rem 0.9rem; border-radius: 999px;
  background: rgb(255 255 255 / 0.10); color: #fff;
  border: 1px solid rgb(255 255 255 / 0.20);
  font-size: 0.84rem; font-weight: 600; text-decoration: none;
  backdrop-filter: blur(8px); cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease;
  min-height: 38px;
}
.chip-btn:hover { background: rgb(255 255 255 / 0.19); border-color: rgb(255 255 255 / 0.38); }
.chip-btn--icon { padding: 0.5rem; width: 38px; justify-content: center; }

/* progress: a job card ticking over */
.g-progress {
  position: absolute; left: 50%; translate: -50% 0; bottom: calc(1rem + env(safe-area-inset-bottom));
  z-index: 30; display: flex; gap: 0.35rem; align-items: center;
  opacity: 0; transition: opacity 0.4s ease; pointer-events: none;
}
.garage[data-act]:not([data-act="attract"]) .g-progress { opacity: 1; }
.g-progress i {
  display: block; width: 26px; height: 3px; border-radius: 2px;
  background: rgb(255 255 255 / 0.22); transition: background 0.35s ease;
}
.g-progress i.done { background: var(--accent); }

/* ---------------- act layer ---------------- */
.acts { position: absolute; inset: 0; z-index: 20; display: grid; min-height: 0; }
.act {
  grid-area: 1/1; display: grid; align-content: center; justify-items: center;
  padding: clamp(1rem, 4vw, 2.5rem);
  padding-top: calc(var(--header-h) + 52px + env(safe-area-inset-top));
  padding-bottom: calc(48px + env(safe-area-inset-bottom));
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translateY(10px);
  transition: opacity 0.45s ease, transform 0.5s cubic-bezier(.2,.7,.3,1), visibility 0.45s;
  text-align: center;
  width: 100%;
  min-height: 0; overflow: hidden;
}
/* the call fills the act box so the replies never fall off the bottom edge */
.act[data-act="call"] { align-content: stretch; }
.act[data-act="call"] > .call--ring { align-self: center; }
.act.is-live { opacity: 1; visibility: visible; pointer-events: auto; transform: none; }

/* ---- Act 0: attract ---- */
.attract__kicker {
  font-family: var(--font-display); text-transform: uppercase;
  letter-spacing: 0.2em; font-size: 0.74rem; font-weight: 700;
  color: rgb(255 255 255 / 0.66); margin-bottom: 1rem;
}
.attract h1 {
  font-size: clamp(2.6rem, 9vw, 5.4rem); line-height: 0.95;
  letter-spacing: -0.04em; margin: 0 0 0.5rem;
  text-shadow: 0 6px 40px rgb(0 0 0 / 0.7);
}
.attract h1 em { font-style: normal; color: var(--accent); }
.attract p {
  max-width: 34ch; margin: 0 auto 1.9rem; color: rgb(255 255 255 / 0.84);
  font-size: clamp(1rem, 0.6vw + 0.95rem, 1.2rem);
  text-shadow: 0 2px 18px rgb(0 0 0 / 0.8);
}
.enter-btn {
  font-size: 1.12rem; padding: 1.1rem 2.2rem;
  box-shadow: 0 10px 40px rgb(255 138 30 / 0.45), 0 0 0 0 rgb(255 138 30 / 0.5);
  animation: enterPulse 3.4s ease-in-out infinite;
}
@keyframes enterPulse {
  0%, 100% { box-shadow: 0 10px 40px rgb(255 138 30 / 0.42), 0 0 0 0 rgb(255 138 30 / 0.45); }
  50% { box-shadow: 0 10px 46px rgb(255 138 30 / 0.55), 0 0 0 16px rgb(255 138 30 / 0); }
}
.scroll-hint {
  text-shadow: 0 2px 12px rgb(0 0 0 / 0.9);
  position: absolute; left: 50%; translate: -50% 0;
  bottom: calc(1.1rem + env(safe-area-inset-bottom)); z-index: 25;
  color: rgb(255 255 255 / 0.72); font-size: 0.82rem; text-decoration: none;
  display: inline-flex; align-items: center; gap: 0.4rem;
  transition: color 0.2s ease;
}
.scroll-hint:hover { color: #fff; }
.scroll-hint span { animation: bob 2.4s ease-in-out infinite; }
@keyframes bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(4px); } }

/* ---- THE JOB DOCKET — the clipboard's whole design system ---- */
.docket {
  width: min(100%, 470px);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 30px 70px rgb(0 0 0 / .66), 0 2px 0 rgb(255 255 255 / .35) inset;
  rotate: -.35deg;
  text-align: left;
  color: #16202e;
  animation: docketIn .42s cubic-bezier(.2,.8,.3,1) both;
  position: relative;
}
@keyframes docketIn { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
.docket::before {
  content: ""; position: absolute; left: 50%; top: -14px; translate: -50% 0;
  width: 86px; height: 17px; border-radius: 3px; z-index: 3;
  background: linear-gradient(#dfe3e9, #9aa0a9 55%, #7d838c);
  box-shadow: 0 4px 9px rgb(0 0 0 / .6), 0 1px 0 rgb(255 255 255 / .7) inset;
}

/* header strip */
.docket__head {
  background: linear-gradient(180deg, #16263f, #0d1a2e);
  color: #cfe0f5; padding: .62rem .95rem .55rem;
  display: flex; align-items: center; gap: .6rem;
  border-bottom: 3px solid var(--accent);
}
.docket__head b {
  font-family: var(--font-display); font-size: .72rem; letter-spacing: .18em;
  text-transform: uppercase; font-weight: 800;
}
.docket__serial {
  margin-left: auto; font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .64rem; letter-spacing: .1em; color: #6f8bb0;
}
.docket__step {
  font-family: ui-monospace, Menlo, monospace; font-size: .64rem;
  color: #16263f; background: var(--accent); border-radius: 3px;
  padding: .1rem .34rem; font-weight: 700;
}

/* the paper */
.docket__body {
  background:
    repeating-linear-gradient(180deg, transparent 0 27px, rgb(22 60 120 / .055) 27px 28px),
    url("/assets/img/tex-paper-tile.webp") repeat,
    linear-gradient(158deg, #fdfbf4, #efe9db);
  background-blend-mode: normal, multiply, normal;
  padding: clamp(1rem, 3.4vw, 1.5rem);
  max-height: min(66vh, 620px); overflow-y: auto; scrollbar-width: thin;
}
/* perforated foot */
.docket__foot {
  background: linear-gradient(180deg, #efe9db, #e3dbc9);
  padding: .7rem .95rem calc(.7rem + env(safe-area-inset-bottom));
  border-top: 1px dashed rgb(22 32 46 / .3);
  display: flex; gap: .55rem; align-items: center;
}
.docket__foot .btn { flex: 1; min-height: 50px; }

.docket__q {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.4rem, 5vw, 1.85rem); line-height: 1.1;
  letter-spacing: -.028em; margin: 0 0 .2rem; color: #0e1826;
}
.docket__hint { font-size: .88rem; color: #6b7789; margin: 0 0 1rem; }

/* what's already written on the sheet */
.sheet-lines { display: grid; gap: 0; margin: 0 0 1.05rem; }
.sheet-line {
  display: flex; gap: .7rem; align-items: baseline;
  padding: .28rem 0; border-bottom: 1px solid rgb(22 32 46 / .1);
  animation: inkIn .4s ease both;
}
.sheet-line b {
  color: #8d97a6; font-weight: 700; min-width: 78px; font-size: .66rem;
  text-transform: uppercase; letter-spacing: .1em;
}
.sheet-line span {
  font-family: var(--font-display); font-weight: 600; font-size: .98rem;
  color: #1b3f78; rotate: -.5deg;
}
@keyframes inkIn { from { opacity: 0; transform: translateX(-5px); } to { opacity: 1; transform: none; } }

/* ---- tiles: the main selector ---- */
.tiles { display: grid; gap: .5rem; }
.tiles--2 { grid-template-columns: repeat(2, 1fr); }
.tiles--3 { grid-template-columns: repeat(3, 1fr); }
.tiles--auto { grid-template-columns: repeat(auto-fill, minmax(102px, 1fr)); }

.tile {
  position: relative; cursor: pointer; border: 0; padding: .72rem .6rem;
  border-radius: 12px; background: linear-gradient(180deg, #fff, #f4f0e6);
  box-shadow: 0 1px 0 rgb(255 255 255 / .9) inset, 0 0 0 1.5px rgb(22 32 46 / .13), 0 2px 4px rgb(22 32 46 / .1);
  display: grid; gap: .3rem; justify-items: center; align-content: center;
  font-family: var(--font-display); font-weight: 700; font-size: .92rem;
  color: #16202e; min-height: 58px; text-align: center; line-height: 1.15;
  transition: transform .13s cubic-bezier(.2,.9,.3,1.3), box-shadow .16s ease, background .16s ease;
}
.tile:hover { transform: translateY(-2px); box-shadow: 0 1px 0 rgb(255 255 255 / .9) inset, 0 0 0 1.5px var(--accent), 0 8px 16px rgb(22 32 46 / .16); }
.tile:active { transform: translateY(0) scale(.975); }
.tile.is-sel {
  background: linear-gradient(180deg, #fff6ec, #ffe6cd);
  box-shadow: 0 0 0 2.5px var(--accent), 0 8px 20px rgb(255 138 30 / .3);
}
.tile.is-sel::after {
  content: "✓"; position: absolute; top: -7px; right: -7px;
  width: 22px; height: 22px; border-radius: 50%; background: var(--accent); color: #fff;
  display: grid; place-items: center; font-size: .74rem; font-weight: 800;
  box-shadow: 0 3px 8px rgb(0 0 0 / .3);
  animation: tickPop .28s cubic-bezier(.2,1.5,.4,1) both;
}
@keyframes tickPop { from { transform: scale(0) rotate(-40deg); } to { transform: none; } }
/* The maker's own mark, in ink, with nothing behind it. A wall of identical
   blue plates with a letter on each is the slowest possible way to find your
   own car, and a shape you have looked at every day for years is the fastest. */
.tile__mark {
  width: 30px; height: 30px; display: block; color: #16263f;
  opacity: .88; transition: opacity .15s ease, transform .15s ease;
}
.tile:hover .tile__mark, .tile.is-sel .tile__mark { opacity: 1; transform: scale(1.06); }
.tile.is-sel .tile__mark { color: #0e1826; }
/* and where there is no mark, a letterform of the same weight, still no box */
.tile__mono {
  font-family: var(--font-display); font-weight: 800; font-size: 1.02rem;
  width: 30px; height: 30px; display: grid; place-items: center;
  color: #16263f; letter-spacing: -.04em; opacity: .8;
}
.tile:hover .tile__mono, .tile.is-sel .tile__mono { opacity: 1; }
.tile--wide { grid-column: 1 / -1; flex-direction: row; }
.tile--ghost {
  background: transparent; box-shadow: 0 0 0 1.5px rgb(22 32 46 / .18);
  color: #55627a; font-weight: 600; font-size: .88rem;
}
.tile--ghost:hover { box-shadow: 0 0 0 1.5px var(--accent); color: #16202e; }
/* the car-shape tiles */
.tile--shape { padding: .5rem .4rem .55rem; }
.tile--shape svg { width: 100%; max-width: 92px; height: auto; }
.tile--shape span { font-size: .74rem; font-weight: 700; letter-spacing: -.01em; }

/* ---- paint chips ---- */
.paints { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: .5rem; }
.paint {
  border: 0; padding: 0; cursor: pointer; background: none;
  display: grid; gap: .32rem; justify-items: center; position: relative;
}
.paint i {
  display: block; width: 100%; aspect-ratio: 1.45; border-radius: 10px; position: relative;
  background-color: var(--pc);
  background-image:
    linear-gradient(155deg, rgb(255 255 255 / .5) 0%, rgb(255 255 255 / .05) 32%, rgb(0 0 0 / .08) 56%, rgb(0 0 0 / .38) 100%);
  box-shadow: 0 0 0 1.5px rgb(22 32 46 / .16), 0 3px 7px rgb(22 32 46 / .22);
  transition: transform .14s cubic-bezier(.2,.9,.3,1.3), box-shadow .16s ease;
}
.paint i::after {
  content: ""; position: absolute; left: 8%; right: 42%; top: 9%; height: 22%;
  border-radius: 999px; background: linear-gradient(90deg, rgb(255 255 255 / .5), rgb(255 255 255 / 0));
  filter: blur(1.5px);
}
.paint span { font-size: .68rem; color: #6b7789; font-weight: 700; letter-spacing: -.01em; }
.paint:hover i { transform: translateY(-3px); box-shadow: 0 0 0 1.5px var(--accent), 0 8px 16px rgb(22 32 46 / .3); }
.paint.is-sel i { box-shadow: 0 0 0 3px var(--accent), 0 8px 18px rgb(255 138 30 / .34); transform: translateY(-2px); }

/* ---- year dial ---- */
.dial {
  display: flex; gap: .4rem; overflow-x: auto; padding: .3rem .2rem .6rem;
  scroll-snap-type: x mandatory; scrollbar-width: none; -ms-overflow-style: none;
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.dial::-webkit-scrollbar { display: none; }
.dial button {
  flex: 0 0 auto; scroll-snap-align: center; cursor: pointer;
  min-width: 74px; padding: .68rem .3rem; border: 0; border-radius: 11px;
  font-family: var(--font-display); font-weight: 800; font-size: 1.16rem;
  letter-spacing: -.03em; color: #16202e;
  background: linear-gradient(180deg, #fff, #f2eee3);
  box-shadow: 0 0 0 1.5px rgb(22 32 46 / .13), 0 2px 4px rgb(22 32 46 / .1);
  transition: transform .13s ease, box-shadow .16s ease, color .16s ease;
}
.dial button:hover { transform: translateY(-2px); box-shadow: 0 0 0 1.5px var(--accent), 0 7px 14px rgb(22 32 46 / .16); }
.dial button.is-sel { background: linear-gradient(180deg, #fff6ec, #ffe0be); box-shadow: 0 0 0 2.5px var(--accent); }

/* ---- mechanical odometer ---- */
.odo {
  display: flex; gap: 3px; justify-content: center; padding: .9rem 0 .3rem;
  perspective: 320px;
}
.odo b {
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 700;
  font-size: clamp(1.5rem, 7vw, 2.1rem); line-height: 1;
  width: 1.06em; padding: .3rem 0; text-align: center; border-radius: 5px;
  background: linear-gradient(180deg, #2b3242 0%, #10141d 45%, #232a38 55%, #0b0e15 100%);
  color: #f6f2e6; box-shadow: 0 2px 5px rgb(0 0 0 / .45) inset, 0 1px 0 rgb(255 255 255 / .1);
  position: relative; overflow: hidden;
}
.odo b::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 46%, rgb(0 0 0 / .5) 50%, transparent 54%);
}
.odo b.is-roll { animation: rollDigit .3s cubic-bezier(.3,.9,.3,1) both; }
@keyframes rollDigit { from { transform: translateY(-42%) rotateX(52deg); opacity: .25; } to { transform: none; opacity: 1; } }
.odo em { align-self: flex-end; font-style: normal; color: #6b7789; font-weight: 700; font-size: .8rem; padding-bottom: .5rem; margin-left: .2rem; }

/* ---- inputs on the docket ---- */
.field { display: grid; gap: .55rem; }
.input {
  width: 100%; padding: .88rem 1rem; font-size: 1.06rem;
  border: 0; border-radius: 11px; color: #101a28;
  background: linear-gradient(180deg, #fff, #fbf9f3);
  box-shadow: 0 0 0 1.5px rgb(22 32 46 / .16), 0 1px 3px rgb(22 32 46 / .1) inset;
  font-family: var(--font-body); min-height: 52px;
}
.input:focus { outline: none; box-shadow: 0 0 0 2.5px var(--accent), 0 1px 3px rgb(22 32 46 / .1) inset; }
.input::placeholder { color: #a3abb8; }
.row { display: flex; gap: .55rem; }
.row .input { flex: 1; }
.row select.input { flex: 0 0 108px; }

/* the plate input, styled like a plate */
.rego-input {
  text-transform: uppercase; letter-spacing: .16em; font-weight: 800;
  font-family: var(--font-display); font-size: 1.32rem; text-align: center;
  background: linear-gradient(180deg, #fff, #f0f2f5);
}

.link-btn {
  background: none; border: 0; cursor: pointer; color: #6b7789;
  font-size: .86rem; text-decoration: underline; padding: .55rem .3rem;
}
.link-btn:hover { color: #16202e; }

/* the prominent alternative to a primary action */
.alt-action {
  width: 100%; margin-top: .6rem; cursor: pointer;
  padding: .78rem 1rem; border-radius: 12px; text-align: left;
  background: rgb(22 38 63 / .045); border: 1.5px dashed rgb(22 38 63 / .3);
  color: #2c3a4f; font-size: .92rem; font-weight: 600;
  display: flex; align-items: center; gap: .6rem; min-height: 50px;
  transition: background .16s ease, border-color .16s ease, transform .12s ease;
}
.alt-action:hover { background: rgb(255 138 30 / .1); border-color: var(--accent); color: #16202e; }
.alt-action:active { transform: scale(.99); }
.alt-action b { font-family: var(--font-display); font-weight: 700; display: block; }
.alt-action small { display: block; color: #78849a; font-size: .78rem; font-weight: 500; }
.alt-action span:last-child { margin-left: auto; color: var(--accent); font-size: 1.1rem; }

.disclosure {
  font-size: .72rem; color: rgb(255 255 255 / .62); max-width: 46ch;
  margin: 0 auto; line-height: 1.45;
}
.docket .disclosure { color: #78849a; max-width: none; }

/* ---- Act 2: the light switch ---- */
.switch-cue {
  display: grid; gap: 1.1rem; justify-items: center;
}
.switch-cue p { max-width: 30ch; color: rgb(255 255 255 / 0.86); text-shadow: 0 2px 14px #000; }
/* ---- Act 3: the call ---- */
.call {
  width: min(100%, 480px);
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto auto; gap: 0.7rem;
  height: 100%; max-height: 100%; min-height: 0;
}
/* The chips take exactly what they need and the log gives up the rest. It has
   minmax(0, 1fr) above, so it is the only thing in the call that shrinks.
   Capping the chip row instead was a mistake, it clipped the reply buttons and
   the type something box straight through the middle. Whatever else gets
   squeezed, the thing the seller has to tap must always be whole. */
.replies { flex: none; }
.call__head {
  display: flex; align-items: center; gap: 0.7rem; text-align: left;
  padding: 0.7rem 0.9rem; border-radius: 14px;
  background: rgb(10 16 28 / 0.72); border: 1px solid rgb(255 255 255 / 0.14);
  backdrop-filter: blur(10px);
}
.call__head b { font-family: var(--font-display); font-size: 1rem; display: block; }
.call__head small { color: rgb(255 255 255 / 0.6); font-size: 0.76rem; }
.call__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--green); box-shadow: 0 0 12px var(--green); flex: none; }
.call__log {
  display: flex; flex-direction: column; gap: 0.55rem; overflow-y: auto;
  padding: 0.2rem 0.2rem 0.55rem; text-align: left; scrollbar-width: thin; min-height: 0;
  align-items: flex-start;
  /* so the last bubble clears the edge instead of sitting flush against it */
  scroll-padding-block-end: 0.55rem;
  overscroll-behavior: contain;
}
.call__log .bubble--me { align-self: flex-end; }
.bubble {
  padding: 0.75rem 1rem; border-radius: 16px; font-size: 1rem; line-height: 1.45;
  max-width: 92%; animation: inkIn 0.3s ease both;
}
.bubble--them {
  background: rgb(247 245 240 / 0.96); color: #16202e; border-bottom-left-radius: 5px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.35);
}
.bubble--me {
  background: var(--accent); color: #fff; justify-self: end; border-bottom-right-radius: 5px;
  font-weight: 500;
}
.typing { display: inline-flex; gap: 4px; padding: 0.3rem 0; }
.typing i { width: 7px; height: 7px; border-radius: 50%; background: #9aa4b4; animation: typedot 1.2s infinite; }
.typing i:nth-child(2) { animation-delay: 0.18s; } .typing i:nth-child(3) { animation-delay: 0.36s; }
@keyframes typedot { 0%,60%,100% { opacity: 0.3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-4px); } }

.replies { display: flex; flex-wrap: wrap; gap: 0.45rem; justify-content: center; align-content: end; }
.reply {
  padding: 0.68rem 1rem; border-radius: 999px; cursor: pointer; min-height: 44px;
  background: rgb(255 255 255 / 0.12); color: #fff; border: 1px solid rgb(255 255 255 / 0.28);
  font-size: 0.95rem; font-weight: 600; backdrop-filter: blur(8px);
  transition: background 0.15s ease, transform 0.12s ease;
}
.reply:hover { background: rgb(255 255 255 / 0.24); }
.reply:active { transform: scale(0.96); }
.call__free { display: flex; gap: 0.5rem; }
.call__free .input { background: rgb(255 255 255 / 0.92); }

.disclosure {
  font-size: 0.72rem; color: rgb(255 255 255 / 0.62); max-width: 46ch;
  margin: 0 auto; line-height: 1.45;
}
.paper .disclosure { color: #7a8496; }

/* ---- Act 4: the walk-around ---- */
.walk { width: min(100%, 560px); min-width: 0; display: grid; gap: .8rem; }
.walk__head { display: flex; align-items: baseline; gap: .6rem; justify-content: center; }
.walk__head b { font-family: var(--font-display); font-size: 1.15rem; }
.walk__head small { color: rgb(255 255 255 / .66); }
/* The polaroid wall.
 *
 * min-width 0 on all three of these, and it is not decoration. A grid item
 * defaults to min-width auto, which means it refuses to shrink below the
 * intrinsic width of its contents. The photo cells have labels and a fixed
 * aspect ratio, so their min content width is wider than a phone, and the
 * whole panel simply pushed the page out sideways instead of fitting.
 *
 * On a phone that is not a cosmetic problem. The browser widens the layout
 * viewport to fit the overflow, which pushed it past the 520px breakpoint
 * below, which switched the grid from three columns back to four, which made
 * it wider again. Craig's screenshot is that loop settling: four polaroids
 * across, the last one hanging off the side of the garage over the footer.
 *
 * auto-fit rather than a fixed count so it can never be wrong at a width
 * nobody thought to test. */
.shots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: .55rem;
  min-width: 0;
}
@media (min-width: 560px) { .shots { grid-template-columns: repeat(4, 1fr); } }

/* an empty slot is a pinned blank polaroid waiting for a shot */
.shot {
  position: relative; cursor: pointer; border: 0; padding: 6px 6px 20px;
  min-width: 0;
  border-radius: 3px; aspect-ratio: 3/3.5;
  background: linear-gradient(180deg, #f6f2e8, #e6dfd0);
  box-shadow: 0 6px 16px rgb(0 0 0 / .5), 0 1px 0 rgb(255 255 255 / .55) inset;
  display: grid; grid-template-rows: 1fr auto; gap: 4px;
  transition: transform .16s cubic-bezier(.2,.9,.3,1.3), box-shadow .18s ease;
  rotate: var(--tilt, -1.2deg);
}
.shot:nth-child(2n) { --tilt: 1.4deg; }
.shot:nth-child(3n) { --tilt: -.6deg; }
.shot:nth-child(5n) { --tilt: 1deg; }
.shot::before {
  content: ""; position: absolute; left: 50%; top: -5px; translate: -50% 0; z-index: 3;
  width: 12px; height: 12px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #ff9d44, #b8410b 70%);
  box-shadow: 0 2px 4px rgb(0 0 0 / .55);
}
.shot i {
  display: grid; place-items: center; border-radius: 2px;
  background: repeating-linear-gradient(45deg, #d9d2c3 0 6px, #d2cbbb 6px 12px);
  color: #7d8494; box-shadow: 0 1px 3px rgb(0 0 0 / .18) inset;
}
.shot i svg { width: 26px; height: 20px; opacity: .8; }
.shot span {
  font-size: .6rem; font-weight: 700; color: #4d566b;
  letter-spacing: -.01em; text-align: center; line-height: 1.1;
  font-family: var(--font-display);
}
.shot:hover { transform: translateY(-3px) rotate(0deg); box-shadow: 0 12px 26px rgb(0 0 0 / .6); }
.shot:active { transform: translateY(0) scale(.97); }
.shot.is-done i { background: none; }
.shot.is-done img { width: 100%; height: 100%; object-fit: cover; border-radius: 2px; }
.shot.is-done { box-shadow: 0 8px 20px rgb(0 0 0 / .55), 0 0 0 1.5px rgb(23 138 76 / .5); }
.shot.is-done::after {
  content: "✓"; position: absolute; right: 5px; bottom: 3px; z-index: 2;
  color: var(--green); font-size: .78rem; font-weight: 800;
}
.shot.is-up i { background: rgb(255 138 30 / .3); animation: pulseFade 1.1s ease-in-out infinite; }
@keyframes pulseFade { 0%,100% { opacity: .45; } 50% { opacity: 1; } }

/* ---- Act 5: stamp + card ---- */
.stamp-wrap { display: grid; justify-items: center; gap: 1.2rem; }
.stamp {
  font-family: var(--font-shout); font-size: clamp(3.2rem, 15vw, 7rem);
  color: #d2452f; letter-spacing: 0.04em; line-height: 0.9;
  border: 8px solid #d2452f; border-radius: 12px; padding: 0.1em 0.24em;
  rotate: -9deg; opacity: 0; transform: scale(2.4);
  text-shadow: 0 0 2px rgb(210 69 47 / 0.6);
  mix-blend-mode: normal;
  filter: url(#stampRough);
}
.stamp.is-stamped { animation: stampDown 0.44s cubic-bezier(.2,1.4,.4,1) forwards; }
@keyframes stampDown {
  0% { opacity: 0; transform: scale(2.4) rotate(-14deg); }
  62% { opacity: 1; transform: scale(0.92) rotate(-9deg); }
  100% { opacity: 0.92; transform: scale(1) rotate(-9deg); }
}
.card-shell { width: min(100%, 400px); display: grid; gap: 0.9rem; justify-items: center; }
.card-shell canvas {
  width: 100%; border-radius: 16px; box-shadow: 0 30px 70px rgb(0 0 0 / 0.7);
}
.callback {
  background: rgb(10 16 28 / 0.76); border: 1px solid rgb(255 255 255 / 0.16);
  border-radius: 16px; padding: 1rem 1.2rem; backdrop-filter: blur(10px);
  max-width: 44ch; text-align: left;
}
.callback b { font-family: var(--font-display); display: block; margin-bottom: 0.2rem; }
.callback p { color: rgb(255 255 255 / 0.82); font-size: 0.95rem; margin: 0; }

/* toast */
.toast {
  position: absolute; left: 50%; translate: -50% 0; z-index: 40;
  top: calc(64px + env(safe-area-inset-top));
  background: rgb(8 14 24 / 0.9); border: 1px solid rgb(255 255 255 / 0.18);
  padding: 0.6rem 1rem; border-radius: 999px; font-size: 0.88rem;
  opacity: 0; transition: opacity 0.3s ease, transform 0.3s ease; pointer-events: none;
  transform: translateY(-8px); backdrop-filter: blur(8px); max-width: 90vw;
}
.toast.is-up { opacity: 1; transform: none; }

/* reduced motion + no-JS */
@media (prefers-reduced-motion: reduce) {
  .plate, .car-holder, .act { transition-duration: 0.001ms !important; }
  .grain { animation: none; }
  .enter-btn, .lamp-bloom, .scroll-hint span { animation: none; }
  .stamp.is-stamped { animation: none; opacity: 0.92; transform: rotate(-9deg); }
}
.no-js .garage { height: auto; min-height: 0; }
.no-js .acts { position: static; }
.no-js .act { opacity: 1; visibility: visible; position: static; }

/* desktop refinements */
@media (min-width: 900px) {
  .plate { background-position: center 55%; }
  .car-holder { width: min(48%, 640px); margin-bottom: 8%; }
  .paper { width: 520px; }
}

/* ---- the payoff: what we would expect to pay ----
   The seller has just answered ten questions and taken six photos. Leaving
   them on "he will be in touch" is the moment the whole thing goes flat, so
   this is the thing they came for, printed like a docket figure rather than a
   web price, and honest about being a range rather than an offer. */
.range {
  width: 100%; margin: .1rem 0 .2rem; padding: 1rem 1.1rem 1.05rem;
  border-radius: 16px; text-align: center; color: #16202e;
  background-color: #f2e6c6;
  background-image:
    url("/assets/img/tex-paper-tile.webp"),
    linear-gradient(168deg, rgb(255 255 255 / .5) 0%, rgb(255 255 255 / 0) 46%),
    linear-gradient(180deg, #f7ecd2, #e0cfa6);
  background-blend-mode: multiply, normal, normal;
  background-size: 200px, auto, auto;
  border: 1px solid #c9b489;
  box-shadow: 0 1px 0 rgb(255 255 255 / .55) inset, 0 14px 34px rgb(0 0 0 / .5);
  animation: rangeIn .6s cubic-bezier(.2,.9,.3,1) both;
}
.range__label {
  display: block; font-family: ui-monospace, Menlo, monospace;
  font-size: .62rem; letter-spacing: .16em; text-transform: uppercase;
  color: #7d6a44; margin-bottom: .3rem;
}
.range__figure {
  display: flex; align-items: baseline; justify-content: center;
  gap: .5rem; flex-wrap: wrap;
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.55rem, 7.4vw, 2.3rem); letter-spacing: -.035em;
  line-height: 1.05; color: #10203a;
}
.range__figure i {
  font-style: normal; font-family: var(--font-body); font-weight: 600;
  font-size: .82rem; color: #7d6a44; letter-spacing: .02em;
}
.range__conf {
  display: block; margin-top: .35rem; font-size: .82rem; font-weight: 600; color: #6a5c3e;
}
.range__note {
  margin: .55rem 0 0; font-size: .76rem; line-height: 1.45; color: #6d6552;
  max-width: 40ch; margin-inline: auto;
}
.range--none { text-align: left; }
.range--none b { font-family: var(--font-display); font-size: 1.05rem; display: block; margin-bottom: .3rem; }
.range--none p { margin: 0; font-size: .86rem; line-height: 1.5; color: #5c5443; }
@keyframes rangeIn {
  from { opacity: 0; transform: translateY(14px) rotate(-.8deg); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .range { animation: none; } }

/* The finish act got taller when the range panel went in, so it scrolls now
   rather than clipping the buttons underneath the card. */
.act[data-act="finish"] { align-content: start; overflow-y: auto; overscroll-behavior: contain; }
.act[data-act="finish"] .card-shell { margin-inline: auto; }
/* and nobody is in a hurry once they have finished, so that chip gets out of
   the way of their card */
.garage[data-act="finish"] .g-chrome__right .chip-btn:not(.chip-btn--icon) { display: none; }

/* ==========================================================================
   SEAMLESS SCROLL ON MOBILE

   Craig's note, and it is the right call. The garage was a fixed height box
   with the job card scrolling inside it, the chat scrolling inside that, and
   the finish screen scrolling inside its own. Three nested scrollers on a
   phone. You flick, nothing moves, you flick again and the wrong thing moves.

   On a phone the whole thing now grows with its content and the PAGE scrolls,
   once, the way every other page on the internet does. The artwork goes fixed
   behind it so the room still sits there while you read.

   Desktop keeps the fixed stage, because there the whole card fits and a
   cinematic frame is the point.
   ========================================================================== */
@media (max-width: 900px) {
  .garage {
    height: auto;
    min-height: 100svh;
    /* Vertically visible, because the room behind the paper is position
       sticky and an ancestor that scrolls or hides would pin it to the wrong
       box and break the seamless scroll.

       Horizontally CLIP, not hidden, and the difference matters. hidden makes
       this a scroll container, which breaks the sticky layers exactly the same
       way. clip does not. Without it every deliberately oversized scene layer,
       the plate at inset -2%, the grain at inset -50% with a moving transform,
       is real scrollable page width. On a phone the browser answers that by
       widening the layout viewport, which pushed the page past the breakpoint
       that decides how many photos fit across, which made it wider again.
       That loop is what put a polaroid on top of the footer in Craig's
       screenshot. */
    overflow: visible;
    overflow-x: clip;
  }

  /* The room stays put behind the paper, using STICKY rather than fixed.
     Fixed was wrong. A fixed layer is positioned against the viewport and has
     no idea the garage has ended, so the dusk plate kept rendering behind the
     footer at the bottom of the page. Sticky is bounded by its own container,
     so the artwork pins while you read the job card and stops dead at the end
     of the garage, which is exactly what it should do.

     The negative margin is what stops each layer adding a screen of height to
     the page. They pin, they paint, they take up no room. */
  .stage, .lamp-bloom, .fx, .grain, .vignette, .car-layer {
    position: sticky; inset: auto; top: 0;
    width: 100%; height: 100svh; margin-bottom: -100svh;
  }
  .car-layer { pointer-events: none; }

  .acts { position: relative; inset: auto; display: block; min-height: 100svh; }
  .act {
    grid-area: auto; display: none; overflow: visible;
    min-height: 100svh; height: auto;
    align-content: start;
  }
  .act.is-live { display: grid; }

  /* nothing scrolls inside anything */
  .docket__body { max-height: none; overflow: visible; }
  .call {
    height: auto; max-height: none;
    grid-template-rows: auto auto auto auto;
  }
  .call__log { overflow: visible; max-height: none; }
  .act[data-act="finish"] { overflow: visible; }

  /* The chat header follows you down, because on a long call you lose track of
     who you are talking to. It has to be OPAQUE though. Half transparent, the
     bubbles slide up underneath it and you get two overlapping messages, which
     reads as a rendering fault rather than a design. */
  .call__head {
    /* Flush under the site header, not 6px below it.
     *
     * Those six pixels were a slot, and a bubble scrolling up behind the
     * header showed through them as a white sliver between two dark bars. It
     * is in Craig's first screenshot of this screen and it reads as a
     * rendering fault, which is the one thing a game cannot afford to look
     * like. There is nothing to gain from a gap here and everything to lose. */
    position: sticky; top: var(--header-h); z-index: 6;
    background: #10161f;
    box-shadow: 0 10px 20px rgb(5 7 12 / .55);
  }
  /* And the site header needs a floor under it during the call, otherwise a
     bubble slides up behind a see through bar and reads as a rendering fault.
     Only during the call, because everywhere else the transparent header over
     the garage art is the whole point. */
  .garage[data-act="call"] ~ * .site-header,
  body.has-garage:has(.garage[data-act="call"]) .site-header {
    background: linear-gradient(180deg, rgb(5 7 12 / .95), rgb(5 7 12 / .82));
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  }
  /* and the replies sit at the bottom of the screen where a thumb already is */
  .replies {
    /* A real floor under the thumb, not one built out of a number that is
     * usually zero.
     *
     * env(safe-area-inset-bottom) is 0 in Chrome on Android even though the
     * gesture bar still draws over the page, so a padding made only of that
     * inset collapses to nothing on exactly the phones most sellers hold, and
     * looks perfect on every desktop it is checked on. Craig: "it's nearly
     * cutting off the button down the bottom."
     *
     * max() keeps the notch handling on the phones that report one and
     * guarantees the rest a thumb's worth of air regardless. */
    position: sticky; bottom: 0; z-index: 5;
    padding: .6rem .2rem calc(.6rem + max(14px, env(safe-area-inset-bottom)));
    margin-inline: -.2rem;
    background: linear-gradient(180deg, rgb(5 7 12 / 0), rgb(5 7 12 / .82) 22%);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  }

  /* the scroll hint belongs to a screen that does not scroll, so it goes */
  body.has-garage .scroll-hint { display: none; }
}


/* ==========================================================================
   STAYING IN THE ROOM

   Craig got seven photos into the walk around, swiped, and came out the
   bottom of the garage into the marketing copy with the polaroids still
   hanging over it. Whatever else was wrong with that screen, the swipe itself
   is the thing that breaks the spell. You do not get to accidentally leave a
   room you are in the middle of doing something in.

   So while a job is actually underway, the page below the garage is not
   rendered at all. Not covered, not scrolled past, not there. A swipe finds
   nothing to move to and the room simply stays put, which is a much better
   feeling than being caught and snapped back.

   Not rendered rather than hidden behind a lock, because the alternatives are
   all worse. Fixing the body position loses the scroll offset and jumps.
   Clamping scroll in JS fights the finger and feels broken on a phone. This
   just removes the destination.

   It is only ever on once the seller has started, so the first paint, and
   anything crawling the page, still gets the whole thing.
   ========================================================================== */
body[data-busy="true"] > #story,
body[data-busy="true"] > .site-footer {
  display: none;
}
/* The garage becomes the whole document while they are in it, so there is no
   stray tail of page under the last act to bounce against. */
body[data-busy="true"] { overscroll-behavior-y: contain; }
