/* Shorepass — the design system for the whole site.
 *
 * Nothing is fetched from anywhere. No framework, no webfont, no analytics: a
 * seafarer reads this on a ship's wifi or a prepaid phone, and the page is a
 * few kilobytes because that is a courtesy, not a constraint we resent.
 *
 * The look is meant to read as a REVIEW INSTITUTION rather than a software
 * product. That is a positioning decision and it drives every choice below:
 *
 *   - A serif for display type. Institutions set their names in serif; SaaS
 *     sets everything in one geometric sans. The serif is a system stack, so
 *     it costs nothing to load and still reads as considered.
 *   - Warm paper (#FBF9F6) rather than #FFF. Pure white is the commonest tell
 *     of a cheap page; a warm ground makes ink look printed.
 *   - Brass, not yellow. #C29A4C is instrument brass. #FBBF24 is a warning
 *     label, and the old palette used it for everything.
 *   - Restraint as the luxury signal: one accent, one focal point per screen,
 *     every decorative opacity dialled down until it is barely sensed.
 *
 * 60-30-10: paper and ink carry ~60%, the deep navy bands ~30%, brass ~10%
 * and only on what a reader is meant to act on or notice first.
 */

:root {
  /* Both themes are hand-made, so the browser must not
   * invent one: declaring dark support turns Android's auto-dark off. */
  color-scheme: light dark;

  /* Ground */
  --paper:     #fbf9f6;   /* warm, so ink reads as printed rather than lit */
  --paper-2:   #f4f0ea;   /* the quieter alternating band */
  --card:      #ffffff;   /* a lifted surface: cards, the sheet, inputs */
  --deep:      #0a1826;   /* the navy the dark sections sit on */
  --deep-2:    #102337;   /* one step up, for depth inside the dark */

  /* Ink */
  --ink:       #14212e;
  --ink-soft:  #4a5a6a;
  --ink-faint: #5c6b7a;   /* was #7d8b99: 3.3:1 on paper, below AA */
  --on-deep:      #f2efe9;
  --on-deep-soft: rgba(242, 239, 233, .72);
  --on-deep-faint:rgba(242, 239, 233, .46);

  /* Accent — used sparingly and never twice in one eyeline */
  --brass:     #c29a4c;
  /* The same accent, dark enough to be READ. Brass at #c29a4c is
   * 2.5:1 on paper: fine as a fill, illegible as a 10px label.
   * Tuned against the DARKER paper-2 band, not paper - a label that
   * only passes on the lighter of the two grounds passes nowhere. */
  --brass-text: #856325;
  --brass-lit: #e0bd76;
  --teal:      #12626e;   /* the second colour, for data and links only */
  --ok:        #1c6b39;
  --warn:      #9a2727;

  /* Structure */
  --line:      #e3dcd2;   /* hairline on paper */
  --line-deep: rgba(242, 239, 233, .13);
  --radius:    4px;       /* small. Big radii read as consumer app */
  --radius-lg: 8px;

  --lift: 0 1px 2px rgba(20, 33, 46, .04),
          0 18px 40px -28px rgba(20, 33, 46, .28);
  --lift-hi: 0 1px 2px rgba(20, 33, 46, .05),
             0 30px 60px -34px rgba(20, 33, 46, .38);

  /* Type. Two families, both already on the reader's machine. */
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
           Georgia, "Times New Roman", serif;
  --sans:  system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono:  ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* Spacing: an 8px base, so nothing lands on an arbitrary number */
  --section: clamp(76px, 9vw, 132px);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  color: var(--ink);
  background: var(--paper);
  font: 400 17px/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--teal); text-underline-offset: 3px; }
a:hover { color: var(--ink); }

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 28px; }

/* --- type ---------------------------------------------------------------- */

h1, h2, h3 { font-family: var(--serif); font-weight: 400; }

h1 {
  font-size: clamp(40px, 6.6vw, 72px);
  line-height: 1.02;
  letter-spacing: -.022em;
  margin: 0 0 22px;
}

h2 {
  font-size: clamp(28px, 3.9vw, 42px);
  line-height: 1.12;
  letter-spacing: -.016em;
  margin: 0 0 18px;
}

h3 {
  font-family: var(--sans);
  font-size: 17px;
  font-weight: 650;
  letter-spacing: -.006em;
  line-height: 1.35;
  margin: 0 0 8px;
}

p { margin: 0 0 16px; }

/* The eyebrow. Small caps, widely tracked - the cheapest way to make a page
 * look edited rather than typed. */
.eyebrow {
  font: 600 11px/1 var(--sans);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--brass-text);
  margin: 0 0 20px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.eyebrow::after {
  content: "";
  height: 1px;
  flex: 1;
  max-width: 68px;
  background: currentColor;
  opacity: .32;
}

.lede {
  font-size: clamp(18px, 2.1vw, 20px);
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 64ch;
}

.small { font-size: 14.5px; color: var(--ink-faint); }
.mono { font-family: var(--mono); }

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

.bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 26px 0;
}
.bar img { width: 30px; height: 30px; display: block; }
.bar strong {
  font-family: var(--serif);
  font-size: 21px;
  font-weight: 400;
  letter-spacing: .01em;
}
.bar nav {
  margin-left: auto;
  display: flex;
  gap: 30px;
  font-size: 14.5px;
}
/* 44px of height for a thumb, taken as padding so nothing on the bar moves.
 * These were 22px tall - readable, but a poor target on a phone held on a
 * moving ship, which is where this gets read. */
.bar nav a {
  color: inherit; text-decoration: none; opacity: .74;
  display: inline-flex; align-items: center; min-height: 44px;
}
.bar nav a:hover { opacity: 1; }

/* The wordmark, when it is a link home - which it is on every page but the
 * home page. Handled here rather than by inline styles on each page, which is
 * how it came to wrap onto two lines and underline itself. */
.bar > a {
  display: flex;
  align-items: center;
  min-height: 44px;
  gap: 12px;
  text-decoration: none;
  color: inherit;
  white-space: nowrap;
}

/* --- the dark ground ----------------------------------------------------- */

header, .band {
  position: relative;
  overflow: hidden;
  background: var(--deep);
  color: var(--on-deep);
}
/* Two quiet light sources, so the dark reads as a room rather than a
 * rectangle of paint. Both far below the threshold of being noticed. */
