/* Callio Studio: the public front page.
 *
 * **Direction 4e, "Rail, light right, vertical", which supersedes 4d.**
 * `design/4e-login-reference.html` is the spec of record and
 * `design/HANDOFF.md` describes it. The reference is a single fixed 1360px
 * composition written in inline styles; this file is the same geometry
 * expressed as classes, which is what makes the responsive rules at the bottom
 * possible at all.
 *
 * What 4e changed from 4d, all of it visible in here: the timeline runs
 * vertically instead of across four columns, the eyebrow lockup moved from the
 * top of the left column into the right rail between the two cards, the header
 * lockup roughly doubled in size, step 2 gained a row of count chips, and the
 * whole thing is border-box.
 *
 * **Two places where this file deliberately departs from the reference**, both
 * on Eugene's instruction and both later than the drawing: the page is full
 * bleed rather than a 1360px card on a mat, and the masthead carries no beta
 * chip and no log-in link. The reference's own markup already dropped the chip
 * and the link; only the frame is still drawn as a card there.
 *
 * This is not `callio.css` and does not extend it. That stylesheet is the local
 * dashboard's own, kept byte-faithful to the system Eugene already uses so any
 * visual difference is a real difference. The front page is a different artefact
 * with a different job, and mixing the two would mean every future change to the
 * dashboard's look had to be checked against a marketing page.
 */

/* --- Fonts ---------------------------------------------------------------- */
/* Self-hosted rather than loaded from Google. This is the login page: it is the
 * one route into the product, it is the page most likely to be reached on a bad
 * connection, and a third-party font host is both a dependency that can be slow
 * and a request that tells someone else who is signing in. Both families are
 * SIL Open Font License, so serving our own copies is permitted. See
 * `web/static/fonts/README.md` for provenance. */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 300 700;   /* one variable file covers the whole range */
  font-display: swap;
  src: url("../fonts/hanken-grotesk-var-latin.a6b899943e31.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/hanken-grotesk-var-latin-ext.a3a0917757d7.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/dm-mono-400-latin.b4ddae058212.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/dm-mono-400-latin-ext.1b65496d99bd.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/dm-mono-500-latin.ecb3fd43cbea.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'DM Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/dm-mono-500-latin-ext.83187a548722.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Tokens --------------------------------------------------------------- */
/* Straight from the handoff table. Named for what they are rather than where
 * they are used, because `--sand` survives a layout change and `--right-panel`
 * would not. */
:root {
  --cream: #F6F1E7;
  --sand: #EDE5D5;
  --paper: #FFFFFF;
  --field: #FAF7F0;
  --page: #EFEADE;
  --ink: #24201B;
  --ink-2: #4A4335;
  --muted: #6E6553;
  --placeholder: #A79E8C;
  --hairline: #EAE2D2;
  --hairline-2: #E3DACA;
  --field-line: #E0D7C5;
  --rust: #C4562A;
  --rust-deep: #B04E24;
  --rust-button: #AC4A22;
  --slate: #3F6683;

  --r-frame: 16px;
  --r-card: 14px;
  --r-control: 9px;

  --font: 'Hanken Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'DM Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* --- Page ----------------------------------------------------------------- */
/* **Border-box, which 4e added and 4d did not have.** It changes what the
 * reference's numbers mean: 4d drew a "26px" ring as a 26px box plus a 2px
 * border, occupying 30px, and 4e's same declaration occupies 26px. Every mark
 * size and every dot in this sheet is now the outer measurement, which is also
 * what the handoff's radii table describes. Adopting it is not optional if the
 * numbers are to be read straight off the reference. */
*,
*::before,
*::after { box-sizing: border-box; }

.front-body {
  margin: 0;
  /* **No padding, because the page is not a card.** Eugene, 2026-08-03: *"you
   * have the webpages in one large card ... they should sit directly on the
   * screen end to end."* The design reference is a 1360px composition floated on
   * a page-coloured mat, which is how a design board presents a screen rather
   * than how the screen wants to be. The mat is gone; the sand panel and the
   * ticker now run to both edges. */
  padding: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}
/* Unprefixed, and this one had to be found by looking at the page.
 *
 * As `.front-body a` at 0-1-1 it out-ranked `.btn-secondary` at 0-1-0, so the
 * CTA on the slate card inherited that card's white text and rendered white on
 * a near-white button: present, clickable, invisible. Third instance of the
 * same trap in this file, and the only one no test would have caught, because
 * the markup and the text were both correct. Element selectors for resets,
 * classes for components, and never the two mixed. */
a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; }
/* Every interactive element gets its chrome removed here, once, rather than
 * relying on each component's own rule to do it.
 *
 * Cross-product log, 2026-08-03: a control nested inside a styled container had
 * no rule of its own, fell back to the browser's default button chrome, and
 * shipped as a grey OS box sitting on a filled chip. Two of the three such
 * controls had rules and the third never did. The failure is invisible until
 * the exact state that renders it occurs, which is why this is a blanket reset
 * on the page and not a note to remember when adding the next button. This page
 * has two nested controls already (the CTA on the slate card, and the beta chip
 * beside the header link), and will grow more. */
/* Bare element selectors on purpose: this sheet is loaded only by the public
 * page, so it needs no `.front-body` guard, and at specificity 0-0-1 every
 * component class below beats it. Prefixing them would make the reset 0-1-1 and
 * it would then silently out-rank `.btn-primary`'s padding, which is the same
 * source-order-and-specificity trap the log warns about, arrived at from the
 * other direction. */
input,
button {
  font: inherit;
  color: inherit;
  -webkit-appearance: none;
  appearance: none;
}
button {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  text-align: inherit;
}

/* Visible focus, which the reference does not have. Nothing on this page is
 * reachable except by keyboard for some people, and the sand and cream surfaces
 * are close enough in value that the browser default ring is hard to see on
 * them. Rust is the one colour on the page that is not close to anything. */
.front-body :focus-visible {
  outline: 2px solid var(--rust);
  outline-offset: 2px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--cream);
  padding: 10px 16px;
  border-radius: var(--r-control);
  font-size: 14px;
  z-index: 10;
}
.skip-link:focus { left: 16px; top: 16px; }

