/* Daycard — a price list, not a marketplace. */

:root {
    /* One pairing across both languages: the Latin face is listed first and the
       Japanese face behind it, so each script is drawn by the font made for it.

       Hina Mincho won the Japanese display face over three rounds auditioned on
       the real for-photographers headline. The other three that reached the last
       round, should this one ever need replacing: Zen Maru Gothic, Zen Old
       Mincho, Shippori Mincho B1. What lost was neutrality - the modern book
       minchos (Noto Serif JP, Shippori Mincho, BIZ UDPMincho) all went early. */
    --font-display: "Instrument Serif", "Hina Mincho", "Hiragino Mincho ProN", serif;

    /* Karla won its own audition on the gate button and stays. The Japanese
       half behind it was re-auditioned on the for-photographers lede, where
       Klee One's pen strokes read as handwriting rather than as a sentence
       anyone would price a day's work by; Zen Kaku Gothic New won. The three
       that reached the last round: Noto Sans JP, Sawarabi Gothic, and Zen Kaku
       Gothic Antique with `palt`. What lost, over and over, was age - every
       mincho, every rounded face and every light 300 cut went early.

       Zen Kaku Gothic New has no 600, so every bold in the UI sets at 700,
       which both faces carry for real. Nothing here is synthesised. */
    --font-ui: "Karla", "Zen Kaku Gothic New", "Hiragino Sans", sans-serif;

    /* Modular scale, base 17px, ratio 1.2. */
    --step-down-2: 11.81px;
    --step-down-1: 14.17px;
    --step-0: 17px;
    --step-1: 20.4px;
    --step-2: 24.48px;
    --step-3: 29.38px;
    --step-4: 35.25px;

    /* Spacing derived from body leading (17 x 1.7 = 29px). */
    --space-half: 14.5px;
    --space-1: 29px;
    --space-2: 43.5px;
    --space-3: 58px;
    --space-4: 87px;

    --color-paper: oklch(0.98 0.006 85);
    --color-paper-sunk: oklch(0.955 0.008 85);
    --color-ink: oklch(0.24 0.015 60);
    --color-ink-soft: oklch(0.53 0.012 60);
    --color-rule: oklch(0.88 0.008 70);
    /* The leader between a handle and its rate, darker than a rule because it is
       dotted: a dotted line is mostly paper, so at the rule's lightness it reads
       fainter than the solid borders drawn in the same ink. Derived from the rule
       rather than typed out, so the two stay the same colour with a gap in
       lightness rather than two colours that happen to be near each other. */
    --color-leader: oklch(from var(--color-rule) calc(l - 0.13) c h);
    /* The accent only ever appears under a pointer - hover and focus, nowhere at
       rest - so a hue was being spent on a state most readers never see, and on
       a page of ink on paper the one blue thing was the thing you happened to be
       touching. It is a grey now, the same warm grey the two inks are, so
       hovering a link or focusing a field reads as the ink shifting rather than
       as a second colour arriving. Derived rather than typed out, for the reason
       the leader is derived from the rule.

       It sits between the two inks, not below them. Below was the first attempt,
       so that every role darkened into it, but the ink is already at 0.24 and a
       step under that is black in all but name - there is no room beneath the
       ink for a grey to be a grey. So the direction of the move depends on where
       the role starts: quiet text at --color-ink-soft darkens into it, and the
       handle, already at --color-ink, lightens into it. Far enough under
       --color-ink-soft that a hovered control cannot be read as a disabled one.
       The filled button lifts the same way but stops short of arriving, since
       the whole distance turns a slab of ink pale - see the note on
       .form__button's hover.

       It is still not the error colour. Those two roles collided in one token
       once, so a focused field and a rejected one were painted the same.
       --color-error is the only red among the text and control roles; the
       drawings' --color-mark-ink below is the one other red, and it never
       paints anything interactive. */
    --color-accent: oklch(from var(--color-ink-soft) calc(l - 0.11) c h);
    --color-accent-quiet: oklch(from var(--color-accent) calc(l + 0.28) calc(c - 0.09) h);
    /* The only red among the text and control roles, and the reason the accent
       could stop being one. It won its own audition over four rounds; the last
       was decided on lightness alone, because error text sets at --step-down-1,
       which is under WCAG's large-text threshold and so owes 4.5:1. This clears
       at 5.10:1 on the paper and 4.74:1 on the sunk paper. The runner-up was
       0.03 lighter, which reads as 4.51:1 on paper but 4.19:1 on the sunk paper
       - so anything brighter than this has to be measured against the darker
       surface, not the one it will usually be seen on. */
    --color-error: oklch(0.55 0.21 28);
    /* Brightness here is chroma, not lightness. The green labels text at
       --step-down-2, which is under WCAG's large-text threshold and so owes
       4.5:1 against the sunk paper as well as the paper - and it was already at
       4.56:1, so a single step lighter drops it to 4.19:1 and out. Saturating
       it instead reads as the brighter green that was wanted and buys contrast
       rather than spending it: 4.95:1 on the paper, 4.60:1 on the sunk. Nothing
       above chroma 0.20 at this lightness holds the floor. */
    --color-positive: oklch(0.5 0.2 148);
    /* The drawings' own ink: the linework prints in vermilion, a second ink the
       way a Japanese form's ruling is printed red, and the rate stays in the
       black the reader would write with - so the number reads as the thing
       somebody filled in, not part of the printing. Two strengths of the one
       ink, the soft derived from the full the way the grey inks derive, so the
       drawings stay a single colour. Warmer and lighter than --color-error so a
       refused field and the drawings cannot be read as one voice. */
    --color-mark-ink: oklch(0.58 0.19 35);
    --color-mark-ink-soft: oklch(from var(--color-mark-ink) calc(l + 0.14) calc(c - 0.06) h);

    /* Japanese reads at roughly 40 characters a line, and a kanji is ~1em. */
    --measure: 41em;
    --column: 860px;

    /* The page gutter scales with the viewport rather than stepping at a
       breakpoint: 5vw reaches --space-1 at 580px, so any screen that wide or
       wider keeps the full 29px gutter, and a phone eases down to --space-half
       so the column never hugs the edge nor wastes a wide band on a small one. */
    --gutter: clamp(var(--space-half), 5vw, var(--space-1));

    --z-base: 0;
    --z-header: 200;
}

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

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

/* The paper is a flat fill, which reads as a screen rather than as a printed
   page, so a grain tile rides over it as a background layer on the body itself -
   no extra element, no stacking context, and the grain stays under everything.

   The blend mode is `multiply`, not the `overlay` or `soft-light` a texture
   tutorial would reach for. Those are neutral at mid-grey and scale the texture
   by the base, so against paper they pass almost nothing. Multiply is neutral at
   white, which is what the tile is built to sit on: it is white with dark
   specks, so every pixel either darkens the paper or does nothing.

   How the tile is made - particle size, strength, and why strength is clipped
   rather than scaled - lives in scripts/generate-paper-grain-tile.sh, which is
   also where it is adjusted. Both are baked into the file, so changing either
   means re-running that script rather than editing this rule. */
