/* SelfMark platform: intake, the wait, the install page.

   The tokens below are the marketing site's tokens (site/css/styles.css),
   copied rather than imported because the platform is a separate service and
   a broken cross-origin stylesheet would take the whole form down with it.
   Keep them in step: if the site's blue moves, this one moves.

   What is new here is the transaction layer the site never needed: fields,
   labels, inline errors, a progress state, and the copy button. Those follow
   Apple's retail grammar rather than its showcase grammar - white canvas,
   border-led containment, 12px control radius, blue reserved for actions. */

:root {
  --black: #000;
  --light: #f5f5f7;
  --white: #fff;

  --ink: #1d1d1f;
  --ink-inv: #f5f5f7;
  --muted-dark: #86868b;
  --muted-light: #6e6e73;
  --hair: #d2d2d7;

  --blue: #0071e3;
  --blue-hover: #0077ed;
  --link: #2997ff;
  --alert: #d70015;
  --good: #1d7d3f;

  /* The app bar's ground and its one edge. These were the builder's, in
     builder.css, because the builder was the only screen with an app bar in
     its working clothes. There is one bar now and it is on every page, so its
     tokens live with the stylesheet every page loads. Same values, same
     roles; builder.css reads them from here. */
  --bar: #0e0e10;
  --edge: rgba(255, 255, 255, .08);

  /* The dense chrome's own light side, and it moved here for exactly the
     reason `--bar` did. `--panel-edge` is one step lighter than `--hair`, and
     it is what a panel wears when a screen carries three of them instead of
     one: the builder's tiles have used it since the builder, and every panel
     under `/app` uses it since amendment 2. Two stylesheets depend on these
     now, so they live with the stylesheet every page loads.

     This was a real defect and a silent one. `app.css` reached for
     `--panel-edge` and `--blue-wash` while both were declared in
     `builder.css`, which no app screen loads, so `border-color:
     var(--panel-edge)` computed to `currentColor` and drew a panel outlined
     in `--ink`, and the marked rail item's `--blue-wash` ground computed to
     nothing at all. */
  --panel: #fff;
  --panel-edge: #e3e3e6;
  --tile: #f7f7f9;
  --blue-wash: rgba(0, 113, 227, .05);

  /* The interface's own motion, which is deliberately small and is not the
     card's: nothing describing how a signature animates may be typed into
     CSS, because those numbers come off /api/spec. DESIGN.md 4 is the table.

     These were the builder's, in builder.css, for the same reason `--bar` was:
     it was the only screen with controls dense enough to need them. The app
     shell needs the same press and hover timings, so they move here at exactly
     the values they had, and builder.css reads them from here. */
  --t-fast: 120ms;
  --t-base: 180ms;
  --t-swap: 240ms;
  --t-glide: 420ms;
  --ease-out: cubic-bezier(.2, .7, .2, 1);
  /* The selection ring lands, it does not bounce. An overshoot on a 2px
     border reads as bad alignment rather than as delight, because the ring's
     whole job is to sit exactly on a tile's edge. Overshoot belongs to the
     card's own motion, where the engine's pops are specified with one, and
     the card's motion is generated from /api/spec rather than from here. */
  --ease-glide: cubic-bezier(.22, 1, .36, 1);
  /* The dashboard's two, and both are `brand-dashboard-v2`'s own numbers.

     `--ease-land` is what arrives: the entrance's 8px rise, the fold's height
     morph, and anything that appears where nothing was. It is `--ease-out`
     with a touch more of the deceleration at the end, which is what a stagger
     of four boxes needs to read as one movement rather than four.

     `--ease-spring` overshoots, on purpose and in exactly two places: the
     period indicator gliding to the segment that was just pressed, and the
     card's tilt following a pointer. Both are beui.dev mechanisms whose point
     IS the spring — `tabs` at stiffness 170 / damping 24 / mass 1.2, and
     `tilt-card` at 200 / 15 / 0.3, both underdamped — and a cubic-bezier
     whose second control point sits above 1 is the cheapest honest version of
     that in a stylesheet. It is never used on a ring, an edge or anything
     that has to line up with something else: see `--ease-glide` above. */
  --ease-land: cubic-bezier(.2, .8, .2, 1);
  --ease-spring: cubic-bezier(.2, .9, .3, 1.2);

  --font: "SF Pro Display", "SF Pro Text", -apple-system, BlinkMacSystemFont,
          "Helvetica Neue", Arial, sans-serif;

  --wrap: 760px;
  --pad: 22px;

  --zoom-card: .64;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

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

body {
  background: var(--light);
  color: var(--ink);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.47;
  letter-spacing: -.01em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

  /* The wait page is short. Without this the footer floats halfway up the
     screen with the page background under it, which reads as a page that
     failed to finish loading - exactly the wrong signal while a customer is
     waiting on a render. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
/* `width: 100%` here is not decoration and it fails silently. In a COLUMN
   flex container the line's cross size is the widest item's max-content, and
   the container's own width does not clamp it, so one wide child (the
   builder's seven-tile reel) stretches every sibling and the whole document
   scrolls sideways. Measured at 375px: the body stayed 375 and `main` went to
   950. Pinning each child to the container's width is the fix. */
body > * { flex-shrink: 0; width: 100%; }
.spacer { flex: 1 0 0; }

img { max-width: 100%; }
.cardhost img { max-width: none; }

.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--pad);
}

