/* ==========================================================================
   OneMacStudio - one stylesheet, no build step, no external requests.

   No webfont is loaded from a CDN on purpose. A font served from Google's CDN
   sends every visitor's IP to Google, which would contradict the "nothing is
   tracked here" promise this site makes and would have to be disclosed in the
   privacy policy. The system stack below costs zero requests and renders
   instantly. To self-host a display face later, drop woff2 files into
   assets/fonts/ and uncomment the @font-face block - the stack already falls
   through to the system fonts if the files are missing.

   Light theme only. A dark theme was built and removed: the cost is not the CSS,
   it is that every image has to work on two backgrounds - the logo has black ink
   in it, and most of the app screenshots have light backgrounds baked in.
   ========================================================================== */

/*
@font-face {
  font-family: "Display";
  src: url("fonts/display.woff2") format("woff2");
  font-weight: 700 800;
  font-display: swap;
}
*/

:root {
  color-scheme: light;

  /* Warm paper, not paper-white. A pure #FFF page is what makes long reading
     feel harsh, and these pages include legal text people actually have to
     read. Cards stay white so they lift off it. */
  --bg:        #F6F5F1;
  --surface:   #FFFFFF;
  --text:      #17181C;
  --muted:     #5A5D67;
  --line:      #E3E1DA;
  --accent:    #0E7C6B;
  --accent-ink:#FFFFFF;
  --accent-bg: #E9F3F0;
  /* A warm second accent, taken from the clay and rope in the header drawing
     and the red in the logo. Teal means "you can tap this"; terracotta means
     "notice this" - section labels and launch offers. Kept to those two jobs,
     so it never competes with the buttons. */
  --warm:      #B4532A;
  --warm-ink:  #9A3412;
  --warm-bg:   #FFE8D6;
  --shadow:    0 1px 2px rgba(23, 24, 28, .04), 0 8px 24px rgba(23, 24, 28, .07);

  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI Variable Text",
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: "Display", var(--font);

  /* One type scale, used everywhere. Deliberately restrained at the top end:
     a studio page should let someone take in the whole shape at a glance and
     read it in order, not discover it one scroll at a time. */
  --t-hero:  clamp(2.1rem, 5vw, 3.4rem);
  --t-lead:  clamp(1.1875rem, 1.7vw, 1.375rem);
  --t-h2:    clamp(1.375rem, 2.4vw, 1.625rem);
  --t-h3:    1.1875rem;
  --t-body:  1.125rem;
  --t-small: 0.9375rem;

  /* Vertical rhythm, in one place. Tight on purpose. */
  --space-section: clamp(2.25rem, 4.5vw, 3.25rem);
  --space-masthead: clamp(1.5rem, 2.5vw, 2.25rem);

  --container: 70rem;
  --prose: 38rem;
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--t-body);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }

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

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

/* The one accessibility affordance a text site genuinely needs. */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--accent-ink);
  padding: .75rem 1rem;
  z-index: 10;
}
.skip:focus { left: 1rem; top: 1rem; }

/* --------------------------------------------------------------------------
   Typography. The scale does the work: one very large thing per screen, one
   medium thing per section, everything else the same size.
   -------------------------------------------------------------------------- */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin: 0;
  text-wrap: balance;
}

h1 { font-size: var(--t-hero); letter-spacing: -0.03em; }

/*
 * The phrase the headline actually turns on, marked twice: accent colour, and a
 * hand-drawn underline borrowed from the app's own store screenshots - they use
 * the same wobbly stroke under their key lines, so the site and the listing read
 * as one hand.
 *
 * The stroke is an inline SVG data URI rather than text-decoration: a straight
 * rule under a headline is a link cue, and this should read as something someone
 * drew, not as something clickable. preserveAspectRatio="none" lets it stretch
 * to whatever width the phrase happens to be.
 */
.mark-hl {
  color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 12' preserveAspectRatio='none'%3E%3Cpath d='M2,8.5 Q30,3.2 60,6.6 T118,4.4' fill='none' stroke='%230E7C6B' stroke-width='3.4' stroke-linecap='round' opacity='0.55'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 0 calc(100% - 0.02em);
  background-size: 100% 0.26em;
  padding-bottom: 0.12em;
}
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); font-weight: 700; letter-spacing: -0.015em; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