body {
    margin: 0;
    background-color: var(--color-paper);
    background-image: url("/images/paper-grain-tile.webp");
    background-blend-mode: multiply;
    color: var(--color-ink);
    font-family: var(--font-ui);
    font-size: var(--step-0);
    font-weight: 400;
    line-height: 1.7;
    letter-spacing: 0.02em;
    line-break: strict;
    overflow-wrap: anywhere;
}

a {
    color: inherit;
}

/* Masthead ---------------------------------------------------------------- */
/* A translucent wash of the ink, not an opaque fill: a paper colour here would
   print a flat band across the top of the grained page, whereas a low alpha
   darkens the band and still lets the body's grain read through it. */
.masthead {
    background-color: oklch(from var(--color-ink) l c h / 0.02);
    border-bottom: 1px solid var(--color-rule);
}

/* The wordmark and the two navigation labels share one row for as long as one
   row holds them, and the nav drops beneath the wordmark the moment it does
   not. Wrapping decides that, rather than a width written down here: the
   Japanese labels are half again as long as the English ones, so any number
   picked would be wrong for one of the two languages. Once wrapped the nav is
   alone on its line, where space-between leaves it at the left edge under the
   wordmark, and the row gap is the shorter step because the two lines are one
   masthead rather than two blocks.

   The nav is centred against the wordmark rather than sat on its baseline. A
   shared baseline is right for two pieces of running text, but these are two
   objects of different sizes in a band: on the baseline the small labels hang
   at the bottom of the tall wordmark's line and the band looks bottom-heavy. */
.masthead__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-half) var(--space-1);
    max-width: var(--column);
    margin: 0 auto;
    padding: var(--space-half) var(--gutter);
}

/* Two words with a space in them, so left to itself the wordmark would break
   across two lines to spare the nav from wrapping - the opposite of what should
   give. Holding it on one line makes the nav the thing that moves.

   The mark sits inside the link rather than beside it, so the whole lockup is
   one target and one thing that wraps. Inline-flex rather than flex: the
   wordmark is still an item in the masthead's own flex row, and a block-level
   display there would stretch it across the band.

   Baseline here, with the mark centred by its own align-self, so that the
   lockup hands out the letters' baseline rather than the mark's bottom edge: a
   flex row whose items all opt out of baseline alignment reports the first
   item's edge instead, and the first item is the image, which sits lower than
   the text baseline. Anything set beside the wordmark on a baseline - the
   admin page's "(Admin)" - would drop by that difference. */
.masthead__wordmark {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4em;
    font-family: var(--font-display);
    font-size: var(--step-2);
    font-weight: 400;
    line-height: 1.25;
    letter-spacing: 0;
    text-decoration: none;
    white-space: nowrap;
}

/* Sized in em so it tracks the wordmark it stands beside at every step of the
   type scale. The file is a square with the card fitted flush across its full
   width, which leaves transparent bands above and below - so the drawing is
   about two thirds as tall as the box, and the box has to be that much taller
   than the letters for the card to match their height.

   pointer-events off because it is inside the link: without it the cursor drops
   back to an arrow as the pointer crosses the image, flickering inside one
   target. The drag rules are a pair - the CSS covers WebKit and Blink, the
   markup's draggable attribute covers Firefox - so the mark cannot be dragged
   out of the page as a loose file. */
.masthead__mark {
    width: 1.15em;
    height: 1.15em;
    align-self: center;
    pointer-events: none;
    -webkit-user-drag: none;
}

.nav {
    display: flex;
    gap: var(--space-1);
}

/* The 3px above the label is the underline's 3px below it - 2px of padding and
   the rule itself - given back at the top. Without it the box is taller under
   the text than over it, so centring the box in the masthead hangs the letters
   above the centre line by half that difference. The masthead centres boxes,
   which is only the same thing as centring the text while the box is symmetric
   about it, so any change to the underline's spacing belongs in both numbers. */
.nav__link {
    font-size: var(--step-down-2);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: 0.08em;
    text-decoration: none;
    color: var(--color-ink-soft);
    border-bottom: 1px solid transparent;
    padding: 3px 0 2px;
    white-space: nowrap;
}

/* The rule under the current page is the ink of the label it sits under, not
   the accent: the inactive links are already a step lighter, so the weight of
   the ink is doing the work and a colour would be saying it a second time. */
.nav__link--active {
    color: var(--color-ink);
    border-bottom-color: var(--color-ink);
}

/* Sign out has to be a button because it posts, but it is one word in a
   masthead beside a wordmark and should read as a link, not as an action with a
   box drawn round it. */
.nav__link--button {
    font-family: inherit;
    background: none;
    border: none;
    border-bottom: 1px solid transparent;
    cursor: pointer;
    touch-action: manipulation;
}

@media (hover: hover) {
    .nav__link:hover {
        color: var(--color-accent);
    }
}

/* Page shell -------------------------------------------------------------- */
.page__main {
    max-width: var(--column);
    margin: 0 auto;
    padding: 0 var(--gutter) var(--space-4);
}

.intro__title {
    font-family: var(--font-display);
    /* One step under the Latin size, like every display line: a mincho fills the
       em square, so the shared px value reads a size larger in Japanese. The en
       layer at the foot restores the larger number for the Latin face. */
    font-size: var(--step-3);
    font-weight: 400;
    line-height: 1.15;
    letter-spacing: 0.01em;
    font-feature-settings: "palt" 1;
    max-width: var(--measure);
    margin: var(--space-4) 0 var(--space-1);
    /* Let the browser find the phrase boundaries rather than writing breaks into
       the copy. A \n there would be a hard break at every width, so a title that
       reads well on a phone would sit in stacked fragments on a desktop with
       room for the whole line. No-op where unsupported, as on the lede. */
    word-break: auto-phrase;
}

/* The sentence is where the title prefers to wrap, so the first break is the one
   its author wrote rather than one a width in a media query guessed. That is
   what the media query cannot do: it is the sentence's own rendered length that
   decides, which differs by language and by the words, and in Japanese every
   character is otherwise a legal break - so a guessed width always leaves some
   viewport where a character or two ends up orphaned on a line of its own.
   inline-block rather than nowrap, because nowrap is absolute: a sentence with
   no room left would run off the side of the page and take the layout with it.
   An inline-block is shrunk to fit the column instead, so it holds together
   while there is room and wraps inside itself when there is not. */
.intro__sentence {
    display: inline-block;
}

/* pretty, not balance: the lede runs long enough that balancing would even out
   every line, where the only thing wrong is a last line left holding one or two
   words. */
.intro__lede {
    max-width: var(--measure);
    margin: 0;
    color: var(--color-ink-soft);
    text-wrap: pretty;
    /* Wrap Japanese at phrase boundaries, not mid-word; no-op where unsupported. */
    word-break: auto-phrase;
}