/* --------------------------------------------------------------- type */
h1, h2, h3 { font-weight: 600; letter-spacing: -.015em; }
h1 { font-size: clamp(30px, 5.4vw, 44px); line-height: 1.08; }
h2 { font-size: clamp(22px, 3.2vw, 28px); line-height: 1.14; }
h3 { font-size: 19px; line-height: 1.21; }

.sub {
  font-size: 19px;
  line-height: 1.42;
  color: var(--muted-light);
  font-weight: 400;
}
.on-dark .sub, .dark .sub { color: var(--muted-dark); }

.micro { font-size: 13px; line-height: 1.5; color: var(--muted-light); }
.step-of {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-light);
}
.dark .step-of { color: var(--muted-dark); }

a { color: var(--blue); }
.dark a { color: var(--link); }

/* ------------------------------------------------------------ chrome */
/* One app bar, and it is the builder's: opaque on `--bar`, closed with a
   hairline in `--edge` rather than with a shadow. It used to be Apple's
   frosted `rgba(22,22,23,.8)` here and the builder's opaque one there, which
   was two bars pretending to be one.
   The frost was also a real accessibility failure and not a small one. Eight
   tenths of #161617 over the page's `--light` composites to about #434344, so
   the support address at `--muted-dark` measured **2.72:1** against it, on
   every page of the service since the first one, and the three new section
   links would have inherited exactly that. On `--bar` the same grey measures
   5.4:1. The material the bar loses is a blur nobody could see over a flat
   canvas; what it gains is text somebody can read. */
.nav {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bar);
  border-bottom: 1px solid var(--edge);
}
.nav-inner {
  max-width: 1160px;
  margin: 0 auto;
  padding: 0 var(--pad);
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}
/* The wordmark is the drawn SelfMark lockup rather than the brand's word set
   in Inter. Both surfaces this stylesheet puts it on, the bar and the footer,
   are black, so both take the on-black file, whose letters are `--ink-inv`
   under another name and whose person is `--blue`. */
.wordmark { text-decoration: none; }
/* The 9px square went with the word. It was a mark standing in for a mark
   nobody had drawn yet, and setting it beside the lockup would be the product
   wearing two of them. The bar is one line of 52px and the lockup is two
   stacked lines, so 30px is the height that sits inside it with air left over
   above and below. */
.nav .wordmark { display: inline-flex; align-items: center; }
.nav .wordmark img { display: block; height: 30px; width: auto; }

.nav-right { font-size: 12px; color: var(--muted-dark); white-space: nowrap; }
.nav-right a { color: var(--muted-dark); text-decoration: none; }
.nav-right a:hover { color: var(--ink-inv); }

/* The account spine, in the bar. Three destinations and a mark on the one
   you are standing in, which is the whole of what four screens were missing.

   The mark is a 2px rule in `--blue` under the label, which is the selection
   language the builder's template tile already speaks, plus the weight going
   to 600. Two signals rather than one, because the underline alone is 2px of
   colour on a near-black bar and the weight alone is a difference nobody
   reads at 13px. Nothing here is a new token.

   The row shrinks before the wordmark does: at a phone's width the three
   labels are the thing worth keeping whole, so they hold their size and the
   wordmark is what gives ground. */
