/* Hello by X24, the public site (2026-10-24 rollout of direction "sign"). Built only from tokens.css.
   The page is one journey, top to bottom: hear it, see what you get, trust it, start. */

/* ================= Base ================= */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--c-bg); color: var(--c-text);
  font: 400 var(--t-md)/var(--lh-body) var(--font-text); -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-underline-offset: 3px; }
:focus-visible { outline: 3px solid var(--c-focus); outline-offset: 2px; }
h1, h2, h3, p { margin: 0; }
.wrap { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 var(--gutter); }
.skip { position: absolute; left: var(--s-2); top: -100px; padding: var(--s-2) var(--s-3); background: var(--c-btn);
  color: var(--c-on-btn); z-index: 10; }
.skip:focus { top: var(--s-2); }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; }
.nowrap { white-space: nowrap; }

/* Charlie's line goes live with one change: data-charlie-live on <html> (index.html). He was Brad until 2026-10-24,
   renamed after his approved voice, ElevenLabs Charlie;
   only his number is still pending. Until then everything of his,
   and every sentence that names both of them, stays out of the page, for screen readers too. */
html[data-charlie-live="false"] .charlie-only { display: none !important; }
html[data-charlie-live="true"] .jess-only { display: none !important; }
/* The urgent-text line: data-sms-default on <html> picks the one that is true (index.html). */
html:not([data-sms-default="true"]) .sms-default { display: none !important; }
html[data-sms-default="true"] .sms-optin { display: none !important; }
/* Sentences carrying the person number (app.js TALK_E164) show only once it has been filled in. */
html:not(.talk-ready) .talk { display: none !important; }

/* Display type */
.d-hero, .d-1, .d-2 {
  font-family: var(--font-display); font-weight: 900; line-height: var(--lh-tight);
  letter-spacing: 0.005em; text-wrap: balance;
}
.d-hero { font-size: var(--t-3xl); line-height: 1.07; }  /* gate round 1: at 0.92 the g of "get" sat on the h of "phone" */
.d-1 { font-size: var(--t-2xl); }
.d-2 { font-size: var(--t-xl); font-weight: 800; line-height: 1; }
.lead { font-size: var(--t-lg); font-weight: 400; line-height: 1.4; max-width: var(--measure); }
.sub { font-size: var(--t-md); font-weight: 500; line-height: 1.45; max-width: var(--measure); }
.muted { color: var(--c-muted); }
.fine { font-size: var(--t-xs); color: var(--c-muted); }

/* ================= Components ================= */

/* Primary button: an enamel plate, square. Ink for everything, red only when it rings someone. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: var(--tap); padding: 0 var(--s-5); border: 0; border-radius: var(--radius);
  background: var(--c-btn); color: var(--c-on-btn);
  font: 700 var(--t-md)/1 var(--font-text); letter-spacing: 0.01em; text-decoration: none;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.btn:hover { background: var(--c-btn-press); }
.btn:active { transform: translateY(1px); }
.btn--ring { background: var(--c-ring); color: var(--c-on-ring); }
.btn--ring:hover { background: var(--c-ring-press); }
.btn--block { display: flex; width: 100%; }
.btn svg { width: 20px; height: 20px; flex: none; }

/* Secondary: a text link with a brush-weight underline. */
.link {
  color: var(--c-text); font-weight: 600; text-decoration: underline; text-decoration-thickness: 2px;
  text-underline-offset: 4px; display: inline-flex; align-items: center; min-height: 44px;
}
.link:hover { text-decoration-thickness: 3px; }
.link--quiet { font-weight: 500; text-decoration-color: var(--c-rule); }
/* Gate round 4 (UX): in the header, Sign up is the new visitor's way in, so it carries the weight and a full ink
   underline; Sign in is a returning client's, quiet and muted. */
.link--signup { font-weight: 700; text-decoration-thickness: 3px; }
.top .link--quiet { color: var(--c-muted); text-decoration: none; }
.top .link--quiet:hover { text-decoration: underline; }

/* Inputs: a 2 px brush border. Gate round 4 (design critic): error and focus never look alike. An error is a
   3 px signal-red border in both modes, with the words under it in the same red, led by the "!" plate (UX
   critic: mark and message read as one). The type in the box stays ink. Focus is separate: an outline 2 px
   outside the box, ink in light (gold on white is 1.9:1) and gold after dark. */
