/* ==========================================================================
   Checklister — public pages, plus sign in and sign up

   The idea: the page is the sheet.

   What this product replaces is a printed checklist taped up by the door, so
   the page is built like one rather than like a software brochure. Sections
   are separated by hairlines, not by floating rounded cards, and headings
   hang in a narrow left column the way labels hang on a form. Each list takes
   the shape of what it is: causes, numbered steps, a spec, a price. The tick is
   kept back for the logo and the pricing table, where it means something.

   The one loud thing is the hero, where the printed code is taped to the page
   and a phone sits over it, just scanned. Everything else stays quiet: two
   weights of one typeface, hairlines, and the tick.

   These pages must render fully without JavaScript, so there is no state
   here — nothing needs a class toggled to become legible.
   ========================================================================== */

:root {
  /* The mark on the printed code. Not a real QR — a drawn one, with the three
     finder squares and the timing lines that make the shape read at a glance.
     If you want the hero code to actually scan, replace this with a rendered
     SVG from /owner/codes/qr and keep the mask. */
  /* Two tinted grounds and one wash, for giving the sheet some weather. They
     live here rather than in base.css because the console must not band: an
     owner reading a table of runs wants one flat surface under it, while a
     public page wants the ground to change as you scroll. Kept to a few per
     cent of the two brand hues — a shaded block on a printed form, not a
     coloured card. Which band a section gets is not decoration: teal is the
     work on the phone, violet is the desk it is read from. */
  --band-brand:  #ecf8fa;
  --band-accent: #f6f3fd;
  --band-rule-brand:  rgba(10, 159, 174, .17);
  --band-rule-accent: rgba(124, 58, 237, .15);
  --hero-wash:
    radial-gradient(90% 120% at 6% -15%, rgba(14, 176, 192, .17), transparent 60%),
    radial-gradient(65% 95% at 100% -5%, rgba(124, 58, 237, .13), transparent 60%);

  /* Masking tape, which is never grey. */
  --tape: rgba(212, 180, 116, .42);

  --qr: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 25 25' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h7v1h-7zM9 0h6v1h-6zM18 0h7v1h-7zM0 1h1v1h-1zM6 1h1v1h-1zM11 1h1v1h-1zM13 1h3v1h-3zM18 1h1v1h-1zM24 1h1v1h-1zM0 2h1v1h-1zM2 2h3v1h-3zM6 2h1v1h-1zM9 2h1v1h-1zM11 2h1v1h-1zM14 2h1v1h-1zM18 2h1v1h-1zM20 2h3v1h-3zM24 2h1v1h-1zM0 3h1v1h-1zM2 3h3v1h-3zM6 3h1v1h-1zM10 3h2v1h-2zM13 3h1v1h-1zM15 3h1v1h-1zM18 3h1v1h-1zM20 3h3v1h-3zM24 3h1v1h-1zM0 4h1v1h-1zM2 4h3v1h-3zM6 4h1v1h-1zM9 4h1v1h-1zM12 4h1v1h-1zM15 4h1v1h-1zM18 4h1v1h-1zM20 4h3v1h-3zM24 4h1v1h-1zM0 5h1v1h-1zM6 5h1v1h-1zM10 5h1v1h-1zM12 5h2v1h-2zM18 5h1v1h-1zM24 5h1v1h-1zM0 6h7v1h-7zM8 6h1v1h-1zM10 6h1v1h-1zM12 6h1v1h-1zM14 6h1v1h-1zM16 6h1v1h-1zM18 6h7v1h-7zM9 7h1v1h-1zM12 7h1v1h-1zM14 7h2v1h-2zM9 8h2v1h-2zM13 8h1v1h-1zM15 8h1v1h-1zM0 9h1v1h-1zM2 9h2v1h-2zM6 9h1v1h-1zM8 9h1v1h-1zM10 9h1v1h-1zM12 9h1v1h-1zM14 9h1v1h-1zM17 9h2v1h-2zM21 9h1v1h-1zM23 9h2v1h-2zM1 10h1v1h-1zM4 10h1v1h-1zM7 10h2v1h-2zM11 10h2v1h-2zM15 10h1v1h-1zM18 10h1v1h-1zM20 10h2v1h-2zM24 10h1v1h-1zM0 11h2v1h-2zM3 11h1v1h-1zM6 11h1v1h-1zM9 11h1v1h-1zM12 11h1v1h-1zM14 11h2v1h-2zM17 11h1v1h-1zM19 11h1v1h-1zM22 11h2v1h-2zM2 12h1v1h-1zM4 12h2v1h-2zM8 12h1v1h-1zM10 12h1v1h-1zM13 12h1v1h-1zM16 12h2v1h-2zM20 12h1v1h-1zM23 12h1v1h-1zM0 13h1v1h-1zM3 13h1v1h-1zM6 13h1v1h-1zM8 13h2v1h-2zM11 13h1v1h-1zM14 13h1v1h-1zM18 13h2v1h-2zM21 13h1v1h-1zM24 13h1v1h-1zM1 14h2v1h-2zM5 14h1v1h-1zM7 14h1v1h-1zM10 14h1v1h-1zM12 14h2v1h-2zM16 14h1v1h-1zM19 14h1v1h-1zM22 14h1v1h-1zM0 15h1v1h-1zM2 15h1v1h-1zM4 15h1v1h-1zM6 15h1v1h-1zM9 15h1v1h-1zM11 15h1v1h-1zM15 15h2v1h-2zM18 15h1v1h-1zM20 15h2v1h-2zM24 15h1v1h-1zM1 16h1v1h-1zM3 16h2v1h-2zM8 16h1v1h-1zM10 16h1v1h-1zM13 16h1v1h-1zM17 16h1v1h-1zM19 16h1v1h-1zM21 16h1v1h-1zM23 16h1v1h-1zM0 17h1v1h-1zM5 17h1v1h-1zM7 17h1v1h-1zM9 17h2v1h-2zM12 17h1v1h-1zM14 17h1v1h-1zM16 17h1v1h-1zM20 17h1v1h-1zM22 17h2v1h-2zM9 18h1v1h-1zM11 18h1v1h-1zM13 18h2v1h-2zM17 18h1v1h-1zM19 18h1v1h-1zM21 18h1v1h-1zM24 18h1v1h-1zM0 18h7v1h-7zM0 19h1v1h-1zM6 19h1v1h-1zM8 19h2v1h-2zM12 19h1v1h-1zM15 19h1v1h-1zM18 19h1v1h-1zM20 19h1v1h-1zM23 19h1v1h-1zM0 20h1v1h-1zM2 20h3v1h-3zM6 20h1v1h-1zM10 20h1v1h-1zM13 20h1v1h-1zM16 20h2v1h-2zM19 20h2v1h-2zM22 20h1v1h-1zM24 20h1v1h-1zM0 21h1v1h-1zM2 21h3v1h-3zM6 21h1v1h-1zM8 21h1v1h-1zM11 21h2v1h-2zM14 21h1v1h-1zM17 21h1v1h-1zM21 21h1v1h-1zM23 21h2v1h-2zM0 22h1v1h-1zM2 22h3v1h-3zM6 22h1v1h-1zM9 22h1v1h-1zM12 22h1v1h-1zM15 22h2v1h-2zM18 22h2v1h-2zM22 22h1v1h-1zM0 23h1v1h-1zM6 23h1v1h-1zM8 23h2v1h-2zM11 23h1v1h-1zM13 23h1v1h-1zM17 23h1v1h-1zM20 23h2v1h-2zM24 23h1v1h-1zM0 24h7v1h-7zM9 24h1v1h-1zM12 24h2v1h-2zM16 24h1v1h-1zM19 24h1v1h-1zM21 24h1v1h-1zM23 24h1v1h-1z'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
  :root {
    /* A tint that reads on paper disappears on a dark ground, so the bands are
       built the other way round in the dark: a step *up* from --paper with the
       hue in it, rather than a step down from white. */
    --band-brand:  #141c1b;
    --band-accent: #181628;
    --band-rule-brand:  rgba(45, 212, 191, .22);
    --band-rule-accent: rgba(139, 92, 246, .26);
    --hero-wash:
      radial-gradient(90% 120% at 6% -15%, rgba(45, 212, 191, .12), transparent 60%),
      radial-gradient(65% 95% at 100% -5%, rgba(139, 92, 246, .16), transparent 60%);
    --tape: rgba(198, 168, 108, .26);
  }
}

