/* The studio. White and quiet, on purpose.
 *
 * The buyer is here to answer three questions and then look at their own
 * website. Anything this interface does with colour competes with both, so it
 * does almost nothing: white ground, black text, one thin rule, and the work
 * carries it. The one place colour is allowed is the colour question, where
 * the colour is the answer.
 *
 * The websites it builds are the buyer's and follow none of this. They live
 * inside an iframe and share no CSS with this file.
 */

/* S7, 2026-09-25. Colours mapped onto the brand tokens in
   public/css/base.css (OS/context/brand-visual.md): paper, ink and red were
   already the same hex as ground, ink and red, so those three keep their
   values here. Hair moves to the exact value of the surface token. Muted and
   faint are darkened so the text pairs that use them clear 4.5:1 on both
   backgrounds they sit on (paper and hair), not only on the lighter of the
   two. Red-700 is added because the buttons below need it. */
:root {
  --paper: #F3F2F2;
  --ink: #201E1D;
  --muted: #5c5955;
  --faint: #666360;
  --hair: #EAE9E9;
  --line: #d6d3ce;
  --red: #EC3013;
  --red-700: #AE1800;

  --font: "Archivo", system-ui, -apple-system, Segoe UI, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

/* The heading is focused when the question changes so a screen reader says
   the new question out loud. It is not a control and cannot be tabbed to,
   so the ring around it says nothing to anybody who can see, and on first
   load it sat there as a black box until something else was clicked. The
   focus stays. Only the ring goes. */
.question h1[tabindex]:focus,
.question h1[tabindex]:focus-visible { outline: none; }

/* None of this is text anybody wants to take away with them, and dragging
   across a question to reach a card selected the heading instead. The
   built site inside the frame is untouched by this, and the two places
   worth copying out of are put back below. */
.ask, .bar, .afbar, .working, .offline { user-select: none; }

/* The folder path is there to be copied, and a field has to be selectable
   or it cannot be edited. user-select on an ancestor reaches both. */
.path, input, textarea { user-select: text; }

/* ── the question screen ───────────────────────────────────────────────── */

/* Centred both ways. safe center is the second declaration so that on a
   window too short for the grid the top stays reachable instead of being
   cut off above the scroll origin. Browsers without it keep the plain
   centring from the line before.

   Only question one lives here now: it is the one answer nothing can be
   built without, so it is the one screen with no site behind it and
   nothing else competing for the middle of the window. */
.ask {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  /* Wider than a reading measure because the grid needs the room. The
     heading and its sub keep their own widths, so only the grid grows. */
  max-width: 1400px;
  margin: 0 auto;
  padding: clamp(24px, 4vh, 56px) clamp(20px, 4vw, 48px);
  display: grid;
  align-content: center;
  align-content: safe center;
}
.ask[hidden] { display: none; }

.question { text-align: center; margin-bottom: clamp(32px, 5vh, 56px); }
.question h1 {
  margin: 0;
  font-size: clamp(28px, 4.2vw, 46px);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.05;
  text-wrap: balance;
}
/* Question one has nothing to say under its heading. An empty paragraph
   still carries its top margin, which left a gap that looked like a missing
   line rather than a deliberate absence. */
.question .sub:empty { display: none; }
.question .sub {
  margin: 14px auto 0;
  max-width: 46ch;
  font-size: clamp(15px, 1.6vw, 17px);
  color: var(--muted);
  text-wrap: pretty;
}

/* ── the grid ──────────────────────────────────────────────────────────── */

/* Question one only: every kind of business on screen at once, and a click
   anywhere on a card is the answer. Colour and type are answered on the
   wheel further down, because both of those need the site itself on
   screen behind them, and a grid that size would leave no room for it.

   The card itself keeps the 16:10 shape the wheel uses too: every size
   printed on it is a percent of that shape, in cqw, and changing the shape
   without retuning those percentages is how a fit that took real measuring
   quietly stops fitting. */
.grid {
  display: grid;
  gap: clamp(14px, 1.8vw, 24px);
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.pick {
  font: inherit;
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  display: grid;
  aspect-ratio: 8 / 5;
}
.pick:hover .card,
.pick:focus-visible .card {
  border-color: var(--line);
  box-shadow: 0 14px 34px rgba(0, 0, 0, .12);
}
/* The one already chosen, for when someone comes back to change it. */
.pick[aria-checked="true"] .card { border-color: var(--ink); box-shadow: 0 0 0 2px var(--ink); }

/* ── the card ──────────────────────────────────────────────────────────── */

/* One box, three things printed on it. Every size on the inside is in cqw, a
   percent of the box's own width, so one piece of markup is right at 300
   pixels across and at 700 without a single breakpoint.

   The box carries nothing but the border and the query container. Padding
   and gaps belong to the element inside it, because an element does not
   answer its own container query: cqw written on .card resolves against the
   window instead, which is how five percent became seventy two pixels
   inside a three hundred pixel card. */
.card {
  container-type: inline-size;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: var(--paper);
  border: 1px solid var(--hair);
  display: grid;
  transition: box-shadow .3s ease, border-color .3s ease;
}
.card > * { display: grid; min-width: 0; }

/* Question one. The kind of business, and nothing else on the card. */
.card-genre {
  place-items: center;
  padding: 6cqw;
  text-align: center;
}
.card-genre .gname {
  font-size: 10cqw;
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.06;
  text-wrap: balance;
}

/* Question two. Every colour the site is built from, blocked out and named.
   The card is painted in the palette itself, so the background is seen as a
   field rather than as a chip, and the names are set in the palette's own
   text colours. Those pairs are held to 4.5:1 by the data, so this cannot
   come out unreadable however dark the scheme is. */
.card-colour {
  align-content: start;
  color: var(--cink);
  gap: 3.4cqw;
  padding: 5cqw;
  background: var(--cbg);
}
.card-colour .cname {
  font-size: 4.6cqw;
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.1;
  text-align: center;
}
.card-colour .roles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.6cqw;
}
.card-colour .role { display: grid; gap: .9cqw; }
.card-colour .role i {
  display: block;
  height: 10.2cqw;
  /* A ring rather than a border, so a white background still reads as a
     block on a white card and keeps its full size. */
  box-shadow: inset 0 0 0 1px rgba(128, 128, 128, .38);
}
.card-colour .role b {
  font-size: 2.7cqw;
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.2;
}
.card-colour .role em {
  font-size: 2.5cqw;
  font-style: normal;
  font-variant-numeric: tabular-nums;
  line-height: 1.25;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--cmuted);
}