/* A link wearing the button's clothes: it navigates, so it is not a button. */
.intro__button {
    display: inline-block;
    margin-top: var(--space-2);
    text-decoration: none;
}

.section__title {
    font-size: var(--step-2);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: 0.01em;
    font-feature-settings: "palt" 1;
    margin: var(--space-3) 0 var(--space-half);
}

/* Filters ----------------------------------------------------------------- */
.filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-1);
    margin-top: var(--space-2);
    padding: var(--space-half) 0;
    border-top: 1px solid var(--color-rule);
    border-bottom: 1px solid var(--color-rule);
}

.filters__field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 180px;
    min-width: 0;
}

/* Field labels take the body's tracking, not the wide setting a small label
   usually gets: that one is for uppercase Latin, and these are sentence case in
   English and kana in Japanese. Opened up to 0.08em the kana drift apart and the
   English reads as letterspaced rather than small. */
.filters__label,
.form__label {
    font-size: var(--step-down-2);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: 0.02em;
    color: var(--color-ink-soft);
}

.form__required {
    color: var(--color-accent);
    margin-left: 3px;
}

.filters__input,
.form__input {
    font-family: var(--font-ui);
    font-size: var(--step-0);
    line-height: 1.4;
    color: var(--color-ink);
    background: var(--color-paper);
    border: 1px solid var(--color-rule);
    border-radius: 2px;
    padding: 6px 8px;
    width: 100%;
    min-width: 0;
    touch-action: manipulation;
}

/* Spinner arrows on a rate field invite clicking to a number nobody charges. */
.filters__input[type="number"],
.form__input[type="number"] {
    appearance: textfield;
    -moz-appearance: textfield;
}

.filters__input::-webkit-outer-spin-button,
.filters__input::-webkit-inner-spin-button,
.form__input::-webkit-outer-spin-button,
.form__input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* A textarea sets in the browser's monospace default unless told otherwise. */
.form__input--long {
    font-family: var(--font-ui);
    line-height: 1.6;
    resize: vertical;
}

.filters__input:focus,
.form__input:focus {
    outline: none;
    border-color: var(--color-accent);
}

/* Directory --------------------------------------------------------------- */
.browse__count {
    font-size: var(--step-down-1);
    line-height: 1.5;
    color: var(--color-ink-soft);
    margin: var(--space-half) 0 var(--space-1);
}

.directory {
    list-style: none;
    margin: 0;
    padding: 0;
}

.directory__item + .directory__item {
    border-top: 1px solid var(--color-rule);
}

.listing {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: var(--space-half) 0;
    text-decoration: none;
}

.listing__handle {
    font-size: var(--step-1);
    line-height: 1.25;
    letter-spacing: 0;
    min-width: 0;
    pointer-events: none;
}

.listing__handle::before {
    content: "@";
    color: var(--color-ink-soft);
}

/* The empty span is baseline-aligned, so it hangs off the baseline and has to
   be lifted to run through the middle of the words either side of it
   rather than under them. The lift is a fraction of the type it runs between,
   not a fixed 4px: the admin page sets the same row a step larger, and a fixed
   lift left the line sagging under the bigger glyphs. Hence the font-size,
   which the span has no text to need - it is only what the em is measured in. */
.listing__leader {
    /* The two knobs, and the reason this is not a dotted border: that border
       draws its dots at its own width and spaces them by the same, so size and
       sparseness are one number and a dot big enough to see arrives already
       touching its neighbours. A repeated gradient separates them - the dot is
       its diameter, the step is how far apart they sit. */
    --leader-dot: 3px;
    --leader-step: 12px;
    flex: 1 1 0;
    min-width: 20px;
    font-size: var(--step-1);
    height: var(--leader-dot);
    /* The half-pixel is the feather on the circle's edge. A hard stop between
       the ink and the transparent aliases into a square at these sizes. */
    background-image: radial-gradient(circle at center, var(--color-leader) calc(var(--leader-dot) / 2 - 0.5px), transparent calc(var(--leader-dot) / 2));
    background-size: var(--leader-step) var(--leader-dot);
    background-repeat: repeat-x;
    transform: translateY(-0.32em);
    pointer-events: none;
}

.listing__rate {
    font-size: var(--step-1);
    font-weight: 700;
    line-height: 1.25;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
    white-space: nowrap;
    pointer-events: none;
}

.listing__rate-unit {
    font-size: var(--step-down-2);
    font-weight: 400;
    letter-spacing: 0.08em;
    color: var(--color-ink-soft);
    margin-left: 4px;
}

@media (hover: hover) {
    .listing:hover .listing__handle,
    .listing:hover .listing__handle::before {
        color: var(--color-accent);
    }
}

.browse__empty {
    font-size: var(--step-0);
    line-height: 1.7;
    color: var(--color-ink-soft);
    max-width: var(--measure);
    margin: var(--space-2) 0 0;
    padding: var(--space-1);
    background: var(--color-paper-sunk);
    border: 1px solid var(--color-rule);
}

.is-hidden {
    display: none;
}

/* Form -------------------------------------------------------------------- */
.form {
    max-width: 420px;
    margin-top: var(--space-2);
}

.form__field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: var(--space-1);
}

/* The hidden attribute is only a display rule in the browser's own sheet, so
   any class here that sets display of its own beats it and the element stays on
   the page. Restated at this specificity so a folded field or button is
   actually folded. */
.form__field[hidden],
.form__button[hidden] {
    display: none;
}

/* The honeypot field: off-screen rather than display: none, which a bot
   checks for before deciding whether a field is real. -9720px rather than the
   -9999px every tutorial prints, which is itself a tell. */
.form__honeypot {
    position: absolute;
    left: -9720px;
}

.form__hint {
    font-size: var(--step-down-1);
    line-height: 1.5;
    color: var(--color-ink-soft);
}

.form__error {
    font-size: var(--step-down-1);
    line-height: 1.5;
    color: var(--color-error);
}

.form__input[aria-invalid="true"] {
    border-color: var(--color-error);
}

/* The interface face, tracked wide and bold, which is what a button looks like
   in Japanese. English overrides this to the display face at the foot of the
   file - see the note there for why the two languages part company here. */
.form__button {
    font-family: var(--font-ui);
    font-size: var(--step-down-1);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: 0.07em;
    color: var(--color-paper);
    background: var(--color-ink);
    border: 1px solid var(--color-ink);
    border-radius: 2px;
    padding: 10px 18px;
    cursor: pointer;
    touch-action: manipulation;
}

.form__button:disabled {
    background: var(--color-ink-soft);
    border-color: var(--color-ink-soft);
    cursor: default;
}

/* A button that just reported a save keeps saying so while the pointer is still
   resting on it, which after a click it usually is. The fill lifts toward the
   accent without arriving at it: the accent is pitched as a colour text can be
   read at, which is most of a third of the way from the ink to the paper, and a
   slab travelling that far reads as the button greying out rather than
   answering the pointer. A third of that lift is the whole of what a fill this
   dark needs. Quiet buttons are named out
   because they have a hover of their own below: every argument in a :not()
   carries its own weight, so without the exclusion this selector outranks the
   one-class-and-a-hover rule that wants to override it and fills a button that
   is meant to have no fill. */