/* --- Header --------------------------------------------------------------
   A hairline and nothing else. No translucency, no shadow: this is the top
   edge of a sheet of paper.
   ------------------------------------------------------------------------ */

.site-header {
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  position: sticky; top: 0; z-index: 20;
}
.site-header .wrap { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 70px; }

.site-nav { display: flex; align-items: center; gap: 1.35rem; }
.site-nav a { color: var(--ink-soft); text-decoration: none; font-size: .95rem; }
.site-nav a:hover, .site-nav a[aria-current="page"] { color: var(--ink); }
/* `.site-nav a` outranks `.btn-primary` — one class plus a type selector beats
   one class — so without these the header's teal call to action draws its text
   in --ink-soft and reads dark-on-teal. Only the hover states were covered
   here, which is why it looked right the moment you pointed at it. */
.site-nav .btn { color: var(--ink); }
.site-nav .btn:hover { color: var(--ink); }
.site-nav .btn-primary,
.site-nav .btn-primary:hover { color: var(--brand-ink); }
.js-auth-links { display: flex; align-items: center; gap: .6rem; }
@media (max-width: 700px) { .site-nav .nav-collapse { display: none; } }

/* At a desk there is room for the mark to be read as a drawing rather than as a
   favicon beside a word, and the header row is 70px tall either way. On a phone
   it stays at the 28px base.css sets, where the bar is tight and the mark is
   sharing the line with a call to action. */