.lead {
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--muted);
  max-width: 34rem;
  text-wrap: pretty;
}

/* The one word in the lead that is a name rather than a claim. Full ink at 600
   lifts it half a tone out of the muted sentence around it - enough to give the
   sentence a subject to start from, without a second coloured mark competing
   with the h1's highlight, and without looking like something to click. */
.lead .name { color: var(--text); font-weight: 600; }

/* 600, not the browser's 700. One phrase in a paragraph only has to step
   forward far enough to be found by someone scanning for it; full bold in body
   copy shouts, and this site's emphasis vocabulary is already set at 600. */
strong { font-weight: 600; }

.eyebrow {
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 1rem;
}

.muted { color: var(--muted); }
.small { font-size: var(--t-small); }

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */
/*
 * Locked to the top of the window. It shrinks once the page has moved - at full
 * size the logo alone is 96px, and a header that height pinned permanently takes
 * a sixth of a laptop screen away from the thing people came to read.
 */
.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  border-bottom: 1px solid transparent;
  background: var(--bg);
  transition: border-color .2s ease;
}
.site-header.is-stuck {
  border-bottom-color: var(--line);
  box-shadow: 0 1px 12px rgba(23, 24, 28, .05);
}
/*
 * Centred, and the same on every page. The wordmark is the link home, so there
 * is no "Home" item beside it - that would duplicate it and leave one side of
 * the bar empty while the other carried a single word. Identical on all six
 * pages means the masthead never shifts as you move between them.
 */
.site-header .container {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  padding-block: 3rem 3.25rem;
  transition: padding .2s ease;
}
.site-header.is-stuck .container { padding-block: .9rem; }

/*
 * Two palms with a hammock slung between them, and the wordmark hanging above
 * it. The header has a lot of empty width either side of a centred logo, and
 * this gives that space a reason to exist.
 *
 * The art carries its own muted colour - sage fronds, clay trunk, tan rope, all
 * desaturated so they sit on the warm paper rather than sitting on top of it.
 * It was grey line art at .38 opacity before; with real colour it can be drawn
 * nearer to full strength and still stay behind the logo.
 *
 * It fades out the moment the page moves. A scene is a welcome at the top of a
 * page; the same scene sitting over someone's shoulder while they read a
 * privacy policy is decoration in the way.
 */
.header-scene {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  max-width: 60rem;
  pointer-events: none;
  opacity: .78;
  transition: opacity .2s ease;
}
.site-header.is-stuck .header-scene { opacity: 0; }

.wordmark { position: relative; z-index: 1; }

/* Below this the palms crowd the logo rather than framing it. */
@media (max-width: 52rem) {
  .header-scene { display: none; }
}

/*
 * The logo IS the name - "1MAC STUDIO" is drawn into it - so no text sits
 * beside it. Sized by height with width:auto, because it is a 2:1 lockup, not
 * an icon. A studio site carries exactly one piece of branding; this is the
 * thing people are meant to remember, so it is the one element allowed to be
 * larger than function demands.
 */
.wordmark {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}
.wordmark img {
  height: 6rem;
  width: auto;
  transition: height .2s ease;
}
.site-header.is-stuck .wordmark img { height: 3.25rem; }

@media (max-width: 46rem) {
  .site-header .container { padding-block: 1.5rem 1.15rem; }
  .wordmark img { height: 4rem; }
  .site-header.is-stuck .wordmark img { height: 2.5rem; }
}
@media (max-width: 30rem) {
  .site-header .container { padding-block: 1.25rem 1.1rem; }
  .wordmark img { height: 3rem; }
  .site-header.is-stuck .wordmark img { height: 2.25rem; }
}

@media (prefers-reduced-motion: reduce) {
  .site-header, .site-header .container, .wordmark img, .header-scene { transition: none; }
}



/* --------------------------------------------------------------------------
   Sections
   -------------------------------------------------------------------------- */