/* Full bleed. The rounded border and the 1360px cap are gone with the mat; what
 * is left of the frame is the cream surface and the `overflow: hidden` that
 * keeps the ticker's doubled track from widening the document.
 *
 * The horizontal paddings below are unchanged, so at a viewport of exactly
 * 1360px every internal measurement still matches the design reference. Above
 * that the columns simply get wider, which is what "end to end" means. */
.frame {
  background: var(--cream);
  overflow: hidden;
  /* Fill the screen vertically as well as horizontally. Without this, a viewport
   * taller than the content leaves a band of page colour under the ticker, which
   * reads as the page having stopped rather than ended.
   *
   * The slack goes to `.statement-wrap` rather than to `.split`. Stretching the
   * split stretches the sand panel and the pitch column with it, and both of
   * them are compositions with a top edge; growing the cream band under the
   * statement instead costs nothing, since it is empty space either way. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* --- Logo mark ------------------------------------------------------------ */
/* Mark 06. The reference builds it from two nested divs at three hard-coded
 * sizes; this is one asset that takes its size from a custom property, so the
 * three uses cannot drift apart.
 *
 * **The sizes are the reference's own numbers again, now that 4e is border-box.**
 * Under 4d they had to be inflated by 4px each, because a "26px" ring there was
 * a 26px box plus a 2px border. 4e sets `box-sizing: border-box` globally, so
 * 38 means 38. The three in use are 38 (header lockup), 26 (eyebrow) and 34
 * (statement). */
.mark {
  width: var(--mark-size, 38px);
  height: var(--mark-size, 38px);
  flex: none;
  display: block;
}

/* --- Header --------------------------------------------------------------- */
.masthead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 20px 46px;
  border-bottom: 1px solid var(--hairline);
}
.wordmark {
  display: flex;
  align-items: center;
  gap: 13px;
}
.wordmark:hover { text-decoration: none; }
/* **The lockup roughly doubled in 4e**, and it is the one change that reaches
 * every page rather than just the front one: ring 26 to 38, "Callio" 23 to 33,
 * "STUDIO" 9 to 17 with slightly tighter tracking. The reference nests the two
 * words in their own flex row inside the outer one, so the 13px gap after the
 * ring and the 13px gap between the words stay independent. */