@media (min-width: 700px) {
  .site-header .brand-mark { width: 36px; height: 36px; }
  .site-header .brand { font-size: 1.15rem; }
}

/* --- Hero ----------------------------------------------------------------
   Words on the left, the actual object on the right: the code you print, taped up,
   with the phone that just read it. Every competitor opens with a floating
   browser window; this product's first object is a piece of paper.
   ------------------------------------------------------------------------ */

/* The one thing on these pages that is not flat paper: colour bleeding in from
   the two top corners, teal from the side the words are on and violet from the
   side the screen is on. It is a light source, not a panel — no edge, nothing
   to mistake for a card. */
.hero {
  padding: clamp(3rem, 7vw, 5.5rem) 0 clamp(3.5rem, 7vw, 5.5rem);
  background: var(--hero-wash);
}
.hero h1 {
  font-size: clamp(2.3rem, 5.6vw, 3.75rem);
  max-width: 15ch; letter-spacing: -.035em; line-height: 1.04;
}
.hero .lede { font-size: clamp(1.05rem, 1.9vw, 1.2rem); color: var(--ink-soft); max-width: 48ch; margin-top: 1.1rem; }
.hero-actions { display: flex; gap: .7rem; flex-wrap: wrap; margin-top: 2rem; }

/* A hero that is only its title. The padding and the type above are sized for a
   headline, a lede and two buttons, so on /contact/ — where the form says the whole
   of it and there is nothing under the heading — they leave a band of empty wash
   over the sheet. Same wash, less of it, and the heading at the size a page title
   wants rather than a headline's. */
.hero-tight { padding: clamp(2rem, 4vw, 3rem) 0 clamp(1.75rem, 3.5vw, 2.5rem); }
.hero-tight h1 { font-size: clamp(1.9rem, 3.6vw, 2.6rem); max-width: none; }
.hero-terms { margin-top: 1.1rem; font-size: .9rem; color: var(--ink-faint); max-width: 44ch; }

.hero-grid { display: grid; gap: clamp(3rem, 6vw, 4.5rem); align-items: center; }
/* The picture is the wider column, and it is the only two-column hero on the
   site, so all of this is scoped to the grid rather than to `.hero`. The phone
   was drawn at 247px, where a screenshot of a checklist is a grey texture
   rather than a checklist, and in a 490px column there was no room to grow it
   except by sliding it further over the sheet, which is how it came to be lying
   across the sheet's own label. 60% of the row, and a narrower gap, is what pays
   for it. The words carry it, and the headline is what limits how far this can
   go: "Checklists your" is 408px at the size it settles on, in a column of
   421px, so 40/60 is close to the last ratio that keeps the headline on three
   lines. This is the page that has to work for somebody who takes in nothing
   but the pictures. */
@media (min-width: 940px) {
  .hero-grid {
    grid-template-columns: minmax(0, 40fr) minmax(0, 60fr);
    gap: 3rem;
    /* The phone is twice the height of the sheet, so it hangs well below it.
       Room for that here rather than on `.hero`, which three other pages use
       for a heading and nothing else. */
    padding-bottom: clamp(0px, 7vw, 5.5rem);
  }
}

/* --- The scene: a printed code, and the phone that read it --------------- */

.scene { position: relative; max-width: 420px; margin-inline: auto; }

.wallcard {
  position: relative; margin: 0;
  width: 78%; padding: 1.6rem 1.4rem 1.3rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 3px;                                  /* paper barely rounds */
  box-shadow: 0 1px 1px rgba(22, 32, 31, .04), 0 18px 34px -22px rgba(22, 32, 31, .55);
  transform: rotate(-1.6deg);
  text-align: center;
}
/* The strip of tape. Every one of these sheets in the wild has one. */
.wallcard::before {
  content: ""; position: absolute; z-index: 1;
  top: -14px; left: 50%; width: 104px; height: 27px;
  transform: translateX(-50%) rotate(-1.2deg);
  background: var(--tape);
  box-shadow: inset 0 0 0 1px rgba(22, 32, 31, .07);
}
.wallcard-qr {
  width: 100%; max-width: 178px; aspect-ratio: 1; margin: 0 auto .95rem;
  background: var(--ink);
  -webkit-mask: var(--qr) center / contain no-repeat;
          mask: var(--qr) center / contain no-repeat;
}
.wallcard-place { font-weight: 700; font-size: 1.05rem; margin: 0; letter-spacing: -.02em; }
/* Set in Atkinson at wide tracking rather than a monospace: this face was
   drawn so a 4 cannot be read as a 9, which is the whole job of a short code
   somebody is typing in because the camera would not focus. */
