/* site.css — makemygreetingcard.com
 *
 * The page is lit the way the product is lit.
 *
 * Every card this service makes is built on one lighting idea: a single warm source with deep
 * falloff, so the card is the brightest thing in the frame and everything else recedes. The page
 * does the same — an ink ground, one pool of light behind the live card, and no second bright
 * object anywhere. That is why there are no white panels, no cards-with-borders and no accent
 * blocks: they would each become a second subject and the product would stop being the hero.
 *
 * The palette is not chosen, it is inherited. Every value here is lifted from
 * site/card/engine/art.js, so the page and the thing it sells cannot drift apart. Change a colour
 * there and change it here, or the card will stop looking like it belongs on its own page.
 *
 * The structural device is the foil rule: a hairline that fades out at both ends, taken from the
 * inner rule on the card stock itself. It is the only ornament, it appears only between sections,
 * and it means something — this is where one thing ends and the next begins.
 */

/* ------------------------------------------------------------------------- tokens ------------- */

:root {
  --ink: #05070f;
  --night: #0b1226;
  --indigo: #16224a;
  --slate: #243357;
  --peacock: #0e6a78;
  --teal: #1c9b92;
  --emerald: #35c79e;
  --gold: #d8a44e;
  --foil: #f4d68c;
  --champagne: #efe0be;
  --ivory: #fbf7ef;
  --ash: #7a88a6;
  --rose: #b95e74;

  --display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --script: 'Pinyon Script', 'Snell Roundhand', cursive;
  --body: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* One rhythm, used everywhere. Sections breathe at --gap-xl, everything inside them at --gap. */
  --gap: clamp(1.1rem, 2.4vw, 1.75rem);
  --gap-xl: clamp(4rem, 11vw, 8.5rem);
  --edge: clamp(1.25rem, 5vw, 4.5rem);
  --max: 1180px;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ink);
  color: var(--champagne);
  font: 400 clamp(1rem, 0.96rem + 0.22vw, 1.125rem)/1.62 var(--body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* The pool of light. Fixed, behind everything, so the whole page sits inside one falloff rather
   than each section carrying its own gradient. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(120% 70% at 72% 0%, rgba(28, 155, 146, 0.16), transparent 62%),
    radial-gradient(90% 60% at 20% 8%, rgba(22, 34, 74, 0.65), transparent 70%);
}

main, header, footer { position: relative; z-index: 1; }

.wrap { max-width: var(--max); margin-inline: auto; padding-inline: var(--edge); }

/* ---------------------------------------------------------------------- typography ------------ */

h1, h2, h3 { font-family: var(--display); font-weight: 400; margin: 0; text-wrap: balance; }

h1 {
  font-size: clamp(2.5rem, 1.5rem + 4.4vw, 4.75rem);
  line-height: 1.02;
  letter-spacing: -0.018em;
  color: var(--ivory);
}
h2 {
  font-size: clamp(1.8rem, 1.2rem + 2.4vw, 3rem);
  line-height: 1.08;
  letter-spacing: -0.012em;
  color: var(--ivory);
}
h3 {
  font-size: clamp(1.15rem, 1rem + 0.7vw, 1.5rem);
  line-height: 1.2;
  color: var(--champagne);
}

/* The script face appears in exactly two places on this site: on the card stock, and wherever the
   page shows a recipient's name back to you. Using it anywhere else would spend the one thing
   that makes a name feel like a name. */
.script { font-family: var(--script); color: var(--foil); }

.eyebrow {
  font: 500 0.75rem/1 var(--body);
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--teal);
  margin: 0 0 1.4rem;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
.eyebrow::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, rgba(28, 155, 146, 0.5), transparent);
}

.lede { font-size: clamp(1.05rem, 1rem + 0.5vw, 1.3rem); color: var(--champagne); opacity: 0.86; max-width: 42ch; }
.muted { color: var(--ash); }
.small { font-size: 0.875rem; line-height: 1.55; }

a { color: var(--foil); text-decoration-color: rgba(244, 214, 140, 0.35); text-underline-offset: 0.25em; }
a:hover { text-decoration-color: var(--foil); }

/* The one ornament. A foil hairline that fades at both ends — the card's own inner rule. */
.rule {
  height: 1px;
  border: 0;
  margin: 0;
  background: linear-gradient(90deg, transparent, rgba(216, 164, 78, 0.42) 22%, rgba(216, 164, 78, 0.42) 78%, transparent);
}

