/* Self-hosted, latin subset only. Pulled from Google Fonts once and
   committed, so the site makes no third-party request and nothing
   render-blocks on another origin. */
@font-face {
  font-family: 'Archivo Black';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/archivo-black-400-e6dca12e.woff2") format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/ibm-plex-mono-400-d13bb5b4.woff2") format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/ibm-plex-mono-600-0fdd541f.woff2") format('woff2');
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/ibm-plex-sans-400-578a0041.woff2") format('woff2');
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/ibm-plex-sans-500-578a0041.woff2") format('woff2');
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/ibm-plex-sans-600-578a0041.woff2") format('woff2');
}

/* The site's whole look. Hand-written: it is one page, and a framework
   would be more code than the page. */

:root{
    --ground:#0B0D14; --surface:#141826; --surface-2:#1B2133;
    --line:#313A54; --line-strong:#556289;
    --ink:#F2F4F8; --muted:#8A93A8; --faint:#8089A0;
    --red:#ED4D54; --blue:#3366EB; --yellow:#FACC38; --cyan:#5CDBF0; --green:#5CE0A0;
    --display:"Archivo Black","Helvetica Neue",Arial,sans-serif;
    --body:"IBM Plex Sans","Helvetica Neue",Arial,sans-serif;
    --mono:"IBM Plex Mono",ui-monospace,Menlo,monospace;
    --gutter:clamp(20px,5vw,64px);
  }
  *{box-sizing:border-box}
  body{
    margin:0; background:var(--ground); color:var(--ink);
    font-family:var(--body); font-size:17px; line-height:1.6;
    -webkit-font-smoothing:antialiased;
  }
  .wrap{max-width:1080px; margin:0 auto; padding-inline:var(--gutter)}
  h1,h2,h3{font-family:var(--display); font-weight:400; text-wrap:balance; margin:0}
  p{margin:0}
  a{color:inherit}

  .eyebrow{
    font-family:var(--mono); font-size:12px; font-weight:600;
    letter-spacing:.16em; text-transform:uppercase; color:var(--cyan);
  }

  /* ---------- coming-soon banner ---------- */
  /* Sits above the hero, centred, and says the one thing a first-time
     visitor needs to know before they look for a download button. */
  .soon-wrap{ display:flex; justify-content:center; padding:22px 20px 0 }

  /* Its own row, sharing the page's gutter and max width, so the button's left
     edge lands on the same line as the eyebrow and the wordmark beneath it. */
  /* The invite on the text column's left edge, the language picker hard right.
     One row, so neither needs a row of its own. */
  .tell-row{
    display:flex; align-items:center; justify-content:space-between; gap:12px;
    max-width:1080px; margin:0 auto; padding:18px var(--gutter) 0;
  }

  .tell{
    display:inline-flex; align-items:center; gap:7px;
    padding:9px 16px; border-radius:999px; cursor:pointer;
    background:transparent; color:var(--cyan);
    border:1px solid rgba(92,219,240,.38);
    font-family:var(--body); font-weight:600; font-size:13.5px;
    white-space:nowrap;
    transition:border-color .16s ease, background .16s ease;
  }
  .tell:hover{ border-color:var(--cyan); background:rgba(92,219,240,.08) }
  .tell:focus-visible{ outline:2px solid var(--cyan); outline-offset:3px }
  /* The confirmation replaces the label, so nothing moves and nothing is
     announced twice. */
  .tell[data-said="1"]{ color:var(--ink); border-color:var(--line-strong) }
  .tell-heart{ width:14px; height:14px; fill:currentColor; flex:none }

  .soon{
    /* Short enough for one line on any screen, so it is a pill again. The
       text lives in its own span rather than as loose flex children, and
       min-width:0 stops a flex item pushing past its own max-width. */
    display:inline-flex; align-items:center; gap:9px;
    box-sizing:border-box; min-width:0; max-width:100%;
    padding:8px 16px; border-radius:999px;
    background:rgba(92,219,240,.07); border:1px solid rgba(92,219,240,.28);
    color:var(--cyan); text-decoration:none;
    font-family:var(--mono); font-size:12.5px; font-weight:600;
    letter-spacing:.04em;
  }
  .soon:hover{ background:rgba(92,219,240,.13); border-color:rgba(92,219,240,.5) }
  .soon:focus-visible{ outline:2px solid var(--cyan); outline-offset:3px }
  /* The store name, not the brand — it is what a visitor has to type into a
     store search box, and the two differ. */
  .soon strong{ color:var(--ink); font-weight:600 }
  .soon-dot{
    flex:none;
    width:7px; height:7px; border-radius:50%; background:var(--cyan);
    box-shadow:0 0 0 0 rgba(92,219,240,.6);
    animation:soon-pulse 2.4s ease-out infinite;
  }
  @keyframes soon-pulse{
    70%{ box-shadow:0 0 0 7px rgba(92,219,240,0) }
    100%{ box-shadow:0 0 0 0 rgba(92,219,240,0) }
  }
  @media(prefers-reduced-motion:reduce){ .soon-dot{ animation:none } }

  /* ---------- hero ---------- */
  header{padding:clamp(48px,9vw,104px) 0 clamp(56px,8vw,96px)}
  .hero{display:grid; gap:clamp(40px,6vw,72px); align-items:center}
  /* minmax(0,1fr) lets the text column shrink below the wordmark's
     min-content width rather than forcing the row wider than the page, and the
     board column is fluid rather than fixed. Between about 900px and 1030px
     the old rule scrolled the page horizontally. */
  /* DOCKIT is one word and must never break. It is a single unbreakable
     token about 3.85x its font-size wide, so the two-column layout has to size
     it against the column it lives in rather than the whole viewport — at 13vw
     beside a fixed 400px board it was wider than the track it was given, which
     scrolled the page sideways from roughly 900px to 1030px. */
  @media(min-width:900px){
    .hero{ grid-template-columns:minmax(0,1fr) minmax(260px,380px) }
    .wordmark{ font-size:clamp(50px, 7.6vw, 100px) }
  }
  .wordmark{ white-space:nowrap }

  .wordmark{
    font-family:var(--display); font-size:clamp(56px,11.4vw,116px);
    line-height:.86; letter-spacing:-.035em; margin:14px 0 0;
  }
  .tagline{
    font-family:var(--mono); font-weight:600; color:var(--cyan);
    font-size:clamp(14px,2.4vw,19px); letter-spacing:.02em; margin-top:18px;
  }
  .pitch{color:var(--muted); max-width:44ch; margin-top:22px; font-size:1.05rem}
  .pitch strong{color:var(--ink); font-weight:600}

  .cta{display:flex; flex-wrap:wrap; gap:12px; align-items:center; margin-top:34px}
  .btn{
    font-family:var(--body); font-weight:600; font-size:15px;
    padding:13px 22px; border-radius:999px; text-decoration:none;
    background:var(--cyan); color:#06202A; border:1px solid transparent;
    transition:transform .16s ease, filter .16s ease;
  }
  .btn:hover{transform:translateY(-2px); filter:brightness(1.06)}
  .btn.ghost{background:transparent; color:var(--ink); border-color:var(--line)}
  .btn.ghost:hover{border-color:var(--cyan); color:var(--cyan)}
  .btn:focus-visible{outline:2px solid var(--cyan); outline-offset:3px}

  /* ---------- the board ---------- */
  /* The square lives on .grid, not on .stage. With aspect-ratio on the stage
     and height:100% on the grid, Safari resolved that percentage against the
     stage's full height rather than its content box, so the grid stood 44px
     taller than the room inside the padding and overflow:hidden ate the last
     row. Sizing the grid itself and letting the stage wrap it needs no
     percentage height at all. The padding is a length for the same reason:
     a percentage resolves against the *containing block's* width, which at
     768px is the whole hero column, not the 400px board. */
  .stage{
    position:relative; width:100%; max-width:400px; margin-inline:auto;
    background:var(--surface); border:1px solid var(--line);
    border-radius:26px; padding:22px; overflow:hidden;
  }
  .grid{position:relative; width:100%; aspect-ratio:1}
  .cell{
    position:absolute; border-radius:16%;
    background:var(--surface-2); border:1px solid #222941;
  }
  .tile{
    position:absolute; border-radius:16%;
    display:grid; place-items:center;
    transition:transform .34s cubic-bezier(.22,.9,.3,1), opacity .22s ease;
    will-change:transform;
  }
  .tile svg{width:68%; height:68%; overflow:visible}
  .tile.pop{animation:pop .42s ease forwards}
  @keyframes pop{
    35%{transform:scale(1.16)}
    100%{transform:scale(.2); opacity:0}
  }

  /* ---------- today: the day as a shape ---------- */
  /* The distribution is bars rather than a chart library: ten rows of two divs
     weigh nothing and read the same in every browser. */
  @media(min-width:680px){ .figures.three{grid-template-columns:repeat(3,1fr)} }
  .dist{margin-top:34px; display:flex; flex-direction:column; gap:7px}
  .bar-row{display:grid; grid-template-columns:64px 1fr 44px; gap:12px; align-items:center}
  .bar-label{font-family:var(--mono); font-size:12px; color:var(--faint); text-align:right}
  .bar-track{background:var(--surface); border:1px solid var(--line); border-radius:6px; height:22px}
  .bar-fill{background:var(--cyan); height:100%; border-radius:5px; min-width:2px}
  .bar-count{font-family:var(--mono); font-size:12px; color:var(--muted)}
  .daily-link{margin-top:18px}
  .daily-link a{color:var(--cyan); text-decoration:none; font-weight:600}
  .daily-link a:hover{text-decoration:underline}
  .empty{color:var(--muted); margin-top:30px; font-size:1.05rem}
  .today-note{color:var(--faint); font-size:13.5px; margin-top:34px}
  .today-note a{color:var(--cyan); text-decoration:none}
  .today-note a:hover{text-decoration:underline}

  /* ---------- sections ---------- */
  section{padding:clamp(48px,7vw,84px) 0; border-top:1px solid var(--line)}
  .head{max-width:56ch}
  .head h2{font-size:clamp(26px,4.4vw,38px); letter-spacing:-.02em; margin-top:12px}
  .head p{color:var(--muted); margin-top:14px}

  .steps{display:grid; gap:20px; margin-top:38px}
  @media(min-width:760px){ .steps{grid-template-columns:repeat(3,1fr)} }
  .step{background:var(--surface); border:1px solid var(--line); border-radius:18px; padding:24px}
  .step .n{
    font-family:var(--mono); font-size:12px; font-weight:600; color:var(--cyan);
    letter-spacing:.14em;
  }
  .step h3{font-size:18px; margin-top:12px; letter-spacing:-.01em}
  .step p{color:var(--muted); font-size:15px; margin-top:8px}

  /* rule examples */
  .examples{display:grid; gap:18px; margin-top:36px}
  @media(min-width:760px){ .examples{grid-template-columns:1fr 1fr} }
  .example{
    background:var(--surface); border:1px solid var(--line);
    border-radius:18px; padding:22px;
  }
  .example.good{border-color:rgba(92,224,160,.35)}
  .example.bad{border-color:rgba(237,77,84,.32)}
  .trio{display:flex; gap:10px; margin:4px 0 16px}
  .trio .tile{position:static; width:64px; height:64px; flex:0 0 auto}
  .verdict{font-family:var(--mono); font-size:13px; font-weight:600}
  .good .verdict{color:var(--green)}
  .bad .verdict{color:var(--red)}
  .example p{color:var(--muted); font-size:14.5px; margin-top:8px}

  /* attribute legend */
  .attrs{display:grid; gap:14px; margin-top:34px}
  @media(min-width:680px){ .attrs{grid-template-columns:repeat(4,1fr)} }
  .attr{
    background:var(--surface); border:1px solid var(--line);
    border-radius:16px; padding:18px;
  }
  .attr .k{font-family:var(--mono); font-size:11px; letter-spacing:.14em; color:var(--faint); text-transform:uppercase}
  .attr .v{font-family:var(--display); font-size:19px; margin-top:8px; letter-spacing:-.01em}
  .attr p{color:var(--muted); font-size:13.5px; margin-top:6px}
  .attr.locked{border-style:dashed}
  .attr.locked .v{color:var(--cyan)}

  /* figures */
  .figures{display:grid; gap:1px; margin-top:36px; background:var(--line);
           border:1px solid var(--line); border-radius:18px; overflow:hidden}
  @media(min-width:680px){ .figures{grid-template-columns:repeat(4,1fr)} }
  .fig{background:var(--surface); padding:22px}
  .fig .big{
    font-family:var(--mono); font-weight:600; font-size:clamp(24px,3.6vw,32px);
    letter-spacing:-.02em; font-variant-numeric:tabular-nums; color:var(--ink);
  }
  .fig .lab{color:var(--muted); font-size:13.5px; margin-top:6px}

  /* One line of legal text, so it gets one line's worth of room. The 40/60
     it had made it read as a section rather than a rule under the page. */
  footer{border-top:1px solid var(--line); padding:14px 0; color:var(--faint); font-size:13.5px}
  /* Three items across one row while they fit. When they do not, they wrap
     centred rather than spread: space-between leaves the last item alone and
     left-aligned on its own line, which reads as a mistake rather than a
     layout. Centring costs nothing at full width — with three items and
     space-between the outer two already sit on the edges. */
  footer .footer-row{
    display:flex; flex-wrap:wrap; align-items:center;
    justify-content:space-between; gap:10px 24px;
    text-align:center;
  }
  /* Below 700px the three genuinely cannot share a line — flex was keeping
     two on one row and letting the copyright run off the edge rather than
     wrapping it. Stacked and centred is the honest answer at that width. */
  @media(max-width:700px){
    footer .footer-row{ flex-direction:column; justify-content:center; gap:8px }
  }
  footer p{ margin:0 }
  footer .footer-strong{ color:var(--muted); font-weight:500 }
  footer .footer-swiss{ display:inline-flex; align-items:center; gap:8px }

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