.wallcard-code {
  margin: .35rem 0 0; font-weight: 700; font-size: 1rem;
  letter-spacing: .16em; color: var(--brand-text);
}
.wallcard-hint { margin: .8rem 0 0; font-size: .82rem; color: var(--ink-faint); }

.scene .shot-phone { width: 60%; max-width: 247px; margin: -14% 0 0 auto; }
@media (min-width: 560px) {
  .scene .shot-phone { position: absolute; right: 0; bottom: -9%; margin: 0; }
}

/* Side by side, the scene is wide enough to hold both objects, so the phone
   lies over the sheet's right edge instead of over the sheet. The sheet takes
   52% of the scene and the phone 55%, and the 7% left over is the overlap: at
   the widest that is 44px onto a sheet whose longest line stops 62px short of
   its own edge, and the margin only grows as the column narrows.

   The sheet is 328px, which is the 327px it has always been, and enlarging it
   is the one change that does not pay here. Every pixel on the sheet costs the
   phone that pixel of room and half a pixel of the white margin it is allowed
   to lie on, so a 390px sheet drags the phone back under 335px and puts it on
   the label again. The room came out of the column instead.

   Two things about the phone. It is centred on the sheet rather than hung off
   the bottom of it, because at 347px it is over twice the height of the paper
   and bottom-anchoring pushed the top of it up through the hero's padding into
   the site header. And it is biased downwards, because what is below the hero
   is air and what is above it is that header. */
@media (min-width: 940px) {
  .scene { max-width: 640px; width: 60%}
  .wallcard { width: 45%; }
  /* Breaks the label onto two lines a little before it has to, which is what
     keeps it clear of the phone through the middle of this range. At the widest
     the sheet is roomy enough that this never bites and the label reads on one
     line the way it always has. */
  .wallcard-hint { max-width: 84%; margin-inline: auto; }
  .scene .shot-phone {
    position: absolute; right: 0; top: 50%; bottom: auto;
    width: 65%; max-width: 360px; margin: 0;
    transform: translateY(-44%);
  }
}

/* --- Sections ------------------------------------------------------------
   A section is a heading hanging in the left margin with its content beside
   it, the way a field label hangs on a form. Below the breakpoint it stacks
   and reads as an ordinary document.
   ------------------------------------------------------------------------ */

.section { padding: clamp(3rem, 6vw, 4.5rem) 0; border-top: 1px solid var(--rule); }

/* A banded section, and which band it gets carries the same meaning the two
   colours carry everywhere else: --band-brand for what happens on the phone,
   --band-accent for what is read at the desk. Alternate them against plain
   paper rather than tinting every section, or the rhythm goes and it is just a
   differently coloured page. The hairline goes with the band: a grey rule
   across a tinted ground reads as a mistake. */
.section-brand  { background: var(--band-brand);  border-top-color: var(--band-rule-brand); }
.section-accent { background: var(--band-accent); border-top-color: var(--band-rule-accent); }

.sheet { display: grid; gap: 1.5rem clamp(2rem, 4vw, 3.5rem); align-items: start; }
@media (min-width: 900px) {
  .sheet { grid-template-columns: minmax(0, 25ch) minmax(0, 1fr); }
}
.sheet-head h2 { margin: 0; font-size: clamp(1.5rem, 2.6vw, 1.9rem); }
/* A short violet rule over every section heading — the mark that says "new
   field" on a form, and the cheapest colour on the page. Violet because it
   frames the work rather than being it, and solid rather than a teal-to-violet
   fade: the two colours blend in exactly two places on this site and this is
   not one of them. */
.sheet-head h2::before,
.section > .wrap > h2::before,
.beside-copy h2::before {
  content: ""; display: block;
  width: 34px; height: 3px; border-radius: 2px;
  margin-bottom: .95rem;
  background: var(--accent);
}
/* For a section that needs its full width — the four steps — the heading sits
   above instead of beside. */
.section > .wrap > h2 { font-size: clamp(1.5rem, 2.6vw, 1.9rem); max-width: 20ch; }
.section-lede { color: var(--ink-soft); max-width: 56ch; margin: .8rem 0 2.25rem; }
.sheet-head p { margin: .7rem 0 0; color: var(--ink-soft); font-size: .95rem; max-width: 34ch; }

/* --- Three lists, three shapes -------------------------------------------
   An earlier pass gave every list on the page a tick box and the page turned
   into wallpaper — and the ticks were lying: three ways a job can start are
   alternatives, not things anybody completed, and four steps through a
   morning are a sequence, not a checklist. So the tick now appears in exactly
   two places, the logo and the pricing table, where it means "included".
   Everything else takes the shape of what it actually is.
   ------------------------------------------------------------------------ */

/* 1. Triggers: three different causes, so three different marks — the code
      itself, a time, a person. The left column *is* the answer to "what
      starts this", before the heading beside it says so. */