/* ------------------------------------------------------------------------ controls ------------ */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font: 500 0.95rem/1 var(--body);
  letter-spacing: 0.02em;
  padding: 0.95rem 1.6rem;
  border-radius: 2px;
  border: 1px solid var(--gold);
  background: linear-gradient(180deg, rgba(244, 214, 140, 0.16), rgba(216, 164, 78, 0.06));
  color: var(--foil);
  cursor: pointer;
  text-decoration: none;
  transition: background 160ms ease, border-color 160ms ease, color 160ms ease;
}
.btn:hover { background: var(--foil); color: #1a1206; border-color: var(--foil); }
.btn--quiet { border-color: rgba(122, 136, 166, 0.4); color: var(--champagne); background: none; }
.btn--quiet:hover { border-color: var(--champagne); background: rgba(239, 224, 190, 0.07); color: var(--ivory); }

:where(a, button, input, select, textarea):focus-visible {
  outline: 2px solid var(--emerald);
  outline-offset: 3px;
}

label { display: block; font: 500 0.72rem/1 var(--body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ash); margin-bottom: 0.55rem; }

input[type=text], input[type=email], select, textarea {
  width: 100%;
  font: 400 1rem/1.5 var(--body);
  color: var(--ivory);
  background: rgba(11, 18, 38, 0.72);
  border: 1px solid rgba(122, 136, 166, 0.32);
  border-radius: 2px;
  padding: 0.8rem 0.95rem;
}
input::placeholder, textarea::placeholder { color: rgba(122, 136, 166, 0.75); }
input:focus, select:focus, textarea:focus { border-color: var(--teal); }
textarea { resize: vertical; min-height: 5.5rem; }

/* --------------------------------------------------------------------------- header ----------- */

.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding: 1.5rem 0 0;
}
.brand { display: flex; align-items: baseline; gap: 0.55rem; font-family: var(--display); font-size: 1.1rem; color: var(--ivory); text-decoration: none; letter-spacing: -0.01em; }
.brand b { font-weight: 400; }
/* The brand is set in the display face, NOT the script. The script is reserved for a
   recipient's name — that is the whole of what makes a name feel handwritten rather than
   filled in, and spending it on a logo at 17px spends it on something illegible. */
.brand em { font-style: normal; color: var(--foil); }
.top nav { display: flex; gap: 1.6rem; font-size: 0.9rem; }
.top nav a { color: var(--ash); text-decoration: none; }
.top nav a:hover { color: var(--champagne); }
@media (max-width: 640px) { .top nav { display: none; } }

/* ----------------------------------------------------------------------------- hero ----------- */

/* padding-BLOCK, not the `padding` shorthand: the shorthand's 0 for the inline sides silently
   overrode .wrap's padding-inline and ran the hero's headline off the left edge of the page. */
.hero { padding-block: clamp(2.5rem, 6vw, 4rem) calc(var(--gap-xl) * 0.7); }
/* Three named areas rather than two columns, so the stacking order can change.
   On a phone the card has to sit ABOVE the name field: the hint says "watch the card, it changes
   as you type", and a card below the button is a card the person typing cannot see. */
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  grid-template-areas: 'head card' 'form card';
  grid-template-rows: auto auto;
  column-gap: clamp(2rem, 5vw, 4.5rem);
  row-gap: 0;
  align-items: center;
}
.hero-head { grid-area: head; align-self: end; }
.hero-form { grid-area: form; align-self: start; }
.hero-art  { grid-area: card; }

@media (max-width: 900px) {
  .hero-grid {
    grid-template-columns: 1fr;
    grid-template-areas: 'head' 'card' 'form';
    row-gap: clamp(1.75rem, 5vw, 2.5rem);
  }
  .hero-head, .hero-form { align-self: auto; }

  /* Capped by HEIGHT on a phone, not by width. A 9:16 card at full width is 690px tall on a
     390px screen, which puts the field you are meant to be typing into two screens below the
     card it is meant to be changing. */
  .hero .frame { max-height: 50vh; max-width: min(380px, calc(50vh * 9 / 16)); }
}

.hero h1 em { font-style: normal; font-family: var(--script); color: var(--foil); font-size: 1.16em; line-height: 0.8; }
.hero .lede { margin: 1.5rem 0 0; }