.section { padding-block: var(--space-section); }
.section + .section { border-top: 1px solid var(--line); }

/* Headline left, the line that qualifies it right - both using the full width.
   As one narrow centred column it left nearly half the band empty. */
.hero { padding-block: var(--space-masthead) 0; }
.hero h1 { max-width: 15ch; }
.hero .lead { margin-top: 1rem; max-width: 30rem; }

/*
 * The masthead shares its geometry with the About and app rows below it (and
 * with .split on the app pages) - same columns, same gap, and the same 3.5rem
 * inset on the right column. They had different track sizes and different
 * gaps, so the right column began at a different x in each row: a ~20px step
 * that the eye catches without being able to name it.
 *
 * Top-aligned, not bottom. With align-items:end the lead's LAST line sat level
 * with the headline's baseline, which pushed its first line well above the
 * headline's cap - the only row on the page not starting level with its
 * neighbour. The small margin is an optical nudge: the headline is three times
 * the size, so its cap sits closer to the top of its line box than the lead's
 * does to the top of hers.
 */
.masthead { display: grid; gap: 1.25rem; }
@media (min-width: 56rem) {
  .masthead {
    grid-template-columns: 1.1fr 1fr;
    gap: 3.5rem;
    align-items: start;
  }
  .masthead .lead {
    margin: .55rem 0 0;
    padding-left: 3.5rem;
  }
}

/* The hero already carries the space below it; without this the two paddings
   stack into a dead band the height of a small screen. */
.hero + .section { border-top: 0; }

.section-head { margin-bottom: 1.5rem; }
.section-head p { color: var(--muted); max-width: var(--prose); margin-top: .5rem; }

/*
 * Two columns side by side with a rule between them (the app pages' privacy and
 * price columns). stretch, not start: the divider has to run the full height of
 * the row, or it hangs off the taller column and reads as a stray line.
 */
.split { display: grid; gap: var(--space-section) 3.5rem; align-items: stretch; }
@media (min-width: 56rem) {
  .split { grid-template-columns: 1.1fr 1fr; }
  .split > * + * { border-left: 1px solid var(--line); padding-left: 3.5rem; }
}

/*
 * A heading people can read, not a 14px grey caption. These name the two halves
 * of the page, so they should look like the section titles they are - the
 * uppercase-micro-label habit makes the most structural text on the page the
 * hardest to read.
 */
.col-head {
  font-family: var(--font-display);
  /* Same reasoning as the tour headings above - a fixed 24px was a desktop
     size being reused, unchanged, on a phone. */
  font-size: clamp(1.25rem, 1.15rem + 0.5vw, 1.5rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  text-transform: none;
  color: var(--text);
  margin: 0 0 1.5rem;
  padding-bottom: .85rem;
  border-bottom: 1px solid var(--line);
}

/* --------------------------------------------------------------------------
   Buttons and links
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .8rem 1.4rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: var(--t-small);
  text-decoration: none;
  border: 1px solid transparent;
  transition: transform .12s ease, opacity .15s, border-color .15s;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--accent); color: var(--accent-ink); }
.btn-primary:hover { opacity: .9; }
.btn-ghost { border-color: var(--line); color: var(--text); }
.btn-ghost:hover { border-color: var(--muted); }
.btn[aria-disabled="true"] {
  background: var(--accent-bg);
  color: var(--accent);
  cursor: default;
  pointer-events: none;
}

.link {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
  border-bottom: 1px solid rgba(14, 124, 107, .35);
  padding-bottom: 1px;
}
.link:hover { border-bottom-color: var(--accent); }

.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.5rem; }

/* --------------------------------------------------------------------------
   Home page: About, then one row per app (rebuilt 2026-10-03)
   -------------------------------------------------------------------------- */
/*
 * About: one continuous paragraph across the row. A size up from body text, so
 * a line this wide (about 75 characters) still reads comfortably. It was two
 * columns for a while, and split like a newspaper it read oddly.
 */
.about {
  max-width: 52rem;
  margin: 0;
  font-size: var(--t-lead);
  line-height: 1.6;
  text-wrap: pretty;
}

/*
 * The two home page section labels (About, Apps): terracotta, with the same
 * hand-drawn stroke as the headline's highlighted phrase, so the page reads as
 * drawn by one hand. Only as wide as the word, so the stroke sits under it.
 */
.section-label {
  width: fit-content;
  color: var(--warm);
  border-bottom: 0;
  padding-bottom: .45em;
  margin-bottom: 1.25rem;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 12' preserveAspectRatio='none'%3E%3Cpath d='M2,8.5 Q30,3.2 60,6.6 T118,4.4' fill='none' stroke='%23B4532A' stroke-width='3.4' stroke-linecap='round' opacity='0.5'/%3E%3C/svg%3E")
              no-repeat 0 100% / 100% .32em;
}

.apps { margin-top: calc(var(--space-section) + 1.25rem); }
.apps-intro { color: var(--muted); margin: 0; }

/*
 * One full-width row per app: what it is on the left, a few of its screens on
 * the right, on the masthead's two tracks again. No card box - the rows sit on
 * the page with a hairline between them, so the list can grow one app at a
 * time without turning into a stack of boxes. A new app is one more
 * <article class="app-row">.
 */
.app-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem;
  padding-block: 2.5rem;
  border-top: 1px solid var(--line);
}
.apps-intro + .app-row { border-top: 0; }
.app-row:last-child { padding-bottom: 0; }
@media (min-width: 56rem) {
  .app-row {
    grid-template-columns: 1.1fr 1fr;
    gap: 3.5rem;
    align-items: center;
  }
  .app-row > :last-child { padding-left: 3.5rem; }
}