@media (hover: hover) {
    .form__button:not(:disabled):not(.form__button--settled):not(.form__button--quiet):hover {
        background: oklch(from var(--color-ink) calc(l + 0.08) c h);
        border-color: oklch(from var(--color-ink) calc(l + 0.08) c h);
    }
}

/* The moment after a save landed. Green is the site's word for "that worked",
   and the button wears it because the button is what was pressed. */
.form__button--settled {
    background: var(--color-positive);
    border-color: var(--color-positive);
}

/* A second action on a page that already has a primary one: same shape, no fill.
   The text and the outline sit a tenth darker than the roles they come from -
   quiet text and a hairline rule are pitched for prose and a table edge, and a
   control has to read as pressable at a glance, which at those lightnesses it
   does not. */
.form__button--quiet {
    color: oklch(from var(--color-ink-soft) calc(l - 0.05) c h);
    background: transparent;
    border-color: oklch(from var(--color-rule) calc(l - 0.09) c h);
}

.form__button--quiet:disabled {
    background: transparent;
}

/* The pointer deepens this button rather than filling it. A secondary action
   that turns into a solid dark slab under the pointer is louder hovered than
   the primary button beside it is at rest, so the fill stays out and the answer
   is a wash of ink under a tenth strength, and only that: the words and the
   outline hold the colour they had, so what the pointer changes is the shape
   filling in rather than the whole control restating itself. The settled clause
   is the same exclusion the filled button carries above, and for the same
   reason - a quiet button can report its own result too, the admin page's copy
   button being the one that does. */
@media (hover: hover) {
    .form__button--quiet:not(:disabled):not(.form__button--settled):hover {
        background: oklch(from var(--color-ink) l c h / 0.075);
    }
}

/* A live listing states its rate rather than showing it in an open field: the
   owner is usually here off the DM saying they went live, and a select with a
   Save under it reads as one more form owed an answer. */
/* The sentence and the button that changes it share a line box, so the measure
   belongs to the block holding both rather than to either. */
.verify-account__standing {
    max-width: var(--measure);
}

.verify-account__rate {
    /* Inline, so the button sits to the right of this sentence rather than under
       it as the next step down the page. */
    display: inline;
    margin: 0;
    /* The softer ink every lede on the site is set in: this is a line telling
       them where things stand, not the page raising its voice. The sentence is
       otherwise set exactly as the lede above it - a display size was tried here
       and read as too loud for a line reporting where things stand. */
    color: var(--color-ink-soft);
}

/* The status reserves a line height so a message arriving does not shove the
   page, which is right where it is the last thing in a form. Here it sits
   between two controls, so an empty one held 35px of nothing between them and
   the 29px the rule below asks for was never the gap that showed. Emptied it
   takes no room, and it stays displayed and in the accessibility tree, so a
   message still announces itself when one lands. */
.verify-account__form .form__status:empty {
    min-height: 0;
    margin-top: 0;
}

/* The form now opens with the rate sentence, so it carries that sentence's own
   step off the prose above. The base form is capped at a field's width, which is
   right for a column of fields and too narrow for a sentence with a button
   beside it - at 420px the button had nowhere to sit and dropped under the rate.
   The cap moves down to the panel, which is the part that actually holds
   fields. */
.verify-account__form {
    max-width: var(--measure);
    margin-top: var(--space-1);
}

/* Inline, so the summary lands in the sentence's line box. The panel inside is
   block-level and splits out of that line on its own, which is what lets the
   fold open underneath without the button ever moving. The space to the left is
   a real gap rather than the word space the source whitespace collapses to: a
   button set a word away from a sentence reads as a word of it. */
.verify-account__change {
    display: inline;
    margin-left: var(--space-half);
}

/* The fold is a details element rather than a scripted one - see the note in
   the template - so its summary is what has to be dressed as the quiet button
   it reads as, and its marker taken off. Blink and Gecko drop the marker with
   the display change alone; the pseudo-element is the one Safari still paints.
   Both sit after the button rules above, which is what they are modifying.

   inline-block puts the button in the line and hands the line its label's own
   baseline, so the words in the button sit on the same line as the words of the
   sentence rather than the box being centred against them. It also keeps the
   label whole: every character is a legal break in Japanese, and an inline label
   would split at the line ending and leave half of it dangling under the
   sentence. An inline-block moves to the next line whole instead, and only
   breaks inside itself when a line cannot hold it at all - which is what
   auto-phrase is here for, so that break lands between phrases. */
.verify-account__change-summary {
    display: inline-block;
    word-break: auto-phrase;
    list-style: none;
}

.verify-account__change-summary::-webkit-details-marker {
    display: none;
}

/* The panel keeps the ladder a line off the sentence above it, and the cap the
   base form used to carry, since this is the part with a field in it. */
.verify-account__change-panel {
    max-width: 420px;
    margin-top: var(--space-1);
}

/* The unfolded ladder stands off the save button by the same step the fields of
   any other form keep from each other. */
.verify-account__change-field {
    margin-bottom: var(--space-1);
}

/* Taking a listing down is not the third step of what is above it, so it is put
   a long way down the page - twice the widest step in the scale - rather than
   the one line that made it read as the next thing to press. It is
   the same quiet button as the one that opens the ladder, and distance is what
   separates them instead of size. The status line between them carries no space
   of its own. */
.verify-account__unlist {
    display: block;
    margin-top: calc(var(--space-4) * 2);
}

/* The quiet button that takes something away wears the site's red under the
   pointer, in the outline and the words rather than as a wash: a button that
   lights up is a button inviting the press, and this one is a last resort.
   It carries the quiet hover's own clauses as well as its two classes so it
   outranks that rule outright rather than tying with it and leaning on which
   of the two was written last. */
@media (hover: hover) {
    .form__button--quiet.verify-account__unlist:not(:disabled):not(.form__button--settled):hover {
        color: var(--color-error);
        background: transparent;
        border-color: var(--color-error);
    }
}

/* Two answers to the same question sit closer to each other than either sits to
   anything else, so the gap along the row is half the one the row keeps when it
   wraps - which it does in Japanese, where a label is wider than its English
   source and the buttons drop onto two lines. */
.form__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-half) calc(var(--space-half) / 2);
    margin-top: var(--space-1);
}

.form--secondary {
    margin-top: var(--space-2);
}

.form__ellipsis {
    display: inline-block;
    width: 1.4em;
    text-align: left;
}

.form__status {
    font-size: var(--step-down-1);
    line-height: 1.5;
    margin: var(--space-half) 0 0;
    min-height: 1.5em;
}

.form__status--error {
    color: var(--color-error);
}

.form__status--success {
    color: var(--color-positive);
}