.wordmark-text {
  display: flex;
  align-items: center;
  gap: 13px;
}
.wordmark-name {
  font-size: 33px;
  font-weight: 600;
  letter-spacing: -0.035em;
}
.wordmark-sub {
  font-family: var(--mono);
  font-size: 17px;
  letter-spacing: 0.2em;
  color: var(--muted);
  margin-top: 5px;
}
/* **Nothing sits opposite the wordmark.** Eugene, 2026-08-03: *"in the top right
 * get rid of 'private beta · 12 seats + log in'."* The beta chip and the log-in
 * link are both gone, so the masthead is the lockup alone. `space-between` on a
 * single child leaves it where it was, which is why the rule above is unchanged.
 *
 * The log-in link was redundant anyway: the card it pointed at is on the same
 * screen. On the waitlist page the affordance survives as "Already have a key?
 * Straight in, then." inside the form, where it reads as an offer rather than as
 * navigation. */

/* --- Two-column body ------------------------------------------------------ */
.split {
  display: grid;
  grid-template-columns: 1.24fr 0.76fr;
  align-items: stretch;
}

.pitch {
  /* 42/46/38 in 4e, down from 52/46/40. The column starts with the hero now
   * rather than with the eyebrow lockup, which moved to the right rail. */
  padding: 42px 46px 38px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
/* **The column is one composition drawn in two pieces**, so that a phone can
 * put the login card between them. See the note in `public/front.html` and the
 * `display: contents` rule in the 899px query.
 *
 * Same axis and the same 22px gap as the parent, which is what makes the wrapper
 * invisible here: hero to subhead, subhead to body and body to timeline are all
 * still 22px apart whether the gap comes from `.pitch` or from one of these. */
.pitch-head,
.pitch-rest {
  display: flex;
  flex-direction: column;
  gap: 22px;
}
/* **The eyebrow lockup moved to the right rail in 4e**, between the login card
 * and the waitlist card, and shrank from a 38px ring to a 26px one. In 4d it
 * opened the left column above the hero. */
.lockup {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 4px 2px;
}
.eyebrow-text {
  margin: 0;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--rust-deep);
  line-height: 1.65;
}
.hero {
  margin: 0;
  font-size: 104px;
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: -0.055em;
}
.subhead {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -0.04em;
}
.subhead-lead { color: var(--rust); }
.pitch-body {
  margin: 0;
  font-size: 19px;
  line-height: 1.6;
  color: var(--ink-2);
  /* The reference pins this to one line per sentence at 1360px. Below that it
   * has to be allowed to wrap, so the no-wrap is scoped to the width it was
   * drawn at rather than written here unconditionally. */
}

/* --- Timeline ------------------------------------------------------------- */
/* **Vertical in 4e, where 4d ran it horizontally across four columns.** Times
 * sit in a 96px left gutter; the dots and connector lines run down beside the
 * labels. The change is the main structural difference between the two
 * directions.
 *
 * An <ol>, because four steps in a fixed order is a list and a screen reader
 * should be told so. The rail and the timestamps carry the sequence visually,
 * so the markers themselves are removed.
 *
 * **Each step is its own two-column grid**, rather than the eight timestamps and
 * bodies being direct children of one grid. The reference is written the second
 * way, but per-step grids give the identical result without needing
 * `display: contents` on the list items, and they make the connector line a
 * child of the step it belongs to: `flex: 1` then stretches it to exactly that
 * step's height, which is what makes a tall step like the second one draw a
 * long dashed line and a short step a short one. */
.timeline {
  display: flex;
  flex-direction: column;
  max-width: 660px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}