.triggers { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.triggers > li {
  display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 1.5rem;
  align-items: start; padding: 1.6rem .25rem; border-bottom: 1px solid var(--rule);
}
.triggers h3 { margin: 0 0 .3rem; }
.triggers p { margin: 0; color: var(--ink-soft); max-width: 60ch; }

.trigger-mark {
  width: 64px; height: 64px; display: grid; place-items: center;
  border: 1px solid var(--rule-strong); border-radius: 4px;
  background: var(--paper-raised);
  font-weight: 700; letter-spacing: -.02em;
}
/* No border on this one: a mask would clip it off anyway, and the code is
   already a shape with its own edges. Teal rather than black — unlike the
   sheet in the hero, this is not a picture of something printed, it is the
   product's own mark for "this starts by scanning". */
.trigger-code {
  border: 0; border-radius: 0; background: var(--brand);
  -webkit-mask: var(--qr) center / contain no-repeat;
          mask: var(--qr) center / contain no-repeat;
}
/* The two automatic triggers are the product, so teal; the one that goes
   through a person is violet, the same way the console is. */
.trigger-time {
  font-size: 1.05rem; font-variant-numeric: tabular-nums;
  color: var(--brand-text); background: var(--brand-tint); border-color: transparent;
}
.trigger-who { font-size: 1.15rem; color: var(--accent); background: var(--accent-tint); border-color: transparent; }

/* 2. The day: four numbered columns, divided like the price table. It is a
      real sequence, so it gets real numbers — set as big pale figures printed
      on the sheet rather than as badges on tiles, which is the treatment
      every product page already has. No icon beside the number: one marker
      per step is enough. */
.steps { list-style: none; margin: 0; padding: 0; counter-reset: step; display: grid; border-top: 1px solid var(--rule); }
.steps > li { counter-increment: step; padding: 1.5rem 0; border-bottom: 1px solid var(--rule); }
.steps > li::before {
  content: counter(step);
  display: block; margin-bottom: .55rem;
  font-size: 2.6rem; font-weight: 700; line-height: 1;
  letter-spacing: -.05em; color: var(--brand);
  font-variant-numeric: tabular-nums;
}
/* The figures were grey, which made the one genuinely sequential thing on the
   page the quietest. They are teal now — and the fourth is violet, because it
   is the one step that happens at the desk rather than on the phone. The
   colour change *is* the handover. */
.steps > li:last-child::before { color: var(--accent); }
.steps h3 { margin: 0 0 .35rem; }
.steps p { margin: 0; color: var(--ink-soft); font-size: .95rem; }

@media (min-width: 900px) {
  .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); border-bottom: 1px solid var(--rule); }
  .steps > li { border-bottom: 0; border-left: 1px solid var(--rule); padding: 1.75rem clamp(1rem, 2vw, 1.75rem); }
  .steps > li:first-child { border-left: 0; padding-left: 0; }
  .steps > li:last-child { padding-right: 0; }
}

/* 3. Specs: a plain capability list, one icon per row so eight of them do not
      read as one grey block. */
.spec { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.spec > li {
  display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: 1rem;
  padding: 1.15rem .25rem; border-bottom: 1px solid var(--rule);
}
.spec h3 { margin: 0 0 .25rem; }
.spec p { margin: 0; color: var(--ink-soft); max-width: 60ch; }
.spec-ico { color: var(--brand); margin-top: .3rem; }
.spec-ico::before { width: 21px; height: 21px; }
/* The desk half of the features page: the same list, violet, because these are
   the things that frame the work rather than the work itself. Two lists of
   eight identical teal glyphs would have read as one list. */
.spec-desk .spec-ico { color: var(--accent); }

/* The tick itself, now earning its keep in the price table. */
.ticks { list-style: none; margin: 0; padding: 0; }
.ticks > li { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: .7rem; padding: .5rem .25rem; color: var(--ink-soft); }
.tickbox {
  width: 18px; height: 18px; margin-top: .25rem;
  border: 2px solid var(--done); border-radius: 4px;
  display: grid; place-items: center;
  background: var(--done); color: #fff;
}
.tickbox::before { width: 12px; height: 12px; }

/* 4. The export: what is being described is a spreadsheet, so the shape on the
      page is a spreadsheet. `table.data` comes from base.css and already draws
      ruled rows with a sunken header, so the only things undone here are the
      console's row hover, since nothing on this page is a row you can open,
      and the wrapping, since a column of a file does not wrap. Below the
      measure it scrolls sideways inside its own .table-scroll rather than
      reflowing into cards the way the console's tables do: the point of the
      picture is that it is a grid. */
.export-preview { border-top: 1px solid var(--rule); }
.export-preview table.data { min-width: 44rem; }
.export-preview table.data tbody tr:hover { background: none; }
.export-preview table.data th,
.export-preview table.data td { white-space: nowrap; }

/* Short statements under an object, ruled like everything else that separates
   here — a tinted box would make a warning out of three ordinary facts. No
   icon on them either: the page already carries two lists that take one per
   row, and a third would be the wallpaper those were shaped to avoid. Used by
   the price table's footnotes and by the export. */
.notes { margin-top: 2rem; border-top: 1px solid var(--rule); }
.notes p { max-width: 60ch; font-size: .95rem; color: var(--ink-soft); padding: .9rem 0; margin: 0; border-bottom: 1px solid var(--rule); }
.notes strong { color: var(--ink); font-weight: 600; }

/* --- Product shots -------------------------------------------------------
   The frames are real; the pictures are not taken yet. A placeholder that
   reads as a considered empty slot is a page you can ship today, where an
   <img> pointing at a file that does not exist is a broken image in the
   middle of the hero. Swapping one in is a one-element change: drop an <img>
   in place of the .shot-slot inside the same .shot-frame, and because the
   frame owns the aspect ratio the layout does not move.
   ------------------------------------------------------------------------ */

.shot { margin: 0; }
.shot-frame {
  position: relative; overflow: hidden;
  border-radius: var(--radius);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
}
/* The picture element is what carries the two themes: a `<source>` on
   prefers-color-scheme and the light shot as the `<img>`, so a reader in the dark gets
   the console in the dark and nothing has to run to arrange it. It needs a box of its
   own, because the img's `height: 100%` resolves against its parent and an inline
   `<picture>` has no height to resolve against — which draws the shot at its natural
   size, straight out of the frame. */
.shot-frame picture { display: block; width: 100%; height: 100%; }
.shot-frame img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top center; }

