/* DECOSWITCH — Bracket Finder.
   Architectural, near-black, brass accent. The plate images carry the piece;
   the chrome stays quiet so the only thing to look at is the choice. */

:root {
  --ink: #0b0b0c;
  --ink-2: #131315;
  --ink-3: #1c1c1f;
  --line: #2a2a2e;
  --paper: #f4f2ee;
  --muted: #8d8b87;
  --brass: #c8a96a;
  --brass-dim: #7d6a42;
  --hazard: #f2b21a;
  --danger: #d8624a;

  --pad: clamp(1.25rem, 4vw, 2.5rem);
  --radius: 2px;

  --sans: ui-sans-serif, "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  --ease: cubic-bezier(0.16, 0.84, 0.34, 1);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

.is-hidden { display: none !important; }

img { max-width: 100%; display: block; }

/* ------------------------------------------------------------ test mode -- */

.test-banner {
  position: sticky;
  top: 0;
  z-index: 50;
  padding: 0.7rem var(--pad);
  background: repeating-linear-gradient(
    45deg, var(--hazard), var(--hazard) 14px, #0b0b0c 14px, #0b0b0c 28px
  );
  color: var(--ink);
  text-align: center;
}
.test-banner span {
  display: inline-block;
  background: var(--hazard);
  color: #000;
  padding: 0.35rem 0.9rem;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
/* Hazard frame around the whole viewport — you cannot mistake this for prod. */
body.is-test::after {
  content: "";
  position: fixed;
  inset: 0;
  border: 3px solid var(--hazard);
  pointer-events: none;
  z-index: 49;
}

/* -------------------------------------------------------------- top bar -- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--pad);
  flex: 0 0 auto;
}
.brand {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.34em;
}
.lang { font-size: 0.72rem; letter-spacing: 0.14em; color: var(--muted); }
.lang-link { color: var(--muted); text-decoration: none; padding: 0.25rem; }
.lang-link.is-active { color: var(--paper); }
.lang-sep { opacity: 0.4; }

/* --------------------------------------------------------------- stage -- */

.stage {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  padding: 0 var(--pad) var(--pad);
}

.screen {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  animation: rise 0.5s var(--ease) both;
}
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

.home-inner, .question-inner, .winner-inner, .email-inner, .thanks-inner {
  width: 100%;
  max-width: 46rem;
  margin: 0 auto;
  text-align: center;
}

/* --------------------------------------------------------- home teaser -- */

.bracket-teaser {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.6rem, 2vw, 1.1rem);
  margin: 0 auto 1.75rem;
  height: 4.5rem;
}
.bt-col { display: flex; flex-direction: column; justify-content: center; gap: 0.4rem; }
.bt-col + .bt-col { gap: 0.9rem; }
.bt-slot {
  width: clamp(1.5rem, 4vw, 2.1rem);
  height: clamp(1.5rem, 4vw, 2.1rem);
  border: 1px solid var(--line);
  background: var(--ink-2);
  transition: border-color 0.4s var(--ease), background 0.4s var(--ease), transform 0.4s var(--ease), opacity 0.4s var(--ease);
}
.bt-slot.is-live { border-color: var(--brass-dim); }
.bt-slot.is-winner { border-color: var(--brass); background: var(--brass); transform: scale(1.08); }
.bt-slot.is-out { opacity: 0.15; transform: scale(0.85); }

.display {
  font-size: clamp(2.1rem, 7vw, 4rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  font-weight: 700;
  margin: 0 0 1rem;
}
.title {
  font-size: clamp(1.5rem, 4.2vw, 2.4rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-weight: 700;
  margin: 0 0 0.75rem;
}
.lede {
  font-size: clamp(0.95rem, 2.1vw, 1.1rem);
  line-height: 1.55;
  color: var(--muted);
  margin: 0 auto 2rem;
  max-width: 34rem;
}
.step {
  font-size: 0.7rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 0 0 0.9rem;
}

/* ------------------------------------------------------------- buttons -- */

.actions {
  display: flex;
  gap: 0.75rem;
  justify-content: center;
  flex-wrap: wrap;
  align-items: center;
}
.btn {
  appearance: none;
  border: 1px solid transparent;
  border-radius: var(--radius);
  padding: 0.95rem 1.9rem;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease), border-color 0.25s var(--ease);
}
.btn-primary { background: var(--paper); color: var(--ink); }
.btn-primary:hover { background: var(--brass); }
.btn-ghost { background: transparent; color: var(--muted); border-color: var(--line); }
.btn-ghost:hover { color: var(--paper); border-color: var(--muted); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ----------------------------------------------------------- questions -- */

.options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 0.6rem;
  margin-top: 1.5rem;
}
/* The room question (5 options): a fixed 3 columns reads as 3 then 2 rather
   than an auto-fit count that shifts with viewport width. */
.options.options--room {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  max-width: 34rem;
  margin-left: auto;
  margin-right: auto;
}
@media (max-width: 480px) {
  .options.options--room { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.option {
  appearance: none;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--paper);
  padding: 1.15rem 1rem;
  font: inherit;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease), transform 0.2s var(--ease);
}
.option:hover:not(:disabled) { border-color: var(--brass); background: var(--ink-3); transform: translateY(-2px); }
.option:disabled { opacity: 0.28; cursor: not-allowed; }
.option .count {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  color: var(--muted);
}
.option .icon {
  display: block;
  width: 1.6rem;
  height: 1.6rem;
  margin: 0 auto 0.6rem;
  color: var(--brass);
}
.option .icon svg { width: 100%; height: 100%; }

/* ------------------------------------------------------- wall chooser -- */

.wall-inner { width: 100%; max-width: 62rem; margin: 0 auto; text-align: center; }

/* Left swatches / centre "your own wall" / right swatches — the upload is
   the option being pushed, so it gets the middle and more room, not one tile
   lost among sixteen equals. */
.wall-layout {
  display: flex;
  align-items: stretch;
  gap: clamp(0.6rem, 2vw, 1.25rem);
  margin: 1.5rem 0 1rem;
}
.wall-side {
  flex: 1 1 0;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-content: start;
  gap: 0.5rem;
}

.wall-tile {
  appearance: none;
  position: relative;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--ink-2) center / cover no-repeat;
  cursor: pointer;
  padding: 0;
  overflow: hidden;
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.wall-tile:hover { border-color: var(--brass); transform: translateY(-2px); }
.wall-tile span {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 0.3rem 0.45rem;
  font-size: 0.62rem;
  letter-spacing: 0.03em;
  color: var(--paper);
  background: linear-gradient(0deg, rgba(0,0,0,0.72), transparent);
  text-align: left;
}

/* The custom-photo tile: centred, taller than the swatches either side of
   it (stretches to match their combined grid height), unmistakably the
   featured option rather than one more swatch. */
.wall-tile.is-custom {
  flex: 0 0 auto;
  width: clamp(8.5rem, 21vw, 12.5rem);
  aspect-ratio: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  background-color: var(--ink-2);
  border-style: dashed;
  border-color: var(--brass-dim);
  color: var(--brass);
  padding: 1rem;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  text-align: center;
}
.wall-tile.is-custom.has-photo { border-style: solid; border-color: var(--brass); background-size: cover; background-position: center; color: var(--paper); }
.wall-tile.is-custom.has-photo span.custom-label {
  background: rgba(11,11,12,0.6);
  padding: 0.35rem 0.6rem;
  border-radius: var(--radius);
}

/* A small looping scene — a dashed "wall" outline, a camera that dips in for
   a shot, a flash — standing in for a real photo until one is taken. Pure
   CSS, no JS timer needed since it's decorative and loops on its own. */
.cam-scene {
  position: relative;
  width: 2.6rem;
  height: 2.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
}
.cam-wall {
  position: absolute;
  inset: 0.3rem;
  border: 1px dashed var(--brass-dim);
  border-radius: 2px;
}
.cam-flash {
  position: absolute;
  inset: 0.3rem;
  border-radius: 2px;
  background: var(--paper);
  opacity: 0;
  animation: cam-flash 2.8s ease-in-out infinite;
}
.cam-icon {
  position: relative;
  z-index: 2;
  width: 1.5rem;
  height: 1.5rem;
  color: var(--brass);
  animation: cam-bob 2.8s ease-in-out infinite;
}
.cam-icon svg { width: 100%; height: 100%; }
@keyframes cam-bob {
  0%, 68%, 100% { transform: translateY(0) scale(1); }
  76%           { transform: translateY(-2px) scale(0.92); }
  84%           { transform: translateY(0) scale(1.04); }
  92%           { transform: translateY(0) scale(1); }
}
@keyframes cam-flash {
  0%, 74%, 100% { opacity: 0; }
  80%           { opacity: 0.9; }
  90%           { opacity: 0; }
}

@media (max-width: 760px) {
  .wall-layout { flex-direction: column; }
  .wall-tile.is-custom { width: 100%; aspect-ratio: 16 / 6; order: -1; }
  .wall-side { grid-template-columns: repeat(3, 1fr); }
}

/* ----------------------------------------------------------------- --- */

/* --------------------------------------------------------------- arena -- */

/* Screen-arena becomes the positioning context so the wallpaper can sit
   full-bleed behind arena-head + arena without disturbing their layout. */
#screen-arena { position: relative; }
.arena-wallbg {
  position: absolute;
  inset: calc(var(--pad) * -1);
  background: center / cover no-repeat;
  z-index: 0;
}
/* Scrim is deliberately light through the middle band, where the plates sit —
   strong enough only at the very top/bottom to keep the round name and hint
   text legible. A heavy scrim across the whole thing was the original bug:
   it read as a darkened page background rather than a wall the plates were
   actually mounted on. */
.arena-wallbg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    var(--ink) 0%, rgba(11,11,12,0.35) 14%,
    rgba(11,11,12,0.08) 30%, rgba(11,11,12,0.08) 70%,
    rgba(11,11,12,0.35) 86%, var(--ink) 100%
  );
}
.arena-head, .arena, .hint { position: relative; z-index: 1; }