/* Question three. The face itself, at the sizes that tell you anything: one
   letter huge, both alphabets, and a sentence at the size a paragraph is
   actually read at. */
.card-type {
  align-content: center;
  justify-items: center;
  gap: 2.2cqw;
  padding: 5cqw;
  text-align: center;
}
.card-type .tname {
  font-family: var(--font);
  font-size: 2.4cqw;
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--faint);
}
.card-type .tbig {
  font-size: 15cqw;
  line-height: .96;
  letter-spacing: -.02em;
}
.card-type .tset {
  font-size: 3.4cqw;
  line-height: 1.34;
  word-spacing: .1em;
}
.card-type .tline {
  font-size: 2.8cqw;
  line-height: 1.4;
  color: var(--muted);
  max-width: 84%;
}


/* ── the wheel ─────────────────────────────────────────────────────────── */

/* Colour and type, turned rather than clicked from a grid, because both sit
   on top of the site itself: the wheel is a strip along the bottom, and
   everything above it is the preview. Turning previews whatever the wheel
   lands on; only the card in the middle is chosen, and only a click on that
   one moves to the question after it. */

.wheelbar {
  flex: none;
  padding: clamp(12px, 1.8vh, 20px) clamp(16px, 3vw, 28px) clamp(14px, 2.2vh, 24px);
  border-top: 1px solid var(--hair);
  background: var(--paper);
}
.wheelbar[hidden] { display: none; }

/* Three columns for the same reason the old under-the-grid bar used them:
   the heading stays in the middle of the bar whether or not the link
   beside it is showing. */
.wheelhead {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  margin-bottom: clamp(10px, 1.6vh, 18px);
}
.wheelhead .back { grid-column: 1; justify-self: start; }
.wheelhead h2 {
  grid-column: 2;
  margin: 0;
  font-size: clamp(16px, 1.8vw, 20px);
  font-weight: 800;
  letter-spacing: -.02em;
  text-align: center;
  white-space: nowrap;
}
.wheelhead .link { grid-column: 3; justify-self: end; }

/* One card at a time and large, exactly as question one's cards read
   before they moved to a grid. The last and the next sit at the edges,
   smaller and faded, so it is plain there are more without them competing
   with the one being looked at. */
.wheelrow {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(6px, 1.2vw, 16px);
  width: 100%;

  /* Fixed rather than measured from the window, because the wheel no
     longer has the window to itself: the site behind it takes whatever
     this does not. The floor is not arbitrary either. A card is
     (rowh - 32) x 1.6, and 288 is the width the hex under each colour
     needs to stay readable, so the floor here is chosen to clear that: at
     220 the card is already 301 wide. */
  --rowh: clamp(220px, 24vh, 270px);
  height: var(--rowh);
}

.viewport {
  height: 100%;
  overflow: hidden;
  position: relative;
}

/* The track is moved by transform rather than by scrolling it. Native
   overflow scrolling reads better on paper and is wrong: smooth scrollTo,
   scrollBy and scrollIntoView all silently do nothing in some embedded
   browsers, which leaves the wheel functionally correct and visually
   frozen. A transform is one number this code owns, and a CSS transition
   animates it everywhere. */
.track {
  display: flex;
  align-items: stretch;
  gap: clamp(12px, 2vw, 30px);
  height: 100%;
  position: relative;
  will-change: transform;
  /* The offset is written straight onto style.transform by centreOn(). It was
     a custom property inside translate3d() first, which does not interpolate
     unless the property is registered, so the track stuck instead of gliding. */
  transform: translate3d(0, 0, 0);
  transition: transform .34s cubic-bezier(.22, .61, .36, 1);
}