header::after, .band::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(90ch 62ch at 12% -18%, rgba(194, 154, 76, .13), transparent 62%),
    radial-gradient(70ch 50ch at 96% 8%, rgba(18, 98, 110, .20), transparent 60%);
}
/* Grain. One texture site-wide - one strategy, not six - kept faint enough to
 * be felt as "printed" rather than seen as an effect. */
header::before, .band::before, footer::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.06'/%3E%3C/svg%3E");
}
header > *, .band > *, footer > * { position: relative; z-index: 2; }
header .bar strong, header .bar nav a, header a { color: var(--on-deep); }

.hero { padding: clamp(44px, 6vw, 76px) 0 clamp(76px, 9vw, 120px); }
/* An inner page's title. Smaller than the landing headline because it labels a
 * task rather than making an argument, and the hero closes up to match. */
h1.page { font-size: clamp(32px, 4.6vw, 46px); }
.hero:has(h1.page) { padding-bottom: clamp(48px, 6vw, 76px); }
.hero h1 { max-width: 17ch; }
.hero .lede { color: var(--on-deep-soft); max-width: 54ch; font-size: clamp(18px, 2.2vw, 21px); }
/* Not --on-deep-faint. This paragraph says what the product IS, and at 46%
 * it was a grey block a reader skips. Faint enough to sit below the lede in
 * the hierarchy, dark enough to actually be read. */
.hero .sub { color: rgba(242, 239, 233, .62); font-size: 16.5px; max-width: 54ch; }

.cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 36px; }

/* Which phones this runs on, said in the hero rather than discovered after
 * paying. Quiet, because it is a fact rather than an argument - but present,
 * because a man with an iPhone deserves to learn it in the first screenful. */
/* The gift, said in the hero. Given before anything is asked for, which is
 * the whole reason it earns the right to ask later. */
.gift {
  margin: 20px 0 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--on-deep-soft);
  max-width: 48ch;
  padding-left: 14px;
  border-left: 2px solid var(--brass);
}

.platform {
  margin: 22px 0 0;
  font-size: 14.5px;
  color: var(--on-deep-soft);
  max-width: 52ch;
}
.platform span { color: var(--on-deep-faint); }
.platform a { color: var(--on-deep-soft); }

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 14px 26px;
  border: 0;
  border-radius: var(--radius);
  font: 600 15px/1 var(--sans);
  letter-spacing: .01em;
  text-decoration: none;
  cursor: pointer;
  transition: transform .16s ease, box-shadow .16s ease, background .16s ease;
}
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--brass);
  color: #21160a;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .34) inset,
              0 12px 26px -14px rgba(194, 154, 76, .8);
}
.btn-primary:hover { background: var(--brass-lit); color: #21160a; }

.btn-ghost {
  background: transparent;
  color: inherit;
  box-shadow: inset 0 0 0 1px currentColor;
  opacity: .8;
}
.btn-ghost:hover { opacity: 1; }

.btn[disabled] { opacity: .45; cursor: default; }

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

section { padding: var(--section) 0; }
section.alt { background: var(--paper-2); }

.head { max-width: 68ch; margin-bottom: clamp(40px, 5vw, 64px); }
.band .lede { color: var(--on-deep-soft); }
.band h2 { color: var(--on-deep); }

/* --- cards --------------------------------------------------------------- */

.grid {
  display: grid;
  /* min() so a fixed track minimum can still collapse on a narrow phone;
   * without it the column stays wider than the screen and the PAGE scrolls
   * sideways - the commonest way a site reads as broken on a 360. */
  grid-template-columns: repeat(auto-fit, minmax(min(268px, 100%), 1fr));
  gap: 20px;
}
.grid.two { grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr)); }

.card {
  position: relative;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 30px 28px;
  box-shadow: var(--lift);
}
/* The 1px catch-light along the top edge. Almost invisible, and the reason a
 * card reads as lifted rather than drawn. */
.card::before {
  content: "";
  position: absolute;
  top: 0; left: 12px; right: 12px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .9), transparent);
}
.card p { color: var(--ink-soft); font-size: 15.5px; margin: 0; }
.card p + p { margin-top: 12px; }

.card .term {
  display: block;
  font-size: 12px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: -4px 0 12px;
}
.band .card .term { color: var(--on-deep-faint); }

.card .n {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--brass-text);
  display: block;
  margin-bottom: 14px;
  letter-spacing: .06em;
}

.band .card {
  background: var(--deep-2);
  border-color: var(--line-deep);
  box-shadow: none;
}
.band .card::before { background: linear-gradient(90deg, transparent, rgba(255,255,255,.10), transparent); }
.band .card p { color: var(--on-deep-soft); }
.band .card h3 { color: var(--on-deep); }

/* On a dark ground the darker text-brass is the opposite mistake, so the
 * bright accent comes back. The header and the best-value price card are the
 * two places these labels sit on navy. */
header .eyebrow, .band .eyebrow, .band .card .n, .price.best .tag {
  color: var(--brass-lit);
}

/* --- the term slider ------------------------------------------------------
 * The saving is given its own colour and weight because it is the one number
 * on the page that rewards moving the control. A discount a reader has to hunt
 * for is a discount that persuades nobody. */

.scale {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--ink-faint);
  margin: -4px 2px 14px;
}
.save {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ok);
  min-height: 22px;
  margin-top: 2px;
}
.free-note {
  background: var(--paper-2);
  border-left: 2px solid var(--brass);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 14px 16px;
  font-size: 15px;
  color: var(--ink-soft);
  margin-top: 4px;
}

/* --- the download sheet ----------------------------------------------------
 *
 * Five reviewers now, so "download" is a real question and not a gate: a man
 * sitting his Chief Mate's has no use for the GMDSS bank. Asking it is a
 * service, and a small yes before a larger one.
 *
 * The email step after it is a genuine trade-off and is treated as one. It is
 * ONE field, and it is skippable, because a required form costs most of the
 * downloads it is put in front of. See site.js for the rule that governs it:
 * the file starts downloading first, and nothing about the form can stop it.
 */

.modal[hidden] { display: none !important; }
.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(6, 14, 24, .62);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  animation: fade .2s ease;
}
@keyframes fade { from { opacity: 0 } to { opacity: 1 } }