/* The left half is one link to the app's page. */
.app-info {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.25rem;
  align-items: start;
  text-decoration: none;
}
.app-info h3 {
  font-size: var(--t-h2);
  margin-bottom: .35rem;
  transition: color .15s;
}
.app-info:hover h3 { color: var(--accent); }

/* The app's own tagline, carried over from its About screen so the site and the
   app introduce it in the same words. Medium, not bold: the name above it
   already is, and two bold blocks stacked read as two competing headings. */
.app-tagline {
  margin-bottom: .7rem;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.45;
}
.app-desc {
  max-width: 30rem;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.65;
}
.status {
  display: inline-block;
  margin-top: .9rem;
  font-size: .875rem;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
}

/* Three screens as a peek. Capped in width, so on a tablet, where the row is
   one column, they stay a peek rather than three posters. */
.app-shots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .9rem;
  max-width: 30rem;
}
.app-shots img {
  width: 100%;
  border-radius: 14px;
  border: 1px solid var(--line);
}

/*
 * An app with no screenshots yet (DueTick, until its store images exist): name,
 * tagline and status on the left, the description where the screens would go.
 * On a phone it reads name, description, status, lined up with the name rather
 * than the icon (6.25rem = the icon plus its gap).
 */
.app-row.no-shots { align-items: start; row-gap: 1rem; }
.app-row.no-shots > .app-desc { margin: 0; padding-left: 6.25rem; }
.app-row.no-shots > .status { margin: 0 0 0 6.25rem; justify-self: start; }
@media (min-width: 56rem) {
  .app-row.no-shots {
    grid-template-areas: "info desc" "status desc";
    row-gap: .6rem;
  }
  .app-row.no-shots > .app-info { grid-area: info; }
  .app-row.no-shots > .app-desc { grid-area: desc; padding-left: 3.5rem; }
  /* padding 0 undoes the right-column inset (it is the row's last child);
     its margin already lines it up with the name. */
  .app-row.no-shots > .status { grid-area: status; padding-left: 0; }
}

/*
 * SVG, so it stays sharp at any size on any screen - the PNG was a 432px source
 * being shown at 80 and 112, which is fine today and soft the moment it is used
 * larger. Rounded at 22.5%, Android's own adaptive-icon corner, so it reads as
 * the icon the user will actually have on their home screen.
 *
 * Shown larger here than it is on a phone on purpose: a website is viewed from
 * arm's length rather than a foot away, so an icon at its phone size looks
 * noticeably smaller on the web than it does in a launcher.
 */