/* ── Document pages (privacy, support) ─────────────────────────────────────
   Same type and colour as the rest of the site, set for reading rather than
   for a hero. */
.doc { max-width: 46rem; margin: 0 auto; padding: 5rem 1.5rem 6rem; }

/* A row of its own above the heading, sharing the text column's left edge so
   the arrow lines up with the prose rather than sitting off on its own. */
.back-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 0 0 1.6rem;
}
.back {
  display: inline-flex; align-items: center; gap: .5rem;
  color: var(--cyan); text-decoration: none;
  font-size: .9rem; font-weight: 600;
}
.back:hover { text-decoration: underline }
.back:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px }
.doc h1 { font-size: clamp(2rem, 6vw, 3rem); margin: 0 0 .35em; }
.doc h2 { margin: 2.4em 0 .5em; font-size: 1.15rem; }
.doc p, .doc li { line-height: 1.65; }
.doc ul { padding-left: 1.2rem; }
.doc a { color: inherit; }
.stamp { font-family: "IBM Plex Mono", monospace; font-size: .8rem; opacity: .55; }

/* ── Download ──────────────────────────────────────────────────────────────
   Two tiles, side by side and equal: neither platform is the afterthought.
   A store that is not live yet renders dimmed and unlinked rather than being
   hidden, so the page reads as "both are coming" rather than "iPhone only". */