.shot-slot {
  height: 100%;
  display: grid; place-content: center; justify-items: center; gap: .5rem;
  padding: 1.5rem; text-align: center;
  /* Tinted, not grey: five of these frames are on the public pages until the
     screenshots exist, and eight grey slabs is most of what made the page
     colourless. Teal for a phone or the tablet that hands work out, violet for
     the console — the same pairing the real screenshots will have in them. */
  background: linear-gradient(170deg, var(--brand-tint), transparent 85%), var(--paper-raised);
}
.shot-ico { color: var(--brand); }
.shot-ico::before { width: 26px; height: 26px; }
.shot-label { font-weight: 700; color: var(--ink-soft); font-size: .92rem; }
.shot-note { font-size: .82rem; color: var(--ink-faint); }
.shot figcaption { margin-top: .9rem; font-size: .88rem; color: var(--ink-soft); }

/* A console: a window with a bar along the top. */
.shot-desk .shot-frame { aspect-ratio: 16 / 10; padding-top: 32px; box-shadow: var(--shadow); }
.shot-desk .shot-slot { background: linear-gradient(170deg, var(--accent-tint), transparent 85%), var(--paper-raised); }
.shot-desk .shot-ico { color: var(--accent); }
.shot-bar {
  position: absolute; inset: 0 0 auto 0; height: 32px;
  display: flex; align-items: center; gap: 6px; padding-inline: 12px;
  background: var(--accent-tint); border-bottom: 1px solid var(--rule);
}
.shot-bar span { width: 8px; height: 8px; border-radius: 50%; background: var(--accent-lift); opacity: .55; flex: none; }

/* A phone: thick dark bezel, tall screen. */
.shot-phone { max-width: 250px; }
.shot-phone .shot-frame {
  aspect-ratio: 9 / 18.5; padding: 10px;
  border-radius: 30px; border-color: transparent;
  background: #1b201f;
  box-shadow: 0 2px 4px rgba(22, 32, 31, .18), 0 26px 44px -26px rgba(22, 32, 31, .8);
}
.shot-phone .shot-slot { border-radius: 21px; gap: .35rem; padding: 1rem; }
.shot-phone .shot-ico::before { width: 21px; height: 21px; }
.shot-phone .shot-label { font-size: .82rem; }
.shot-phone .shot-note { font-size: .74rem; }
.shot-phone .shot-frame img { border-radius: 21px; }
/* No drawn notch or speaker across the top of the screen. There was one while the frame
   held a placeholder, where it was the mark that said "phone" — but a real screenshot
   arrives with its own status bar, and a second one drawn over it reads as clutter
   rather than as hardware. The tablet's lens is a different case: it sits in the bezel
   rather than over the screen, so it still lands on nothing. */

/* Three frames in a row. One picture of a phone shows the shape of the app;
   three show what it does, which is what a features page is for. auto-fit
   rather than a fixed three columns, because three 110px phones on a 360px
   screen is a row of thumbnails nobody can read: it stacks instead, and the
   250px cap is the same one a lone phone shot has. */
.shot-row {
  margin-top: 2.25rem;
  display: grid; gap: clamp(1rem, 2.5vw, 1.75rem);
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  justify-items: center; align-items: start;
}
.shot-row .shot-phone { width: 100%; }