/* Pitch -------------------------------------------------------------------- */
/* The argument for listing, under the form rather than on a page of its own.
   Someone who arrived to be listed submits and never sees any of this; someone
   who does not yet understand why a posted rate helps them has one thing to
   press and then only has to keep scrolling. It asks the question the argument
   below it answers, so it is set in the display face that argument is in, at the
   body ink - a line of the same voice, not a control bolted above it. Weight 400
   for the reason every display line on the site is: the face is loaded at one
   weight, so a bold here would be synthesised. Size carries it instead. */
.pitch__cue {
    display: flex;
    width: fit-content;
    margin-top: var(--space-3);
    margin-inline: auto;
    align-items: center;
    min-height: 44px;
    font-family: var(--font-display);
    font-size: var(--step-3);
    font-weight: 400;
    line-height: 1.3;
    letter-spacing: 0.01em;
    color: var(--color-ink);
    text-decoration: none;
}

@media (hover: hover) {
    .pitch__cue:hover {
        color: var(--color-accent);
    }
}

/* The beats are not a flat run but a three-act argument with a hinge, so the
   space between them encodes that shape rather than stepping evenly: beats
   inside one act sit close, and only an act boundary - the problem giving way to
   the reader's own position, and either side of the turn - opens the wide gap.
   Two custom properties carry the two distances so the phone override retunes
   both from one place. The rule is what separates the half of the page that asks
   from the half that argues. */
.pitch {
    --beat-gap-within: var(--space-2);
    --beat-gap-act: var(--space-4);
    display: flex;
    flex-direction: column;
    margin-top: var(--space-half);
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-rule);
}

/* The space is a top margin on each beat, not one gap on the column, so a
   boundary can be wide or tight on its own. The default is the within-act step;
   the first beat takes the pitch's own padding instead of a margin, and the two
   act boundaries below override to the wide step. Flex items don't collapse
   margins, so each value lands exactly as written. */
.pitch__beat {
    margin-top: var(--beat-gap-within);
}

.pitch__beat:first-child {
    margin-top: 0;
}

/* Two lines that are one unit: the sentence and the paragraph under it. The
   space that matters is the one to the next beat, which that beat's own top
   margin supplies, so this one stays tight. */
.pitch__title {
    font-family: var(--font-display);
    /* A step under the turn rather than two, and a step under the Latin size the
       en layer restores: at step-3 a mincho title read a size louder than the
       Instrument Serif it was tuned on. */
    font-size: var(--step-2);
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: 0.01em;
    font-feature-settings: "palt" 1;
    max-width: var(--measure);
    margin: 0 0 var(--space-half);
    text-wrap: pretty;
    /* Wrap Japanese at phrase boundaries, not mid-word; no-op where unsupported.
       Not the intro title's unbreakable spans: those hold because that headline
       is two short sentences, and a beat here is one long one that would run
       off the side of a phone if it were forbidden from wrapping. */
    word-break: auto-phrase;
}

.pitch__body {
    max-width: var(--measure);
    margin: 0;
    color: var(--color-ink-soft);
    text-wrap: pretty;
    /* Wrap Japanese at phrase boundaries, not mid-word; no-op where unsupported. */
    word-break: auto-phrase;
}

/* Beat marks -----------------------------------------------------------------
   A line drawing printed in the second ink, one per beat that has something to
   show rather than only something to say, so the argument is not an unbroken
   wall of type. The stroke holds one hairline weight at every size
   (non-scaling-stroke), the primary lines in the mark ink and the secondary
   detail in its soft strength, the price set in the display face the headlines
   use and in the writing ink - see the token's comment. Each viewBox is cut to
   the mark's own shape - the phone and the card wide, the feed square - so it
   fills its box rather than floating in a square; the beats below place and
   size their own. */
.pitch__mark {
    display: block;
    width: 7rem;
    height: 7rem;
    margin: 0 0 var(--space-1);
}

.pitch__mark-stroke {
    fill: none;
    stroke: var(--color-mark-ink);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}

.pitch__mark-soft {
    fill: none;
    stroke: var(--color-mark-ink-soft);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}

.pitch__mark-fill-ink {
    fill: var(--color-mark-ink);
}

/* The paper the form's inputs are filled in, which is the page colour without
   the body's grain over it, so a shape wearing it reads as a panel laid on the
   page rather than an outline drawn on it. It does two jobs. Every mark's
   backmost shape takes it as a plate to sit on - the phone's body, both
   daycards, the speech bubble, the feed's rect. Anything further up the stack
   takes it to occlude: the storefront's awning has to hide the facade behind
   it, and inside the feed the sea's waterline, the tree and the hill ridge each
   have to hide the sun or the skyline drawn before them, because SVG paints in
   source order and there is nothing else to stop a line showing through.

   It is declared after -stroke and -soft, so it wins the fill on an element
   wearing both and leaves that element's stroke alone; on its own it is a plate
   with no outline. */
.pitch__mark-fill-paper {
    fill: var(--color-paper);
}

.pitch__mark-num {
    fill: var(--color-ink);
    font-family: var(--font-display);
}

/* The turn is centred, so the message that carries the rate centres over the
   line, a touch larger than a stacked mark since it is the hinge. Height follows
   the width now that the viewBox is cut to the bubble - a square box around a
   wide shape letterboxes it, and the empty band is what used to read as too much
   space under the mark. */
.pitch__beat--pivot .pitch__mark {
    width: 9.5rem;
    height: auto;
    margin: 0 auto var(--space-half);
}

/* Beat treatments ------------------------------------------------------------
   A row of blocks each set the same way reads as a document rather than as
   separate thoughts - the eye learns the shape after two of them and stops
   arriving at each one fresh. So each beat gets its own setting, and the
   variation carries meaning rather than decorating: scale marks how much the
   beat matters, layout marks whether the beat is one statement or a pair, and a
   mark beside the words marks a beat with something to show. The face does not vary -
   every beat here is the argument talking, so all of them are the display face.

   These blocks are modifiers of the two above, so they must stay after them:
   two single-class selectors tie and source order decides. */

/* The four beats that stand a mark beside their words are a flex row of two
   things, the mark and this block, rather than a grid the title and body sit in
   as separate cells. A grid was the first attempt and it was wrong: a mark taller
   than the two lines grows the row tracks it spans, so the space between a title
   and its own answer opened or closed with the height of the picture next to it.
   Wrapped, the pair keep their own leading at any mark size, and the mark centres
   against the block as a whole. */
.pitch__text {
    flex: 1 1 auto;
    min-width: 0;
}

/* The opening pairs the hook with the phone the client reached for instead: the
   headline and its answer on the left, the phone standing beside them. The mark
   is written first in the markup, as every mark on this page is, and ordered last
   here so it reads on the right on a wide screen. This is the one mark a phone
   does not get at all - see the breakpoint at the foot of the file. */
.pitch__beat--opening {
    display: flex;
    align-items: center;
    /* One rhythm step, not the marked beats' three: the column left beside the
       phone is what the headline wraps in, and at the wider gap the Japanese
       line lost its last phrase to a fourth line by eight pixels. */
    gap: var(--space-1);
}