/* THE SHEET IS A FRAME; THE BODY SCROLLS INSIDE IT.
 *
 * Two things need this split. A corner ribbon has to be clipped by the sheet's
 * rounded corner, which means the sheet must own `overflow: hidden` - and it
 * cannot also be the scroller. And the close button now stays where the reader
 * left it instead of scrolling away with the content, which on a phone (where
 * the content ALWAYS overflows - five reviewers do not fit a 360) is the
 * difference between a dialog you can leave and one you have to guess at.
 *
 * `dvh` matters more than it looks: on a mobile browser `vh` is the height
 * with the address bar hidden, so a sheet sized in `vh` is taller than the
 * screen the moment the bar is showing. `dvh` is the height actually
 * available, with a `vh` fallback for anything too old to know the unit. */
.sheet {
  position: relative;
  width: 100%;
  max-width: 560px;
  overflow: hidden;
  background: var(--paper);
  border-radius: 14px;
  box-shadow: 0 40px 90px -30px rgba(6, 14, 24, .7);
  animation: rise .26s cubic-bezier(.2, .7, .3, 1);
}
.sheet-body {
  max-height: calc(100vh - 40px);
  max-height: calc(100dvh - 40px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 34px 30px 30px;
  /* Room for the ribbon, so the step label sits beside it rather than under. */
  padding-top: 30px;
}

/* The scroll cue. Content that overflows with no sign of it reads as content
 * that ends - and the fifth reviewer is the one below the fold. A short fade
 * pinned to the FRAME (not the scroller, or it would slide) says there is
 * more. It sits behind nothing: pointer-events are off. */
.sheet::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 46px;
  pointer-events: none;
  background: linear-gradient(to top, var(--paper), transparent);
}

/* The promotional mark: one ribbon across the top-left corner. */
.corner-ribbon {
  position: absolute;
  top: 17px; left: -42px;
  z-index: 3;
  width: 150px;
  transform: rotate(-45deg);
  transform-origin: center;
  /* FIXED COLOURS, not theme tokens. `--ok` flips to a LIGHT green in dark
   * mode, which put white text on a light ground at 1.79 - the audit caught it
   * on the first run that opened the dialog. A promotional badge should look
   * the same in both themes anyway: it is a sticker on the sheet, not part of
   * the page's palette. */
  background: #196033;
  color: #fff;
  text-align: center;
  font: 700 11px/1 var(--sans);
  letter-spacing: .18em;
  text-transform: uppercase;
  padding: 6px 0;
  box-shadow: 0 6px 16px -8px rgba(6, 14, 24, .55);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The step label starts clear of the ribbon. */
.sheet .step { padding-left: 74px; }
@keyframes rise { from { opacity: 0; transform: translateY(14px) } to { opacity: 1; transform: none } }
.sheet h3 {
  font-family: var(--serif);
  font-size: clamp(22px, 3.6vw, 27px);
  font-weight: 400;
  letter-spacing: -.015em;
  line-height: 1.2;
  margin: 0 0 8px;
}
.sheet .lede { font-size: 15.5px; margin-bottom: 20px; }
.sheet .close {
  position: absolute;
  top: 12px; right: 12px;
  width: 38px; height: 38px;
  border: 0; border-radius: 50%;
  background: transparent;
  color: var(--ink-faint);
  font-size: 24px; line-height: 1;
  cursor: pointer;
}
.sheet .close:hover { background: var(--paper-2); color: var(--ink); }

/* One row per reviewer. A row, not a card, because five cards is a wall and a
 * list is read top to bottom in the order a candidate would think of them. */
.picks { display: grid; gap: 9px; }
.pick {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  text-align: left;
  padding: 15px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--card);
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}
.pick:hover { border-color: var(--brass); transform: translateY(-1px); box-shadow: var(--lift); }
.pick b { display: block; font-size: 15.5px; font-weight: 650; }
.pick span { display: block; font-size: 13.5px; color: var(--ink-faint); margin-top: 2px; }
.pick .count {
  margin-left: auto;
  text-align: right;
  font-size: 12.5px;
  color: var(--ink-faint);
  white-space: nowrap;
}
.pick .count b { font-family: var(--serif); font-size: 17px; color: var(--ink); font-weight: 400; }