.nav-links {
  display: flex;
  align-items: center;
  gap: 18px;
  font-size: 13px;
  line-height: 1.2;
  flex: 0 1 auto;
  min-width: 0;
}
.nav-links a {
  color: var(--muted-dark);
  text-decoration: none;
  white-space: nowrap;
  padding: 3px 0;
  border-bottom: 2px solid transparent;
  transition: color .18s ease, border-color .18s ease;
}
.nav-links a:hover { color: var(--ink-inv); }
.nav-links a[aria-current] {
  color: var(--ink-inv);
  font-weight: 600;
  border-bottom-color: var(--blue);
}
/* The bar is one line of 52px, and the brand's word plus three labels plus
   the support address measured 384px across a 375px phone. Something has to
   give, and now that the brand is a drawn thing rather than a set word it is
   the lockup that gives rather than the lockup that goes: at 22px tall it is
   about 44px wide, well under the 72px the word took at 15px, so the three
   links and the support address keep their size and the row comes back inside
   the screen with the brand still visible on it. 22px is small and the letters
   survive it, because the lockup is drawn heavy and stacked in two lines
   rather than run out in one. From 360 up, at any rate: the block after this
   one is what a 320 does, and why it cannot do this. */
@media (max-width: 559px) {
  .nav-inner { gap: 14px; }
  .nav-links { gap: 16px; }
  .nav .wordmark img { height: 22px; }
  /* At that size the link home is 44px across and 22 tall: half a tap target,
     on the one screen size where the only pointer IS a thumb. The lockup
     stays 22px and the TARGET becomes 44 square, which is the size everything
     else on this bar already is.

     An overlay rather than a taller box, because padding the anchor out to 44
     would have it fighting the 52px bar for the room, and the pseudo-element
     takes no space at all: it reaches into the bar's own padding on one side
     and into the gap before Signature on the other, and both of those are
     air.

     **It is anchored to the bar's padding edge, not centred on the mark, and
     a second review is the author of that.** Centred, it ran from -17.5 to
     +26.5 around a 9px mark, and `.nav-inner` bottoms out at its 14px gap on
     a 320px screen: the last 3.5px of the overlay lay over the first 3.5px of
     Signature, and being positioned it won every tap there. A thumb aiming at
     the account got sent to the marketing site.

     Widening the gap was the obvious fix and there is nothing to widen it
     with — the row exactly fills 320 — and shrinking the target is the wrong
     direction on the one width where the target is the whole point. So the
     overlay starts where the bar's own padding does, which puts its left edge
     on the screen edge and its right edge at 44. Measured signed in, with all
     three labels: Signature starts at 72.5 at 320 and further right at every
     width above it, so the two boxes are disjoint everywhere this rule
     applies. An edge-flush target is also the easiest kind of all to hit.

     The lockup outruns the target to the right now, ending at 66.4. That
     leaves nothing uncovered, because the anchor's own box is a link wherever
     the mark is drawn and the overlay is only what gives the short side its
     44; a thumb landing on either gets the same address. */
  .nav .wordmark { position: relative; }
  .nav .wordmark::after {
    content: "";
    position: absolute;
    top: 50%;
    left: calc(var(--pad) * -1);
    width: 44px;
    height: 44px;
    transform: translateY(-50%);
  }
}

/* **And on a 320 the brand still has to stand down, because the row there has
   no room for a mark at all.** Measured signed in, at 320, with the bar's own
   22px of padding either side: the three labels want 166px, the support
   address wants 75.5, the two gaps want 28, and 276 is all there is. That
   leaves 6.5px for the wordmark — less than the 9px square that used to sit
   there. Anything larger is taken back out of `.nav-links`, which carries
   `min-width: 0` and so gives way silently: at 22px the lockup is 36.5 wide,
   the labels lose 30px of their box, and `Account` is printed straight over
   `Need a hand?`. Trimming the gaps does not reach it either — the labels
   would have to sit 6px apart before the row cleared, and 6px between three
   words is not a row anybody can read.

   So below 360 the lockup goes and the 9px square comes back, which is what
   this bar did at every phone width until the mark existed. The brand is on
   the bar from 360 up, which is every phone made this decade, and on the one
   size below it the link home is what it always was: a square, an accessible
   name, and the same 44px target under it. Measured slack before `Need a
   hand?`: 320 → +12.0 with the square, and 360 → +15.3, 375 → +22.8,
   390 → +30.3 with the lockup. */
@media (max-width: 359px) {
  .nav .wordmark img { display: none; }
  .nav .wordmark::before {
    content: "";
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 2.5px;
    background: var(--ink-inv);
  }
}

.foot {
  background: var(--black);
  padding: 46px 0 54px;
  text-align: center;
  margin-top: 74px;
}
/* The footer's lockup is a signature at the end of a page rather than a piece
   of chrome, so it is drawn at 44px, half again the bar's, and the `.foot`
   centres it the way it centres everything else under it. */