.pitch__beat--opening .pitch__mark {
    order: 1;
    flex: 0 0 auto;
    width: 12rem;
    height: auto;
    margin: -1.5rem 0 0;
}

/* The opening. Nothing else on the page is set this large, including the
   headline over the form, because this is the one line that has to stop
   somebody who was already scrolling past. Sized against the viewport rather
   than off the step scale: the scale tops out at a size that is right beside a
   form and too small alone on a screen. Its answer sets in the body ink instead
   of the soft ink, so the two lines read as one voice landing a blow rather
   than as a heading and its caption. */
.pitch__beat--opening .pitch__title {
    /* Two steps under the Latin 58px, not one like the rest: this sentence runs
       long in Japanese, and beside the mark's narrow column even 48px stacked it
       five lines high - a wall, not a headline. */
    font-size: clamp(var(--step-3), 5.2vw, 40px);
    /* Looser than the Latin 1.05: kanji fill the em, so lines this tight touch. */
    line-height: 1.1;
    letter-spacing: -0.01em;
    max-width: 18em;
    margin-bottom: var(--space-1);
}

.pitch__beat--opening .pitch__body {
    font-size: var(--step-1);
    line-height: 1.4;
    color: var(--color-ink);
}

/* The explanation, and the mirror of the promise that closes the page: the same
   band, the same headline size, the mark on the left instead of the right. It
   was a sunk-paper panel before, which read as a footnote boxed off from the
   argument when it is in fact the answer to the line above it.

   The hairlines are the promise's too, and this beat takes one on each side: a
   band ruled top and bottom reads as lifted out of the run without being boxed
   off from it, which is what the panel was reaching for and missed.

   Its mark is the promise's daycard for now, standing in until this beat gets a
   drawing of its own. */
.pitch__beat--aside {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    max-width: var(--column);
    padding-block: var(--space-2);
    border-block: 1px solid var(--color-ink);
}

.pitch__beat--aside .pitch__mark {
    flex: 0 0 auto;
    width: 13rem;
    height: auto;
    margin: 0;
}

.pitch__beat--aside .pitch__title {
    font-size: clamp(var(--step-2), 3.75vw, var(--step-4));
    line-height: 1.1;
    max-width: 16em;
}

/* The first act boundary: the problem and its footnote are behind us, and the
   argument turns to the reader's own position, so this beat opens the wide gap.

   It is also the mirror of the portfolio beat under it: this one shows the shop
   that needed the photographer and stands its mark on the right, that one shows
   the reader's own grid and stands its mark on the left, so the pair face each
   other instead of leaning the same way. */
.pitch__beat--wide {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--beat-gap-act);
    max-width: var(--column);
}

.pitch__beat--wide .pitch__mark {
    order: 1;
    flex: 0 0 auto;
    width: 13rem;
    height: auto;
    margin: 0;
}

/* The one beat about the reader's own portfolio, so it shows one: the Instagram
   grid stands to the left of the title and its answer, the picture and the point
   taken together. The mark leads in the markup here too, and needs no reorder.

   It closes to half the within-act step on the beat above, which is its mirror:
   the pair are the client's side and the reader's side of the same moment, and
   at the full step they read as two separate stops rather than one comparison. */
.pitch__beat--split {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-1);
    max-width: var(--column);
}

.pitch__beat--split .pitch__mark {
    flex: 0 0 auto;
    width: 11rem;
    height: 11rem;
    margin: 0;
}

/* The turn, the hinge of the whole argument and the one line the section is
   built to be remembered by. Everything before it is the reader's problem and
   everything after is what to do, so it stands alone and centred - the only
   centred thing on the site - opened by its mark, a message carrying a rate, the
   reading eye forced to reset before it reads a word. That reset is what marks
   the turn, so it takes the tightest space on the page rather than the act
   boundary it used to: centring already separates it, and a wide gap stacked on
   top of that read as the argument having stopped rather than turned. The block
   padding went with the margin for the same reason - the two were adding up, and
   what looked like one gap above the turn was two. It sets larger than the two
   beats it follows so the turn reads as the peak of the middle of the page, below
   only the opening that had to stop the scroll and the promise it builds to. */
.pitch__beat--pivot {
    max-width: 24em;
    /* Half a step over the tight gap it used to take: cropping the bubble's
       viewBox to the drawing took away the empty band that had been sitting above
       it, so the beat has to buy that air back as real space or the mark bunches
       up under the grid above. */
    margin-top: calc(var(--space-1) + var(--space-half));
    margin-inline: auto;
    text-align: center;
}

.pitch__beat--pivot .pitch__title,
.pitch__beat--pivot .pitch__body {
    max-width: none;
}

/* Between the middle beats and the promise: it starts where they sit and grows
   past them with the viewport, short of the promise's clamp, so the three peaks
   of the page stay ordered. Tracking is left
   to inherit - the base for Japanese, the en override's tighter value for the
   display face - since a mincho wants none and this line carries both scripts. */
.pitch__beat--pivot .pitch__title {
    /* Tops out at step-3, one place under the promise and one above the middle
       beats' step-2, so the turn is the third peak and the size stays on the
       scale. */
    font-size: clamp(var(--step-2), 3.3vw, var(--step-3));
    /* Tight to its own body: the mark above supplies the space that sets the
       turn apart, so the line and its answer read as one centred unit. */
    margin-bottom: var(--space-half);
    /* Even the two lines rather than leaving the second holding two words: a
       centred display line rags worse than a left-set one, and this is short
       enough for balance to hold (pretty only fixes the last line). */
    text-wrap: balance;
}

/* The promise, and the second-largest thing on the page. The rule over it is
   the same hairline that opens the pitch, closing the argument the way it was
   opened, and it is what marks this beat as the one the rest was building to.
   The daycard itself stands to the right, the thing the reader ends up with
   beside the sentence that offers it. */
.pitch__beat--promise {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    max-width: var(--column);
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-ink);
}

.pitch__beat--promise .pitch__mark {
    order: 1;
    flex: 0 0 auto;
    width: 13rem;
    height: auto;
    margin: 0;
}

/* The answer under it sets at the body size the rest of the argument does, not a
   step up: the headline is already the second-largest thing on the page, so
   raising its answer too only flattens the difference between them. The space
   between the two is the base one every beat uses. */
.pitch__beat--promise .pitch__title {
    font-size: clamp(var(--step-2), 3.75vw, var(--step-4));
    line-height: 1.1;
    max-width: 16em;
}

/* The closing beat is only the ask: the terms prose that used to sit here is
   gone, so what is left is the title over the form. */
.pitch__beat--terms {
    max-width: var(--column);
}

/* The form is the ask, headed by its own title the way the form at the top of
   the page is. A hairline and a wide gap over that title divide the ask off from
   the argument - it ends, and the thing the whole page was for begins - and the
   title echoes the opening "Tell us your rate" in the display face, closing the
   page on the same question it opened with. */