.sheet .step {
  font: 600 11px/1 var(--sans);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--brass-text);
  margin: 0 0 14px;
}
.sheet .skip {
  display: block;
  text-align: center;
  margin-top: 14px;
  font-size: 14px;
  color: var(--ink-faint);
  background: none;
  border: 0;
  width: 100%;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.sheet .skip:hover { color: var(--ink); }
.sheet .chosen {
  display: flex; align-items: center; gap: 10px;
  background: var(--paper-2);
  border-radius: var(--radius);
  padding: 12px 14px;
  font-size: 14.5px;
  margin-bottom: 18px;
}
.sheet .chosen button {
  margin-left: auto; background: none; border: 0; cursor: pointer;
  color: var(--teal); font: inherit; font-size: 13.5px; text-decoration: underline;
}

/* --- the sticky bar --------------------------------------------------------
 *
 * Appears once the hero has scrolled away, and carries the one action that
 * matters. On a page this long the download button is otherwise a scroll away
 * from wherever a reader has got to, and a decision made at the bottom of the
 * method section should not need a journey to act on.
 *
 * Glass here and nowhere else. A frosted panel needs something behind it worth
 * blurring - over a flat fill it is just a lighter rectangle - and a bar
 * sliding over the page's own content is exactly the case it was invented for.
 * Backed by a solid colour first, so a browser without backdrop-filter gets a
 * readable bar rather than a transparent one.
 */

.sticky {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  background: rgba(10, 24, 38, .92);
  border-bottom: 1px solid rgba(242, 239, 233, .10);
  transform: translateY(-100%);
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
  will-change: transform;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .sticky {
    background: rgba(10, 24, 38, .72);
    -webkit-backdrop-filter: blur(14px) saturate(150%);
    backdrop-filter: blur(14px) saturate(150%);
  }
}
.sticky.up { transform: translateY(0); }
.sticky .wrap {
  display: flex;
  align-items: center;
  gap: 14px;
  /* Written in full rather than adjusting only the vertical, so the bar keeps
   * its side margins whatever the page's own .wrap padding does at any width.
   * A call-to-action flush against the edge of a phone screen looks broken and
   * is harder to hit. */
  padding: 11px 20px;
}
@media (min-width: 641px) { .sticky .wrap { padding: 11px 28px; } }
.sticky img { width: 26px; height: 26px; display: block; }
.sticky strong {
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 400;
  color: var(--on-deep);
}
.sticky .btn {
  margin-left: auto;
  padding: 10px 20px;
  font-size: 14px;
}

/* --- arriving ---------------------------------------------------------------
 *
 * Sections rise a little as they come into view. Small - 14px and a fade -
 * because the point is that the page feels considered, not that anything
 * performs. Anything not yet revealed stays fully visible if the script never
 * runs, so a reader with JavaScript off loses nothing at all.
 */
.reveal { opacity: 0; transform: translateY(14px); }
.reveal.in {
  opacity: 1;
  transform: none;
  transition: opacity .6s ease, transform .6s cubic-bezier(.2, .7, .3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.in { opacity: 1; transform: none; transition: none; }
}

/* --- focus ------------------------------------------------------------------
 * Visible, branded, and only for keyboard users - so it helps the people who
 * need it without putting a ring round every tap on a phone. */
:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
  border-radius: 3px;
}

/* --- pictures -------------------------------------------------------------
 *
 * Three images on the whole site, and each one earns its place by saying
 * something the text cannot: what the app looks like, and who this is for.
 * All three are WebP, cropped to what they need to show, and sized to what
 * they are actually displayed at - 89 KB for the lot, because a seafarer opens
 * this on ship wifi and a light page is the same courtesy as a light app.
 */

figure { margin: 0; }

.shot {
  /* A phone, drawn rather than photographed - a real device mockup is a large
   * image of a bezel, and the screenshot is the only part anybody looks at. */
  width: 100%;
  max-width: 300px;
  border-radius: 26px;
  padding: 8px;
  background: #10202f;
  box-shadow: 0 2px 4px rgba(20, 33, 46, .10),
              0 40px 70px -34px rgba(20, 33, 46, .45);
  margin: 0 auto;
}
.shot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 19px;
}
.band .shot { background: #061220; box-shadow: 0 30px 60px -30px rgba(0, 0, 0, .6); }

/* Text one side, phone the other. Stacks on a phone, where the screenshot goes
 * FIRST - somebody on a small screen wants to see the thing before reading
 * about it. */
.showcase {
  display: grid;
  grid-template-columns: 1fr;
  gap: 34px;
  align-items: center;
  margin-bottom: clamp(40px, 5vw, 60px);
}
@media (min-width: 860px) {
  .showcase { grid-template-columns: 1.15fr .85fr; gap: 56px; }
  .showcase .words { order: 1; }
  .showcase figure { order: 2; }
}
.showcase .head { margin-bottom: 0; }

figcaption {
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-faint);
  text-align: center;
  margin-top: 16px;
  max-width: 34ch;
  margin-left: auto;
  margin-right: auto;
}
.band figcaption { color: var(--on-deep-faint); }

/* The photograph. Full width of the column, and deliberately wide and short so
 * it reads as a band of relief between two blocks of reading rather than as a
 * picture demanding attention of its own. */
.photo {
  margin: 0 0 clamp(40px, 5vw, 58px);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--lift);
}
.photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 8;
  object-fit: cover;
  object-position: center 42%;
}

/* --- the numbers band ---------------------------------------------------- */

.stat {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
  gap: 1px;
  border: 1px solid;
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.stat > div {
  background: var(--card);
  padding: 34px 26px;
  text-align: center;
}
.stat b {
  display: block;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(34px, 4.6vw, 50px);
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--brass-text);
  margin-bottom: 12px;
}
.stat span {
  display: block;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-soft);
  max-width: 24ch;
  margin: 0 auto;
}

/* THE SAME BLOCK ON THE DARK BAND.
 *
 * This was originally written the other way round - the dark treatment as the
 * base rule - because the landing page's band was the only place it appeared.
 * That made it a trap: the desk reused `.stat` on the light body and the
 * headline figure came out at 1.69 against white, which is the shop's takings
 * rendered all but invisible. Same shape of bug as `.skim`, and the same fix:
 * a component owns its ink, and the DARK case is the override, because the
 * dark case is the one with a wrapper (`.band`) to hang it on. */
.stat { border-color: var(--line); background: var(--line); }
.band .stat { background: var(--line-deep); border-color: var(--line-deep); }
.band .stat > div {
  /* Translucent rather than solid, so the band's own light shows through the
   * grid and the four figures read as one piece of glass rather than four
   * painted boxes. */
  background: rgba(255, 255, 255, .035);
}
@supports (backdrop-filter: blur(1px)) {
  .band .stat > div { -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
}
.band .stat b { color: var(--brass-lit); }
.band .stat span { color: var(--on-deep-soft); }

/* --- pricing ------------------------------------------------------------- */

.prices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 22px;
  align-items: start;
}
.price {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 34px 32px;
  box-shadow: var(--lift);
}
.price.best {
  background: var(--deep);
  border-color: transparent;
  color: var(--on-deep);
  box-shadow: var(--lift-hi);
}
.price .tag {
  font: 600 11px/1 var(--sans);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--brass-text);
  margin-bottom: 22px;
}
.price .amount {
  font-family: var(--serif);
  font-size: clamp(38px, 5vw, 50px);
  line-height: 1;
  letter-spacing: -.025em;
  margin-bottom: 26px;
}
.price .amount small {
  display: block;
  font-family: var(--sans);
  font-size: 14px;
  letter-spacing: 0;
  color: var(--ink-faint);
  margin-top: 10px;
}
.price.best .amount small { color: var(--on-deep-faint); }
.price ul { list-style: none; margin: 0 0 28px; padding: 0; }
.price li {
  position: relative;
  padding: 0 0 12px 24px;
  font-size: 15.5px;
  color: var(--ink-soft);
}
.price.best li { color: var(--on-deep-soft); }
.price li::before {
  content: "";
  position: absolute;
  left: 2px; top: 9px;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--brass);
  opacity: .55;
}
.price .btn { width: 100%; }

/* --- the price the slider draws ------------------------------------------
 *
 * In the system rather than inline on the element, so it moves with the type
 * scale instead of drifting away from it. The total is the one number on that
 * page a buyer is deciding on, so it gets the serif and the size. */