.foot .wordmark { display: inline-block; }
.foot .wordmark img { display: block; height: 44px; width: auto; margin: 0 auto; }
.foot-legal {
  margin-top: 14px;
  font-size: 12px;
  color: var(--muted-dark);
}
.foot-legal a { color: var(--muted-dark); text-decoration: none; }
.foot-legal a:hover { color: var(--ink-inv); }
.foot-links-row { margin-top: 8px; display: flex; gap: 20px; justify-content: center; }
.foot-links-row a { text-decoration: underline; text-underline-offset: 2px; }

/* ------------------------------------------------------------ sections */
.dark {
  background: var(--black);
  color: var(--ink-inv);
  text-align: center;
  padding: 62px 0 68px;
}
.dark h1, .dark h2 { color: var(--ink-inv); }

.pad { padding: 54px 0 0; }
.center { text-align: center; }

/* --------------------------------------------------------- the card */
.cardhost {
  text-align: center;
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
}
.cardzoom { display: inline-block; zoom: var(--zoom-card); }
.cardglow {
  display: inline-block;
  filter: drop-shadow(0 30px 70px rgba(255, 255, 255, .10))
          drop-shadow(0 6px 18px rgba(0, 0, 0, .6));
}

.win {
  background: var(--white);
  border: 1px solid #e4e7eb;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 12px 34px rgba(20, 24, 28, .07);
}
.win-bar { padding: 11px 14px; border-bottom: 1px solid #edf0f3; text-align: left; }
.win-bar span {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: #e4e7eb;
  margin-right: 6px;
}
.win-body { padding: 24px 14px 26px; }

/* ------------------------------------------------------------ buttons */
.pill {
  display: inline-block;
  background: var(--blue);
  color: #fff;
  border: 0;
  border-radius: 980px;
  padding: 13px 28px;
  font-family: inherit;
  font-size: 17px;
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -.012em;
  text-decoration: none;
  cursor: pointer;
  transition: background .2s ease, transform .12s ease;
}
.pill:hover { background: var(--blue-hover); }
.pill:active { transform: scale(.985); }
/* `display: inline-block` on a class beats the UA sheet's
   `[hidden] { display: none }`, so a pill that ships hidden and is un-hidden by
   script — Play on the account page — has to restate it or it is a control
   that shows up on a page with no script and does nothing. Same restatement,
   same reason, as `.drop[hidden]` in builder.css. */
.pill[hidden] { display: none; }
.pill-block { display: block; width: 100%; text-align: center; padding: 15px 28px; }
.pill-big { font-size: 19px; padding: 16px 40px; }
.pill-quiet {
  background: transparent;
  color: var(--blue);
  padding: 13px 10px;
}
.pill-quiet:hover { background: transparent; text-decoration: underline; }
.dark .pill-quiet { color: var(--link); }

.linkish {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--blue);
  cursor: pointer;
  text-decoration: none;
}
.linkish:hover { text-decoration: underline; }

:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
  border-radius: 4px;
}

/* -------------------------------------------------------------- sheet */
.sheet {
  background: var(--white);
  border: 1px solid var(--hair);
  border-radius: 20px;
  padding: 32px 26px;
  margin-top: 28px;
}
.sheet + .sheet { margin-top: 20px; }
.sheet-head { margin-bottom: 22px; }
.sheet-head h2 { margin-bottom: 6px; }

/* ------------------------------------------------------------- prose
   The two legal pages are the only long-form reading in the platform. The
   reset zeroes every margin, which is right for a form sheet and wrong for a
   page somebody has to read a screenful of, so this is the one place a bare
   <p> and a bare <li> get their own rhythm back. */
.prose > * + * { margin-top: 14px; }
/* The two legal pages ran `h1` straight to `h3`, which is a skipped level and
   a real audit failure: a screen reader user tabbing headings is told there
   is a level missing. They are `h2` now and they are drawn at exactly the
   size they were drawn at before, because the defect was the semantics and
   not the type. */
.prose h2, .prose h3 { font-size: 19px; line-height: 1.21; margin-top: 30px; }
.prose > h2:first-child, .prose > h3:first-child { margin-top: 0; }
.prose p, .prose li {
  font-size: 16px;
  line-height: 1.55;
  color: var(--muted-light);
}
.prose strong { color: var(--ink); font-weight: 600; }
.prose ul { list-style: none; }
.prose li { position: relative; padding-left: 18px; }
.prose li + li { margin-top: 8px; }
.prose li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 11px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--hair);
}