.pitch__signup-title {
    margin-top: 0;
    margin-bottom: var(--space-1);
    padding-top: var(--space-3);
    border-top: 1px solid var(--color-rule);
    font-family: var(--font-display);
    font-size: clamp(var(--step-2), 3.3vw, var(--step-3));
    font-weight: 400;
    line-height: 1.1;
    letter-spacing: 0.01em;
}

.pitch__beat--terms .form {
    margin-top: 0;
}

/* Terms and privacy -------------------------------------------------------- */
/* Prose in the soft ink rather than the body ink: the page is read once, by
   somebody checking one thing, and it should not set as loudly as the pages
   that are trying to tell you something. */
.legal__paragraph {
    max-width: var(--measure);
    margin: 0 0 var(--space-1);
    color: var(--color-ink-soft);
    text-wrap: pretty;
    /* Wrap Japanese at phrase boundaries, not mid-word; no-op where unsupported. */
    word-break: auto-phrase;
}

.legal__updated {
    margin: var(--space-2) 0 0;
    font-size: var(--step-down-1);
    color: var(--color-ink-soft);
}

/* Questions ---------------------------------------------------------------- */
/* Read by somebody hunting one answer rather than reading the page, so the
   entries are set to be skimmed: the question carries the full ink while its
   answer sits back in the soft one, so a scan down the page reads only the
   questions. Space does the separating and no rule is drawn - at three entries
   a hairline apiece reads as a table of terms, and the gap between an answer and
   the next question is already several times the gap inside a pair. */
.faq {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

/* A step over its answer and no more. This is a question somebody arrived with,
   not a heading announcing a section, so it wants to be findable rather than
   loud - the pitch page is where the page is allowed to raise its voice. */
.faq__question {
    max-width: var(--measure);
    margin: 0 0 var(--space-half);
    font-size: var(--step-1);
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: 0.01em;
    font-feature-settings: "palt" 1;
    text-wrap: pretty;
    word-break: auto-phrase;
}

.faq__answer {
    max-width: var(--measure);
    margin: 0;
    color: var(--color-ink-soft);
    text-wrap: pretty;
    /* Wrap Japanese at phrase boundaries, not mid-word; no-op where unsupported. */
    word-break: auto-phrase;
}

/* The answers that end in somewhere to go. Full ink against the softened
   answer around it, so the way on reads as the way on. */
.faq__answer a {
    color: var(--color-ink);
    text-decoration-color: var(--color-rule);
    text-underline-offset: 0.2em;
}

/* Not found ---------------------------------------------------------------- */
/* The number says which page this is, so the sentence under it does not have to
   spend itself saying "404" in words. Set at the masthead nav's size and colour
   rather than the title's, because it is a label on the page and not the page's
   message: a 404 blown up to display size would be the loudest thing on a page
   whose whole content is that there is nothing here. */
.not-found__code {
    margin: var(--space-4) 0 0;
    font-size: var(--step-down-2);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: 0.08em;
    color: var(--color-ink-soft);
}

/* The title's own top margin is what frames a hero, and here the number above
   it is the top of that block - so the two set as one unit and the space in
   front of them is the number's. */
.intro--not-found .intro__title {
    margin-top: var(--space-half);
}

/* Underlined at rest, unlike the footer's links: it is the only thing on this
   page to press, and a page that exists to send you somewhere else cannot make
   the way out wait for a pointer to reveal it. */
.not-found__home {
    display: inline-block;
    margin-top: var(--space-2);
    font-size: var(--step-down-1);
    text-underline-offset: 0.25em;
}

@media (hover: hover) {
    .not-found__home:hover {
        color: var(--color-accent);
    }
}

/* Footer ------------------------------------------------------------------ */
.colophon {
    margin-top: var(--space-4);
}

/* Centred, not baseline-aligned: the picker's labels are 44px tap targets, so
   their text sits mid-box rather than on the copyright line's baseline. */
.colophon__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-1);
    max-width: var(--column);
    margin: 0 auto;
    padding: var(--space-1) var(--gutter);
}

.colophon__line {
    margin: 0;
    font-size: var(--step-down-1);
    line-height: 1.6;
    color: var(--color-ink-soft);
}

/* Undecorated at rest, like the language picker beside it. Nobody arrives
   wanting this page, and an underline in the footer is the only mark on an
   otherwise unruled column, so it would advertise the one line here that has
   nothing to sell. It sets in the same ink as the copyright it follows and only
   admits to being a link under a pointer. */
/* Smaller than the copyright it sits beside, because this label is the only
   Japanese on that line and a kanji fills its em box where a lowercase Latin
   word uses about two thirds of it - at the same px the two read as different
   sizes, and this label is the longest run on the line as well as the one with
   least to say. An optical correction, not a step on the scale, which is why it
   is a ratio and not one of the step tokens; English needs none of it and takes
   the line's own size back below. */
.colophon__link {
    color: inherit;
    font-size: 0.8em;
    text-decoration: none;
}

.colophon__separator {
    margin-inline: 0.5em;
    color: var(--color-rule);
    pointer-events: none;
}

@media (hover: hover) {
    .colophon__link:hover {
        color: var(--color-accent);
        text-decoration: underline;
        text-decoration-color: var(--color-rule);
        text-underline-offset: 0.2em;
    }
}

/* Both languages are on screen at once: a control offering only the other one
   advertises that the site is bilingual after you have already clicked it. */
.colophon__languages {
    display: inline-flex;
    align-items: center;
    /* The last label's own padding would inset it from the column edge, so the
       row is pulled back out by that much to line up with the copyright line. */
    margin-block: 0;
    margin-inline: 0 -0.5em;
    font-size: var(--step-down-2);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: 0.08em;
    white-space: nowrap;
}

/* Nothing is drawn but the three text nodes. The opacity gap is the whole hover
   signal, so narrowing it turns the hover into a flicker. Hovering the other
   language lands on exactly the current one's weight - it is a preview of
   what you are about to switch to, so the two values are declared once. */
.colophon__language {
    --language-current-opacity: 0.8;

    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-inline: 0.5em;
    opacity: var(--language-current-opacity);
    color: var(--color-ink-soft);
    text-decoration: none;
}

.colophon__language--other {
    opacity: 0.45;
    transition: opacity 0.15s ease-out;
}

/* The gap around the slash is tuned here, never on the labels' padding - that
   padding is what makes a two-glyph label hittable. */
.colophon__language-separator {
    margin-inline: -0.05em;
    color: var(--color-rule);
    pointer-events: none;
}

@media (hover: hover) {
    .colophon__language--other:hover {
        opacity: var(--language-current-opacity);
        text-decoration: none;
    }
}

/* English sets tighter than Japanese: no ideographic spacing, shorter leading,
   and a narrower measure - the Japanese 41em would run past 80 Latin characters
   a line. Its display lines also set a step larger: a mincho fills the em
   square, so the size a headline wants differs by script, and the base rules
   carry the Japanese number while these restore the Latin one. */
html[lang="en"] {
    --measure: 38em;
}

html[lang="en"] body {
    line-height: 1.55;
    letter-spacing: 0;
}