/* `--timeline-gutter` is declared here rather than on `.step`, where it used to
 * live, because the caption below the list needs the same number and a custom
 * property does not travel sideways between siblings. The steps inherit it and
 * are otherwise untouched; the two media queries that narrow it now set it on
 * this element. */
.timeline-wrap {
  --timeline-gutter: 96px;
}
/* The caption that makes the whole drawing illustrative. It indents past the
 * timestamp gutter, the 11px rail and the 18px gap, so it starts exactly where
 * the four labels start and reads as a note on them rather than on the last
 * timestamp. */
.timeline-note {
  max-width: 660px;
  margin: 10px 0 0;
  padding-left: calc(var(--timeline-gutter, 96px) + 29px);
  font-size: 12px;
  color: var(--muted);
}
.step {
  display: grid;
  grid-template-columns: var(--timeline-gutter, 96px) 1fr;
}
.step-time {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink);
  padding-top: 1px;
}
.step-body {
  display: flex;
  gap: 18px;
}
/* The rail: a fixed 11px column holding the dot and the line under it. Fixed
 * rather than shrink-to-fit so the labels of all four steps line up even though
 * step 2's line is 3px wide and the rest are 2px. */
.step-rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: none;
  width: 11px;
}
.step-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--ink);
  flex: none;
}
.step-line {
  width: 2px;
  flex: 1;
  background: var(--ink);
}
/* -4px, because the label's cap height sits below the top of its line box and
 * the dot would otherwise read as hanging low against it. */
.step-text {
  margin-top: -4px;
  padding-bottom: 24px;
}
.step-label {
  display: block;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.3;
}
.step-note {
  display: block;
  font-size: 13px;
  color: var(--muted);
  margin-top: 4px;
}

/* Step 2 is the machine's stretch of the night, and the whole point of the
 * drawing is that it looks different from the two human steps on either side:
 * an open dot, a dashed rust line, a rust timestamp, and the extra room its
 * chip row needs. */
.step--machine .step-time { color: var(--rust-deep); }
.step--machine .step-dot {
  background: var(--cream);
  border: 2px solid var(--rust);
}
.step--machine .step-line {
  width: 3px;
  background: repeating-linear-gradient(180deg, var(--rust) 0 9px, transparent 9px 16px);
}
.step--machine .step-text { padding-bottom: 34px; }

/* The count chips under step 2. New in 4e. */
.step-chips {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  flex-wrap: wrap;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
}
.step-chip {
  border: 1px solid var(--field-line);
  border-radius: 99px;
  padding: 4px 10px;
}

/* Step 4 ends the sequence, so its line carries on past the last note and fades
 * out rather than stopping. `min-height` is what gives the tail something to
 * fade across once `flex: 1` has run out of step to fill; the handoff calls it
 * decorative and says nothing hangs off it. */
.step--last .step-time { color: var(--muted); }
.step--last .step-dot { background: var(--rust); }
.step--last .step-line {
  min-height: 26px;
  background: linear-gradient(180deg, var(--rust), rgba(196, 86, 42, 0));
}
.step--last .step-text { padding-bottom: 18px; }

/* --- Right rail ----------------------------------------------------------- */
.rail-right {
  padding: 44px 38px 40px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  background: var(--sand);
  border-left: 1px solid var(--hairline-2);
}

.card-login {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  padding: 32px;
}
/* The 22px under the heading now lives on the summary that wraps it, because
 * that is the element the form actually follows. Same gap, one level out. */
.card-login h2 {
  margin: 0;
  font-size: 33px;
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1;
}

/* The login card's summary. It holds the heading in both states and, below
 * 900px, whichever chevron the current state calls for.
 *
 * `list-style: none` plus the WebKit pseudo-element removes the browser's own
 * triangle. Both are needed; Safari ignores the first.
 *
 * `cursor: default` because on a wide screen this is a heading and nothing else:
 * there is nothing to fold, and the script cancels the click. The 899px query
 * turns it back into a pointer. */
.login-head {
  display: flex;
  flex-direction: column;
  gap: 22px;
  list-style: none;
  cursor: default;
}
.login-head::-webkit-details-marker { display: none; }
.login-head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
/* The gap to the form, which only exists when there is a form under it. Folded,
 * the card ends at the cue and its own padding closes it off. */