.quote { display: flex; justify-content: space-between; align-items: baseline; margin-top: 8px; }
.quote .term { font-weight: 600; font-size: 18px; }
.quote .total {
  font-family: var(--serif);
  font-size: 30px;
  line-height: 1;
  letter-spacing: -.02em;
}

/* --- notes, forms, small parts ------------------------------------------- */

.note {
  border-left: 2px solid var(--brass);
  background: var(--paper-2);
  padding: 18px 22px;
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 15.5px;
  color: var(--ink-soft);
}
.band .note { background: var(--deep-2); color: var(--on-deep-soft); }

.hint { font-size: 14px; color: var(--ink-faint); margin-top: 8px; }
.good { color: var(--ok); }
.bad { color: var(--warn); }
.warn { background: #fdeceb; color: var(--warn); padding: 12px 16px; border-radius: var(--radius); }

label {
  display: block;
  font: 600 12px/1 var(--sans);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 22px 0 9px;
}
input, select, textarea {
  width: 100%;
  padding: 13px 15px;
  font: 400 16px/1.4 var(--sans);
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brass);
  box-shadow: 0 0 0 3px rgba(194, 154, 76, .16);
}
/* A checkbox is not the target - its LABEL is, and the label is a full-width
 * row. Still nudged up from the UA's 13px so it can be hit directly. */
input[type=checkbox] { width: auto; min-width: 20px; min-height: 20px; }

.code {
  font-family: var(--mono);
  font-size: 13.5px;
  line-height: 1.6;
  word-break: break-all;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
}

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

footer {
  background: var(--deep);
  color: var(--on-deep-faint);
  padding: 64px 0 72px;
  font-size: 14px;
  position: relative;
  overflow: hidden;
}
footer .wrap > div { margin-bottom: 12px; max-width: 76ch; }
footer strong { color: var(--on-deep); font-weight: 600; font-family: var(--serif); }
footer a { color: var(--on-deep-soft); }

/* --- the shared page furniture the other pages use ----------------------- */

.doc { max-width: 780px; margin: 0 auto; padding: 8px 28px 96px; }
.doc h2 { margin-top: 46px; font-size: clamp(24px, 3vw, 32px); }
.doc h3 { margin-top: 28px; font-size: 17px; }
.doc p, .doc li { color: var(--ink-soft); }
.doc table { width: 100%; border-collapse: collapse; margin: 18px 0; font-size: 15px; }
.doc th, .doc td {
  text-align: left; padding: 12px 12px; border-bottom: 1px solid var(--line);
  vertical-align: top; color: var(--ink-soft);
}
.doc th {
  color: var(--ink); font: 600 11px/1.2 var(--sans);
  letter-spacing: .14em; text-transform: uppercase;
}
.doc .note { margin: 22px 0; }
.hero.doc-hero { padding-bottom: 40px; }

/* 360dp is the commonest Android width in this market, and at that size four
 * nav items wrapped onto two lines and broke the header. Below 460 the nav
 * keeps only the two ACTIONS - reading links are a scroll away, buying is
 * not - and the wordmark stops competing for the room. */
@media (max-width: 460px) {
  .bar nav a.hide-xs { display: none; }
  .bar nav { gap: 16px; }
  .bar strong { font-size: 19px; }
  .bar { gap: 10px; }
  .eyebrow { letter-spacing: .14em; font-size: 10.5px; }
  .sticky strong { display: none; }     /* the mark alone is enough up there */
}

@media (max-width: 640px) {
  .wrap { padding: 0 20px; }
  .card { padding: 26px 22px; }
  .price { padding: 28px 24px; }
  .bar nav { gap: 18px; font-size: 13.5px; }
  .bar nav a.hide-sm { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; scroll-behavior: auto !important; }
}

/* ===========================================================================
   THE PAGE PRACTISES WHAT IT SELLS
   ===========================================================================
 *
 * This site argues that six things make a fact stick. It would be a poor
 * advertisement for that argument if the page itself were a wall of prose
 * nobody finishes - so the same six shape how it is set.
 *
 *   Cue and key      -> .key marks the few words that decide a sentence, so a
 *                       reader who reads ONLY the marked words still leaves
 *                       with the argument.
 *   Distinctiveness  -> one odd, memorable detail per section: a numeral, an
 *                       icon, a single figure set large. Uniform pages are
 *                       forgettable pages.
 *   Discrimination   -> .vs puts the look-alikes side by side, because that is
 *                       the only arrangement in which anyone notices a
 *                       difference.
 *   Retrieval        -> section heads ask before they tell.
 *   Fluency          -> short lines. One idea each.
 *
 * THE RULE THAT KEEPS .key HONEST, and it is the same rule the app follows:
 * mark three to six words, never a whole line. The page says as much itself -
 * "a whole line painted yellow gives it none" - and a site that highlighted
 * every second sentence would be disproving its own claim in public.
 */

.key {
  background: linear-gradient(180deg, transparent 58%, rgba(194, 154, 76, .30) 58%);
  color: inherit;
  font-weight: 640;
  padding: 0 .06em;
  border-radius: 1px;
}
.band .key, .price.best .key {
  background: linear-gradient(180deg, transparent 58%, rgba(224, 189, 118, .34) 58%);
  color: var(--on-deep);
}

/* The second weight: the phrase a reader must not miss even while skimming
 * past everything else. Once or twice a section at most. */
.key-hi {
  background: rgba(194, 154, 76, .20);
  box-shadow: inset 0 0 0 1px rgba(194, 154, 76, .38);
  border-radius: 3px;
  padding: .08em .3em;
  font-weight: 660;
}
.band .key-hi, .price.best .key-hi {
  background: rgba(224, 189, 118, .18);
  box-shadow: inset 0 0 0 1px rgba(224, 189, 118, .34);
  color: var(--on-deep);
}

/* --- icons -----------------------------------------------------------------
 * Drawn inline, from one sprite at the top of the document. No icon font and
 * no request: the same reasoning that keeps a webfont off this site. */