.app-icon { width: 5rem; height: 5rem; border-radius: 22.5%; flex: none; object-fit: cover; }
.app-icon-lg { width: 7rem; height: 7rem; }

/* --------------------------------------------------------------------------
   App page
   -------------------------------------------------------------------------- */
/*
 * Icon, name and tagline on the left; the description on the right. Identical
 * geometry to the home page's masthead - same tracks, same gap, same 3.5rem
 * inset on the right column - so the two pages line up rather than each finding
 * their own edges.
 */
/* minmax(0, 1fr), not the default auto track: an auto track grows to fit its
   widest unbreakable content, and the store buttons' two columns pushed the
   page past the edge of a 320px phone. */
.app-hero { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
.app-title-row { display: flex; align-items: center; gap: 1.25rem; }

@media (min-width: 56rem) {
  .app-hero {
    grid-template-columns: 1.1fr 1fr;
    gap: 3.5rem;
    align-items: start;
  }
  .app-hero-side { padding-left: 3.5rem; padding-top: .4rem; }
}

/*
 * The tour: one screenshot, one explanation, stacked down the page. The whole
 * page scrolls normally - an earlier version pinned each image with
 * position:sticky and it was the wrong call; a tour someone reads straight down
 * does not need the picture held in place while they do it.
 *
 * EVERYTHING HERE IS DERIVED FROM --tour-scale. The image, the heading, the body
 * and the spec rows all multiply off one number, so enlarging the tour keeps
 * their relationship to each other intact. Nudging four values by hand is how
 * the image ended up 15% bigger while the spec rows grew 21% and the body 10% -
 * each step correct on its own and the proportions quietly drifting.
 *
 * To make the whole tour bigger or smaller, change this one number.
 *
 * The images are LARGER than the phone they are pictures of, on purpose. A
 * laptop is viewed from much further away than a phone, and these screenshots
 * carry their own headline text - at anything smaller none of it can be read.
 *
 * Image on the left every time. It alternated before; a consistent side reads as
 * a list you can scan, an alternating one as a layout showing off.
 */
.walk {
  /* Layout only now - image width and column gap. It used to size the type too,
     which meant a heading sat at 32px on a 27" display and at 32px on a 320px
     phone. Fitting is not the same as being the right size: a phone is held at
     about 30cm and a laptop at about 60cm, so type that reads as a heading on
     the desk reads as shouting in the hand, and takes four lines to do it. */
  --tour-scale: 1.15;
  --tour-shot:  calc(26rem   * var(--tour-scale));
  --tour-gap:   calc(4.25rem * var(--tour-scale));

  /* Type scales with the viewport between a sensible floor and the old desktop
     size as the ceiling, so nothing got smaller on a large screen. The floors
     are the readable minimums: 24px headings, 17px body, 15px facts. */
  --tour-head:  clamp(1.5rem,    1.05rem + 1.6vw,  2.0125rem);
  --tour-body:  clamp(1.0625rem, 1rem    + 0.55vw, 1.3656rem);
  --tour-fact:  clamp(0.9375rem, 0.91rem + 0.2vw,  1.0781rem);
  --tour-kick:  clamp(0.8125rem, 0.79rem + 0.16vw, 0.9344rem);

  display: grid;
}

.walk-step {
  display: grid;
  gap: 1.75rem;
  padding-block: var(--space-section);
  border-top: 1px solid var(--line);
}
.walk-step:first-child { border-top: 0; padding-top: 0; }

@media (min-width: 60rem) {
  .walk-step {
    grid-template-columns: var(--tour-shot) 1fr;
    gap: var(--tour-gap);
    /* stretch, not center: the text column is a flex column whose last child
       (.walk-scene) is pushed down by margin-top:auto, so the words sit level
       with the top of the screenshot and the little drawing sits level with
       its bottom. Centring would collapse that space back again. */
    align-items: stretch;
    padding-block: calc(4.25rem * var(--tour-scale));
  }
  /* An img stretched by the grid would have its aspect ratio pulled out of
     shape - it opts out of the stretch above. */
  .walk-shot { align-self: start; }
}

.walk-text { display: flex; flex-direction: column; }

.walk-shot {
  width: 100%;
  max-width: var(--tour-shot);
  border-radius: calc(1.125rem * var(--tour-scale));
  /* No border or plate - these are finished marketing images with their own
     background. A frame around an already-framed image is a frame too many. */
}

/* h2, not h3: these five are the page's top-level sections, and jumping h1 -> h3
   leaves a hole a screen reader's heading list reads as a missing level. */
.walk-text h2 {
  margin-bottom: calc(0.75rem * var(--tour-scale));
  font-size: var(--tour-head);
  line-height: 1.15;
  letter-spacing: -0.025em;
}
.walk-text > p {
  color: var(--muted);
  max-width: 36rem;
  font-size: var(--tour-body);
  line-height: 1.65;
}
.walk-text .step-no {
  display: block;
  font-size: var(--tour-kick);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: calc(0.6rem * var(--tour-scale));
}

/*
 * The specifics, under the paragraph. The text column was three lines against a
 * 700px image, and the fix was never more prose - it was that each block said
 * what a feature IS without saying what you actually get. How many, which ones,
 * what is free: the things someone deciding whether to install wants to know.
 */
.walk-facts {
  list-style: none;
  margin: calc(1.5rem * var(--tour-scale)) 0 0;
  padding: 0;
  max-width: 36rem;
  border-top: 1px solid var(--line);
}
.walk-facts li {
  display: grid;
  grid-template-columns: calc(9rem * var(--tour-scale)) 1fr;
  gap: calc(1.25rem * var(--tour-scale));
  padding: calc(0.7rem * var(--tour-scale)) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--tour-fact);
  line-height: 1.55;
}
.walk-facts .k { color: var(--accent); font-weight: 700; }
.walk-facts .v { color: var(--muted); }