.login-details[open] > .login-head { margin-bottom: 22px; }

/* The folded state's cue, which only a narrow viewport ever sees.
 *
 * **Styled as the form's own fields, not as a button.** It is the same surface,
 * the same 1px line, the same radius and the same 13/14 padding as an `<input>`,
 * because what it stands in for is the fields: it reads as the form rolled up
 * rather than as a second call to action competing with the rust one inside it.
 *
 * **Gone once the card is open**, where leaving it would put "let me in" twice on
 * one card, the second time on the button that actually signs you in. That is
 * also what holds the desktop layout: above 899px the card is never closed, so
 * the cue is never drawn and no width-scoped rule is needed to hide it. */
.login-cue {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 14px;
  background: var(--field);
  border: 1px solid var(--field-line);
  border-radius: var(--r-control);
  font-size: 16px;
  font-weight: 600;
}
.login-details[open] .login-cue { display: none; }

.login-chevron {
  width: 16px;
  height: 16px;
  flex: none;
  color: var(--rust-deep);
}
/* **The way back out, and it is drawn nowhere else.** Eugene, 2026-08-03:
 * *"after the Oh good youre back opens, there shold be a chevron to cllapse it
 * again, next to where it says Oh good youre back."*
 *
 * Hidden by default rather than shown by default, because the two states it must
 * not appear in are both the common ones: any width above 899px, where the card
 * cannot be folded at all, and the folded card itself, which already has the cue
 * below the heading and would otherwise carry two chevrons at once. The 899px
 * query turns it on for the one state that wants it. */
.login-chevron--fold {
  display: none;
  width: 20px;
  height: 20px;
}

.form-fields {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.field label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--muted);
}
.field input {
  background: var(--field);
  border: 1px solid var(--field-line);
  border-radius: var(--r-control);
  padding: 13px 14px;
  font-size: 15px;
  color: var(--ink);
}
.field input::placeholder { color: var(--placeholder); }
.field input[type="password"] { letter-spacing: 0.2em; }
.field input[type="password"]::placeholder { letter-spacing: normal; }

/* The error state is designed, not improvised: the field border goes rust and
 * the message sits under it in the deeper rust at 13px. */
.field--error input { border-color: var(--rust); }
.field-error {
  font-size: 13px;
  color: var(--rust-deep);
  line-height: 1.4;
}

.btn-primary {
  background: var(--rust-button);
  color: #fff;
  border: none;
  border-radius: var(--r-control);
  padding: 15px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  margin-top: 4px;
}
.btn-primary:hover { background: var(--rust-deep); }

.form-aside {
  margin: 0;
  font-size: 13px;
  color: var(--muted);
}
.form-aside a {
  color: var(--rust-deep);
  text-decoration: underline;
}

/* The waitlist card. `margin-top:auto` is what pins it to the bottom of the
 * rail so the two cards frame the panel instead of bunching at the top. */
/* No `margin-top: auto` in 4e. The rail is three things stacked from the top
 * with 18px between them, and the lockup row is what separates the two cards;
 * pinning the waitlist to the bottom would open a gap where that row sits. */
.card-waitlist {
  background: var(--slate);
  color: #fff;
  border-radius: var(--r-card);
  padding: 26px 28px;
}
.card-waitlist h2 {
  margin: 0 0 8px;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.2;
}
/* `.card-waitlist-copy`, not `.card-waitlist p`.
 *
 * As a descendant selector it was 0-1-1 and quietly out-ranked `.seat-count`
 * at 0-1-0, so the counter under the button inherited this rule's margins and
 * the card came out 14px taller than the design. Fourth time in this file that
 * a descendant selector beat the class that was supposed to own the element.
 * Cross-product log, 2026-08-02: if the specific rule must win, make it more
 * specific rather than merely later. Here the fix is to stop the general rule
 * ever reaching the element. */