.group { border: 0; margin-top: 34px; }
.group:first-of-type { margin-top: 0; }
.group legend {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted-light);
  margin-bottom: 16px;
}

/* -------------------------------------------------------------- fields */
.field { margin-top: 18px; }
.field:first-of-type { margin-top: 0; }
.field label { display: block; font-size: 14px; font-weight: 600; margin-bottom: 7px; }
.field .opt { font-weight: 400; color: var(--muted-light); }

.field input[type="text"],
.field input[type="email"],
.field input[type="url"] {
  width: 100%;
  font-family: inherit;
  font-size: 17px;
  line-height: 1.3;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--hair);
  border-radius: 12px;
  padding: 12px 14px;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field input::placeholder { color: #a1a1a6; }
.field input:focus {
  outline: 0;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(0, 113, 227, .18);
}
.field input[aria-invalid="true"] { border-color: var(--alert); }

.hint { margin-top: 7px; font-size: 13px; line-height: 1.45; color: var(--muted-light); }
.err {
  margin-top: 7px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--alert);
  font-weight: 500;
}

.row2 { display: grid; grid-template-columns: 1fr; gap: 18px; }

/* colour + file controls */
.swatch { display: flex; align-items: center; gap: 12px; }
.swatch input[type="color"] {
  width: 54px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--hair);
  border-radius: 10px;
  background: var(--white);
  cursor: pointer;
}
.swatch code { font-size: 14px; color: var(--muted-light); }