.space {
  font: inherit;
  text-align: left;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  flex: none;
  height: 100%;
  padding-block: 16px;
  /* --rowh has a 220px floor for legibility (see .wheelrow above), which
     draws a 301px card regardless of window size. Below roughly a 333px
     window that is wider than .viewport itself, .viewport's overflow:hidden
     silently clips both edges of it. The card's own contents are already
     sized in cqw of this box, so letting the box itself give way here on
     a window that narrow costs nothing above it and avoids the clip. */
  width: min(calc((var(--rowh) - 32px) * 1.6), 92vw);
  display: grid;
  /* The slots are all the same size and only the middle one is drawn full
     size, so the spacing never shifts as the wheel turns. */
  transform: scale(.82);
  opacity: .6;
  transition: transform .3s ease, opacity .3s ease;
}
.space[data-active] { transform: none; opacity: 1; }
.space[data-active] .card { border-color: var(--line); box-shadow: 0 16px 44px rgba(0, 0, 0, .14); }
/* The one already chosen, for when someone comes back to change it. */
.space[aria-checked="true"] .card { border-color: var(--ink); box-shadow: 0 0 0 2px var(--ink); }

.nudge {
  font: inherit;
  width: clamp(32px, 3vw, 40px);
  height: clamp(32px, 3vw, 40px);
  display: grid;
  place-items: center;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 0; /* S7: no rounded corners, brand-visual.md */
  color: var(--ink);
  cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.nudge:hover { border-color: var(--ink); box-shadow: 0 2px 10px rgba(0, 0, 0, .08); }
.nudge svg {
  width: 42%; height: 42%;
  fill: none; stroke: currentColor; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
}
/* A thumb has no hover to find the arrows with, and at phone width there is
   not room for them beside a 288px card besides. Touch already turns the
   wheel by swipe, wired in wireWheel(), so the arrows are a pointer-only
   convenience rather than the only way to reach either one. */
@media (hover: none) {
  .nudge { display: none; }
}

/* ── the website ───────────────────────────────────────────────────────── */

.full { display: flex; flex-direction: column; height: 100vh; height: 100dvh; }
.full[hidden] { display: none; }

.stage {
  flex: 1;
  position: relative;
  min-height: 0;
  background: #f4f3f0;
  display: grid;
  place-items: center;
  padding: 12px;
  /* .stage.stowed, near .love below, is what actually sets this in motion. */
  transition: transform .32s cubic-bezier(.3, .7, .3, 1), opacity .32s ease, filter .32s ease;
}

/* The frame is laid out from the start and fades in when the page actually
   lands in it. Showing it the moment the build returns crosses to a blank
   white rectangle and then pops, which is worse than not fading at all.

   It may not use [hidden] for this. display:none cannot be transitioned, and
   an element that is not laid out cannot fade. */
#preview {
  grid-area: 1 / 1;
  width: 100%; height: 100%; max-width: 100%; border: 0; background: #fff;
  box-shadow: 0 1px 18px rgba(0, 0, 0, .14);
  transition: opacity .5s ease, max-width .2s ease;
}
#preview[data-w="820"] { max-width: 820px; }
#preview[data-w="390"] { max-width: 390px; }

.stage[data-showing="waiting"] #preview { opacity: 0; pointer-events: none; visibility: hidden; }

@media (prefers-reduced-motion: reduce) {
  #preview { transition: none; }
  .stage { transition: none; }
}

/* A pill rather than a panel, so the stage is not thrown away for the half
   second between asking for a site and getting one. */
.working {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 16px;
  background: var(--ink);
  color: var(--paper);
  border-radius: 0; /* S7: was a 999px pill, brand-visual.md allows no rounded corners */
  font-size: 11px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
}
/* Without this the pill never goes away: display:flex above is an author rule
   and beats the browser default for [hidden]. */
.working[hidden] { display: none; }
.working span { width: 9px; height: 9px; border-radius: 0; background: var(--paper); animation: pulse .8s ease-in-out infinite alternate; }
@keyframes pulse { from { opacity: .25; transform: scale(.7); } to { opacity: 1; transform: none; } }

/* ── the bar ───────────────────────────────────────────────────────────── */

.bar[hidden] { display: none; }
.bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 22px);
  padding: 10px clamp(16px, 3vw, 28px);
  border-bottom: 1px solid var(--hair);
  background: var(--paper);
}

.barstep {
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.6vw, 20px);
  flex: 1;
  min-width: 0;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.back {
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  background: none;
  border: 0;
  padding: 8px 0;
  cursor: pointer;
  flex: none;
}
.back:hover { color: var(--ink); }
.back[hidden] { display: none; }

/* ── the finished thing ────────────────────────────────────────────────── */

.chose {
  font-size: 14px; font-weight: 600; letter-spacing: -.01em;
  display: flex; align-items: baseline; flex-wrap: wrap; margin-right: auto;
}
.chose b { font-weight: 800; }
.chose span { color: var(--faint); font-weight: 400; margin: 0 6px; }
.chose .jump {
  font: inherit; font-size: 14px; font-weight: 600;
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--muted); border-bottom: 1px dashed var(--line);
}
.chose .jump:hover { color: var(--ink); border-bottom-style: solid; border-bottom-color: var(--ink); }