/* The live control. Deliberately not styled as a form: it is part of the card, and the point is
   that what you type is already on the card before you have decided to buy anything. */
.namebar { margin-top: 2.2rem; max-width: 30rem; }
.namebar-row { display: flex; gap: 0.6rem; align-items: flex-end; }
.namebar-row > div { flex: 1; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 0.8rem; align-items: center; margin-top: 1.9rem; }
.pricenote { font-size: 0.9rem; color: var(--ash); }
.pricenote b { color: var(--champagne); font-weight: 500; }

/* ------------------------------------------------------------------------ the frame ----------- */

/* Cards are 9:16 and are shown at that shape everywhere on the site, because that is the shape
   they will be looked at in — a phone, held up, passed across a table. */
.frame {
  position: relative;
  aspect-ratio: 9 / 16;
  border-radius: 6px;
  overflow: hidden;
  background: var(--ink);
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(122, 136, 166, 0.16);
}
.frame .cardsvg { display: block; width: 100%; height: 100%; }
.hero .frame { max-width: 380px; margin-inline: auto; }

.frame-bar {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 0.85rem;
  background: linear-gradient(0deg, rgba(5, 7, 15, 0.85), transparent);
  opacity: 0;
  transition: opacity 160ms ease;
}
.frame:hover .frame-bar, .frame:focus-within .frame-bar { opacity: 1; }
/* A touch device has no hover, so a control that only appears on hover does not exist there at
   all — the play button and the scrubber were invisible on every phone. Show them always where
   hover is unavailable, which is exactly the set of devices that cannot reveal them. */
@media (hover: none) { .frame-bar { opacity: 1; } }
.frame-bar button {
  border: 1px solid rgba(239, 224, 190, 0.3);
  background: rgba(5, 7, 15, 0.6);
  color: var(--champagne);
  border-radius: 2px;
  font: 500 0.72rem/1 var(--body);
  letter-spacing: 0.08em;
  padding: 0.45rem 0.7rem;
  cursor: pointer;
}
.frame-bar button:hover { color: var(--ivory); border-color: var(--champagne); }
.scrub { flex: 1; accent-color: var(--teal); height: 2px; }

/* ------------------------------------------------------------------------- sections ----------- */

section { padding-block: calc(var(--gap-xl) * 0.58); }
.section-head { max-width: 56ch; margin-bottom: clamp(2rem, 4vw, 3.2rem); }
.section-head p { margin: 1rem 0 0; color: var(--ash); }

/* ------------------------------------------------------------------------ two lanes ----------- */

.lanes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.5rem, 4vw, 3.5rem); }
@media (max-width: 800px) { .lanes { grid-template-columns: 1fr; } }

.lane { display: flex; flex-direction: column; gap: 1.1rem; }
.lane-price {
  font-family: var(--display);
  font-size: clamp(2.4rem, 1.6rem + 3vw, 3.6rem);
  line-height: 1;
  color: var(--foil);
  letter-spacing: -0.02em;
}
.lane-price span { font-family: var(--body); font-size: 0.85rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ash); display: block; margin-top: 0.7rem; }
.lane ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.7rem; }
.lane li { display: grid; grid-template-columns: 1.1rem 1fr; gap: 0.7rem; font-size: 0.95rem; color: var(--champagne); opacity: 0.9; }
/* A foil hairline, the same ornament as the section rules, at list scale. A mid-dot at this
   size reads as a stray apostrophe. */
.lane li::before { content: ''; height: 1px; width: 0.85rem; background: var(--gold); margin-top: 0.78em; }
/* margin-top is reset, not inherited: the dash above needs 0.78em to sit on the text's baseline,
   and a glyph does not — leaving it on dropped every × most of a line below its own text. */
.lane li.no::before { content: '×'; height: auto; width: auto; background: none; margin-top: 0; color: var(--ash); font-size: 0.9rem; line-height: 1.72; }
.lane li.no { color: var(--ash); }

/* --------------------------------------------------------------------------- gallery ---------- */

.gallery { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1rem, 3vw, 2.2rem); }
@media (max-width: 800px) { .gallery { grid-template-columns: 1fr; max-width: 26rem; margin-inline: auto; } }
.gcard h3 { margin: 1.1rem 0 0.35rem; }
.gcard .occ { font: 500 0.7rem/1 var(--body); letter-spacing: 0.15em; text-transform: uppercase; color: var(--teal); }
.gcard p { margin: 0.5rem 0 0; font-size: 0.92rem; color: var(--ash); }