/* When a wall is behind the arena, the card chrome steps aside so the plate
   image — a transparent cutout render — sits directly on that wall instead
   of floating in an opaque dark box. Only the meta strip keeps a translucent
   plate to hold the title legible over an arbitrary photo. */
.arena.has-wall .plate-card { background: transparent; border-color: transparent; }
.arena.has-wall .plate-card:hover { border-color: rgba(200,169,106,0.4); }
.arena.has-wall .plate-media { background: transparent; }
.arena.has-wall .plate-meta {
  background: rgba(11,11,12,0.55);
  backdrop-filter: blur(3px);
  border-top-color: transparent;
  border-radius: var(--radius);
}
.arena.has-wall .plate-card.is-winner { border-color: var(--brass); }

.arena-head { text-align: center; margin-bottom: clamp(0.75rem, 2vh, 1.5rem); }
.round-name {
  font-size: 0.7rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 0 0 0.7rem;
}
/* Progress rail: each matchup gets a slot. Once decided, the slot shows a
   thumbnail of the plate that won it — the whole run becomes visible at a
   glance instead of an abstract bar. */
.progress {
  display: flex;
  gap: 5px;
  justify-content: center;
  margin: 0 0 0.9rem;
  padding: 0;
  list-style: none;
  flex-wrap: wrap;
}
.pip {
  position: relative;
  width: 1.9rem;
  height: 1.9rem;
  border: 1px solid var(--line);
  background: var(--ink-2);
  overflow: hidden;
  transition: border-color 0.35s var(--ease), transform 0.35s var(--ease);
}
.pip.is-current { border-color: var(--paper); transform: scale(1.12); }
.pip.is-done { border-color: var(--brass); }
.pip img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.pip.is-filled img { opacity: 1; transform: scale(1); }