.field { display: grid; gap: var(--s-2); margin: 0; scroll-margin-top: var(--s-6); }
.field > span:first-child { font: 600 var(--t-sm)/1.2 var(--font-text); }
.field small { font-size: var(--t-xs); color: var(--c-muted); }
.box { position: relative; display: block; }
.input {
  width: 100%; min-height: var(--tap); padding: 0 var(--s-4);
  border: var(--border) solid var(--c-text); border-radius: var(--radius);
  background: var(--c-bg); color: var(--c-text); font: 500 1.125rem/1 var(--font-text); appearance: none;
}
.input:focus { outline: 3px solid var(--c-focus); outline-offset: 2px; }
.field--error .input { border: 3px solid var(--c-error); padding-left: calc(var(--s-4) - 1px); }
.bang {
  display: inline-grid; flex: none; width: 20px; height: 20px; margin-top: 1px; place-items: center;
  background: var(--c-error); color: var(--c-on-error); font: 800 0.8125rem/1 var(--font-text); font-style: normal;
}
.field__error { display: none; gap: var(--s-2); align-items: start; color: var(--c-error);
  font: 600 var(--t-sm)/1.35 var(--font-text); }
.field--error .field__error { display: flex; }
.field__error [data-empty], .field__error [data-bad] { display: none; }
.field__error [data-premium] { display: none; }
[data-why="empty"] .field__error [data-empty], [data-why="bad"] .field__error [data-bad],
[data-why="premium"] .field__error [data-premium] { display: inline; }
/* Gate round 3: while the error shows, the hint goes, so there's one message under the label, not two. */
.field--error small { display: none; }

/* The plate: a black sign panel, square, with a gold keyline set in from the edge. An outline on a square box
   mitres its own corners, so the keyline turns each corner on a clean 45. */
.plate {
  background: var(--c-panel); color: var(--c-on-panel); border-radius: var(--radius);
  outline: var(--rule) solid var(--c-trim); outline-offset: calc(-1 * var(--keyline));
}

/* On air: black and gold, never red. The lamp keeps the Australian double ring, 400 on, 200 off, 400 on, then
   2 seconds off, 3 s in all. Motion only: with reduced motion it just stays lit. */
.onair {
  display: inline-flex; align-items: center; gap: var(--s-2); padding: 5px 9px 4px;
  background: var(--sign-black); color: var(--gold-leaf); font: 700 var(--t-xs)/1.1 var(--font-text);
  outline: var(--rule) solid var(--gold-leaf); outline-offset: -3px; white-space: nowrap;
}
.onair i { width: 8px; height: 8px; background: var(--gold-leaf); animation: ring 3s infinite; }
@keyframes ring {
  0%, 13.3% { opacity: 1; }
  13.34%, 19.99% { opacity: 0.18; }
  20%, 33.3% { opacity: 1; }
  33.34%, 100% { opacity: 0.18; }
}

/* ================= Header ================= */
.top { display: flex; align-items: center; gap: var(--s-4); min-height: 72px; }
.top .home { margin-right: auto; display: block; padding: var(--s-2) 0; }
.wm { display: block; height: 40px; width: auto; }
.top .link { font-size: var(--t-sm); min-height: 44px; padding: 0 2px; }  /* gate round 3: a 44 px tap target */

section { scroll-margin-top: var(--s-5); }

/* ================= 1. Hear it ================= */
.hear { padding: var(--s-4) 0 var(--s-8); display: grid; gap: var(--s-6); }
.start .lead { margin-top: var(--s-5); color: var(--c-muted); }
.hear .lead { margin-top: var(--s-5); }
.hear .sub { margin-top: var(--s-3); color: var(--c-muted); }
.hear__price { margin-top: var(--s-1); font: 600 var(--t-md)/1.45 var(--font-text); }
.contacts { display: grid; gap: var(--s-4); }
.contact {
  border: var(--border) solid var(--c-text); outline: var(--rule) solid var(--c-card-rule); outline-offset: -7px;
  padding: var(--s-5) var(--s-5) var(--s-5); display: grid; gap: var(--s-4);
}
/* Gate round 4: "On air" sits on the name's baseline, 10 px after it (it floated 16 px off at 375). */
.contact__head { display: flex; align-items: baseline; gap: 10px; }
/* Round 5 (design): on the baseline the box still read low against the tall name; up 3 px it sits on the x-height. */
.contact__head .onair { position: relative; top: -3px; }
.contact__name { font: 900 3rem/0.9 var(--font-display); }
/* Gate round 3: the number in Big Shoulders at about 40 px on every width, so it reads as the thing to ring. */
.contact__num {
  font: 900 2.5rem/1 var(--font-display); font-variant-numeric: tabular-nums; letter-spacing: 0.01em;
  white-space: nowrap; text-decoration: none; justify-self: start;
}
.contact__qr { display: none; }