html[lang="en"] .intro__title {
    font-size: var(--step-4);
    line-height: 1.1;
    letter-spacing: -0.02em;
}

html[lang="en"] .section__title {
    letter-spacing: -0.01em;
}

html[lang="en"] .faq__question {
    letter-spacing: -0.01em;
}

html[lang="en"] .pitch__title {
    font-size: var(--step-3);
    line-height: 1.15;
    letter-spacing: -0.02em;
}

/* The beats that size their own title, given back their Latin clamps. These
   selectors outweigh the base beat rules, so each declaration here wins in
   English and the base value stands everywhere else. */
html[lang="en"] .pitch__beat--opening .pitch__title {
    font-size: clamp(var(--step-4), 7.5vw, 58px);
    line-height: 1.05;
}

html[lang="en"] .pitch__beat--aside .pitch__title,
html[lang="en"] .pitch__beat--promise .pitch__title {
    font-size: clamp(var(--step-3), 4.5vw, 42px);
}

html[lang="en"] .pitch__beat--pivot .pitch__title {
    font-size: clamp(var(--step-3), 4vw, var(--step-4));
}

html[lang="en"] .pitch__signup-title {
    font-size: clamp(var(--step-3), 4vw, var(--step-4));
    letter-spacing: -0.02em;
}

html[lang="en"] .colophon__link {
    font-size: inherit;
}

/* The button is the one control that changes face with the language. In English
   the display face is Instrument Serif, and a button set in it reads as the
   answer to the headline that asked rather than as interface bolted underneath.
   The Japanese display face is a mincho, and a mincho on a button reads as a
   printed document rather than as something to press, so Japanese keeps the
   gothic the base rule sets.

   Weight 400, because the display face is loaded at one weight in both scripts
   and a 700 would be a synthesised bold. The bold and the wide tracking the base
   rule uses are what carried the label there; here the face does that work, so
   both are dropped and size takes over. It sits between the body size and the
   step above it - a full step up read as a heading somebody had boxed, and the
   body size read as a label rather than a press. Off the scale on purpose, since
   the scale has nothing between those two, but written as a multiple of the base
   rather than as the 18.7px it resolves to, so that moving the base moves this
   with it instead of quietly leaving it outside the pair it sits between. Face,
   size and tracking are the whole of the difference - the shape, the fill and
   every state stay in the rule above. */
html[lang="en"] .form__button {
    font-family: var(--font-display);
    font-size: calc(var(--step-0) * 1.1);
    font-weight: 400;
    letter-spacing: 0.01em;
}

/* The two controls on a live listing's page: the one that opens the rate ladder
   and the one that ends the listing. They are the same quiet button at the same
   size, and what separates them is the distance between them, which is set
   where the unlist rule is written. Sized apart from each other they read as one
   control rendered twice, which is what a difference in size says when the
   shape, the fill and the outline are all identical.

   One step down the scale, which leaves them three quarters of a full English
   button. Two smaller values were tried on the unlist alone and both failed:
   half the base step read as a smudge rather than a control, and three quarters
   of it was off the scale at 12.75px, where the English display face - a display
   cut - thins out and the label rendered fuzzy beside a crisp button. A step of
   the scale is the smallest this face can be set at and still read as drawn.

   The weight and the tracking are dropped here for both languages rather than
   only for Japanese, though Japanese is where it showed: the base button rule
   sets 700 and wide tracking, and the English rule above quietly resets to 400,
   so the bold gothic was reaching only the one page nobody had looked at. A
   bold, widely tracked label is what made the least reversible press on the
   site the loudest thing on it.

   Both selectors carry the language attribute and the base class as well as
   their own because the English rule above is qualified by an attribute and so
   outranks a lone class: written as `.verify-account__unlist` alone, these
   declarations applied on the Japanese page and were silently dead on the
   English one. The selectors as they stand outrank that rule wherever they sit,
   so it is the qualification rather than the position doing the work - keep the
   former if this ever moves. */
html[lang] .form__button.verify-account__change-summary,
html[lang] .form__button.verify-account__unlist {
    font-size: var(--step-down-1);
    font-weight: 400;
    letter-spacing: 0.01em;
    padding: 7px 13px;
}

/* Narrow screens -------------------------------------------------------------
   The masthead is not here. It wraps on its own, at whatever width its own
   contents stop fitting, so a number written here could only be wrong in one of
   the two languages. What follows is vertical rhythm, which has no such
   self-measuring form and does need a width to trigger it. */
@media (max-width: 560px) {
    /* The large vertical steps are tuned for a wide screen, where they frame the
       hero with air; on a phone that same air reads as emptiness the visitor has
       to scroll past, so the biggest gaps collapse to the ordinary line rhythm. */
    .intro__title {
        margin-top: var(--space-1);
    }

    /* The 404 page's block starts at the number rather than the title, so the
       step above it is the one that has to collapse. */
    .not-found__code {
        margin-top: var(--space-1);
    }

    .section__title {
        margin-top: var(--space-2);
    }

    .page__main {
        padding-bottom: var(--space-2);
    }

    /* A beat gets a screen of its own on a desktop, where the wide gaps frame the
       argument with air. On a phone that air is most of a screen of nothing
       between two sentences, so both rhythm steps tighten - retuned here from the
       one place they are defined rather than per beat. */
    .pitch {
        --beat-gap-within: var(--space-1);
        --beat-gap-act: var(--space-2);
        padding-top: var(--space-2);
    }

    /* The image-beside-text bands have no room for two columns on a phone, so
       each stacks instead. The mark is written first in every one of them, and
       dropping the order it was given for the wide layout puts it back on top.
       The opening is in this list for its gap alone - its mark is hidden further
       down, so the column it forms holds only the text. */
    .pitch__beat--opening,
    .pitch__beat--aside,
    .pitch__beat--wide,
    .pitch__beat--split,
    .pitch__beat--promise {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-1);
    }

    .pitch__beat--wide .pitch__mark,
    .pitch__beat--promise .pitch__mark {
        order: 0;
    }

    /* Every mark centres on the column while the words stay left aligned - the
       stacking is what makes them a caption and a paragraph rather than a pair,
       and a drawing hard against the left margin reads as having slipped there.
       align-self on the mark alone, not text-align on the beat, so nothing is
       centred that anyone has to read. */
    .pitch__beat--aside .pitch__mark,
    .pitch__beat--wide .pitch__mark,
    .pitch__beat--split .pitch__mark,
    .pitch__beat--promise .pitch__mark {
        align-self: center;
    }

    /* The opening's phone is dropped rather than stacked. It is the one mark that
       is a picture of the wrong tool rather than of the thing being offered, so
       out of the two-column pairing it stops being read against the line and
       becomes a riddle. The line it illustrates already says iPhone. */
    .pitch__beat--opening .pitch__mark {
        display: none;
    }

    .pitch__cue {
        margin-top: var(--space-2);
    }

    .colophon {
        margin-top: var(--space-2);
    }
}