.devices { display: flex; border: 1px solid var(--hair); }
.devices button {
  font: inherit; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  padding: 7px 12px; cursor: pointer; border: 0; border-left: 1px solid var(--hair);
  background: none; color: var(--muted);
}
.devices button:first-child { border-left: 0; }
.devices button[aria-pressed="true"] { background: var(--ink); color: var(--paper); }

.link {
  font: inherit; font-size: 13px; font-weight: 600; color: var(--ink);
  background: none; border: 0; padding: 0; cursor: pointer;
  text-decoration: none; border-bottom: 1px solid var(--line);
  flex: none;
}
.link:hover { border-bottom-color: var(--ink); }
.link[hidden] { display: none; }

.btn {
  font: inherit; font-size: 13px; font-weight: 800; letter-spacing: .02em;
  padding: 9px 18px; cursor: pointer;
  color: var(--paper); background: var(--ink); border: 1px solid var(--ink);
  flex: none;
}
.btn:hover { opacity: .86; }

.path {
  flex: none; margin: 0; padding: 7px clamp(16px, 3vw, 28px);
  font-size: 11px; color: var(--faint); border-top: 1px solid var(--hair);
  word-break: break-all;
}
.path:empty { display: none; }

/* ── every face in the builder ─────────────────────────────────────────── */

.allfonts {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: var(--paper);
  display: flex;
  flex-direction: column;
}
.allfonts[hidden] { display: none; }

.afbar {
  flex: none;
  display: flex;
  align-items: flex-start;
  gap: 20px;
  padding: clamp(18px, 3vh, 30px) clamp(20px, 4vw, 48px);
  border-bottom: 1px solid var(--hair);
}
.afbar h2 { margin: 0; font-size: clamp(20px, 2.4vw, 28px); font-weight: 800; letter-spacing: -.02em; }
.afbar p { margin: 5px 0 0; font-size: 14px; color: var(--muted); max-width: 60ch; }
.afbar .btn { margin-left: auto; }

.afgrid {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 1px;
  background: var(--hair);
  border-top: 1px solid var(--hair);
}

.face {
  font: inherit;
  text-align: left;
  background: var(--paper);
  border: 0;
  padding: 18px 20px 16px;
  cursor: pointer;
  display: grid;
  gap: 6px;
  align-content: start;
}
.face:hover { background: #fafaf8; }
.face[aria-checked="true"] { background: var(--ink); color: var(--paper); }
/* The name set in its own face, which is the only honest way to show one. */
.face .spec { font-size: 27px; line-height: 1.15; letter-spacing: -.01em; }
.face .from { font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--faint); }
.face[aria-checked="true"] .from { color: var(--paper); opacity: .7; }

/* ── tier 2: one AI generation, from a capped intake ─────────────────────── */

.customize {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  align-items: center; /* centres customizeBody; the header below opts back out */
}
.customize[hidden] { display: none; }
.customize > .afbar { align-self: stretch; }

/* Centred horizontally (the column itself, width-capped) and vertically
   (the field group as a whole, when it fits the viewport) rather than
   pinned to the top - "safe" so a form taller than the window still starts
   scrolling from its own top edge instead of clipping it against the
   centring. */
.customizeBody {
  flex: 1;
  width: 100%;
  /* Widened alongside .wizQ's doubled text - a 38px heading and a 28px
     textarea wrap constantly at the old 640px and read worse for it, not
     better. */
  max-width: 880px;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  justify-content: safe center;
  gap: 22px;
  padding: clamp(20px, 3vh, 32px) clamp(20px, 4vw, 48px) 40px;
}