input[type="file"] {
  width: 100%;
  font-family: inherit;
  font-size: 14px;
  color: var(--muted-light);
}
input[type="file"]::file-selector-button {
  font-family: inherit;
  font-size: 14px;
  color: var(--ink);
  background: var(--light);
  border: 1px solid var(--hair);
  border-radius: 980px;
  padding: 8px 16px;
  margin-right: 12px;
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: #ebebed; }

/* Radio choices, as Apple's option tiles rather than dots. Selectors are
   scoped through .choices because a tile IS a <label>, and `.field label`
   below would otherwise win on specificity and flatten the flex row. */
.choices { display: grid; gap: 10px; }
.choices .choice {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  border: 1px solid var(--hair);
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 0;
  font-size: 15px;
  font-weight: 400;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.choices .choice:hover { background: var(--light); }
.choices .choice input { margin-top: 3px; accent-color: var(--blue); flex: none; }
.choices .choice-body strong { display: block; font-size: 15px; font-weight: 600; }
.choices .choice-body span {
  display: block;
  font-size: 13px;
  font-weight: 400;
  color: var(--muted-light);
  margin-top: 2px;
}
.choices .choice:has(input:checked) { border-color: var(--blue); background: rgba(0, 113, 227, .04); }

.submit-row { margin-top: 30px; }
.submit-note { margin-top: 14px; font-size: 13px; color: var(--muted-light); text-align: center; }

/* ------------------------------------------------------------ progress */
.stage {
  margin-top: 30px;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -.014em;
}
.bar {
  position: relative;
  width: min(420px, 100%);
  height: 4px;
  margin: 22px auto 0;
  border-radius: 999px;
  background: #2c2c2e;
  overflow: hidden;
}
.bar i {
  position: absolute;
  inset: 0;
  display: block;
  width: 38%;
  border-radius: 999px;
  background: var(--blue);
  transform: translateX(-100%);
  animation: sweep 1.9s cubic-bezier(.45, 0, .25, 1) infinite;
}
@keyframes sweep {
  0%   { transform: translateX(-105%); }
  100% { transform: translateX(320%); }
}

/* -------------------------------------------------------- instructions */
.howto { counter-reset: s; list-style: none; margin-top: 14px; }
.howto li {
  counter-increment: s;
  position: relative;
  padding: 0 0 12px 34px;
  font-size: 16px;
  line-height: 1.5;
}
.howto li::before {
  content: counter(s);
  position: absolute;
  left: 0;
  top: 1px;
  width: 23px;
  height: 23px;
  border-radius: 50%;
  background: var(--light);
  border: 1px solid var(--hair);
  font-size: 12px;
  font-weight: 600;
  color: var(--muted-light);
  display: flex;
  align-items: center;
  justify-content: center;
}

.notice {
  border: 1px solid var(--hair);
  border-radius: 14px;
  padding: 18px 20px;
  background: var(--light);
  font-size: 15px;
  line-height: 1.5;
}
.notice strong { display: block; margin-bottom: 4px; }
.notice-alert { border-color: rgba(215, 0, 21, .35); background: rgba(215, 0, 21, .04); }
/* The same object on a dark section. The wait page is the only place a notice
   lands on black, and the sheet's colours are invisible there. */
.dark .notice { background: #1c1c1e; border-color: #2c2c2e; color: var(--ink-inv); }
.dark .notice-alert { border-color: rgba(255, 105, 97, .4); background: rgba(255, 105, 97, .07); }

/* The wait page's honest late state: the same width as the progress bar it
   sits under, and left aligned, because it is three sentences rather than a
   headline. */
.wait-late { max-width: 460px; margin: 30px auto 0; text-align: left; }
.wait-late .submit-row { margin-top: 18px; }
.dark .wait-late .kv, .dark .wait-late .micro { color: var(--muted-dark); }

/* -------------------------------------------------- the client chooser
   Radios and sibling selectors rather than script. The install steps are the
   whole product at this point, so they have to be on the page before any
   JavaScript is, and a keyboard has to be able to move between them. */
.clients { border: 0; margin-top: 24px; }
.clients legend { font-size: 16px; font-weight: 600; margin-bottom: 12px; }
.client-pick { position: absolute; opacity: 0; width: 1px; height: 1px; }
.client-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 22px; }
.client-tabs label {
  padding: 8px 15px;
  border: 1px solid var(--hair);
  border-radius: 980px;
  font-size: 14px;
  line-height: 1.2;
  color: var(--muted-light);
  cursor: pointer;
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.client-tabs label:hover { background: var(--light); }
.client-panel { display: none; }
.client-panel h3 { font-size: 16px; color: var(--muted-light); font-weight: 600; }

#cl-gmail:checked   ~ .client-tabs label[for="cl-gmail"],
#cl-outlook:checked ~ .client-tabs label[for="cl-outlook"],
#cl-apple:checked   ~ .client-tabs label[for="cl-apple"],
#cl-zoho:checked    ~ .client-tabs label[for="cl-zoho"] {
  border-color: var(--blue);
  background: rgba(0, 113, 227, .06);
  color: var(--ink);
  font-weight: 600;
}
#cl-gmail:focus-visible   ~ .client-tabs label[for="cl-gmail"],
#cl-outlook:focus-visible ~ .client-tabs label[for="cl-outlook"],
#cl-apple:focus-visible   ~ .client-tabs label[for="cl-apple"],
#cl-zoho:focus-visible    ~ .client-tabs label[for="cl-zoho"] {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
}
#cl-gmail:checked   ~ [data-client="gmail"],
#cl-outlook:checked ~ [data-client="outlook"],
#cl-apple:checked   ~ [data-client="apple"],
#cl-zoho:checked    ~ [data-client="zoho"] { display: block; }

.copied { margin-top: 14px; font-size: 15px; color: var(--good); min-height: 22px; }
.dark .copied { color: #6ee7a0; }

.kv { margin-top: 10px; font-size: 13px; color: var(--muted-light); }
/* An address is one unbroken token and the two this page prints are long
   ones. Without this the order's own URL is 411px of `<code>` inside a 375px
   phone, which scrolls the whole document sideways: measured on the install
   page at 375, and it predates the card block that now prints one too. */
.kv code { font-size: 12.5px; overflow-wrap: anywhere; }

/* a receipt-style list: what is being bought, before it is bought */
.lines { margin-top: 4px; }
.lines > div {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 11px 0;
  border-top: 1px solid var(--hair);
  font-size: 15px;
}
.lines > div:first-child { border-top: 0; }
.lines dt { color: var(--muted-light); flex: none; }
.lines dd { text-align: right; min-width: 0; overflow-wrap: anywhere; }

/* ------------------------------------------------- the card's controls
   The account page's one new block. It stays in the platform's vocabulary,
   which is the standing rule for /me: the builder is the designed surface and
   the card is the customer's own, and a third styled screen competing with
   both is a redesign nobody asked for.

   The theme picker is a real fieldset of radios, like the builder's template
   picker, so it is keyboard navigable with arrow keys for free and the tile
   is the <label>. */
.themes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(152px, 1fr));
  gap: 12px;
  margin-top: 4px;
}
.themes .pick { position: absolute; opacity: 0; width: 1px; height: 1px; }
.themes label {
  display: block;
  padding: 8px 8px 10px;
  border: 1px solid var(--hair);
  border-radius: 14px;
  background: var(--white);
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.themes label:hover { background: var(--light); }
.themes .pick:checked + label {
  border-color: var(--blue);
  background: rgba(0, 113, 227, .05);
}
.themes .pick:focus-visible + label { outline: 3px solid var(--blue); outline-offset: 2px; }

.themes .tname {
  display: block;
  margin-top: 9px;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
}
/* Same rule as the tabs above: the chosen tile is already marked by its
   border and its ground, and #0071e3 on the blue wash measures 4.39:1. */
.themes .pick:checked + label .tname { color: var(--ink); }
.themes .tblurb {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--muted-light);
}
.themes .tnote {
  display: block;
  margin-top: 5px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--muted-light);
  font-style: italic;
}