.ico {
  width: 20px; height: 20px; flex: none;
  stroke: currentColor; fill: none;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.ico-box {
  display: grid; place-items: center;
  width: 42px; height: 42px;
  border-radius: var(--radius);
  background: rgba(194, 154, 76, .11);
  color: var(--brass);
  margin-bottom: 16px;
}
.ico-box .ico { width: 22px; height: 22px; }
.band .ico-box { background: rgba(224, 189, 118, .13); color: var(--brass-lit); }

/* --- the twenty-second version --------------------------------------------
 * Most readers never reach the bottom of a long page, and pretending
 * otherwise loses them. This is the whole argument in four lines, put where
 * they are still reading. Anyone who leaves here leaves knowing what this is. */
.skim {
  display: grid;
  /* OWNS ITS INK, and this is not decoration. This panel is a light card that
   * sits inside the DARK header, which sets a near-white text colour for its
   * own contents - so without this the headlines inherited white-on-white and
   * the whole summary was invisible. A surface that sets its own background
   * must set its own colour in the same breath. */
  color: var(--ink);
  gap: 0;
  margin: 34px 0 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--card);
  box-shadow: var(--lift);
  overflow: hidden;
}
.skim .row { display: flex; gap: 14px; align-items: flex-start; padding: 16px 20px; }
.skim .row + .row { border-top: 1px solid var(--line); }
.skim .row > .ico { color: var(--brass); margin-top: 2px; }
.skim b { font-weight: 650; }
.skim p { margin: 3px 0 0; font-size: 14.5px; color: var(--ink-soft); }
.skim .cap {
  padding: 12px 20px;
  background: var(--paper-2);
  border-top: 1px solid var(--line);
  font: 600 11px/1.4 var(--sans);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.band .skim { color: var(--on-deep); background: var(--deep-2); border-color: var(--line-deep); box-shadow: none; }
.band .skim .row + .row { border-color: var(--line-deep); }
.band .skim p { color: var(--on-deep-soft); }
.band .skim .cap { background: rgba(0,0,0,.18); border-color: var(--line-deep); color: var(--on-deep-faint); }

/* --- look-alikes, side by side --------------------------------------------
 * Discrimination training, applied to the page itself. */
.vs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 18px;
  margin-top: 30px;
}
.vs > div {
  border-radius: var(--radius-lg);
  padding: 24px 24px 26px;
  border: 1px solid var(--line);
  background: var(--card);
}
.vs .no { background: var(--paper-2); }
.vs .yes { border-color: rgba(194, 154, 76, .45); box-shadow: var(--lift); }
.vs h4 {
  display: flex; align-items: center; gap: 9px;
  font: 600 12px/1 var(--sans);
  letter-spacing: .14em; text-transform: uppercase;
  margin: 0 0 14px;
}
.vs .no h4  { color: var(--ink-faint); }
.vs .yes h4 { color: var(--brass-text); }
.vs ul { margin: 0; padding: 0; list-style: none; }
.vs li { font-size: 15px; color: var(--ink-soft); padding: 7px 0 7px 22px; position: relative; }
.vs li::before {
  content: "";
  position: absolute; left: 0; top: 15px;
  width: 10px; height: 1px; background: var(--line);
}
.vs .yes li::before { background: var(--brass); }

/* --- a line worth stopping on ---------------------------------------------
 * One per page at most. Distinctiveness only works while it is rare. */
.pull {
  font-family: var(--serif);
  font-size: clamp(21px, 3.1vw, 29px);
  line-height: 1.34;
  margin: 34px 0 0;
  padding: 4px 0 4px 22px;
  border-left: 2px solid var(--brass);
  color: var(--ink);
}
.band .pull { color: var(--on-deep); border-color: var(--brass-lit); }