@media (max-width: 640px) {
  .pip { width: 1.4rem; height: 1.4rem; }
}

.prompt { margin: 0; font-size: clamp(1.05rem, 2.6vw, 1.4rem); font-weight: 600; letter-spacing: -0.01em; }

.arena {
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(0.5rem, 2vw, 1.5rem);
  max-width: 60rem;
  width: 100%;
  margin: 0 auto;
  touch-action: pan-y;
  transition: transform 0.35s var(--ease);
}
.arena.is-dragging { transition: none; }

.versus {
  color: var(--line);
  font-size: clamp(1.4rem, 4vw, 2.2rem);
  font-weight: 300;
  user-select: none;
}

.plate-card {
  position: relative;
  appearance: none;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0;
  cursor: pointer;
  overflow: hidden;
  text-align: left;
  color: inherit;
  font: inherit;
  transition: border-color 0.25s var(--ease), transform 0.4s var(--ease), opacity 0.4s var(--ease);
}
.plate-card:hover { border-color: var(--brass-dim); }
.plate-media {
  position: relative; /* anchors the shatter tiles to exactly this box */
  aspect-ratio: 3 / 4;
  background: var(--ink-3);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.plate-media img { width: 100%; height: 100%; object-fit: contain; }
.plate-meta {
  padding: 0.9rem 1rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  border-top: 1px solid var(--line);
}
.plate-title { font-size: 0.95rem; font-weight: 600; letter-spacing: -0.01em; }
.plate-sub { font-size: 0.75rem; color: var(--muted); letter-spacing: 0.02em; }
.plate-sub.big { font-size: 0.9rem; margin: 0 0 1.25rem; }

/* Swipe affordance: the side you are heading toward lights up. */
.pick-flag {
  position: absolute;
  inset: 0;
  border: 2px solid var(--brass);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s linear;
}
.plate-card.is-target .pick-flag { opacity: 1; }

/* Resolution: the loser recedes, the winner asserts itself. */
.plate-card.is-winner { border-color: var(--brass); transform: scale(1.03); }
.plate-card.is-winner .plate-media img { opacity: 0; } /* the flying clone stands in for it */
.plate-card.is-loser { opacity: 0; transform: scale(0.95); transition-delay: 0.05s; }

/* -------------------------------------------------- shatter (loser exit) -- */

/* Built at decision time from a grid of tiles, each showing one slice of the
   same plate image via background-position — a CSS-only "shatter" that needs
   no image processing. Each tile gets its own random fly-out transform
   inline, set from JS, so the effect never repeats identically twice. */
/* Shards must escape the card's frame to read as an explosion rather than a
   crop, so overflow opens up only for the duration of the effect. */
.plate-media.is-shattering { overflow: visible; }
.shatter-wrap {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}
.shatter-tile {
  position: absolute;
  background-repeat: no-repeat;
  opacity: 1;
  transform: translate(0, 0) rotate(0deg) scale(1);
  transition: transform 0.62s cubic-bezier(0.35, 0, 0.65, 1), opacity 0.62s ease-in;
}
.shatter-tile.is-flying { opacity: 0; }

/* ---------------------------------------------------------- reject stamp -- */

/* Lands on the loser the instant a choice is made, alongside the shatter —
   a quick, unambiguous "this one's out" before the tiles fly. */
.reject-mark {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  animation: stamp-in 0.55s cubic-bezier(0.2, 1.6, 0.4, 1) forwards;
}
.reject-mark svg {
  width: 44%;
  height: 44%;
  color: var(--danger);
  filter: drop-shadow(0 2px 8px rgba(0,0,0,0.65));
}
@keyframes stamp-in {
  0%   { opacity: 0; transform: scale(2.2) rotate(-16deg); }
  55%  { opacity: 1; transform: scale(0.92) rotate(-8deg); }
  72%  { transform: scale(1.06) rotate(-10deg); }
  100% { opacity: 1; transform: scale(1) rotate(-10deg); }
}

/* ------------------------------------------------- winner -> rail flight -- */

/* A fixed-position clone of the winning image, animated from its on-screen
   rect to its slot in the progress rail (a manual FLIP), then discarded once
   the rail slot itself shows the thumbnail. */
.winner-flight {
  position: fixed;
  z-index: 40;
  object-fit: contain;
  pointer-events: none;
  border-radius: var(--radius);
  transition: transform 0.6s cubic-bezier(0.2, 0.7, 0.3, 1), opacity 0.6s ease-in;
  will-change: transform;
}

.hint {
  text-align: center;
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: clamp(0.75rem, 2vh, 1.5rem) 0 0;
}

/* -------------------------------------------------------------- winner -- */

/* Same wall the duel just happened on, kept behind the reveal — the section
   is deliberately scoped to the plate only (not the group reveal below it,
   which returns to plain black: a family is a different statement than one
   plate on one wall). Bleeds out to the page edge like the arena's version. */
.winner-plate-section {
  position: relative;
  padding: var(--pad) var(--pad) 0.5rem;
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 0;
}
.winner-wallbg {
  position: absolute;
  inset: 0;
  background: center / cover no-repeat;
  z-index: 0;
}
.winner-wallbg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, var(--ink) 0%, rgba(11,11,12,0.2) 18%, rgba(11,11,12,0.2) 80%, var(--ink) 100%);
}
/* :not() keeps this from re-winning the specificity tie against
   .winner-wallbg's own position:absolute rule above — without it, this
   catch-all silently flattened the wallpaper layer back into normal flow,
   which is why the wall never actually showed here. */