@media (max-width: 32rem) {
  .walk-facts li { grid-template-columns: 1fr; gap: .15rem; }
}

/* --------------------------------------------------------------------------
   Walkthrough doodles - one line drawing per step, sitting in the space the
   screenshot leaves below the text. Flat 3:1 PNGs on transparent, so they take
   the page background as-is; width/height on the <img> reserves the row before
   the file lands, which keeps the drawing from shoving the text as it loads.
   -------------------------------------------------------------------------- */
.walk-scene {
  margin-top: auto;                      /* pin to the bottom of the column */
  padding-top: calc(2.5rem * var(--tour-scale));
  width: 100%;
  max-width: 36rem;
}
.walk-scene img { display: block; width: 100%; height: auto; }

/* Below the two-column breakpoint the drawing follows the facts list instead
   of filling leftover height - it needs less air there. */
@media (max-width: 60rem) {
  .walk-scene { padding-top: calc(1.75rem * var(--tour-scale)); }
}

/* --------------------------------------------------------------------------
   Prose - about, and every legal page
   -------------------------------------------------------------------------- */
/* WCAG 2.2 SC 2.5.8 wants a 24x24 CSS px target. A link inside a sentence is
   exempt, because reflow makes its position unpredictable - but a link that is
   the only thing in its paragraph is not in a sentence, and an inline box around
   18px text is 23px tall. The padding buys the missing pixels without moving
   anything: inline-block keeps the underline and the flow identical. */
p > .link:only-child {
  display: inline-block;
  padding-block: .15rem;
}

.prose { max-width: var(--prose); }
.prose h2 { margin-top: 2.5rem; margin-bottom: .75rem; font-size: 1.375rem; }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: 1.9rem; margin-bottom: .5rem; font-size: 1.125rem; }
.prose ul { padding-left: 1.15rem; margin: 0 0 1.15em; }
.prose li { margin-bottom: .4em; }
.prose li::marker { color: var(--accent); }
.prose a { color: var(--accent); }

.doc-meta { font-size: var(--t-small); color: var(--muted); margin-top: 1rem; }