/* ================= 2. See what you get ================= */
.see { padding: var(--s-7) 0 var(--s-8); border-top: var(--rule-heavy) solid var(--c-text); display: grid;
  gap: var(--s-6); align-items: start; }
.see .lead { margin-top: var(--s-4); color: var(--c-muted); }
.see .sub { margin-top: var(--s-4); color: var(--c-muted); }
/* Gate round 4: the picture is inert (UX critic: "Ring Priya back" looked tappable), and "Example" sits on its top
   edge. Above the crop, the inbox row the email arrives as: small wordmark, sender, time, subject. */
.crop { position: relative; margin: 0; width: 100%; max-width: 380px; pointer-events: none; user-select: none;
  -webkit-user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent;
  border-top: var(--rule) solid var(--c-rule); padding-top: var(--s-4); }
.crop figcaption { position: absolute; top: -11px; right: 0; padding: 2px 7px 1px; background: var(--c-bg);
  border: var(--rule) solid var(--c-rule); font: 600 var(--t-xs)/1.4 var(--font-text); color: var(--c-muted); }
.mailrow { display: grid; grid-template-columns: auto 1fr auto; column-gap: var(--s-3); row-gap: 2px;
  align-items: center; padding: 0 0 var(--s-3); border-bottom: var(--rule) solid var(--c-rule); }
.mailrow .wm { width: 56px; height: auto; grid-row: 1 / span 2; }
.mailrow__from { font: 700 var(--t-sm)/1.3 var(--font-text); }
.mailrow__time { font: 500 var(--t-xs)/1.3 var(--font-text); color: var(--c-muted); font-variant-numeric: tabular-nums; }
.mailrow__subj { grid-column: 2 / -1; font: 500 var(--t-xs)/1.35 var(--font-text); color: var(--c-muted); }
/* No frame (gate round 3): the email's own edges are enough. Round 5 (UX): the picture's colour is muted, so its
   red "Ring Priya back" reads as part of a picture, not a button; the words keep their contrast. */
.crop picture { display: block; filter: saturate(0.45); }
.crop img { width: 100%; height: auto; }
.crop--wide { display: none; }

/* ================= 3. Trust it ================= */
.trust { padding-bottom: var(--s-8); }
/* Gate round 4 (design critic, 375): one spacing step between blocks in the panel, 32 px either side of each
   gold rule, and nothing trailing after the fine print. */
.trust .plate { padding: var(--s-7) var(--s-5) var(--s-6); display: grid; gap: var(--s-6); }
.price__line { font: 900 var(--t-2xl)/1 var(--font-display); text-wrap: balance; }
.price p + p { margin-top: var(--s-3); }
.price__week { margin-top: var(--s-3); font-weight: 600; }
.price .price__all { margin-top: var(--s-1); color: var(--c-panel-muted); }
.cancel, .call, .more { padding-top: var(--s-6); border-top: var(--rule) solid var(--c-trim); }
.call { padding-top: var(--s-7); }  /* round 5 (design, 375): the call is its own beat in a long panel */
.cancel h3 { font: 700 var(--t-md)/1.3 var(--font-text); }
.cancel p { margin-top: var(--s-1); color: var(--c-panel-muted); }
.price .fine { color: var(--c-panel-muted); }
.price__body { margin-top: var(--s-4); max-width: var(--measure); }
.price .price__bill { margin-top: var(--s-4); max-width: var(--measure); }
.price .fine { margin: var(--s-3) 0 0; max-width: var(--measure); }

/* The tape (from the "tool" direction): a day drawn as a 24-hour rule with her hours marked on it. */
.tape { position: relative; height: 46px; margin-top: var(--s-5); max-width: 30rem; }
.tape__ticks {
  position: absolute; inset: 0 0 18px 0; border-bottom: 2px solid var(--c-on-panel);
  background:
    repeating-linear-gradient(90deg, var(--c-on-panel) 0 1px, transparent 1px calc(100% / 4)) bottom / 100% 14px no-repeat,
    repeating-linear-gradient(90deg, var(--c-panel-muted) 0 1px, transparent 1px calc(100% / 24)) bottom / 100% 7px no-repeat;
}
.tape__on { position: absolute; bottom: 20px; height: 12px; left: 37.5%; width: 33.33%; background: var(--c-trim); }
/* Gate round 4: each inner label centred on its tick (25, 50, 75 %); the end labels flush with the ends. */
.tape__hrs { position: absolute; inset: auto 0 0 0; height: 11px;
  font: 500 11px/1 var(--font-text); color: var(--c-panel-muted); }