/* --- FREE, said where the hesitation happens ------------------------------
 * A reader deciding whether to tap a download is asking one question, and it
 * is not which reviewer. It is what this will cost. Answer it on the button
 * itself and the question never gets the chance to stop them. */
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  font: 700 10.5px/1 var(--sans);
  letter-spacing: .13em; text-transform: uppercase;
  padding: 5px 8px;
  border-radius: 3px;
  white-space: nowrap;
}
.pill-free { background: rgba(28, 107, 57, .12); color: var(--ok); }
.pill-brass { background: rgba(194, 154, 76, .16); color: #8a6a26; }
.band .pill-free { background: rgba(255,255,255,.13); color: #9ad9b0; }
/* The pills that used to sit here took the row's width and pushed the
 * question count out of the layout at 360. One ribbon on the sheet says
 * the same thing once. */

/* --- the flag on the twelve-month stop ------------------------------------
 * Its wording lives in ONE place in the markup so that, when there are real
 * numbers behind it, it is a one-line change and not an archaeology
 * exercise. Until then it says only what arithmetic supports. */
.ribbon {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--deep);
  color: var(--brass-lit);
  font: 700 10.5px/1 var(--sans);
  letter-spacing: .15em; text-transform: uppercase;
  padding: 7px 11px;
  border-radius: 3px;
}
.ribbon .ico { width: 14px; height: 14px; stroke-width: 2; }
.ribbon-line {
  margin: 10px 0 0;
  font-size: 14.5px;
  color: var(--ink-soft);
}

/* --- the small reassurances, next to the button that needs them ----------- */
.trust { display: grid; gap: 10px; margin-top: 18px; }
.trust div { display: flex; gap: 10px; align-items: flex-start; font-size: 14.5px; color: var(--ink-soft); }
.trust .ico { color: var(--ok); margin-top: 1px; width: 17px; height: 17px; }

/* --- what the payment actually buys --------------------------------------- */
.getlist { list-style: none; margin: 16px 0 0; padding: 0; }
.getlist li { position: relative; padding: 6px 0 6px 26px; font-size: 15px; color: var(--ink-soft); }
.getlist li .ico { position: absolute; left: 0; top: 8px; width: 16px; height: 16px; color: var(--brass); }

/* --- "you just did it" ----------------------------------------------------
 * Claiming a method works, and then showing a reader they have just used it,
 * is worth more than another paragraph claiming it. */
.selfnote {
  margin-top: 34px;
  border: 1px solid rgba(194, 154, 76, .42);
  background: linear-gradient(180deg, rgba(194,154,76,.07), rgba(194,154,76,.02));
  border-radius: var(--radius-lg);
  padding: 26px 28px;
}
.selfnote h3 { margin: 0 0 10px; }
.selfnote p { margin: 0; color: var(--ink-soft); font-size: 15.5px; }
.selfnote p + p { margin-top: 10px; }

/* --- the resume line on the enrolment page --------------------------------
 * Shown only to somebody who started a payment in this tab and came back
 * without one. It offers; it never takes over the page. */
.resume {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  border: 1px solid rgba(194, 154, 76, .45);
  background: rgba(194, 154, 76, .07);
  border-radius: var(--radius-lg);
  padding: 14px 18px;
  margin-bottom: 22px;
  font-size: 15px;
}
.resume .ico { color: var(--brass); }
.resume button {
  margin-left: auto;
  font: 600 14px var(--sans);
  background: none; border: 0; padding: 0;
  color: var(--teal); cursor: pointer; text-decoration: underline;
}

@media (max-width: 620px) {
  .skim .row { padding: 14px 16px; }
  .vs > div { padding: 20px; }
  .selfnote { padding: 22px 20px; }
}

/* ===========================================================================
   DARK MODE
   ===========================================================================
 *
 * WHY THIS EXISTS AT ALL, given the design is deliberately warm paper. Two
 * reasons, and the second is the one that forced it:
 *
 * 1. This audience reads on cheap Android phones, and a great many of them run
 *    the system dark theme for battery.
 *
 * 2. Chrome on Android will FORCE-DARKEN a page that does not say what it is.
 *    Auto-dark inverts colours by machine, and it does it badly here: the
 *    `.key` highlight is a gradient, gradients invert unpredictably, and the
 *    navy `.band` sections and the deep price card would have been dragged to
 *    near-black against a near-black ground - losing the one panel the page
 *    uses to separate its sections. Declaring `color-scheme: light dark` and
 *    shipping a real palette turns auto-dark OFF, because the page has said it
 *    handles dark itself. A hand-made theme is better than a guessed one.
 *
 * THE ONE STRUCTURAL DECISION. In light, the navy bands are DARKER than the
 * paper - that is what makes them read as inset panels. Invert the page and
 * that relationship collapses, so in dark the band grounds are a step LIGHTER
 * than the page. The bands stay panels; only the direction of the contrast
 * flips. Everything else is a token swap, which is the whole reason the light
 * theme was written with tokens.
 *
 * Only tokens are redefined below - no layout, no new rules - so the two
 * themes cannot drift apart structurally. Verified with Playwright at seven
 * widths in both schemes: no horizontal overflow, and every text/background
 * pair at WCAG AA or better.
 */

@media (prefers-color-scheme: dark) {
  :root {
    /* Ground. Navy-black rather than grey, so it belongs to the same family
     * as the brand's deep navy instead of reading as a generic dark theme. */
    --paper:     #0b1420;
    --paper-2:   #111d2b;   /* the quieter alternating band */
    --card:      #14202e;   /* what was white; a lifted surface */

    /* The bands invert their relationship to the page - see above. */
    --deep:      #1b2a3c;
    --deep-2:    #223347;

    /* Ink. Warm off-white, never pure white: the same reasoning that keeps the
     * light theme off pure white, in the other direction. */
    --ink:       #e8e4dc;
    --ink-soft:  #b3bcc6;
    --ink-faint: #8b97a4;

    /* Brass has to lift off a dark ground, so the lit variant leads. */
    --brass:     #d8b46a;
    --brass-lit: #eccd8c;
    /* The label brass has to invert with everything else. */
    --brass-text: #d8b46a;
    --teal:      #4fc3cf;   /* the light-theme teal fails AA on this ground */
    --ok:        #6ed69a;
    --warn:      #ff8a8a;

    --line:      #26364a;
    --line-deep: rgba(232, 228, 220, .14);

    /* Shadows do almost nothing on a dark ground; a hairline does the lifting,
     * so the shadow is kept only as a soft depth cue. */
    --lift:    0 1px 2px rgba(0, 0, 0, .30), 0 18px 40px -28px rgba(0, 0, 0, .60);
    --lift-hi: 0 1px 2px rgba(0, 0, 0, .34), 0 30px 60px -34px rgba(0, 0, 0, .70);
  }

  /* The catch-light along a card's top edge is a white sheen. On a dark
   * surface it reads as a scratch, so it is dimmed to a hint. */
  .card::before,
  .band .card::before {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .07), transparent);
  }

  /* The marked words. The light-theme wash is tuned for dark ink on paper; on
   * a dark ground it needs the brighter mix the navy bands already use, or the
   * highlight disappears and takes the argument with it. */
  .key {
    background: linear-gradient(180deg, transparent 58%, rgba(224, 189, 118, .30) 58%);
    color: var(--ink);
  }
  .key-hi {
    background: rgba(224, 189, 118, .16);
    box-shadow: inset 0 0 0 1px rgba(224, 189, 118, .34);
    color: var(--ink);
  }

  /* FREE has to stay legible without shouting. */
  .pill-free  { background: rgba(110, 214, 154, .14); color: #8fe0b1; }
  .pill-brass { background: rgba(216, 180, 106, .16); color: var(--brass-lit); }

  /* The twelve-month flag sits on --deep, which is now LIGHTER than the page;
   * it keeps working, but the border stops it floating. */
  .ribbon { box-shadow: inset 0 0 0 1px rgba(236, 205, 140, .30); }

  /* A photograph lit for a light page is a lamp on a dark one. Taken down a
   * little so it sits in the page rather than glaring out of it. */
  .photo img, .shot img { filter: brightness(.92) contrast(1.02); }

  /* The comparison panel: the rejected column must still read as the quieter
   * of the two once both are dark. */
  .vs .no  { background: var(--paper-2); }
  .vs .yes { background: var(--card); border-color: rgba(216, 180, 106, .45); }

  .selfnote {
    border-color: rgba(216, 180, 106, .40);
    background: linear-gradient(180deg, rgba(216,180,106,.09), rgba(216,180,106,.03));
  }

  .resume { border-color: rgba(216, 180, 106, .42); background: rgba(216, 180, 106, .09); }

  /* Buttons. The brass fill carries dark text in both themes - it is a light
   * surface either way - so only the ghost button needs its outline back. */
  .btn-ghost { box-shadow: inset 0 0 0 1px var(--line); }
}

/* A table has a minimum width it cannot go below, and the privacy notice has
 * one. So it scrolls INSIDE its own box and the page never does - wide content
 * carries its own overflow rather than exporting it. */