/* ----------------------------------------------------------------------------- steps ---------- */

/* Numbered because this genuinely is a sequence — you cannot pay before you have written the
   name, and you cannot be sent a card before it has rendered. */
.steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.5rem, 4vw, 3rem); counter-reset: step; }
@media (max-width: 800px) { .steps { grid-template-columns: 1fr; } }
.step { counter-increment: step; padding-top: 1.6rem; border-top: 1px solid rgba(216, 164, 78, 0.28); }
.step::before {
  content: counter(step, decimal-leading-zero);
  font: 400 0.8rem/1 var(--body);
  letter-spacing: 0.12em;
  color: var(--gold);
  display: block;
  margin-bottom: 0.9rem;
}
.step h3 { margin-bottom: 0.5rem; }
.step p { margin: 0; font-size: 0.95rem; color: var(--ash); }

/* -------------------------------------------------------------------------- the plan ---------- */

.plan { display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start; }
@media (max-width: 900px) { .plan { grid-template-columns: 1fr; } }

.shotlist { display: grid; gap: 0; }
.shot { display: grid; grid-template-columns: 4.5rem 1fr; gap: 1.2rem; padding: 1.05rem 0; border-top: 1px solid rgba(122, 136, 166, 0.18); }
.shot:last-child { border-bottom: 1px solid rgba(122, 136, 166, 0.18); }
.shot time { font: 500 0.78rem/1.5 var(--body); letter-spacing: 0.05em; color: var(--gold); font-variant-numeric: tabular-nums; }
.shot p { margin: 0; font-size: 0.94rem; color: var(--champagne); opacity: 0.88; }


/* ---------------------------------------------------------------------------- order ----------- */

.maker { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr); gap: clamp(1.8rem, 5vw, 4rem); align-items: start; }
@media (max-width: 900px) { .maker { grid-template-columns: 1fr; } }

/* WHY STICKY: the form runs to ~1900px, a 9:16 preview to ~1100px, so a static right column
   left an 800px void under the card. The two-column shape is right — the whole point of the
   maker is that the card answers the form live — so instead the column stretches to the form's
   full height and the preview travels inside it, staying in view beside whichever field you
   are filling in. The column's height is now spent following you rather than standing empty. */
.maker-side { align-self: stretch; }
.maker-side-stick { position: sticky; top: clamp(1.25rem, 4vh, 2.5rem); }
.maker-side .frame { max-width: 300px; }
@media (max-width: 900px) {
  /* One column: the preview follows the fields in source order, capped by height like the hero
     card so it never pushes anything a full screen away. Sticky off — a pinned card over a
     phone-length form would sit on top of the fields it is meant to sit beside. */
  .maker-side { align-self: auto; }
  .maker-side-stick { position: static; }
  .maker-side .frame { max-height: 45vh; max-width: min(240px, calc(45vh * 9 / 16)); }
}

/* The four decisions. Each group opens with the same numbered foil-rule device as the
   "How it works" steps — the form IS those steps, being taken. */