.cfield-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.cfield-head b { font-size: 12px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; }
.cfield-head i { font-style: normal; font-size: 11px; color: var(--faint); }
.cfield-head .ccount { font-variant-numeric: tabular-nums; }
.cfield-head .ccount.over { color: #b3261e; font-weight: 700; }

.cuploads { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.cupload { display: grid; gap: 6px; }
.cupload input { font-size: 12px; }
@media (max-width: 560px) { .cuploads { grid-template-columns: 1fr; } }

.cerror {
  margin: 0; padding: 10px 14px; font-size: 13px;
  background: #fbeceb; color: #7a1f18; border: 1px solid #e7b8b3;
}
.cerror[hidden] { display: none; }

.cupload-plan { border: 1px solid var(--line); padding: 16px 18px; margin-top: 10px; }
.cplan-title { margin: 0; font-size: 13px; font-weight: 800; letter-spacing: -.005em; }

.wizUploads { display: grid; gap: 4px; margin-bottom: 6px; }
.wizUploads[hidden] { display: none; }

/* The progress line and the question below it - one question, one screen,
   the count is the only thing here that does not change shape from one to
   the next. */
.wizProgress { margin: 0; font-size: 12px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); }

/* Rebuilt fresh on every step (see studio.js's renderWizStep), which is
   exactly what makes the animation below replay each time: a keyframe
   animation runs when the node it is on is inserted, not only once per
   stylesheet load, so a freshly built question lifts into place
   on its own without any class toggling from the script that built it. */
/* Every size in this question - label, hint, textarea, counter, the skip
   box - is exactly double its ordinary equivalent elsewhere in this file
   (.wizQ-label started at 19px, the hint at 12.5px, and so on). Asked for
   directly: one question at a time already gave this a whole screen to
   itself, so there was room to make it easier to read without anything
   else on the page having to shrink to fit it. */
.wizQ { display: grid; gap: 20px; animation: wizIn .32s ease both; }
@keyframes wizIn {
  from { transform: translateY(10px); }
  to { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .wizQ { animation: none; }
}

.wizQ-label { margin: 0; font-size: 38px; font-weight: 800; letter-spacing: -.01em; line-height: 1.3; }
.wizQ-label i { font-style: normal; font-weight: 600; color: var(--muted); }
.wizQ-hint { margin: -8px 0 0; font-size: 25px; line-height: 1.45; color: var(--muted); }

.wizQ textarea {
  font: inherit; font-size: 28px; color: var(--ink); background: var(--paper);
  border: 2px solid var(--line); padding: 18px 22px; resize: vertical; min-height: 168px;
}
.wizQ textarea:focus-visible { border-color: var(--ink); outline-offset: 0; }
.wizQ textarea:disabled { background: var(--hair); color: var(--muted); }
.wizQ .ccount { justify-self: end; font-size: 22px; }

.wizPlanSkip {
  display: flex; align-items: baseline; gap: 16px; cursor: pointer;
  font-size: 26px; color: var(--muted);
}
.wizPlanSkip input { flex: none; margin-top: 4px; transform: scale(2); transform-origin: left center; }

/* Next stays pinned to the right whether or not Back is showing - space-
   between would otherwise pull it back to the left the moment Back is
   [hidden], on the very first step. */
.wizNav { display: flex; align-items: center; gap: 16px; }
#wizNext { margin-left: auto; }
#wizNext[disabled] { opacity: .55; cursor: default; }

/* The one red element on this bar - brand red, whole-button rather than
   red text over whatever the live preview happens to be showing behind it,
   since a photo or video background makes red text a contrast gamble a
   solid button never has to take. */
/* S7: was #EC3013. Paper text on #EC3013 measures 3.76:1 and fails the
   4.5:1 floor, the same finding base.css documents for its own .btn-red,
   fixed there the same way: the button fills with red-700, and full red
   stays for the focus ring only, which is an accent rather than text. */
.btn-red {
  color: #F3F2F2;
  background: var(--red-700);
  border-color: var(--red-700);
}
.btn-red:hover { opacity: .9; }
.btn-red:focus-visible { outline: 2px solid #EC3013; outline-offset: 2px; }

/* ── love what you see? / the mock checkout ──────────────────────────────── */

/* Full screen from the first click on "Personalize It" - there is no small
   popup step before this one. The site itself visibly stows away
   underneath (.stage.stowed, below) while this comes out over it, so the
   comparison reads as replacing the site for a moment, not just covering
   it. */
.love {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  animation: loveIn .38s cubic-bezier(.2, .8, .2, 1) both;
}
.love[hidden] { display: none; }

@keyframes loveIn {
  from { transform: scale(.97) translateY(10px); }
  to { transform: none; }
}

/* The site, put away for as long as the comparison (or anything reached
   from it - checkout, the generation form) is up: smaller, dimmer, a touch
   desaturated, so it plainly reads as tucked aside rather than merely
   covered. stowStage() in studio.js is the only thing that toggles this;
   the transition itself lives on .stage's own rule, above. */
.stage.stowed { transform: scale(.93) translateY(8px); opacity: .5; filter: saturate(.55); }

@media (prefers-reduced-motion: reduce) {
  .love { animation: none; }
}

.loveCheckout {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  align-items: center;
}
.loveCheckout[hidden] { display: none; }
.loveCheckout > .afbar { align-self: stretch; }

.loveBody {
  flex: 1;
  width: 100%;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 16px 18px 20px;
}
.loveCheckout .loveBody {
  max-width: 640px;
  justify-content: safe center;
  gap: 26px;
  padding: clamp(20px, 3vh, 32px) clamp(20px, 4vw, 48px) 40px;
}

/* The comparison: two plans, side by side once there is room for both. */
.loveCompare {
  width: 100%;
  max-width: 920px;
  margin: 0 auto;
  display: grid;
  gap: 20px;
}
@media (min-width: 680px) { .loveCompare { grid-template-columns: 1fr 1fr; } }

/* S7, C8: Upgrade It is hidden (.plan[hidden] below), so the finish screen
   has one plan left, not two. Left at 1fr 1fr it would sit in the left
   column with an empty column beside it, so this panel's grid drops to one
   track and the card is given a reading width instead of stretching full
   bleed. #love keeps the two-column grid above: both its plans, DIY and
   Personalize It, still show. */
#finishLove .loveCompare { max-width: 460px; }
@media (min-width: 680px) { #finishLove .loveCompare { grid-template-columns: 1fr; } }

.plan {
  border: 1px solid var(--line);
  padding: clamp(20px, 3vw, 30px) clamp(20px, 3vw, 28px) 24px;
  display: grid;
  gap: 14px;
  align-content: start;
}
/* S7, C8: Upgrade It and the SEO/AEO add-on carry the hidden attribute
   in index.html rather than being removed, so studio.js's $('id') lookups
   still find them. Neither .plan nor .addon has a [hidden] override of its
   own yet, and both set their own display, which beats the browser default
   for [hidden] the same way .love[hidden] and the others below already
   need one. */
.plan[hidden] { display: none; }
/* The one plan actually being sold on, next to the one everybody gets
   anyway: a bolder border says "this one," without repainting the whole
   card the way the old single-choice list once did. */
.plan-highlight { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink); }
.plan-name { margin: 0; font-size: 20px; font-weight: 800; letter-spacing: -.01em; }
.plan-line { margin: -8px 0 0; font-size: 13px; color: var(--muted); }
.plan-price { margin: 0; font-size: 30px; font-weight: 800; font-variant-numeric: tabular-nums; }

.plan-features { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; font-size: 14px; }
.plan-features li { padding-left: 22px; position: relative; }
.plan-features li::before { content: "\2713"; position: absolute; left: 0; top: 0; font-weight: 800; }

.plan .btn { width: 100%; text-align: center; margin-top: 4px; }

/* The hosting add-on, one per plan: same service, same price, but adding
   it to the free files is a different thing to buy than adding it to the
   personalized site, so it is never a single shared checkbox. */
.addon {
  display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; align-items: baseline;
  background: var(--paper); border: 1px solid var(--hair); padding: 12px 14px; cursor: pointer;
}
.addon[hidden] { display: none; } /* S7, C8: the SEO/AEO add-on */
.addon input { grid-row: 1 / span 2; align-self: start; margin-top: 3px; }
.addon-name { font-size: 13px; font-weight: 800; }
.addon-name i { font-style: normal; font-weight: 700; color: var(--muted); margin-left: 8px; }
.addon-line { grid-column: 2; font-size: 12.5px; color: var(--muted); }

.loveSummary-line { font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; }

.checkoutItems { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.checkoutItems li {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 14px; padding-bottom: 8px; border-bottom: 1px solid var(--hair);
}
.checkoutItems li b { font-variant-numeric: tabular-nums; }

.offline {
  position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%);
  margin: 0; padding: 10px 16px; font-size: 13px;
  background: var(--ink); color: var(--paper);
  z-index: 5;
}
.offline[hidden] { display: none; }

/* The first-draft notice: a real dialog over a dimmed page, not a toast
   that could go unread. Above every other overlay's z-index of 10 - it is
   meant to be the one thing in front, the moment a generation lands. */
.firstDraft {
  position: fixed; inset: 0; z-index: 20;
  background: rgba(20, 19, 15, .5); /* --ink, as rgb - this file has no --ink-rgb of its own */
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.firstDraft[hidden] { display: none; }
.firstDraft-card {
  width: min(480px, 100%);
  background: var(--paper);
  border: 1px solid var(--line);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .3);
  padding: 28px 26px;
  display: grid;
  gap: 14px;
}
.firstDraft-card h2 { margin: 0; font-size: 20px; font-weight: 800; letter-spacing: -.01em; }
.firstDraft-card p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--muted); }
.firstDraft-card .btn { justify-self: start; }

/* The studio itself, at the same three widths the sites it builds use.
   Over 900 is a desktop, 900 and under a tablet, 620 and under a phone.

   A tablet needs no new geometry: the grid already drops a column as the
   row runs out of width for one, and a card sized from cqw reads the same
   at any width it lands on. What a tablet does need is something a finger
   can hit, and that is not a question about width. */

@media (hover: none) {
  /* Forty four pixels is a thumb. */
  .devices button { padding: 11px 14px; }
  .link, .back, .btn { padding-block: 12px; }
}

@media (max-width: 900px) {
  .bar { flex-wrap: wrap; }
  .question { margin-bottom: clamp(20px, 3vh, 36px); }
}

/* A phone. The grid needs nothing special here: auto-fill already drops to
   one column once nothing wider fits, which is the whole point of a grid
   over a wheel, and the 16:10 card reads the same size it prints itself at
   any width. Only the chrome around it needs a phone's worth of padding
   and a smaller heading. */
@media (max-width: 620px) {
  .ask { padding: clamp(16px, 3vh, 28px) 16px; }

  .question h1 { font-size: clamp(24px, 7vw, 32px); }

  /* The bar had grown to a third of the screen, because six controls that
     sit on one line at a desk each take a line of their own here, and the
     thing being built was left with what was over. Everything keeps its
     forty four pixels of thumb and gives up its padding. */
  .bar { gap: 7px 12px; padding: 7px 12px; }
  .chose { width: 100%; font-size: 11px; margin-right: 0; }
  .chose .jump { font-size: 11px; }
  .chose span { margin: 0 4px; }
  .devices button { padding: 13px 10px; font-size: 10px; }
  .link { font-size: 12px; }
  .btn { padding: 12px 14px; font-size: 12px; }

  /* The three little links that jump back to a question are eighteen
     pixels of text and a thumb is forty four. Growing them would put two
     more lines on a bar that is already too tall, so what grows is only
     what the finger lands on. */
  .chose .jump { position: relative; }
  .chose .jump::after { content: ""; position: absolute; inset: -13px -8px; }
  /* A folder on this machine, read on another one. Worth showing, not
     worth two lines. */
  .path { font-size: 10px; padding: 5px 12px; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; }
}

@media (prefers-reduced-motion: reduce) {
  .working span { animation: none; }
  .card { transition: none; }
  .track { transition: none; }
  .space { transition: none; }
}

/* The full library uses native filters and lightweight composition cards.
   A real website is built only when a visitor chooses a template. */
.ask { max-width: 1560px; align-content: start; padding: 24px clamp(20px,4vw,64px) 64px; }
.library-brand { display:flex; align-items:center; justify-content:space-between; gap:20px; border-bottom:2px solid var(--ink); padding-bottom:22px; font-size:13px; }
.library-brand a { color:var(--ink); text-decoration:none; font-size:20px; font-weight:800; }
.library-brand a span { font-size:13px; font-weight:500; margin-left:12px; }
.library-heading { text-align:left; margin:56px 0 36px; }
.library-eyebrow { font-size:12px; font-weight:800; letter-spacing:.14em; color:#b7240d; margin:0 0 18px; }
.library-heading h1 { font-size:clamp(36px,5.7vw,78px); max-width:850px; letter-spacing:-.055em; }
.library-heading .sub { margin:22px 0 0; max-width:64ch; font-size:17px; text-wrap:pretty; }
.library-controls { display:flex; gap:16px; align-items:end; margin-bottom:24px; }
.library-controls label { display:flex; flex-direction:column; gap:8px; font-size:12px; font-weight:700; }
.library-search { flex:1; }
.library-controls input,.library-controls select { font:16px var(--font); min-height:50px; padding:12px 16px; border:2px solid var(--ink); background:#fff; border-radius:0; color:var(--ink); }
.library-controls input { width:100%; }
.library-page-filter { width:210px; }
.genre-filters { display:flex; gap:8px; flex-wrap:wrap; }
.genre-filters button { display:flex; align-items:center; justify-content:space-between; gap:12px; background:transparent; border:1px solid #bdb9b5; border-radius:0; min-height:42px; padding:9px 12px; font:500 12px var(--font); cursor:pointer; color:var(--ink); }
.genre-filters button[aria-pressed="true"] { background:var(--ink); color:#fff; border-color:var(--ink); }
.genre-filters button:hover { border-color:var(--red); }
.genre-filters small { opacity:.7; font-size:11px; }
.library-results { display:flex; justify-content:space-between; align-items:center; gap:16px; margin:30px 0 20px; border-top:1px solid #c9c5c1; padding-top:18px; font-size:13px; }
.library-results p { margin:0; font-weight:600; }
.template-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:28px 24px; }
.template-card { min-width:0; background:white; border:1px solid #c8c5c1; display:flex; flex-direction:column; transition:border-color .18s,transform .18s; }
.template-card:focus-within,.template-card:hover { border-color:var(--ink); transform:translateY(-3px); }
.template-picture { aspect-ratio:1.48; padding:14px 18px; overflow:hidden; display:flex; flex-direction:column; background:#efebe4; color:#272622; }
.template-picture.template-screenshot { padding:0; aspect-ratio:1.44; }
.template-screenshot img { display:block; width:100%; height:100%; object-fit:cover; object-position:top; }
/* A picture that has not been asked for yet carries its address on data-src
   and no src at all, so the browser would otherwise draw the alt text in the
   hole where the screenshot goes. It keeps its box - width, height and the
   aspect-ratio above all still apply - and reads as a plain tile until
   watchCardImage() hands it the address. */
.template-picture img[data-src] { color:transparent; font-size:0; background:#ddd8d1; }
.template-card:nth-child(5n+2) .template-picture { background:#e3e9e8; color:#233b3b; }
.template-card:nth-child(5n+3) .template-picture { background:#ece6e0; color:#473b34; }
.template-card:nth-child(5n+4) .template-picture { background:#e6e9df; color:#323a2b; }
.template-card:nth-child(5n+5) .template-picture { background:#e5e4ee; color:#343047; }
.template-mock-nav { display:flex; justify-content:space-between; gap:12px; align-items:center; font-size:7px; border-bottom:1px solid #29252130; padding-bottom:12px; }
.template-mock-nav b { font-size:9px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.template-mock-nav span { font-size:5px; white-space:nowrap; }
.template-mock-body { flex:1; min-height:0; display:grid; grid-template-columns:1fr 1fr; gap:15px; align-items:center; padding:15px 0; }
.template-mock-body img { height:100%; max-height:155px; width:100%; object-fit:cover; }
.template-mock-copy { min-width:0; }
.template-mock-copy small { display:block; font-size:5px; text-transform:uppercase; letter-spacing:.08em; margin-bottom:7px; }
.template-mock-copy strong { display:block; font-family:Georgia,serif; font-size:clamp(16px,1.7vw,25px); line-height:1.06; font-weight:500; letter-spacing:-.025em; max-height:4.3em; overflow:hidden; }
.template-mock-copy i { display:inline-block; background:currentColor; margin-top:9px; padding:5px 9px; font-size:5px; line-height:1; font-style:normal; color:#fff; background:#373c36; }
.mock-line { display:block; height:2px; background:currentColor; opacity:.2; margin-top:10px; width:92%; }
.mock-line.short { width:65%; margin-top:3px; }
.template-mock-sections { display:flex; justify-content:space-between; gap:8px; border-top:1px solid #29252130; padding:9px 0 0; font-size:5px; text-transform:uppercase; letter-spacing:.02em; }
.template-mock-sections span { flex:1; }
.template-picture[data-composition="editorial"] .template-mock-copy strong { font-style:italic; }
.template-picture[data-composition="rail"] .template-mock-nav { display:none; }
.template-picture[data-composition="rail"] .template-mock-body { border-left:14px solid #343331; padding-left:15px; }
.template-picture[data-composition="offset"] .template-mock-body img { transform:translateY(8px); border:6px solid #fff; }
.template-picture[data-composition="panel"] .template-mock-body { margin:8px 0; background:#ffffff75; padding:12px; }
.template-picture[data-composition="centered"] .template-mock-body,.template-picture[data-composition="stacked"] .template-mock-body { grid-template-columns:1fr; gap:8px; padding:10px 0; text-align:center; }
.template-picture[data-composition="centered"] .template-mock-copy strong,.template-picture[data-composition="stacked"] .template-mock-copy strong { font-size:20px; max-width:85%; margin:auto; }
.template-picture[data-composition="centered"] .template-mock-body img,.template-picture[data-composition="stacked"] .template-mock-body img { max-height:65px; }
.template-picture[data-composition="centered"] .mock-line,.template-picture[data-composition="stacked"] .mock-line { display:none; }
.template-picture[data-composition="cover"] .template-mock-body,.template-picture[data-composition="banner"] .template-mock-body { position:relative; grid-template-columns:1fr; padding:16px; margin:10px 0; }
.template-picture[data-composition="cover"] .template-mock-body img,.template-picture[data-composition="banner"] .template-mock-body img { position:absolute; inset:0; height:100%; max-height:none; z-index:0; filter:brightness(.45); }
.template-picture[data-composition="cover"] .template-mock-copy,.template-picture[data-composition="banner"] .template-mock-copy { position:relative; z-index:1; color:white; max-width:75%; }
.template-details { display:flex; flex-direction:column; flex:1; padding:20px; }
.template-meta { display:flex; justify-content:space-between; gap:12px; color:#65605c; font-size:10px; font-weight:500; }
.template-meta span:last-child { white-space:nowrap; }
.template-details h2 { margin:14px 0 2px; font-size:24px; line-height:1.15; letter-spacing:-.035em; font-weight:800; }
.template-business { margin:5px 0 0; font-size:12px; font-weight:700; }
.template-description { font-size:13px; color:#66605b; line-height:1.65; margin:10px 0 22px; }
.template-use { width:100%; margin-top:auto; min-height:44px; border:2px solid var(--ink); border-radius:0; background:white; color:var(--ink); padding:11px 14px; text-align:left; font:700 12px var(--font); cursor:pointer; }
.template-use:hover,.template-use:focus-visible { color:white; background:var(--ink); }
.library-note { font-size:13px; max-width:74ch; color:var(--muted); border-top:2px solid var(--ink); padding-top:24px; margin-top:40px; }
.library-empty { padding:50px 20px; text-align:center; border:1px solid var(--line); }
.pagebar { display:flex; flex:none; align-items:center; gap:12px; padding:8px 20px; border-bottom:1px solid var(--line); font-size:12px; background:var(--paper); }
.pagebar[hidden] { display:none; }
.pagebar select { padding:8px 30px 8px 10px; font:600 12px var(--font); max-width:240px; border:1px solid var(--ink); border-radius:0; background:white; }
.pagebar span:last-child { margin-left:auto; color:var(--muted); }
.btn,.back { border-radius:0; }
.barstep { flex-wrap:wrap; }
@media(max-width:1100px) { .template-grid { grid-template-columns:repeat(2,minmax(0,1fr)); } .template-mock-copy strong { font-size:24px; } }
@media(max-width:650px) {
  .library-brand>span,.library-brand a span { display:none; }
  .library-heading { margin:35px 0 28px; }
  .library-heading .sub { font-size:15px; }
  .library-controls { flex-direction:column; align-items:stretch; gap:12px; }
  .library-page-filter { width:100%; }
  .template-grid { grid-template-columns:1fr; gap:22px; }
  .template-picture { aspect-ratio:1.6; }
  .template-mock-copy strong { font-size:27px; }
  .genre-filters button { flex:1 1 44%; font-size:11px; gap:6px; padding:9px; }
  .genre-filters button:first-child { flex-basis:100%; }
  .library-results { font-size:11px; }
  .pagebar { flex-wrap:wrap; padding:8px 12px; gap:8px; }
  .pagebar span:last-child { display:none; }
  .pagebar select { max-width:calc(100vw - 165px); }
}
@media(prefers-reduced-motion:reduce) { .template-card { transition:none; } .template-card:hover { transform:none; } }