.tape__hrs span { position: absolute; top: 0; white-space: nowrap; }
.tape__hrs span:nth-child(1) { left: 0; }
.tape__hrs span:nth-child(2) { left: 25%; transform: translateX(-50%); }
.tape__hrs span:nth-child(3) { left: 50%; transform: translateX(-50%); }
.tape__hrs span:nth-child(4) { left: 75%; transform: translateX(-50%); }
.tape__hrs span:nth-child(5) { right: 0; }

.script { margin: 0; display: grid; gap: var(--s-4); }
.script div { display: grid; gap: var(--s-1); }
.script dt { font: 700 var(--t-xs)/1.2 var(--font-text); color: var(--c-panel-muted); }
.script dd { margin: 0; font-size: var(--t-lg); line-height: 1.4; }
.call__note { margin-top: var(--s-4); font-weight: 600; max-width: var(--measure); }
.call__note + .call__note { margin-top: var(--s-1); }

/* Recording and who we are: two plain paragraphs at the full measure, with run-in heads (gate round 4). */
.more p { max-width: var(--measure); color: var(--c-panel-muted); }
.more p + p { margin-top: var(--s-4); }
.more b { color: var(--c-on-panel); font-weight: 700; }
.more a { color: var(--c-on-panel); }

/* ================= 4. Start ================= */
.start { padding: var(--s-4) 0 var(--s-9); display: grid; gap: var(--s-6); }
.start form { display: grid; gap: var(--s-5); max-width: 440px; }
.pick { border: 0; padding: 0; margin: 0; display: grid; gap: var(--s-2); }
.pick legend { font: 600 var(--t-sm)/1.2 var(--font-text); padding: 0; margin-bottom: var(--s-2); }
.pick .two { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2); }
.opt { position: relative; }
.opt input { position: absolute; opacity: 0; inset: 0; }
.opt span { display: flex; align-items: center; justify-content: center; gap: var(--s-2); min-height: var(--tap);
  border: var(--border) solid var(--c-text); font: 800 1.5rem/1 var(--font-display); cursor: pointer; }
.opt input:checked + span { background: var(--c-text); color: var(--c-bg); }
.opt input:checked + span::before { content: ""; width: 14px; height: 8px; border: 3px solid currentColor;
  border-top: 0; border-right: 0; transform: rotate(-45deg) translateY(-2px); }
.opt input:focus-visible + span { outline: 3px solid var(--c-focus); outline-offset: 2px; }
.pick small { font-size: var(--t-xs); color: var(--c-muted); }
.start .quiet { color: var(--c-muted); font-size: var(--t-sm); }
.btn[aria-disabled="true"] { cursor: progress; }
.start .quiet a { color: var(--c-text); font-weight: 600; }
.start h2 { line-height: 1; }

/* ================= Footer ================= */
.foot { border-top: var(--rule) solid var(--c-rule); padding: var(--s-5) 0 calc(var(--s-7) + 64px);
  display: grid; gap: var(--s-3); font-size: var(--t-sm); color: var(--c-muted); }
.foot .wm { height: 30px; }
.foot nav { display: flex; flex-wrap: wrap; gap: 0 var(--s-5); }
.foot nav a { color: var(--c-text); min-height: 44px; display: inline-flex; align-items: center; }
.foot .fine { max-width: 60em; }

/* Phones only: once Jess's card has scrolled away, a slim bar to ring her. Never while the card or the
   sign-up form is on screen, so it never repeats a button you can already see. */
.ringbar { position: fixed; left: 0; right: 0; bottom: 0; display: flex; gap: var(--s-2);
  background: var(--c-ring); padding: var(--s-2) var(--gutter) calc(var(--s-2) + env(safe-area-inset-bottom));
  transform: translateY(110%); transition: transform 0.2s ease; z-index: 5; }
.ringbar.on { transform: none; }
.ringbar a { flex: 1; display: flex; align-items: center; justify-content: center; gap: var(--s-2); min-height: 48px;
  color: var(--c-on-ring); text-decoration: none; font-weight: 700; }
/* Charlie live: two 48 px halves with a full-height white divider between them (UX critic: at least 44 px each). */
.ringbar a + a { border-left: 2px solid var(--c-on-ring); }
.ringbar svg { width: 16px; height: 16px; }
.ringbar b { font-weight: 500; font-variant-numeric: tabular-nums; }