/* THE PREVIEW. A real card in a real frame, at a fifth of the size.

   Phase B drew six rectangles and a disc per theme in this file, and the
   comment where they used to be apologised for it: those values were the one
   place in the service where card.css's own tokens were written twice, and
   they said WHICH theme and nothing else. They could not say what a hero
   looks like, could not show the customer their own photograph in it, and
   went out of date the moment a theme moved.

   The frame is 380x500 of real card scaled to 0.4, and the scale is on the
   iframe rather than on anything inside it, so the card is laid out at a
   phone's width and then photographed rather than being laid out small. That
   is the difference between a preview and a different design.

   500 rather than 470 since the four rebuilt themes: `frame`'s portrait is
   full bleed across the card now, so its Save contact sits lower than any
   other theme's and it is still the tallest of the seven to that mark.

   The box is a fixed 152 by 200 rather than a fraction of its column, so the
   scale is the constant 0.4 and every preview is the same crop of the same
   card at the same size. A box that sized itself to the grid would want a
   container query to keep the scale honest, and a preview whose scale depends
   on when a query resolved is a preview that is a different size in a
   screenshot than it is on the page.

   `card.css` still never loads on THIS page, which was the point of the
   comment that used to be here. It loads inside the frames, where its reset
   and its `body` rules have nothing to collide with, and one fetch serves all
   seven because all seven name the same URL. */
.shot {
  display: block;
  width: 152px;
  height: 200px;
  max-width: 100%;
  border-radius: 9px;
  overflow: hidden;
  background: var(--light);
  position: relative;
  /* The frame is a picture of a control, not a control. */
  pointer-events: none;
}
.shot .mini {
  position: absolute;
  top: 0;
  left: 0;
  width: 380px;
  height: 500px;
  border: 0;
  transform-origin: 0 0;
  transform: scale(.4);          /* 380 -> 152, 500 -> 200 */
}