.winner-plate-section > *:not(.winner-wallbg) { position: relative; z-index: 1; }

.winner-media {
  width: min(22rem, 70vw);
  margin: 0 auto 1.5rem;
  aspect-ratio: 3 / 4;
  background: var(--ink-2);
  border: 1px solid var(--brass);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: crown 0.7s var(--ease) both;
}
.winner-media.small { width: min(12rem, 44vw); border-color: var(--line); margin-bottom: 1.5rem; }
/* Same treatment as the arena: with a wall behind the section, the frame's
   fill has to go too, or the transparent-cutout plate render sits inside a
   solid black box instead of on the wall showing through it. */
.winner-plate-section.has-wall .winner-media { background: transparent; border-color: rgba(200, 169, 106, 0.55); }
.winner-media img { width: 100%; height: 100%; object-fit: contain; }
@keyframes crown {
  0%   { opacity: 0; transform: scale(0.9); }
  60%  { opacity: 1; transform: scale(1.02); }
  100% { opacity: 1; transform: scale(1); }
}

/* -------------------------------------------------- style-group reveal -- */

/* Separated from the winner by a rule rather than a card: the group is a
   second statement about the same result, not a different offer. */
.group-reveal {
  margin: 2.25rem auto 2rem;
  padding-top: 2rem;
  border-top: 1px solid var(--line);
  max-width: 38rem;
  animation: rise 0.5s var(--ease) both;
  animation-delay: 0.25s;
}
.group-name {
  font-size: clamp(1.3rem, 3.4vw, 1.9rem);
  letter-spacing: -0.015em;
  font-weight: 600;
  margin: 0 0 0.75rem;
  color: var(--paper);
}
.lede.sm { font-size: 0.9rem; margin-bottom: 1.75rem; }