.maker-fields { display: grid; gap: clamp(1.6rem, 3.2vw, 2.4rem); }
.fgroup { display: grid; gap: 1.15rem; padding-top: 1.35rem; border-top: 1px solid rgba(216, 164, 78, 0.28); }
.fgroup-label {
  margin: 0;
  font: 500 0.72rem/1 var(--body);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------------ format choice ------------ */

/* Two real options with prices on them, not a pair of radio buttons. The decision being made here
   is "now or better", and it deserves the space that implies. */
.formats { border: 0; padding: 0; margin: 0; }
.formats legend { padding: 0; font: 500 0.72rem/1 var(--body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ash); margin-bottom: 0.7rem; }
.format-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
@media (max-width: 560px) { .format-opts { grid-template-columns: 1fr; } }
.format { display: block; margin: 0; cursor: pointer; text-transform: none; letter-spacing: 0; }
.format input { position: absolute; opacity: 0; pointer-events: none; }
.format-body {
  display: block;
  border: 1px solid rgba(122, 136, 166, 0.32);
  border-radius: 3px;
  padding: 1rem 1.1rem;
  transition: border-color 140ms ease, background 140ms ease;
}
.format:hover .format-body { border-color: rgba(216, 164, 78, 0.55); }

/* The coming-soon option. Legible, not greyed into unreadability: it is there to be read and
   wanted. The cursor and the hover state are what say it cannot be picked. */
.format.is-soon { cursor: default; }
.format.is-soon .format-body { opacity: .58; }
.format.is-soon:hover .format-body { border-color: var(--hairline); }
.format-body i.soon {
  display: inline-block;
  margin-left: .5rem;
  padding: .12rem .45rem;
  border: 1px solid var(--gold);
  border-radius: 2px;
  font: 500 .62rem/1.5 var(--body);
  font-style: normal;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--foil);
  vertical-align: middle;
}
.format:has(input:checked) .format-body { border-color: var(--gold); background: rgba(216, 164, 78, 0.09); }
.format:has(input:focus-visible) .format-body { outline: 2px solid var(--emerald); outline-offset: 2px; }
.format-body b { display: block; font: 500 1rem/1.3 var(--body); color: var(--ivory); }
.format-price { display: block; font-family: var(--display); font-size: 1.6rem; color: var(--foil); line-height: 1.1; margin: 0.15rem 0 0.4rem; }
.format-note { display: block; font-size: 0.85rem; line-height: 1.5; color: var(--ash); }
/* The hint is a caption OF the choice, not a stray sentence after it: tight to the cards,
   opened with the same foil dash the lane lists use, and gone entirely when empty. */
.format-hint { margin: 0.6rem 0 0; font-size: 0.8rem; line-height: 1.45; color: var(--ash); display: flex; align-items: flex-start; gap: 0.6rem; }
.format-hint::before { content: ''; flex: none; width: 0.85rem; height: 1px; background: var(--gold); margin-top: 0.65em; }
.format-hint:empty { display: none; }

/* --------------------------------------------------------------- design picker --------------- */

/* The animated card is one of three fixed designs, and pretending otherwise would be a lie the
   engine cannot cover: it composes from a frozen catalogue of fourteen primitives and cannot draw
   a rabbit. So the constraint is presented as a choice, which is what it honestly is. */
.designs-pick { border: 0; padding: 0; margin: 0; }
.designs-pick legend { padding: 0; font: 500 0.72rem/1 var(--body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ash); margin-bottom: 0.7rem; }
.design-opts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.6rem; }
.design { margin: 0; cursor: pointer; text-transform: none; letter-spacing: 0; display: block; }
.design input { position: absolute; opacity: 0; pointer-events: none; }
.design span {
  display: block;
  border: 1px solid rgba(122, 136, 166, 0.32);
  border-radius: 3px;
  padding: 0.7rem 0.8rem;
  font: 400 0.85rem/1.35 var(--body);
  color: var(--champagne);
}
.design span i { display: block; font-style: normal; font-size: 0.75rem; color: var(--ash); margin-top: 0.2rem; }
.design:hover span { border-color: rgba(216, 164, 78, 0.5); }
.design:has(input:checked) span { border-color: var(--gold); background: rgba(216, 164, 78, 0.09); color: var(--ivory); }
.design:has(input:focus-visible) span { outline: 2px solid var(--emerald); outline-offset: 2px; }

/* ----------------------------------------------------------------------- chips --------------- */

/* Openers, not decoration. They write the first three words so the box is never blank. */
.chips { display: flex; flex-wrap: wrap; gap: 0.45rem; margin-top: 0.7rem; }
.chip {
  font: 400 0.82rem/1 var(--body);
  color: var(--champagne);
  background: rgba(28, 155, 146, 0.10);
  border: 1px solid rgba(28, 155, 146, 0.34);
  border-radius: 999px;
  padding: 0.5rem 0.85rem;
  cursor: pointer;
}
.chip:hover { background: rgba(28, 155, 146, 0.2); color: var(--ivory); }

/* ---------------------------------------------------------------------- photos --------------- */

/* The whole area is the <label> for the real file input, which sits invisibly across it — so a
   click anywhere opens the picker, a drop lands on the input itself, and Tab still reaches it
   (focus ring drawn on the area via :has). No browser-chrome "Choose Files" text anywhere. */