.card-waitlist-copy {
  margin: 0 0 18px;
  font-size: 14px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.78);
}
.btn-secondary {
  display: block;
  background: #FFFDF8;
  color: var(--ink);
  border: none;
  border-radius: var(--r-control);
  padding: 14px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  /* No `width: 100%`. A block-level element already fills its container, and
   * adding it made the width the *content* box, so the 14px of padding pushed
   * the button 28px past the card's right edge. There is no global
   * `box-sizing: border-box` in this sheet, and deliberately so: the reference
   * is drawn in content-box, where the machine step's dot is 11px plus a 2px
   * ring and reads 15px wide. Switching globally would silently shrink it. */
}
.btn-secondary:hover { text-decoration: none; background: #fff; }
/* The seat counter that sat here is gone. Eugene, 2026-08-03: *"get rid of 12
 * seats under the sign up button."* `apps/marketing/seats.py` went with it,
 * along with `CALLIO_SEATS_TOTAL` and `CALLIO_WAITLIST_BASE`, rather than being
 * left as machinery computing a number nothing renders. The waitlist table and
 * everything that writes to it are untouched. */
/* On slate, the rust focus ring is nearly invisible, so this one surface gets a
 * light ring instead. Same idea, opposite background. */
.card-waitlist :focus-visible { outline-color: #FFFDF8; }

/* --- Statement ------------------------------------------------------------ */
/* **No padding on the right.** Eugene, 2026-08-03: *"let's have that card go all
 * the way to the right side of the screen without any rounded corners. It should
 * just integrate into the very right end."* So the card keeps its 46px left
 * inset, which is what aligns it with the hero and the timeline above, and runs
 * off the right edge. The asymmetry is the instruction, not an oversight. */
.statement-wrap {
  padding: 0 0 34px 46px;
  background: var(--cream);
  /* Takes the slack when the viewport is taller than the page. See `.frame`.
   * Declared here rather than beside that rule so this selector appears once in
   * the sheet: two blocks for one class is how a later property silently wins an
   * argument nobody knew was happening. */
  flex: 1;
}
.statement {
  background: var(--paper);
  /* No border on the right, because it would draw a line where the card is meant
   * to stop existing. **The left corners keep their radius**: Eugene asked for
   * "no rounded corners" and the 4e reference, drawn after that, resolves it as
   * `12px 0 0 12px`, rounded where the card has an edge and square where it
   * bleeds. The reference is the later word and the more considered one. */
  border: 1px solid var(--hairline);
  border-right: none;
  border-radius: 12px 0 0 12px;
  padding: 24px 28px;
  display: flex;
  align-items: center;
  gap: 24px;
}
.statement p {
  margin: 0;
  font-size: 21px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.02em;
  flex: 1;
  text-wrap: pretty;
}
.statement em {
  font-style: normal;
  color: var(--rust);
}
/* An extra 28px in from the card's own right padding. The card's right edge is
 * now the screen's, and without this the glyph would sit tight against it. */
.statement .mark { margin-right: 28px; }

/* --- Single-column public pages ------------------------------------------- */
/* The waitlist form and its thank-you. Not in the reference, which draws only
 * the front page, so this is built from the same tokens rather than invented:
 * cream surface, paper card, the same field and button components the login card
 * uses. A visitor arrives here by pressing a button on that card and should not
 * feel they have left. */
.panel {
  padding: 56px 46px 52px;
  display: flex;
  justify-content: center;
  /* Takes the slack on every page that is a single panel rather than the front
   * page's split, so the ticker lands on the bottom edge here too. `.frame` is a
   * 100vh flex column and something in it has to grow; on the front page that
   * job belongs to `.statement-wrap`, and these pages have no statement. Without
   * this the leftover height collected after the ticker and drew a band of cream
   * below it. */
  flex: 1;
}
.panel-inner {
  width: 100%;
  max-width: 620px;
}
.panel-eyebrow {
  margin: 0 0 14px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--rust-deep);
}
.panel-title {
  margin: 0 0 16px;
  font-size: 52px;
  font-weight: 600;
  line-height: 1.0;
  letter-spacing: -0.045em;
}
.panel-lede {
  margin: 0 0 30px;
  font-size: 19px;
  line-height: 1.6;
  color: var(--ink-2);
}
.panel-lede strong { font-weight: 600; color: var(--ink); }
.card-form {
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  padding: 32px;
}
/* The waitlist page's own seat counter went too. It sat under a sign-up button
 * exactly as the front page's did, and leaving one of the two would have been a
 * half-application of the same instruction. */
.field textarea {
  background: var(--field);
  border: 1px solid var(--field-line);
  border-radius: var(--r-control);
  padding: 13px 14px;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  resize: vertical;
  min-height: 96px;
}
.field textarea::placeholder { color: var(--placeholder); }
.field--error textarea { border-color: var(--rust); }
.field-hint {
  font-size: 13px;
  color: var(--muted);
  line-height: 1.4;
}

/* --- Ticker --------------------------------------------------------------- */
.ticker {
  border-top: 1px solid var(--hairline);
  background: var(--sand);
  overflow: hidden;
  padding: 13px 0;
}
.ticker-track {
  display: flex;
  gap: 44px;
  width: max-content;
  animation: ticker 38s linear infinite;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--muted);
  white-space: nowrap;
}
@keyframes ticker {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* --- Responsive ----------------------------------------------------------- */
/* Not in the reference, which is a single fixed composition. The sizes below
 * are the handoff's, and the ordering decision it left open is resolved in the
 * markup rather than here: on a narrow screen the login card is moved above the
 * pitch, because someone on a phone is far more likely to be a tenant signing in
 * than a stranger reading the pitch for the first time. */

/* At the width it was drawn for, the two body lines hold on one line each,
 * which is part of the composition. */
@media (min-width: 1200px) {
  .pitch-body { white-space: nowrap; }
}

/* **No mat at any width.** `.front-body` had 32px of padding here and 16px in
 * the band below, left over from the version that floated the page on a
 * page-coloured surface, and `.frame` took its rounded corners back at 899px.
 * The effect was that the instruction to run end to end held on a desktop and
 * quietly stopped holding on everything narrower. Eugene, 2026-08-03: *"mobile
 * site still shows up with the whole site on a card. we need to get rid of that
 * and have it expand to the margins just like desktop."* Both declarations are
 * gone rather than zeroed, so there is nothing left to drift back. */
@media (max-width: 1199px) {
  .hero { font-size: 72px; }
  /* The handoff's number for this band. The gutter only holds a mono timestamp,
   * so it shrinks before anything else does. */
  .timeline-wrap { --timeline-gutter: 80px; }
  .pitch { padding: 44px 36px 36px; }
  .rail-right { padding: 38px 30px 34px; }
  .statement-wrap { padding: 0 0 30px 36px; }
  .masthead { padding: 18px 36px; }
  .panel { padding: 46px 36px 44px; }
  .panel-title { font-size: 44px; }
}

@media (max-width: 899px) {
  .split { grid-template-columns: 1fr; }

  /* **The narrow order is Eugene's, and it interleaves the two columns.**
   * 2026-08-03: hero, subhead, the login card, the eyebrow line, the waitlist
   * card, then the rest of the page. The previous rule simply hoisted the whole
   * right rail above the whole left column, which put "I've been up all night
   * working on your socials" on screen before the sentence it answers.
   *
   * `display: contents` on `.pitch` is what makes it possible: it drops the
   * column's own box so its two halves become grid items in their own right and
   * the rail can be ordered between them. The box it drops was carrying the
   * padding and the gap, so both move down to the halves. */
  .pitch { display: contents; }
  /* 24px under the subhead rather than none: the sand block that follows brings
   * its own 28px of top padding, but it also brings a hairline, and with a zero
   * bottom the rule sat almost on the descenders of "I'll do the boring 90%." */
  .pitch-head { order: 1; padding: 34px 24px 24px; gap: 20px; }
  .pitch-rest { order: 3; padding: 30px 24px; gap: 20px; }
  /* Order 2, between the two halves. Sand between two cream blocks now rather
   * than a column beside one, so the hairline that separated them runs along
   * both edges. One block for one class: a second `.rail-right` rule further
   * down this query is how a padding silently wins an argument nobody knew was
   * happening. */
  .rail-right {
    order: 2;
    border-left: none;
    border-top: 1px solid var(--hairline-2);
    border-bottom: 1px solid var(--hairline-2);
    padding: 28px 24px;
  }
  .card-waitlist { margin-top: 0; }
  /* The 8px under the heading was a gap before a paragraph. With the paragraph
   * gone it is a gap before a button, and needs to look like one. */
  .card-waitlist h2 { margin-bottom: 14px; }
  /* **The sentence goes, the card stays.** Eugene: *"the no keys yet card (but
   * maybe no text to save space)"*. "No key yet?" and "get on the list →" carry
   * the whole action between them; the line under the heading is pitch, and it
   * is pitch the visitor is about to read in full on the page the button opens.
   * `display: none` rather than a visually-hidden class on purpose: there is no
   * version of this where a screen reader user wants a sentence the design has
   * decided is surplus read out to them. */
  .card-waitlist-copy { display: none; }

  /* The one state the collapse chevron is for: narrow enough to fold, and
   * currently open. See the note on `.login-chevron--fold`. */
  .login-details[open] .login-chevron--fold { display: block; }
  .login-head { cursor: pointer; }

  .hero { font-size: 48px; letter-spacing: -0.04em; }
  .subhead { font-size: 26px; gap: 8px; }
  .pitch-body { font-size: 17px; }
  /* **The line breaks stay.** Hiding them with `display: none` looked like the
   * obvious way to let the copy reflow, and it renders "Hi. I'll take itfrom
   * here." and "tracking, reportingAll while you sleep": a `<br>` is the only
   * thing separating those words, so removing it joins them. Both breaks fall
   * where the copy wants them anyway. */
  .masthead { padding: 16px 24px; gap: 12px; }
  .statement-wrap { padding: 0 0 24px 24px; }
  .statement { flex-direction: column; align-items: flex-start; gap: 16px; }
  .statement p { font-size: 19px; }
  .panel { padding: 34px 24px 32px; }
  .panel-title { font-size: 34px; letter-spacing: -0.035em; }
  .panel-lede { font-size: 17px; }
  .card-form { padding: 24px; }

  /* **The timeline needs almost nothing here now.** 4d's ran horizontally
   * across four columns and had to be rotated on its side for a phone, with a
   * named-areas grid and a reset for the last label's no-wrap. 4e is already
   * vertical, so the whole rotation is gone and only the gutter narrows, per
   * the handoff's number for this band. The chips wrap on their own. */
  .timeline-wrap { --timeline-gutter: 72px; }
}

@media (max-width: 479px) {
  .hero { font-size: 40px; }
  .subhead { font-size: 22px; }
  .card-login { padding: 24px; }
  .card-login h2 { font-size: 27px; }
  /* The 4e lockup is nearly double 4d's, so on the narrowest screens it needs
   * reining in or "Callio STUDIO" runs into the edge. Proportions are kept. */
  .wordmark-name { font-size: 26px; }
  .wordmark-sub { font-size: 13px; margin-top: 4px; }
  .wordmark, .wordmark-text { gap: 10px; }
  .mark { --mark-size: 32px; }
}

/* The handoff's 15px floor for body copy is held by the values in the media
 * queries above (17px, then 15px), not by a rule down here. A trailing
 * `font-size: max(15px, 1em)` was the obvious way to write it and it is wrong
 * twice over: `1em` resolves against the *parent*, so it computes 16px and
 * shrinks the 19px body copy, and being last at equal specificity it wins that
 * race silently. Cross-product log, 2026-08-02: make the rule that must win
 * genuinely more specific rather than merely later. The 13px notes and asides
 * are at the size the design draws them and are not body copy. */

@media (prefers-reduced-motion: reduce) {
  /* Paused rather than hidden. The strip is content, and someone who has asked
   * for less motion should still be able to read it. */
  .ticker-track { animation-play-state: paused; }
}