/* A tablet: the phone's bezel at the size the board is actually used at.
   Reception props one on a desk, which is why that screen is tiles and ruled
   rows rather than a table with an Edit column, so the frame is part of the
   argument rather than decoration around it. Landscape at 10/7 rather than
   16/10, because a laptop screen and a tablet differ by about that much and it
   is the whole of how a reader tells this frame from the console one. */
.shot-tablet { max-width: 520px; }
.shot-tablet .shot-frame {
  aspect-ratio: 10 / 7; padding: 12px;
  border-radius: 24px; border-color: transparent;
  background: #1b201f;
  box-shadow: 0 2px 4px rgba(22, 32, 31, .18), 0 26px 44px -26px rgba(22, 32, 31, .8);
}
.shot-tablet .shot-slot { border-radius: 14px; }
.shot-tablet .shot-frame img { border-radius: 14px; }
/* The camera sits in the bezel here rather than over the screen: an iPad has a
   dot on the long edge, and a phone's notch on a tablet reads as a big phone. */
.shot-lens {
  position: absolute; z-index: 2; top: 4px; left: 50%; transform: translateX(-50%);
  width: 5px; height: 5px; border-radius: 50%; background: rgba(255, 255, 255, .28);
}

/* Copy on one side, the screen that proves it on the other. */
.beside { display: grid; gap: clamp(2rem, 4vw, 3rem); align-items: center; }
.beside-copy { display: grid; gap: 1.75rem; }
.beside-copy h2 { margin: 0 0 .5rem; }
.beside-copy p { margin: 0; color: var(--ink-soft); }
@media (min-width: 880px) { .beside { grid-template-columns: minmax(0, 1.5fr) minmax(0, .5fr); } }

/* --- Pricing -------------------------------------------------------------
   Three columns on one sheet, divided by rules. The chosen one is marked by
   a heavier rule above it, not by a shadow and a ring — a printed price list
   would underline it, not levitate it.
   ------------------------------------------------------------------------ */

/* Two amounts in the markup and one of them on the screen. Euro is what stands with
   nothing running, which is what a crawler and a reader with no JavaScript get; the
   head script sets [data-currency] on <html> and this decides which pair is drawn.
   There is no switch to style: see the note in src/_includes/currency.njk. */
.cur-usd { display: none; }
[data-currency="usd"] .cur-eur { display: none; }
[data-currency="usd"] .cur-usd { display: inline; }

.plans { display: grid; gap: 0; border-top: 1px solid var(--rule); }
.plan { display: flex; flex-direction: column; padding: 1.75rem 0; border-bottom: 1px solid var(--rule); }
/* Centred rather than baseline-aligned: the pill beside the name is a box with
   padding round a smaller line of text, so sitting it on the heading's baseline
   hangs it below the word. Both boxes are a line of text at line-height 1.14, so
   centring them lines the pill up with the name's own middle. */
.plan h3 { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; font-size: 1.15rem; margin-bottom: .8rem; }
.plan-blurb { color: var(--ink-soft); font-size: .95rem; margin: -.4rem 0 1rem; }
.plan-amount { font-size: 2.6rem; font-weight: 700; letter-spacing: -.04em; line-height: 1; }
.plan-per { font-size: .95rem; color: var(--ink-soft); font-weight: 400; letter-spacing: normal; }
/* The one thing that differs between the columns, so it is the one thing under the
   price — and it takes the growth that the tick list used to take, since there is no
   tick list in a column any more. The allowance is said twice, once as the number
   that is charged for and once in the unit a reader already thinks in: somebody
   pricing themselves knows roughly what their team gets through in a day and has no
   idea what that comes to in a month. */
.plan-allow { flex: 1 1 auto; margin: 1.25rem 0; }
.plan-count { font-weight: 600; }
.plan-rate { color: var(--ink-soft); font-size: .9rem; margin-top: .35rem; }
/* The chosen column: the heavier rule it always had, and now the ground under
   it is tinted too — a price list marks the recommended column by shading it,
   the same gesture the "this is on" option cards in the checklist editor use.
   Still no shadow and no ring: it does not levitate, it is just shaded. */
.plan-chosen {
  border-top: 3px solid var(--accent); margin-top: -1px;
  background: linear-gradient(180deg, var(--accent-tint), transparent 60%);
}
.plan-chosen h3 { color: var(--accent-dark); }
/* "Most chosen" is a violet-tinted pill, and the column it sits in is now
   violet-tinted too — so it disappeared. Solid fill here instead. */
.plan-chosen .tag-accent { background: var(--accent); color: var(--accent-ink); }

/* What is in every plan, said once under the table instead of three identical times
   inside it. This is where the tick earns its keep on this page: here "included" is
   exactly what it means. */
.plan-included { margin-top: 2rem; }
.plan-included-head { margin-bottom: .9rem; }
.plan-included .ticks { display: grid; gap: .55rem 2rem; }