.stores{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(15rem, 1fr));
  gap:1rem; margin:2.5rem 0 1.75rem;
}
.store{
  display:flex; align-items:center; gap:1rem;
  padding:1.1rem 1.4rem; border:1px solid var(--line); border-radius:14px;
  text-decoration:none; color:var(--ink); background:rgba(255,255,255,.02);
  transition:border-color .18s ease, transform .18s ease, background .18s ease;
}
a.store:hover{
  border-color:var(--cyan); background:rgba(255,255,255,.05);
  transform:translateY(-2px);
}
a.store:focus-visible{ outline:2px solid var(--cyan); outline-offset:3px }
/* Not opacity. Fading the whole tile took the platform line to 1.6:1,
   which is unreadable — and this is the state every visitor sees until the
   apps are live. It reads as pending through a dashed border instead. */
.store.soon{ cursor:default; border-style:dashed; background:transparent }
.store-glyph{ display:flex; align-items:center; color:var(--ink) }
.store-text{ display:flex; flex-direction:column; gap:.1rem }
.store-lead{ font-size:.72rem; letter-spacing:.04em; text-transform:uppercase; color:var(--muted) }
.store-name{ font-size:1.15rem; font-weight:600 }
.store-plat{ font-family:"IBM Plex Mono", monospace; font-size:.72rem; color:var(--faint) }
/* The two tiers, side by side. Structure rather than a sentence: the prose
   above already states the shape, and saying it twice read as a fragment. */