.dropzone {
  position: relative;
  display: block;
  margin: 0;
  padding: 1.05rem 1.15rem;
  border: 1px dashed rgba(122, 136, 166, 0.45);
  border-radius: 3px;
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
  transition: border-color 140ms ease, background 140ms ease;
}
.dropzone:hover { border-color: rgba(216, 164, 78, 0.55); background: rgba(216, 164, 78, 0.04); }
.dropzone:has(input:focus-visible) { outline: 2px solid var(--emerald); outline-offset: 2px; }
.dropzone input[type=file] { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.dropzone-title { display: block; font: 500 0.95rem/1.4 var(--body); color: var(--champagne); }
.dropzone-hint { display: block; font-size: 0.8rem; line-height: 1.45; color: var(--ash); margin-top: 0.25rem; }
.thumbs { display: grid; grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); gap: 0.6rem; margin-top: 0.9rem; }
.thumb { margin: 0; aspect-ratio: 1; border-radius: 3px; overflow: hidden; background: rgba(11,18,38,.7); }
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.fields { display: grid; gap: 1.1rem; }
.pair, .fields .pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
@media (max-width: 520px) { .fields .pair { grid-template-columns: 1fr; } }

.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
@media (max-width: 520px) { .pair { grid-template-columns: 1fr; } }
.choice { display: grid; gap: 0.6rem; }
.choice-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.choice-opts label {
  margin: 0;
  border: 1px solid rgba(122, 136, 166, 0.32);
  border-radius: 2px;
  padding: 0.85rem 1rem;
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
  font: 400 0.95rem/1.35 var(--body);
  color: var(--champagne);
  display: block;
}
.choice-opts input { position: absolute; opacity: 0; pointer-events: none; }
.choice-opts label:has(input:checked) { border-color: var(--gold); background: rgba(216, 164, 78, 0.09); color: var(--ivory); }
.choice-opts label:has(input:focus-visible) { outline: 2px solid var(--emerald); outline-offset: 2px; }
.choice-opts label b { display: block; font-weight: 500; }
.choice-opts label span { font-size: 0.8rem; color: var(--ash); }

.formnote { font-size: 0.85rem; color: var(--ash); margin: 0; }

/* The early-access line. Amber rather than red: it is a fact about the shop, not a mistake the
   reader made, and a red banner on arrival reads as something broken. */
.early {
  margin: 1rem 0 0;
  padding: .7rem 1rem;
  border-left: 2px solid var(--gold);
  background: rgba(244, 214, 140, .07);
  font-size: .92rem;
  color: var(--parchment);
}
.made-title { font-family: var(--display); font-size: 1.15rem; margin: 0 0 .8rem; }

/* Helper text under a field, answering the question the field itself provokes. */
.fieldnote { font-size: 0.8rem; line-height: 1.45; color: var(--ash); margin: 0.5rem 0 0; }
.status { margin: 0; font-size: 0.92rem; min-height: 1.5em; }
.status.ok { color: var(--emerald); }
.status.bad { color: var(--rose); }

/* ------------------------------------------------------------------- the made panel ---------- */

.made { margin-top: 1.6rem; border-top: 1px solid rgba(216, 164, 78, 0.3); padding-top: 1.3rem; }
.made-title { font-family: var(--display); font-size: 1.3rem; color: var(--ivory); margin: 0 0 0.4rem; }
.made .btn { margin-top: 1.1rem; }
.made .eta { color: var(--ash); font-weight: 400; }

/* An honest progress bar: it fills against a measured render time, and it stops filling and says
   so if the render takes longer than expected rather than sitting at 99% pretending. */
.prog { margin-top: 1.1rem; }
.prog-bar {
  height: 3px;
  background: rgba(122, 136, 166, 0.25);
  border-radius: 2px;
  overflow: hidden;
}
.prog-bar span {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--teal), var(--foil));
  transition: width 420ms linear;
}
.prog p { margin-top: 0.6rem; }

/* --------------------------------------------------------------------------- footer ----------- */

footer { padding: calc(var(--gap-xl) * 0.5) 0 3rem; color: var(--ash); font-size: 0.87rem; }
footer .cols { display: flex; flex-wrap: wrap; gap: 2rem 3rem; justify-content: space-between; align-items: baseline; }
footer a { color: var(--ash); }

/* ------------------------------------------------------------------- reduced motion ----------- */

/* The cards handle this themselves — the player renders their held frame and never starts a
   clock. Nothing here needs to hide anything, because there is no decorative motion on the page
   to hide: every moving thing on it is a card. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 1ms !important; }
}