.switch {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  border: 1px solid var(--hair);
  border-radius: 12px;
  padding: 14px 16px;
  margin-top: 10px;
  font-size: 15px;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.switch:hover { background: var(--light); }
.switch input { margin-top: 3px; accent-color: var(--blue); flex: none; }
.switch strong { display: block; font-size: 15px; font-weight: 600; }
.switch span {
  display: block;
  font-size: 13px;
  color: var(--muted-light);
  margin-top: 2px;
}
.switch:has(input:checked) { border-color: var(--blue); background: rgba(0, 113, 227, .04); }

/* ------------------------------------------------------- the account spine
   The index under the masthead. Three destinations, the same three the app
   bar carries, and it sticks under the bar so that position stays on the
   screen while the sections move past it.

   The pill grammar is the install page's client chooser, unchanged: a
   hairline capsule that takes the blue when it is the one you are in. Two
   objects on this service look like tabs and they now look like each other,
   which is a thing that used to be true of neither. */
.spine {
  position: sticky;
  top: 52px;
  z-index: 15;
  background: var(--light);
  border-bottom: 1px solid var(--hair);
  padding: 12px 0;
}
.spine-inner { display: flex; gap: 8px; }
.spine a {
  padding: 7px 15px;
  border: 1px solid var(--hair);
  border-radius: 980px;
  background: var(--white);
  font-size: 14px;
  line-height: 1.2;
  color: var(--muted-light);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.spine a:hover { background: var(--light); }
/* The current tab. Blue border and blue wash carry the mark; the LABEL is
   `--ink`, because #0071e3 on that wash measures 4.45:1 at 14px and the bar
   for normal text is 4.5. The colour was doing the marking either way. */
.spine a[aria-current] {
  border-color: var(--blue);
  background: rgba(0, 113, 227, .06);
  color: var(--ink);
  font-weight: 600;
}
/* An anchor landing under two sticky bars is an anchor that lands on the
   wrong thing. 52 of bar, 55 of index, and a little air. */
.spine-part { scroll-margin-top: 118px; }

/* The portrait well in "Who you are". Square with the card's radius rather
   than a circle, because four of the seven themes do not draw a circle and
   this is a picture of what they will draw rather than an avatar. */
.portrait { display: flex; align-items: flex-start; gap: 16px; }
.portrait-shot {
  flex: none;
  width: 72px;
  height: 72px;
  border-radius: 12px;
  border: 1px solid var(--hair);
  object-fit: cover;
  background: var(--light);
}
.portrait-mono {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--accent, var(--muted-light));
}
.portrait-say { min-width: 0; flex: 1 1 auto; }
.portrait-say label { display: block; font-size: 14px; font-weight: 600; margin-bottom: 7px; }

/* One link on the rail, being edited. The glyph is the label's own mark, at
   the size the panel draws it, so the row says which icon it is about to
   change rather than only naming a service. */
.addline label { display: flex; align-items: center; gap: 8px; }
.addglyph {
  display: inline-flex;
  width: 16px;
  height: 16px;
  color: var(--muted-light);
}
.addglyph svg { width: 16px; height: 16px; display: block; }

/* "+ Add a link", closed, holding everything still on offer. The list is
   never empty and the affordance is never replaced by the rows it makes,
   which is the same rule the builder's own chooser follows. */
.addmore { margin-top: 18px; }
.addmore > summary {
  display: inline-block;
  font-size: 15px;
  list-style: none;
  cursor: pointer;
}
.addmore > summary::-webkit-details-marker { display: none; }
.addmore > summary:hover { text-decoration: underline; }
.addmore-body {
  margin-top: 16px;
  padding: 18px 18px 4px;
  border: 1px dashed var(--hair);
  border-radius: 12px;
}
.addmore-body .field:first-of-type { margin-top: 0; }

/* A save and what it says, on one line. The confirmation belongs beside the
   button that earned it: a banner at the top of a section is a thing a
   customer scrolls back up to read. */
.said-row { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px; }
.said {
  margin: 0;
  font-size: 15px;
  line-height: 1.4;
  color: var(--good);
  min-height: 22px;
}
.said-row .copied { margin: 0; }

/* One bought signature inside its section, and the rule between two. */
.owned-next { margin-top: 34px; border-top: 1px solid var(--hair); padding-top: 30px; }
.billing-row {
  margin-top: 22px;
  display: flex;
  flex-wrap: wrap;
  gap: 12px 16px;
  align-items: center;
}

/* The install page's handoff: the card that came with the signature, its
   address and the one button that opens it. Stacked on a phone and side by
   side once there is room for the preview to sit beside its own sentence. */
.handoff { display: flex; flex-wrap: wrap; gap: 22px 26px; align-items: flex-start; }
.handoff .shot { flex: none; }
.handoff-say { flex: 1 1 260px; min-width: 0; }

/* The address, and the two files somebody prints it as. */
.address {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 14px;
  margin-top: 4px;
  font-size: 15px;
}
.address code { overflow-wrap: anywhere; }
.address a, .address button { font-size: 14px; }
.address .copied { margin: 0; min-height: 0; font-size: 14px; }

/* ------------------------------------------------------- breakpoints */
@media (max-width: 359px) { :root { --zoom-card: .5; } }
@media (min-width: 480px) { :root { --zoom-card: .82; } }
@media (min-width: 700px) {
  :root { --pad: 24px; --zoom-card: 1; }
  .sheet { padding: 40px 40px 38px; }
  .row2 { grid-template-columns: 1fr 1fr; gap: 20px; }
  .dark { padding: 76px 0 84px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; }
  .bar i { animation: none; transform: none; width: 100%; opacity: .55; }
}

/* Four layouts in one row: the same frame the theme picker draws, at 120
   rather than 150, because there are four of them and they are page-shaped
   rather than card-shaped so a row of four reads as a shelf of pages.

   Written against `.app-main .themes` as well as `.themes`, because the app
   shell's own sheet narrows the picker to `auto-fill` at 150 and loads after
   this one; one extra class is what carries the modifier past it. */
.app-main .themes.themes-four { grid-template-columns: repeat(4, 120px); }
.app-main .themes.themes-four .shot { width: 120px; height: 158px; }
.app-main .themes.themes-four .shot .mini { transform: scale(.3158); }