/* ================= Small pages (404, thanks) ================= */
.lost { padding: var(--s-6) 0 var(--s-9); display: grid; gap: var(--s-5); max-width: 640px; }
.lost .lead { color: var(--c-muted); }
/* Gate round 4: the plate is as wide as what it holds, not the column (it ran ~445 px round a two-word path). */
.lost .plate { padding: var(--s-5) var(--s-5); display: grid; gap: var(--s-1); }
.lost .plate p:first-child { font-size: var(--t-xs); color: var(--c-panel-muted); }
.lost .plate p:nth-child(2) { font: 900 var(--t-xl)/1 var(--font-display); overflow-wrap: anywhere; }
.lost .plate p:last-child { color: var(--c-panel-muted); }
.lost .btn { justify-self: stretch; }  /* full width on phones, like "Set it up" (gate round 4, UX) */

/* ================= Wider screens ================= */
@media (min-width: 600px) {
  .hear h1 { font-size: 4.5rem; }
  /* Gate round 4: the card runs the full content width at 600-899, sharing its right edge with the rule. */
  .contacts { max-width: none; }
  .lost .btn { justify-self: start; }
  .lost .plate { width: fit-content; min-width: 20rem; max-width: 100%; }  /* phones keep the full column */
  html[data-charlie-live="true"] .contacts { grid-template-columns: 1fr; }
  .contact { grid-template-columns: 1fr auto; column-gap: var(--s-5); align-items: center; }
  .contact__head, .contact__num, .contact .btn--ring { grid-column: 1; }
  .contact__qr { display: grid; grid-column: 2; grid-row: 1 / span 3; justify-items: center; gap: var(--s-2); }
  .contact__qr span:first-child { background: var(--duco-white); padding: 8px; }
  .contact__qr img { width: 96px; height: 96px; }
  .contact__qr .fine { max-width: 112px; text-align: center; }
}
@media (min-width: 768px) {
  .start { grid-template-columns: 1fr 1fr; gap: var(--s-7); align-items: start; }
  .see { grid-template-columns: 1fr 1fr; column-gap: var(--s-6); }
  .see__words { grid-column: 1 / -1; max-width: 40rem; }
  .crop--wide { display: block; }
}
/* Round 5 (design): from 1100 the words sit above and the two emails run at about 1.15x (437 px, from 380), so
   the email's own small print reads. The crops are rendered at 2.5x for it. */
@media (min-width: 1100px) {
  .see { grid-template-columns: repeat(2, 437px); column-gap: var(--s-8); }
  .crop { max-width: 437px; }
}
@media (min-width: 900px) {
  .wrap { padding: 0 var(--s-7); }
  .top { min-height: 104px; gap: var(--s-5); }
  .top .wm { height: 52px; }
  /* Round 5 (design): the card's top edge on the headline's cap height, so the two halves lock together. */
  .hear { grid-template-columns: 1.1fr 1fr; gap: var(--s-8); align-items: start; padding: var(--s-8) 0 var(--s-9); }
  .contacts { margin-top: 0.6rem; }
  .hear h1 { font-size: clamp(5rem, 8.4vw, 8.25rem); }
  .contacts, html[data-charlie-live="true"] .contacts { grid-template-columns: 1fr; max-width: none; }
  .contact { grid-template-columns: 1fr auto; align-items: end; padding: var(--s-6); column-gap: var(--s-5); }
  .contact__head, .contact__num { grid-column: 1; }
  .contact__name { font-size: 3.5rem; }
  .contact .btn--ring { display: none; }
  .contact__qr { grid-row: 1 / span 2; }
  .see { padding: var(--s-9) 0; row-gap: var(--s-7); }
  .trust .plate { grid-template-columns: 1fr 1fr; padding: var(--s-8); column-gap: var(--s-8); row-gap: var(--s-7); }
  .price__line { font-size: var(--t-3xl); }
  /* The price runs down the left; the call and then "Stop when you like." stack top-down on the right. */
  .trust .plate { grid-template-rows: auto 1fr; }
  .price { grid-row: 1 / span 2; }
  .call { grid-column: 2; grid-row: 1; }
  .cancel { grid-column: 2; grid-row: 2; align-self: start; }
  .call { border-top: 0; padding-top: 0; }
  .more { grid-column: 1 / -1; }
  .start { gap: var(--s-8); padding: var(--s-8) 0 var(--s-10); }
  .foot { padding-bottom: var(--s-7); grid-template-columns: auto 1fr; align-items: center; column-gap: var(--s-6); }
  .foot nav { justify-content: flex-end; }
  .foot .fine { grid-column: 1 / -1; }
  .ringbar { display: none; }
  .lost { padding: var(--s-8) 0 var(--s-10); }
}

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