@media (min-width: 860px) {
  .plan-included .ticks { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .plans { grid-template-columns: repeat(3, minmax(0, 1fr)); border-bottom: 1px solid var(--rule); }
  .plan { padding: 1.75rem clamp(1.25rem, 2.5vw, 2rem); border-bottom: 0; border-left: 1px solid var(--rule); }
  .plan:first-child { border-left: 0; padding-left: 0; }
  .plan:last-child { padding-right: 0; }
}

/* --- Closing band --------------------------------------------------------
   The one full-bleed dark surface, and the same teal-into-plum as the console
   rail — the page ends on the colour the app opens with.
   ------------------------------------------------------------------------ */

.cta-band {
  background: linear-gradient(160deg, #0d2f2c 0%, #1b1533 100%);
  color: #fff;
  padding: clamp(3.25rem, 7vw, 5rem) 0;
}
.cta-band h2 { color: #fff; max-width: 18ch; font-size: clamp(1.7rem, 3.4vw, 2.4rem); }
.cta-band p { color: rgba(255, 255, 255, .74); max-width: 46ch; }
.cta-band .muted { color: rgba(255, 255, 255, .74); }
/* A teal button sinks into a teal band, so here the primary action is white. */
.cta-band .btn-primary { background: #fff; color: #06414a; border-color: transparent; box-shadow: none; }
.cta-band .btn-primary:hover { background: #e4f5f8; color: #06414a; }

/* --- Footer -------------------------------------------------------------- */

/* Tinted, so a page that ends on white paper — pricing, the legal pages — still
   ends on something rather than trailing off. On the homepage it is the quiet
   step down from the dark closing band. */
.site-footer {
  border-top: 1px solid var(--band-rule-brand);
  background: var(--band-brand);
  padding: 3rem 0 3.5rem; color: var(--ink-soft); font-size: .9rem;
}
.site-footer .wrap { display: flex; gap: 2rem; justify-content: space-between; flex-wrap: wrap; }
.site-footer nav { display: flex; gap: 1.4rem; flex-wrap: wrap; align-items: flex-start; }
.site-footer a { color: var(--ink-soft); text-decoration: none; }
.site-footer a:hover { color: var(--ink); text-decoration: underline; }
.site-footer .brand:hover { text-decoration: none; }

/* Bigger here than in the header, and deliberately so: the footer is the one
   place on the page with nothing competing for attention, the tagline sits
   under it as a caption, and the mark is the last thing somebody sees on the
   way off the page. */
@media (min-width: 700px) {
  .site-footer .brand-mark { width: 52px; height: 52px; }
  .site-footer .brand { font-size: 1.4rem; gap: .7rem; }
}

/* --- Sign in / sign up ---------------------------------------------------
   One sheet, one job. The form sits on paper with a rule around it rather
   than in a floating card, so it matches the pages that lead to it.
   ------------------------------------------------------------------------ */

/* The same wash as a hero, for the same reason: the white sheet of the form
   needs something behind it, and these two pages are the first thing a
   returning customer sees. */
.auth-main { padding: clamp(2.5rem, 6vw, 4.5rem) 0; background: var(--hero-wash); }
.form-sheet {
  background: var(--paper-raised);
  border: 1px solid var(--rule); border-radius: var(--radius);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  box-shadow: 0 1px 1px rgba(22, 32, 31, .04), 0 20px 40px -28px rgba(22, 32, 31, .5);
}
.form-sheet h1 { font-size: 1.6rem; }
.auth-aside { margin: 1.25rem 0 0; font-size: .9rem; color: var(--ink-soft); text-align: center; }

/* The way out of a form that has just refused you, kept *inside* the sheet: a
   password that will not work is a dead end, and the way past it belongs where
   the refusal is rather than at the foot of the page with the sign-up line. */
.auth-alt { margin: 1.25rem 0 0; font-size: .9rem; color: var(--ink-soft); text-align: center; }

/* Waiting for the server on a page that was reached by tapping a link in a
   message: the first thing it owes the reader is that something is happening.
   A flex row because `.spinner` is a sized box, and a bare inline span cannot
   be one. */
.auth-wait { display: flex; align-items: center; gap: .6rem; margin: 0; color: var(--ink-soft); }

/* An invitation names its own person, above the field rather than in it. The
   address is stated because the token already identifies it — and because a
   password box with no name on it is the shape of a phishing page. */
.invite-who {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem 1rem;
  margin: 0 0 1.5rem; padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--rule);
}
.invite-who .ico { font-size: .9rem; color: var(--ink-soft); }

/* --- Long-form pages ----------------------------------------------------- */

.prose { max-width: var(--measure); }
.prose h2 { margin-top: 2.5rem; }
.prose li { margin-bottom: .4em; }

/* The confirmation after the contact form: the box gets ticked. */
.done-mark {
  width: 56px; height: 56px; margin-bottom: 1.5rem;
  border: 3px solid var(--done); border-radius: 8px;
  display: grid; place-items: center; color: var(--done);
}
.done-mark::before { width: 34px; height: 34px; }
