/* snuug.app/style-quiz, on top of base.css: the app's taste test as one screen. A picture of the taste room, one
   slider under it (the app's dimmer: research/taste-test-v3.json, mechanic.keep_exactly) and one button. Then the
   style card, the same object as the home page's (how.css, .holo-card) and the app's (StyleCardFront.swift): the
   style's own ink, its pixel-art room, the name in Inter Light.
   Speed: everything that moves is a transform or an opacity on its own layer (the knob, the fill, the stacked
   pictures, the card), and quiz.js writes them once per frame. Nothing here animates by itself. */

/* ---------- The screen. On a phone the quiz fills the first screen exactly (100svh), and the picture takes the
   height that is left, so the picture, the slider and the button are always on screen together. */
.quiz { display: flex; min-height: 100svh; padding: calc(80px + env(safe-area-inset-top, 0px)) 0 calc(16px + env(safe-area-inset-bottom, 0px)); }
.quiz-in { display: flex; flex-direction: column; min-height: 0; max-width: calc(460px + 2 * var(--gutter)); }
.q-nojs { margin-top: 18px; }
.q-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 16px; }
.quiz [hidden] { display: none !important; }   /* BUG-389: the parts below set their own display, which beats the browser's [hidden] rule */
.q-steps { display: flex; gap: 4px; margin: 0; padding: 0; list-style: none; }
.q-steps li { width: 18px; height: 4px; border-radius: 2px; background: var(--line); transition: background-color 0.4s; }
.q-steps li.now { background: var(--ink); }

.ask { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(180px, 1fr) auto auto; min-height: 0; transition: opacity 0.25s; }
.ask.out { opacity: 0; }
/* The question: one line on every phone (the longest, "How should your living room feel?", fits 320 px at 5.7vw). */
.q-title { margin-top: 10px; font-size: clamp(20px, 5.7vw, 27px); font-weight: 300; letter-spacing: -0.03em; line-height: 1.2; white-space: nowrap; }

/* The picture: the set's stills stacked, the first at the bottom. quiz.js fades each one in over the one below as
   the knob passes its stop, so a drag blends neighbours and nothing is decoded or laid out on the way. Two decks:
   the next question's set fades in over the last one. */