/* A quiet box for the one thing on a legal page worth reading first. */
.callout {
  font-size: 1.0625rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  background: var(--surface);
  border-radius: 10px;
  padding: 1.1rem 1.25rem;
  margin: 0 0 2rem;
  line-height: 1.65;
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--line);
  padding-block: 1.75rem 2.25rem;
  font-size: var(--t-small);
  color: var(--muted);
}
.site-footer .container {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 1.5rem;
  align-items: center;
  justify-content: space-between;
}
.site-footer nav { display: flex; flex-wrap: wrap; gap: 1.25rem; }
.site-footer a { text-decoration: none; }
.site-footer a:hover { color: var(--text); }

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

/* --------------------------------------------------------------------------
   Added with DueTick (2026-09-28)
   -------------------------------------------------------------------------- */
/*
 * A tour step with no screenshot yet: words and facts only. On a wide screen the
 * heading sits on the left and the detail on the right, so the page still reads
 * as a list of stops rather than one long column. Both halves are .walk-text, so
 * the step label, heading, paragraph and fact rows keep their usual styles.
 */
.walk-step.no-shot { grid-template-columns: 1fr; }
@media (min-width: 60rem) {
  .walk-step.no-shot { grid-template-columns: minmax(0, 22rem) 1fr; align-items: start; }
}
/* Legal pages: a numbered list, and a list inside the short-version box. */
.prose ol { padding-left: 1.35rem; margin: 0 0 1.15em; }
.callout > p:first-child { margin-bottom: .5rem; }
.callout ul { margin-bottom: .75rem; }

/* --------------------------------------------------------------------------
   Added with the Classic Randomizers launch (2026-10-03)
   -------------------------------------------------------------------------- */
/* Anything marked hidden stays hidden, even where a rule above gives it a
   display value (the home card's offer tag is display:block). The launch
   offers depend on this. */
[hidden] { display: none !important; }

/*
 * The two store buttons, laid out like the stores' own badges: a small line,
 * then the store's name. In one line each ("Download on the App Store") the
 * pair was too wide for the hero column and broke onto two rows; this way they
 * sit side by side on a laptop and on a phone.
 */
.btn-store {
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  padding: .5rem 1.35rem .55rem;
  font-size: 1.0625rem;
  line-height: 1.25;
}
.btn-kick { font-size: .75rem; font-weight: 500; opacity: .88; }

/*
 * The stores side by side, each with its own launch offer directly under its
 * button, so the offer reads as part of the choice rather than a separate box
 * to work out. Quiet on purpose: small text, the end date in plain words, no
 * countdown. offers.js decides whether a note shows at all.
 */
.stores {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 1.25rem;
  max-width: 23rem;
}
/* Each button fills its column, so the pair stays an even, tidy row once the
   offers have gone and only the buttons are left. */
.store .btn-store { width: 100%; align-items: center; text-align: center; }
.store-note {
  margin: .8rem 0 0;
  font-size: .875rem;
  line-height: 1.5;
  color: var(--muted);
}
.store-note strong {
  display: block;
  width: fit-content;
  margin-bottom: .4rem;
  padding: .05rem .5rem;
  border-radius: 6px;
  background: var(--warm-bg);
  color: var(--warm-ink);
  font-size: .8125rem;
}

/*
 * An app page with store buttons: name and buttons on the left, description on
 * the right. Under the description, the buttons left the whole left column
 * empty below the name. On a phone the order stays name, description, buttons.
 */
@media (min-width: 56rem) {
  .app-hero.has-stores {
    grid-template-areas: "name side" "stores side";
    row-gap: 2rem;
  }
  .app-hero.has-stores > :first-child { grid-area: name; }
  .app-hero.has-stores > .app-hero-side { grid-area: side; }
  .app-hero.has-stores > .stores { grid-area: stores; }
}

/* The home page's pointer to that offer: a small tag above the app's status
   line, only as wide as its words. Square-ish corners, so it doesn't read as a
   button (buttons here are fully rounded). */
.offer-tag {
  display: block;
  width: fit-content;
  margin-top: .8rem;
  padding: .1rem .55rem;
  border-radius: 6px;
  background: var(--warm-bg);
  color: var(--warm-ink);
  font-size: .8125rem;
  font-weight: 600;
  line-height: 1.7;
}
.offer-tag + .status { margin-top: .5rem; }