.group-strip {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  display: flex;
  gap: 0.75rem;
  justify-content: center;
  flex-wrap: wrap;
}
.group-strip li {
  width: 6.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.group-strip img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: contain;
  background: var(--ink-2);
  border: 1px solid var(--line);
}
.group-strip span {
  font-size: 0.68rem;
  line-height: 1.3;
  color: var(--muted);
  letter-spacing: 0.02em;
}

@keyframes rise {
  from { opacity: 0; transform: translateY(0.75rem); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------- email -- */

#email-form { max-width: 26rem; margin: 0 auto; }
#email-input {
  width: 100%;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--paper);
  padding: 1rem 1.1rem;
  font: inherit;
  font-size: 1rem;
  margin-bottom: 0.9rem;
}
#email-input:focus { outline: none; border-color: var(--brass); }
.consent {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  text-align: left;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--muted);
  margin-bottom: 1.25rem;
  cursor: pointer;
}
.consent input { margin-top: 0.15rem; accent-color: var(--brass); }
.form-error { color: var(--danger); font-size: 0.8rem; margin: 0 0 1rem; }

/* -------------------------------------------------------------- mobile -- */

@media (max-width: 640px) {
  .arena { gap: 0.5rem; }
  .versus { font-size: 1rem; }
  .plate-meta { padding: 0.6rem 0.65rem 0.8rem; }
  .plate-title { font-size: 0.82rem; }
  .plate-sub { font-size: 0.68rem; }
  .btn { padding: 0.85rem 1.4rem; font-size: 0.72rem; }
  .actions { flex-direction: column; align-items: stretch; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