.q-pic { position: relative; margin-top: 12px; border-radius: 18px; overflow: hidden; background: var(--surface); isolation: isolate; }
.q-pic .deck { position: absolute; inset: 0; opacity: 0; transition: opacity 0.45s var(--ease), transform 0.6s var(--ease); transform: scale(1.04); }
.q-pic .deck.on { opacity: 1; transform: none; }
.q-pic img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 58%; will-change: opacity; -webkit-user-select: none; user-select: none; pointer-events: none; }
/* The stop's name on the picture, white on a soft dark fade. */
.q-pic::after { content: ""; position: absolute; inset: auto 0 0; height: 88px; background: linear-gradient(transparent, rgb(12 12 10 / 0.42)); pointer-events: none; }
.q-stop { position: absolute; left: 16px; bottom: 14px; z-index: 1; color: #FFF; font-size: 20px; font-weight: 500; letter-spacing: -0.015em; line-height: 1; }

/* ---------- The dimmer: a 44 px pill track with a stop dot at each answer, a fill in the stop's colour (the app's
   taste ribbon) and one big white knob. The stops sit half a knob in from each end (--in), so the knob rests flush with the track's end. The real
   control is the range input laid over it, invisible: the keyboard and screen readers use it, and quiz.js follows
   it. A finger drags anywhere on the track; touch-action: pan-y leaves an up or down swipe to the page. */
.dim { --tint: #151514; --in: 27px; position: relative; height: 54px; margin-top: 16px; touch-action: pan-y; cursor: pointer; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.dim-track { position: absolute; inset: 5px 0; border-radius: 22px; background: rgb(21 21 20 / 0.08); overflow: hidden; isolation: isolate; }
.dim-fill { position: absolute; inset: 0; transform: translateX(calc(-100% + var(--in))); will-change: transform; }
.dim-fill i { position: absolute; inset: 0; opacity: 0; transition: opacity 0.165s; }
.dim-fill i.on { opacity: 1; }
.dim-dots { position: absolute; inset: 0 var(--in); }
.dim-dots i { position: absolute; top: 50%; width: 6px; height: 6px; margin: -3px; border-radius: 50%; background: rgb(21 21 20 / 0.3); }
.dim-dots i.in { background: rgb(255 255 255 / 0.8); }
.dim-run { position: absolute; inset: 0 var(--in); pointer-events: none; }
/* The knob's carrier has no width: quiz.js moves it in px along the run. (BUG-388: as a box as wide as the run, moved
   by a share of its own width, it reached past the screen's right edge and made the page scroll sideways.) */
.dim-at { position: absolute; left: 0; top: 0; width: 0; height: 100%; will-change: transform; }
.dim-knob { position: absolute; left: -27px; top: 0; width: 54px; height: 54px; border-radius: 50%; background: #FFF;
  box-shadow: 0 0 0 0.5px rgb(20 20 18 / 0.08), 0 1px 2px rgb(20 20 18 / 0.2), 0 8px 16px -6px rgb(20 20 18 / 0.34);
  transition: transform 0.22s cubic-bezier(0.3, 1.5, 0.5, 1); }
/* Held: the knob grows to 64 px and a soft ring in the stop's colour opens round it (a box of its own behind the
   knob, so only its opacity and scale change). */
.dim-at::before { content: ""; position: absolute; left: -41px; top: -14px; width: 82px; height: 82px; border-radius: 50%; background: var(--tint); opacity: 0; transform: scale(0.7);
  transition: opacity 0.22s, transform 0.22s cubic-bezier(0.3, 1.5, 0.5, 1); }
.dim.held .dim-knob { transform: scale(1.185); }
.dim.held .dim-at::before { opacity: 0.24; transform: none; }
/* The knob slides back to the left for the next question, and nods when an answer is chosen. */
.dim.back .dim-at, .dim.back .dim-fill { transition: transform 0.5s var(--ease); }
.dim.nod .dim-knob { animation: knob-nod 0.42s cubic-bezier(0.3, 1.5, 0.5, 1); }
@keyframes knob-nod { 35% { transform: scale(0.86); } }
.dim-input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; pointer-events: none; font-size: 16px; }
.dim:has(.dim-input:focus-visible) .dim-knob { outline: 2px solid var(--ink); outline-offset: 3px; }

.q-row { display: flex; gap: 10px; margin-top: 14px; }
.q-go { flex: 1; height: 52px; padding: 0 22px; border: 0; border-radius: 999px; background: var(--ink); color: #FFF; font-size: 16px; font-weight: 500; letter-spacing: -0.005em; cursor: pointer;
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), background-color 0.25s, box-shadow 0.25s; }
.q-back { flex: none; display: grid; place-items: center; width: 52px; height: 52px; padding: 0; border: 0; border-radius: 50%; background: var(--tint); cursor: pointer;
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), background-color 0.25s; }
.q-back svg { width: 22px; height: 22px; fill: none; stroke: var(--ink); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
@media (hover: hover) { .q-go:hover { background: #2B2B29; } .q-back:hover { background: #E2E2DE; } }
.q-go:active { transform: scale(0.98); box-shadow: inset 0 2px 5px rgb(0 0 0 / 0.5); transition-duration: 0.12s; }
.q-back:active { transform: scale(0.94); transition-duration: 0.12s; }

/* ---------- The result. --w is the card's width: 300 px, less on a short screen (270 px on an iPhone's 664 px), so
   the card, the style's line, the App Store badge, Share and the two links share the first screen. --c is one point
   of the card: every size on it is a number of points, so the card scales as one object (the app draws it 360 pt wide). */
.reveal { --w: clamp(232px, calc((100svh - 334px) / 1.22), 300px); --c: calc(var(--w) / 300); flex: 1; display: grid; justify-items: center; align-content: start; }
.scard { --ground: #1A1512; --accent: #D2A06A; --mx: 50%; --my: 30%;
  position: relative; width: var(--w); height: calc(var(--w) * 1.22); perspective: 1100px; cursor: pointer; -webkit-user-select: none; user-select: none; }
/* Two turns, each on its own box: .tilt leans towards a mouse (quiz.js), .flip turns the card over. The flip's easing
   is symmetric, so the card is edge-on exactly half way through, when the faces change over (below). */
.scard .tilt, .scard .flip { position: absolute; inset: 0; transform-style: preserve-3d; }
.scard .tilt { transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1); }
.scard .flip { transition: transform 0.6s cubic-bezier(0.45, 0, 0.55, 1); }
.scard.isback .flip { transform: rotateY(180deg); }
.face { position: absolute; inset: 0; margin: 0; border-radius: calc(var(--c) * 20); overflow: hidden; color: #FFF; -webkit-backface-visibility: hidden; backface-visibility: hidden;
  background: radial-gradient(130% 55% at 50% 100%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 70%), var(--ground);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.18), 0 26px 44px -22px rgb(0 0 0 / 0.55); }
/* The face turned away is hidden by hand too, half way through the turn (the card is edge-on then): WebKit hit-tests
   a face turned away, and headless WebKit flattens CSS 3D, where backface-visibility hides nothing (BUG-007). */
.face { transition: opacity 0s 0.3s, visibility 0s 0.3s; }
.scard:not(.isback) .back, .scard.isback .front { opacity: 0; visibility: hidden; }
.face.back { transform: rotateY(180deg); display: flex; flex-direction: column; padding: calc(var(--c) * 24) calc(var(--c) * 24) calc(var(--c) * 52); }
/* The rim: a light inset line, so the card's edge stays crisp on every ink (how.css). */
.face::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.1), inset 0 1px 0 rgb(255 255 255 / 0.14); }
/* The style's room in pixel art (120 x 96, drawn 2.5 times its size): its last rows dither out into the card's ink. */
.front .art { position: absolute; inset: 0 0 auto; width: 100%; height: auto; aspect-ratio: 120 / 96; image-rendering: pixelated; }
/* The holo: a faint rainbow and a glare (how.css); it follows a mouse, and rests on a phone. */
.face .holo { position: absolute; inset: 0; pointer-events: none; mix-blend-mode: screen; opacity: 0.07;
  background: radial-gradient(circle at var(--mx) var(--my), rgb(255 255 255 / 0.4), transparent 42%), linear-gradient(115deg, transparent 18%, #FF6AA8 30%, #FFD56B 39%, #7DFFB4 48%, #68D6FF 57%, #B78CFF 66%, transparent 78%);
  background-size: 100% 100%, 260% 260%; background-position: 0 0, var(--mx) var(--my); }
.face .kick { display: block; margin: 0; font-size: calc(var(--c) * 13); font-weight: 500; line-height: calc(var(--c) * 16); letter-spacing: 0.01em; color: rgb(255 255 255 / 0.56); }
.front .words { position: absolute; left: calc(var(--c) * 24); right: calc(var(--c) * 24); bottom: calc(var(--c) * 50); margin: 0; }
.front .name { display: block; margin-top: calc(var(--c) * 4); font-size: calc(var(--c) * 40); font-weight: 300; line-height: calc(var(--c) * 46); letter-spacing: -0.045em; white-space: nowrap; }
/* (.cfoot, not .foot: that is the page's footer in base.css.) */
.face .cfoot { position: absolute; left: calc(var(--c) * 24); right: calc(var(--c) * 24); bottom: calc(var(--c) * 22); display: flex; align-items: center; justify-content: space-between; height: calc(var(--c) * 14); margin: 0; }
.face .wm { width: calc(var(--c) * 58); height: calc(var(--c) * 14); margin-left: auto; color: #FFF; opacity: 0.92; }
/* The taste ribbon: the colour of each answer, in order. Empty on a shared card: it has no answers. */
.ribbon { display: flex; height: calc(var(--c) * 6); }
.ribbon i { width: calc(var(--c) * 18); height: 100%; }
.back .feel { margin: calc(var(--c) * 10) 0 0; font-size: calc(var(--c) * 19); font-weight: 300; line-height: calc(var(--c) * 25); letter-spacing: -0.02em; text-wrap: balance; }
.back .facts { display: grid; gap: calc(var(--c) * 8); margin-top: auto; }
.back .facts li { position: relative; padding-left: calc(var(--c) * 16); font-size: calc(var(--c) * 14); line-height: calc(var(--c) * 20); color: rgb(255 255 255 / 0.76); text-wrap: pretty; }
.back .facts li::before { content: ""; position: absolute; left: 0; top: calc(var(--c) * 7.5); width: calc(var(--c) * 5); height: calc(var(--c) * 5); background: var(--accent); }
/* One control, top right on both sides: it turns the card (so does a tap anywhere on it). 36 px, with a 44 px target. */
.turn { position: absolute; top: 10px; right: 10px; z-index: 2; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 50%; background: rgb(12 12 14 / 0.46); color: #FFF; cursor: pointer;
  box-shadow: inset 0 0 0 0.7px rgb(255 255 255 / 0.24); transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }
.turn::before { content: ""; position: absolute; inset: -4px; }
.turn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transition: transform 0.6s cubic-bezier(0.45, 0, 0.55, 1); }
.scard.isback .turn svg { transform: rotate(180deg); }
.turn:active { transform: scale(0.9); }
.turn:focus-visible { outline: 2px solid #FFF; outline-offset: 2px; }
/* The card arrives: it rises and settles with a small bounce; the words under it follow. */
.reveal.in .scard { animation: card-in 0.8s cubic-bezier(0.3, 1.3, 0.5, 1) both; }
.reveal.in .r-txt { animation: txt-in 0.6s var(--ease) 0.3s both; }
@keyframes card-in { from { opacity: 0; transform: translateY(28px) scale(0.94); } 40% { opacity: 1; } }
@keyframes txt-in { from { opacity: 0; transform: translateY(10px); } }

.r-txt { width: 100%; max-width: 340px; margin-top: 16px; text-align: center; }
.r-name:focus { outline: 0; }
.r-name span { white-space: nowrap; }
.r-line { font-size: 15px; line-height: 22px; color: var(--muted); text-wrap: balance; }
.r-streak { margin-top: 4px; font-size: 15px; line-height: 22px; }
.r-streak a, .r-links a { text-underline-offset: 3px; text-decoration-color: var(--soft); }
.r-txt .cta { flex-wrap: nowrap; justify-content: center; gap: 10px; margin-top: 16px; }
.r-txt .ghost { border: 0; cursor: pointer; }
.r-txt .micro { margin-top: 12px; }
/* One row on every phone: the longest, "Read about Mid-century modern" and "Retake", is 285 px. */
.r-links { display: flex; justify-content: center; gap: 4px 22px; flex-wrap: wrap; margin-top: 2px; font-size: 15px; }
.r-links a, .r-links button { display: inline-flex; align-items: center; min-height: 44px; }
.r-links button { padding: 0; border: 0; background: none; color: var(--muted); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--soft); }
@media (hover: hover) { .r-links button:hover { color: var(--ink); } .r-streak a:hover, .r-links a:hover { text-decoration-color: currentColor; } }
/* On a phone the card carries the name, and it starts right under the bar: the result's heading and the page's
   small heading stay for screen readers only. */
@media (max-width: 899px) {
  .r-name, .quiz.done .q-top, .is-result .q-top { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .quiz.done, .is-result .quiz { padding-top: calc(76px + env(safe-area-inset-top, 0px)); }
}

/* BUG-387: a shared result (quiz-boot.js marks the page before it paints): no question, no steps. */
.is-result .ask, .is-result .q-steps, .quiz.done .q-steps { display: none; }

/* ---------- Under the quiz: what it is, the 14 styles, the questions. */
.about { padding-top: var(--space); }
.style-list { display: grid; gap: 10px; max-width: 980px; margin: var(--head) auto 0; }
.style-list a { display: grid; grid-template-columns: 80px minmax(0, 1fr); align-items: center; gap: 14px; padding: 10px 16px 10px 10px; border-radius: 18px; background: var(--surface); text-decoration: none; transition: background-color 0.25s; }
.style-list img { width: 80px; height: 64px; border-radius: 10px; image-rendering: pixelated; }
.style-list span { display: grid; gap: 2px; font-size: 15px; line-height: 1.4; color: var(--muted); text-wrap: pretty; }
.style-list b { font-size: 17px; font-weight: 500; letter-spacing: -0.015em; color: var(--ink); }
@media (hover: hover) { .style-list a:hover { background: var(--tint); } }
@media (hover: none) { .style-list a:active { background: var(--tint); } }
@media (min-width: 720px) { .style-list { grid-template-columns: 1fr 1fr; gap: 12px; } .style-list a { grid-template-columns: 90px minmax(0, 1fr); gap: 16px; padding-right: 18px; } .style-list img { width: 90px; height: 72px; } }

/* ---------- A wide screen: the picture on the left at its own 3:4, the question and the dimmer beside it; the card
   on the left, its words beside it. */
@media (min-width: 900px) {
  .quiz { min-height: min(100svh, 900px); padding: 116px 0 56px; }
  .quiz-in { max-width: calc(950px + 2 * var(--gutter)); }
  .q-top { justify-content: flex-start; gap: 20px; }
  .ask { grid-template-columns: minmax(0, 420px) minmax(0, 420px); grid-template-rows: 1fr auto auto auto 1fr; column-gap: 48px; justify-content: space-between; align-items: start; margin-top: 28px; }
  .q-pic { grid-column: 1; grid-row: 1 / -1; align-self: center; margin: 0; aspect-ratio: 3 / 4; width: 100%; max-height: calc(100svh - 230px); border-radius: 24px; }
  .q-pic img { object-position: 50% 50%; }
  .q-stop { left: 22px; bottom: 20px; font-size: 22px; }
  .q-title { grid-column: 2; grid-row: 2; margin: 0; font-size: clamp(40px, 3.6vw, 52px); letter-spacing: -0.04em; line-height: 1.05; white-space: normal; text-wrap: balance; }
  .dim { grid-column: 2; grid-row: 3; margin-top: 44px; }
  .q-row { grid-column: 2; grid-row: 4; margin-top: 20px; }
  .reveal { --w: clamp(280px, calc((100svh - 300px) / 1.22), 360px); grid-template-columns: auto minmax(0, 440px); column-gap: 48px; justify-content: space-between; align-content: center; align-items: center; padding-top: 28px; }
  .r-txt { max-width: none; margin: 0; text-align: left; }
  .r-name { font-size: clamp(44px, 4.4vw, 64px); font-weight: 300; letter-spacing: -0.045em; line-height: 1.02; text-wrap: balance; }
  .r-line { margin-top: 18px; font-size: 19px; line-height: 1.5; }
  .r-streak { margin-top: 8px; font-size: 17px; }
  .r-txt .cta { justify-content: flex-start; margin-top: 28px; }
  .r-txt .micro { margin-top: 14px; }
  .r-links { justify-content: flex-start; margin-top: 6px; }
}

@media (prefers-reduced-motion: reduce) {
  .q-pic .deck { transform: none; }
  .scard .flip, .scard.isback .flip, .scard .tilt { transform: none; }
  .face.back { transform: none; }
  .face { transition: opacity 0.2s, visibility 0.2s; }
  .reveal.in .scard, .reveal.in .r-txt, .dim.nod .dim-knob { animation: none; }
}
@media print { .ask, .turn { display: none; } }