.doc table {
  display: block;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}

/* A finger is about 44px. The primary actions came out at 43, which is a silly
 * reason to be missed. */
.btn { min-height: 44px; }

/* ===========================================================================
   THE ENROLMENT WIZARD
   ===========================================================================
 *
 * The till is four steps rather than one long form: the phone, the length,
 * the payment, the licence. Showing all of it at once asked somebody to take
 * in a device code, a price ladder, an email field and a payment method before
 * they could act on any of it - which on a 360-wide phone is a page of
 * scrolling before the first decision.
 *
 * The rail across the top exists because a checkout that will not say how much
 * further it goes is a checkout people abandon in the middle.
 */

.rail {
  display: flex;
  gap: 0;
  list-style: none;
  margin: 0 0 28px;
  padding: 0;
  counter-reset: step;
}
.rail li {
  flex: 1 1 0;
  min-width: 0;                  /* or a long label refuses to shrink and the
                                    rail pushes the page sideways */
  padding: 0 6px 0 0;
  border-top: 2px solid var(--line);
  padding-top: 10px;
  font-size: 12.5px;
  color: var(--ink-faint);
  display: flex;
  align-items: baseline;
  gap: 7px;
}
.rail li b {
  font: 600 11px/1 var(--sans);
  letter-spacing: .04em;
  width: 18px; height: 18px;
  flex: none;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--line);
  color: var(--ink-soft);
}
.rail li span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail li.on { border-color: var(--brass); color: var(--ink); font-weight: 620; }
.rail li.on b { background: var(--brass); color: #21160a; }
/* A finished step is quietly marked rather than left looking pending. */
.rail li.done { border-color: var(--brass-text); color: var(--ink-soft); }
.rail li.done b { background: var(--brass-text); color: #fff; }

.panel[hidden] { display: none !important; }

.step-title {
  font-family: var(--serif);
  font-size: clamp(23px, 4.4vw, 30px);
  font-weight: 400;
  letter-spacing: -.015em;
  line-height: 1.18;
  margin: 0 0 10px;
}

/* Back on the left, forward on the right, and they never sit on top of each
 * other however narrow the screen gets. */
.nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 26px;
  flex-wrap: wrap;
}
.nav-row .btn { flex: 1 1 auto; }
.btn-back {
  background: var(--wash);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line);
  flex: 0 0 auto;
}

/* What is about to be charged, restated on the payment step. */
.summary {
  margin: 0 0 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--card);
  box-shadow: var(--lift);
  overflow: hidden;
}
.summary > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 13px 18px;
}
.summary > div + div { border-top: 1px solid var(--line); }
.summary dt {
  font: 600 11px/1.3 var(--sans);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}
.summary dd { margin: 0; font-size: 16px; text-align: right; }
.summary dd.mono { font-family: var(--mono); font-size: 15px; letter-spacing: .04em; }
.summary .tot { background: var(--paper-2); }
.summary .tot dd {
  font-family: var(--serif);
  font-size: clamp(22px, 3.6vw, 27px);
  color: var(--ink);
}

@media (max-width: 520px) {
  /* Below this the four labels cannot share a line legibly, so the rail keeps
   * the numbers and drops to the label of the CURRENT step only - which is the
   * only one a reader needs anyway. */
  .rail li span { display: none; }
  .rail li.on span { display: block; }
  .rail li { padding-right: 4px; }
  .nav-row .btn { width: 100%; flex: 1 1 100%; }
  .nav-row .btn-back { order: 2; }
}

/* The enrolment header, compressed. Same voice, less runway. */
header.till { padding-bottom: 26px; }
header.till .hero { padding-top: 18px; max-width: 46ch; }
header.till .hero h1.page { font-size: clamp(27px, 6.4vw, 40px); margin-bottom: 8px; }
header.till .hero .sub { font-size: 15.5px; margin: 0; }
@media (max-width: 620px) {
  header.till { padding-bottom: 20px; }
  header.till .hero { padding-top: 12px; }
}

/* --- the desk -------------------------------------------------------------
 * Reuses the shop's tokens deliberately: an internal tool that looks like a
 * different product is one more thing to hold in your head. */
.deskrows { display: grid; gap: 0; }
.deskrow {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; padding: 13px 2px;
  border-bottom: 1px solid var(--line);
}
/* A flex item will not shrink below its content, and a desk row's content is
 * an order reference and an email address - two things with no spaces in them.
 * Without these the row stayed 372px wide and took the whole PAGE sideways on
 * a 320 phone, which is exactly where the owner reads it. */
.deskrow > div { min-width: 0; }
.deskrow b, .deskrow .hint { overflow-wrap: anywhere; }
.deskrow b { font-weight: 640; display: block; }
.deskrow .hint { display: block; margin-top: 3px; }
/* The value never shrinks and never wraps: it is a price and a state, and
 * "PAID, NO LICENCE" broken across two lines is the one line on this page
 * that must be read in one glance. So the LEFT side gives way instead - it is
 * the half that can wrap. Without `flex: none` the two shared the squeeze,
 * the value was crushed to 43px with 114px of unbreakable text inside it, and
 * the overflow took the whole page sideways. */
.deskrow .val { text-align: right; white-space: nowrap; font-weight: 620; flex: none; }
.deskrow .mono, .mono { font-family: var(--mono); font-size: 14px; word-break: break-all; }

.fieldrow { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); gap: 0 16px; }

/* A text button that is still a TARGET.
 *
 * It looked like a link and measured 17px tall, which is fine for a mouse and
 * useless for a thumb - and this desk is read on a phone more than anywhere
 * else. The ink is unchanged; only the reachable area grew. */
.linkish {
  background: none; border: 0; padding: 0 0 0 10px;
  font: 600 13px var(--sans); color: var(--teal);
  cursor: pointer; text-decoration: underline;
  display: inline-flex; align-items: center; min-height: 44px;
}

/* The desk's tabs are the enrolment rail, without the numbered-step meaning. */
#tabs li b { display: none; }
#tabs li span { display: block; }
#tabs li { cursor: pointer; padding-top: 12px; }

select {
  width: 100%; padding: 13px 15px;
  font: 400 16px/1.4 var(--sans);
  color: var(--ink); background: var(--card);
  border: 1px solid var(--line); border-radius: var(--radius);
}