.tiers{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(15rem, 1fr));
  gap:1rem;
}
.tier{
  padding:1.25rem 1.4rem; border:1px solid var(--line); border-radius:14px;
  background:rgba(255,255,255,.015);
}
.tier-pro{ border-color:#2E3A5C }
.tier-name{
  display:flex; align-items:baseline; justify-content:space-between; gap:.6rem;
  font-weight:600; font-size:.95rem; margin-bottom:.7rem;
  color:var(--ink);
}
/* The price sits on the tier's own line rather than in the list: it is what
   the tier costs, not another thing the tier gives you. */
.tier-price{
  font-weight:400; font-size:.78rem; color:var(--faint);
  letter-spacing:.01em; white-space:nowrap;
}
.tier-pro .tier-price{ color:var(--muted) }
.tier-pro .tier-name{ color:var(--cyan) }
.tier ul{ margin:0; padding:0; list-style:none; display:grid; gap:.42rem }
.tier li{
  color:var(--muted); font-size:.9rem; line-height:1.45;
  padding-left:1.1rem; position:relative;
}
.tier li::before{
  content:"·"; position:absolute; left:.25rem; color:var(--faint);
}

  /* The ghost button's border is its only affordance, so it gets the token
     that actually clears 3:1 rather than the subtle one the cards use. */
  .btn.ghost{ border-color:var(--line-strong) }

  /* A skip link: the home page is one long column and the first thing in it
     is a banner. Off-screen until focused. */
  .skip{
    position:absolute; left:-9999px; top:0; z-index:50;
    background:var(--cyan); color:#06202A; padding:10px 16px;
    border-radius:0 0 10px 0; font-weight:600; text-decoration:none;
  }
  .skip:focus{ left:0 }

  /* Focus was styled for buttons and store tiles but not for prose or footer
     links, which fell back to the UA ring and looked like a different site. */
  .doc a:focus-visible, footer a:focus-visible{
    outline:2px solid var(--cyan); outline-offset:3px; border-radius:2px;
  }
  .doc a{ color:var(--cyan); text-decoration-color:rgba(92,219,240,.45) }
  footer a{ color:var(--muted) }
  footer a:hover{ color:var(--ink) }
  footer .footer-links{ display:flex; gap:16px }

  /* The two words the sentence turns on, in the same cyan as the section
     eyebrow above it — so "free" and "Pro" read as the two tiers rather than
     as emphasis. */
  .tier-word{ color:var(--cyan); font-weight:600 }

  /* The language picker. A disclosure so sixteen links do not sit in the
     footer permanently, and a plain list inside so it works with scripting
     off and a crawler can follow every one of them. */
  .langs{ position:relative; font-size:15px }
  .langs summary{
    cursor:pointer; color:var(--muted); list-style:none;
    padding:4px 2px; border-bottom:1px dotted var(--line-strong);
  }
  .langs summary::-webkit-details-marker{ display:none }
  .langs summary:hover{ color:var(--cyan) }
  .langs[open] summary{ color:var(--cyan) }
  /* Downward and right-aligned. It used to open upward, from the footer; at
     the top of the page that put it off the screen entirely. Right-anchored
     because it now sits against the right edge, where a centred panel would
     hang past it. */
  .langs ul{
    position:absolute; top:calc(100% + 8px); right:0;
    z-index:20; margin:0; padding:8px; list-style:none;
    /* max-content, not 1fr: the panel is absolutely positioned, so it has no
       width for fractions to divide and the two columns collapsed on top of
       each other. It sizes to the longest language name instead. */
    width:max-content;
    display:grid; grid-template-columns:repeat(2, max-content); gap:2px 18px;
    background:var(--panel, #12151F); border:1px solid var(--line-strong);
    border-radius:12px; white-space:nowrap;
    box-shadow:0 12px 30px rgba(0,0,0,.45);
  }
  .langs a{ color:var(--muted); text-decoration:none; padding:5px 8px; display:block }
  /* On a narrow screen a two-column panel anchored right still fits, but the
     row above it wraps — keep the panel inside the viewport either way. */
  @media (max-width:520px){
    .langs ul{ grid-template-columns:1fr; max-height:60vh; overflow-y:auto }
  }
  .langs a:hover{ color:var(--cyan) }
  .langs [aria-current]{ color:var(--ink); padding:5px 8px; display:block }
